2 * GLX initialization. Code based on glxext.c, glx_query.c, and
3 * glcontextmodes.c under src/glx/. The major difference is that DRI
4 * related code is stripped out.
6 * If the maintenance of this file takes too much time, we should consider
7 * refactoring glxext.c.
12 #include <X11/Xproto.h>
13 #include <X11/Xlibint.h>
14 #include <X11/extensions/Xext.h>
15 #include <X11/extensions/extutil.h>
18 #include "GL/glxproto.h"
19 #include "GL/glxtokens.h"
20 #include "GL/gl.h" /* for GL types needed by __GLcontextModes */
21 #include "glcore.h" /* for __GLcontextModes */
25 #ifdef GLX_DIRECT_RENDERING
27 typedef struct GLXGenericGetString
34 } xGLXGenericGetStringReq
;
36 #define sz_xGLXGenericGetStringReq 12
37 #define X_GLXGenericGetString 0
39 /* Extension required boiler plate */
41 static char *__glXExtensionName
= GLX_EXTENSION_NAME
;
42 static XExtensionInfo
*__glXExtensionInfo
= NULL
;
45 __glXCloseDisplay(Display
* dpy
, XExtCodes
* codes
)
47 return XextRemoveDisplay(__glXExtensionInfo
, dpy
);
50 static /* const */ XExtensionHooks __glXExtensionHooks
= {
55 NULL
, /* create_font */
57 __glXCloseDisplay
, /* close_display */
58 NULL
, /* wire_to_event */
59 NULL
, /* event_to_wire */
61 NULL
, /* error_string */
64 static XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay
, __glXExtensionInfo
,
65 __glXExtensionName
, &__glXExtensionHooks
,
66 __GLX_NUMBER_EVENTS
, NULL
)
69 _gl_convert_from_x_visual_type(int visualType
)
71 #define NUM_VISUAL_TYPES 6
72 static const int glx_visual_types
[NUM_VISUAL_TYPES
] = {
73 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
74 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
75 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
78 return ((unsigned) visualType
< NUM_VISUAL_TYPES
)
79 ? glx_visual_types
[visualType
] : GLX_NONE
;
83 _gl_context_modes_destroy(__GLcontextModes
* modes
)
85 while (modes
!= NULL
) {
86 __GLcontextModes
*const next
= modes
->next
;
93 static __GLcontextModes
*
94 _gl_context_modes_create(unsigned count
, size_t minimum_size
)
96 const size_t size
= (minimum_size
> sizeof(__GLcontextModes
))
97 ? minimum_size
: sizeof(__GLcontextModes
);
98 __GLcontextModes
*base
= NULL
;
99 __GLcontextModes
**next
;
103 for (i
= 0; i
< count
; i
++) {
104 *next
= (__GLcontextModes
*) malloc(size
);
106 _gl_context_modes_destroy(base
);
111 memset(*next
, 0, size
);
112 (*next
)->visualID
= GLX_DONT_CARE
;
113 (*next
)->visualType
= GLX_DONT_CARE
;
114 (*next
)->visualRating
= GLX_NONE
;
115 (*next
)->transparentPixel
= GLX_NONE
;
116 (*next
)->transparentRed
= GLX_DONT_CARE
;
117 (*next
)->transparentGreen
= GLX_DONT_CARE
;
118 (*next
)->transparentBlue
= GLX_DONT_CARE
;
119 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
120 (*next
)->transparentIndex
= GLX_DONT_CARE
;
121 (*next
)->xRenderable
= GLX_DONT_CARE
;
122 (*next
)->fbconfigID
= GLX_DONT_CARE
;
123 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
124 (*next
)->bindToTextureRgb
= GLX_DONT_CARE
;
125 (*next
)->bindToTextureRgba
= GLX_DONT_CARE
;
126 (*next
)->bindToMipmapTexture
= GLX_DONT_CARE
;
127 (*next
)->bindToTextureTargets
= GLX_DONT_CARE
;
128 (*next
)->yInverted
= GLX_DONT_CARE
;
130 next
= &((*next
)->next
);
137 __glXQueryServerString(Display
* dpy
, int opcode
, CARD32 screen
, CARD32 name
)
139 xGLXGenericGetStringReq
*req
;
140 xGLXSingleReply reply
;
144 CARD32 for_whom
= screen
;
145 CARD32 glxCode
= X_GLXQueryServerString
;
151 /* All of the GLX protocol requests for getting a string from the server
152 * look the same. The exact meaning of the for_whom field is usually
153 * either the screen number (for glXQueryServerString) or the context tag
157 GetReq(GLXGenericGetString
, req
);
158 req
->reqType
= opcode
;
159 req
->glxCode
= glxCode
;
160 req
->for_whom
= for_whom
;
163 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
165 length
= reply
.length
* 4;
166 numbytes
= reply
.size
;
168 buf
= (char *) malloc(numbytes
);
170 _XRead(dpy
, buf
, numbytes
);
174 _XEatData(dpy
, length
);
182 /************************************************************************/
184 ** Free the per screen configs data as well as the array of
185 ** __glXScreenConfigs.
188 FreeScreenConfigs(__GLXdisplayPrivate
* priv
)
190 __GLXscreenConfigs
*psc
;
193 /* Free screen configuration information */
194 screens
= ScreenCount(priv
->dpy
);
195 for (i
= 0; i
< screens
; i
++) {
196 psc
= priv
->screenConfigs
[i
];
200 _gl_context_modes_destroy(psc
->configs
);
201 psc
->configs
= NULL
; /* NOTE: just for paranoia */
203 free((char *) psc
->serverGLXexts
);
205 free((char *) priv
->screenConfigs
);
206 priv
->screenConfigs
= NULL
;
210 ** Release the private memory referred to in a display private
211 ** structure. The caller will free the extension structure.
214 __glXFreeDisplayPrivate(XExtData
* extension
)
216 __GLXdisplayPrivate
*priv
;
218 priv
= (__GLXdisplayPrivate
*) extension
->private_data
;
219 FreeScreenConfigs(priv
);
220 if (priv
->serverGLXversion
)
221 free((char *) priv
->serverGLXversion
);
227 /************************************************************************/
230 ** Query the version of the GLX extension. This procedure works even if
231 ** the client extension is not completely set up.
234 #define GLX_MAJOR_VERSION 1 /* current version numbers */
235 #define GLX_MINOR_VERSION 4
238 QueryVersion(Display
* dpy
, int opcode
, int *major
, int *minor
)
240 xGLXQueryVersionReq
*req
;
241 xGLXQueryVersionReply reply
;
243 /* Send the glXQueryVersion request */
245 GetReq(GLXQueryVersion
, req
);
246 req
->reqType
= opcode
;
247 req
->glxCode
= X_GLXQueryVersion
;
248 req
->majorVersion
= GLX_MAJOR_VERSION
;
249 req
->minorVersion
= GLX_MINOR_VERSION
;
250 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
254 if (reply
.majorVersion
!= GLX_MAJOR_VERSION
) {
256 ** The server does not support the same major release as this
261 *major
= reply
.majorVersion
;
262 *minor
= min(reply
.minorVersion
, GLX_MINOR_VERSION
);
266 #define __GLX_MIN_CONFIG_PROPS 18
267 #define __GLX_MAX_CONFIG_PROPS 500
268 #define __GLX_EXT_CONFIG_PROPS 10
269 #define __GLX_TOTAL_CONFIG (__GLX_MIN_CONFIG_PROPS + \
270 2 * __GLX_EXT_CONFIG_PROPS)
273 __glXInitializeVisualConfigFromTags(__GLcontextModes
* config
, int count
,
274 const INT32
* bp
, Bool tagged_only
,
275 Bool fbconfig_style_tags
)
280 /* Copy in the first set of properties */
281 config
->visualID
= *bp
++;
283 config
->visualType
= _gl_convert_from_x_visual_type(*bp
++);
285 config
->rgbMode
= *bp
++;
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
++;
296 config
->doubleBufferMode
= *bp
++;
297 config
->stereoMode
= *bp
++;
299 config
->rgbBits
= *bp
++;
300 config
->depthBits
= *bp
++;
301 config
->stencilBits
= *bp
++;
302 config
->numAuxBuffers
= *bp
++;
303 config
->level
= *bp
++;
305 count
-= __GLX_MIN_CONFIG_PROPS
;
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.
314 #define FETCH_OR_SET(tag) \
315 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
317 for (i
= 0; i
< count
; i
+= 2) {
320 FETCH_OR_SET(rgbMode
);
322 case GLX_BUFFER_SIZE
:
323 config
->rgbBits
= *bp
++;
326 config
->level
= *bp
++;
328 case GLX_DOUBLEBUFFER
:
329 FETCH_OR_SET(doubleBufferMode
);
332 FETCH_OR_SET(stereoMode
);
334 case GLX_AUX_BUFFERS
:
335 config
->numAuxBuffers
= *bp
++;
338 config
->redBits
= *bp
++;
341 config
->greenBits
= *bp
++;
344 config
->blueBits
= *bp
++;
347 config
->alphaBits
= *bp
++;
350 config
->depthBits
= *bp
++;
352 case GLX_STENCIL_SIZE
:
353 config
->stencilBits
= *bp
++;
355 case GLX_ACCUM_RED_SIZE
:
356 config
->accumRedBits
= *bp
++;
358 case GLX_ACCUM_GREEN_SIZE
:
359 config
->accumGreenBits
= *bp
++;
361 case GLX_ACCUM_BLUE_SIZE
:
362 config
->accumBlueBits
= *bp
++;
364 case GLX_ACCUM_ALPHA_SIZE
:
365 config
->accumAlphaBits
= *bp
++;
367 case GLX_VISUAL_CAVEAT_EXT
:
368 config
->visualRating
= *bp
++;
370 case GLX_X_VISUAL_TYPE
:
371 config
->visualType
= *bp
++;
373 case GLX_TRANSPARENT_TYPE
:
374 config
->transparentPixel
= *bp
++;
376 case GLX_TRANSPARENT_INDEX_VALUE
:
377 config
->transparentIndex
= *bp
++;
379 case GLX_TRANSPARENT_RED_VALUE
:
380 config
->transparentRed
= *bp
++;
382 case GLX_TRANSPARENT_GREEN_VALUE
:
383 config
->transparentGreen
= *bp
++;
385 case GLX_TRANSPARENT_BLUE_VALUE
:
386 config
->transparentBlue
= *bp
++;
388 case GLX_TRANSPARENT_ALPHA_VALUE
:
389 config
->transparentAlpha
= *bp
++;
392 config
->visualID
= *bp
++;
394 case GLX_DRAWABLE_TYPE
:
395 config
->drawableType
= *bp
++;
397 case GLX_RENDER_TYPE
:
398 config
->renderType
= *bp
++;
400 case GLX_X_RENDERABLE
:
401 config
->xRenderable
= *bp
++;
403 case GLX_FBCONFIG_ID
:
404 config
->fbconfigID
= *bp
++;
406 case GLX_MAX_PBUFFER_WIDTH
:
407 config
->maxPbufferWidth
= *bp
++;
409 case GLX_MAX_PBUFFER_HEIGHT
:
410 config
->maxPbufferHeight
= *bp
++;
412 case GLX_MAX_PBUFFER_PIXELS
:
413 config
->maxPbufferPixels
= *bp
++;
415 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
:
416 config
->optimalPbufferWidth
= *bp
++;
418 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
:
419 config
->optimalPbufferHeight
= *bp
++;
421 case GLX_VISUAL_SELECT_GROUP_SGIX
:
422 config
->visualSelectGroup
= *bp
++;
424 case GLX_SWAP_METHOD_OML
:
425 config
->swapMethod
= *bp
++;
427 case GLX_SAMPLE_BUFFERS_SGIS
:
428 config
->sampleBuffers
= *bp
++;
430 case GLX_SAMPLES_SGIS
:
431 config
->samples
= *bp
++;
433 case GLX_BIND_TO_TEXTURE_RGB_EXT
:
434 config
->bindToTextureRgb
= *bp
++;
436 case GLX_BIND_TO_TEXTURE_RGBA_EXT
:
437 config
->bindToTextureRgba
= *bp
++;
439 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT
:
440 config
->bindToMipmapTexture
= *bp
++;
442 case GLX_BIND_TO_TEXTURE_TARGETS_EXT
:
443 config
->bindToTextureTargets
= *bp
++;
445 case GLX_Y_INVERTED_EXT
:
446 config
->yInverted
= *bp
++;
457 (config
->rgbMode
) ? GLX_RGBA_BIT
: GLX_COLOR_INDEX_BIT
;
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);
467 static __GLcontextModes
*
468 createConfigsFromProperties(Display
* dpy
, int nvisuals
, int nprops
,
469 int screen
, GLboolean tagged_only
)
471 INT32 buf
[__GLX_TOTAL_CONFIG
], *props
;
473 __GLcontextModes
*modes
, *m
;
479 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
481 /* Check number of properties */
482 if (nprops
< __GLX_MIN_CONFIG_PROPS
|| nprops
> __GLX_MAX_CONFIG_PROPS
)
485 /* Allocate memory for our config structure */
486 modes
= _gl_context_modes_create(nvisuals
, sizeof(__GLcontextModes
));
490 prop_size
= nprops
* __GLX_SIZE_INT32
;
491 if (prop_size
<= sizeof(buf
))
494 props
= malloc(prop_size
);
496 /* Read each config structure and convert it into our format */
498 for (i
= 0; i
< nvisuals
; i
++) {
499 _XRead(dpy
, (char *) props
, prop_size
);
500 /* Older X servers don't send this so we default it here. */
501 m
->drawableType
= GLX_WINDOW_BIT
;
502 __glXInitializeVisualConfigFromTags(m
, nprops
, props
,
503 tagged_only
, GL_TRUE
);
515 getFBConfigs(__GLXscreenConfigs
*psc
, __GLXdisplayPrivate
*priv
, int screen
)
517 xGLXGetFBConfigsReq
*fb_req
;
518 xGLXGetFBConfigsSGIXReq
*sgi_req
;
519 xGLXVendorPrivateWithReplyReq
*vpreq
;
520 xGLXGetFBConfigsReply reply
;
521 Display
*dpy
= priv
->dpy
;
524 __glXQueryServerString(dpy
, priv
->majorOpcode
, screen
, GLX_EXTENSIONS
);
529 if (atof(priv
->serverGLXversion
) >= 1.3) {
530 GetReq(GLXGetFBConfigs
, fb_req
);
531 fb_req
->reqType
= priv
->majorOpcode
;
532 fb_req
->glxCode
= X_GLXGetFBConfigs
;
533 fb_req
->screen
= screen
;
535 else if (strstr(psc
->serverGLXexts
, "GLX_SGIX_fbconfig") != NULL
) {
536 GetReqExtra(GLXVendorPrivateWithReply
,
537 sz_xGLXGetFBConfigsSGIXReq
+
538 sz_xGLXVendorPrivateWithReplyReq
, vpreq
);
539 sgi_req
= (xGLXGetFBConfigsSGIXReq
*) vpreq
;
540 sgi_req
->reqType
= priv
->majorOpcode
;
541 sgi_req
->glxCode
= X_GLXVendorPrivateWithReply
;
542 sgi_req
->vendorCode
= X_GLXvop_GetFBConfigsSGIX
;
543 sgi_req
->screen
= screen
;
548 if (!_XReply(dpy
, (xReply
*) & reply
, 0, False
))
551 psc
->configs
= createConfigsFromProperties(dpy
,
553 reply
.numAttribs
* 2,
558 return psc
->configs
!= NULL
;
562 AllocAndFetchScreenConfigs(Display
* dpy
, __GLXdisplayPrivate
* priv
)
564 __GLXscreenConfigs
*psc
;
568 ** First allocate memory for the array of per screen configs.
570 screens
= ScreenCount(dpy
);
571 priv
->screenConfigs
= malloc(screens
* sizeof *priv
->screenConfigs
);
572 if (!priv
->screenConfigs
) {
576 priv
->serverGLXversion
=
577 __glXQueryServerString(dpy
, priv
->majorOpcode
, 0, GLX_VERSION
);
578 if (priv
->serverGLXversion
== NULL
) {
579 FreeScreenConfigs(priv
);
583 for (i
= 0; i
< screens
; i
++) {
584 psc
= calloc(1, sizeof *psc
);
587 getFBConfigs(psc
, priv
, i
);
588 priv
->screenConfigs
[i
] = psc
;
596 _X_HIDDEN __GLXdisplayPrivate
*
597 __glXInitialize(Display
* dpy
)
599 XExtDisplayInfo
*info
= __glXFindDisplay(dpy
);
600 XExtData
**privList
, *private, *found
;
601 __GLXdisplayPrivate
*dpyPriv
;
602 XEDataObject dataObj
;
605 if (!XextHasExtension(info
))
608 /* See if a display private already exists. If so, return it */
609 dataObj
.display
= dpy
;
610 privList
= XEHeadOfExtensionList(dataObj
);
611 found
= XFindOnExtensionList(privList
, info
->codes
->extension
);
613 return (__GLXdisplayPrivate
*) found
->private_data
;
615 /* See if the versions are compatible */
616 if (!QueryVersion(dpy
, info
->codes
->major_opcode
, &major
, &minor
))
620 ** Allocate memory for all the pieces needed for this buffer.
622 private = (XExtData
*) malloc(sizeof(XExtData
));
625 dpyPriv
= (__GLXdisplayPrivate
*) calloc(1, sizeof(__GLXdisplayPrivate
));
632 ** Init the display private and then read in the screen config
633 ** structures from the server.
635 dpyPriv
->majorOpcode
= info
->codes
->major_opcode
;
638 if (!AllocAndFetchScreenConfigs(dpy
, dpyPriv
)) {
645 ** Fill in the private structure. This is the actual structure that
646 ** hangs off of the Display structure. Our private structure is
647 ** referred to by this structure. Got that?
649 private->number
= info
->codes
->extension
;
651 private->free_private
= __glXFreeDisplayPrivate
;
652 private->private_data
= (char *) dpyPriv
;
653 XAddToExtensionList(privList
, private);
658 #endif /* GLX_DIRECT_RENDERING */