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