xm_dd.c revision 894844a8d956a0ee5f95836331dc318f49fdb845
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.1
4 *
5 * Copyright (C) 1999-2004  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#include "glxheader.h"
27#include "bufferobj.h"
28#include "context.h"
29#include "colormac.h"
30#include "depth.h"
31#include "drawpix.h"
32#include "extensions.h"
33#include "macros.h"
34#include "imports.h"
35#include "mtypes.h"
36#include "state.h"
37#include "texobj.h"
38#include "teximage.h"
39#include "texstore.h"
40#include "texformat.h"
41#include "xmesaP.h"
42#include "array_cache/acache.h"
43#include "swrast/swrast.h"
44#include "swrast/s_auxbuffer.h"
45#include "swrast/s_context.h"
46#include "swrast/s_drawpix.h"
47#include "swrast/s_alphabuf.h"
48#include "swrast_setup/swrast_setup.h"
49#include "tnl/tnl.h"
50#include "tnl/t_context.h"
51
52#ifdef XFree86Server
53#include <GL/glxtokens.h>
54#endif
55
56
57
58/*
59 * Dithering kernels and lookup tables.
60 */
61
62const int xmesa_kernel8[DITH_DY * DITH_DX] = {
63    0 * MAXC,  8 * MAXC,  2 * MAXC, 10 * MAXC,
64   12 * MAXC,  4 * MAXC, 14 * MAXC,  6 * MAXC,
65    3 * MAXC, 11 * MAXC,  1 * MAXC,  9 * MAXC,
66   15 * MAXC,  7 * MAXC, 13 * MAXC,  5 * MAXC,
67};
68
69const short xmesa_HPCR_DRGB[3][2][16] = {
70   {
71      { 16, -4,  1,-11, 14, -6,  3, -9, 15, -5,  2,-10, 13, -7,  4, -8},
72      {-15,  5,  0, 12,-13,  7, -2, 10,-14,  6, -1, 11,-12,  8, -3,  9}
73   },
74   {
75      {-11, 15, -7,  3, -8, 14, -4,  2,-10, 16, -6,  4, -9, 13, -5,  1},
76      { 12,-14,  8, -2,  9,-13,  5, -1, 11,-15,  7, -3, 10,-12,  6,  0}
77   },
78   {
79      {  6,-18, 26,-14,  2,-22, 30,-10,  8,-16, 28,-12,  4,-20, 32, -8},
80      { -4, 20,-24, 16,  0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
81   }
82};
83
84const int xmesa_kernel1[16] = {
85   0*47,  9*47,  4*47, 12*47,     /* 47 = (255*3)/16 */
86   6*47,  2*47, 14*47,  8*47,
87  10*47,  1*47,  5*47, 11*47,
88   7*47, 13*47,  3*47, 15*47
89};
90
91
92/*
93 * Return the size (width, height) of the X window for the given GLframebuffer.
94 * Output:  width - width of buffer in pixels.
95 *          height - height of buffer in pixels.
96 */
97static void
98get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
99{
100   /* We can do this cast because the first field in the XMesaBuffer
101    * struct is a GLframebuffer struct.  If this weren't true, we'd
102    * need a pointer from the GLframebuffer to the XMesaBuffer.
103    */
104   const XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
105   unsigned int winwidth, winheight;
106#ifdef XFree86Server
107   /* XFree86 GLX renderer */
108   if (xmBuffer->frontbuffer->width > MAX_WIDTH ||
109       xmBuffer->frontbuffer->height > MAX_HEIGHT) {
110     winwidth = buffer->Width;
111     winheight = buffer->Height;
112   } else {
113     winwidth = xmBuffer->frontbuffer->width;
114     winheight = xmBuffer->frontbuffer->height;
115   }
116#else
117   Window root;
118   int winx, winy;
119   unsigned int bw, d;
120
121   _glthread_LOCK_MUTEX(_xmesa_lock);
122   XSync(xmBuffer->xm_visual->display, 0); /* added for Chromium */
123   XGetGeometry( xmBuffer->xm_visual->display, xmBuffer->frontbuffer, &root,
124		 &winx, &winy, &winwidth, &winheight, &bw, &d );
125   _glthread_UNLOCK_MUTEX(_xmesa_lock);
126#endif
127
128   *width = winwidth;
129   *height = winheight;
130}
131
132
133static void
134finish_or_flush( GLcontext *ctx )
135{
136#ifdef XFree86Server
137      /* NOT_NEEDED */
138#else
139   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
140   if (xmesa) {
141      _glthread_LOCK_MUTEX(_xmesa_lock);
142      XSync( xmesa->display, False );
143      _glthread_UNLOCK_MUTEX(_xmesa_lock);
144   }
145#endif
146}
147
148
149
150/*
151 * This chooses the color buffer for reading and writing spans, points,
152 * lines, and triangles.
153 */
154void
155xmesa_set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
156{
157   /* We can make this cast since the XMesaBuffer wraps GLframebuffer.
158    * GLframebuffer is the first member in a XMesaBuffer struct.
159    */
160   XMesaBuffer target = (XMesaBuffer) buffer;
161   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
162
163   /* This assignment tells the span/point/line/triangle functions
164    * which XMesaBuffer to use.
165    */
166   xmesa->xm_buffer = target;
167
168   /*
169    * Now determine front vs back color buffer.
170    */
171   if (bufferBit == DD_FRONT_LEFT_BIT) {
172      target->buffer = target->frontbuffer;
173      xmesa_update_span_funcs(ctx);
174   }
175   else if (bufferBit == DD_BACK_LEFT_BIT) {
176      ASSERT(target->db_state);
177      if (target->backpixmap) {
178         /* back buffer is a pixmap */
179         target->buffer = (XMesaDrawable) target->backpixmap;
180      }
181      else if (target->backimage) {
182         /* back buffer is an XImage */
183         target->buffer = None;
184      }
185      else {
186         /* No back buffer!!!!  Must be out of memory, use front buffer */
187         target->buffer = target->frontbuffer;
188      }
189      xmesa_update_span_funcs(ctx);
190   }
191   else if (bufferBit & (DD_AUX0_BIT | DD_AUX1_BIT | DD_AUX2_BIT | DD_AUX3_BIT)) {
192      _swrast_use_aux_buffer(ctx, buffer, bufferBit);
193   }
194   else {
195      _mesa_problem(ctx, "invalid buffer 0x%x in set_buffer() in xm_dd.c");
196      return;
197   }
198}
199
200
201
202static void
203clear_index( GLcontext *ctx, GLuint index )
204{
205   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
206   xmesa->clearpixel = (unsigned long) index;
207   XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
208                       (unsigned long) index );
209}
210
211
212static void
213clear_color( GLcontext *ctx, const GLfloat color[4] )
214{
215   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
216   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
217   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
218   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
219   CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
220   xmesa->clearpixel = xmesa_color_to_pixel( xmesa,
221                                             xmesa->clearcolor[0],
222                                             xmesa->clearcolor[1],
223                                             xmesa->clearcolor[2],
224                                             xmesa->clearcolor[3],
225                                             xmesa->xm_visual->undithered_pf );
226   _glthread_LOCK_MUTEX(_xmesa_lock);
227   XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
228                       xmesa->clearpixel );
229   _glthread_UNLOCK_MUTEX(_xmesa_lock);
230}
231
232
233
234/* Set index mask ala glIndexMask */
235static void
236index_mask( GLcontext *ctx, GLuint mask )
237{
238   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
239   if (xmesa->xm_draw_buffer->buffer != XIMAGE) {
240      unsigned long m;
241      if (mask==0xffffffff) {
242	 m = ((unsigned long)~0L);
243      }
244      else {
245         m = (unsigned long) mask;
246      }
247      XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
248      XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m );
249   }
250}
251
252
253/* Implements glColorMask() */
254static void
255color_mask(GLcontext *ctx,
256           GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
257{
258   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
259   const int xclass = xmesa->xm_visual->mesa_visual.visualType;
260   (void) amask;
261
262   if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
263      unsigned long m;
264      if (rmask && gmask && bmask) {
265         m = ((unsigned long)~0L);
266      }
267      else {
268         m = 0;
269         if (rmask)   m |= GET_REDMASK(xmesa->xm_visual);
270         if (gmask)   m |= GET_GREENMASK(xmesa->xm_visual);
271         if (bmask)   m |= GET_BLUEMASK(xmesa->xm_visual);
272      }
273      XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
274      XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m );
275   }
276}
277
278
279
280/**********************************************************************/
281/*** glClear implementations                                        ***/
282/**********************************************************************/
283
284
285static void
286clear_front_pixmap( GLcontext *ctx, GLboolean all,
287                    GLint x, GLint y, GLint width, GLint height )
288{
289   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
290   if (all) {
291      XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
292                          xmesa->xm_draw_buffer->cleargc,
293                          0, 0,
294                          xmesa->xm_draw_buffer->width+1,
295                          xmesa->xm_draw_buffer->height+1 );
296   }
297   else {
298      XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
299                          xmesa->xm_draw_buffer->cleargc,
300                          x, xmesa->xm_draw_buffer->height - y - height,
301                          width, height );
302   }
303}
304
305
306static void
307clear_back_pixmap( GLcontext *ctx, GLboolean all,
308                   GLint x, GLint y, GLint width, GLint height )
309{
310   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
311   if (all) {
312      XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
313                          xmesa->xm_draw_buffer->cleargc,
314                          0, 0,
315                          xmesa->xm_draw_buffer->width+1,
316                          xmesa->xm_draw_buffer->height+1 );
317   }
318   else {
319      XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
320                          xmesa->xm_draw_buffer->cleargc,
321                          x, xmesa->xm_draw_buffer->height - y - height,
322                          width, height );
323   }
324}
325
326
327static void
328clear_8bit_ximage( GLcontext *ctx, GLboolean all,
329                   GLint x, GLint y, GLint width, GLint height )
330{
331   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
332   if (all) {
333      size_t n = xmesa->xm_draw_buffer->backimage->bytes_per_line
334         * xmesa->xm_draw_buffer->backimage->height;
335      MEMSET( xmesa->xm_draw_buffer->backimage->data, xmesa->clearpixel, n );
336   }
337   else {
338      GLint i;
339      for (i=0;i<height;i++) {
340         GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, y+i );
341         MEMSET( ptr, xmesa->clearpixel, width );
342      }
343   }
344}
345
346
347static void
348clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
349                   GLint x, GLint y, GLint width, GLint height )
350{
351   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
352   if (all) {
353      GLint i, c16 = (xmesa->xm_draw_buffer->backimage->bytes_per_line>>4)<<4;
354      GLubyte *ptr  = (GLubyte *)xmesa->xm_draw_buffer->backimage->data;
355      for (i=0; i<xmesa->xm_draw_buffer->backimage->height; i++) {
356         GLint j;
357         GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
358         if (i&1) {
359            sptr += 16;
360         }
361         for (j=0; j<c16; j+=16) {
362            ptr[0] = sptr[0];
363            ptr[1] = sptr[1];
364            ptr[2] = sptr[2];
365            ptr[3] = sptr[3];
366            ptr[4] = sptr[4];
367            ptr[5] = sptr[5];
368            ptr[6] = sptr[6];
369            ptr[7] = sptr[7];
370            ptr[8] = sptr[8];
371            ptr[9] = sptr[9];
372            ptr[10] = sptr[10];
373            ptr[11] = sptr[11];
374            ptr[12] = sptr[12];
375            ptr[13] = sptr[13];
376            ptr[14] = sptr[14];
377            ptr[15] = sptr[15];
378            ptr += 16;
379         }
380         for (; j<xmesa->xm_draw_buffer->backimage->bytes_per_line; j++) {
381            *ptr = sptr[j&15];
382            ptr++;
383         }
384      }
385   }
386   else {
387      GLint i;
388      for (i=y; i<y+height; i++) {
389         GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, i );
390         int j;
391         GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
392         if (i&1) {
393            sptr += 16;
394         }
395         for (j=x; j<x+width; j++) {
396            *ptr = sptr[j&15];
397            ptr++;
398         }
399      }
400   }
401}
402
403
404static void
405clear_16bit_ximage( GLcontext *ctx, GLboolean all,
406                    GLint x, GLint y, GLint width, GLint height )
407{
408   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
409   register GLuint pixel = (GLuint) xmesa->clearpixel;
410   if (xmesa->swapbytes) {
411      pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
412   }
413   if (all) {
414      register GLuint n;
415      register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
416      if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
417         /* low and high bytes are equal so use memset() */
418         n = xmesa->xm_draw_buffer->backimage->bytes_per_line
419            * xmesa->xm_draw_buffer->height;
420         MEMSET( ptr4, pixel & 0xff, n );
421      }
422      else {
423         pixel = pixel | (pixel<<16);
424         n = xmesa->xm_draw_buffer->backimage->bytes_per_line
425            * xmesa->xm_draw_buffer->height / 4;
426         do {
427            *ptr4++ = pixel;
428               n--;
429         } while (n!=0);
430
431         if ((xmesa->xm_draw_buffer->backimage->bytes_per_line *
432              xmesa->xm_draw_buffer->height) & 0x2)
433            *(GLushort *)ptr4 = pixel & 0xffff;
434      }
435   }
436   else {
437      register int i, j;
438      for (j=0;j<height;j++) {
439         register GLushort *ptr2 = PIXELADDR2( xmesa->xm_draw_buffer, x, y+j );
440         for (i=0;i<width;i++) {
441            *ptr2++ = pixel;
442         }
443      }
444   }
445}
446
447
448/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
449static void
450clear_24bit_ximage( GLcontext *ctx, GLboolean all,
451                    GLint x, GLint y, GLint width, GLint height )
452{
453   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
454   const GLubyte r = xmesa->clearcolor[0];
455   const GLubyte g = xmesa->clearcolor[1];
456   const GLubyte b = xmesa->clearcolor[2];
457#if 0	/* See below */
458   register GLuint clearPixel;
459   if (xmesa->swapbytes) {
460      clearPixel = (b << 16) | (g << 8) | r;
461   }
462   else {
463      clearPixel = (r << 16) | (g << 8) | b;
464   }
465#endif
466
467   if (all) {
468      if (r==g && g==b) {
469         /* same value for all three components (gray) */
470         const GLint w3 = xmesa->xm_draw_buffer->width * 3;
471         const GLint h = xmesa->xm_draw_buffer->height;
472         GLint i;
473         for (i = 0; i < h; i++) {
474            bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
475            MEMSET(ptr3, r, w3);
476         }
477      }
478      else {
479         /* the usual case */
480         const GLint w = xmesa->xm_draw_buffer->width;
481         const GLint h = xmesa->xm_draw_buffer->height;
482         GLint i, j;
483         for (i = 0; i < h; i++) {
484            bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
485            for (j = 0; j < w; j++) {
486               ptr3->r = r;
487               ptr3->g = g;
488               ptr3->b = b;
489               ptr3++;
490            }
491         }
492#if 0 /* this code doesn't work for all window widths */
493         register GLuint *ptr4 = (GLuint *) ptr3;
494         register GLuint px;
495         GLuint pixel4[3];
496         register GLuint *p = pixel4;
497         pixel4[0] = clearPixel | (clearPixel << 24);
498         pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
499         pixel4[2] = (clearPixel << 8) | (clearPixel >>  16);
500         switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
501            case 0:
502               break;
503            case 1:
504               px = *ptr4 & 0x00ffffff;
505               px |= pixel4[0] & 0xff000000;
506               *ptr4++ = px;
507               px = *ptr4 & 0xffff0000;
508               px |= pixel4[2] & 0x0000ffff;
509               *ptr4 = px;
510               if (0 == --n)
511                  break;
512            case 2:
513               px = *ptr4 & 0x0000fffff;
514               px |= pixel4[1] & 0xffff0000;
515               *ptr4++ = px;
516               px = *ptr4 & 0xffffff00;
517               px |= pixel4[2] & 0x000000ff;
518               *ptr4 = px;
519               if (0 == --n)
520                  break;
521            case 3:
522               px = *ptr4 & 0x000000ff;
523               px |= pixel4[2] & 0xffffff00;
524               *ptr4++ = px;
525               --n;
526               break;
527         }
528         while (n > 3) {
529            p = pixel4;
530            *ptr4++ = *p++;
531            *ptr4++ = *p++;
532            *ptr4++ = *p++;
533            n -= 4;
534         }
535         switch (n) {
536            case 3:
537               p = pixel4;
538               *ptr4++ = *p++;
539               *ptr4++ = *p++;
540               px = *ptr4 & 0xffffff00;
541               px |= clearPixel & 0xff;
542               *ptr4 = px;
543               break;
544            case 2:
545               p = pixel4;
546               *ptr4++ = *p++;
547               px = *ptr4 & 0xffff0000;
548               px |= *p & 0xffff;
549               *ptr4 = px;
550               break;
551            case 1:
552               px = *ptr4 & 0xff000000;
553               px |= *p & 0xffffff;
554               *ptr4 = px;
555               break;
556            case 0:
557               break;
558         }
559#endif
560      }
561   }
562   else {
563      /* only clear subrect of color buffer */
564      if (r==g && g==b) {
565         /* same value for all three components (gray) */
566         GLint j;
567         for (j=0;j<height;j++) {
568            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
569            MEMSET(ptr3, r, 3 * width);
570         }
571      }
572      else {
573         /* non-gray clear color */
574         GLint i, j;
575         for (j = 0; j < height; j++) {
576            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
577            for (i = 0; i < width; i++) {
578               ptr3->r = r;
579               ptr3->g = g;
580               ptr3->b = b;
581               ptr3++;
582            }
583         }
584#if 0 /* this code might not always (seems ptr3 always == ptr4) */
585         GLint j;
586         GLuint pixel4[3];
587         pixel4[0] = clearPixel | (clearPixel << 24);
588         pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
589         pixel4[2] = (clearPixel << 8) | (clearPixel >>  16);
590         for (j=0;j<height;j++) {
591            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
592            register GLuint *ptr4 = (GLuint *)ptr3;
593            register GLuint *p, px;
594            GLuint w = width;
595            switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
596               case 0:
597                  break;
598               case 1:
599                  px = *ptr4 & 0x00ffffff;
600                  px |= pixel4[0] & 0xff000000;
601                  *ptr4++ = px;
602                  px = *ptr4 & 0xffff0000;
603                  px |= pixel4[2] & 0x0000ffff;
604                  *ptr4 = px;
605                  if (0 == --w)
606                     break;
607               case 2:
608                  px = *ptr4 & 0x0000fffff;
609                  px |= pixel4[1] & 0xffff0000;
610                  *ptr4++ = px;
611                  px = *ptr4 & 0xffffff00;
612                  px |= pixel4[2] & 0x000000ff;
613                  *ptr4 = px;
614                  if (0 == --w)
615                     break;
616               case 3:
617                  px = *ptr4 & 0x000000ff;
618                  px |= pixel4[2] & 0xffffff00;
619                  *ptr4++ = px;
620                  --w;
621                  break;
622            }
623            while (w > 3){
624               p = pixel4;
625               *ptr4++ = *p++;
626               *ptr4++ = *p++;
627               *ptr4++ = *p++;
628               w -= 4;
629            }
630            switch (w) {
631               case 3:
632                  p = pixel4;
633                  *ptr4++ = *p++;
634                  *ptr4++ = *p++;
635                  px = *ptr4 & 0xffffff00;
636                  px |= *p & 0xff;
637                  *ptr4 = px;
638                  break;
639               case 2:
640                  p = pixel4;
641                  *ptr4++ = *p++;
642                  px = *ptr4 & 0xffff0000;
643                  px |= *p & 0xffff;
644                  *ptr4 = px;
645                  break;
646               case 1:
647                  px = *ptr4 & 0xff000000;
648                  px |= pixel4[0] & 0xffffff;
649                  *ptr4 = px;
650                  break;
651               case 0:
652                  break;
653            }
654         }
655#endif
656      }
657   }
658}
659
660
661static void
662clear_32bit_ximage( GLcontext *ctx, GLboolean all,
663                    GLint x, GLint y, GLint width, GLint height )
664{
665   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
666   register GLuint pixel = (GLuint) xmesa->clearpixel;
667   if (xmesa->swapbytes) {
668      pixel = ((pixel >> 24) & 0x000000ff)
669            | ((pixel >> 8)  & 0x0000ff00)
670            | ((pixel << 8)  & 0x00ff0000)
671            | ((pixel << 24) & 0xff000000);
672   }
673   if (all) {
674      register GLint n = xmesa->xm_draw_buffer->width * xmesa->xm_draw_buffer->height;
675      register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
676      if (pixel==0) {
677         MEMSET( ptr4, pixel, 4*n );
678      }
679      else {
680         do {
681            *ptr4++ = pixel;
682            n--;
683         } while (n!=0);
684      }
685   }
686   else {
687      register int i, j;
688      for (j=0;j<height;j++) {
689         register GLuint *ptr4 = PIXELADDR4( xmesa->xm_draw_buffer, x, y+j );
690         for (i=0;i<width;i++) {
691            *ptr4++ = pixel;
692         }
693      }
694   }
695}
696
697
698static void
699clear_nbit_ximage( GLcontext *ctx, GLboolean all,
700                   GLint x, GLint y, GLint width, GLint height )
701{
702   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
703   XMesaImage *img = xmesa->xm_draw_buffer->backimage;
704   if (all) {
705      register int i, j;
706      width = xmesa->xm_draw_buffer->width;
707      height = xmesa->xm_draw_buffer->height;
708      for (j=0;j<height;j++) {
709         for (i=0;i<width;i++) {
710            XMesaPutPixel( img, i, j, xmesa->clearpixel );
711         }
712      }
713   }
714   else {
715      /* TODO: optimize this */
716      register int i, j;
717      y = FLIP(xmesa->xm_draw_buffer, y);
718      for (j=0;j<height;j++) {
719         for (i=0;i<width;i++) {
720            XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
721         }
722      }
723   }
724}
725
726
727
728static void
729clear_buffers( GLcontext *ctx, GLbitfield mask,
730               GLboolean all, GLint x, GLint y, GLint width, GLint height )
731{
732   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
733   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
734
735   if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) &&
736       xmesa->xm_draw_buffer->mesa_buffer.UseSoftwareAlphaBuffers &&
737       ctx->Color.ColorMask[ACOMP]) {
738      _swrast_clear_alpha_buffers(ctx);
739   }
740
741   /* we can't handle color or index masking */
742   if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
743      if (mask & DD_FRONT_LEFT_BIT) {
744	 ASSERT(xmesa->xm_draw_buffer->front_clear_func);
745	 (*xmesa->xm_draw_buffer->front_clear_func)( ctx, all, x, y, width, height );
746	 mask &= ~DD_FRONT_LEFT_BIT;
747      }
748      if (mask & DD_BACK_LEFT_BIT) {
749	 ASSERT(xmesa->xm_draw_buffer->back_clear_func);
750	 (*xmesa->xm_draw_buffer->back_clear_func)( ctx, all, x, y, width, height );
751	 mask &= ~DD_BACK_LEFT_BIT;
752      }
753   }
754
755   if (mask)
756      _swrast_Clear( ctx, mask, all, x, y, width, height );
757}
758
759
760/*
761 * When we detect that the user has resized the window this function will
762 * get called.  Here we'll reallocate the back buffer, depth buffer,
763 * stencil buffer etc. to match the new window size.
764 */
765void
766xmesa_resize_buffers( GLframebuffer *buffer )
767{
768   int height = (int) buffer->Height;
769   /* We can do this cast because the first field in the XMesaBuffer
770    * struct is a GLframebuffer struct.  If this weren't true, we'd
771    * need a pointer from the GLframebuffer to the XMesaBuffer.
772    */
773   XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
774
775   xmBuffer->width = buffer->Width;
776   xmBuffer->height = buffer->Height;
777   xmesa_alloc_back_buffer( xmBuffer );
778
779   /* Needed by FLIP macro */
780   xmBuffer->bottom = height - 1;
781
782   if (xmBuffer->backimage) {
783      /* Needed by PIXELADDR1 macro */
784      xmBuffer->ximage_width1 = xmBuffer->backimage->bytes_per_line;
785      xmBuffer->ximage_origin1 = (GLubyte *) xmBuffer->backimage->data
786         + xmBuffer->ximage_width1 * (height-1);
787
788      /* Needed by PIXELADDR2 macro */
789      xmBuffer->ximage_width2 = xmBuffer->backimage->bytes_per_line / 2;
790      xmBuffer->ximage_origin2 = (GLushort *) xmBuffer->backimage->data
791         + xmBuffer->ximage_width2 * (height-1);
792
793      /* Needed by PIXELADDR3 macro */
794      xmBuffer->ximage_width3 = xmBuffer->backimage->bytes_per_line;
795      xmBuffer->ximage_origin3 = (GLubyte *) xmBuffer->backimage->data
796         + xmBuffer->ximage_width3 * (height-1);
797
798      /* Needed by PIXELADDR4 macro */
799      xmBuffer->ximage_width4 = xmBuffer->backimage->width;
800      xmBuffer->ximage_origin4 = (GLuint *) xmBuffer->backimage->data
801         + xmBuffer->ximage_width4 * (height-1);
802   }
803
804   _swrast_alloc_buffers( buffer );
805}
806
807
808#ifndef XFree86Server
809/* XXX this was never tested in the Xserver environment */
810
811/**
812 * This function implements glDrawPixels() with an XPutImage call when
813 * drawing to the front buffer (X Window drawable).
814 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
815 */
816static void
817xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
818                         GLint x, GLint y, GLsizei width, GLsizei height,
819                         GLenum format, GLenum type,
820                         const struct gl_pixelstore_attrib *unpack,
821                         const GLvoid *pixels )
822{
823   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
824   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
825   XMesaDisplay *dpy = xmesa->xm_visual->display;
826   const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
827   const XMesaGC gc = xmesa->xm_draw_buffer->gc;
828
829   ASSERT(dpy);
830   ASSERT(gc);
831   ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
832   ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
833
834   if (swrast->NewState)
835      _swrast_validate_derived( ctx );
836
837   if (buffer &&   /* buffer != 0 means it's a Window or Pixmap */
838       format == GL_BGRA &&
839       type == GL_UNSIGNED_BYTE &&
840       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
841       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
842       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
843       ctx->Pixel.ZoomY == 1.0) {
844      int dstX = x;
845      int dstY = y;
846      int w = width;
847      int h = height;
848      int srcX = unpack->SkipPixels;
849      int srcY = unpack->SkipRows;
850      int rowLength = unpack->RowLength ? unpack->RowLength : width;
851
852      pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
853                                           format, type, (GLvoid *) pixels);
854      if (!pixels)
855         return;
856
857      if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
858         /* This is a little tricky since all coordinates up to now have
859          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
860          * so we have to carefully compute the Y coordinates/addresses here.
861          */
862         XMesaImage ximage;
863         MEMSET(&ximage, 0, sizeof(XMesaImage));
864         ximage.width = width;
865         ximage.height = height;
866         ximage.format = ZPixmap;
867         ximage.data = (char *) pixels
868            + ((srcY + h - 1) * rowLength + srcX) * 4;
869         ximage.byte_order = LSBFirst;
870         ximage.bitmap_unit = 32;
871         ximage.bitmap_bit_order = LSBFirst;
872         ximage.bitmap_pad = 32;
873         ximage.depth = 24;
874         ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
875         ximage.bits_per_pixel = 32;
876         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
877         /* flip Y axis for dest position */
878         dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
879         XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
880      }
881   }
882   else {
883      /* software fallback */
884      _swrast_DrawPixels(ctx, x, y, width, height,
885                         format, type, unpack, pixels);
886   }
887}
888
889
890
891/**
892 * This function implements glDrawPixels() with an XPutImage call when
893 * drawing to the front buffer (X Window drawable).  The image format
894 * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
895 * match the PF_5R6G5B pixel format.
896 */
897static void
898xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
899                         GLint x, GLint y, GLsizei width, GLsizei height,
900                         GLenum format, GLenum type,
901                         const struct gl_pixelstore_attrib *unpack,
902                         const GLvoid *pixels )
903{
904   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
905   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
906   XMesaDisplay *dpy = xmesa->xm_visual->display;
907   const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
908   const XMesaGC gc = xmesa->xm_draw_buffer->gc;
909
910   ASSERT(dpy);
911   ASSERT(gc);
912   ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
913
914   if (swrast->NewState)
915      _swrast_validate_derived( ctx );
916
917   if (buffer &&   /* buffer != 0 means it's a Window or Pixmap */
918       format == GL_RGB &&
919       type == GL_UNSIGNED_SHORT_5_6_5 &&
920       !ctx->Color.DitherFlag &&  /* no dithering */
921       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
922       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
923       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
924       ctx->Pixel.ZoomY == 1.0) {
925      int dstX = x;
926      int dstY = y;
927      int w = width;
928      int h = height;
929      int srcX = unpack->SkipPixels;
930      int srcY = unpack->SkipRows;
931      int rowLength = unpack->RowLength ? unpack->RowLength : width;
932
933      pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
934                                           format, type, (GLvoid *) pixels);
935      if (!pixels)
936         return;
937
938      if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
939         /* This is a little tricky since all coordinates up to now have
940          * been in the OpenGL bottom-to-top orientation.  X is top-to-bottom
941          * so we have to carefully compute the Y coordinates/addresses here.
942          */
943         XMesaImage ximage;
944         MEMSET(&ximage, 0, sizeof(XMesaImage));
945         ximage.width = width;
946         ximage.height = height;
947         ximage.format = ZPixmap;
948         ximage.data = (char *) pixels
949            + ((srcY + h - 1) * rowLength + srcX) * 2;
950         ximage.byte_order = LSBFirst;
951         ximage.bitmap_unit = 16;
952         ximage.bitmap_bit_order = LSBFirst;
953         ximage.bitmap_pad = 16;
954         ximage.depth = 16;
955         ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
956         ximage.bits_per_pixel = 16;
957         /* it seems we don't need to set the ximage.red/green/blue_mask fields */
958         /* flip Y axis for dest position */
959         dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
960         XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
961      }
962   }
963   else {
964      /* software fallback */
965      _swrast_DrawPixels(ctx, x, y, width, height,
966                         format, type, unpack, pixels);
967   }
968}
969
970
971
972/**
973 * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
974 * for the color buffer.  Don't support zooming, pixel transfer, etc.
975 * We do support copying from one window to another, ala glXMakeCurrentRead.
976 */
977static void
978xmesa_CopyPixels( GLcontext *ctx,
979                  GLint srcx, GLint srcy, GLsizei width, GLsizei height,
980                  GLint destx, GLint desty, GLenum type )
981{
982   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
983   const SWcontext *swrast = SWRAST_CONTEXT( ctx );
984   XMesaDisplay *dpy = xmesa->xm_visual->display;
985   const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
986   const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
987   const XMesaGC gc = xmesa->xm_draw_buffer->gc;
988
989   ASSERT(dpy);
990   ASSERT(gc);
991
992   if (swrast->NewState)
993      _swrast_validate_derived( ctx );
994
995   if (ctx->Color.DrawBuffer == GL_FRONT &&
996       ctx->Pixel.ReadBuffer == GL_FRONT &&
997       drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */
998       readBuffer &&
999       type == GL_COLOR &&
1000       (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
1001       ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */
1002       ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */
1003       ctx->Pixel.ZoomY == 1.0) {
1004      /* Note: we don't do any special clipping work here.  We could,
1005       * but X will do it for us.
1006       */
1007      srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
1008      desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
1009      XCopyArea(dpy, readBuffer, drawBuffer, gc,
1010                srcx, srcy, width, height, destx, desty);
1011   }
1012   else {
1013      _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
1014   }
1015}
1016#endif /* XFree86Server */
1017
1018
1019
1020/*
1021 * Every driver should implement a GetString function in order to
1022 * return a meaningful GL_RENDERER string.
1023 */
1024static const GLubyte *
1025get_string( GLcontext *ctx, GLenum name )
1026{
1027   (void) ctx;
1028   switch (name) {
1029      case GL_RENDERER:
1030#ifdef XFree86Server
1031         return (const GLubyte *) "Mesa GLX Indirect";
1032#else
1033         return (const GLubyte *) "Mesa X11";
1034#endif
1035      case GL_VENDOR:
1036#ifdef XFree86Server
1037         return (const GLubyte *) "Mesa project: www.mesa3d.org";
1038#else
1039         return NULL;
1040#endif
1041      default:
1042         return NULL;
1043   }
1044}
1045
1046
1047/*
1048 * We implement the glEnable function only because we care about
1049 * dither enable/disable.
1050 */
1051static void
1052enable( GLcontext *ctx, GLenum pname, GLboolean state )
1053{
1054   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
1055
1056   switch (pname) {
1057      case GL_DITHER:
1058         if (state)
1059            xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
1060         else
1061            xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
1062         break;
1063      default:
1064         ;  /* silence compiler warning */
1065   }
1066}
1067
1068
1069void xmesa_update_state( GLcontext *ctx, GLuint new_state )
1070{
1071   const XMesaContext xmesa = XMESA_CONTEXT(ctx);
1072
1073   /* Propogate statechange information to swrast and swrast_setup
1074    * modules.  The X11 driver has no internal GL-dependent state.
1075    */
1076   _swrast_InvalidateState( ctx, new_state );
1077   _ac_InvalidateState( ctx, new_state );
1078   _tnl_InvalidateState( ctx, new_state );
1079   _swsetup_InvalidateState( ctx, new_state );
1080
1081
1082   /* setup pointers to front and back buffer clear functions */
1083   xmesa->xm_draw_buffer->front_clear_func = clear_front_pixmap;
1084   if (xmesa->xm_draw_buffer->backpixmap != XIMAGE) {
1085      xmesa->xm_draw_buffer->back_clear_func = clear_back_pixmap;
1086   }
1087   else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
1088      xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
1089   }
1090   else switch (xmesa->xm_visual->BitsPerPixel) {
1091   case 8:
1092      if (xmesa->xm_visual->hpcr_clear_flag) {
1093	 xmesa->xm_draw_buffer->back_clear_func = clear_HPCR_ximage;
1094      }
1095      else {
1096	 xmesa->xm_draw_buffer->back_clear_func = clear_8bit_ximage;
1097      }
1098      break;
1099   case 16:
1100      xmesa->xm_draw_buffer->back_clear_func = clear_16bit_ximage;
1101      break;
1102   case 24:
1103      xmesa->xm_draw_buffer->back_clear_func = clear_24bit_ximage;
1104      break;
1105   case 32:
1106      xmesa->xm_draw_buffer->back_clear_func = clear_32bit_ximage;
1107      break;
1108   default:
1109      xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
1110      break;
1111   }
1112
1113   if (ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
1114      xmesa_update_span_funcs(ctx);
1115   }
1116}
1117
1118
1119
1120/**
1121 * Called via ctx->Driver.TestProxyTeximage().  Normally, we'd just use
1122 * the _mesa_test_proxy_teximage() fallback function, but we're going to
1123 * special-case the 3D texture case to allow textures up to 512x512x32
1124 * texels.
1125 */
1126static GLboolean
1127test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
1128                    GLint internalFormat, GLenum format, GLenum type,
1129                    GLint width, GLint height, GLint depth, GLint border)
1130{
1131   if (target == GL_PROXY_TEXTURE_3D) {
1132      /* special case for 3D textures */
1133      if (width * height * depth > 512 * 512 * 64 ||
1134          width  < 2 * border ||
1135          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1136           _mesa_bitcount(width  - 2 * border) != 1) ||
1137          height < 2 * border ||
1138          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1139           _mesa_bitcount(height - 2 * border) != 1) ||
1140          depth  < 2 * border ||
1141          (!ctx->Extensions.ARB_texture_non_power_of_two &&
1142           _mesa_bitcount(depth  - 2 * border) != 1)) {
1143         /* Bad size, or too many texels */
1144         return GL_FALSE;
1145      }
1146      return GL_TRUE;
1147   }
1148   else {
1149      /* use the fallback routine for 1D, 2D, cube and rect targets */
1150      return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
1151                                       format, type, width, height, depth,
1152                                       border);
1153   }
1154}
1155
1156
1157/**
1158 * Initialize the device driver function table with the functions
1159 * we implement in this driver.
1160 */
1161void xmesa_init_driver_functions( XMesaVisual xmvisual,
1162                                  struct dd_function_table *driver )
1163{
1164   driver->GetString = get_string;
1165   driver->UpdateState = xmesa_update_state;
1166   driver->GetBufferSize = get_buffer_size;
1167   driver->Flush = finish_or_flush;
1168   driver->Finish = finish_or_flush;
1169   driver->ClearIndex = clear_index;
1170   driver->ClearColor = clear_color;
1171   driver->IndexMask = index_mask;
1172   driver->ColorMask = color_mask;
1173   driver->Enable = enable;
1174   driver->Clear = clear_buffers;
1175   driver->ResizeBuffers = xmesa_resize_buffers;
1176#ifndef XFree86Server
1177   driver->CopyPixels = /*_swrast_CopyPixels;*/xmesa_CopyPixels;
1178   if (xmvisual->undithered_pf == PF_8R8G8B &&
1179       xmvisual->dithered_pf == PF_8R8G8B) {
1180      driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
1181   }
1182   else if (xmvisual->undithered_pf == PF_5R6G5B) {
1183      driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
1184   }
1185#endif
1186   driver->TestProxyTexImage = test_proxy_teximage;
1187}
1188
1189
1190#define XMESA_NEW_POINT  (_NEW_POINT | \
1191                          _NEW_RENDERMODE | \
1192                          _SWRAST_NEW_RASTERMASK)
1193
1194#define XMESA_NEW_LINE   (_NEW_LINE | \
1195                          _NEW_TEXTURE | \
1196                          _NEW_LIGHT | \
1197                          _NEW_DEPTH | \
1198                          _NEW_RENDERMODE | \
1199                          _SWRAST_NEW_RASTERMASK)
1200
1201#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1202                            _NEW_TEXTURE | \
1203                            _NEW_LIGHT | \
1204                            _NEW_DEPTH | \
1205                            _NEW_RENDERMODE | \
1206                            _SWRAST_NEW_RASTERMASK)
1207
1208
1209/* Extend the software rasterizer with our line/point/triangle
1210 * functions.
1211 */
1212void xmesa_register_swrast_functions( GLcontext *ctx )
1213{
1214   SWcontext *swrast = SWRAST_CONTEXT( ctx );
1215   struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference(ctx);
1216
1217   dd->SetBuffer = xmesa_set_buffer;
1218
1219   swrast->choose_point = xmesa_choose_point;
1220   swrast->choose_line = xmesa_choose_line;
1221   swrast->choose_triangle = xmesa_choose_triangle;
1222
1223   swrast->invalidate_point |= XMESA_NEW_POINT;
1224   swrast->invalidate_line |= XMESA_NEW_LINE;
1225   swrast->invalidate_triangle |= XMESA_NEW_TRIANGLE;
1226}
1227