use combined depth/stencil buffer when possible
[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 mesaCtx->st->pipe->surface_alloc = xmesa_surface_alloc;
1614 mesaCtx->st->pipe->supported_formats = xmesa_supported_formats;
1615
1616 mesaCtx->st->haveFramebufferRegions = GL_FALSE;
1617
1618 /* special pipe->clear function */
1619 mesaCtx->st->pipe->clear = xmesa_clear;
1620
1621 return c;
1622 }
1623
1624
1625
1626 PUBLIC
1627 void XMesaDestroyContext( XMesaContext c )
1628 {
1629 GLcontext *mesaCtx = &c->mesa;
1630
1631 #ifdef FX
1632 FXdestroyContext( XMESA_BUFFER(mesaCtx->DrawBuffer) );
1633 #endif
1634
1635 _swsetup_DestroyContext( mesaCtx );
1636 _swrast_DestroyContext( mesaCtx );
1637 _tnl_DestroyContext( mesaCtx );
1638 _vbo_DestroyContext( mesaCtx );
1639 _mesa_free_context_data( mesaCtx );
1640 _mesa_free( c );
1641 }
1642
1643
1644
1645 /**
1646 * Private function for creating an XMesaBuffer which corresponds to an
1647 * X window or pixmap.
1648 * \param v the window's XMesaVisual
1649 * \param w the window we're wrapping
1650 * \return new XMesaBuffer or NULL if error
1651 */
1652 PUBLIC XMesaBuffer
1653 XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
1654 {
1655 #ifndef XFree86Server
1656 XWindowAttributes attr;
1657 #endif
1658 XMesaBuffer b;
1659 XMesaColormap cmap;
1660 int depth;
1661
1662 assert(v);
1663 assert(w);
1664
1665 /* Check that window depth matches visual depth */
1666 #ifdef XFree86Server
1667 depth = ((XMesaDrawable)w)->depth;
1668 #else
1669 XGetWindowAttributes( v->display, w, &attr );
1670 depth = attr.depth;
1671 #endif
1672 if (GET_VISUAL_DEPTH(v) != depth) {
1673 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1674 GET_VISUAL_DEPTH(v), depth);
1675 return NULL;
1676 }
1677
1678 /* Find colormap */
1679 #ifdef XFree86Server
1680 cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
1681 #else
1682 if (attr.colormap) {
1683 cmap = attr.colormap;
1684 }
1685 else {
1686 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1687 /* this is weird, a window w/out a colormap!? */
1688 /* OK, let's just allocate a new one and hope for the best */
1689 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1690 }
1691 #endif
1692
1693 b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
1694 if (!b)
1695 return NULL;
1696
1697 if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
1698 (XMesaDrawable) w, cmap )) {
1699 xmesa_free_buffer(b);
1700 return NULL;
1701 }
1702
1703 return b;
1704 }
1705
1706
1707
1708 /**
1709 * Create a new XMesaBuffer from an X pixmap.
1710 *
1711 * \param v the XMesaVisual
1712 * \param p the pixmap
1713 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1714 * \c GLX_DIRECT_COLOR visual for the pixmap
1715 * \returns new XMesaBuffer or NULL if error
1716 */
1717 PUBLIC XMesaBuffer
1718 XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
1719 {
1720 XMesaBuffer b;
1721
1722 assert(v);
1723
1724 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1725 if (!b)
1726 return NULL;
1727
1728 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1729 (XMesaDrawable) p, cmap)) {
1730 xmesa_free_buffer(b);
1731 return NULL;
1732 }
1733
1734 return b;
1735 }
1736
1737
1738 /**
1739 * For GLX_EXT_texture_from_pixmap
1740 */
1741 XMesaBuffer
1742 XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
1743 XMesaColormap cmap,
1744 int format, int target, int mipmap)
1745 {
1746 GET_CURRENT_CONTEXT(ctx);
1747 XMesaBuffer b;
1748 GLuint width, height;
1749
1750 assert(v);
1751
1752 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
1753 if (!b)
1754 return NULL;
1755
1756 /* get pixmap size, update framebuffer/renderbuffer dims */
1757 xmesa_get_window_size(v->display, b, &width, &height);
1758 _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height);
1759
1760 if (target == 0) {
1761 /* examine dims */
1762 if (ctx->Extensions.ARB_texture_non_power_of_two) {
1763 target = GLX_TEXTURE_2D_EXT;
1764 }
1765 else if ( _mesa_bitcount(width) == 1
1766 && _mesa_bitcount(height) == 1) {
1767 /* power of two size */
1768 if (height == 1) {
1769 target = GLX_TEXTURE_1D_EXT;
1770 }
1771 else {
1772 target = GLX_TEXTURE_2D_EXT;
1773 }
1774 }
1775 else if (ctx->Extensions.NV_texture_rectangle) {
1776 target = GLX_TEXTURE_RECTANGLE_EXT;
1777 }
1778 else {
1779 /* non power of two textures not supported */
1780 XMesaDestroyBuffer(b);
1781 return 0;
1782 }
1783 }
1784
1785 b->TextureTarget = target;
1786 b->TextureFormat = format;
1787 b->TextureMipmap = mipmap;
1788
1789 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1790 (XMesaDrawable) p, cmap)) {
1791 xmesa_free_buffer(b);
1792 return NULL;
1793 }
1794
1795 return b;
1796 }
1797
1798
1799
1800 XMesaBuffer
1801 XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
1802 unsigned int width, unsigned int height)
1803 {
1804 #ifndef XFree86Server
1805 XMesaWindow root;
1806 XMesaDrawable drawable; /* X Pixmap Drawable */
1807 XMesaBuffer b;
1808
1809 /* allocate pixmap for front buffer */
1810 root = RootWindow( v->display, v->visinfo->screen );
1811 drawable = XCreatePixmap(v->display, root, width, height,
1812 v->visinfo->depth);
1813 if (!drawable)
1814 return NULL;
1815
1816 b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1817 if (!b)
1818 return NULL;
1819
1820 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1821 drawable, cmap)) {
1822 xmesa_free_buffer(b);
1823 return NULL;
1824 }
1825
1826 return b;
1827 #else
1828 return 0;
1829 #endif
1830 }
1831
1832
1833
1834 /*
1835 * Deallocate an XMesaBuffer structure and all related info.
1836 */
1837 PUBLIC void
1838 XMesaDestroyBuffer(XMesaBuffer b)
1839 {
1840 xmesa_free_buffer(b);
1841 }
1842
1843
1844 /**
1845 * Query the current window size and update the corresponding GLframebuffer
1846 * and all attached renderbuffers.
1847 * Called when:
1848 * 1. the first time a buffer is bound to a context.
1849 * 2. from glViewport to poll for window size changes
1850 * 3. from the XMesaResizeBuffers() API function.
1851 * Note: it's possible (and legal) for xmctx to be NULL. That can happen
1852 * when resizing a buffer when no rendering context is bound.
1853 */
1854 void
1855 xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1856 {
1857 GLuint width, height;
1858 xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height);
1859 if (drawBuffer->mesa_buffer.Width != width ||
1860 drawBuffer->mesa_buffer.Height != height) {
1861 GLcontext *ctx = xmctx ? &xmctx->mesa : NULL;
1862 _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height);
1863 }
1864 drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */
1865 }
1866
1867
1868 /*
1869 * Bind buffer b to context c and make c the current rendering context.
1870 */
1871 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1872 {
1873 return XMesaMakeCurrent2( c, b, b );
1874 }
1875
1876
1877 /*
1878 * Bind buffer b to context c and make c the current rendering context.
1879 */
1880 PUBLIC
1881 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1882 XMesaBuffer readBuffer )
1883 {
1884 if (c) {
1885 if (!drawBuffer || !readBuffer)
1886 return GL_FALSE; /* must specify buffers! */
1887
1888 if (&(c->mesa) == _mesa_get_current_context()
1889 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1890 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
1891 && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
1892 /* same context and buffer, do nothing */
1893 return GL_TRUE;
1894 }
1895
1896 c->xm_buffer = drawBuffer;
1897
1898 #ifdef FX
1899 if (FXmakeCurrent( drawBuffer ))
1900 return GL_TRUE;
1901 #endif
1902
1903 /* Call this periodically to detect when the user has begun using
1904 * GL rendering from multiple threads.
1905 */
1906 _glapi_check_multithread();
1907
1908 xmesa_check_and_update_buffer_size(c, drawBuffer);
1909 if (readBuffer != drawBuffer)
1910 xmesa_check_and_update_buffer_size(c, readBuffer);
1911
1912 _mesa_make_current(&(c->mesa),
1913 &drawBuffer->mesa_buffer,
1914 &readBuffer->mesa_buffer);
1915
1916 if (c->xm_visual->mesa_visual.rgbMode) {
1917 /*
1918 * Must recompute and set these pixel values because colormap
1919 * can be different for different windows.
1920 */
1921 c->clearpixel = xmesa_color_to_pixel( &c->mesa,
1922 c->clearcolor[0],
1923 c->clearcolor[1],
1924 c->clearcolor[2],
1925 c->clearcolor[3],
1926 c->xm_visual->undithered_pf);
1927 XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
1928 }
1929
1930 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1931 drawBuffer->wasCurrent = GL_TRUE;
1932 }
1933 else {
1934 /* Detach */
1935 _mesa_make_current( NULL, NULL, NULL );
1936 }
1937 return GL_TRUE;
1938 }
1939
1940
1941 /*
1942 * Unbind the context c from its buffer.
1943 */
1944 GLboolean XMesaUnbindContext( XMesaContext c )
1945 {
1946 /* A no-op for XFree86 integration purposes */
1947 return GL_TRUE;
1948 }
1949
1950
1951 XMesaContext XMesaGetCurrentContext( void )
1952 {
1953 GET_CURRENT_CONTEXT(ctx);
1954 if (ctx) {
1955 XMesaContext xmesa = XMESA_CONTEXT(ctx);
1956 return xmesa;
1957 }
1958 else {
1959 return 0;
1960 }
1961 }
1962
1963
1964 XMesaBuffer XMesaGetCurrentBuffer( void )
1965 {
1966 GET_CURRENT_CONTEXT(ctx);
1967 if (ctx) {
1968 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
1969 return xmbuf;
1970 }
1971 else {
1972 return 0;
1973 }
1974 }
1975
1976
1977 /* New in Mesa 3.1 */
1978 XMesaBuffer XMesaGetCurrentReadBuffer( void )
1979 {
1980 GET_CURRENT_CONTEXT(ctx);
1981 if (ctx) {
1982 return XMESA_BUFFER(ctx->ReadBuffer);
1983 }
1984 else {
1985 return 0;
1986 }
1987 }
1988
1989
1990 #ifdef XFree86Server
1991 PUBLIC
1992 GLboolean XMesaForceCurrent(XMesaContext c)
1993 {
1994 if (c) {
1995 _glapi_set_dispatch(c->mesa.CurrentDispatch);
1996
1997 if (&(c->mesa) != _mesa_get_current_context()) {
1998 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
1999 }
2000 }
2001 else {
2002 _mesa_make_current(NULL, NULL, NULL);
2003 }
2004 return GL_TRUE;
2005 }
2006
2007
2008 PUBLIC
2009 GLboolean XMesaLoseCurrent(XMesaContext c)
2010 {
2011 (void) c;
2012 _mesa_make_current(NULL, NULL, NULL);
2013 return GL_TRUE;
2014 }
2015
2016
2017 PUBLIC
2018 GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask )
2019 {
2020 _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
2021 return GL_TRUE;
2022 }
2023 #endif /* XFree86Server */
2024
2025
2026 #ifndef FX
2027 GLboolean XMesaSetFXmode( GLint mode )
2028 {
2029 (void) mode;
2030 return GL_FALSE;
2031 }
2032 #endif
2033
2034
2035
2036 /*
2037 * Copy the back buffer to the front buffer. If there's no back buffer
2038 * this is a no-op.
2039 */
2040 PUBLIC
2041 void XMesaSwapBuffers( XMesaBuffer b )
2042 {
2043 GET_CURRENT_CONTEXT(ctx);
2044
2045 if (!b->backxrb) {
2046 /* single buffered */
2047 return;
2048 }
2049
2050 /* If we're swapping the buffer associated with the current context
2051 * we have to flush any pending rendering commands first.
2052 */
2053 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2054 _mesa_notifySwapBuffers(ctx);
2055
2056 if (b->db_mode) {
2057 #ifdef FX
2058 if (FXswapBuffers(b))
2059 return;
2060 #endif
2061 if (b->backxrb->ximage) {
2062 /* Copy Ximage (back buf) from client memory to server window */
2063 #if defined(USE_XSHM) && !defined(XFree86Server)
2064 if (b->shm) {
2065 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2066 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2067 b->swapgc,
2068 b->backxrb->ximage, 0, 0,
2069 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2070 False );
2071 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2072 }
2073 else
2074 #endif
2075 {
2076 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2077 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2078 b->swapgc,
2079 b->backxrb->ximage, 0, 0,
2080 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
2081 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2082 }
2083 }
2084 else if (b->backxrb->pixmap) {
2085 /* Copy pixmap (back buf) to window (front buf) on server */
2086 /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
2087 XMesaCopyArea( b->xm_visual->display,
2088 b->backxrb->pixmap, /* source drawable */
2089 b->frontxrb->drawable, /* dest. drawable */
2090 b->swapgc,
2091 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
2092 0, 0 /* dest region */
2093 );
2094 /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
2095 }
2096
2097 if (b->swAlpha)
2098 _mesa_copy_soft_alpha_renderbuffers(ctx, &b->mesa_buffer);
2099 }
2100 #if !defined(XFree86Server)
2101 XSync( b->xm_visual->display, False );
2102 #endif
2103 }
2104
2105
2106
2107 /*
2108 * Copy sub-region of back buffer to front buffer
2109 */
2110 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
2111 {
2112 GET_CURRENT_CONTEXT(ctx);
2113
2114 /* If we're swapping the buffer associated with the current context
2115 * we have to flush any pending rendering commands first.
2116 */
2117 if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
2118 _mesa_notifySwapBuffers(ctx);
2119
2120 if (!b->backxrb) {
2121 /* single buffered */
2122 return;
2123 }
2124
2125 if (b->db_mode) {
2126 int yTop = b->mesa_buffer.Height - y - height;
2127 #ifdef FX
2128 if (FXswapBuffers(b))
2129 return;
2130 #endif
2131 if (b->backxrb->ximage) {
2132 /* Copy Ximage from host's memory to server's window */
2133 #if defined(USE_XSHM) && !defined(XFree86Server)
2134 if (b->shm) {
2135 /* XXX assuming width and height aren't too large! */
2136 XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
2137 b->swapgc,
2138 b->backxrb->ximage, x, yTop,
2139 x, yTop, width, height, False );
2140 /* wait for finished event??? */
2141 }
2142 else
2143 #endif
2144 {
2145 /* XXX assuming width and height aren't too large! */
2146 XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
2147 b->swapgc,
2148 b->backxrb->ximage, x, yTop,
2149 x, yTop, width, height );
2150 }
2151 }
2152 else {
2153 /* Copy pixmap to window on server */
2154 XMesaCopyArea( b->xm_visual->display,
2155 b->backxrb->pixmap, /* source drawable */
2156 b->frontxrb->drawable, /* dest. drawable */
2157 b->swapgc,
2158 x, yTop, width, height, /* source region */
2159 x, yTop /* dest region */
2160 );
2161 }
2162 }
2163 }
2164
2165
2166 /*
2167 * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
2168 * is a way to get "under the hood" of X/Mesa so one can manipulate the
2169 * back buffer directly.
2170 * Output: pixmap - pointer to back buffer's Pixmap, or 0
2171 * ximage - pointer to back buffer's XImage, or NULL
2172 * Return: GL_TRUE = context is double buffered
2173 * GL_FALSE = context is single buffered
2174 */
2175 #ifndef XFree86Server
2176 GLboolean XMesaGetBackBuffer( XMesaBuffer b,
2177 XMesaPixmap *pixmap,
2178 XMesaImage **ximage )
2179 {
2180 if (b->db_mode) {
2181 if (pixmap)
2182 *pixmap = b->backxrb->pixmap;
2183 if (ximage)
2184 *ximage = b->backxrb->ximage;
2185 return GL_TRUE;
2186 }
2187 else {
2188 *pixmap = 0;
2189 *ximage = NULL;
2190 return GL_FALSE;
2191 }
2192 }
2193 #endif /* XFree86Server */
2194
2195
2196 /*
2197 * Return the depth buffer associated with an XMesaBuffer.
2198 * Input: b - the XMesa buffer handle
2199 * Output: width, height - size of buffer in pixels
2200 * bytesPerValue - bytes per depth value (2 or 4)
2201 * buffer - pointer to depth buffer values
2202 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
2203 */
2204 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
2205 GLint *bytesPerValue, void **buffer )
2206 {
2207 struct gl_renderbuffer *rb
2208 = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
2209 if (!rb || !rb->Data) {
2210 *width = 0;
2211 *height = 0;
2212 *bytesPerValue = 0;
2213 *buffer = 0;
2214 return GL_FALSE;
2215 }
2216 else {
2217 *width = b->mesa_buffer.Width;
2218 *height = b->mesa_buffer.Height;
2219 *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
2220 ? sizeof(GLushort) : sizeof(GLuint);
2221 *buffer = rb->Data;
2222 return GL_TRUE;
2223 }
2224 }
2225
2226
2227 void XMesaFlush( XMesaContext c )
2228 {
2229 if (c && c->xm_visual) {
2230 #ifdef XFree86Server
2231 /* NOT_NEEDED */
2232 #else
2233 XSync( c->xm_visual->display, False );
2234 #endif
2235 }
2236 }
2237
2238
2239
2240 const char *XMesaGetString( XMesaContext c, int name )
2241 {
2242 (void) c;
2243 if (name==XMESA_VERSION) {
2244 return "5.0";
2245 }
2246 else if (name==XMESA_EXTENSIONS) {
2247 return "";
2248 }
2249 else {
2250 return NULL;
2251 }
2252 }
2253
2254
2255
2256 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
2257 {
2258 XMesaBuffer b;
2259 for (b=XMesaBufferList; b; b=b->Next) {
2260 if (b->frontxrb->drawable == d && b->display == dpy) {
2261 return b;
2262 }
2263 }
2264 return NULL;
2265 }
2266
2267
2268 /**
2269 * Free/destroy all XMesaBuffers associated with given display.
2270 */
2271 void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
2272 {
2273 XMesaBuffer b, next;
2274 for (b = XMesaBufferList; b; b = next) {
2275 next = b->Next;
2276 if (b->display == dpy) {
2277 xmesa_free_buffer(b);
2278 }
2279 }
2280 }
2281
2282
2283 /*
2284 * Look for XMesaBuffers whose X window has been destroyed.
2285 * Deallocate any such XMesaBuffers.
2286 */
2287 void XMesaGarbageCollect( void )
2288 {
2289 XMesaBuffer b, next;
2290 for (b=XMesaBufferList; b; b=next) {
2291 next = b->Next;
2292 if (b->display && b->frontxrb->drawable && b->type == WINDOW) {
2293 #ifdef XFree86Server
2294 /* NOT_NEEDED */
2295 #else
2296 XSync(b->display, False);
2297 if (!window_exists( b->display, b->frontxrb->drawable )) {
2298 /* found a dead window, free the ancillary info */
2299 XMesaDestroyBuffer( b );
2300 }
2301 #endif
2302 }
2303 }
2304 }
2305
2306
2307 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
2308 GLfloat red, GLfloat green,
2309 GLfloat blue, GLfloat alpha )
2310 {
2311 GLcontext *ctx = &xmesa->mesa;
2312 GLint r = (GLint) (red * 255.0F);
2313 GLint g = (GLint) (green * 255.0F);
2314 GLint b = (GLint) (blue * 255.0F);
2315 GLint a = (GLint) (alpha * 255.0F);
2316
2317 switch (xmesa->pixelformat) {
2318 case PF_Index:
2319 return 0;
2320 case PF_Truecolor:
2321 {
2322 unsigned long p;
2323 PACK_TRUECOLOR( p, r, g, b );
2324 return p;
2325 }
2326 case PF_8A8B8G8R:
2327 return PACK_8A8B8G8R( r, g, b, a );
2328 case PF_8A8R8G8B:
2329 return PACK_8A8R8G8B( r, g, b, a );
2330 case PF_8R8G8B:
2331 return PACK_8R8G8B( r, g, b );
2332 case PF_5R6G5B:
2333 return PACK_5R6G5B( r, g, b );
2334 case PF_Dither:
2335 {
2336 DITHER_SETUP;
2337 return DITHER( x, y, r, g, b );
2338 }
2339 case PF_1Bit:
2340 /* 382 = (3*255)/2 */
2341 return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
2342 case PF_HPCR:
2343 return DITHER_HPCR(x, y, r, g, b);
2344 case PF_Lookup:
2345 {
2346 LOOKUP_SETUP;
2347 return LOOKUP( r, g, b );
2348 }
2349 case PF_Grayscale:
2350 return GRAY_RGB( r, g, b );
2351 case PF_Dither_5R6G5B:
2352 /* fall through */
2353 case PF_Dither_True:
2354 {
2355 unsigned long p;
2356 PACK_TRUEDITHER(p, x, y, r, g, b);
2357 return p;
2358 }
2359 default:
2360 _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
2361 }
2362 return 0;
2363 }
2364
2365
2366 /*
2367 * This is typically called when the window size changes and we need
2368 * to reallocate the buffer's back/depth/stencil/accum buffers.
2369 */
2370 PUBLIC void
2371 XMesaResizeBuffers( XMesaBuffer b )
2372 {
2373 GET_CURRENT_CONTEXT(ctx);
2374 XMesaContext xmctx = XMESA_CONTEXT(ctx);
2375 if (!xmctx)
2376 return;
2377 xmesa_check_and_update_buffer_size(xmctx, b);
2378 }
2379
2380
2381 static GLint
2382 xbuffer_to_renderbuffer(int buffer)
2383 {
2384 assert(MAX_AUX_BUFFERS <= 4);
2385
2386 switch (buffer) {
2387 case GLX_FRONT_LEFT_EXT:
2388 return BUFFER_FRONT_LEFT;
2389 case GLX_FRONT_RIGHT_EXT:
2390 return BUFFER_FRONT_RIGHT;
2391 case GLX_BACK_LEFT_EXT:
2392 return BUFFER_BACK_LEFT;
2393 case GLX_BACK_RIGHT_EXT:
2394 return BUFFER_BACK_RIGHT;
2395 case GLX_AUX0_EXT:
2396 return BUFFER_AUX0;
2397 case GLX_AUX1_EXT:
2398 return BUFFER_AUX1;
2399 case GLX_AUX2_EXT:
2400 return BUFFER_AUX2;
2401 case GLX_AUX3_EXT:
2402 return BUFFER_AUX3;
2403 case GLX_AUX4_EXT:
2404 case GLX_AUX5_EXT:
2405 case GLX_AUX6_EXT:
2406 case GLX_AUX7_EXT:
2407 case GLX_AUX8_EXT:
2408 case GLX_AUX9_EXT:
2409 default:
2410 /* BadValue error */
2411 return -1;
2412 }
2413 }
2414
2415
2416 PUBLIC void
2417 XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
2418 const int *attrib_list)
2419 {
2420 #if 0
2421 GET_CURRENT_CONTEXT(ctx);
2422 const GLuint unit = ctx->Texture.CurrentUnit;
2423 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
2424 struct gl_texture_object *texObj;
2425 #endif
2426 struct gl_renderbuffer *rb;
2427 struct xmesa_renderbuffer *xrb;
2428 GLint b;
2429 XMesaImage *img = NULL;
2430 GLboolean freeImg = GL_FALSE;
2431
2432 b = xbuffer_to_renderbuffer(buffer);
2433 if (b < 0)
2434 return;
2435
2436 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT)
2437 return; /* BadMatch error */
2438
2439 rb = drawable->mesa_buffer.Attachment[b].Renderbuffer;
2440 if (!rb) {
2441 /* invalid buffer */
2442 return;
2443 }
2444 xrb = xmesa_renderbuffer(rb);
2445
2446 #if 0
2447 switch (drawable->TextureTarget) {
2448 case GLX_TEXTURE_1D_EXT:
2449 texObj = texUnit->Current1D;
2450 break;
2451 case GLX_TEXTURE_2D_EXT:
2452 texObj = texUnit->Current2D;
2453 break;
2454 case GLX_TEXTURE_RECTANGLE_EXT:
2455 texObj = texUnit->CurrentRect;
2456 break;
2457 default:
2458 return; /* BadMatch error */
2459 }
2460 #endif
2461
2462 /*
2463 * The following is a quick and simple way to implement
2464 * BindTexImage. The better way is to write some new FetchTexel()
2465 * functions which would extract texels from XImages. We'd still
2466 * need to use GetImage when texturing from a Pixmap (front buffer)
2467 * but texturing from a back buffer (XImage) would avoid an image
2468 * copy.
2469 */
2470
2471 /* get XImage */
2472 if (xrb->pixmap) {
2473 img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L,
2474 ZPixmap);
2475 freeImg = GL_TRUE;
2476 }
2477 else if (xrb->ximage) {
2478 img = xrb->ximage;
2479 }
2480
2481 /* store the XImage as a new texture image */
2482 if (img) {
2483 GLenum format, type, intFormat;
2484 if (img->bits_per_pixel == 32) {
2485 format = GL_BGRA;
2486 type = GL_UNSIGNED_BYTE;
2487 intFormat = GL_RGBA;
2488 }
2489 else if (img->bits_per_pixel == 24) {
2490 format = GL_BGR;
2491 type = GL_UNSIGNED_BYTE;
2492 intFormat = GL_RGB;
2493 }
2494 else if (img->bits_per_pixel == 16) {
2495 format = GL_BGR;
2496 type = GL_UNSIGNED_SHORT_5_6_5;
2497 intFormat = GL_RGB;
2498 }
2499 else {
2500 _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage");
2501 return;
2502 }
2503 if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) {
2504 intFormat = GL_RGBA;
2505 }
2506 else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) {
2507 intFormat = GL_RGB;
2508 }
2509
2510 _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0,
2511 format, type, img->data);
2512
2513 if (freeImg) {
2514 XMesaDestroyImage(img);
2515 }
2516 }
2517 }
2518
2519
2520
2521 PUBLIC void
2522 XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
2523 {
2524 const GLint b = xbuffer_to_renderbuffer(buffer);
2525 if (b < 0)
2526 return;
2527
2528 /* no-op for now */
2529 }
2530