1 /* $XFree86: xc/lib/GL/glx/glxext.c,v 1.22 2003/12/08 17:35:28 dawes Exp $ */
4 ** License Applicability. Except to the extent portions of this file are
5 ** made subject to an alternative license as permitted in the SGI Free
6 ** Software License B, Version 1.1 (the "License"), the contents of this
7 ** file are subject only to the provisions of the License. You may not use
8 ** this file except in compliance with the License. You may obtain a copy
9 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
10 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
12 ** http://oss.sgi.com/projects/FreeB
14 ** Note that, as provided in the License, the Software is distributed on an
15 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
16 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
17 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
18 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
20 ** Original Code. The Original Code is: OpenGL Sample Implementation,
21 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
22 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
23 ** Copyright in any portions created by third parties is as indicated
24 ** elsewhere herein. All Rights Reserved.
26 ** Additional Notice Provisions: The application programming interfaces
27 ** established by SGI in conjunction with the Original Code are The
28 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
29 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
30 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
31 ** Window System(R) (Version 1.3), released October 19, 1998. This software
32 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
33 ** published by SGI, but has not been independently verified as being
34 ** compliant with the OpenGL(R) version 1.2.1 Specification.
40 * GLX protocol interface boot-strap code.
42 * Direct rendering support added by Precision Insight, Inc.
44 * \author Kevin E. Martin <kevin@precisioninsight.com>
47 #include "glxclient.h"
52 #include "indirect_init.h"
55 # include "Xthreads.h"
56 #elif defined(PTHREADS)
59 #include "glxextensions.h"
60 #include "glcontextmodes.h"
63 #ifdef GLX_DIRECT_RENDERING
73 #include <X11/XCB/xcb.h>
74 #include <X11/XCB/glx.h>
80 void __glXDumpDrawBuffer(__GLXcontext
*ctx
);
85 * This is where our dispatch table's bounds are.
86 * And the static mesa_init is taken directly from
87 * Mesa's 'sparc.c' initializer.
89 * We need something like this here, because this version
90 * of openGL/glx never initializes a Mesa context, and so
91 * the address of the dispatch table pointer never gets stuffed
92 * into the dispatch jump table otherwise.
94 * It matters only on SPARC, and only if you are using assembler
95 * code instead of C-code indirect dispatch.
99 extern unsigned int _mesa_sparc_glapi_begin
;
100 extern unsigned int _mesa_sparc_glapi_end
;
101 extern void __glapi_sparc_icache_flush(unsigned int *);
102 static void _glx_mesa_init_sparc_glapi_relocs(void);
103 static int _mesa_sparc_needs_init
= 1;
104 #define INIT_MESA_SPARC { \
105 if(_mesa_sparc_needs_init) { \
106 _glx_mesa_init_sparc_glapi_relocs(); \
107 _mesa_sparc_needs_init = 0; \
111 #define INIT_MESA_SPARC
114 static Bool
MakeContextCurrent(Display
*dpy
, GLXDrawable draw
,
115 GLXDrawable read
, GLXContext gc
);
118 ** We setup some dummy structures here so that the API can be used
119 ** even if no context is current.
122 static GLubyte dummyBuffer
[__GLX_BUFFER_LIMIT_SIZE
];
125 ** Dummy context used by small commands when there is no current context.
127 ** gl and glx entry points are designed to operate as nop's when using
128 ** the dummy context structure.
130 static __GLXcontext dummyContext
= {
134 &dummyBuffer
[__GLX_BUFFER_LIMIT_SIZE
],
140 ** All indirect rendering contexts will share the same indirect dispatch table.
142 static __GLapi
*IndirectAPI
= NULL
;
146 * Current context management and locking
149 #if defined( XTHREADS )
152 static GLboolean TSDinitialized
= GL_FALSE
;
153 static xthread_key_t ContextTSD
;
155 __GLXcontext
*__glXGetCurrentContext(void)
157 if (!TSDinitialized
) {
158 xthread_key_create(&ContextTSD
, NULL
);
159 TSDinitialized
= GL_TRUE
;
160 return &dummyContext
;
164 xthread_get_specific(ContextTSD
, &p
);
166 return &dummyContext
;
168 return (__GLXcontext
*) p
;
172 void __glXSetCurrentContext(__GLXcontext
*c
)
174 if (!TSDinitialized
) {
175 xthread_key_create(&ContextTSD
, NULL
);
176 TSDinitialized
= GL_TRUE
;
178 xthread_set_specific(ContextTSD
, c
);
182 /* Used by the __glXLock() and __glXUnlock() macros */
183 xmutex_rec __glXmutex
;
185 #elif defined( PTHREADS )
187 pthread_mutex_t __glXmutex
= PTHREAD_MUTEX_INITIALIZER
;
189 # if defined( GLX_USE_TLS )
192 * Per-thread GLX context pointer.
194 * \c __glXSetCurrentContext is written is such a way that this pointer can
195 * \b never be \c NULL. This is important! Because of this
196 * \c __glXGetCurrentContext can be implemented as trivial macro.
198 __thread
void * __glX_tls_Context
__attribute__((tls_model("initial-exec")))
201 void __glXSetCurrentContext( __GLXcontext
* c
)
203 __glX_tls_Context
= (c
!= NULL
) ? c
: &dummyContext
;
208 static pthread_once_t once_control
= PTHREAD_ONCE_INIT
;
211 * Per-thread data key.
213 * Once \c init_thread_data has been called, the per-thread data key will
214 * take a value of \c NULL. As each new thread is created the default
215 * value, in that thread, will be \c NULL.
217 static pthread_key_t ContextTSD
;
220 * Initialize the per-thread data key.
222 * This function is called \b exactly once per-process (not per-thread!) to
223 * initialize the per-thread data key. This is ideally done using the
224 * \c pthread_once mechanism.
226 static void init_thread_data( void )
228 if ( pthread_key_create( & ContextTSD
, NULL
) != 0 ) {
229 perror( "pthread_key_create" );
234 void __glXSetCurrentContext( __GLXcontext
* c
)
236 pthread_once( & once_control
, init_thread_data
);
237 pthread_setspecific( ContextTSD
, c
);
240 __GLXcontext
* __glXGetCurrentContext( void )
244 pthread_once( & once_control
, init_thread_data
);
246 v
= pthread_getspecific( ContextTSD
);
247 return (v
== NULL
) ? & dummyContext
: (__GLXcontext
*) v
;
250 # endif /* defined( GLX_USE_TLS ) */
252 #elif defined( THREADS )
254 #error Unknown threading method specified.
258 /* not thread safe */
259 __GLXcontext
*__glXcurrentContext
= &dummyContext
;
265 ** You can set this cell to 1 to force the gl drawing stuff to be
266 ** one command per packet
271 ** forward prototype declarations
273 int __glXCloseDisplay(Display
*dpy
, XExtCodes
*codes
);
275 static GLboolean
FillInVisuals( __GLXscreenConfigs
* psc
);
277 /************************************************************************/
279 /* Extension required boiler plate */
281 static char *__glXExtensionName
= GLX_EXTENSION_NAME
;
282 XExtensionInfo
*__glXExtensionInfo
= NULL
;
284 static /* const */ char *error_list
[] = {
286 "GLXBadContextState",
290 "GLXBadCurrentWindow",
291 "GLXBadRenderRequest",
292 "GLXBadLargeRequest",
293 "GLXUnsupportedPrivateRequest",
296 int __glXCloseDisplay(Display
*dpy
, XExtCodes
*codes
)
300 gc
= __glXGetCurrentContext();
301 if (dpy
== gc
->currentDpy
) {
302 __glXSetCurrentContext(&dummyContext
);
303 #ifdef GLX_DIRECT_RENDERING
304 _glapi_set_dispatch(NULL
); /* no-op functions */
306 __glXFreeContext(gc
);
309 return XextRemoveDisplay(__glXExtensionInfo
, dpy
);
313 static XEXT_GENERATE_ERROR_STRING(__glXErrorString
, __glXExtensionName
,
314 __GLX_NUMBER_ERRORS
, error_list
)
316 static /* const */ XExtensionHooks __glXExtensionHooks
= {
317 NULL
, /* create_gc */
321 NULL
, /* create_font */
322 NULL
, /* free_font */
323 __glXCloseDisplay
, /* close_display */
324 NULL
, /* wire_to_event */
325 NULL
, /* event_to_wire */
327 __glXErrorString
, /* error_string */
331 XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay
, __glXExtensionInfo
,
332 __glXExtensionName
, &__glXExtensionHooks
,
333 __GLX_NUMBER_EVENTS
, NULL
)
335 /************************************************************************/
338 ** Free the per screen configs data as well as the array of
339 ** __glXScreenConfigs.
341 static void FreeScreenConfigs(__GLXdisplayPrivate
*priv
)
343 __GLXscreenConfigs
*psc
;
346 /* Free screen configuration information */
347 psc
= priv
->screenConfigs
;
348 screens
= ScreenCount(priv
->dpy
);
349 for (i
= 0; i
< screens
; i
++, psc
++) {
351 _gl_context_modes_destroy( psc
->configs
);
352 if(psc
->effectiveGLXexts
)
353 Xfree(psc
->effectiveGLXexts
);
355 if ( psc
->old_configs
!= NULL
) {
356 Xfree( psc
->old_configs
);
357 psc
->old_configs
= NULL
;
358 psc
->numOldConfigs
= 0;
361 psc
->configs
= NULL
; /* NOTE: just for paranoia */
364 #ifdef GLX_DIRECT_RENDERING
365 /* Free the direct rendering per screen data */
366 if (psc
->driScreen
.private)
367 (*psc
->driScreen
.destroyScreen
)(priv
->dpy
, i
,
368 psc
->driScreen
.private);
369 psc
->driScreen
.private = NULL
;
372 XFree((char*) priv
->screenConfigs
);
376 ** Release the private memory referred to in a display private
377 ** structure. The caller will free the extension structure.
379 static int __glXFreeDisplayPrivate(XExtData
*extension
)
381 __GLXdisplayPrivate
*priv
;
383 priv
= (__GLXdisplayPrivate
*) extension
->private_data
;
384 FreeScreenConfigs(priv
);
385 if(priv
->serverGLXvendor
) {
386 Xfree((char*)priv
->serverGLXvendor
);
387 priv
->serverGLXvendor
= 0x0; /* to protect against double free's */
389 if(priv
->serverGLXversion
) {
390 Xfree((char*)priv
->serverGLXversion
);
391 priv
->serverGLXversion
= 0x0; /* to protect against double free's */
394 #if 0 /* GLX_DIRECT_RENDERING */
395 /* Free the direct rendering per display data */
396 if (priv
->driDisplay
.private)
397 (*priv
->driDisplay
.destroyDisplay
)(priv
->dpy
,
398 priv
->driDisplay
.private);
399 priv
->driDisplay
.private = NULL
;
402 #ifdef GLX_DIRECT_RENDERING
403 XFree(priv
->driDisplay
.createScreen
);
410 /************************************************************************/
413 ** Query the version of the GLX extension. This procedure works even if
414 ** the client extension is not completely set up.
416 static Bool
QueryVersion(Display
*dpy
, int opcode
, int *major
, int *minor
)
418 xGLXQueryVersionReq
*req
;
419 xGLXQueryVersionReply reply
;
421 /* Send the glXQueryVersion request */
423 GetReq(GLXQueryVersion
,req
);
424 req
->reqType
= opcode
;
425 req
->glxCode
= X_GLXQueryVersion
;
426 req
->majorVersion
= GLX_MAJOR_VERSION
;
427 req
->minorVersion
= GLX_MINOR_VERSION
;
428 _XReply(dpy
, (xReply
*) &reply
, 0, False
);
432 if (reply
.majorVersion
!= GLX_MAJOR_VERSION
) {
434 ** The server does not support the same major release as this
439 *major
= reply
.majorVersion
;
440 *minor
= min(reply
.minorVersion
, GLX_MINOR_VERSION
);
446 * Determine if a \c __GLcontextModes structure has the right mojo to be
447 * converted to a \c __GLXvisualConfig to be sent to an "old" style DRI
450 #define MODE_HAS_MOJO(m) \
451 ((m)->visualID != GLX_DONT_CARE) \
452 && ((m)->sampleBuffers == 0) \
453 && ((m)->samples == 0) \
454 && (((m)->drawableType & GLX_WINDOW_BIT) != 0) \
455 && (((m)->xRenderable == GL_TRUE) \
456 || ((m)->xRenderable == GLX_DONT_CARE))
460 * Convert the FBConfigs associated with a screen into an array of
461 * \c __GLXvisualConfig structures. These structures are passed into DRI
462 * drivers that use the "old" interface. The old-style drivers had a fairly
463 * strict set of visual types that could be supported. FBConfigs that
464 * cannot be supported are not converted.
466 * \param psc Screen whose FBConfigs need to be swizzled.
469 * If memory could be allocated and at least one FBConfig could be converted
470 * to a \c __GLXvisualConfig structure, \c GL_TRUE is returned. Otherwise,
471 * \c GL_FALSE is returned.
474 * When the old DRI driver interface is no longer supported, this function
478 FillInVisuals( __GLXscreenConfigs
* psc
)
480 __GLcontextModes
*modes
;
481 int glx_visual_count
;
484 glx_visual_count
= 0;
485 for ( modes
= psc
->configs
; modes
!= NULL
; modes
= modes
->next
) {
486 if ( MODE_HAS_MOJO( modes
) ) {
491 psc
->old_configs
= (__GLXvisualConfig
*)
492 Xmalloc( sizeof( __GLXvisualConfig
) * glx_visual_count
);
493 if ( psc
->old_configs
== NULL
) {
497 glx_visual_count
= 0;
498 for ( modes
= psc
->configs
; modes
!= NULL
; modes
= modes
->next
) {
499 if ( MODE_HAS_MOJO( modes
) ) {
501 #define COPY_VALUE(src_tag,dst_tag) \
502 psc->old_configs[glx_visual_count]. dst_tag = modes-> src_tag
504 COPY_VALUE( visualID
, vid
);
505 COPY_VALUE( rgbMode
, rgba
);
506 COPY_VALUE( stereoMode
, stereo
);
507 COPY_VALUE( doubleBufferMode
, doubleBuffer
);
509 psc
->old_configs
[glx_visual_count
].class =
510 _gl_convert_to_x_visual_type( modes
->visualType
);
512 COPY_VALUE( level
, level
);
513 COPY_VALUE( numAuxBuffers
, auxBuffers
);
515 COPY_VALUE( redBits
, redSize
);
516 COPY_VALUE( greenBits
, greenSize
);
517 COPY_VALUE( blueBits
, blueSize
);
518 COPY_VALUE( alphaBits
, alphaSize
);
519 COPY_VALUE( rgbBits
, bufferSize
);
520 COPY_VALUE( accumRedBits
, accumRedSize
);
521 COPY_VALUE( accumGreenBits
, accumGreenSize
);
522 COPY_VALUE( accumBlueBits
, accumBlueSize
);
523 COPY_VALUE( accumAlphaBits
, accumAlphaSize
);
524 COPY_VALUE( depthBits
, depthSize
);
525 COPY_VALUE( stencilBits
, stencilSize
);
527 COPY_VALUE( visualRating
, visualRating
);
528 COPY_VALUE( transparentPixel
, transparentPixel
);
529 COPY_VALUE( transparentRed
, transparentRed
);
530 COPY_VALUE( transparentGreen
, transparentGreen
);
531 COPY_VALUE( transparentBlue
, transparentBlue
);
532 COPY_VALUE( transparentAlpha
, transparentAlpha
);
533 COPY_VALUE( transparentIndex
, transparentIndex
);
541 psc
->numOldConfigs
= glx_visual_count
;
542 if ( glx_visual_count
== 0 ) {
543 Xfree( psc
->old_configs
);
544 psc
->old_configs
= NULL
;
547 return (glx_visual_count
!= 0);
552 __glXInitializeVisualConfigFromTags( __GLcontextModes
*config
, int count
,
553 const INT32
*bp
, Bool tagged_only
,
554 Bool fbconfig_style_tags
)
559 /* Copy in the first set of properties */
560 config
->visualID
= *bp
++;
562 config
->visualType
= _gl_convert_from_x_visual_type( *bp
++ );
564 config
->rgbMode
= *bp
++;
566 config
->redBits
= *bp
++;
567 config
->greenBits
= *bp
++;
568 config
->blueBits
= *bp
++;
569 config
->alphaBits
= *bp
++;
570 config
->accumRedBits
= *bp
++;
571 config
->accumGreenBits
= *bp
++;
572 config
->accumBlueBits
= *bp
++;
573 config
->accumAlphaBits
= *bp
++;
575 config
->doubleBufferMode
= *bp
++;
576 config
->stereoMode
= *bp
++;
578 config
->rgbBits
= *bp
++;
579 config
->depthBits
= *bp
++;
580 config
->stencilBits
= *bp
++;
581 config
->numAuxBuffers
= *bp
++;
582 config
->level
= *bp
++;
584 count
-= __GLX_MIN_CONFIG_PROPS
;
588 ** Additional properties may be in a list at the end
589 ** of the reply. They are in pairs of property type
590 ** and property value.
593 #define FETCH_OR_SET(tag) \
594 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
596 for (i
= 0; i
< count
; i
+= 2 ) {
599 FETCH_OR_SET( rgbMode
);
601 case GLX_BUFFER_SIZE
:
602 config
->rgbBits
= *bp
++;
605 config
->level
= *bp
++;
607 case GLX_DOUBLEBUFFER
:
608 FETCH_OR_SET( doubleBufferMode
);
611 FETCH_OR_SET( stereoMode
);
613 case GLX_AUX_BUFFERS
:
614 config
->numAuxBuffers
= *bp
++;
617 config
->redBits
= *bp
++;
620 config
->greenBits
= *bp
++;
623 config
->blueBits
= *bp
++;
626 config
->alphaBits
= *bp
++;
629 config
->depthBits
= *bp
++;
631 case GLX_STENCIL_SIZE
:
632 config
->stencilBits
= *bp
++;
634 case GLX_ACCUM_RED_SIZE
:
635 config
->accumRedBits
= *bp
++;
637 case GLX_ACCUM_GREEN_SIZE
:
638 config
->accumGreenBits
= *bp
++;
640 case GLX_ACCUM_BLUE_SIZE
:
641 config
->accumBlueBits
= *bp
++;
643 case GLX_ACCUM_ALPHA_SIZE
:
644 config
->accumAlphaBits
= *bp
++;
646 case GLX_VISUAL_CAVEAT_EXT
:
647 config
->visualRating
= *bp
++;
649 case GLX_X_VISUAL_TYPE
:
650 config
->visualType
= *bp
++;
652 case GLX_TRANSPARENT_TYPE
:
653 config
->transparentPixel
= *bp
++;
655 case GLX_TRANSPARENT_INDEX_VALUE
:
656 config
->transparentIndex
= *bp
++;
658 case GLX_TRANSPARENT_RED_VALUE
:
659 config
->transparentRed
= *bp
++;
661 case GLX_TRANSPARENT_GREEN_VALUE
:
662 config
->transparentGreen
= *bp
++;
664 case GLX_TRANSPARENT_BLUE_VALUE
:
665 config
->transparentBlue
= *bp
++;
667 case GLX_TRANSPARENT_ALPHA_VALUE
:
668 config
->transparentAlpha
= *bp
++;
671 config
->visualID
= *bp
++;
673 case GLX_DRAWABLE_TYPE
:
674 config
->drawableType
= *bp
++;
676 case GLX_RENDER_TYPE
:
677 config
->renderType
= *bp
++;
679 case GLX_X_RENDERABLE
:
680 config
->xRenderable
= *bp
++;
682 case GLX_FBCONFIG_ID
:
683 config
->fbconfigID
= *bp
++;
685 case GLX_MAX_PBUFFER_WIDTH
:
686 config
->maxPbufferWidth
= *bp
++;
688 case GLX_MAX_PBUFFER_HEIGHT
:
689 config
->maxPbufferHeight
= *bp
++;
691 case GLX_MAX_PBUFFER_PIXELS
:
692 config
->maxPbufferPixels
= *bp
++;
694 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
:
695 config
->optimalPbufferWidth
= *bp
++;
697 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
:
698 config
->optimalPbufferHeight
= *bp
++;
700 case GLX_VISUAL_SELECT_GROUP_SGIX
:
701 config
->visualSelectGroup
= *bp
++;
703 case GLX_SWAP_METHOD_OML
:
704 config
->swapMethod
= *bp
++;
706 case GLX_SAMPLE_BUFFERS_SGIS
:
707 config
->sampleBuffers
= *bp
++;
709 case GLX_SAMPLES_SGIS
:
710 config
->samples
= *bp
++;
720 config
->renderType
= (config
->rgbMode
) ? GLX_RGBA_BIT
: GLX_COLOR_INDEX_BIT
;
722 config
->haveAccumBuffer
= ((config
->accumRedBits
+
723 config
->accumGreenBits
+
724 config
->accumBlueBits
+
725 config
->accumAlphaBits
) > 0);
726 config
->haveDepthBuffer
= (config
->depthBits
> 0);
727 config
->haveStencilBuffer
= (config
->stencilBits
> 0);
731 #ifdef GLX_DIRECT_RENDERING
733 filter_modes( __GLcontextModes
** server_modes
,
734 const __GLcontextModes
* driver_modes
)
736 __GLcontextModes
* m
;
737 __GLcontextModes
** prev_next
;
738 const __GLcontextModes
* check
;
739 unsigned modes_count
= 0;
741 if ( driver_modes
== NULL
) {
742 fprintf(stderr
, "libGL warning: 3D driver returned no fbconfigs.\n");
746 /* For each mode in server_modes, check to see if a matching mode exists
747 * in driver_modes. If not, then the mode is not available.
750 prev_next
= server_modes
;
751 for ( m
= *prev_next
; m
!= NULL
; m
= *prev_next
) {
752 GLboolean do_delete
= GL_TRUE
;
754 for ( check
= driver_modes
; check
!= NULL
; check
= check
->next
) {
755 if ( _gl_context_modes_are_same( m
, check
) ) {
756 do_delete
= GL_FALSE
;
761 /* The 3D has to support all the modes that match the GLX visuals
762 * sent from the X server.
764 if ( do_delete
&& (m
->visualID
!= 0) ) {
765 do_delete
= GL_FALSE
;
767 fprintf(stderr
, "libGL warning: 3D driver claims to not support "
768 "visual 0x%02x\n", m
->visualID
);
772 *prev_next
= m
->next
;
775 _gl_context_modes_destroy( m
);
779 prev_next
= & m
->next
;
789 * Perform the required libGL-side initialization and call the client-side
790 * driver's \c __driCreateNewScreen function.
792 * \param dpy Display pointer.
793 * \param scrn Screen number on the display.
794 * \param psc DRI screen information.
795 * \param driDpy DRI display information.
796 * \param createNewScreen Pointer to the client-side driver's
797 * \c __driCreateNewScreen function.
798 * \returns A pointer to the \c __DRIscreenPrivate structure returned by
799 * the client-side driver on success, or \c NULL on failure.
801 * \todo This function needs to be modified to remove context-modes from the
802 * list stored in the \c __GLXscreenConfigsRec to match the list
803 * returned by the client-side driver.
806 CallCreateNewScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
807 __DRIdisplay
* driDpy
,
808 CreateNewScreenFunc createNewScreen
)
810 __DRIscreenPrivate
*psp
= NULL
;
811 #ifndef GLX_USE_APPLEGL
815 __DRIversion ddx_version
;
816 __DRIversion dri_version
;
817 __DRIversion drm_version
;
818 __DRIframebuffer framebuffer
;
821 const char * err_msg
;
822 const char * err_extra
;
823 int api_ver
= __glXGetInternalVersion();
826 dri_version
.major
= driDpy
->private->driMajor
;
827 dri_version
.minor
= driDpy
->private->driMinor
;
828 dri_version
.patch
= driDpy
->private->driPatch
;
831 err_msg
= "XF86DRIOpenConnection";
834 framebuffer
.dev_priv
= NULL
;
836 if (XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
837 fd
= drmOpen(NULL
,BusID
);
838 Xfree(BusID
); /* No longer needed */
840 err_msg
= "open DRM";
841 err_extra
= strerror( -fd
);
846 err_msg
= "drmGetMagic";
849 if (!drmGetMagic(fd
, &magic
)) {
850 drmVersionPtr version
= drmGetVersion(fd
);
852 drm_version
.major
= version
->version_major
;
853 drm_version
.minor
= version
->version_minor
;
854 drm_version
.patch
= version
->version_patchlevel
;
855 drmFreeVersion(version
);
858 drm_version
.major
= -1;
859 drm_version
.minor
= -1;
860 drm_version
.patch
= -1;
863 err_msg
= "XF86DRIAuthConnection";
864 if (XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
868 * Get device name (like "tdfx") and the ddx version numbers.
869 * We'll check the version in each DRI driver's "createScreen"
872 err_msg
= "XF86DRIGetClientDriverName";
873 if (XF86DRIGetClientDriverName(dpy
, scrn
,
881 /* No longer needed. */
886 * Get device-specific info. pDevPriv will point to a struct
887 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
888 * that has information about the screen size, depth, pitch,
889 * ancilliary buffers, DRM mmap handles, etc.
891 err_msg
= "XF86DRIGetDeviceInfo";
892 if (XF86DRIGetDeviceInfo(dpy
, scrn
,
897 &framebuffer
.dev_priv_size
,
898 &framebuffer
.dev_priv
)) {
899 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
900 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
903 * Map the framebuffer region.
905 status
= drmMap(fd
, hFB
, framebuffer
.size
,
906 (drmAddressPtr
)&framebuffer
.base
);
908 err_msg
= "drmMap of framebuffer";
909 err_extra
= strerror( -status
);
913 * Map the SAREA region. Further mmap regions may be setup in
914 * each DRI driver's "createScreen" function.
916 status
= drmMap(fd
, hSAREA
, SAREA_MAX
,
919 err_msg
= "drmMap of sarea";
920 err_extra
= strerror( -status
);
923 __GLcontextModes
* driver_modes
= NULL
;
924 __GLXscreenConfigs
*configs
= psc
->screenConfigs
;
926 err_msg
= "InitDriver";
928 psp
= (*createNewScreen
)(dpy
, scrn
,
940 filter_modes( & configs
->configs
,
942 _gl_context_modes_destroy( driver_modes
);
953 if ( pSAREA
!= MAP_FAILED
) {
954 (void)drmUnmap(pSAREA
, SAREA_MAX
);
957 if ( framebuffer
.base
!= MAP_FAILED
) {
958 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
961 if ( framebuffer
.dev_priv
!= NULL
) {
962 Xfree(framebuffer
.dev_priv
);
969 (void)XF86DRICloseConnection(dpy
, scrn
);
971 if ( err_extra
!= NULL
) {
972 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
976 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
979 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
981 #endif /* !GLX_USE_APPLEGL */
985 #endif /* GLX_DIRECT_RENDERING */
989 ** Allocate the memory for the per screen configs for each screen.
990 ** If that works then fetch the per screen configs data.
992 static Bool
AllocAndFetchScreenConfigs(Display
*dpy
, __GLXdisplayPrivate
*priv
)
994 xGLXGetVisualConfigsReq
*req
;
995 xGLXGetFBConfigsReq
*fb_req
;
996 xGLXVendorPrivateWithReplyReq
*vpreq
;
997 xGLXGetFBConfigsSGIXReq
*sgi_req
;
998 xGLXGetVisualConfigsReply reply
;
999 __GLXscreenConfigs
*psc
;
1000 __GLcontextModes
*config
;
1001 GLint i
, j
, nprops
, screens
;
1002 INT32 buf
[__GLX_TOTAL_CONFIG
], *props
;
1003 unsigned supported_request
= 0;
1007 ** First allocate memory for the array of per screen configs.
1009 screens
= ScreenCount(dpy
);
1010 psc
= (__GLXscreenConfigs
*) Xmalloc(screens
* sizeof(__GLXscreenConfigs
));
1014 memset(psc
, 0, screens
* sizeof(__GLXscreenConfigs
));
1015 priv
->screenConfigs
= psc
;
1017 priv
->serverGLXversion
= __glXGetStringFromServer(dpy
, priv
->majorOpcode
,
1018 X_GLXQueryServerString
,
1020 if ( priv
->serverGLXversion
== NULL
) {
1021 FreeScreenConfigs(priv
);
1025 if ( atof( priv
->serverGLXversion
) >= 1.3 ) {
1026 supported_request
= 1;
1030 ** Now fetch each screens configs structures. If a screen supports
1031 ** GL (by returning a numVisuals > 0) then allocate memory for our
1032 ** config structure and then fill it in.
1034 for (i
= 0; i
< screens
; i
++, psc
++) {
1035 if ( supported_request
!= 1 ) {
1036 psc
->serverGLXexts
= __glXGetStringFromServer(dpy
, priv
->majorOpcode
,
1037 X_GLXQueryServerString
,
1039 if ( strstr( psc
->serverGLXexts
, "GLX_SGIX_fbconfig" ) != NULL
) {
1040 supported_request
= 2;
1043 supported_request
= 3;
1049 switch( supported_request
) {
1051 GetReq(GLXGetFBConfigs
,fb_req
);
1052 fb_req
->reqType
= priv
->majorOpcode
;
1053 fb_req
->glxCode
= X_GLXGetFBConfigs
;
1058 GetReqExtra(GLXVendorPrivateWithReply
,
1059 sz_xGLXGetFBConfigsSGIXReq
-sz_xGLXVendorPrivateWithReplyReq
,vpreq
);
1060 sgi_req
= (xGLXGetFBConfigsSGIXReq
*) vpreq
;
1061 sgi_req
->reqType
= priv
->majorOpcode
;
1062 sgi_req
->glxCode
= X_GLXVendorPrivateWithReply
;
1063 sgi_req
->vendorCode
= X_GLXvop_GetFBConfigsSGIX
;
1064 sgi_req
->screen
= i
;
1068 GetReq(GLXGetVisualConfigs
,req
);
1069 req
->reqType
= priv
->majorOpcode
;
1070 req
->glxCode
= X_GLXGetVisualConfigs
;
1075 if (!_XReply(dpy
, (xReply
*) &reply
, 0, False
)) {
1076 /* Something is busted. Punt. */
1078 FreeScreenConfigs(priv
);
1083 if (!reply
.numVisuals
) {
1084 /* This screen does not support GL rendering */
1089 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for
1092 /* Check number of properties */
1093 nprops
= reply
.numProps
;
1094 if ((nprops
< __GLX_MIN_CONFIG_PROPS
) ||
1095 (nprops
> __GLX_MAX_CONFIG_PROPS
)) {
1096 /* Huh? Not in protocol defined limits. Punt */
1099 FreeScreenConfigs(priv
);
1103 /* Allocate memory for our config structure */
1104 psc
->configs
= _gl_context_modes_create(reply
.numVisuals
,
1105 sizeof(__GLcontextModes
));
1106 if (!psc
->configs
) {
1109 FreeScreenConfigs(priv
);
1113 /* Allocate memory for the properties, if needed */
1114 if ( supported_request
!= 3 ) {
1118 prop_size
= nprops
* __GLX_SIZE_INT32
;
1120 if (prop_size
<= sizeof(buf
)) {
1123 props
= (INT32
*) Xmalloc(prop_size
);
1126 /* Read each config structure and convert it into our format */
1127 config
= psc
->configs
;
1128 for (j
= 0; j
< reply
.numVisuals
; j
++) {
1129 assert( config
!= NULL
);
1130 _XRead(dpy
, (char *)props
, prop_size
);
1132 if ( supported_request
!= 3 ) {
1133 config
->rgbMode
= GL_TRUE
;
1134 config
->drawableType
= GLX_WINDOW_BIT
;
1137 config
->drawableType
= GLX_WINDOW_BIT
| GLX_PIXMAP_BIT
;
1140 __glXInitializeVisualConfigFromTags( config
, nprops
, props
,
1141 (supported_request
!= 3),
1143 if ( config
->fbconfigID
== GLX_DONT_CARE
) {
1144 config
->fbconfigID
= config
->visualID
;
1147 config
= config
->next
;
1150 Xfree((char *)props
);
1154 #ifdef GLX_DIRECT_RENDERING
1155 /* Initialize per screen dynamic client GLX extensions */
1156 psc
->ext_list_first_time
= GL_TRUE
;
1157 /* Initialize the direct rendering per screen data and functions */
1158 if (priv
->driDisplay
.private != NULL
) {
1159 if (priv
->driDisplay
.createNewScreen
&&
1160 priv
->driDisplay
.createNewScreen
[i
]) {
1162 psc
->driScreen
.screenConfigs
= (void *)psc
;
1163 psc
->driScreen
.private =
1164 CallCreateNewScreen(dpy
, i
, & psc
->driScreen
,
1166 priv
->driDisplay
.createNewScreen
[i
] );
1168 else if (priv
->driDisplay
.createScreen
&&
1169 priv
->driDisplay
.createScreen
[i
]) {
1170 /* screen initialization (bootstrap the driver) */
1171 if ( (psc
->old_configs
== NULL
)
1172 && !FillInVisuals(psc
) ) {
1173 FreeScreenConfigs(priv
);
1177 psc
->driScreen
.screenConfigs
= (void *)psc
;
1178 psc
->driScreen
.private =
1179 (*(priv
->driDisplay
.createScreen
[i
]))(dpy
, i
, &psc
->driScreen
,
1191 ** Initialize the client side extension code.
1193 __GLXdisplayPrivate
*__glXInitialize(Display
* dpy
)
1195 XExtDisplayInfo
*info
= __glXFindDisplay(dpy
);
1196 XExtData
**privList
, *private, *found
;
1197 __GLXdisplayPrivate
*dpyPriv
;
1198 XEDataObject dataObj
;
1201 #if defined(XTHREADS)
1203 static int firstCall
= 1;
1205 /* initialize the GLX mutexes */
1206 xmutex_init(&__glXmutex
);
1213 /* The one and only long long lock */
1216 if (!XextHasExtension(info
)) {
1217 /* No GLX extension supported by this server. Oh well. */
1219 XMissingExtension(dpy
, __glXExtensionName
);
1223 /* See if a display private already exists. If so, return it */
1224 dataObj
.display
= dpy
;
1225 privList
= XEHeadOfExtensionList(dataObj
);
1226 found
= XFindOnExtensionList(privList
, info
->codes
->extension
);
1229 return (__GLXdisplayPrivate
*) found
->private_data
;
1232 /* See if the versions are compatible */
1233 if (!QueryVersion(dpy
, info
->codes
->major_opcode
, &major
, &minor
)) {
1234 /* The client and server do not agree on versions. Punt. */
1240 ** Allocate memory for all the pieces needed for this buffer.
1242 private = (XExtData
*) Xmalloc(sizeof(XExtData
));
1247 dpyPriv
= (__GLXdisplayPrivate
*) Xmalloc(sizeof(__GLXdisplayPrivate
));
1250 Xfree((char*) private);
1255 ** Init the display private and then read in the screen config
1256 ** structures from the server.
1258 dpyPriv
->majorOpcode
= info
->codes
->major_opcode
;
1259 dpyPriv
->majorVersion
= major
;
1260 dpyPriv
->minorVersion
= minor
;
1263 dpyPriv
->serverGLXvendor
= 0x0;
1264 dpyPriv
->serverGLXversion
= 0x0;
1266 #ifdef GLX_DIRECT_RENDERING
1268 ** Initialize the direct rendering per display data and functions.
1269 ** Note: This _must_ be done before calling any other DRI routines
1270 ** (e.g., those called in AllocAndFetchScreenConfigs).
1272 if (getenv("LIBGL_ALWAYS_INDIRECT")) {
1273 /* Assinging zero here assures we'll never go direct */
1274 dpyPriv
->driDisplay
.private = 0;
1275 dpyPriv
->driDisplay
.destroyDisplay
= 0;
1276 dpyPriv
->driDisplay
.createScreen
= 0;
1279 dpyPriv
->driDisplay
.private =
1280 driCreateDisplay(dpy
, &dpyPriv
->driDisplay
);
1284 if (!AllocAndFetchScreenConfigs(dpy
, dpyPriv
)) {
1286 Xfree((char*) dpyPriv
);
1287 Xfree((char*) private);
1292 ** Fill in the private structure. This is the actual structure that
1293 ** hangs off of the Display structure. Our private structure is
1294 ** referred to by this structure. Got that?
1296 private->number
= info
->codes
->extension
;
1298 private->free_private
= __glXFreeDisplayPrivate
;
1299 private->private_data
= (char *) dpyPriv
;
1300 XAddToExtensionList(privList
, private);
1302 if (dpyPriv
->majorVersion
== 1 && dpyPriv
->minorVersion
>= 1) {
1303 __glXClientInfo(dpy
, dpyPriv
->majorOpcode
);
1311 ** Setup for sending a GLX command on dpy. Make sure the extension is
1312 ** initialized. Try to avoid calling __glXInitialize as its kinda slow.
1314 CARD8
__glXSetupForCommand(Display
*dpy
)
1317 __GLXdisplayPrivate
*priv
;
1319 /* If this thread has a current context, flush its rendering commands */
1320 gc
= __glXGetCurrentContext();
1321 if (gc
->currentDpy
) {
1322 /* Flush rendering buffer of the current context, if any */
1323 (void) __glXFlushRenderBuffer(gc
, gc
->pc
);
1325 if (gc
->currentDpy
== dpy
) {
1326 /* Use opcode from gc because its right */
1328 return gc
->majorOpcode
;
1331 ** Have to get info about argument dpy because it might be to
1332 ** a different server
1337 /* Forced to lookup extension via the slow initialize route */
1338 priv
= __glXInitialize(dpy
);
1342 return priv
->majorOpcode
;
1346 * Flush the drawing command transport buffer.
1348 * \param ctx Context whose transport buffer is to be flushed.
1349 * \param pc Pointer to first unused buffer location.
1352 * Modify this function to use \c ctx->pc instead of the explicit
1355 GLubyte
*__glXFlushRenderBuffer(__GLXcontext
*ctx
, GLubyte
*pc
)
1357 Display
* const dpy
= ctx
->currentDpy
;
1359 XCBConnection
*c
= XCBConnectionOfDisplay(dpy
);
1362 #endif /* USE_XCB */
1363 const GLint size
= pc
- ctx
->buf
;
1365 if ( (dpy
!= NULL
) && (size
> 0) ) {
1367 XCBGlxRender(c
, ctx
->currentContextTag
, size
, (char *)ctx
->buf
);
1369 /* Send the entire buffer as an X request */
1371 GetReq(GLXRender
,req
);
1372 req
->reqType
= ctx
->majorOpcode
;
1373 req
->glxCode
= X_GLXRender
;
1374 req
->contextTag
= ctx
->currentContextTag
;
1375 req
->length
+= (size
+ 3) >> 2;
1376 _XSend(dpy
, (char *)ctx
->buf
, size
);
1382 /* Reset pointer and return it */
1389 * Send a portion of a GLXRenderLarge command to the server. The advantage of
1390 * this function over \c __glXSendLargeCommand is that callers can use the
1391 * data buffer in the GLX context and may be able to avoid allocating an
1392 * extra buffer. The disadvantage is the clients will have to do more
1393 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1395 * \sa __glXSendLargeCommand
1397 * \param gc GLX context
1398 * \param requestNumber Which part of the whole command is this? The first
1400 * \param totalRequests How many requests will there be?
1401 * \param data Command data.
1402 * \param dataLen Size, in bytes, of the command data.
1404 void __glXSendLargeChunk(__GLXcontext
*gc
, GLint requestNumber
,
1405 GLint totalRequests
,
1406 const GLvoid
* data
, GLint dataLen
)
1408 Display
*dpy
= gc
->currentDpy
;
1410 XCBConnection
*c
= XCBConnectionOfDisplay(dpy
);
1411 XCBGlxRenderLarge(c
, gc
->currentContextTag
, requestNumber
, totalRequests
, dataLen
, data
);
1413 xGLXRenderLargeReq
*req
;
1415 if ( requestNumber
== 1 ) {
1419 GetReq(GLXRenderLarge
,req
);
1420 req
->reqType
= gc
->majorOpcode
;
1421 req
->glxCode
= X_GLXRenderLarge
;
1422 req
->contextTag
= gc
->currentContextTag
;
1423 req
->length
+= (dataLen
+ 3) >> 2;
1424 req
->requestNumber
= requestNumber
;
1425 req
->requestTotal
= totalRequests
;
1426 req
->dataBytes
= dataLen
;
1427 Data(dpy
, data
, dataLen
);
1429 if ( requestNumber
== totalRequests
) {
1433 #endif /* USE_XCB */
1438 * Send a command that is too large for the GLXRender protocol request.
1440 * Send a large command, one that is too large for some reason to
1441 * send using the GLXRender protocol request. One reason to send
1442 * a large command is to avoid copying the data.
1444 * \param ctx GLX context
1445 * \param header Header data.
1446 * \param headerLen Size, in bytes, of the header data. It is assumed that
1447 * the header data will always be small enough to fit in
1448 * a single X protocol packet.
1449 * \param data Command data.
1450 * \param dataLen Size, in bytes, of the command data.
1452 void __glXSendLargeCommand(__GLXcontext
*ctx
,
1453 const GLvoid
*header
, GLint headerLen
,
1454 const GLvoid
*data
, GLint dataLen
)
1457 GLint totalRequests
, requestNumber
;
1460 ** Calculate the maximum amount of data can be stuffed into a single
1461 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum
1462 ** packet size minus sz_xGLXRenderReq.
1464 maxSize
= (ctx
->bufSize
+ sz_xGLXRenderReq
) - sz_xGLXRenderLargeReq
;
1465 totalRequests
= 1 + (dataLen
/ maxSize
);
1466 if (dataLen
% maxSize
) totalRequests
++;
1469 ** Send all of the command, except the large array, as one request.
1471 assert( headerLen
<= maxSize
);
1472 __glXSendLargeChunk(ctx
, 1, totalRequests
, header
, headerLen
);
1475 ** Send enough requests until the whole array is sent.
1477 for ( requestNumber
= 2 ; requestNumber
<= (totalRequests
- 1) ; requestNumber
++ ) {
1478 __glXSendLargeChunk(ctx
, requestNumber
, totalRequests
, data
, maxSize
);
1479 data
= (const GLvoid
*) (((const GLubyte
*) data
) + maxSize
);
1481 assert( dataLen
> 0 );
1484 assert( dataLen
<= maxSize
);
1485 __glXSendLargeChunk(ctx
, requestNumber
, totalRequests
, data
, dataLen
);
1488 /************************************************************************/
1490 GLXContext
glXGetCurrentContext(void)
1492 GLXContext cx
= __glXGetCurrentContext();
1494 if (cx
== &dummyContext
) {
1501 GLXDrawable
glXGetCurrentDrawable(void)
1503 GLXContext gc
= __glXGetCurrentContext();
1504 return gc
->currentDrawable
;
1508 /************************************************************************/
1510 #ifdef GLX_DIRECT_RENDERING
1511 /* Return the DRI per screen structure */
1512 __DRIscreen
*__glXFindDRIScreen(__DRInativeDisplay
*dpy
, int scrn
)
1514 __DRIscreen
*pDRIScreen
= NULL
;
1515 XExtDisplayInfo
*info
= __glXFindDisplay(dpy
);
1516 XExtData
**privList
, *found
;
1517 __GLXdisplayPrivate
*dpyPriv
;
1518 XEDataObject dataObj
;
1521 dataObj
.display
= dpy
;
1522 privList
= XEHeadOfExtensionList(dataObj
);
1523 found
= XFindOnExtensionList(privList
, info
->codes
->extension
);
1527 dpyPriv
= (__GLXdisplayPrivate
*)found
->private_data
;
1528 pDRIScreen
= &dpyPriv
->screenConfigs
[scrn
].driScreen
;
1535 /************************************************************************/
1537 static Bool
SendMakeCurrentRequest( Display
*dpy
, CARD8 opcode
,
1538 GLXContextID gc
, GLXContextTag old_gc
, GLXDrawable draw
, GLXDrawable read
,
1539 xGLXMakeCurrentReply
* reply
);
1542 * Sends a GLX protocol message to the specified display to make the context
1543 * and the drawables current.
1545 * \param dpy Display to send the message to.
1546 * \param opcode Major opcode value for the display.
1547 * \param gc_id Context tag for the context to be made current.
1548 * \param draw Drawable ID for the "draw" drawable.
1549 * \param read Drawable ID for the "read" drawable.
1550 * \param reply Space to store the X-server's reply.
1553 * This function assumes that \c dpy is locked with \c LockDisplay on entry.
1555 static Bool
SendMakeCurrentRequest( Display
*dpy
, CARD8 opcode
,
1556 GLXContextID gc_id
, GLXContextTag gc_tag
,
1557 GLXDrawable draw
, GLXDrawable read
,
1558 xGLXMakeCurrentReply
* reply
)
1560 if ( draw
== read
) {
1561 xGLXMakeCurrentReq
*req
;
1563 GetReq(GLXMakeCurrent
,req
);
1564 req
->reqType
= opcode
;
1565 req
->glxCode
= X_GLXMakeCurrent
;
1566 req
->drawable
= draw
;
1567 req
->context
= gc_id
;
1568 req
->oldContextTag
= gc_tag
;
1571 __GLXdisplayPrivate
*priv
= __glXInitialize(dpy
);
1573 /* If the server can support the GLX 1.3 version, we should
1574 * perfer that. Not only that, some servers support GLX 1.3 but
1575 * not the SGI extension.
1578 if ( (priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3) ) {
1579 xGLXMakeContextCurrentReq
*req
;
1581 GetReq(GLXMakeContextCurrent
,req
);
1582 req
->reqType
= opcode
;
1583 req
->glxCode
= X_GLXMakeContextCurrent
;
1584 req
->drawable
= draw
;
1585 req
->readdrawable
= read
;
1586 req
->context
= gc_id
;
1587 req
->oldContextTag
= gc_tag
;
1590 xGLXVendorPrivateWithReplyReq
*vpreq
;
1591 xGLXMakeCurrentReadSGIReq
*req
;
1593 GetReqExtra(GLXVendorPrivateWithReply
,
1594 sz_xGLXMakeCurrentReadSGIReq
-sz_xGLXVendorPrivateWithReplyReq
,vpreq
);
1595 req
= (xGLXMakeCurrentReadSGIReq
*)vpreq
;
1596 req
->reqType
= opcode
;
1597 req
->glxCode
= X_GLXVendorPrivateWithReply
;
1598 req
->vendorCode
= X_GLXvop_MakeCurrentReadSGI
;
1599 req
->drawable
= draw
;
1600 req
->readable
= read
;
1601 req
->context
= gc_id
;
1602 req
->oldContextTag
= gc_tag
;
1606 return _XReply(dpy
, (xReply
*) reply
, 0, False
);
1610 static Bool
BindContextWrapper( Display
*dpy
, GLXContext gc
,
1611 GLXDrawable draw
, GLXDrawable read
)
1613 #ifdef GLX_DIRECT_RENDERING
1614 if ( gc
->driContext
.bindContext3
!= NULL
) {
1615 return (*gc
->driContext
.bindContext3
)(dpy
, gc
->screen
, draw
, read
,
1618 #ifndef DRI_NEW_INTERFACE_ONLY
1620 return (*gc
->driContext
.bindContext2
)(dpy
, gc
->screen
, draw
, read
,
1629 static Bool
UnbindContextWrapper( Display
*dpy
, GLXContext gc
)
1631 #ifdef GLX_DIRECT_RENDERING
1632 if ( gc
->driContext
.unbindContext3
!= NULL
) {
1633 return (*gc
->driContext
.unbindContext3
)(dpy
, gc
->screen
,
1634 gc
->currentDrawable
,
1635 gc
->currentReadable
,
1638 #ifndef DRI_NEW_INTERFACE_ONLY
1640 return (*gc
->driContext
.unbindContext2
)(dpy
, gc
->screen
,
1641 gc
->currentDrawable
,
1642 gc
->currentReadable
, gc
);
1651 ** Make a particular context current.
1652 ** NOTE: this is in this file so that it can access dummyContext.
1654 USED
static Bool
MakeContextCurrent(Display
*dpy
, GLXDrawable draw
,
1655 GLXDrawable read
, GLXContext gc
)
1657 xGLXMakeCurrentReply reply
;
1659 CARD8 opcode
, oldOpcode
;
1660 Bool sentRequestToOldDpy
= False
;
1661 Bool bindReturnValue
= True
;
1663 opcode
= __glXSetupForCommand(dpy
);
1669 ** Make sure that the new context has a nonzero ID. In the request,
1670 ** a zero context ID is used only to mean that we bind to no current
1673 if ((gc
!= NULL
) && (gc
->xid
== None
)) {
1677 oldGC
= __glXGetCurrentContext();
1678 oldOpcode
= (gc
== oldGC
) ? opcode
: __glXSetupForCommand(dpy
);
1683 if ((dpy
!= oldGC
->currentDpy
|| (gc
&& gc
->isDirect
)) &&
1684 !oldGC
->isDirect
&& oldGC
!= &dummyContext
) {
1686 ** We are either switching from one dpy to another and have to
1687 ** send a request to the previous dpy to unbind the previous
1688 ** context, or we are switching away from a indirect context to
1689 ** a direct context and have to send a request to the dpy to
1690 ** unbind the previous context.
1692 sentRequestToOldDpy
= True
;
1693 LockDisplay(oldGC
->currentDpy
);
1694 if ( ! SendMakeCurrentRequest( oldGC
->currentDpy
, oldOpcode
, None
,
1695 oldGC
->currentContextTag
, None
, None
,
1697 /* The make current failed. Just return GL_FALSE. */
1698 UnlockDisplay(oldGC
->currentDpy
);
1703 oldGC
->currentContextTag
= 0;
1706 #ifdef GLX_DIRECT_RENDERING
1707 /* Unbind the old direct rendering context */
1708 if (oldGC
->isDirect
) {
1709 if (oldGC
->driContext
.private) {
1710 if (! UnbindContextWrapper( oldGC
->currentDpy
, oldGC
)) {
1711 /* The make current failed. Just return GL_FALSE. */
1715 oldGC
->currentContextTag
= 0;
1718 /* Bind the direct rendering context to the drawable */
1719 if (gc
&& gc
->isDirect
) {
1720 if (gc
->driContext
.private) {
1721 bindReturnValue
= BindContextWrapper( dpy
, gc
, draw
, read
);
1725 _glapi_check_multithread();
1726 /* Send a glXMakeCurrent request to bind the new context. */
1729 bindReturnValue
= SendMakeCurrentRequest( dpy
, opcode
,
1730 gc
? gc
->xid
: None
,
1731 oldGC
->currentContextTag
,
1732 draw
, read
, &reply
);
1734 #ifdef GLX_DIRECT_RENDERING
1739 if (!bindReturnValue
) {
1740 /* The make current failed. */
1741 if (gc
&& !gc
->isDirect
) {
1745 #ifdef GLX_DIRECT_RENDERING
1746 /* If the old context was direct rendering, then re-bind to it. */
1747 if (oldGC
->isDirect
) {
1748 if (oldGC
->driContext
.private) {
1749 if (! BindContextWrapper( oldGC
->currentDpy
, oldGC
,
1750 oldGC
->currentDrawable
,
1751 oldGC
->currentReadable
)) {
1753 ** The request failed; this cannot happen with the
1754 ** current API. If in the future the API is
1755 ** extended to allow context sharing between
1756 ** clients, then this may fail (because another
1757 ** client may have grabbed the context); in that
1758 ** case, we cannot undo the previous request, and
1759 ** cannot adhere to the "no-op" behavior.
1766 ** If we had just sent a request to a previous dpy, we have to
1767 ** undo that request (because if a command fails, it should act
1768 ** like a no-op) by making current to the previous context and
1771 if (sentRequestToOldDpy
) {
1772 if ( !SendMakeCurrentRequest( oldGC
->currentDpy
, oldOpcode
,
1774 oldGC
->currentDrawable
,
1775 oldGC
->currentReadable
, &reply
) ) {
1776 UnlockDisplay(oldGC
->currentDpy
);
1779 ** The request failed; this cannot happen with the
1780 ** current API. If in the future the API is extended to
1781 ** allow context sharing between clients, then this may
1782 ** fail (because another client may have grabbed the
1783 ** context); in that case, we cannot undo the previous
1784 ** request, and cannot adhere to the "no-op" behavior.
1788 UnlockDisplay(oldGC
->currentDpy
);
1790 oldGC
->currentContextTag
= reply
.contextTag
;
1795 /* Update our notion of what is current */
1799 ** Even though the contexts are the same the drawable might have
1800 ** changed. Note that gc cannot be the dummy, and that oldGC
1801 ** cannot be NULL, therefore if they are the same, gc is not
1802 ** NULL and not the dummy.
1804 gc
->currentDrawable
= draw
;
1805 gc
->currentReadable
= read
;
1807 if (oldGC
!= &dummyContext
) {
1808 /* Old current context is no longer current to anybody */
1809 oldGC
->currentDpy
= 0;
1810 oldGC
->currentDrawable
= None
;
1811 oldGC
->currentReadable
= None
;
1812 oldGC
->currentContextTag
= 0;
1814 if (oldGC
->xid
== None
) {
1816 ** We are switching away from a context that was
1817 ** previously destroyed, so we need to free the memory
1818 ** for the old handle.
1820 #ifdef GLX_DIRECT_RENDERING
1821 /* Destroy the old direct rendering context */
1822 if (oldGC
->isDirect
) {
1823 if (oldGC
->driContext
.private) {
1824 (*oldGC
->driContext
.destroyContext
)
1825 (dpy
, oldGC
->screen
, oldGC
->driContext
.private);
1826 oldGC
->driContext
.private = NULL
;
1830 __glXFreeContext(oldGC
);
1834 __glXSetCurrentContext(gc
);
1835 #ifdef GLX_DIRECT_RENDERING
1836 if (!gc
->isDirect
) {
1838 IndirectAPI
= __glXNewIndirectAPI();
1839 _glapi_set_dispatch(IndirectAPI
);
1840 # ifdef GLX_USE_APPLEGL
1842 extern void XAppleDRIUseIndirectDispatch(void);
1843 XAppleDRIUseIndirectDispatch();
1848 /* if not direct rendering, always need indirect dispatch */
1850 IndirectAPI
= __glXNewIndirectAPI();
1851 _glapi_set_dispatch(IndirectAPI
);
1853 gc
->currentDpy
= dpy
;
1854 gc
->currentDrawable
= draw
;
1855 gc
->currentReadable
= read
;
1857 if ( ! gc
->isDirect
) {
1858 __GLXattribute
* state
= (__GLXattribute
*)(gc
->client_state_private
);
1860 gc
->currentContextTag
= reply
.contextTag
;
1861 if ( state
->array_state
== NULL
) {
1862 (void) glGetString( GL_EXTENSIONS
);
1863 (void) glGetString( GL_VERSION
);
1864 __glXInitVertexArrayState(gc
);
1868 gc
->currentContextTag
= -1;
1871 __glXSetCurrentContext(&dummyContext
);
1872 #ifdef GLX_DIRECT_RENDERING
1873 _glapi_set_dispatch(NULL
); /* no-op functions */
1882 PUBLIC Bool
GLX_PREFIX(glXMakeCurrent
)(Display
*dpy
, GLXDrawable draw
,
1885 return MakeContextCurrent( dpy
, draw
, draw
, gc
);
1888 PUBLIC
GLX_ALIAS(Bool
, glXMakeCurrentReadSGI
,
1889 (Display
*dpy
, GLXDrawable d
, GLXDrawable r
, GLXContext ctx
),
1890 (dpy
, d
, r
, ctx
), MakeContextCurrent
)
1892 PUBLIC
GLX_ALIAS(Bool
, glXMakeContextCurrent
,
1893 (Display
*dpy
, GLXDrawable d
, GLXDrawable r
, GLXContext ctx
),
1894 (dpy
, d
, r
, ctx
), MakeContextCurrent
)
1898 void __glXDumpDrawBuffer(__GLXcontext
*ctx
)
1900 GLubyte
*p
= ctx
->buf
;
1901 GLubyte
*end
= ctx
->pc
;
1902 GLushort opcode
, length
;
1906 opcode
= *((GLushort
*) p
);
1907 length
= *((GLushort
*) (p
+ 2));
1908 printf("%2x: %5d: ", opcode
, length
);
1911 while (length
> 0) {
1912 printf("%08x ", *((unsigned *) p
));
1921 #ifdef USE_SPARC_ASM
1923 * Used only when we are sparc, using sparc assembler.
1928 _glx_mesa_init_sparc_glapi_relocs(void)
1930 unsigned int *insn_ptr
, *end_ptr
;
1931 unsigned long disp_addr
;
1933 insn_ptr
= &_mesa_sparc_glapi_begin
;
1934 end_ptr
= &_mesa_sparc_glapi_end
;
1935 disp_addr
= (unsigned long) &_glapi_Dispatch
;
1938 * Verbatim from Mesa sparc.c. It's needed because there doesn't
1939 * seem to be a better way to do this:
1941 * UNCONDITIONAL_JUMP ( (*_glapi_Dispatch) + entry_offset )
1943 * This code is patching in the ADDRESS of the pointer to the
1944 * dispatch table. Hence, it must be called exactly once, because
1945 * that address is not going to change.
1947 * What it points to can change, but Mesa (and hence, we) assume
1948 * that there is only one pointer.
1951 while (insn_ptr
< end_ptr
) {
1952 #if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) )
1954 This code patches for 64-bit addresses. This had better
1955 not happen for Sparc/Linux, no matter what architecture we
1956 are building for. So, don't do this.
1958 The 'defined(__linux_64__)' is used here as a placeholder for
1959 when we do do 64-bit usermode on sparc linux.
1961 insn_ptr
[0] |= (disp_addr
>> (32 + 10));
1962 insn_ptr
[1] |= ((disp_addr
& 0xffffffff) >> 10);
1963 __glapi_sparc_icache_flush(&insn_ptr
[0]);
1964 insn_ptr
[2] |= ((disp_addr
>> 32) & ((1 << 10) - 1));
1965 insn_ptr
[3] |= (disp_addr
& ((1 << 10) - 1));
1966 __glapi_sparc_icache_flush(&insn_ptr
[2]);
1969 insn_ptr
[0] |= (disp_addr
>> 10);
1970 insn_ptr
[1] |= (disp_addr
& ((1 << 10) - 1));
1971 __glapi_sparc_icache_flush(&insn_ptr
[0]);
1976 #endif /* sparc ASM in use */