f87d72d0c8c06624dfa7a97deecc894e511f9fcd
[mesa.git] / src / mesa / pipe / xlib / xm_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 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 * \file xm_api.c
27 *
28 * All the XMesa* API functions.
29 *
30 *
31 * NOTES:
32 *
33 * The window coordinate system origin (0,0) is in the lower-left corner
34 * of the window. X11's window coordinate origin is in the upper-left
35 * corner of the window. Therefore, most drawing functions in this
36 * file have to flip Y coordinates.
37 *
38 * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
39 * in support for the MIT Shared Memory extension. If enabled, when you
40 * use an Ximage for the back buffer in double buffered mode, the "swap"
41 * operation will be faster. You must also link with -lXext.
42 *
43 * Byte swapping: If the Mesa host and the X display use a different
44 * byte order then there's some trickiness to be aware of when using
45 * XImages. The byte ordering used for the XImage is that of the X
46 * display, not the Mesa host.
47 * The color-to-pixel encoding for True/DirectColor must be done
48 * according to the display's visual red_mask, green_mask, and blue_mask.
49 * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
50 * do byte swapping if needed. If one wants to directly "poke" the pixel
51 * into the XImage's buffer then the pixel must be byte swapped first. In
52 * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
53 * and use XPutPixel everywhere except in the implementation of
54 * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so
55 * instead of using XPutPixel we "poke" our values after byte-swapping
56 * the clear pixel value if needed.
57 *
58 */
59
60 #ifdef __CYGWIN__
61 #undef WIN32
62 #undef __WIN32__
63 #endif
64
65 #include "glxheader.h"
66 #include "GL/xmesa.h"
67 #include "xmesaP.h"
68 #include "context.h"
69 #include "extensions.h"
70 #include "framebuffer.h"
71 #include "glthread.h"
72 #include "imports.h"
73 #include "macros.h"
74 #include "renderbuffer.h"
75 #include "teximage.h"
76 #include "vbo/vbo.h"
77
78 #include "state_tracker/st_public.h"
79 #include "state_tracker/st_context.h"
80 #include "pipe/softpipe/sp_context.h"
81 #include "pipe/p_defines.h"
82
83 /**
84 * Global X driver lock
85 */
86 _glthread_Mutex _xmesa_lock;
87
88
89
90 /**********************************************************************/
91 /***** X Utility Functions *****/
92 /**********************************************************************/
93
94
95 /**
96 * Return the host's byte order as LSBFirst or MSBFirst ala X.
97 */
98 #ifndef XFree86Server
99 static int host_byte_order( void )
100 {
101 int i = 1;
102 char *cptr = (char *) &i;
103 return (*cptr==1) ? LSBFirst : MSBFirst;
104 }
105 #endif
106
107
108 /**
109 * Check if the X Shared Memory extension is available.
110 * Return: 0 = not available
111 * 1 = shared XImage support available
112 * 2 = shared Pixmap support available also
113 */
114 static int check_for_xshm( XMesaDisplay *display )
115 {
116 #if defined(USE_XSHM) && !defined(XFree86Server)
117 int major, minor, ignore;
118 Bool pixmaps;
119
120 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
121 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
122 return (pixmaps==True) ? 2 : 1;
123 }
124 else {
125 return 0;
126 }
127 }
128 else {
129 return 0;
130 }
131 #else
132 /* No XSHM support */
133 return 0;
134 #endif
135 }
136
137
138 /**
139 * Apply gamma correction to an intensity value in [0..max]. Return the
140 * new intensity value.
141 */
142 static GLint
143 gamma_adjust( GLfloat gamma, GLint value, GLint max )
144 {
145 if (gamma == 1.0) {
146 return value;
147 }
148 else {
149 double x = (double) value / (double) max;
150 return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma));
151 }
152 }
153
154
155
156 /**
157 * Return the true number of bits per pixel for XImages.
158 * For example, if we request a 24-bit deep visual we may actually need/get
159 * 32bpp XImages. This function returns the appropriate bpp.
160 * Input: dpy - the X display
161 * visinfo - desribes the visual to be used for XImages
162 * Return: true number of bits per pixel for XImages
163 */
164 static int
165 bits_per_pixel( XMesaVisual xmv )
166 {
167 #ifdef XFree86Server
168 const int depth = xmv->nplanes;
169 int i;
170 assert(depth > 0);
171 for (i = 0; i < screenInfo.numPixmapFormats; i++) {
172 if (screenInfo.formats[i].depth == depth)
173 return screenInfo.formats[i].bitsPerPixel;
174 }
175 return depth; /* should never get here, but this should be safe */
176 #else
177 XMesaDisplay *dpy = xmv->display;
178 XMesaVisualInfo visinfo = xmv->visinfo;
179 XMesaImage *img;
180 int bitsPerPixel;
181 /* Create a temporary XImage */
182 img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
183 ZPixmap, 0, /*format, offset*/
184 (char*) MALLOC(8), /*data*/
185 1, 1, /*width, height*/
186 32, /*bitmap_pad*/
187 0 /*bytes_per_line*/
188 );
189 assert(img);
190 /* grab the bits/pixel value */
191 bitsPerPixel = img->bits_per_pixel;
192 /* free the XImage */
193 _mesa_free( img->data );
194 img->data = NULL;
195 XMesaDestroyImage( img );
196 return bitsPerPixel;
197 #endif
198 }
199
200
201
202 /*
203 * Determine if a given X window ID is valid (window exists).
204 * Do this by calling XGetWindowAttributes() for the window and
205 * checking if we catch an X error.
206 * Input: dpy - the display
207 * win - the window to check for existance
208 * Return: GL_TRUE - window exists
209 * GL_FALSE - window doesn't exist
210 */
211 #ifndef XFree86Server
212 static GLboolean WindowExistsFlag;
213
214 static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
215 {
216 (void) dpy;
217 if (xerr->error_code == BadWindow) {
218 WindowExistsFlag = GL_FALSE;
219 }
220 return 0;
221 }
222
223 static GLboolean window_exists( XMesaDisplay *dpy, Window win )
224 {
225 XWindowAttributes wa;
226 int (*old_handler)( XMesaDisplay*, XErrorEvent* );
227 WindowExistsFlag = GL_TRUE;
228 old_handler = XSetErrorHandler(window_exists_err_handler);
229 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
230 XSetErrorHandler(old_handler);
231 return WindowExistsFlag;
232 }
233
234 static Status
235 get_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height )
236 {
237 Window root;
238 Status stat;
239 int xpos, ypos;
240 unsigned int w, h, bw, depth;
241 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
242 *width = w;
243 *height = h;
244 return stat;
245 }
246 #endif
247
248
249 /**
250 * Return the size of the window (or pixmap) that corresponds to the
251 * given XMesaBuffer.
252 * \param width returns width in pixels
253 * \param height returns height in pixels
254 */
255 void
256 xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
257 GLuint *width, GLuint *height)
258 {
259 #ifdef XFree86Server
260 *width = MIN2(b->frontxrb->drawable->width, MAX_WIDTH);
261 *height = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT);
262 #else
263 Status stat;
264
265 _glthread_LOCK_MUTEX(_xmesa_lock);
266 XSync(b->xm_visual->display, 0); /* added for Chromium */
267 stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height);
268 _glthread_UNLOCK_MUTEX(_xmesa_lock);
269
270 if (!stat) {
271 /* probably querying a window that's recently been destroyed */
272 _mesa_warning(NULL, "XGetGeometry failed!\n");
273 *width = *height = 1;
274 }
275 #endif
276 }
277
278
279
280 /**********************************************************************/
281 /***** Linked list of XMesaBuffers *****/
282 /**********************************************************************/
283
284 XMesaBuffer XMesaBufferList = NULL;
285
286
287 /**
288 * Allocate a new XMesaBuffer object which corresponds to the given drawable.
289 * Note that XMesaBuffer is derived from GLframebuffer.
290 * The new XMesaBuffer will not have any size (Width=Height=0).
291 *
292 * \param d the corresponding X drawable (window or pixmap)
293 * \param type either WINDOW, PIXMAP or PBUFFER, describing d
294 * \param vis the buffer's visual
295 * \param cmap the window's colormap, if known.
296 * \return new XMesaBuffer or NULL if any problem
297 */
298 static XMesaBuffer
299 create_xmesa_buffer(XMesaDrawable d, BufferType type,
300 XMesaVisual vis, XMesaColormap cmap)
301 {
302 XMesaBuffer b;
303 GLframebuffer *fb;
304 struct pipe_winsys *winsys = xmesa_get_pipe_winsys();
305
306 ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
307
308 b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
309 if (!b)
310 return NULL;
311
312 b->display = vis->display;
313 b->xm_visual = vis;
314 b->type = type;
315 b->cmap = cmap;
316
317 /*
318 * Create framebuffer, but we'll plug in our own renderbuffers below.
319 */
320 b->stfb = st_create_framebuffer(&vis->mesa_visual, GL_FALSE, (void *) b);
321 fb = &b->stfb->Base;
322
323 fb->Delete = xmesa_delete_framebuffer;
324
325 /*
326 * XXX we want to create surfaces for pipe, not renderbuffers for Mesa.
327 */
328
329 /*
330 * Front renderbuffer
331 */
332 b->frontxrb = xmesa_create_renderbuffer(winsys, 0, vis, GL_FALSE);
333 if (!b->frontxrb) {
334 _mesa_free(b);
335 return NULL;
336 }
337 b->frontxrb->Parent = b;
338 b->frontxrb->drawable = d;
339 b->frontxrb->pixmap = (XMesaPixmap) d;
340 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &b->frontxrb->St.Base);
341
342 /*
343 * Back renderbuffer
344 */
345 if (vis->mesa_visual.doubleBufferMode) {
346 b->backxrb = xmesa_create_renderbuffer(winsys, 0, vis, GL_TRUE);
347 if (!b->backxrb) {
348 /* XXX free front xrb too */
349 _mesa_free(b);
350 return NULL;
351 }
352 b->backxrb->Parent = b;
353 /* determine back buffer implementation */
354 b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP;
355
356 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &b->backxrb->St.Base);
357 }
358
359 /*
360 * Software alpha planes
361 */
362 if (vis->mesa_visual.alphaBits > 0
363 && vis->undithered_pf != PF_8A8B8G8R
364 && vis->undithered_pf != PF_8A8R8G8B) {
365 /* Visual has alpha, but pixel format doesn't support it.
366 * We'll use an alpha renderbuffer wrapper.
367 */
368 #if 0
369 b->swAlpha = GL_TRUE; /* don't do any renderbuffer wrapping */
370 #else
371 b->swAlpha = GL_FALSE;
372 #endif
373 }
374 else {
375 b->swAlpha = GL_FALSE;
376 }
377
378 if (vis->mesa_visual.depthBits > 0 &&
379 vis->mesa_visual.stencilBits > 0) {
380 /* combined depth/stencil */
381 struct gl_renderbuffer *rb
382 = st_new_renderbuffer_fb(GL_DEPTH24_STENCIL8_EXT);
383 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
384 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
385 }
386 else {
387 if (vis->mesa_visual.depthBits > 24) {
388 struct gl_renderbuffer *rb
389 = st_new_renderbuffer_fb(GL_DEPTH_COMPONENT32);
390 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
391 }
392 else if (vis->mesa_visual.depthBits > 16) {
393 struct gl_renderbuffer *rb
394 = st_new_renderbuffer_fb(GL_DEPTH24_STENCIL8_EXT);
395 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
396 }
397 else if (vis->mesa_visual.depthBits > 1) {
398 struct gl_renderbuffer *rb
399 = st_new_renderbuffer_fb(GL_DEPTH_COMPONENT16);
400 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
401 }
402
403 if (vis->mesa_visual.stencilBits > 0) {
404 struct gl_renderbuffer *rb
405 = st_new_renderbuffer_fb(GL_STENCIL_INDEX8_EXT);
406 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
407 }
408 }
409
410 if (vis->mesa_visual.accumRedBits > 0) {
411 struct gl_renderbuffer *rb
412 = st_new_renderbuffer_fb(GL_RGBA16);
413 _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb);
414 }
415
416
417 /*
418 * Other renderbuffer (depth, stencil, etc)
419 */
420 _mesa_add_soft_renderbuffers(fb,
421 GL_FALSE, /* color */
422 GL_FALSE, /*vis->mesa_visual.haveDepthBuffer,*/
423 GL_FALSE, /* stencil */
424 GL_FALSE, /* accum */
425 b->swAlpha,
426 vis->mesa_visual.numAuxBuffers > 0 );
427
428 /* GLX_EXT_texture_from_pixmap */
429 b->TextureTarget = 0;
430 b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
431 b->TextureMipmap = 0;
432
433 /* insert buffer into linked list */
434 b->Next = XMesaBufferList;
435 XMesaBufferList = b;
436
437 return b;
438 }
439
440
441 /**
442 * Find an XMesaBuffer by matching X display and colormap but NOT matching
443 * the notThis buffer.
444 */
445 XMesaBuffer
446 xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
447 {
448 XMesaBuffer b;
449 for (b=XMesaBufferList; b; b=b->Next) {
450 if (b->display==dpy && b->cmap==cmap && b!=notThis) {
451 return b;
452 }
453 }
454 return NULL;
455 }
456
457
458 /**
459 * Remove buffer from linked list, delete if no longer referenced.
460 */
461 static void
462 xmesa_free_buffer(XMesaBuffer buffer)
463 {
464 XMesaBuffer prev = NULL, b;
465
466 for (b = XMesaBufferList; b; b = b->Next) {
467 if (b == buffer) {
468 struct gl_framebuffer *fb = &buffer->stfb->Base;
469
470 /* unlink buffer from list */
471 if (prev)
472 prev->Next = buffer->Next;
473 else
474 XMesaBufferList = buffer->Next;
475
476 /* mark as delete pending */
477 fb->DeletePending = GL_TRUE;
478
479 /* Since the X window for the XMesaBuffer is going away, we don't
480 * want to dereference this pointer in the future.
481 */
482 b->frontxrb->drawable = 0;
483
484 /* Unreference. If count = zero we'll really delete the buffer */
485 _mesa_unreference_framebuffer(&fb);
486
487 return;
488 }
489 /* continue search */
490 prev = b;
491 }
492 /* buffer not found in XMesaBufferList */
493 _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
494 }
495
496
497 /**
498 * Copy X color table stuff from one XMesaBuffer to another.
499 */
500 static void
501 copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
502 {
503 MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
504 MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
505 MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
506 MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
507 dst->num_alloced = src->num_alloced;
508 MEMCPY(dst->alloced_colors, src->alloced_colors,
509 sizeof(src->alloced_colors));
510 }
511
512
513
514 /**********************************************************************/
515 /***** Misc Private Functions *****/
516 /**********************************************************************/
517
518
519 /**
520 * A replacement for XAllocColor. This function should never
521 * fail to allocate a color. When XAllocColor fails, we return
522 * the nearest matching color. If we have to allocate many colors
523 * this function isn't too efficient; the XQueryColors() could be
524 * done just once.
525 * Written by Michael Pichler, Brian Paul, Mark Kilgard
526 * Input: dpy - X display
527 * cmap - X colormap
528 * cmapSize - size of colormap
529 * In/Out: color - the XColor struct
530 * Output: exact - 1=exact color match, 0=closest match
531 * alloced - 1=XAlloc worked, 0=XAlloc failed
532 */
533 static void
534 noFaultXAllocColor( int client,
535 XMesaDisplay *dpy,
536 XMesaColormap cmap,
537 int cmapSize,
538 XMesaColor *color,
539 int *exact, int *alloced )
540 {
541 #ifdef XFree86Server
542 Pixel *ppixIn;
543 xrgb *ctable;
544 #else
545 /* we'll try to cache ctable for better remote display performance */
546 static Display *prevDisplay = NULL;
547 static XMesaColormap prevCmap = 0;
548 static int prevCmapSize = 0;
549 static XMesaColor *ctable = NULL;
550 #endif
551 XMesaColor subColor;
552 int i, bestmatch;
553 double mindist; /* 3*2^16^2 exceeds long int precision. */
554
555 (void) client;
556
557 /* First try just using XAllocColor. */
558 #ifdef XFree86Server
559 if (AllocColor(cmap,
560 &color->red, &color->green, &color->blue,
561 &color->pixel,
562 client) == Success)
563 #else
564 if (XAllocColor(dpy, cmap, color))
565 #endif
566 {
567 *exact = 1;
568 *alloced = 1;
569 return;
570 }
571
572 /* Alloc failed, search for closest match */
573
574 /* Retrieve color table entries. */
575 /* XXX alloca candidate. */
576 #ifdef XFree86Server
577 ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
578 ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
579 for (i = 0; i < cmapSize; i++) {
580 ppixIn[i] = i;
581 }
582 QueryColors(cmap, cmapSize, ppixIn, ctable);
583 #else
584 if (prevDisplay != dpy || prevCmap != cmap
585 || prevCmapSize != cmapSize || !ctable) {
586 /* free previously cached color table */
587 if (ctable)
588 _mesa_free(ctable);
589 /* Get the color table from X */
590 ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
591 assert(ctable);
592 for (i = 0; i < cmapSize; i++) {
593 ctable[i].pixel = i;
594 }
595 XQueryColors(dpy, cmap, ctable, cmapSize);
596 prevDisplay = dpy;
597 prevCmap = cmap;
598 prevCmapSize = cmapSize;
599 }
600 #endif
601
602 /* Find best match. */
603 bestmatch = -1;
604 mindist = 0.0;
605 for (i = 0; i < cmapSize; i++) {
606 double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
607 double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
608 double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
609 double dist = dr * dr + dg * dg + db * db;
610 if (bestmatch < 0 || dist < mindist) {
611 bestmatch = i;
612 mindist = dist;
613 }
614 }
615
616 /* Return result. */
617 subColor.red = ctable[bestmatch].red;
618 subColor.green = ctable[bestmatch].green;
619 subColor.blue = ctable[bestmatch].blue;
620 /* Try to allocate the closest match color. This should only
621 * fail if the cell is read/write. Otherwise, we're incrementing
622 * the cell's reference count.
623 */
624 #ifdef XFree86Server
625 if (AllocColor(cmap,
626 &subColor.red, &subColor.green, &subColor.blue,
627 &subColor.pixel,
628 client) == Success) {
629 #else
630 if (XAllocColor(dpy, cmap, &subColor)) {
631 #endif
632 *alloced = 1;
633 }
634 else {
635 /* do this to work around a problem reported by Frank Ortega */
636 subColor.pixel = (unsigned long) bestmatch;
637 subColor.red = ctable[bestmatch].red;
638 subColor.green = ctable[bestmatch].green;
639 subColor.blue = ctable[bestmatch].blue;
640 subColor.flags = DoRed | DoGreen | DoBlue;
641 *alloced = 0;
642 }
643 #ifdef XFree86Server
644 _mesa_free(ppixIn);
645 _mesa_free(ctable);
646 #else
647 /* don't free table, save it for next time */
648 #endif
649
650 *color = subColor;
651 *exact = 0;
652 }
653
654
655
656 /**
657 * Do setup for PF_GRAYSCALE pixel format.
658 * Note that buffer may be NULL.
659 */
660 static GLboolean
661 setup_grayscale(int client, XMesaVisual v,
662 XMesaBuffer buffer, XMesaColormap cmap)
663 {
664 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
665 return GL_FALSE;
666 }
667
668 if (buffer) {
669 XMesaBuffer prevBuffer;
670
671 if (!cmap) {
672 return GL_FALSE;
673 }
674
675 prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
676 if (prevBuffer &&
677 (buffer->xm_visual->mesa_visual.rgbMode ==
678 prevBuffer->xm_visual->mesa_visual.rgbMode)) {
679 /* Copy colormap stuff from previous XMesaBuffer which uses same
680 * X colormap. Do this to avoid time spent in noFaultXAllocColor.
681 */
682 copy_colortable_info(buffer, prevBuffer);
683 }
684 else {
685 /* Allocate 256 shades of gray */
686 int gray;
687 int colorsfailed = 0;
688 for (gray=0;gray<256;gray++) {
689 GLint r = gamma_adjust( v->RedGamma, gray, 255 );
690 GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
691 GLint b = gamma_adjust( v->BlueGamma, gray, 255 );
692 int exact, alloced;
693 XMesaColor xcol;
694 xcol.red = (r << 8) | r;
695 xcol.green = (g << 8) | g;
696 xcol.blue = (b << 8) | b;
697 noFaultXAllocColor( client, v->display,
698 cmap, GET_COLORMAP_SIZE(v),
699 &xcol, &exact, &alloced );
700 if (!exact) {
701 colorsfailed++;
702 }
703 if (alloced) {
704 assert(buffer->num_alloced<256);
705 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
706 buffer->num_alloced++;
707 }
708
709 /*OLD
710 assert(gray < 576);
711 buffer->color_table[gray*3+0] = xcol.pixel;
712 buffer->color_table[gray*3+1] = xcol.pixel;
713 buffer->color_table[gray*3+2] = xcol.pixel;
714 assert(xcol.pixel < 65536);
715 buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
716 buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
717 buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
718 */
719 buffer->color_table[gray] = xcol.pixel;
720 assert(xcol.pixel < 65536);
721 buffer->pixel_to_r[xcol.pixel] = gray;
722 buffer->pixel_to_g[xcol.pixel] = gray;
723 buffer->pixel_to_b[xcol.pixel] = gray;
724 }
725
726 if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
727 _mesa_warning(NULL,
728 "Note: %d out of 256 needed colors do not match exactly.\n",
729 colorsfailed );
730 }
731 }
732 }
733
734 v->dithered_pf = PF_Grayscale;
735 v->undithered_pf = PF_Grayscale;
736 return GL_TRUE;
737 }
738
739
740
741 /**
742 * Setup RGB rendering for a window with a PseudoColor, StaticColor,
743 * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
744 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
745 * color. While this function was originally designed just for 8-bit
746 * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
747 * Dithering code contributed by Bob Mercier.
748 */
749 static GLboolean
750 setup_dithered_color(int client, XMesaVisual v,
751 XMesaBuffer buffer, XMesaColormap cmap)
752 {
753 if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
754 return GL_FALSE;
755 }
756
757 if (buffer) {
758 XMesaBuffer prevBuffer;
759
760 if (!cmap) {
761 return GL_FALSE;
762 }
763
764 prevBuffer = xmesa_find_buffer(v->display, cmap, buffer);
765 if (prevBuffer &&
766 (buffer->xm_visual->mesa_visual.rgbMode ==
767 prevBuffer->xm_visual->mesa_visual.rgbMode)) {
768 /* Copy colormap stuff from previous, matching XMesaBuffer.
769 * Do this to avoid time spent in noFaultXAllocColor.
770 */
771 copy_colortable_info(buffer, prevBuffer);
772 }
773 else {
774 /* Allocate X colors and initialize color_table[], red_table[], etc */
775 int r, g, b, i;
776 int colorsfailed = 0;
777 for (r = 0; r < DITH_R; r++) {
778 for (g = 0; g < DITH_G; g++) {
779 for (b = 0; b < DITH_B; b++) {
780 XMesaColor xcol;
781 int exact, alloced;
782 xcol.red =gamma_adjust(v->RedGamma, r*65535/(DITH_R-1),65535);
783 xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
784 xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(DITH_B-1),65535);
785 noFaultXAllocColor( client, v->display,
786 cmap, GET_COLORMAP_SIZE(v),
787 &xcol, &exact, &alloced );
788 if (!exact) {
789 colorsfailed++;
790 }
791 if (alloced) {
792 assert(buffer->num_alloced<256);
793 buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
794 buffer->num_alloced++;
795 }
796 i = DITH_MIX( r, g, b );
797 assert(i < 576);
798 buffer->color_table[i] = xcol.pixel;
799 assert(xcol.pixel < 65536);
800 buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
801 buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
802 buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
803 }
804 }
805 }
806
807 if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
808 _mesa_warning(NULL,
809 "Note: %d out of %d needed colors do not match exactly.\n",
810 colorsfailed, DITH_R * DITH_G * DITH_B );
811 }
812 }
813 }
814
815 v->dithered_pf = PF_Dither;
816 v->undithered_pf = PF_Lookup;
817 return GL_TRUE;
818 }
819
820
821 /**
822 * Setup RGB rendering for a window with a True/DirectColor visual.
823 */
824 static void
825 setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap)
826 {
827 unsigned long rmask, gmask, bmask;
828 (void) buffer;
829 (void) cmap;
830
831 /* Compute red multiplier (mask) and bit shift */
832 v->rshift = 0;
833 rmask = GET_REDMASK(v);
834 while ((rmask & 1)==0) {
835 v->rshift++;
836 rmask = rmask >> 1;
837 }
838
839 /* Compute green multiplier (mask) and bit shift */
840 v->gshift = 0;
841 gmask = GET_GREENMASK(v);
842 while ((gmask & 1)==0) {
843 v->gshift++;
844 gmask = gmask >> 1;
845 }
846
847 /* Compute blue multiplier (mask) and bit shift */
848 v->bshift = 0;
849 bmask = GET_BLUEMASK(v);
850 while ((bmask & 1)==0) {
851 v->bshift++;
852 bmask = bmask >> 1;
853 }
854
855 /*
856 * Compute component-to-pixel lookup tables and dithering kernel
857 */
858 {
859 static GLubyte kernel[16] = {
860 0*16, 8*16, 2*16, 10*16,
861 12*16, 4*16, 14*16, 6*16,
862 3*16, 11*16, 1*16, 9*16,
863 15*16, 7*16, 13*16, 5*16,
864 };
865 GLint rBits = _mesa_bitcount(rmask);
866 GLint gBits = _mesa_bitcount(gmask);
867 GLint bBits = _mesa_bitcount(bmask);
868 GLint maxBits;
869 GLuint i;
870
871 /* convert pixel components in [0,_mask] to RGB values in [0,255] */
872 for (i=0; i<=rmask; i++)
873 v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
874 for (i=0; i<=gmask; i++)
875 v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
876 for (i=0; i<=bmask; i++)
877 v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
878
879 /* convert RGB values from [0,255] to pixel components */
880
881 for (i=0;i<256;i++) {
882 GLint r = gamma_adjust(v->RedGamma, i, 255);
883 GLint g = gamma_adjust(v->GreenGamma, i, 255);
884 GLint b = gamma_adjust(v->BlueGamma, i, 255);
885 v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
886 v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
887 v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
888 }
889 /* overflow protection */
890 for (i=256;i<512;i++) {
891 v->RtoPixel[i] = v->RtoPixel[255];
892 v->GtoPixel[i] = v->GtoPixel[255];
893 v->BtoPixel[i] = v->BtoPixel[255];
894 }
895
896 /* setup dithering kernel */
897 maxBits = rBits;
898 if (gBits > maxBits) maxBits = gBits;
899 if (bBits > maxBits) maxBits = bBits;
900 for (i=0;i<16;i++) {
901 v->Kernel[i] = kernel[i] >> maxBits;
902 }
903
904 v->undithered_pf = PF_Truecolor;
905 v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
906 }
907
908 /*
909 * Now check for TrueColor visuals which we can optimize.
910 */
911 if ( GET_REDMASK(v) ==0x0000ff
912 && GET_GREENMASK(v)==0x00ff00
913 && GET_BLUEMASK(v) ==0xff0000
914 && CHECK_BYTE_ORDER(v)
915 && v->BitsPerPixel==32
916 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
917 /* common 32 bpp config used on SGI, Sun */
918 v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */
919 }
920 else if (GET_REDMASK(v) == 0xff0000
921 && GET_GREENMASK(v)== 0x00ff00
922 && GET_BLUEMASK(v) == 0x0000ff
923 && CHECK_BYTE_ORDER(v)
924 && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){
925 if (v->BitsPerPixel==32) {
926 /* if 32 bpp, and visual indicates 8 bpp alpha channel */
927 if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8)
928 v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */
929 else
930 v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */
931 }
932 else if (v->BitsPerPixel == 24) {
933 v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */
934 }
935 }
936 else if (GET_REDMASK(v) ==0xf800
937 && GET_GREENMASK(v)==0x07e0
938 && GET_BLUEMASK(v) ==0x001f
939 && CHECK_BYTE_ORDER(v)
940 && v->BitsPerPixel==16
941 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
942 /* 5-6-5 RGB */
943 v->undithered_pf = PF_5R6G5B;
944 v->dithered_pf = PF_Dither_5R6G5B;
945 }
946 }
947
948
949
950 /**
951 * Setup RGB rendering for a window with a monochrome visual.
952 */
953 static void
954 setup_monochrome( XMesaVisual v, XMesaBuffer b )
955 {
956 (void) b;
957 v->dithered_pf = v->undithered_pf = PF_1Bit;
958 /* if black=1 then we must flip pixel values */
959 v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
960 }
961
962
963
964 /**
965 * When a context is bound for the first time, we can finally finish
966 * initializing the context's visual and buffer information.
967 * \param v the XMesaVisual to initialize
968 * \param b the XMesaBuffer to initialize (may be NULL)
969 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode
970 * \param window the window/pixmap we're rendering into
971 * \param cmap the colormap associated with the window/pixmap
972 * \return GL_TRUE=success, GL_FALSE=failure
973 */
974 static GLboolean
975 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
976 GLboolean rgb_flag, XMesaDrawable window,
977 XMesaColormap cmap)
978 {
979 int client = 0;
980
981 #ifdef XFree86Server
982 client = (window) ? CLIENT_ID(window->id) : 0;
983 #endif
984
985 ASSERT(!b || b->xm_visual == v);
986
987 /* Save true bits/pixel */
988 v->BitsPerPixel = bits_per_pixel(v);
989 assert(v->BitsPerPixel > 0);
990
991 if (rgb_flag == GL_FALSE) {
992 /* COLOR-INDEXED WINDOW:
993 * Even if the visual is TrueColor or DirectColor we treat it as
994 * being color indexed. This is weird but might be useful to someone.
995 */
996 v->dithered_pf = v->undithered_pf = PF_Index;
997 v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
998 }
999 else {
1000 /* RGB WINDOW:
1001 * We support RGB rendering into almost any kind of visual.
1002 */
1003 const int xclass = v->mesa_visual.visualType;
1004 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
1005 setup_truecolor( v, b, cmap );
1006 }
1007 else if (xclass == GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v) == 1) {
1008 setup_monochrome( v, b );
1009 }
1010 else if (xclass == GLX_GRAY_SCALE || xclass == GLX_STATIC_GRAY) {
1011 if (!setup_grayscale( client, v, b, cmap )) {
1012 return GL_FALSE;
1013 }
1014 }
1015 else if ((xclass == GLX_PSEUDO_COLOR || xclass == GLX_STATIC_COLOR)
1016 && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
1017 if (!setup_dithered_color( client, v, b, cmap )) {
1018 return GL_FALSE;
1019 }
1020 }
1021 else {
1022 _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n");
1023 return GL_FALSE;
1024 }
1025 v->mesa_visual.indexBits = 0;
1026
1027 if (_mesa_getenv("MESA_NO_DITHER")) {
1028 v->dithered_pf = v->undithered_pf;
1029 }
1030 }
1031
1032
1033 /*
1034 * If MESA_INFO env var is set print out some debugging info
1035 * which can help Brian figure out what's going on when a user
1036 * reports bugs.
1037 */
1038 if (_mesa_getenv("MESA_INFO")) {
1039 _mesa_printf("X/Mesa visual = %p\n", (void *) v);
1040 _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
1041 _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
1042 _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
1043 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
1044 _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
1045 }
1046
1047 if (b && window) {
1048 char *data;
1049
1050 /* Do window-specific initializations */
1051
1052 /* these should have been set in create_xmesa_buffer */
1053 ASSERT(b->frontxrb->drawable == window);
1054 ASSERT(b->frontxrb->pixmap == (XMesaPixmap) window);
1055
1056 /* Setup for single/double buffering */
1057 if (v->mesa_visual.doubleBufferMode) {
1058 /* Double buffered */
1059 b->shm = check_for_xshm( v->display );
1060 }
1061
1062 /* X11 graphics contexts */
1063 #ifdef XFree86Server
1064 b->gc = CreateScratchGC(v->display, window->depth);
1065 #else
1066 b->gc = XCreateGC( v->display, window, 0, NULL );
1067 #endif
1068 XMesaSetFunction( v->display, b->gc, GXcopy );
1069
1070 /* cleargc - for glClear() */
1071 #ifdef XFree86Server
1072 b->cleargc = CreateScratchGC(v->display, window->depth);
1073 #else
1074 b->cleargc = XCreateGC( v->display, window, 0, NULL );
1075 #endif
1076 XMesaSetFunction( v->display, b->cleargc, GXcopy );
1077
1078 /*
1079 * Don't generate Graphics Expose/NoExpose events in swapbuffers().
1080 * Patch contributed by Michael Pichler May 15, 1995.
1081 */
1082 #ifdef XFree86Server
1083 b->swapgc = CreateScratchGC(v->display, window->depth);
1084 {
1085 CARD32 v[1];
1086 v[0] = FALSE;
1087 dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
1088 }
1089 #else
1090 {
1091 XGCValues gcvalues;
1092 gcvalues.graphics_exposures = False;
1093 b->swapgc = XCreateGC(v->display, window,
1094 GCGraphicsExposures, &gcvalues);
1095 }
1096 #endif
1097 XMesaSetFunction( v->display, b->swapgc, GXcopy );
1098
1099 /* Initialize the row buffer XImage for use in write_color_span() */
1100 data = (char*) MALLOC(MAX_WIDTH*4);
1101 #ifdef XFree86Server
1102 b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, data);
1103 #else
1104 b->rowimage = XCreateImage( v->display,
1105 v->visinfo->visual,
1106 v->visinfo->depth,
1107 ZPixmap, 0, /*format, offset*/
1108 data, /*data*/
1109 MAX_WIDTH, 1, /*width, height*/
1110 32, /*bitmap_pad*/
1111 0 /*bytes_per_line*/ );
1112 #endif
1113 if (!b->rowimage)
1114 return GL_FALSE;
1115 }
1116
1117 return GL_TRUE;
1118 }
1119
1120
1121
1122 /*
1123 * Convert an RGBA color to a pixel value.
1124 */
1125 unsigned long
1126 xmesa_color_to_pixel(XMesaContext xmesa,
1127 GLubyte r, GLubyte g, GLubyte b, GLubyte a,
1128 GLuint pixelFormat)
1129 {
1130 GLcontext *ctx = xmesa->st->ctx;
1131
1132 switch (pixelFormat) {
1133 case PF_Index:
1134 return 0;
1135 case PF_Truecolor:
1136 {
1137 unsigned long p;
1138 PACK_TRUECOLOR( p, r, g, b );
1139 return p;
1140 }
1141 case PF_8A8B8G8R:
1142 return PACK_8A8B8G8R( r, g, b, a );
1143 case PF_8A8R8G8B:
1144 return PACK_8A8R8G8B( r, g, b, a );
1145 case PF_8R8G8B:
1146 /* fall through */
1147 case PF_8R8G8B24:
1148 return PACK_8R8G8B( r, g, b );
1149 case PF_5R6G5B:
1150 return PACK_5R6G5B( r, g, b );
1151 case PF_Dither:
1152 {
1153 DITHER_SETUP;
1154 return DITHER( 1, 0, r, g, b );
1155 }
1156 case PF_1Bit:
1157 /* 382 = (3*255)/2 */
1158 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
1159 case PF_Lookup:
1160 {
1161 LOOKUP_SETUP;
1162 return LOOKUP( r, g, b );
1163 }
1164 case PF_Grayscale:
1165 return GRAY_RGB( r, g, b );
1166 case PF_Dither_True:
1167 /* fall through */
1168 case PF_Dither_5R6G5B:
1169 {
1170 unsigned long p;
1171 PACK_TRUEDITHER(p, 1, 0, r, g, b);
1172 return p;
1173 }
1174 default:
1175 _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
1176 }
1177 return 0;
1178 }
1179
1180
1181 #define NUM_VISUAL_TYPES 6
1182
1183 /**
1184 * Convert an X visual type to a GLX visual type.
1185 *
1186 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
1187 * to be converted.
1188 * \return If \c visualType is a valid X visual type, a GLX visual type will
1189 * be returned. Otherwise \c GLX_NONE will be returned.
1190 *
1191 * \note
1192 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
1193 * DRI CVS tree.
1194 */
1195 static GLint
1196 xmesa_convert_from_x_visual_type( int visualType )
1197 {
1198 static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
1199 GLX_STATIC_GRAY, GLX_GRAY_SCALE,
1200 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
1201 GLX_TRUE_COLOR, GLX_DIRECT_COLOR
1202 };
1203
1204 return ( (unsigned) visualType < NUM_VISUAL_TYPES )
1205 ? glx_visual_types[ visualType ] : GLX_NONE;
1206 }
1207
1208
1209 /**********************************************************************/
1210 /***** Public Functions *****/
1211 /**********************************************************************/
1212
1213
1214 /*
1215 * Create a new X/Mesa visual.
1216 * Input: display - X11 display
1217 * visinfo - an XVisualInfo pointer
1218 * rgb_flag - GL_TRUE = RGB mode,
1219 * GL_FALSE = color index mode
1220 * alpha_flag - alpha buffer requested?
1221 * db_flag - GL_TRUE = double-buffered,
1222 * GL_FALSE = single buffered
1223 * stereo_flag - stereo visual?
1224 * ximage_flag - GL_TRUE = use an XImage for back buffer,
1225 * GL_FALSE = use an off-screen pixmap for back buffer
1226 * depth_size - requested bits/depth values, or zero
1227 * stencil_size - requested bits/stencil values, or zero
1228 * accum_red_size - requested bits/red accum values, or zero
1229 * accum_green_size - requested bits/green accum values, or zero
1230 * accum_blue_size - requested bits/blue accum values, or zero
1231 * accum_alpha_size - requested bits/alpha accum values, or zero
1232 * num_samples - number of samples/pixel if multisampling, or zero
1233 * level - visual level, usually 0
1234 * visualCaveat - ala the GLX extension, usually GLX_NONE
1235 * Return; a new XMesaVisual or 0 if error.
1236 */
1237 PUBLIC
1238 XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
1239 XMesaVisualInfo visinfo,
1240 GLboolean rgb_flag,
1241 GLboolean alpha_flag,
1242 GLboolean db_flag,
1243 GLboolean stereo_flag,
1244 GLboolean ximage_flag,
1245 GLint depth_size,
1246 GLint stencil_size,
1247 GLint accum_red_size,
1248 GLint accum_green_size,
1249 GLint accum_blue_size,
1250 GLint accum_alpha_size,
1251 GLint num_samples,
1252 GLint level,
1253 GLint visualCaveat )
1254 {
1255 char *gamma;
1256 XMesaVisual v;
1257 GLint red_bits, green_bits, blue_bits, alpha_bits;
1258
1259 #ifndef XFree86Server
1260 /* For debugging only */
1261 if (_mesa_getenv("MESA_XSYNC")) {
1262 /* This makes debugging X easier.
1263 * In your debugger, set a breakpoint on _XError to stop when an
1264 * X protocol error is generated.
1265 */
1266 XSynchronize( display, 1 );
1267 }
1268 #endif
1269
1270 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
1271 if (!v) {
1272 return NULL;
1273 }
1274
1275 v->display = display;
1276
1277 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
1278 * the struct but we may need some of the information contained in it
1279 * at a later time.
1280 */
1281 #ifndef XFree86Server
1282 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
1283 if(!v->visinfo) {
1284 _mesa_free(v);
1285 return NULL;
1286 }
1287 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
1288 #endif
1289
1290 /* check for MESA_GAMMA environment variable */
1291 gamma = _mesa_getenv("MESA_GAMMA");
1292 if (gamma) {
1293 v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
1294 sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
1295 if (v->RedGamma<=0.0) v->RedGamma = 1.0;
1296 if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma;
1297 if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma;
1298 }
1299 else {
1300 v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
1301 }
1302
1303 v->ximage_flag = ximage_flag;
1304
1305 #ifdef XFree86Server
1306 /* We could calculate these values by ourselves. nplanes is either the sum
1307 * of the red, green, and blue bits or the number index bits.
1308 * ColormapEntries is either (1U << index_bits) or
1309 * (1U << max(redBits, greenBits, blueBits)).
1310 */
1311 assert(visinfo->nplanes > 0);
1312 v->nplanes = visinfo->nplanes;
1313 v->ColormapEntries = visinfo->ColormapEntries;
1314
1315 v->mesa_visual.redMask = visinfo->redMask;
1316 v->mesa_visual.greenMask = visinfo->greenMask;
1317 v->mesa_visual.blueMask = visinfo->blueMask;
1318 v->mesa_visual.visualID = visinfo->vid;
1319 v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
1320 #else
1321 v->mesa_visual.redMask = visinfo->red_mask;
1322 v->mesa_visual.greenMask = visinfo->green_mask;
1323 v->mesa_visual.blueMask = visinfo->blue_mask;
1324 v->mesa_visual.visualID = visinfo->visualid;
1325 v->mesa_visual.screen = visinfo->screen;
1326 #endif
1327
1328 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
1329 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
1330 #else
1331 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
1332 #endif
1333
1334 v->mesa_visual.visualRating = visualCaveat;
1335
1336 if (alpha_flag)
1337 v->mesa_visual.alphaBits = 8;
1338
1339 (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
1340
1341 {
1342 const int xclass = v->mesa_visual.visualType;
1343 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
1344 red_bits = _mesa_bitcount(GET_REDMASK(v));
1345 green_bits = _mesa_bitcount(GET_GREENMASK(v));
1346 blue_bits = _mesa_bitcount(GET_BLUEMASK(v));
1347 }
1348 else {
1349 /* this is an approximation */
1350 int depth;
1351 depth = GET_VISUAL_DEPTH(v);
1352 red_bits = depth / 3;
1353 depth -= red_bits;
1354 green_bits = depth / 2;
1355 depth -= green_bits;
1356 blue_bits = depth;
1357 alpha_bits = 0;
1358 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
1359 }
1360 alpha_bits = v->mesa_visual.alphaBits;
1361 }
1362
1363 _mesa_initialize_visual( &v->mesa_visual,
1364 rgb_flag, db_flag, stereo_flag,
1365 red_bits, green_bits,
1366 blue_bits, alpha_bits,
1367 v->mesa_visual.indexBits,
1368 depth_size,
1369 stencil_size,
1370 accum_red_size, accum_green_size,
1371 accum_blue_size, accum_alpha_size,
1372 0 );
1373
1374 /* XXX minor hack */
1375 v->mesa_visual.level = level;
1376 return v;
1377 }
1378
1379
1380 PUBLIC
1381 void XMesaDestroyVisual( XMesaVisual v )
1382 {
1383 #ifndef XFree86Server
1384 _mesa_free(v->visinfo);
1385 #endif
1386 _mesa_free(v);
1387 }
1388
1389
1390
1391 static void
1392 finish_or_flush( GLcontext *ctx )
1393 {
1394 #ifdef XFree86Server
1395 /* NOT_NEEDED */
1396 #else
1397 const XMesaContext xmesa = XMESA_CONTEXT(ctx);
1398 ctx->st->pipe->flush(ctx->st->pipe, 0);
1399 if (xmesa) {
1400 _glthread_LOCK_MUTEX(_xmesa_lock);
1401 XSync( xmesa->display, False );
1402 _glthread_UNLOCK_MUTEX(_xmesa_lock);
1403 }
1404 #endif
1405 }
1406
1407
1408 /**
1409 * Called by glViewport.
1410 * This is a good time for us to poll the current X window size and adjust
1411 * our renderbuffers to match the current window size.
1412 * Remember, we have no opportunity to respond to conventional
1413 * X Resize/StructureNotify events since the X driver has no event loop.
1414 * Thus, we poll.
1415 * Note that this trick isn't fool-proof. If the application never calls
1416 * glViewport, our notion of the current window size may be incorrect.
1417 * That problem led to the GLX_MESA_resize_buffers extension.
1418 */
1419 static void
1420 xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
1421 {
1422 XMesaContext xmctx = XMESA_CONTEXT(ctx);
1423 XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
1424 XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
1425 xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
1426 xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
1427 (void) x;
1428 (void) y;
1429 (void) w;
1430 (void) h;
1431 }
1432
1433
1434 /**
1435 * Initialize the device driver function table with the functions
1436 * we implement in this driver.
1437 */
1438 static void
1439 xmesa_init_driver_functions(struct dd_function_table *driver)
1440 {
1441 #if 0 /* not needed for now */
1442 driver->Flush = finish_or_flush;
1443 driver->Finish = finish_or_flush;
1444 #else
1445 (void) finish_or_flush;
1446 #endif
1447 driver->Viewport = xmesa_viewport;
1448 }
1449
1450
1451 /**
1452 * Create a new XMesaContext.
1453 * \param v the XMesaVisual
1454 * \param share_list another XMesaContext with which to share display
1455 * lists or NULL if no sharing is wanted.
1456 * \return an XMesaContext or NULL if error.
1457 */
1458 PUBLIC
1459 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
1460 {
1461 static GLboolean firstTime = GL_TRUE;
1462 struct pipe_context *pipe;
1463 XMesaContext c;
1464 GLcontext *mesaCtx;
1465
1466 if (firstTime) {
1467 _glthread_INIT_MUTEX(_xmesa_lock);
1468 firstTime = GL_FALSE;
1469 }
1470
1471 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
1472 c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
1473 if (!c)
1474 return NULL;
1475
1476 pipe = xmesa_create_context( c );
1477
1478 c->st = st_create_context(pipe, &v->mesa_visual,
1479 share_list ? share_list->st : NULL);
1480 mesaCtx = c->st->ctx;
1481 c->st->ctx->DriverCtx = c;
1482
1483 #if 00
1484 _mesa_enable_sw_extensions(mesaCtx);
1485 _mesa_enable_1_3_extensions(mesaCtx);
1486 _mesa_enable_1_4_extensions(mesaCtx);
1487 _mesa_enable_1_5_extensions(mesaCtx);
1488 _mesa_enable_2_0_extensions(mesaCtx);
1489 #endif
1490
1491 #ifdef XFree86Server
1492 /* If we're running in the X server, do bounds checking to prevent
1493 * segfaults and server crashes!
1494 */
1495 mesaCtx->Const.CheckArrayBounds = GL_TRUE;
1496 #endif
1497
1498 xmesa_init_driver_functions(&mesaCtx->Driver);
1499
1500 /* finish up xmesa context initializations */
1501 c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
1502 c->xm_visual = v;
1503 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
1504 c->display = v->display;
1505 c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */
1506
1507 /* override these functions, as if the xlib driver were derived from
1508 * the softpipe driver.
1509 */
1510 pipe->get_tile = xmesa_get_tile;
1511 pipe->put_tile = xmesa_put_tile;
1512 pipe->get_tile_rgba = xmesa_get_tile_rgba;
1513 pipe->put_tile_rgba = xmesa_put_tile_rgba;
1514
1515 c->st->haveFramebufferRegions = GL_FALSE;
1516
1517 /* special pipe->clear function */
1518 pipe->clear = xmesa_clear;
1519
1520 return c;
1521 }
1522
1523
1524
1525 PUBLIC
1526 void XMesaDestroyContext( XMesaContext c )
1527 {
1528 st_destroy_context(c->st);
1529 _mesa_free(c);
1530 }
1531
1532
1533
1534 /**
1535 * Private function for creating an XMesaBuffer which corresponds to an
1536 * X window or pixmap.
1537 * \param v the window's XMesaVisual
1538 * \param w the window we're wrapping
1539 * \return new XMesaBuffer or NULL if error
1540 */
1541 PUBLIC XMesaBuffer
1542 XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1543 {
1544 #ifndef XFree86Server
1545 XWindowAttributes attr;
1546 #endif
1547 XMesaBuffer b;
1548 XMesaColormap cmap;
1549 int depth;
1550
1551 assert(v);
1552 assert(w);
1553
1554 /* Check that window depth matches visual depth */
1555 #ifdef XFree86Server
1556 depth = ((XMesaDrawable)w)->depth;
1557 #else
1558 XGetWindowAttributes( v->display, w, &attr );
1559 depth = attr.depth;
1560 #endif
1561 if (GET_VISUAL_DEPTH(v) != depth) {
1562 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1563 GET_VISUAL_DEPTH(v), depth);
1564 return NULL;
1565 }
1566
1567 /* Find colormap */
1568 #ifdef XFree86Server
1569 cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1570 #else
1571 if (attr.colormap) {
1572 cmap = attr.colormap;
1573 }
1574 else {
1575 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1576 /* this is weird, a window w/out a colormap!? */
1577 /* OK, let's just allocate a new one and hope for the best */
1578 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1579 }
1580 #endif
1581
1582 b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
1583 if (!b)
1584 return NULL;
1585
1586 if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
1587 (XMesaDrawable) w, cmap )) {
1588 xmesa_free_buffer(b);
1589 return NULL;
1590 }
1591
1592 return b;
1593 }
1594
1595
1596
1597 /**
1598 * Create a new XMesaBuffer from an X pixmap.
1599 *
1600 * \param v the XMesaVisual
1601 * \param p the pixmap
1602 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1603 * \c GLX_DIRECT_COLOR visual for the pixmap
1604 * \returns new XMesaBuffer or NULL if error
1605 */
1606 PUBLIC XMesaBuffer
1607 XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1608 {
1609 XMesaBuffer b;
1610
1611 assert(v);
1612
1613 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1614 if (!b)
1615 return NULL;
1616
1617 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1618 (XMesaDrawable) p, cmap)) {
1619 xmesa_free_buffer(b);
1620 return NULL;
1621 }
1622
1623 return b;
1624 }
1625
1626
1627 /**
1628 * For GLX_EXT_texture_from_pixmap
1629 */
1630 XMesaBuffer
1631 XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
1632 XMesaColormap cmap,
1633 int format, int target, int mipmap)
1634 {
1635 GET_CURRENT_CONTEXT(ctx);
1636 XMesaBuffer b;
1637 GLuint width, height;
1638
1639 assert(v);
1640
1641 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1642 if (!b)
1643 return NULL;
1644
1645 /* get pixmap size, update framebuffer/renderbuffer dims */
1646 xmesa_get_window_size(v->display, b, &width, &height);
1647 _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
1648
1649 if (target == 0) {
1650 /* examine dims */
1651 if (ctx->Extensions.ARB_texture_non_power_of_two) {
1652 target = GLX_TEXTURE_2D_EXT;
1653 }
1654 else if ( _mesa_bitcount(width) == 1
1655 && _mesa_bitcount(height) == 1) {
1656 /* power of two size */
1657 if (height == 1) {
1658 target = GLX_TEXTURE_1D_EXT;
1659 }
1660 else {
1661 target = GLX_TEXTURE_2D_EXT;
1662 }
1663 }
1664 else if (ctx->Extensions.NV_texture_rectangle) {
1665 target = GLX_TEXTURE_RECTANGLE_EXT;
1666 }
1667 else {
1668 /* non power of two textures not supported */
1669 XMesaDestroyBuffer(b);
1670 return 0;
1671 }
1672 }
1673
1674 b->TextureTarget = target;
1675 b->TextureFormat = format;
1676 b->TextureMipmap = mipmap;
1677
1678 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1679 (XMesaDrawable) p, cmap)) {
1680 xmesa_free_buffer(b);
1681 return NULL;
1682 }
1683
1684 return b;
1685 }
1686
1687
1688
1689 XMesaBuffer
1690 XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1691 unsigned int width, unsigned int height)
1692 {
1693 #ifndef XFree86Server
1694 XMesaWindow root;
1695 XMesaDrawable drawable; /* X Pixmap Drawable */
1696 XMesaBuffer b;
1697
1698 /* allocate pixmap for front buffer */
1699 root = RootWindow( v->display, v->visinfo->screen );
1700 drawable = XCreatePixmap(v->display, root, width, height,
1701 v->visinfo->depth);
1702 if (!drawable)
1703 return NULL;
1704
1705 b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1706 if (!b)
1707 return NULL;
1708
1709 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1710 drawable, cmap)) {
1711 xmesa_free_buffer(b);
1712 return NULL;
1713 }
1714
1715 return b;
1716 #else
1717 return 0;
1718 #endif
1719 }
1720
1721
1722
1723 /*
1724 * Deallocate an XMesaBuffer structure and all related info.
1725 */
1726 PUBLIC void
1727 XMesaDestroyBuffer(XMesaBuffer b)
1728 {
1729 xmesa_free_buffer(b);
1730 }
1731
1732
1733 /**
1734 * Query the current window size and update the corresponding GLframebuffer
1735 * and all attached renderbuffers.
1736 * Called when:
1737 * 1. the first time a buffer is bound to a context.
1738 * 2. from glViewport to poll for window size changes
1739 * 3. from the XMesaResizeBuffers() API function.
1740 * Note: it's possible (and legal) for xmctx to be NULL. That can happen
1741 * when resizing a buffer when no rendering context is bound.
1742 */
1743 void
1744 xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1745 {
1746 GLuint width, height;
1747 xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height);
1748 st_resize_framebuffer(drawBuffer->stfb, width, height);
1749 }
1750
1751
1752 /*
1753 * Bind buffer b to context c and make c the current rendering context.
1754 */
1755 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1756 {
1757 return XMesaMakeCurrent2( c, b, b );
1758 }
1759
1760
1761 /*
1762 * Bind buffer b to context c and make c the current rendering context.
1763 */
1764 PUBLIC
1765 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1766 XMesaBuffer readBuffer )
1767 {
1768 if (c) {
1769 if (!drawBuffer || !readBuffer)
1770 return GL_FALSE; /* must specify buffers! */
1771
1772 #if 0
1773 /* XXX restore this optimization */
1774 if (&(c->mesa) == _mesa_get_current_context()
1775 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1776 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
1777 && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
1778 /* same context and buffer, do nothing */
1779 return GL_TRUE;
1780 }
1781 #endif
1782
1783 c->xm_buffer = drawBuffer;
1784
1785 /* Call this periodically to detect when the user has begun using
1786 * GL rendering from multiple threads.
1787 */
1788 _glapi_check_multithread();
1789
1790 xmesa_check_and_update_buffer_size(c, drawBuffer);
1791 if (readBuffer != drawBuffer)
1792 xmesa_check_and_update_buffer_size(c, readBuffer);
1793
1794 st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
1795
1796 #if 0
1797 if (c->xm_visual->mesa_visual.rgbMode) {
1798 /*
1799 * Must recompute and set these pixel values because colormap
1800 * can be different for different windows.
1801 */
1802 c->clearpixel = xmesa_color_to_pixel( c,
1803 c->clearcolor[0],
1804 c->clearcolor[1],
1805 c->clearcolor[2],
1806 c->clearcolor[3],
1807 c->xm_visual->undithered_pf);
1808 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
1809 }
1810 #endif
1811
1812 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1813 drawBuffer->wasCurrent = GL_TRUE;
1814 }
1815 else {
1816 /* Detach */
1817 st_make_current( NULL, NULL, NULL );
1818 }
1819 return GL_TRUE;
1820 }
1821
1822
1823 /*
1824 * Unbind the context c from its buffer.
1825 */
1826 GLboolean XMesaUnbindContext( XMesaContext c )
1827 {
1828 /* A no-op for XFree86 integration purposes */
1829 return GL_TRUE;
1830 }
1831
1832
1833 XMesaContext XMesaGetCurrentContext( void )
1834 {
1835 GET_CURRENT_CONTEXT(ctx);
1836 if (ctx) {
1837 XMesaContext xmesa = XMESA_CONTEXT(ctx);
1838 return xmesa;
1839 }
1840 else {
1841 return 0;
1842 }
1843 }
1844
1845
1846 XMesaBuffer XMesaGetCurrentBuffer( void )
1847 {
1848 GET_CURRENT_CONTEXT(ctx);
1849 if (ctx) {
1850 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
1851 return xmbuf;
1852 }
1853 else {
1854 return 0;
1855 }
1856 }
1857
1858
1859 /* New in Mesa 3.1 */
1860 XMesaBuffer XMesaGetCurrentReadBuffer( void )
1861 {
1862 GET_CURRENT_CONTEXT(ctx);
1863 if (ctx) {
1864 return XMESA_BUFFER(ctx->ReadBuffer);
1865 }
1866 else {
1867 return 0;
1868 }
1869 }
1870
1871
1872 #ifdef XFree86Server
1873 PUBLIC
1874 GLboolean XMesaForceCurrent(XMesaContext c)
1875 {
1876 if (c) {
1877 _glapi_set_dispatch(c->mesa.CurrentDispatch);
1878
1879 if (&(c->mesa) != _mesa_get_current_context()) {
1880 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
1881 }
1882 }
1883 else {
1884 _mesa_make_current(NULL, NULL, NULL);
1885 }
1886 return GL_TRUE;
1887 }
1888
1889
1890 PUBLIC
1891 GLboolean XMesaLoseCurrent(XMesaContext c)
1892 {
1893 (void) c;
1894 _mesa_make_current(NULL, NULL, NULL);
1895 return GL_TRUE;
1896 }
1897
1898
1899 PUBLIC
1900 GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask )
1901 {
1902 _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
1903 return GL_TRUE;
1904 }
1905 #endif /* XFree86Server */
1906
1907
1908 #ifndef FX
1909 GLboolean XMesaSetFXmode( GLint mode )
1910 {
1911 (void) mode;
1912 return GL_FALSE;
1913 }
1914 #endif
1915
1916
1917
1918 /*
1919 * Copy the back buffer to the front buffer. If there's no back buffer
1920 * this is a no-op.
1921 */
1922 PUBLIC
1923 void XMesaSwapBuffers( XMesaBuffer b )
1924 {
1925 if (!b->backxrb) {
1926 /* single buffered */
1927 return;
1928 }
1929
1930 /* If we're swapping the buffer associated with the current context
1931 * we have to flush any pending rendering commands first.
1932 */
1933 st_notify_swapbuffers(b->stfb);
1934
1935 if (b->db_mode) {
1936 if (b->backxrb->ximage) {
1937 /* Copy Ximage (back buf) from client memory to server window */
1938 #if defined(USE_XSHM) && !defined(XFree86Server)
1939 if (b->shm) {
1940 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1941 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
1942 b->swapgc,
1943 b->backxrb->ximage, 0, 0,
1944 0, 0, xmesa_buffer_width(b), xmesa_buffer_height(b),
1945 False );
1946 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1947 }
1948 else
1949 #endif
1950 {
1951 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1952 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
1953 b->swapgc,
1954 b->backxrb->ximage, 0, 0,
1955 0, 0,
1956 xmesa_buffer_width(b), xmesa_buffer_height(b));
1957 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1958 }
1959 }
1960 else if (b->backxrb->pixmap) {
1961 /* Copy pixmap (back buf) to window (front buf) on server */
1962 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
1963 XMesaCopyArea( b->xm_visual->display,
1964 b->backxrb->pixmap, /* source drawable */
1965 b->frontxrb->drawable, /* dest. drawable */
1966 b->swapgc,
1967 0, 0, xmesa_buffer_width(b), xmesa_buffer_height(b),
1968 0, 0 /* dest region */
1969 );
1970 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
1971 }
1972
1973 if (b->swAlpha) {
1974 GET_CURRENT_CONTEXT(ctx);
1975 _mesa_copy_soft_alpha_renderbuffers(ctx, &b->stfb->Base);
1976 }
1977 }
1978 #if !defined(XFree86Server)
1979 XSync( b->xm_visual->display, False );
1980 #endif
1981 }
1982
1983
1984
1985 /*
1986 * Copy sub-region of back buffer to front buffer
1987 */
1988 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1989 {
1990 if (!b->backxrb) {
1991 /* single buffered */
1992 return;
1993 }
1994
1995 /* If we're swapping the buffer associated with the current context
1996 * we have to flush any pending rendering commands first.
1997 */
1998 st_notify_swapbuffers(b->stfb);
1999
2000 if (b->db_mode) {
2001 int yTop = xmesa_buffer_height(b) - y - height;
2002 if (b->backxrb->ximage) {
2003 /* Copy Ximage from host's memory to server's window */
2004 #if defined(USE_XSHM) && !defined(XFree86Server)
2005 if (b->shm) {
2006 /* XXX assuming width and height aren't too large! */
2007 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2008 b->swapgc,
2009 b->backxrb->ximage, x, yTop,
2010 x, yTop, width, height, False );
2011 /* wait for finished event??? */
2012 }
2013 else
2014 #endif
2015 {
2016 /* XXX assuming width and height aren't too large! */
2017 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2018 b->swapgc,
2019 b->backxrb->ximage, x, yTop,
2020 x, yTop, width, height );
2021 }
2022 }
2023 else {
2024 /* Copy pixmap to window on server */
2025 XMesaCopyArea( b->xm_visual->display,
2026 b->backxrb->pixmap, /* source drawable */
2027 b->frontxrb->drawable, /* dest. drawable */
2028 b->swapgc,
2029 x, yTop, width, height, /* source region */
2030 x, yTop /* dest region */
2031 );
2032 }
2033 }
2034 }
2035
2036
2037 /*
2038 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2039 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2040 * back buffer directly.
2041 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2042 * ximage - pointer to back buffer's XImage, or NULL
2043 * Return: GL_TRUE = context is double buffered
2044 * GL_FALSE = context is single buffered
2045 */
2046 #ifndef XFree86Server
2047 GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2048 XMesaPixmap *pixmap,
2049 XMesaImage **ximage )
2050 {
2051 if (b->db_mode) {
2052 if (pixmap)
2053 *pixmap = b->backxrb->pixmap;
2054 if (ximage)
2055 *ximage = b->backxrb->ximage;
2056 return GL_TRUE;
2057 }
2058 else {
2059 *pixmap = 0;
2060 *ximage = NULL;
2061 return GL_FALSE;
2062 }
2063 }
2064 #endif /* XFree86Server */
2065
2066
2067 /*
2068 * Return the depth buffer associated with an XMesaBuffer.
2069 * Input: b - the XMesa buffer handle
2070 * Output: width, height - size of buffer in pixels
2071 * bytesPerValue - bytes per depth value (2 or 4)
2072 * buffer - pointer to depth buffer values
2073 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2074 */
2075 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2076 GLint *bytesPerValue, void **buffer )
2077 {
2078 struct gl_renderbuffer *rb
2079 = b->stfb->Base.Attachment[BUFFER_DEPTH].Renderbuffer;
2080 if (!rb || !rb->Data) {
2081 *width = 0;
2082 *height = 0;
2083 *bytesPerValue = 0;
2084 *buffer = 0;
2085 return GL_FALSE;
2086 }
2087 else {
2088 *width = xmesa_buffer_width(b);
2089 *height = xmesa_buffer_height(b);
2090 *bytesPerValue = b->stfb->Base.Visual.depthBits <= 16
2091 ? sizeof(GLushort) : sizeof(GLuint);
2092 *buffer = rb->Data;
2093 return GL_TRUE;
2094 }
2095 }
2096
2097
2098 void XMesaFlush( XMesaContext c )
2099 {
2100 if (c && c->display) {
2101 #ifdef XFree86Server
2102 /* NOT_NEEDED */
2103 #else
2104 XSync( c->display, False );
2105 #endif
2106 }
2107 }
2108
2109
2110
2111 const char *XMesaGetString( XMesaContext c, int name )
2112 {
2113 (void) c;
2114 if (name==XMESA_VERSION) {
2115 return "5.0";
2116 }
2117 else if (name==XMESA_EXTENSIONS) {
2118 return "";
2119 }
2120 else {
2121 return NULL;
2122 }
2123 }
2124
2125
2126
2127 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2128 {
2129 XMesaBuffer b;
2130 for (b=XMesaBufferList; b; b=b->Next) {
2131 if (b->frontxrb->drawable == d && b->display == dpy) {
2132 return b;
2133 }
2134 }
2135 return NULL;
2136 }
2137
2138
2139 /**
2140 * Free/destroy all XMesaBuffers associated with given display.
2141 */
2142 void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
2143 {
2144 XMesaBuffer b, next;
2145 for (b = XMesaBufferList; b; b = next) {
2146 next = b->Next;
2147 if (b->display == dpy) {
2148 xmesa_free_buffer(b);
2149 }
2150 }
2151 }
2152
2153
2154 /*
2155 * Look for XMesaBuffers whose X window has been destroyed.
2156 * Deallocate any such XMesaBuffers.
2157 */
2158 void XMesaGarbageCollect( void )
2159 {
2160 XMesaBuffer b, next;
2161 for (b=XMesaBufferList; b; b=next) {
2162 next = b->Next;
2163 if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2164 #ifdef XFree86Server
2165 /* NOT_NEEDED */
2166 #else
2167 XSync(b->display, False);
2168 if (!window_exists( b->display, b->frontxrb->drawable )) {
2169 /* found a dead window, free the ancillary info */
2170 XMesaDestroyBuffer( b );
2171 }
2172 #endif
2173 }
2174 }
2175 }
2176
2177
2178 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2179 GLfloat red, GLfloat green,
2180 GLfloat blue, GLfloat alpha )
2181 {
2182 GLcontext *ctx = xmesa->st->ctx;
2183 GLint r = (GLint) (red * 255.0F);
2184 GLint g = (GLint) (green * 255.0F);
2185 GLint b = (GLint) (blue * 255.0F);
2186 GLint a = (GLint) (alpha * 255.0F);
2187
2188 switch (xmesa->pixelformat) {
2189 case PF_Index:
2190 return 0;
2191 case PF_Truecolor:
2192 {
2193 unsigned long p;
2194 PACK_TRUECOLOR( p, r, g, b );
2195 return p;
2196 }
2197 case PF_8A8B8G8R:
2198 return PACK_8A8B8G8R( r, g, b, a );
2199 case PF_8A8R8G8B:
2200 return PACK_8A8R8G8B( r, g, b, a );
2201 case PF_8R8G8B:
2202 return PACK_8R8G8B( r, g, b );
2203 case PF_5R6G5B:
2204 return PACK_5R6G5B( r, g, b );
2205 case PF_Dither:
2206 {
2207 DITHER_SETUP;
2208 return DITHER( x, y, r, g, b );
2209 }
2210 case PF_1Bit:
2211 /* 382 = (3*255)/2 */
2212 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2213 case PF_Lookup:
2214 {
2215 LOOKUP_SETUP;
2216 return LOOKUP( r, g, b );
2217 }
2218 case PF_Grayscale:
2219 return GRAY_RGB( r, g, b );
2220 case PF_Dither_5R6G5B:
2221 /* fall through */
2222 case PF_Dither_True:
2223 {
2224 unsigned long p;
2225 PACK_TRUEDITHER(p, x, y, r, g, b);
2226 return p;
2227 }
2228 default:
2229 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2230 }
2231 return 0;
2232 }
2233
2234
2235 /*
2236 * This is typically called when the window size changes and we need
2237 * to reallocate the buffer's back/depth/stencil/accum buffers.
2238 */
2239 PUBLIC void
2240 XMesaResizeBuffers( XMesaBuffer b )
2241 {
2242 GET_CURRENT_CONTEXT(ctx);
2243 XMesaContext xmctx = XMESA_CONTEXT(ctx);
2244 if (!xmctx)
2245 return;
2246 xmesa_check_and_update_buffer_size(xmctx, b);
2247 }
2248
2249
2250 static GLint
2251 xbuffer_to_renderbuffer(int buffer)
2252 {
2253 assert(MAX_AUX_BUFFERS <= 4);
2254
2255 switch (buffer) {
2256 case GLX_FRONT_LEFT_EXT:
2257 return BUFFER_FRONT_LEFT;
2258 case GLX_FRONT_RIGHT_EXT:
2259 return BUFFER_FRONT_RIGHT;
2260 case GLX_BACK_LEFT_EXT:
2261 return BUFFER_BACK_LEFT;
2262 case GLX_BACK_RIGHT_EXT:
2263 return BUFFER_BACK_RIGHT;
2264 case GLX_AUX0_EXT:
2265 return BUFFER_AUX0;
2266 case GLX_AUX1_EXT:
2267 return BUFFER_AUX1;
2268 case GLX_AUX2_EXT:
2269 return BUFFER_AUX2;
2270 case GLX_AUX3_EXT:
2271 return BUFFER_AUX3;
2272 case GLX_AUX4_EXT:
2273 case GLX_AUX5_EXT:
2274 case GLX_AUX6_EXT:
2275 case GLX_AUX7_EXT:
2276 case GLX_AUX8_EXT:
2277 case GLX_AUX9_EXT:
2278 default:
2279 /* BadValue error */
2280 return -1;
2281 }
2282 }
2283
2284
2285 PUBLIC void
2286 XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
2287 const int *attrib_list)
2288 {
2289 #if 0
2290 GET_CURRENT_CONTEXT(ctx);
2291 const GLuint unit = ctx->Texture.CurrentUnit;
2292 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
2293 struct gl_texture_object *texObj;
2294 #endif
2295 struct gl_renderbuffer *rb;
2296 struct xmesa_renderbuffer *xrb;
2297 GLint b;
2298 XMesaImage *img = NULL;
2299 GLboolean freeImg = GL_FALSE;
2300
2301 b = xbuffer_to_renderbuffer(buffer);
2302 if (b < 0)
2303 return;
2304
2305 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT)
2306 return; /* BadMatch error */
2307
2308 rb = drawable->stfb->Base.Attachment[b].Renderbuffer;
2309 if (!rb) {
2310 /* invalid buffer */
2311 return;
2312 }
2313 xrb = xmesa_renderbuffer(rb);
2314
2315 #if 0
2316 switch (drawable->TextureTarget) {
2317 case GLX_TEXTURE_1D_EXT:
2318 texObj = texUnit->Current1D;
2319 break;
2320 case GLX_TEXTURE_2D_EXT:
2321 texObj = texUnit->Current2D;
2322 break;
2323 case GLX_TEXTURE_RECTANGLE_EXT:
2324 texObj = texUnit->CurrentRect;
2325 break;
2326 default:
2327 return; /* BadMatch error */
2328 }
2329 #endif
2330
2331 /*
2332 * The following is a quick and simple way to implement
2333 * BindTexImage. The better way is to write some new FetchTexel()
2334 * functions which would extract texels from XImages. We'd still
2335 * need to use GetImage when texturing from a Pixmap (front buffer)
2336 * but texturing from a back buffer (XImage) would avoid an image
2337 * copy.
2338 */
2339
2340 /* get XImage */
2341 if (xrb->pixmap) {
2342 img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L,
2343 ZPixmap);
2344 freeImg = GL_TRUE;
2345 }
2346 else if (xrb->ximage) {
2347 img = xrb->ximage;
2348 }
2349
2350 /* store the XImage as a new texture image */
2351 if (img) {
2352 GLenum format, type, intFormat;
2353 if (img->bits_per_pixel == 32) {
2354 format = GL_BGRA;
2355 type = GL_UNSIGNED_BYTE;
2356 intFormat = GL_RGBA;
2357 }
2358 else if (img->bits_per_pixel == 24) {
2359 format = GL_BGR;
2360 type = GL_UNSIGNED_BYTE;
2361 intFormat = GL_RGB;
2362 }
2363 else if (img->bits_per_pixel == 16) {
2364 format = GL_BGR;
2365 type = GL_UNSIGNED_SHORT_5_6_5;
2366 intFormat = GL_RGB;
2367 }
2368 else {
2369 _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage");
2370 return;
2371 }
2372 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) {
2373 intFormat = GL_RGBA;
2374 }
2375 else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) {
2376 intFormat = GL_RGB;
2377 }
2378
2379 _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0,
2380 format, type, img->data);
2381
2382 if (freeImg) {
2383 XMesaDestroyImage(img);
2384 }
2385 }
2386 }
2387
2388
2389
2390 PUBLIC void
2391 XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
2392 {
2393 const GLint b = xbuffer_to_renderbuffer(buffer);
2394 if (b < 0)
2395 return;
2396
2397 /* no-op for now */
2398 }
2399