glx: xcbified visual and FBConfig choosing
[mesa.git] / src / glx / x11 / glxext.c
1 /*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included 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 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31 /**
32 * \file glxext.c
33 * GLX protocol interface boot-strap code.
34 *
35 * Direct rendering support added by Precision Insight, Inc.
36 *
37 * \author Kevin E. Martin <kevin@precisioninsight.com>
38 */
39
40 #include <assert.h>
41 #include "glxclient.h"
42 #include <X11/extensions/Xext.h>
43 #include <X11/extensions/extutil.h>
44 #include "glapi.h"
45 #include "glxextensions.h"
46 #include "glcontextmodes.h"
47
48 #ifdef USE_XCB
49 #include <X11/Xlib-xcb.h>
50 #include <xcb/xcb.h>
51 #include <xcb/glx.h>
52 #endif
53
54
55 #ifdef DEBUG
56 void __glXDumpDrawBuffer(__GLXcontext * ctx);
57 #endif
58
59 #ifdef USE_SPARC_ASM
60 static void _glx_mesa_init_sparc_glapi_relocs(void);
61 static int _mesa_sparc_needs_init = 1;
62 #define INIT_MESA_SPARC do { \
63 if (_mesa_sparc_needs_init) { \
64 _glx_mesa_init_sparc_glapi_relocs(); \
65 _mesa_sparc_needs_init = 0; \
66 } \
67 } while(0)
68 #else
69 #define INIT_MESA_SPARC do { } while(0)
70 #endif
71
72 /*
73 ** You can set this cell to 1 to force the gl drawing stuff to be
74 ** one command per packet
75 */
76 _X_HIDDEN int __glXDebug = 0;
77
78 /* Extension required boiler plate */
79
80 static char *__glXExtensionName = GLX_EXTENSION_NAME;
81 XExtensionInfo *__glXExtensionInfo = NULL;
82
83 static /* const */ char *error_list[] = {
84 "GLXBadContext",
85 "GLXBadContextState",
86 "GLXBadDrawable",
87 "GLXBadPixmap",
88 "GLXBadContextTag",
89 "GLXBadCurrentWindow",
90 "GLXBadRenderRequest",
91 "GLXBadLargeRequest",
92 "GLXUnsupportedPrivateRequest",
93 "GLXBadFBConfig",
94 "GLXBadPbuffer",
95 "GLXBadCurrentDrawable",
96 "GLXBadWindow",
97 };
98
99 static int
100 __glXCloseDisplay(Display * dpy, XExtCodes * codes)
101 {
102 GLXContext gc;
103
104 gc = __glXGetCurrentContext();
105 if (dpy == gc->currentDpy) {
106 __glXSetCurrentContextNull();
107 __glXFreeContext(gc);
108 }
109
110 return XextRemoveDisplay(__glXExtensionInfo, dpy);
111 }
112
113
114 static
115 XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
116 __GLX_NUMBER_ERRORS, error_list)
117
118 static /* const */ XExtensionHooks __glXExtensionHooks = {
119 NULL, /* create_gc */
120 NULL, /* copy_gc */
121 NULL, /* flush_gc */
122 NULL, /* free_gc */
123 NULL, /* create_font */
124 NULL, /* free_font */
125 __glXCloseDisplay, /* close_display */
126 NULL, /* wire_to_event */
127 NULL, /* event_to_wire */
128 NULL, /* error */
129 __glXErrorString, /* error_string */
130 };
131
132 static
133 XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
134 __glXExtensionName, &__glXExtensionHooks,
135 __GLX_NUMBER_EVENTS, NULL)
136
137 /************************************************************************/
138 /*
139 ** Free the per screen configs data as well as the array of
140 ** __glXScreenConfigs.
141 */
142 static void
143 FreeScreenConfigs(__GLXdisplayPrivate * priv)
144 {
145 __GLXscreenConfigs *psc;
146 GLint i, screens;
147
148 /* Free screen configuration information */
149 psc = priv->screenConfigs;
150 screens = ScreenCount(priv->dpy);
151 for (i = 0; i < screens; i++, psc++) {
152 if (psc->configs) {
153 _gl_context_modes_destroy(psc->configs);
154 if (psc->effectiveGLXexts)
155 Xfree(psc->effectiveGLXexts);
156 psc->configs = NULL; /* NOTE: just for paranoia */
157 }
158 if (psc->visuals) {
159 _gl_context_modes_destroy(psc->visuals);
160 psc->visuals = NULL; /* NOTE: just for paranoia */
161 }
162 Xfree((char *) psc->serverGLXexts);
163
164 #ifdef GLX_DIRECT_RENDERING
165 if (psc->driScreen) {
166 psc->driScreen->destroyScreen(psc);
167 __glxHashDestroy(psc->drawHash);
168 XFree(psc->driScreen);
169 psc->driScreen = NULL;
170 }
171 #endif
172 }
173 XFree((char *) priv->screenConfigs);
174 priv->screenConfigs = NULL;
175 }
176
177 /*
178 ** Release the private memory referred to in a display private
179 ** structure. The caller will free the extension structure.
180 */
181 static int
182 __glXFreeDisplayPrivate(XExtData * extension)
183 {
184 __GLXdisplayPrivate *priv;
185
186 priv = (__GLXdisplayPrivate *) extension->private_data;
187 FreeScreenConfigs(priv);
188 if (priv->serverGLXvendor) {
189 Xfree((char *) priv->serverGLXvendor);
190 priv->serverGLXvendor = 0x0; /* to protect against double free's */
191 }
192 if (priv->serverGLXversion) {
193 Xfree((char *) priv->serverGLXversion);
194 priv->serverGLXversion = 0x0; /* to protect against double free's */
195 }
196
197 #ifdef GLX_DIRECT_RENDERING
198 /* Free the direct rendering per display data */
199 if (priv->driswDisplay)
200 (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
201 priv->driswDisplay = NULL;
202
203 if (priv->driDisplay)
204 (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
205 priv->driDisplay = NULL;
206
207 if (priv->dri2Display)
208 (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
209 priv->dri2Display = NULL;
210 #endif
211
212 Xfree((char *) priv);
213 return 0;
214 }
215
216 /************************************************************************/
217
218 /*
219 ** Query the version of the GLX extension. This procedure works even if
220 ** the client extension is not completely set up.
221 */
222 static Bool
223 QueryVersion(Display * dpy, int opcode, int *major, int *minor)
224 {
225 #ifdef USE_XCB
226 xcb_connection_t *c = XGetXCBConnection(dpy);
227 xcb_glx_query_version_reply_t* reply =
228 xcb_glx_query_version_reply(c,
229 xcb_glx_query_version(c,
230 GLX_MAJOR_VERSION,
231 GLX_MINOR_VERSION),
232 NULL);
233
234 if(reply->major_version != GLX_MAJOR_VERSION)
235 {
236 free(reply);
237 return GL_FALSE;
238 }
239 *major = reply->major_version;
240 *minor = min(reply->minor_version, GLX_MINOR_VERSION);
241 free(reply);
242 return GL_TRUE;
243 #else
244 xGLXQueryVersionReq *req;
245 xGLXQueryVersionReply reply;
246
247 /* Send the glXQueryVersion request */
248 LockDisplay(dpy);
249 GetReq(GLXQueryVersion, req);
250 req->reqType = opcode;
251 req->glxCode = X_GLXQueryVersion;
252 req->majorVersion = GLX_MAJOR_VERSION;
253 req->minorVersion = GLX_MINOR_VERSION;
254 _XReply(dpy, (xReply *) & reply, 0, False);
255 UnlockDisplay(dpy);
256 SyncHandle();
257
258 if (reply.majorVersion != GLX_MAJOR_VERSION) {
259 /*
260 ** The server does not support the same major release as this
261 ** client.
262 */
263 return GL_FALSE;
264 }
265 *major = reply.majorVersion;
266 *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
267 return GL_TRUE;
268 #endif /* USE_XCB */
269 }
270
271
272 _X_HIDDEN void
273 __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
274 const INT32 * bp, Bool tagged_only,
275 Bool fbconfig_style_tags)
276 {
277 int i;
278
279 if (!tagged_only) {
280 /* Copy in the first set of properties */
281 config->visualID = *bp++;
282
283 config->visualType = _gl_convert_from_x_visual_type(*bp++);
284
285 config->rgbMode = *bp++;
286
287 config->redBits = *bp++;
288 config->greenBits = *bp++;
289 config->blueBits = *bp++;
290 config->alphaBits = *bp++;
291 config->accumRedBits = *bp++;
292 config->accumGreenBits = *bp++;
293 config->accumBlueBits = *bp++;
294 config->accumAlphaBits = *bp++;
295
296 config->doubleBufferMode = *bp++;
297 config->stereoMode = *bp++;
298
299 config->rgbBits = *bp++;
300 config->depthBits = *bp++;
301 config->stencilBits = *bp++;
302 config->numAuxBuffers = *bp++;
303 config->level = *bp++;
304
305 count -= __GLX_MIN_CONFIG_PROPS;
306 }
307
308 /*
309 ** Additional properties may be in a list at the end
310 ** of the reply. They are in pairs of property type
311 ** and property value.
312 */
313
314 #define FETCH_OR_SET(tag) \
315 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
316
317 for (i = 0; i < count; i += 2) {
318 switch (*bp++) {
319 case GLX_RGBA:
320 FETCH_OR_SET(rgbMode);
321 break;
322 case GLX_BUFFER_SIZE:
323 config->rgbBits = *bp++;
324 break;
325 case GLX_LEVEL:
326 config->level = *bp++;
327 break;
328 case GLX_DOUBLEBUFFER:
329 FETCH_OR_SET(doubleBufferMode);
330 break;
331 case GLX_STEREO:
332 FETCH_OR_SET(stereoMode);
333 break;
334 case GLX_AUX_BUFFERS:
335 config->numAuxBuffers = *bp++;
336 break;
337 case GLX_RED_SIZE:
338 config->redBits = *bp++;
339 break;
340 case GLX_GREEN_SIZE:
341 config->greenBits = *bp++;
342 break;
343 case GLX_BLUE_SIZE:
344 config->blueBits = *bp++;
345 break;
346 case GLX_ALPHA_SIZE:
347 config->alphaBits = *bp++;
348 break;
349 case GLX_DEPTH_SIZE:
350 config->depthBits = *bp++;
351 break;
352 case GLX_STENCIL_SIZE:
353 config->stencilBits = *bp++;
354 break;
355 case GLX_ACCUM_RED_SIZE:
356 config->accumRedBits = *bp++;
357 break;
358 case GLX_ACCUM_GREEN_SIZE:
359 config->accumGreenBits = *bp++;
360 break;
361 case GLX_ACCUM_BLUE_SIZE:
362 config->accumBlueBits = *bp++;
363 break;
364 case GLX_ACCUM_ALPHA_SIZE:
365 config->accumAlphaBits = *bp++;
366 break;
367 case GLX_VISUAL_CAVEAT_EXT:
368 config->visualRating = *bp++;
369 break;
370 case GLX_X_VISUAL_TYPE:
371 config->visualType = *bp++;
372 break;
373 case GLX_TRANSPARENT_TYPE:
374 config->transparentPixel = *bp++;
375 break;
376 case GLX_TRANSPARENT_INDEX_VALUE:
377 config->transparentIndex = *bp++;
378 break;
379 case GLX_TRANSPARENT_RED_VALUE:
380 config->transparentRed = *bp++;
381 break;
382 case GLX_TRANSPARENT_GREEN_VALUE:
383 config->transparentGreen = *bp++;
384 break;
385 case GLX_TRANSPARENT_BLUE_VALUE:
386 config->transparentBlue = *bp++;
387 break;
388 case GLX_TRANSPARENT_ALPHA_VALUE:
389 config->transparentAlpha = *bp++;
390 break;
391 case GLX_VISUAL_ID:
392 config->visualID = *bp++;
393 break;
394 case GLX_DRAWABLE_TYPE:
395 config->drawableType = *bp++;
396 break;
397 case GLX_RENDER_TYPE:
398 config->renderType = *bp++;
399 break;
400 case GLX_X_RENDERABLE:
401 config->xRenderable = *bp++;
402 break;
403 case GLX_FBCONFIG_ID:
404 config->fbconfigID = *bp++;
405 break;
406 case GLX_MAX_PBUFFER_WIDTH:
407 config->maxPbufferWidth = *bp++;
408 break;
409 case GLX_MAX_PBUFFER_HEIGHT:
410 config->maxPbufferHeight = *bp++;
411 break;
412 case GLX_MAX_PBUFFER_PIXELS:
413 config->maxPbufferPixels = *bp++;
414 break;
415 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
416 config->optimalPbufferWidth = *bp++;
417 break;
418 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
419 config->optimalPbufferHeight = *bp++;
420 break;
421 case GLX_VISUAL_SELECT_GROUP_SGIX:
422 config->visualSelectGroup = *bp++;
423 break;
424 case GLX_SWAP_METHOD_OML:
425 config->swapMethod = *bp++;
426 break;
427 case GLX_SAMPLE_BUFFERS_SGIS:
428 config->sampleBuffers = *bp++;
429 break;
430 case GLX_SAMPLES_SGIS:
431 config->samples = *bp++;
432 break;
433 case GLX_BIND_TO_TEXTURE_RGB_EXT:
434 config->bindToTextureRgb = *bp++;
435 break;
436 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
437 config->bindToTextureRgba = *bp++;
438 break;
439 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
440 config->bindToMipmapTexture = *bp++;
441 break;
442 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
443 config->bindToTextureTargets = *bp++;
444 break;
445 case GLX_Y_INVERTED_EXT:
446 config->yInverted = *bp++;
447 break;
448 case None:
449 i = count;
450 break;
451 default:
452 break;
453 }
454 }
455
456 config->renderType =
457 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
458
459 config->haveAccumBuffer = ((config->accumRedBits +
460 config->accumGreenBits +
461 config->accumBlueBits +
462 config->accumAlphaBits) > 0);
463 config->haveDepthBuffer = (config->depthBits > 0);
464 config->haveStencilBuffer = (config->stencilBits > 0);
465 }
466
467 static __GLcontextModes *
468 createConfigsFromProperties(
469 #ifdef USE_XCB
470 uint32_t* properties,
471 #else
472 Display *dpy,
473 #endif
474 int nvisuals, int nprops,
475 int screen, GLboolean tagged_only)
476 {
477 INT32 buf[__GLX_TOTAL_CONFIG], *props;
478 unsigned prop_size;
479 __GLcontextModes *modes, *m;
480 int i;
481
482 if (nprops == 0)
483 return NULL;
484
485 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
486
487 /* Check number of properties */
488 if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
489 return NULL;
490
491 /* Allocate memory for our config structure */
492 modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
493 if (!modes)
494 return NULL;
495
496 prop_size = nprops * __GLX_SIZE_INT32;
497 if (prop_size <= sizeof(buf))
498 props = buf;
499 else
500 props = Xmalloc(prop_size);
501
502 /* Read each config structure and convert it into our format */
503 m = modes;
504 for (i = 0; i < nvisuals; i++) {
505 #ifdef USE_XCB
506 memcpy(props, &properties[i*nprops], prop_size);
507 #else
508 _XRead(dpy, (char *) props, prop_size);
509 #endif
510 /* Older X servers don't send this so we default it here. */
511 m->drawableType = GLX_WINDOW_BIT;
512 __glXInitializeVisualConfigFromTags(m, nprops, props,
513 tagged_only, GL_TRUE);
514 m->screen = screen;
515 m = m->next;
516 }
517
518 if (props != buf)
519 Xfree(props);
520
521 return modes;
522 }
523
524 static GLboolean
525 getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
526 {
527 __GLXscreenConfigs *psc;
528 #ifdef USE_XCB
529 xcb_connection_t* c = XGetXCBConnection(dpy);
530 xcb_glx_get_visual_configs_reply_t* reply = NULL;
531 uint32_t* props;
532
533 psc = priv->screenConfigs + screen;
534 psc->visuals = NULL;
535
536 reply = xcb_glx_get_visual_configs_reply(c,
537 xcb_glx_get_visual_configs(c,
538 screen),
539 NULL);
540 if(!reply)
541 goto out;
542
543 props = xcb_glx_get_visual_configs_property_list(reply);
544 psc->visuals = createConfigsFromProperties(props,
545 reply->num_visuals,
546 reply->num_properties,
547 screen,
548 GL_FALSE);
549 free(reply);
550
551 out:
552 return psc->visuals != NULL;
553 #else /* USE_XCB */
554 xGLXGetVisualConfigsReq *req;
555 xGLXGetVisualConfigsReply reply;
556
557 LockDisplay(dpy);
558
559 psc = priv->screenConfigs + screen;
560 psc->visuals = NULL;
561 GetReq(GLXGetVisualConfigs, req);
562 req->reqType = priv->majorOpcode;
563 req->glxCode = X_GLXGetVisualConfigs;
564 req->screen = screen;
565
566 if (!_XReply(dpy, (xReply *) & reply, 0, False))
567 goto out;
568
569 psc->visuals = createConfigsFromProperties(dpy,
570 reply.numVisuals,
571 reply.numProps,
572 screen, GL_FALSE);
573
574 out:
575 UnlockDisplay(dpy);
576 return psc->visuals != NULL;
577 #endif /* USE_XCB */
578 }
579
580 static GLboolean
581 getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
582 {
583 __GLXscreenConfigs *psc;
584 #ifdef USE_XCB
585 xcb_connection_t* c = XGetXCBConnection(dpy);
586 xcb_glx_get_fb_configs_reply_t* reply_fb = NULL;
587 xcb_glx_get_fb_configs_sgix_reply_t* reply_sgix = NULL;
588 uint32_t num_fb_configs;
589 uint32_t num_properties;
590 uint32_t* props;
591
592 psc = priv->screenConfigs + screen;
593 psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode,
594 screen, GLX_EXTENSIONS);
595 psc->configs = NULL;
596
597 if (atof(priv->serverGLXversion) >= 1.3) {
598 reply_fb = xcb_glx_get_fb_configs_reply(c,
599 xcb_glx_get_fb_configs(c,
600 screen),
601 NULL);
602 if (!reply_fb)
603 goto out;
604
605 num_fb_configs = reply_fb->num_fb_configs;
606 num_properties = reply_fb->num_properties * 2;
607 props = xcb_glx_get_fb_configs_property_list(reply_fb);
608 } else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
609 reply_sgix = xcb_glx_get_fb_configs_sgix_reply(
610 c,
611 xcb_glx_get_fb_configs_sgix(c,
612 65540, /* X_GLXvop_GetFBConfigsSGIX */
613 0,
614 screen),
615 NULL);
616
617 if (!reply_sgix)
618 goto out;
619
620 num_fb_configs = reply_sgix->num_fb_configs;
621 num_properties = reply_sgix->num_properties * 2;
622 props = xcb_glx_get_fb_configs_sgix_property_list(reply_sgix);
623 } else
624 goto out;
625
626 psc->configs = createConfigsFromProperties(props,
627 num_fb_configs,
628 num_properties,
629 screen,
630 GL_TRUE);
631
632 if (reply_fb)
633 free(reply_fb);
634
635 if (reply_sgix)
636 free(reply_sgix);
637
638 out:
639 return psc->configs != NULL;
640 #else /* USE_XCB */
641 xGLXGetFBConfigsReq *fb_req;
642 xGLXGetFBConfigsSGIXReq *sgi_req;
643 xGLXVendorPrivateWithReplyReq *vpreq;
644 xGLXGetFBConfigsReply reply;
645
646 psc = priv->screenConfigs + screen;
647 psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode,
648 screen, GLX_EXTENSIONS);
649
650 LockDisplay(dpy);
651
652 psc->configs = NULL;
653 if (atof(priv->serverGLXversion) >= 1.3) {
654 GetReq(GLXGetFBConfigs, fb_req);
655 fb_req->reqType = priv->majorOpcode;
656 fb_req->glxCode = X_GLXGetFBConfigs;
657 fb_req->screen = screen;
658 }
659 else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
660 GetReqExtra(GLXVendorPrivateWithReply,
661 sz_xGLXGetFBConfigsSGIXReq +
662 sz_xGLXVendorPrivateWithReplyReq, vpreq);
663 sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
664 sgi_req->reqType = priv->majorOpcode;
665 sgi_req->glxCode = X_GLXVendorPrivateWithReply;
666 sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
667 sgi_req->screen = screen;
668 }
669 else
670 goto out;
671
672 if (!_XReply(dpy, (xReply *) & reply, 0, False))
673 goto out;
674
675 psc->configs = createConfigsFromProperties(dpy,
676 reply.numFBConfigs,
677 reply.numAttribs * 2,
678 screen, GL_TRUE);
679
680 out:
681 UnlockDisplay(dpy);
682 return psc->configs != NULL;
683 #endif /* USE_XCB */
684 }
685
686 /*
687 ** Allocate the memory for the per screen configs for each screen.
688 ** If that works then fetch the per screen configs data.
689 */
690 static Bool
691 AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
692 {
693 __GLXscreenConfigs *psc;
694 GLint i, screens;
695
696 /*
697 ** First allocate memory for the array of per screen configs.
698 */
699 screens = ScreenCount(dpy);
700 psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
701 if (!psc) {
702 return GL_FALSE;
703 }
704 memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
705 priv->screenConfigs = psc;
706
707 priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode,
708 0, GLX_VERSION);
709 if (priv->serverGLXversion == NULL) {
710 FreeScreenConfigs(priv);
711 return GL_FALSE;
712 }
713
714 for (i = 0; i < screens; i++, psc++) {
715 getVisualConfigs(dpy, priv, i);
716 getFBConfigs(dpy, priv, i);
717
718 #ifdef GLX_DIRECT_RENDERING
719 psc->scr = i;
720 psc->dpy = dpy;
721 psc->drawHash = __glxHashCreate();
722 if (psc->drawHash == NULL)
723 continue;
724
725 if (priv->dri2Display)
726 psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
727
728 if (psc->driScreen == NULL && priv->driDisplay)
729 psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
730
731 if (psc->driScreen == NULL && priv->driswDisplay)
732 psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
733
734 if (psc->driScreen == NULL) {
735 __glxHashDestroy(psc->drawHash);
736 psc->drawHash = NULL;
737 }
738 #endif
739 }
740 SyncHandle();
741 return GL_TRUE;
742 }
743
744 /*
745 ** Initialize the client side extension code.
746 */
747 _X_HIDDEN __GLXdisplayPrivate *
748 __glXInitialize(Display * dpy)
749 {
750 XExtDisplayInfo *info = __glXFindDisplay(dpy);
751 XExtData **privList, *private, *found;
752 __GLXdisplayPrivate *dpyPriv;
753 XEDataObject dataObj;
754 int major, minor;
755 #ifdef GLX_DIRECT_RENDERING
756 Bool glx_direct, glx_accel;
757 #endif
758
759 #if defined(USE_XTHREADS)
760 {
761 static int firstCall = 1;
762 if (firstCall) {
763 /* initialize the GLX mutexes */
764 xmutex_init(&__glXmutex);
765 firstCall = 0;
766 }
767 }
768 #endif
769
770 INIT_MESA_SPARC;
771 /* The one and only long long lock */
772 __glXLock();
773
774 if (!XextHasExtension(info)) {
775 /* No GLX extension supported by this server. Oh well. */
776 __glXUnlock();
777 XMissingExtension(dpy, __glXExtensionName);
778 return 0;
779 }
780
781 /* See if a display private already exists. If so, return it */
782 dataObj.display = dpy;
783 privList = XEHeadOfExtensionList(dataObj);
784 found = XFindOnExtensionList(privList, info->codes->extension);
785 if (found) {
786 __glXUnlock();
787 return (__GLXdisplayPrivate *) found->private_data;
788 }
789
790 /* See if the versions are compatible */
791 if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
792 /* The client and server do not agree on versions. Punt. */
793 __glXUnlock();
794 return 0;
795 }
796
797 /*
798 ** Allocate memory for all the pieces needed for this buffer.
799 */
800 private = (XExtData *) Xmalloc(sizeof(XExtData));
801 if (!private) {
802 __glXUnlock();
803 return 0;
804 }
805 dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
806 if (!dpyPriv) {
807 __glXUnlock();
808 Xfree((char *) private);
809 return 0;
810 }
811
812 /*
813 ** Init the display private and then read in the screen config
814 ** structures from the server.
815 */
816 dpyPriv->majorOpcode = info->codes->major_opcode;
817 dpyPriv->majorVersion = major;
818 dpyPriv->minorVersion = minor;
819 dpyPriv->dpy = dpy;
820
821 dpyPriv->serverGLXvendor = 0x0;
822 dpyPriv->serverGLXversion = 0x0;
823
824 #ifdef GLX_DIRECT_RENDERING
825 glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
826 glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
827
828 /*
829 ** Initialize the direct rendering per display data and functions.
830 ** Note: This _must_ be done before calling any other DRI routines
831 ** (e.g., those called in AllocAndFetchScreenConfigs).
832 */
833 if (glx_direct && glx_accel) {
834 dpyPriv->dri2Display = dri2CreateDisplay(dpy);
835 dpyPriv->driDisplay = driCreateDisplay(dpy);
836 }
837 if (glx_direct)
838 dpyPriv->driswDisplay = driswCreateDisplay(dpy);
839 #endif
840
841 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
842 __glXUnlock();
843 Xfree((char *) dpyPriv);
844 Xfree((char *) private);
845 return 0;
846 }
847
848 /*
849 ** Fill in the private structure. This is the actual structure that
850 ** hangs off of the Display structure. Our private structure is
851 ** referred to by this structure. Got that?
852 */
853 private->number = info->codes->extension;
854 private->next = 0;
855 private->free_private = __glXFreeDisplayPrivate;
856 private->private_data = (char *) dpyPriv;
857 XAddToExtensionList(privList, private);
858
859 if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
860 __glXClientInfo(dpy, dpyPriv->majorOpcode);
861 }
862 __glXUnlock();
863
864 return dpyPriv;
865 }
866
867 /*
868 ** Setup for sending a GLX command on dpy. Make sure the extension is
869 ** initialized. Try to avoid calling __glXInitialize as its kinda slow.
870 */
871 _X_HIDDEN CARD8
872 __glXSetupForCommand(Display * dpy)
873 {
874 GLXContext gc;
875 __GLXdisplayPrivate *priv;
876
877 /* If this thread has a current context, flush its rendering commands */
878 gc = __glXGetCurrentContext();
879 if (gc->currentDpy) {
880 /* Flush rendering buffer of the current context, if any */
881 (void) __glXFlushRenderBuffer(gc, gc->pc);
882
883 if (gc->currentDpy == dpy) {
884 /* Use opcode from gc because its right */
885 INIT_MESA_SPARC;
886 return gc->majorOpcode;
887 }
888 else {
889 /*
890 ** Have to get info about argument dpy because it might be to
891 ** a different server
892 */
893 }
894 }
895
896 /* Forced to lookup extension via the slow initialize route */
897 priv = __glXInitialize(dpy);
898 if (!priv) {
899 return 0;
900 }
901 return priv->majorOpcode;
902 }
903
904 /**
905 * Flush the drawing command transport buffer.
906 *
907 * \param ctx Context whose transport buffer is to be flushed.
908 * \param pc Pointer to first unused buffer location.
909 *
910 * \todo
911 * Modify this function to use \c ctx->pc instead of the explicit
912 * \c pc parameter.
913 */
914 _X_HIDDEN GLubyte *
915 __glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
916 {
917 Display *const dpy = ctx->currentDpy;
918 #ifdef USE_XCB
919 xcb_connection_t *c = XGetXCBConnection(dpy);
920 #else
921 xGLXRenderReq *req;
922 #endif /* USE_XCB */
923 const GLint size = pc - ctx->buf;
924
925 if ((dpy != NULL) && (size > 0)) {
926 #ifdef USE_XCB
927 xcb_glx_render(c, ctx->currentContextTag, size,
928 (const uint8_t *) ctx->buf);
929 #else
930 /* Send the entire buffer as an X request */
931 LockDisplay(dpy);
932 GetReq(GLXRender, req);
933 req->reqType = ctx->majorOpcode;
934 req->glxCode = X_GLXRender;
935 req->contextTag = ctx->currentContextTag;
936 req->length += (size + 3) >> 2;
937 _XSend(dpy, (char *) ctx->buf, size);
938 UnlockDisplay(dpy);
939 SyncHandle();
940 #endif
941 }
942
943 /* Reset pointer and return it */
944 ctx->pc = ctx->buf;
945 return ctx->pc;
946 }
947
948
949 /**
950 * Send a portion of a GLXRenderLarge command to the server. The advantage of
951 * this function over \c __glXSendLargeCommand is that callers can use the
952 * data buffer in the GLX context and may be able to avoid allocating an
953 * extra buffer. The disadvantage is the clients will have to do more
954 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
955 *
956 * \sa __glXSendLargeCommand
957 *
958 * \param gc GLX context
959 * \param requestNumber Which part of the whole command is this? The first
960 * request is 1.
961 * \param totalRequests How many requests will there be?
962 * \param data Command data.
963 * \param dataLen Size, in bytes, of the command data.
964 */
965 _X_HIDDEN void
966 __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
967 GLint totalRequests, const GLvoid * data, GLint dataLen)
968 {
969 Display *dpy = gc->currentDpy;
970 #ifdef USE_XCB
971 xcb_connection_t *c = XGetXCBConnection(dpy);
972 xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
973 totalRequests, dataLen, data);
974 #else
975 xGLXRenderLargeReq *req;
976
977 if (requestNumber == 1) {
978 LockDisplay(dpy);
979 }
980
981 GetReq(GLXRenderLarge, req);
982 req->reqType = gc->majorOpcode;
983 req->glxCode = X_GLXRenderLarge;
984 req->contextTag = gc->currentContextTag;
985 req->length += (dataLen + 3) >> 2;
986 req->requestNumber = requestNumber;
987 req->requestTotal = totalRequests;
988 req->dataBytes = dataLen;
989 Data(dpy, data, dataLen);
990
991 if (requestNumber == totalRequests) {
992 UnlockDisplay(dpy);
993 SyncHandle();
994 }
995 #endif /* USE_XCB */
996 }
997
998
999 /**
1000 * Send a command that is too large for the GLXRender protocol request.
1001 *
1002 * Send a large command, one that is too large for some reason to
1003 * send using the GLXRender protocol request. One reason to send
1004 * a large command is to avoid copying the data.
1005 *
1006 * \param ctx GLX context
1007 * \param header Header data.
1008 * \param headerLen Size, in bytes, of the header data. It is assumed that
1009 * the header data will always be small enough to fit in
1010 * a single X protocol packet.
1011 * \param data Command data.
1012 * \param dataLen Size, in bytes, of the command data.
1013 */
1014 _X_HIDDEN void
1015 __glXSendLargeCommand(__GLXcontext * ctx,
1016 const GLvoid * header, GLint headerLen,
1017 const GLvoid * data, GLint dataLen)
1018 {
1019 GLint maxSize;
1020 GLint totalRequests, requestNumber;
1021
1022 /*
1023 ** Calculate the maximum amount of data can be stuffed into a single
1024 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum
1025 ** packet size minus sz_xGLXRenderReq.
1026 */
1027 maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1028 totalRequests = 1 + (dataLen / maxSize);
1029 if (dataLen % maxSize)
1030 totalRequests++;
1031
1032 /*
1033 ** Send all of the command, except the large array, as one request.
1034 */
1035 assert(headerLen <= maxSize);
1036 __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1037
1038 /*
1039 ** Send enough requests until the whole array is sent.
1040 */
1041 for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1042 requestNumber++) {
1043 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1044 data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1045 dataLen -= maxSize;
1046 assert(dataLen > 0);
1047 }
1048
1049 assert(dataLen <= maxSize);
1050 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1051 }
1052
1053 /************************************************************************/
1054
1055 #ifdef DEBUG
1056 _X_HIDDEN void
1057 __glXDumpDrawBuffer(__GLXcontext * ctx)
1058 {
1059 GLubyte *p = ctx->buf;
1060 GLubyte *end = ctx->pc;
1061 GLushort opcode, length;
1062
1063 while (p < end) {
1064 /* Fetch opcode */
1065 opcode = *((GLushort *) p);
1066 length = *((GLushort *) (p + 2));
1067 printf("%2x: %5d: ", opcode, length);
1068 length -= 4;
1069 p += 4;
1070 while (length > 0) {
1071 printf("%08x ", *((unsigned *) p));
1072 p += 4;
1073 length -= 4;
1074 }
1075 printf("\n");
1076 }
1077 }
1078 #endif
1079
1080 #ifdef USE_SPARC_ASM
1081 /*
1082 * This is where our dispatch table's bounds are.
1083 * And the static mesa_init is taken directly from
1084 * Mesa's 'sparc.c' initializer.
1085 *
1086 * We need something like this here, because this version
1087 * of openGL/glx never initializes a Mesa context, and so
1088 * the address of the dispatch table pointer never gets stuffed
1089 * into the dispatch jump table otherwise.
1090 *
1091 * It matters only on SPARC, and only if you are using assembler
1092 * code instead of C-code indirect dispatch.
1093 *
1094 * -- FEM, 04.xii.03
1095 */
1096 extern unsigned int _mesa_sparc_glapi_begin;
1097 extern unsigned int _mesa_sparc_glapi_end;
1098 extern void __glapi_sparc_icache_flush(unsigned int *);
1099
1100 static void
1101 _glx_mesa_init_sparc_glapi_relocs(void)
1102 {
1103 unsigned int *insn_ptr, *end_ptr;
1104 unsigned long disp_addr;
1105
1106 insn_ptr = &_mesa_sparc_glapi_begin;
1107 end_ptr = &_mesa_sparc_glapi_end;
1108 disp_addr = (unsigned long) &_glapi_Dispatch;
1109
1110 /*
1111 * Verbatim from Mesa sparc.c. It's needed because there doesn't
1112 * seem to be a better way to do this:
1113 *
1114 * UNCONDITIONAL_JUMP ( (*_glapi_Dispatch) + entry_offset )
1115 *
1116 * This code is patching in the ADDRESS of the pointer to the
1117 * dispatch table. Hence, it must be called exactly once, because
1118 * that address is not going to change.
1119 *
1120 * What it points to can change, but Mesa (and hence, we) assume
1121 * that there is only one pointer.
1122 *
1123 */
1124 while (insn_ptr < end_ptr) {
1125 #if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) )
1126 /*
1127 This code patches for 64-bit addresses. This had better
1128 not happen for Sparc/Linux, no matter what architecture we
1129 are building for. So, don't do this.
1130
1131 The 'defined(__linux_64__)' is used here as a placeholder for
1132 when we do do 64-bit usermode on sparc linux.
1133 */
1134 insn_ptr[0] |= (disp_addr >> (32 + 10));
1135 insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10);
1136 __glapi_sparc_icache_flush(&insn_ptr[0]);
1137 insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1));
1138 insn_ptr[3] |= (disp_addr & ((1 << 10) - 1));
1139 __glapi_sparc_icache_flush(&insn_ptr[2]);
1140 insn_ptr += 11;
1141 #else
1142 insn_ptr[0] |= (disp_addr >> 10);
1143 insn_ptr[1] |= (disp_addr & ((1 << 10) - 1));
1144 __glapi_sparc_icache_flush(&insn_ptr[0]);
1145 insn_ptr += 5;
1146 #endif
1147 }
1148 }
1149 #endif /* sparc ASM in use */