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