2 * GLX initialization. Code based on glxext.c, glx_query.c, and
3 * glcontextmodes.c under src/glx/x11/. 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/extensions/Xext.h>
14 #include <X11/extensions/extutil.h>
19 typedef struct GLXGenericGetString
26 } xGLXGenericGetStringReq
;
28 #define sz_xGLXGenericGetStringReq 12
29 #define X_GLXGenericGetString 0
31 /* Extension required boiler plate */
33 static char *__glXExtensionName
= GLX_EXTENSION_NAME
;
34 static XExtensionInfo
*__glXExtensionInfo
= NULL
;
37 __glXCloseDisplay(Display
* dpy
, XExtCodes
* codes
)
39 return XextRemoveDisplay(__glXExtensionInfo
, dpy
);
42 static /* const */ XExtensionHooks __glXExtensionHooks
= {
47 NULL
, /* create_font */
49 __glXCloseDisplay
, /* close_display */
50 NULL
, /* wire_to_event */
51 NULL
, /* event_to_wire */
53 NULL
, /* error_string */
56 XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay
, __glXExtensionInfo
,
57 __glXExtensionName
, &__glXExtensionHooks
,
58 __GLX_NUMBER_EVENTS
, NULL
)
61 _gl_convert_from_x_visual_type(int visualType
)
63 #define NUM_VISUAL_TYPES 6
64 static const int glx_visual_types
[NUM_VISUAL_TYPES
] = {
65 GLX_STATIC_GRAY
, GLX_GRAY_SCALE
,
66 GLX_STATIC_COLOR
, GLX_PSEUDO_COLOR
,
67 GLX_TRUE_COLOR
, GLX_DIRECT_COLOR
70 return ((unsigned) visualType
< NUM_VISUAL_TYPES
)
71 ? glx_visual_types
[visualType
] : GLX_NONE
;
74 static __GLcontextModes
*
75 _gl_context_modes_create(unsigned count
, size_t minimum_size
)
77 const size_t size
= (minimum_size
> sizeof(__GLcontextModes
))
78 ? minimum_size
: sizeof(__GLcontextModes
);
79 __GLcontextModes
*base
= NULL
;
80 __GLcontextModes
**next
;
84 for (i
= 0; i
< count
; i
++) {
85 *next
= (__GLcontextModes
*) Xmalloc(size
);
87 _gl_context_modes_destroy(base
);
92 memset(*next
, 0, size
);
93 (*next
)->visualID
= GLX_DONT_CARE
;
94 (*next
)->visualType
= GLX_DONT_CARE
;
95 (*next
)->visualRating
= GLX_NONE
;
96 (*next
)->transparentPixel
= GLX_NONE
;
97 (*next
)->transparentRed
= GLX_DONT_CARE
;
98 (*next
)->transparentGreen
= GLX_DONT_CARE
;
99 (*next
)->transparentBlue
= GLX_DONT_CARE
;
100 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
101 (*next
)->transparentIndex
= GLX_DONT_CARE
;
102 (*next
)->xRenderable
= GLX_DONT_CARE
;
103 (*next
)->fbconfigID
= GLX_DONT_CARE
;
104 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
105 (*next
)->bindToTextureRgb
= GLX_DONT_CARE
;
106 (*next
)->bindToTextureRgba
= GLX_DONT_CARE
;
107 (*next
)->bindToMipmapTexture
= GLX_DONT_CARE
;
108 (*next
)->bindToTextureTargets
= GLX_DONT_CARE
;
109 (*next
)->yInverted
= GLX_DONT_CARE
;
111 next
= &((*next
)->next
);
118 _gl_context_modes_destroy(__GLcontextModes
* modes
)
120 while (modes
!= NULL
) {
121 __GLcontextModes
*const next
= modes
->next
;
129 __glXQueryServerString(Display
* dpy
, int opcode
, CARD32 screen
, CARD32 name
)
131 xGLXGenericGetStringReq
*req
;
132 xGLXSingleReply reply
;
136 CARD32 for_whom
= screen
;
137 CARD32 glxCode
= X_GLXQueryServerString
;
143 /* All of the GLX protocol requests for getting a string from the server
144 * look the same. The exact meaning of the for_whom field is usually
145 * either the screen number (for glXQueryServerString) or the context tag
149 GetReq(GLXGenericGetString
, req
);
150 req
->reqType
= opcode
;
151 req
->glxCode
= glxCode
;
152 req
->for_whom
= for_whom
;
155 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
157 length
= reply
.length
* 4;
158 numbytes
= reply
.size
;
160 buf
= (char *) Xmalloc(numbytes
);
162 _XRead(dpy
, buf
, numbytes
);
166 _XEatData(dpy
, length
);
174 /************************************************************************/
176 ** Free the per screen configs data as well as the array of
177 ** __glXScreenConfigs.
180 FreeScreenConfigs(__GLXdisplayPrivate
* priv
)
182 __GLXscreenConfigs
*psc
;
185 /* Free screen configuration information */
186 psc
= priv
->screenConfigs
;
187 screens
= ScreenCount(priv
->dpy
);
188 for (i
= 0; i
< screens
; i
++, psc
++) {
190 _gl_context_modes_destroy(psc
->configs
);
191 psc
->configs
= NULL
; /* NOTE: just for paranoia */
194 _gl_context_modes_destroy(psc
->visuals
);
195 psc
->visuals
= NULL
; /* NOTE: just for paranoia */
197 Xfree((char *) psc
->serverGLXexts
);
199 XFree((char *) priv
->screenConfigs
);
200 priv
->screenConfigs
= NULL
;
204 ** Release the private memory referred to in a display private
205 ** structure. The caller will free the extension structure.
208 __glXFreeDisplayPrivate(XExtData
* extension
)
210 __GLXdisplayPrivate
*priv
;
212 priv
= (__GLXdisplayPrivate
*) extension
->private_data
;
213 FreeScreenConfigs(priv
);
214 if (priv
->serverGLXvendor
) {
215 Xfree((char *) priv
->serverGLXvendor
);
216 priv
->serverGLXvendor
= 0x0; /* to protect against double free's */
218 if (priv
->serverGLXversion
) {
219 Xfree((char *) priv
->serverGLXversion
);
220 priv
->serverGLXversion
= 0x0; /* to protect against double free's */
223 Xfree((char *) priv
);
227 /************************************************************************/
230 ** Query the version of the GLX extension. This procedure works even if
231 ** the client extension is not completely set up.
234 QueryVersion(Display
* dpy
, int opcode
, int *major
, int *minor
)
236 xGLXQueryVersionReq
*req
;
237 xGLXQueryVersionReply reply
;
239 /* Send the glXQueryVersion request */
241 GetReq(GLXQueryVersion
, req
);
242 req
->reqType
= opcode
;
243 req
->glxCode
= X_GLXQueryVersion
;
244 req
->majorVersion
= GLX_MAJOR_VERSION
;
245 req
->minorVersion
= GLX_MINOR_VERSION
;
246 _XReply(dpy
, (xReply
*) & reply
, 0, False
);
250 if (reply
.majorVersion
!= GLX_MAJOR_VERSION
) {
252 ** The server does not support the same major release as this
257 *major
= reply
.majorVersion
;
258 *minor
= min(reply
.minorVersion
, GLX_MINOR_VERSION
);
263 __glXInitializeVisualConfigFromTags(__GLcontextModes
* config
, int count
,
264 const INT32
* bp
, Bool tagged_only
,
265 Bool fbconfig_style_tags
)
270 /* Copy in the first set of properties */
271 config
->visualID
= *bp
++;
273 config
->visualType
= _gl_convert_from_x_visual_type(*bp
++);
275 config
->rgbMode
= *bp
++;
277 config
->redBits
= *bp
++;
278 config
->greenBits
= *bp
++;
279 config
->blueBits
= *bp
++;
280 config
->alphaBits
= *bp
++;
281 config
->accumRedBits
= *bp
++;
282 config
->accumGreenBits
= *bp
++;
283 config
->accumBlueBits
= *bp
++;
284 config
->accumAlphaBits
= *bp
++;
286 config
->doubleBufferMode
= *bp
++;
287 config
->stereoMode
= *bp
++;
289 config
->rgbBits
= *bp
++;
290 config
->depthBits
= *bp
++;
291 config
->stencilBits
= *bp
++;
292 config
->numAuxBuffers
= *bp
++;
293 config
->level
= *bp
++;
295 count
-= __GLX_MIN_CONFIG_PROPS
;
299 ** Additional properties may be in a list at the end
300 ** of the reply. They are in pairs of property type
301 ** and property value.
304 #define FETCH_OR_SET(tag) \
305 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
307 for (i
= 0; i
< count
; i
+= 2) {
310 FETCH_OR_SET(rgbMode
);
312 case GLX_BUFFER_SIZE
:
313 config
->rgbBits
= *bp
++;
316 config
->level
= *bp
++;
318 case GLX_DOUBLEBUFFER
:
319 FETCH_OR_SET(doubleBufferMode
);
322 FETCH_OR_SET(stereoMode
);
324 case GLX_AUX_BUFFERS
:
325 config
->numAuxBuffers
= *bp
++;
328 config
->redBits
= *bp
++;
331 config
->greenBits
= *bp
++;
334 config
->blueBits
= *bp
++;
337 config
->alphaBits
= *bp
++;
340 config
->depthBits
= *bp
++;
342 case GLX_STENCIL_SIZE
:
343 config
->stencilBits
= *bp
++;
345 case GLX_ACCUM_RED_SIZE
:
346 config
->accumRedBits
= *bp
++;
348 case GLX_ACCUM_GREEN_SIZE
:
349 config
->accumGreenBits
= *bp
++;
351 case GLX_ACCUM_BLUE_SIZE
:
352 config
->accumBlueBits
= *bp
++;
354 case GLX_ACCUM_ALPHA_SIZE
:
355 config
->accumAlphaBits
= *bp
++;
357 case GLX_VISUAL_CAVEAT_EXT
:
358 config
->visualRating
= *bp
++;
360 case GLX_X_VISUAL_TYPE
:
361 config
->visualType
= *bp
++;
363 case GLX_TRANSPARENT_TYPE
:
364 config
->transparentPixel
= *bp
++;
366 case GLX_TRANSPARENT_INDEX_VALUE
:
367 config
->transparentIndex
= *bp
++;
369 case GLX_TRANSPARENT_RED_VALUE
:
370 config
->transparentRed
= *bp
++;
372 case GLX_TRANSPARENT_GREEN_VALUE
:
373 config
->transparentGreen
= *bp
++;
375 case GLX_TRANSPARENT_BLUE_VALUE
:
376 config
->transparentBlue
= *bp
++;
378 case GLX_TRANSPARENT_ALPHA_VALUE
:
379 config
->transparentAlpha
= *bp
++;
382 config
->visualID
= *bp
++;
384 case GLX_DRAWABLE_TYPE
:
385 config
->drawableType
= *bp
++;
387 case GLX_RENDER_TYPE
:
388 config
->renderType
= *bp
++;
390 case GLX_X_RENDERABLE
:
391 config
->xRenderable
= *bp
++;
393 case GLX_FBCONFIG_ID
:
394 config
->fbconfigID
= *bp
++;
396 case GLX_MAX_PBUFFER_WIDTH
:
397 config
->maxPbufferWidth
= *bp
++;
399 case GLX_MAX_PBUFFER_HEIGHT
:
400 config
->maxPbufferHeight
= *bp
++;
402 case GLX_MAX_PBUFFER_PIXELS
:
403 config
->maxPbufferPixels
= *bp
++;
405 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
:
406 config
->optimalPbufferWidth
= *bp
++;
408 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
:
409 config
->optimalPbufferHeight
= *bp
++;
411 case GLX_VISUAL_SELECT_GROUP_SGIX
:
412 config
->visualSelectGroup
= *bp
++;
414 case GLX_SWAP_METHOD_OML
:
415 config
->swapMethod
= *bp
++;
417 case GLX_SAMPLE_BUFFERS_SGIS
:
418 config
->sampleBuffers
= *bp
++;
420 case GLX_SAMPLES_SGIS
:
421 config
->samples
= *bp
++;
423 case GLX_BIND_TO_TEXTURE_RGB_EXT
:
424 config
->bindToTextureRgb
= *bp
++;
426 case GLX_BIND_TO_TEXTURE_RGBA_EXT
:
427 config
->bindToTextureRgba
= *bp
++;
429 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT
:
430 config
->bindToMipmapTexture
= *bp
++;
432 case GLX_BIND_TO_TEXTURE_TARGETS_EXT
:
433 config
->bindToTextureTargets
= *bp
++;
435 case GLX_Y_INVERTED_EXT
:
436 config
->yInverted
= *bp
++;
447 (config
->rgbMode
) ? GLX_RGBA_BIT
: GLX_COLOR_INDEX_BIT
;
449 config
->haveAccumBuffer
= ((config
->accumRedBits
+
450 config
->accumGreenBits
+
451 config
->accumBlueBits
+
452 config
->accumAlphaBits
) > 0);
453 config
->haveDepthBuffer
= (config
->depthBits
> 0);
454 config
->haveStencilBuffer
= (config
->stencilBits
> 0);
457 static __GLcontextModes
*
458 createConfigsFromProperties(Display
* dpy
, int nvisuals
, int nprops
,
459 int screen
, GLboolean tagged_only
)
461 INT32 buf
[__GLX_TOTAL_CONFIG
], *props
;
463 __GLcontextModes
*modes
, *m
;
469 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
471 /* Check number of properties */
472 if (nprops
< __GLX_MIN_CONFIG_PROPS
|| nprops
> __GLX_MAX_CONFIG_PROPS
)
475 /* Allocate memory for our config structure */
476 modes
= _gl_context_modes_create(nvisuals
, sizeof(__GLcontextModes
));
480 prop_size
= nprops
* __GLX_SIZE_INT32
;
481 if (prop_size
<= sizeof(buf
))
484 props
= Xmalloc(prop_size
);
486 /* Read each config structure and convert it into our format */
488 for (i
= 0; i
< nvisuals
; i
++) {
489 _XRead(dpy
, (char *) props
, prop_size
);
490 /* Older X servers don't send this so we default it here. */
491 m
->drawableType
= GLX_WINDOW_BIT
;
492 __glXInitializeVisualConfigFromTags(m
, nprops
, props
,
493 tagged_only
, GL_TRUE
);
505 getVisualConfigs(Display
* dpy
, __GLXdisplayPrivate
* priv
, int screen
)
507 xGLXGetVisualConfigsReq
*req
;
508 __GLXscreenConfigs
*psc
;
509 xGLXGetVisualConfigsReply reply
;
513 psc
= priv
->screenConfigs
+ screen
;
515 GetReq(GLXGetVisualConfigs
, req
);
516 req
->reqType
= priv
->majorOpcode
;
517 req
->glxCode
= X_GLXGetVisualConfigs
;
518 req
->screen
= screen
;
520 if (!_XReply(dpy
, (xReply
*) & reply
, 0, False
))
523 psc
->visuals
= createConfigsFromProperties(dpy
,
530 return psc
->visuals
!= NULL
;
534 getFBConfigs(Display
* dpy
, __GLXdisplayPrivate
* priv
, int screen
)
536 xGLXGetFBConfigsReq
*fb_req
;
537 xGLXGetFBConfigsSGIXReq
*sgi_req
;
538 xGLXVendorPrivateWithReplyReq
*vpreq
;
539 xGLXGetFBConfigsReply reply
;
540 __GLXscreenConfigs
*psc
;
542 psc
= priv
->screenConfigs
+ screen
;
544 __glXQueryServerString(dpy
, priv
->majorOpcode
, screen
, GLX_EXTENSIONS
);
549 if (atof(priv
->serverGLXversion
) >= 1.3) {
550 GetReq(GLXGetFBConfigs
, fb_req
);
551 fb_req
->reqType
= priv
->majorOpcode
;
552 fb_req
->glxCode
= X_GLXGetFBConfigs
;
553 fb_req
->screen
= screen
;
555 else if (strstr(psc
->serverGLXexts
, "GLX_SGIX_fbconfig") != NULL
) {
556 GetReqExtra(GLXVendorPrivateWithReply
,
557 sz_xGLXGetFBConfigsSGIXReq
+
558 sz_xGLXVendorPrivateWithReplyReq
, vpreq
);
559 sgi_req
= (xGLXGetFBConfigsSGIXReq
*) vpreq
;
560 sgi_req
->reqType
= priv
->majorOpcode
;
561 sgi_req
->glxCode
= X_GLXVendorPrivateWithReply
;
562 sgi_req
->vendorCode
= X_GLXvop_GetFBConfigsSGIX
;
563 sgi_req
->screen
= screen
;
568 if (!_XReply(dpy
, (xReply
*) & reply
, 0, False
))
571 psc
->configs
= createConfigsFromProperties(dpy
,
573 reply
.numAttribs
* 2,
578 return psc
->configs
!= NULL
;
582 AllocAndFetchScreenConfigs(Display
* dpy
, __GLXdisplayPrivate
* priv
)
584 __GLXscreenConfigs
*psc
;
588 ** First allocate memory for the array of per screen configs.
590 screens
= ScreenCount(dpy
);
591 psc
= (__GLXscreenConfigs
*) Xmalloc(screens
* sizeof(__GLXscreenConfigs
));
595 memset(psc
, 0, screens
* sizeof(__GLXscreenConfigs
));
596 priv
->screenConfigs
= psc
;
598 priv
->serverGLXversion
=
599 __glXQueryServerString(dpy
, priv
->majorOpcode
, 0, GLX_VERSION
);
600 if (priv
->serverGLXversion
== NULL
) {
601 FreeScreenConfigs(priv
);
605 for (i
= 0; i
< screens
; i
++, psc
++) {
606 getFBConfigs(dpy
, priv
, i
);
607 getVisualConfigs(dpy
, priv
, i
);
617 _X_HIDDEN __GLXdisplayPrivate
*
618 __glXInitialize(Display
* dpy
)
620 XExtDisplayInfo
*info
= __glXFindDisplay(dpy
);
621 XExtData
**privList
, *private, *found
;
622 __GLXdisplayPrivate
*dpyPriv
;
623 XEDataObject dataObj
;
626 if (!XextHasExtension(info
))
629 /* See if a display private already exists. If so, return it */
630 dataObj
.display
= dpy
;
631 privList
= XEHeadOfExtensionList(dataObj
);
632 found
= XFindOnExtensionList(privList
, info
->codes
->extension
);
634 return (__GLXdisplayPrivate
*) found
->private_data
;
636 /* See if the versions are compatible */
637 if (!QueryVersion(dpy
, info
->codes
->major_opcode
, &major
, &minor
))
641 ** Allocate memory for all the pieces needed for this buffer.
643 private = (XExtData
*) Xmalloc(sizeof(XExtData
));
646 dpyPriv
= (__GLXdisplayPrivate
*) Xcalloc(1, sizeof(__GLXdisplayPrivate
));
653 ** Init the display private and then read in the screen config
654 ** structures from the server.
656 dpyPriv
->majorOpcode
= info
->codes
->major_opcode
;
657 dpyPriv
->majorVersion
= major
;
658 dpyPriv
->minorVersion
= minor
;
661 dpyPriv
->serverGLXvendor
= NULL
;
662 dpyPriv
->serverGLXversion
= NULL
;
664 if (!AllocAndFetchScreenConfigs(dpy
, dpyPriv
)) {
671 ** Fill in the private structure. This is the actual structure that
672 ** hangs off of the Display structure. Our private structure is
673 ** referred to by this structure. Got that?
675 private->number
= info
->codes
->extension
;
677 private->free_private
= __glXFreeDisplayPrivate
;
678 private->private_data
= (char *) dpyPriv
;
679 XAddToExtensionList(privList
, private);