2004-10-25 22:09:16 +01:00
|
|
|
/*
|
Update to SGI FreeB 2.0.
Under the terms of version 1.1, "once Covered Code has been published
under a particular version of the License, Recipient may, for the
duration of the License, continue to use it under the terms of that
version, or choose to use such Covered Code under the terms of any
subsequent version published by SGI."
FreeB 2.0 license refers to "dates of first publication". They are here
taken to be 1991-2000, as noted in the original license text:
** Original Code. The Original Code is: OpenGL Sample Implementation,
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
** Copyright in any portions created by third parties is as indicated
** elsewhere herein. All Rights Reserved.
Official FreeB 2.0 text:
http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf
As always, this code has not been tested for conformance with the OpenGL
specification. OpenGL conformance testing is available from
http://khronos.org/ and is required for use of the OpenGL logo in
product advertising and promotion.
2008-09-19 22:16:53 +01:00
|
|
|
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
|
|
|
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice including the dates of first publication and
|
|
|
|
* either this permission notice or a reference to
|
|
|
|
* http://oss.sgi.com/projects/FreeB/
|
|
|
|
* shall be included in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*
|
|
|
|
* Except as contained in this notice, the name of Silicon Graphics, Inc.
|
|
|
|
* shall not be used in advertising or otherwise to promote the sale, use or
|
|
|
|
* other dealings in this Software without prior written authorization from
|
|
|
|
* Silicon Graphics, Inc.
|
|
|
|
*/
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \file glxcmds.c
|
|
|
|
* Client-side GLX interface.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "glxclient.h"
|
|
|
|
#include "glapi.h"
|
|
|
|
#include "glxextensions.h"
|
2010-12-26 10:24:13 +00:00
|
|
|
#include "indirect.h"
|
2011-12-08 00:13:02 +00:00
|
|
|
#include "glx_error.h"
|
2008-04-18 15:28:34 +01:00
|
|
|
|
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
Fix build of appleglx
Define GLX_USE_APPLEGL, as config/darwin used to, to turn on specific code to
use the applegl direct renderer
Convert src/glx/apple/Makefile to automake
Since the applegl libGL is now built by linking libappleglx into libGL, rather
than by linking selected files into a special libGL:
- Remove duplicate code in apple/glxreply.c and apple/apple_glx.c. This makes
apple/glxreply.c empty, so remove it
- Some indirect rendering code is already guarded by !GLX_USE_APPLEGL, but we
need to add those guards to indirect_glx.c, indirect_init.c (via it's
generator), render2.c and vertarr.c so they don't generate anything
Fix and update various includes
glapi_gentable.c (which is only used on darwin), should be included in shared
glapi as well, to provide _glapi_create_table_from_handle()
Note that neither swrast nor indirect is supported in the APPLEGL path at the
moment, which makes things more complex than they need to be. More untangling
is needed to allow that
v2: Correct apple/Makefile.am for srcdir != builddir
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
2014-05-12 10:47:07 +01:00
|
|
|
#include "apple/apple_glx_context.h"
|
|
|
|
#include "apple/apple_glx.h"
|
2017-12-02 17:05:43 +00:00
|
|
|
#include "util/debug.h"
|
2010-04-01 19:01:31 +01:00
|
|
|
#else
|
2018-12-14 13:20:10 +00:00
|
|
|
#ifndef GLX_USE_WINDOWSGL
|
2008-04-18 15:28:34 +01:00
|
|
|
#include <X11/extensions/xf86vmode.h>
|
2018-12-11 16:20:40 +00:00
|
|
|
#endif /* GLX_USE_WINDOWSGL */
|
2010-04-21 12:58:54 +01:00
|
|
|
#endif
|
2010-04-02 09:35:19 +01:00
|
|
|
#endif
|
2020-09-09 20:54:21 +01:00
|
|
|
#include <limits.h>
|
2008-11-04 09:59:39 +00:00
|
|
|
#include <X11/Xlib-xcb.h>
|
|
|
|
#include <xcb/xcb.h>
|
|
|
|
#include <xcb/glx.h>
|
2016-03-03 17:43:53 +00:00
|
|
|
#include "GL/mesa_glinterop.h"
|
2008-11-04 09:59:39 +00:00
|
|
|
|
2009-11-06 22:52:49 +00:00
|
|
|
static const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
|
2004-10-25 22:09:16 +01:00
|
|
|
static const char __glXGLXClientVersion[] = "1.4";
|
2007-01-07 13:12:01 +00:00
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2007-01-07 13:12:01 +00:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/**
|
|
|
|
* Get the __DRIdrawable for the drawable associated with a GLXContext
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2021-05-03 13:38:02 +01:00
|
|
|
* \param dpy The display associated with \c drawable.
|
2004-10-25 22:09:16 +01:00
|
|
|
* \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
|
2007-01-07 13:12:01 +00:00
|
|
|
* \param scrn_num If non-NULL, the drawables screen is stored there
|
2004-10-25 22:09:16 +01:00
|
|
|
* \returns A pointer to the context's __DRIdrawable on success, or NULL if
|
|
|
|
* the drawable is not associated with a direct-rendering context.
|
|
|
|
*/
|
DRI interface changes and DRI2 direct rendering support.
Add DRI2 direct rendering support to libGL and add DRI2 client side
protocol code. Extend the GLX 1.3 create drawable functions in
glx_pbuffer.c to call into the DRI driver when possible.
Introduce __DRIconfig, opaque struct that represents a DRI driver
configuration. Get's rid of the open coded __GLcontextModes in the
DRI driver interface and the context modes create and destroy
functions that the loader was requires to provide. glcore.h is no
longer part of the DRI driver interface. The DRI config is GL binding
agnostic, that is, not specific to GLX, EGL or other bindings.
The core API is now also an extension, and the driver exports a list
of extensions as the symbol __driDriverExtensions, which the loader
must dlsym() for. The list of extension will always include the DRI
core extension, which allows creating and manipulating DRI screens,
drawables and contexts. The DRI legacy extension, when available,
provides alternative entry points for creating the DRI objects that
work with the XF86DRI infrastructure.
Change DRI2 client code to not use drm drawables or contexts. We
never used drm_drawable_t's and the only use for drm_context_t was as
a unique identifier when taking the lock. We now just allocate a
unique lock ID out of the DRILock sarea block. Once we get rid of the
lock entirely, we can drop this hack.
Change the interface between dri_util.c and the drivers, so that the
drivers now export the DriverAPI struct as driDriverAPI instead of the
InitScreen entry point. This lets us avoid dlsym()'ing for the DRI2
init screen function to see if DRI2 is supported by the driver.
2008-03-26 23:26:59 +00:00
|
|
|
_X_HIDDEN __GLXDRIdrawable *
|
2021-05-03 13:38:02 +01:00
|
|
|
GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
2009-08-12 11:41:22 +01:00
|
|
|
__GLXDRIdrawable *pdraw;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (priv == NULL)
|
|
|
|
return NULL;
|
DRI interface changes and DRI2 direct rendering support.
Add DRI2 direct rendering support to libGL and add DRI2 client side
protocol code. Extend the GLX 1.3 create drawable functions in
glx_pbuffer.c to call into the DRI driver when possible.
Introduce __DRIconfig, opaque struct that represents a DRI driver
configuration. Get's rid of the open coded __GLcontextModes in the
DRI driver interface and the context modes create and destroy
functions that the loader was requires to provide. glcore.h is no
longer part of the DRI driver interface. The DRI config is GL binding
agnostic, that is, not specific to GLX, EGL or other bindings.
The core API is now also an extension, and the driver exports a list
of extensions as the symbol __driDriverExtensions, which the loader
must dlsym() for. The list of extension will always include the DRI
core extension, which allows creating and manipulating DRI screens,
drawables and contexts. The DRI legacy extension, when available,
provides alternative entry points for creating the DRI objects that
work with the XF86DRI infrastructure.
Change DRI2 client code to not use drm drawables or contexts. We
never used drm_drawable_t's and the only use for drm_context_t was as
a unique identifier when taking the lock. We now just allocate a
unique lock ID out of the DRILock sarea block. Once we get rid of the
lock entirely, we can drop this hack.
Change the interface between dri_util.c and the drivers, so that the
drivers now export the DriverAPI struct as driDriverAPI instead of the
InitScreen entry point. This lets us avoid dlsym()'ing for the DRI2
init screen function to see if DRI2 is supported by the driver.
2008-03-26 23:26:59 +00:00
|
|
|
|
2010-07-23 03:36:37 +01:00
|
|
|
if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0)
|
2010-07-20 02:15:50 +01:00
|
|
|
return pdraw;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
2007-01-07 13:12:01 +00:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
|
|
|
|
2011-05-06 18:31:24 +01:00
|
|
|
_X_HIDDEN struct glx_drawable *
|
2021-05-03 13:38:02 +01:00
|
|
|
GetGLXDrawable(Display *dpy, GLXDrawable drawable)
|
2011-05-06 18:31:24 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
2011-05-06 18:31:24 +01:00
|
|
|
struct glx_drawable *glxDraw;
|
|
|
|
|
|
|
|
if (priv == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0)
|
|
|
|
return glxDraw;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_X_HIDDEN int
|
2021-05-03 13:38:02 +01:00
|
|
|
InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable,
|
|
|
|
GLXDrawable drawable)
|
2011-05-06 18:31:24 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
|
|
|
|
|
|
|
if (!priv)
|
|
|
|
return -1;
|
|
|
|
|
2011-05-06 18:31:24 +01:00
|
|
|
glxDraw->xDrawable = xDrawable;
|
|
|
|
glxDraw->drawable = drawable;
|
|
|
|
glxDraw->lastEventSbc = 0;
|
|
|
|
glxDraw->eventSbcWrap = 0;
|
|
|
|
|
|
|
|
return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw);
|
|
|
|
}
|
|
|
|
|
|
|
|
_X_HIDDEN void
|
2021-05-03 13:38:02 +01:00
|
|
|
DestroyGLXDrawable(Display *dpy, GLXDrawable drawable)
|
2011-05-06 18:31:24 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
2011-05-06 18:31:24 +01:00
|
|
|
struct glx_drawable *glxDraw;
|
|
|
|
|
2021-05-03 13:38:02 +01:00
|
|
|
if (!priv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
glxDraw = GetGLXDrawable(dpy, drawable);
|
2011-05-06 18:31:24 +01:00
|
|
|
__glxHashDelete(priv->glXDrawHash, drawable);
|
|
|
|
free(glxDraw);
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the GLX per-screen data structure associated with a GLX context.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \param dpy Display for which the GLX per-screen information is to be
|
|
|
|
* retrieved.
|
|
|
|
* \param scrn Screen on \c dpy for which the GLX per-screen information is
|
|
|
|
* to be retrieved.
|
|
|
|
* \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
|
|
|
|
* specify a valid GLX screen, or NULL otherwise.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \todo Should this function validate that \c scrn is within the screen
|
|
|
|
* number range for \c dpy?
|
|
|
|
*/
|
|
|
|
|
2011-11-30 18:33:37 +00:00
|
|
|
_X_HIDDEN struct glx_screen *
|
2009-08-12 11:41:22 +01:00
|
|
|
GetGLXScreenConfigs(Display * dpy, int scrn)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *const priv = __glXInitialize(dpy);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return (priv
|
2010-07-28 15:28:43 +01:00
|
|
|
&& priv->screens !=
|
|
|
|
NULL) ? priv->screens[scrn] : NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-07-28 16:16:00 +01:00
|
|
|
GetGLXPrivScreenConfig(Display * dpy, int scrn, struct glx_display ** ppriv,
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen ** ppsc)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Initialize the extension, if needed . This has the added value
|
|
|
|
* of initializing/allocating the display private
|
|
|
|
*/
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (dpy == NULL) {
|
|
|
|
return GLX_NO_EXTENSION;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
*ppriv = __glXInitialize(dpy);
|
|
|
|
if (*ppriv == NULL) {
|
|
|
|
return GLX_NO_EXTENSION;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Check screen number to see if its valid */
|
|
|
|
if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
|
|
|
|
return GLX_BAD_SCREEN;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Check to see if the GL is supported on this screen */
|
2010-07-28 15:28:43 +01:00
|
|
|
*ppsc = (*ppriv)->screens[scrn];
|
2013-11-18 07:34:52 +00:00
|
|
|
if ((*ppsc)->configs == NULL && (*ppsc)->visuals == NULL) {
|
2009-08-12 11:41:22 +01:00
|
|
|
/* No support for GL on this screen regardless of visual */
|
|
|
|
return GLX_BAD_VISUAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Success;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if a \c GLXFBConfig supplied by the application is valid.
|
|
|
|
*
|
|
|
|
* \param dpy Application supplied \c Display pointer.
|
|
|
|
* \param config Application supplied \c GLXFBConfig.
|
|
|
|
*
|
|
|
|
* \returns If the \c GLXFBConfig is valid, the a pointer to the matching
|
2010-07-28 15:07:52 +01:00
|
|
|
* \c struct glx_config structure is returned. Otherwise, \c NULL
|
2004-10-25 22:09:16 +01:00
|
|
|
* is returned.
|
|
|
|
*/
|
2010-07-28 15:07:52 +01:00
|
|
|
static struct glx_config *
|
|
|
|
ValidateGLXFBConfig(Display * dpy, GLXFBConfig fbconfig)
|
2009-08-12 11:41:22 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *const priv = __glXInitialize(dpy);
|
2010-07-28 15:07:52 +01:00
|
|
|
int num_screens = ScreenCount(dpy);
|
2009-08-12 11:41:22 +01:00
|
|
|
unsigned i;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config;
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
if (priv != NULL) {
|
|
|
|
for (i = 0; i < num_screens; i++) {
|
2010-07-28 15:28:43 +01:00
|
|
|
for (config = priv->screens[i]->configs; config != NULL;
|
2010-07-28 15:07:52 +01:00
|
|
|
config = config->next) {
|
|
|
|
if (config == (struct glx_config *) fbconfig) {
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
}
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
}
|
2008-10-15 04:07:42 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2013-07-18 22:19:38 +01:00
|
|
|
/**
|
|
|
|
* Verifies context's GLX_RENDER_TYPE value with config.
|
|
|
|
*
|
|
|
|
* \param config GLX FBConfig which will support the returned renderType.
|
|
|
|
* \param renderType The context render type to be verified.
|
|
|
|
* \return True if the value of context renderType was approved, or 0 if no
|
|
|
|
* valid value was found.
|
|
|
|
*/
|
|
|
|
Bool
|
|
|
|
validate_renderType_against_config(const struct glx_config *config,
|
|
|
|
int renderType)
|
|
|
|
{
|
2017-11-07 16:36:51 +00:00
|
|
|
/* GLX_EXT_no_config_context supports any render type */
|
|
|
|
if (!config)
|
2017-11-14 20:13:06 +00:00
|
|
|
return renderType == GLX_DONT_CARE;
|
2017-11-07 16:36:51 +00:00
|
|
|
|
|
|
|
switch (renderType) {
|
|
|
|
case GLX_RGBA_TYPE:
|
|
|
|
return (config->renderType & GLX_RGBA_BIT) != 0;
|
|
|
|
case GLX_COLOR_INDEX_TYPE:
|
|
|
|
return (config->renderType & GLX_COLOR_INDEX_BIT) != 0;
|
|
|
|
case GLX_RGBA_FLOAT_TYPE_ARB:
|
|
|
|
return (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) != 0;
|
|
|
|
case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
|
|
|
|
return (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) != 0;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2013-07-18 22:19:38 +01:00
|
|
|
}
|
|
|
|
|
2010-07-23 02:24:14 +01:00
|
|
|
_X_HIDDEN Bool
|
2010-07-28 16:16:00 +01:00
|
|
|
glx_context_init(struct glx_context *gc,
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc, struct glx_config *config)
|
2010-07-23 02:24:14 +01:00
|
|
|
{
|
|
|
|
gc->majorOpcode = __glXSetupForCommand(psc->display->dpy);
|
|
|
|
if (!gc->majorOpcode)
|
2013-06-26 20:42:51 +01:00
|
|
|
return False;
|
2010-07-23 02:24:14 +01:00
|
|
|
|
|
|
|
gc->screen = psc->scr;
|
|
|
|
gc->psc = psc;
|
2010-07-28 15:07:52 +01:00
|
|
|
gc->config = config;
|
2010-07-23 02:24:14 +01:00
|
|
|
gc->isDirect = GL_TRUE;
|
2010-07-28 20:33:09 +01:00
|
|
|
gc->currentContextTag = -1;
|
2010-07-23 02:24:14 +01:00
|
|
|
|
2017-11-14 20:13:06 +00:00
|
|
|
if (!config)
|
|
|
|
gc->renderType = GLX_DONT_CARE;
|
|
|
|
|
2013-06-26 20:42:51 +01:00
|
|
|
return True;
|
2010-07-23 02:24:14 +01:00
|
|
|
}
|
|
|
|
|
glx: Demand success from CreateContext requests (v2)
GLXCreate{,New}Context, like most X resource creation requests, does not
emit a reply and therefore is emitted into the X stream asynchronously.
However, unlike most resource creation requests, the GLXContext we
return is a handle to library state instead of an XID. So if context
creation fails for any reason - say, the server doesn't support indirect
contexts - then we will fail in strange places for strange reasons.
We could make every GLX entrypoint robust against half-created contexts,
or we could just verify that context creation worked. Reuse the
__glXIsDirect code to do this, as a cheap way of verifying that the
XID is real.
glXCreateContextAttribsARB solves this by using the _checked version of
the xcb command, so effectively this change makes the classic context
creation paths as robust as CreateContextAttribs.
v2: Better use of Bool, check that error != NULL first (Olivier Fourdan)
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2018-08-07 21:55:37 +01:00
|
|
|
/**
|
|
|
|
* Determine if a context uses direct rendering.
|
|
|
|
*
|
|
|
|
* \param dpy Display where the context was created.
|
|
|
|
* \param contextID ID of the context to be tested.
|
2020-12-01 15:53:41 +00:00
|
|
|
* \param error Out parameter, set to True on error if not NULL,
|
|
|
|
* otherwise raise the error to the application.
|
glx: Demand success from CreateContext requests (v2)
GLXCreate{,New}Context, like most X resource creation requests, does not
emit a reply and therefore is emitted into the X stream asynchronously.
However, unlike most resource creation requests, the GLXContext we
return is a handle to library state instead of an XID. So if context
creation fails for any reason - say, the server doesn't support indirect
contexts - then we will fail in strange places for strange reasons.
We could make every GLX entrypoint robust against half-created contexts,
or we could just verify that context creation worked. Reuse the
__glXIsDirect code to do this, as a cheap way of verifying that the
XID is real.
glXCreateContextAttribsARB solves this by using the _checked version of
the xcb command, so effectively this change makes the classic context
creation paths as robust as CreateContextAttribs.
v2: Better use of Bool, check that error != NULL first (Olivier Fourdan)
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2018-08-07 21:55:37 +01:00
|
|
|
*
|
|
|
|
* \returns \c True if the context is direct rendering or not.
|
|
|
|
*/
|
|
|
|
static Bool
|
|
|
|
__glXIsDirect(Display * dpy, GLXContextID contextID, Bool *error)
|
|
|
|
{
|
|
|
|
xcb_connection_t *c;
|
|
|
|
xcb_generic_error_t *err;
|
|
|
|
xcb_glx_is_direct_reply_t *reply;
|
|
|
|
Bool is_direct;
|
|
|
|
|
|
|
|
c = XGetXCBConnection(dpy);
|
|
|
|
reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err);
|
|
|
|
is_direct = (reply != NULL && reply->is_direct) ? True : False;
|
|
|
|
|
|
|
|
if (err != NULL) {
|
|
|
|
if (error)
|
|
|
|
*error = True;
|
2020-12-01 15:53:41 +00:00
|
|
|
else
|
|
|
|
__glXSendErrorForXcb(dpy, err);
|
glx: Demand success from CreateContext requests (v2)
GLXCreate{,New}Context, like most X resource creation requests, does not
emit a reply and therefore is emitted into the X stream asynchronously.
However, unlike most resource creation requests, the GLXContext we
return is a handle to library state instead of an XID. So if context
creation fails for any reason - say, the server doesn't support indirect
contexts - then we will fail in strange places for strange reasons.
We could make every GLX entrypoint robust against half-created contexts,
or we could just verify that context creation worked. Reuse the
__glXIsDirect code to do this, as a cheap way of verifying that the
XID is real.
glXCreateContextAttribsARB solves this by using the _checked version of
the xcb command, so effectively this change makes the classic context
creation paths as robust as CreateContextAttribs.
v2: Better use of Bool, check that error != NULL first (Olivier Fourdan)
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2018-08-07 21:55:37 +01:00
|
|
|
free(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(reply);
|
|
|
|
|
|
|
|
return is_direct;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/**
|
2011-04-29 21:30:50 +01:00
|
|
|
* Create a new context.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \param renderType For FBConfigs, what is the rendering type?
|
|
|
|
*/
|
|
|
|
|
|
|
|
static GLXContext
|
2011-04-29 21:30:50 +01:00
|
|
|
CreateContext(Display *dpy, int generic_id, struct glx_config *config,
|
|
|
|
GLXContext shareList_user, Bool allowDirect,
|
2022-07-01 16:50:04 +01:00
|
|
|
unsigned code, int renderType)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-08-19 19:06:21 +01:00
|
|
|
struct glx_context *gc;
|
|
|
|
struct glx_screen *psc;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *shareList = (struct glx_context *) shareList_user;
|
2009-08-12 11:41:22 +01:00
|
|
|
if (dpy == NULL)
|
|
|
|
return NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2022-07-01 16:50:04 +01:00
|
|
|
psc = GetGLXScreenConfigs(dpy, config->screen);
|
2010-08-19 19:06:21 +01:00
|
|
|
if (psc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2010-02-05 01:06:18 +00:00
|
|
|
if (generic_id == None)
|
2009-08-12 11:41:22 +01:00
|
|
|
return NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2021-10-07 11:14:44 +01:00
|
|
|
/* Some application may request an indirect context but we may want to force a direct
|
|
|
|
* one because Xorg only allows indirect contexts if they were enabled.
|
|
|
|
*/
|
|
|
|
if (!allowDirect &&
|
|
|
|
psc->force_direct_context) {
|
|
|
|
allowDirect = 1;
|
|
|
|
}
|
|
|
|
|
2010-07-23 21:15:31 +01:00
|
|
|
gc = NULL;
|
2011-06-05 23:50:55 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
|
|
|
gc = applegl_create_context(psc, config, shareList, renderType);
|
|
|
|
#else
|
2010-07-23 21:15:31 +01:00
|
|
|
if (allowDirect && psc->vtable->create_context)
|
2010-07-28 15:07:52 +01:00
|
|
|
gc = psc->vtable->create_context(psc, config, shareList, renderType);
|
2010-07-23 02:24:14 +01:00
|
|
|
if (!gc)
|
2010-07-28 15:07:52 +01:00
|
|
|
gc = indirect_create_context(psc, config, shareList, renderType);
|
2011-06-05 23:50:55 +01:00
|
|
|
#endif
|
2010-07-23 02:24:14 +01:00
|
|
|
if (!gc)
|
|
|
|
return NULL;
|
2010-05-21 15:36:56 +01:00
|
|
|
|
2010-02-05 00:46:46 +00:00
|
|
|
LockDisplay(dpy);
|
|
|
|
switch (code) {
|
|
|
|
case X_GLXCreateContext: {
|
|
|
|
xGLXCreateContextReq *req;
|
|
|
|
|
|
|
|
/* Send the glXCreateContext request */
|
|
|
|
GetReq(GLXCreateContext, req);
|
|
|
|
req->reqType = gc->majorOpcode;
|
|
|
|
req->glxCode = X_GLXCreateContext;
|
|
|
|
req->context = gc->xid = XAllocID(dpy);
|
2010-02-05 01:06:18 +00:00
|
|
|
req->visual = generic_id;
|
2022-07-01 16:50:04 +01:00
|
|
|
req->screen = config->screen;
|
2010-02-05 00:46:46 +00:00
|
|
|
req->shareList = shareList ? shareList->xid : None;
|
2010-07-28 20:33:09 +01:00
|
|
|
req->isDirect = gc->isDirect;
|
2010-02-05 00:46:46 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-02-05 00:46:46 +00:00
|
|
|
case X_GLXCreateNewContext: {
|
|
|
|
xGLXCreateNewContextReq *req;
|
|
|
|
|
|
|
|
/* Send the glXCreateNewContext request */
|
|
|
|
GetReq(GLXCreateNewContext, req);
|
|
|
|
req->reqType = gc->majorOpcode;
|
|
|
|
req->glxCode = X_GLXCreateNewContext;
|
|
|
|
req->context = gc->xid = XAllocID(dpy);
|
2010-02-05 01:06:18 +00:00
|
|
|
req->fbconfig = generic_id;
|
2022-07-01 16:50:04 +01:00
|
|
|
req->screen = config->screen;
|
2010-02-05 00:46:46 +00:00
|
|
|
req->renderType = renderType;
|
|
|
|
req->shareList = shareList ? shareList->xid : None;
|
2010-07-28 20:33:09 +01:00
|
|
|
req->isDirect = gc->isDirect;
|
2010-02-05 00:46:46 +00:00
|
|
|
break;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2010-02-05 00:28:52 +00:00
|
|
|
|
2010-02-05 00:46:46 +00:00
|
|
|
case X_GLXvop_CreateContextWithConfigSGIX: {
|
|
|
|
xGLXVendorPrivateWithReplyReq *vpreq;
|
|
|
|
xGLXCreateContextWithConfigSGIXReq *req;
|
|
|
|
|
|
|
|
/* Send the glXCreateNewContext request */
|
|
|
|
GetReqExtra(GLXVendorPrivateWithReply,
|
|
|
|
sz_xGLXCreateContextWithConfigSGIXReq -
|
|
|
|
sz_xGLXVendorPrivateWithReplyReq, vpreq);
|
|
|
|
req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
|
|
|
|
req->reqType = gc->majorOpcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivateWithReply;
|
|
|
|
req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
|
|
|
|
req->context = gc->xid = XAllocID(dpy);
|
2010-02-05 01:06:18 +00:00
|
|
|
req->fbconfig = generic_id;
|
2022-07-01 16:50:04 +01:00
|
|
|
req->screen = config->screen;
|
2010-02-05 00:46:46 +00:00
|
|
|
req->renderType = renderType;
|
|
|
|
req->shareList = shareList ? shareList->xid : None;
|
2010-07-28 20:33:09 +01:00
|
|
|
req->isDirect = gc->isDirect;
|
2010-02-05 00:46:46 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-02-05 00:28:52 +00:00
|
|
|
|
2010-02-05 00:46:46 +00:00
|
|
|
default:
|
|
|
|
/* What to do here? This case is the sign of an internal error. It
|
|
|
|
* should never be reachable.
|
|
|
|
*/
|
|
|
|
break;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-02-05 00:46:46 +00:00
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2011-12-08 23:03:19 +00:00
|
|
|
gc->share_xid = shareList ? shareList->xid : None;
|
2010-02-05 00:46:46 +00:00
|
|
|
gc->imported = GL_FALSE;
|
2009-09-29 17:24:27 +01:00
|
|
|
|
glx: Demand success from CreateContext requests (v2)
GLXCreate{,New}Context, like most X resource creation requests, does not
emit a reply and therefore is emitted into the X stream asynchronously.
However, unlike most resource creation requests, the GLXContext we
return is a handle to library state instead of an XID. So if context
creation fails for any reason - say, the server doesn't support indirect
contexts - then we will fail in strange places for strange reasons.
We could make every GLX entrypoint robust against half-created contexts,
or we could just verify that context creation worked. Reuse the
__glXIsDirect code to do this, as a cheap way of verifying that the
XID is real.
glXCreateContextAttribsARB solves this by using the _checked version of
the xcb command, so effectively this change makes the classic context
creation paths as robust as CreateContextAttribs.
v2: Better use of Bool, check that error != NULL first (Olivier Fourdan)
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2018-08-07 21:55:37 +01:00
|
|
|
/* Unlike most X resource creation requests, we're about to return a handle
|
|
|
|
* with client-side state, not just an XID. To simplify error handling
|
|
|
|
* elsewhere in libGL, force a round-trip here to ensure the CreateContext
|
|
|
|
* request above succeeded.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
Bool error = False;
|
|
|
|
int isDirect = __glXIsDirect(dpy, gc->xid, &error);
|
|
|
|
|
|
|
|
if (error != False || isDirect != gc->isDirect) {
|
|
|
|
gc->vtable->destroy(gc);
|
|
|
|
gc = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-28 16:16:00 +01:00
|
|
|
return (GLXContext) gc;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXContext
|
2009-08-12 11:41:22 +01:00
|
|
|
glXCreateContext(Display * dpy, XVisualInfo * vis,
|
|
|
|
GLXContext shareList, Bool allowDirect)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = NULL;
|
2013-07-17 12:49:14 +01:00
|
|
|
int renderType = GLX_RGBA_TYPE;
|
2010-02-05 00:59:10 +00:00
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL)
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *const psc = GetGLXScreenConfigs(dpy, vis->screen);
|
2010-02-05 00:59:10 +00:00
|
|
|
|
2014-02-07 12:43:57 +00:00
|
|
|
if (psc)
|
|
|
|
config = glx_config_find_visual(psc->visuals, vis->visualid);
|
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
if (config == NULL) {
|
2017-11-14 20:13:02 +00:00
|
|
|
__glXSendError(dpy, BadValue, vis->visualid, X_GLXCreateContext, True);
|
2010-02-05 00:59:10 +00:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2013-07-17 12:49:17 +01:00
|
|
|
/* Choose the context render type based on DRI config values. It is
|
|
|
|
* unusual to set this type from config, but we have no other choice, as
|
|
|
|
* this old API does not provide renderType parameter.
|
|
|
|
*/
|
|
|
|
if (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) {
|
|
|
|
renderType = GLX_RGBA_FLOAT_TYPE_ARB;
|
|
|
|
} else if (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) {
|
|
|
|
renderType = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
|
|
|
|
} else if (config->renderType & GLX_RGBA_BIT) {
|
|
|
|
renderType = GLX_RGBA_TYPE;
|
|
|
|
} else if (config->renderType & GLX_COLOR_INDEX_BIT) {
|
|
|
|
renderType = GLX_COLOR_INDEX_TYPE;
|
|
|
|
}
|
2010-02-05 00:59:10 +00:00
|
|
|
#endif
|
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
return CreateContext(dpy, vis->visualid, config, shareList, allowDirect,
|
2022-07-01 16:50:04 +01:00
|
|
|
X_GLXCreateContext, renderType);
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2011-12-07 21:31:27 +00:00
|
|
|
static void
|
2010-07-23 04:45:18 +01:00
|
|
|
glx_send_destroy_context(Display *dpy, XID xid)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-23 04:45:18 +01:00
|
|
|
CARD8 opcode = __glXSetupForCommand(dpy);
|
|
|
|
xGLXDestroyContextReq *req;
|
|
|
|
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXDestroyContext, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXDestroyContext;
|
|
|
|
req->context = xid;
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
|
|
|
}
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** Destroy the named context
|
|
|
|
*/
|
2011-06-02 21:29:59 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2011-06-02 21:29:59 +01:00
|
|
|
glXDestroyContext(Display * dpy, GLXContext ctx)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = (struct glx_context *) ctx;
|
|
|
|
|
2011-12-07 21:31:27 +00:00
|
|
|
if (gc == NULL || gc->xid == None)
|
2009-08-12 11:41:22 +01:00
|
|
|
return;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
__glXLock();
|
2011-12-07 21:31:27 +00:00
|
|
|
if (!gc->imported)
|
|
|
|
glx_send_destroy_context(dpy, gc->xid);
|
|
|
|
|
2009-10-23 01:19:01 +01:00
|
|
|
if (gc->currentDpy) {
|
|
|
|
/* This context is bound to some thread. According to the man page,
|
|
|
|
* we should not actually delete the context until it's unbound.
|
|
|
|
* Note that we set gc->xid = None above. In MakeContextCurrent()
|
|
|
|
* we check for that and delete the context there.
|
|
|
|
*/
|
2010-07-23 04:45:18 +01:00
|
|
|
gc->xid = None;
|
2011-12-07 21:31:27 +00:00
|
|
|
} else {
|
|
|
|
gc->vtable->destroy(gc);
|
2009-10-23 01:19:01 +01:00
|
|
|
}
|
2010-07-23 04:45:18 +01:00
|
|
|
__glXUnlock();
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
2004-12-15 17:18:06 +00:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** Return the major and minor version #s for the GLX extension
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC Bool
|
2009-08-12 11:41:22 +01:00
|
|
|
glXQueryVersion(Display * dpy, int *major, int *minor)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Init the extension. This fetches the major and minor version. */
|
|
|
|
priv = __glXInitialize(dpy);
|
|
|
|
if (!priv)
|
2013-06-26 20:42:51 +01:00
|
|
|
return False;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (major)
|
2021-04-22 18:10:44 +01:00
|
|
|
*major = GLX_MAJOR_VERSION;
|
2009-08-12 11:41:22 +01:00
|
|
|
if (minor)
|
|
|
|
*minor = priv->minorVersion;
|
2013-06-26 20:42:51 +01:00
|
|
|
return True;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-04-22 11:33:17 +01:00
|
|
|
** Query the existence of the GLX extension
|
2004-10-25 22:09:16 +01:00
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC Bool
|
2009-08-12 11:41:22 +01:00
|
|
|
glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
|
|
|
|
{
|
|
|
|
int major_op, erb, evb;
|
|
|
|
Bool rv;
|
|
|
|
|
|
|
|
rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
|
|
|
|
if (rv) {
|
|
|
|
if (errorBase)
|
|
|
|
*errorBase = erb;
|
|
|
|
if (eventBase)
|
|
|
|
*eventBase = evb;
|
|
|
|
}
|
|
|
|
return rv;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-07-23 03:24:00 +01:00
|
|
|
** Put a barrier in the token stream that forces the GL to finish its
|
|
|
|
** work before X can proceed.
|
2004-10-25 22:09:16 +01:00
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2010-07-23 03:24:00 +01:00
|
|
|
glXWaitGL(void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2017-11-14 20:13:01 +00:00
|
|
|
if (gc->vtable->wait_gl)
|
2010-07-23 03:24:00 +01:00
|
|
|
gc->vtable->wait_gl(gc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Put a barrier in the token stream that forces X to finish its
|
|
|
|
** work before GL can proceed.
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2010-07-23 03:24:00 +01:00
|
|
|
glXWaitX(void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2017-11-14 20:13:01 +00:00
|
|
|
if (gc->vtable->wait_x)
|
2010-07-23 03:24:00 +01:00
|
|
|
gc->vtable->wait_x(gc);
|
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2010-07-23 03:24:00 +01:00
|
|
|
glXUseXFont(Font font, int first, int count, int listBase)
|
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2021-03-11 18:41:40 +00:00
|
|
|
xGLXUseXFontReq *req;
|
|
|
|
Display *dpy = gc->currentDpy;
|
2010-07-23 03:24:00 +01:00
|
|
|
|
2021-03-11 18:41:40 +00:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
|
|
|
if (gc->isDirect) {
|
|
|
|
DRI_glXUseXFont(gc, font, first, count, listBase);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Flush any pending commands out */
|
|
|
|
__glXFlushRenderBuffer(gc, gc->pc);
|
|
|
|
|
|
|
|
/* Send the glXUseFont request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXUseXFont, req);
|
|
|
|
req->reqType = gc->majorOpcode;
|
|
|
|
req->glxCode = X_GLXUseXFont;
|
|
|
|
req->contextTag = gc->currentContextTag;
|
|
|
|
req->font = font;
|
|
|
|
req->first = first;
|
|
|
|
req->count = count;
|
|
|
|
req->listBase = listBase;
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Copy the source context to the destination context using the
|
|
|
|
** attribute "mask".
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2010-07-28 16:16:00 +01:00
|
|
|
glXCopyContext(Display * dpy, GLXContext source_user,
|
|
|
|
GLXContext dest_user, unsigned long mask)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *source = (struct glx_context *) source_user;
|
|
|
|
struct glx_context *dest = (struct glx_context *) dest_user;
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2010-04-01 19:01:31 +01:00
|
|
|
int errorcode;
|
|
|
|
bool x11error;
|
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext,
|
2010-04-01 19:01:31 +01:00
|
|
|
mask, &errorcode, &x11error)) {
|
|
|
|
__glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXCopyContextReq *req;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXContextTag tag;
|
|
|
|
CARD8 opcode;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2010-07-28 20:33:09 +01:00
|
|
|
if (gc->isDirect) {
|
2009-08-12 11:41:22 +01:00
|
|
|
/* NOT_DONE: This does not work yet */
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** If the source is the current context, send its tag so that the context
|
|
|
|
** can be flushed before the copy.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if (source == gc && dpy == gc->currentDpy) {
|
|
|
|
tag = gc->currentContextTag;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send the glXCopyContext request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXCopyContext, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXCopyContext;
|
|
|
|
req->source = source ? source->xid : None;
|
|
|
|
req->dest = dest ? dest->xid : None;
|
|
|
|
req->mask = mask;
|
|
|
|
req->contextTag = tag;
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif /* GLX_USE_APPLEGL */
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC Bool
|
2010-07-28 16:16:00 +01:00
|
|
|
glXIsDirect(Display * dpy, GLXContext gc_user)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = (struct glx_context *) gc_user;
|
|
|
|
|
2021-04-22 21:46:44 +01:00
|
|
|
/* This is set for us at context creation */
|
|
|
|
return gc ? gc->isDirect : False;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXPixmap
|
2009-08-12 11:41:22 +01:00
|
|
|
glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
|
|
|
int screen = vis->screen;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
|
2010-07-28 15:07:52 +01:00
|
|
|
const struct glx_config *config;
|
2010-04-01 19:01:31 +01:00
|
|
|
|
2011-06-05 23:19:59 +01:00
|
|
|
config = glx_config_find_visual(psc->visuals, vis->visualid);
|
2010-04-01 19:01:31 +01:00
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config))
|
2010-04-01 19:01:31 +01:00
|
|
|
return None;
|
|
|
|
|
|
|
|
return pixmap;
|
|
|
|
#else
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXCreateGLXPixmapReq *req;
|
2011-05-06 18:31:24 +01:00
|
|
|
struct glx_drawable *glxDraw;
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXPixmap xid;
|
|
|
|
CARD8 opcode;
|
2021-05-03 13:38:02 +01:00
|
|
|
|
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2014-02-07 12:43:57 +00:00
|
|
|
struct glx_display *const priv = __glXInitialize(dpy);
|
|
|
|
|
|
|
|
if (priv == NULL)
|
|
|
|
return None;
|
2021-05-03 13:38:02 +01:00
|
|
|
#endif
|
2014-02-07 12:43:57 +00:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return None;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2012-09-05 06:52:36 +01:00
|
|
|
glxDraw = malloc(sizeof(*glxDraw));
|
2011-05-06 18:31:24 +01:00
|
|
|
if (!glxDraw)
|
|
|
|
return None;
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Send the glXCreateGLXPixmap request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXCreateGLXPixmap, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXCreateGLXPixmap;
|
|
|
|
req->screen = vis->screen;
|
|
|
|
req->visual = vis->visualid;
|
|
|
|
req->pixmap = pixmap;
|
|
|
|
req->glxpixmap = xid = XAllocID(dpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2009-08-30 11:43:37 +01:00
|
|
|
|
2021-05-03 13:38:02 +01:00
|
|
|
if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
|
2011-05-06 18:31:24 +01:00
|
|
|
free(glxDraw);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2009-08-30 12:06:18 +01:00
|
|
|
do {
|
|
|
|
/* FIXME: Maybe delay __DRIdrawable creation until the drawable
|
|
|
|
* is actually bound to a context... */
|
|
|
|
|
|
|
|
__GLXDRIdrawable *pdraw;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config;
|
2009-08-30 12:06:18 +01:00
|
|
|
|
2010-07-28 15:28:43 +01:00
|
|
|
psc = priv->screens[vis->screen];
|
2009-08-30 12:06:18 +01:00
|
|
|
if (psc->driScreen == NULL)
|
2011-03-31 21:43:57 +01:00
|
|
|
return xid;
|
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
config = glx_config_find_visual(psc->visuals, vis->visualid);
|
2021-11-09 09:19:44 +00:00
|
|
|
pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, GLX_PIXMAP_BIT, config);
|
2009-08-30 12:06:18 +01:00
|
|
|
if (pdraw == NULL) {
|
|
|
|
fprintf(stderr, "failed to create pixmap\n");
|
2011-03-31 21:43:57 +01:00
|
|
|
xid = None;
|
2009-08-30 12:06:18 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-06-01 16:33:48 +01:00
|
|
|
if (__glxHashInsert(priv->drawHash, xid, pdraw)) {
|
2009-08-30 12:06:18 +01:00
|
|
|
(*pdraw->destroyDrawable) (pdraw);
|
2011-03-31 21:43:57 +01:00
|
|
|
xid = None;
|
|
|
|
break;
|
2009-08-30 12:06:18 +01:00
|
|
|
}
|
|
|
|
} while (0);
|
2011-03-31 21:43:57 +01:00
|
|
|
|
|
|
|
if (xid == None) {
|
|
|
|
xGLXDestroyGLXPixmapReq *dreq;
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXDestroyGLXPixmap, dreq);
|
|
|
|
dreq->reqType = opcode;
|
|
|
|
dreq->glxCode = X_GLXDestroyGLXPixmap;
|
|
|
|
dreq->glxpixmap = xid;
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
|
|
|
}
|
2009-08-30 11:43:37 +01:00
|
|
|
#endif
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return xid;
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Destroy the named pixmap
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2009-08-12 11:41:22 +01:00
|
|
|
glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
|
|
|
|
{
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
|
|
|
if(apple_glx_pixmap_destroy(dpy, glxpixmap))
|
|
|
|
__glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false);
|
|
|
|
#else
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXDestroyGLXPixmapReq *req;
|
|
|
|
CARD8 opcode;
|
|
|
|
|
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send the glXDestroyGLXPixmap request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReq(GLXDestroyGLXPixmap, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXDestroyGLXPixmap;
|
|
|
|
req->glxpixmap = glxpixmap;
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2009-06-19 10:19:07 +01:00
|
|
|
|
2021-05-03 13:38:02 +01:00
|
|
|
DestroyGLXDrawable(dpy, glxpixmap);
|
2011-05-06 18:31:24 +01:00
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2009-08-12 11:41:22 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
struct glx_display *const priv = __glXInitialize(dpy);
|
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap);
|
2009-08-12 11:41:22 +01:00
|
|
|
|
2014-02-07 12:43:57 +00:00
|
|
|
if (priv != NULL && pdraw != NULL) {
|
2009-08-12 11:41:22 +01:00
|
|
|
(*pdraw->destroyDrawable) (pdraw);
|
2010-07-20 02:15:50 +01:00
|
|
|
__glxHashDelete(priv->drawHash, glxpixmap);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
}
|
2009-06-19 10:19:07 +01:00
|
|
|
#endif
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif /* GLX_USE_APPLEGL */
|
2008-10-15 04:07:42 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2009-08-12 11:41:22 +01:00
|
|
|
glXSwapBuffers(Display * dpy, GLXDrawable drawable)
|
2008-10-15 04:07:42 +01:00
|
|
|
{
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
2011-06-05 23:22:47 +01:00
|
|
|
struct glx_context * gc = __glXGetCurrentContext();
|
2017-08-17 23:08:36 +01:00
|
|
|
if(gc != &dummyContext && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
|
2010-04-02 09:35:19 +01:00
|
|
|
apple_glx_swap_buffers(gc->driContext);
|
2010-04-01 19:01:31 +01:00
|
|
|
} else {
|
|
|
|
__glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);
|
|
|
|
}
|
|
|
|
#else
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc;
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXContextTag tag;
|
|
|
|
CARD8 opcode;
|
|
|
|
xcb_connection_t *c;
|
2009-01-18 16:59:07 +00:00
|
|
|
|
2011-02-15 02:38:33 +00:00
|
|
|
gc = __glXGetCurrentContext();
|
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2011-08-19 15:36:22 +01:00
|
|
|
{
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2011-08-19 15:36:22 +01:00
|
|
|
if (pdraw != NULL) {
|
2016-06-07 11:33:33 +01:00
|
|
|
Bool flush = gc != &dummyContext && drawable == gc->currentDrawable;
|
2011-02-15 02:38:33 +00:00
|
|
|
|
2022-04-26 21:01:20 +01:00
|
|
|
if (pdraw->psc->driScreen->swapBuffers(pdraw, 0, 0, 0, flush) == -1)
|
|
|
|
__glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);
|
2011-08-19 15:36:22 +01:00
|
|
|
return;
|
|
|
|
}
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** The calling thread may or may not have a current context. If it
|
|
|
|
** does, send the context tag so the server can do a flush.
|
|
|
|
*/
|
2016-06-07 11:33:33 +01:00
|
|
|
if ((gc != &dummyContext) && (dpy == gc->currentDpy) &&
|
2009-08-12 11:41:22 +01:00
|
|
|
((drawable == gc->currentDrawable)
|
|
|
|
|| (drawable == gc->currentReadable))) {
|
|
|
|
tag = gc->currentContextTag;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tag = 0;
|
|
|
|
}
|
2008-10-15 04:07:42 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
c = XGetXCBConnection(dpy);
|
|
|
|
xcb_glx_swap_buffers(c, tag, drawable);
|
|
|
|
xcb_flush(c);
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif /* GLX_USE_APPLEGL */
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Return configuration information for the given display, screen and
|
|
|
|
** visual combination.
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC int
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
|
|
|
|
int *value_return)
|
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config;
|
2009-08-12 11:41:22 +01:00
|
|
|
int status;
|
|
|
|
|
|
|
|
status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
|
|
|
|
if (status == Success) {
|
2010-07-28 15:07:52 +01:00
|
|
|
config = glx_config_find_visual(psc->visuals, vis->visualid);
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
/* Lookup attribute after first finding a match on the visual */
|
2010-07-28 15:07:52 +01:00
|
|
|
if (config != NULL) {
|
|
|
|
return glx_config_get(config, attribute, value_return);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
status = GLX_BAD_VISUAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** If we can't find the config for this visual, this visual is not
|
|
|
|
** supported by the OpenGL implementation on the server.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
|
2013-06-26 20:42:51 +01:00
|
|
|
*value_return = False;
|
2009-08-12 11:41:22 +01:00
|
|
|
status = Success;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return status;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
static void
|
2010-07-28 15:07:52 +01:00
|
|
|
init_fbconfig_for_chooser(struct glx_config * config,
|
2009-08-12 11:41:22 +01:00
|
|
|
GLboolean fbconfig_style_tags)
|
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
memset(config, 0, sizeof(struct glx_config));
|
2009-08-12 11:41:22 +01:00
|
|
|
config->visualID = (XID) GLX_DONT_CARE;
|
|
|
|
config->visualType = GLX_DONT_CARE;
|
|
|
|
|
2013-07-17 12:49:20 +01:00
|
|
|
/* glXChooseFBConfig specifies different defaults for these properties than
|
2009-08-12 11:41:22 +01:00
|
|
|
* glXChooseVisual.
|
|
|
|
*/
|
|
|
|
if (fbconfig_style_tags) {
|
|
|
|
config->doubleBufferMode = GLX_DONT_CARE;
|
2014-02-13 20:07:09 +00:00
|
|
|
config->renderType = GLX_RGBA_BIT;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
2014-02-13 20:07:09 +00:00
|
|
|
config->drawableType = GLX_WINDOW_BIT;
|
2009-08-12 11:41:22 +01:00
|
|
|
config->visualRating = GLX_DONT_CARE;
|
|
|
|
config->transparentPixel = GLX_NONE;
|
|
|
|
config->transparentRed = GLX_DONT_CARE;
|
|
|
|
config->transparentGreen = GLX_DONT_CARE;
|
|
|
|
config->transparentBlue = GLX_DONT_CARE;
|
|
|
|
config->transparentAlpha = GLX_DONT_CARE;
|
|
|
|
config->transparentIndex = GLX_DONT_CARE;
|
|
|
|
|
|
|
|
config->xRenderable = GLX_DONT_CARE;
|
|
|
|
config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
|
|
|
|
|
|
|
|
config->swapMethod = GLX_DONT_CARE;
|
2018-07-14 15:24:14 +01:00
|
|
|
config->sRGBCapable = GLX_DONT_CARE;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MATCH_DONT_CARE( param ) \
|
|
|
|
do { \
|
2010-02-04 23:59:51 +00:00
|
|
|
if ( ((int) a-> param != (int) GLX_DONT_CARE) \
|
2009-08-12 11:41:22 +01:00
|
|
|
&& (a-> param != b-> param) ) { \
|
|
|
|
return False; \
|
|
|
|
} \
|
|
|
|
} while ( 0 )
|
|
|
|
|
|
|
|
#define MATCH_MINIMUM( param ) \
|
|
|
|
do { \
|
2010-02-04 23:59:51 +00:00
|
|
|
if ( ((int) a-> param != (int) GLX_DONT_CARE) \
|
2009-08-12 11:41:22 +01:00
|
|
|
&& (a-> param > b-> param) ) { \
|
|
|
|
return False; \
|
|
|
|
} \
|
|
|
|
} while ( 0 )
|
|
|
|
|
|
|
|
#define MATCH_EXACT( param ) \
|
|
|
|
do { \
|
|
|
|
if ( a-> param != b-> param) { \
|
|
|
|
return False; \
|
|
|
|
} \
|
|
|
|
} while ( 0 )
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-04-09 03:09:11 +01:00
|
|
|
/* Test that all bits from a are contained in b */
|
|
|
|
#define MATCH_MASK(param) \
|
|
|
|
do { \
|
2013-04-01 22:38:27 +01:00
|
|
|
if ( ((int) a-> param != (int) GLX_DONT_CARE) \
|
|
|
|
&& ((a->param & ~b->param) != 0) ) { \
|
2010-04-09 03:09:11 +01:00
|
|
|
return False; \
|
2013-04-01 22:38:27 +01:00
|
|
|
} \
|
2010-04-09 03:09:11 +01:00
|
|
|
} while (0);
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/**
|
|
|
|
* Determine if two GLXFBConfigs are compatible.
|
|
|
|
*
|
|
|
|
* \param a Application specified config to test.
|
|
|
|
* \param b Server specified config to test against \c a.
|
|
|
|
*/
|
|
|
|
static Bool
|
2010-07-28 15:07:52 +01:00
|
|
|
fbconfigs_compatible(const struct glx_config * const a,
|
|
|
|
const struct glx_config * const b)
|
2009-08-12 11:41:22 +01:00
|
|
|
{
|
|
|
|
MATCH_DONT_CARE(doubleBufferMode);
|
|
|
|
MATCH_DONT_CARE(visualType);
|
|
|
|
MATCH_DONT_CARE(visualRating);
|
|
|
|
MATCH_DONT_CARE(xRenderable);
|
|
|
|
MATCH_DONT_CARE(fbconfigID);
|
|
|
|
MATCH_DONT_CARE(swapMethod);
|
|
|
|
|
|
|
|
MATCH_MINIMUM(rgbBits);
|
|
|
|
MATCH_MINIMUM(numAuxBuffers);
|
|
|
|
MATCH_MINIMUM(redBits);
|
|
|
|
MATCH_MINIMUM(greenBits);
|
|
|
|
MATCH_MINIMUM(blueBits);
|
|
|
|
MATCH_MINIMUM(alphaBits);
|
|
|
|
MATCH_MINIMUM(depthBits);
|
|
|
|
MATCH_MINIMUM(stencilBits);
|
|
|
|
MATCH_MINIMUM(accumRedBits);
|
|
|
|
MATCH_MINIMUM(accumGreenBits);
|
|
|
|
MATCH_MINIMUM(accumBlueBits);
|
|
|
|
MATCH_MINIMUM(accumAlphaBits);
|
|
|
|
MATCH_MINIMUM(sampleBuffers);
|
|
|
|
MATCH_MINIMUM(maxPbufferWidth);
|
|
|
|
MATCH_MINIMUM(maxPbufferHeight);
|
|
|
|
MATCH_MINIMUM(maxPbufferPixels);
|
|
|
|
MATCH_MINIMUM(samples);
|
|
|
|
|
|
|
|
MATCH_DONT_CARE(stereoMode);
|
|
|
|
MATCH_EXACT(level);
|
|
|
|
|
2010-04-09 03:09:11 +01:00
|
|
|
MATCH_MASK(drawableType);
|
|
|
|
MATCH_MASK(renderType);
|
2017-04-27 00:21:32 +01:00
|
|
|
MATCH_DONT_CARE(sRGBCapable);
|
2021-06-16 19:01:04 +01:00
|
|
|
MATCH_DONT_CARE(floatComponentsNV);
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
/* There is a bug in a few of the XFree86 DDX drivers. They contain
|
|
|
|
* visuals with a "transparent type" of 0 when they really mean GLX_NONE.
|
|
|
|
* Technically speaking, it is a bug in the DDX driver, but there is
|
|
|
|
* enough of an installed base to work around the problem here. In any
|
|
|
|
* case, 0 is not a valid value of the transparent type, so we'll treat 0
|
|
|
|
* from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
|
|
|
|
* 0 from the server to be a match to maintain backward compatibility with
|
|
|
|
* the (broken) drivers.
|
|
|
|
*/
|
|
|
|
|
2010-02-04 23:59:51 +00:00
|
|
|
if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) {
|
2009-08-12 11:41:22 +01:00
|
|
|
if (a->transparentPixel == GLX_NONE) {
|
|
|
|
if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MATCH_EXACT(transparentPixel);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (a->transparentPixel) {
|
|
|
|
case GLX_TRANSPARENT_RGB:
|
|
|
|
MATCH_DONT_CARE(transparentRed);
|
|
|
|
MATCH_DONT_CARE(transparentGreen);
|
|
|
|
MATCH_DONT_CARE(transparentBlue);
|
|
|
|
MATCH_DONT_CARE(transparentAlpha);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GLX_TRANSPARENT_INDEX:
|
|
|
|
MATCH_DONT_CARE(transparentIndex);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return True;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* There's some trickly language in the GLX spec about how this is supposed
|
|
|
|
* to work. Basically, if a given component size is either not specified
|
|
|
|
* or the requested size is zero, it is supposed to act like PERFER_SMALLER.
|
|
|
|
* Well, that's really hard to do with the code as-is. This behavior is
|
|
|
|
* closer to correct, but still not technically right.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
#define PREFER_LARGER_OR_ZERO(comp) \
|
|
|
|
do { \
|
|
|
|
if ( ((*a)-> comp) != ((*b)-> comp) ) { \
|
|
|
|
if ( ((*a)-> comp) == 0 ) { \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
else if ( ((*b)-> comp) == 0 ) { \
|
|
|
|
return 1; \
|
|
|
|
} \
|
|
|
|
else { \
|
|
|
|
return ((*b)-> comp) - ((*a)-> comp) ; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while( 0 )
|
|
|
|
|
|
|
|
#define PREFER_LARGER(comp) \
|
|
|
|
do { \
|
|
|
|
if ( ((*a)-> comp) != ((*b)-> comp) ) { \
|
|
|
|
return ((*b)-> comp) - ((*a)-> comp) ; \
|
|
|
|
} \
|
|
|
|
} while( 0 )
|
|
|
|
|
|
|
|
#define PREFER_SMALLER(comp) \
|
|
|
|
do { \
|
|
|
|
if ( ((*a)-> comp) != ((*b)-> comp) ) { \
|
|
|
|
return ((*a)-> comp) - ((*b)-> comp) ; \
|
|
|
|
} \
|
|
|
|
} while( 0 )
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Compare two GLXFBConfigs. This function is intended to be used as the
|
|
|
|
* compare function passed in to qsort.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \returns If \c a is a "better" config, according to the specification of
|
|
|
|
* SGIX_fbconfig, a number less than zero is returned. If \c b is
|
|
|
|
* better, then a number greater than zero is return. If both are
|
|
|
|
* equal, zero is returned.
|
|
|
|
* \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
|
|
|
|
*/
|
|
|
|
static int
|
2010-07-28 15:07:52 +01:00
|
|
|
fbconfig_compare(struct glx_config **a, struct glx_config **b)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
/* The order of these comparisons must NOT change. It is defined by
|
2014-02-15 17:48:40 +00:00
|
|
|
* the GLX 1.4 specification.
|
2009-08-12 11:41:22 +01:00
|
|
|
*/
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
PREFER_SMALLER(visualSelectGroup);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
|
|
|
|
* GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
|
|
|
|
* numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
|
|
|
|
*/
|
|
|
|
PREFER_SMALLER(visualRating);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* This isn't quite right. It is supposed to compare the sum of the
|
|
|
|
* components the user specifically set minimums for.
|
|
|
|
*/
|
|
|
|
PREFER_LARGER_OR_ZERO(redBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(greenBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(blueBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(alphaBits);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
PREFER_SMALLER(rgbBits);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
|
|
|
|
/* Prefer single-buffer.
|
|
|
|
*/
|
|
|
|
return (!(*a)->doubleBufferMode) ? -1 : 1;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
PREFER_SMALLER(numAuxBuffers);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2014-02-15 17:48:40 +00:00
|
|
|
PREFER_SMALLER(sampleBuffers);
|
|
|
|
PREFER_SMALLER(samples);
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
PREFER_LARGER_OR_ZERO(depthBits);
|
|
|
|
PREFER_SMALLER(stencilBits);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* This isn't quite right. It is supposed to compare the sum of the
|
|
|
|
* components the user specifically set minimums for.
|
|
|
|
*/
|
|
|
|
PREFER_LARGER_OR_ZERO(accumRedBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(accumGreenBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(accumBlueBits);
|
|
|
|
PREFER_LARGER_OR_ZERO(accumAlphaBits);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
PREFER_SMALLER(visualType);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* None of the pbuffer or fbconfig specs say that this comparison needs
|
|
|
|
* to happen at all, but it seems like it should.
|
|
|
|
*/
|
|
|
|
PREFER_LARGER(maxPbufferWidth);
|
|
|
|
PREFER_LARGER(maxPbufferHeight);
|
|
|
|
PREFER_LARGER(maxPbufferPixels);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return 0;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Selects and sorts a subset of the supplied configs based on the attributes.
|
2016-09-30 11:01:28 +01:00
|
|
|
* This function forms to basis of \c glXChooseFBConfig and
|
|
|
|
* \c glXChooseFBConfigSGIX.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \param configs Array of pointers to possible configs. The elements of
|
|
|
|
* this array that do not meet the criteria will be set to
|
|
|
|
* NULL. The remaining elements will be sorted according to
|
|
|
|
* the various visual / FBConfig selection rules.
|
|
|
|
* \param num_configs Number of elements in the \c configs array.
|
|
|
|
* \param attribList Attributes used select from \c configs. This array is
|
2016-09-30 11:01:28 +01:00
|
|
|
* terminated by a \c None tag. The array is of the form
|
|
|
|
* expected by \c glXChooseFBConfig (where every tag has a
|
|
|
|
* value).
|
2004-10-25 22:09:16 +01:00
|
|
|
* \returns The number of valid elements left in \c configs.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2016-09-30 11:01:28 +01:00
|
|
|
* \sa glXChooseFBConfig, glXChooseFBConfigSGIX
|
2004-10-25 22:09:16 +01:00
|
|
|
*/
|
|
|
|
static int
|
2016-09-30 11:01:28 +01:00
|
|
|
choose_fbconfig(struct glx_config ** configs, int num_configs,
|
|
|
|
const int *attribList)
|
2009-08-12 11:41:22 +01:00
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config test_config;
|
2009-08-12 11:41:22 +01:00
|
|
|
int base;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* This is a fairly direct implementation of the selection method
|
|
|
|
* described by GLX_SGIX_fbconfig. Start by culling out all the
|
|
|
|
* configs that are not compatible with the selected parameter
|
|
|
|
* list.
|
|
|
|
*/
|
|
|
|
|
2016-09-30 11:01:28 +01:00
|
|
|
init_fbconfig_for_chooser(&test_config, GL_TRUE);
|
2009-08-12 11:41:22 +01:00
|
|
|
__glXInitializeVisualConfigFromTags(&test_config, 512,
|
|
|
|
(const INT32 *) attribList,
|
2016-09-30 11:01:28 +01:00
|
|
|
GL_TRUE, GL_TRUE);
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
base = 0;
|
|
|
|
for (i = 0; i < num_configs; i++) {
|
|
|
|
if (fbconfigs_compatible(&test_config, configs[i])) {
|
|
|
|
configs[base] = configs[i];
|
|
|
|
base++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base < num_configs) {
|
|
|
|
(void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* After the incompatible configs are removed, the resulting
|
|
|
|
* list is sorted according to the rules set out in the various
|
|
|
|
* specifications.
|
|
|
|
*/
|
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
qsort(configs, base, sizeof(struct glx_config *),
|
2009-08-12 11:41:22 +01:00
|
|
|
(int (*)(const void *, const void *)) fbconfig_compare);
|
|
|
|
return base;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Return the visual that best matches the template. Return None if no
|
|
|
|
** visual matches the template.
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC XVisualInfo *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXChooseVisual(Display * dpy, int screen, int *attribList)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
XVisualInfo *visualList = NULL;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config test_config;
|
|
|
|
struct glx_config *config;
|
|
|
|
struct glx_config *best_config = NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** Get a list of all visuals, return if list is empty
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
|
|
|
|
return None;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** Build a template from the defaults and the attribute list
|
|
|
|
** Free visual list and return if an unexpected token is encountered
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
init_fbconfig_for_chooser(&test_config, GL_FALSE);
|
|
|
|
__glXInitializeVisualConfigFromTags(&test_config, 512,
|
|
|
|
(const INT32 *) attribList,
|
|
|
|
GL_TRUE, GL_FALSE);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** Eliminate visuals that don't meet minimum requirements
|
|
|
|
** Compute a score for those that do
|
|
|
|
** Remember which visual, if any, got the highest score
|
2009-05-12 07:01:22 +01:00
|
|
|
** If no visual is acceptable, return None
|
|
|
|
** Otherwise, create an XVisualInfo list with just the selected X visual
|
|
|
|
** and return this.
|
2004-10-25 22:09:16 +01:00
|
|
|
*/
|
2010-07-28 15:07:52 +01:00
|
|
|
for (config = psc->visuals; config != NULL; config = config->next) {
|
|
|
|
if (fbconfigs_compatible(&test_config, config)
|
|
|
|
&& ((best_config == NULL) ||
|
|
|
|
(fbconfig_compare (&config, &best_config) < 0))) {
|
2009-08-12 11:41:22 +01:00
|
|
|
XVisualInfo visualTemplate;
|
|
|
|
XVisualInfo *newList;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
visualTemplate.screen = screen;
|
2010-07-28 15:07:52 +01:00
|
|
|
visualTemplate.visualid = config->visualID;
|
2009-08-12 11:41:22 +01:00
|
|
|
newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
|
|
|
|
&visualTemplate, &i);
|
|
|
|
|
|
|
|
if (newList) {
|
2012-09-05 06:52:36 +01:00
|
|
|
free(visualList);
|
2009-08-12 11:41:22 +01:00
|
|
|
visualList = newList;
|
2010-07-28 15:07:52 +01:00
|
|
|
best_config = config;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-15 04:07:42 +01:00
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
2017-09-08 11:56:02 +01:00
|
|
|
if(visualList && env_var_as_boolean("LIBGL_DUMP_VISUALID", false)) {
|
2010-04-01 19:01:31 +01:00
|
|
|
printf("visualid 0x%lx\n", visualList[0].visualid);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return visualList;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC const char *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXQueryExtensionsString(Display * dpy, int screen)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2021-04-22 19:44:26 +01:00
|
|
|
int is_direct_capable = GL_FALSE;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (!psc->effectiveGLXexts) {
|
|
|
|
if (!psc->serverGLXexts) {
|
|
|
|
psc->serverGLXexts =
|
2021-04-22 23:39:41 +01:00
|
|
|
__glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-04-02 09:35:19 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2021-04-22 19:44:26 +01:00
|
|
|
is_direct_capable = (psc->driScreen != NULL);
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
2021-04-22 19:44:26 +01:00
|
|
|
__glXCalculateUsableExtensions(psc, is_direct_capable);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return psc->effectiveGLXexts;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC const char *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetClientString(Display * dpy, int name)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-02-04 23:47:54 +00:00
|
|
|
(void) dpy;
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
switch (name) {
|
|
|
|
case GLX_VENDOR:
|
|
|
|
return (__glXGLXClientVendorName);
|
|
|
|
case GLX_VERSION:
|
|
|
|
return (__glXGLXClientVersion);
|
|
|
|
case GLX_EXTENSIONS:
|
2017-11-14 20:13:06 +00:00
|
|
|
return (__glXGetClientExtensions(dpy));
|
2009-08-12 11:41:22 +01:00
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC const char *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXQueryServerString(Display * dpy, int screen, int name)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2009-08-12 11:41:22 +01:00
|
|
|
const char **str;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
switch (name) {
|
|
|
|
case GLX_VENDOR:
|
2021-04-23 06:17:00 +01:00
|
|
|
str = &psc->serverGLXvendor;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_VERSION:
|
2021-04-23 06:17:00 +01:00
|
|
|
str = &psc->serverGLXversion;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_EXTENSIONS:
|
|
|
|
str = &psc->serverGLXexts;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (*str == NULL) {
|
2021-04-22 23:39:41 +01:00
|
|
|
*str = __glXQueryServerString(dpy, screen, name);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return *str;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** EXT_import_context
|
|
|
|
*/
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC Display *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetCurrentDisplay(void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc == &dummyContext)
|
2009-08-12 11:41:22 +01:00
|
|
|
return NULL;
|
|
|
|
return gc->currentDpy;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
|
|
|
|
glXGetCurrentDisplay)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifndef GLX_USE_APPLEGL
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXContext
|
2010-07-23 21:15:31 +01:00
|
|
|
glXImportContextEXT(Display *dpy, GLXContextID contextID)
|
2009-08-12 11:41:22 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
2011-12-07 19:15:14 +00:00
|
|
|
struct glx_screen *psc = NULL;
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXQueryContextReply reply;
|
|
|
|
CARD8 opcode;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *ctx;
|
2017-09-26 21:38:31 +01:00
|
|
|
int i, renderType = GLX_RGBA_TYPE; /* By default, assume RGBA context */
|
|
|
|
XID share = None;
|
|
|
|
struct glx_config *mode = NULL;
|
2011-12-07 19:15:14 +00:00
|
|
|
uint32_t fbconfigID = 0;
|
|
|
|
uint32_t visualID = 0;
|
2013-03-13 14:35:21 +00:00
|
|
|
uint32_t screen = 0;
|
2011-12-07 19:15:14 +00:00
|
|
|
Bool got_screen = False;
|
2010-07-23 21:15:31 +01:00
|
|
|
|
2014-02-07 12:43:57 +00:00
|
|
|
if (priv == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2011-12-08 00:13:02 +00:00
|
|
|
/* The GLX_EXT_import_context spec says:
|
|
|
|
*
|
|
|
|
* "If <contextID> does not refer to a valid context, then a BadContext
|
|
|
|
* error is generated; if <contextID> refers to direct rendering
|
|
|
|
* context then no error is generated but glXImportContextEXT returns
|
|
|
|
* NULL."
|
|
|
|
*
|
2020-12-01 15:49:03 +00:00
|
|
|
* We can handle both conditions with the __glXIsDirect call, because
|
|
|
|
* passing None to a GLXIsDirect request will throw GLXBadContext.
|
2011-12-08 00:13:02 +00:00
|
|
|
*/
|
glx: Demand success from CreateContext requests (v2)
GLXCreate{,New}Context, like most X resource creation requests, does not
emit a reply and therefore is emitted into the X stream asynchronously.
However, unlike most resource creation requests, the GLXContext we
return is a handle to library state instead of an XID. So if context
creation fails for any reason - say, the server doesn't support indirect
contexts - then we will fail in strange places for strange reasons.
We could make every GLX entrypoint robust against half-created contexts,
or we could just verify that context creation worked. Reuse the
__glXIsDirect code to do this, as a cheap way of verifying that the
XID is real.
glXCreateContextAttribsARB solves this by using the _checked version of
the xcb command, so effectively this change makes the classic context
creation paths as robust as CreateContextAttribs.
v2: Better use of Bool, check that error != NULL first (Olivier Fourdan)
Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2018-08-07 21:55:37 +01:00
|
|
|
if (__glXIsDirect(dpy, contextID, NULL))
|
2010-07-23 21:15:31 +01:00
|
|
|
return NULL;
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
opcode = __glXSetupForCommand(dpy);
|
2010-07-23 21:15:31 +01:00
|
|
|
if (!opcode)
|
2009-08-12 11:41:22 +01:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Send the glXQueryContextInfoEXT request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
|
2021-04-22 18:10:44 +01:00
|
|
|
if (priv->minorVersion >= 3) {
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXQueryContextReq *req;
|
|
|
|
|
|
|
|
GetReq(GLXQueryContext, req);
|
|
|
|
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXQueryContext;
|
2010-07-23 21:15:31 +01:00
|
|
|
req->context = contextID;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
xGLXVendorPrivateReq *vpreq;
|
|
|
|
xGLXQueryContextInfoEXTReq *req;
|
|
|
|
|
|
|
|
GetReqExtra(GLXVendorPrivate,
|
2010-07-23 21:15:31 +01:00
|
|
|
sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
|
|
|
|
vpreq);
|
2009-08-12 11:41:22 +01:00
|
|
|
req = (xGLXQueryContextInfoEXTReq *) vpreq;
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivateWithReply;
|
|
|
|
req->vendorCode = X_GLXvop_QueryContextInfoEXT;
|
2010-07-23 21:15:31 +01:00
|
|
|
req->context = contextID;
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
2017-09-26 21:38:31 +01:00
|
|
|
if (_XReply(dpy, (xReply *) & reply, 0, False) &&
|
|
|
|
reply.n < (INT32_MAX / 2)) {
|
|
|
|
|
2018-06-01 17:59:36 +01:00
|
|
|
for (i = 0; i < reply.n; i++) {
|
2017-09-26 21:38:31 +01:00
|
|
|
int prop[2];
|
|
|
|
|
|
|
|
_XRead(dpy, (char *)prop, sizeof(prop));
|
|
|
|
switch (prop[0]) {
|
|
|
|
case GLX_SCREEN:
|
|
|
|
screen = prop[1];
|
|
|
|
got_screen = True;
|
|
|
|
break;
|
|
|
|
case GLX_SHARE_CONTEXT_EXT:
|
|
|
|
share = prop[1];
|
|
|
|
break;
|
|
|
|
case GLX_VISUAL_ID_EXT:
|
|
|
|
visualID = prop[1];
|
|
|
|
break;
|
|
|
|
case GLX_FBCONFIG_ID:
|
|
|
|
fbconfigID = prop[1];
|
|
|
|
break;
|
|
|
|
case GLX_RENDER_TYPE:
|
|
|
|
renderType = prop[1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-08-12 11:41:22 +01:00
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2010-07-23 21:15:31 +01:00
|
|
|
|
2011-12-07 19:15:14 +00:00
|
|
|
if (!got_screen)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
psc = GetGLXScreenConfigs(dpy, screen);
|
|
|
|
if (psc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (fbconfigID != 0) {
|
|
|
|
mode = glx_config_find_fbconfig(psc->configs, fbconfigID);
|
|
|
|
} else if (visualID != 0) {
|
|
|
|
mode = glx_config_find_visual(psc->visuals, visualID);
|
|
|
|
}
|
|
|
|
|
2010-07-23 21:15:31 +01:00
|
|
|
if (mode == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ctx = indirect_create_context(psc, mode, NULL, renderType);
|
|
|
|
if (ctx == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ctx->xid = contextID;
|
|
|
|
ctx->imported = GL_TRUE;
|
|
|
|
ctx->share_xid = share;
|
|
|
|
|
2010-07-28 16:16:00 +01:00
|
|
|
return (GLXContext) ctx;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC int
|
2010-07-28 16:16:00 +01:00
|
|
|
glXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *ctx = (struct glx_context *) ctx_user;
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
switch (attribute) {
|
2010-04-01 19:01:31 +01:00
|
|
|
case GLX_SHARE_CONTEXT_EXT:
|
2010-07-23 21:15:31 +01:00
|
|
|
*value = ctx->share_xid;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_VISUAL_ID_EXT:
|
2010-07-28 15:07:52 +01:00
|
|
|
*value = ctx->config ? ctx->config->visualID : None;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_SCREEN:
|
2010-07-23 21:15:31 +01:00
|
|
|
*value = ctx->screen;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_FBCONFIG_ID:
|
2010-07-28 15:07:52 +01:00
|
|
|
*value = ctx->config ? ctx->config->fbconfigID : None;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
case GLX_RENDER_TYPE:
|
2010-07-23 21:15:31 +01:00
|
|
|
*value = ctx->renderType;
|
2009-08-12 11:41:22 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return GLX_BAD_ATTRIBUTE;
|
|
|
|
}
|
|
|
|
return Success;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_ALIAS(int, glXQueryContextInfoEXT,
|
|
|
|
(Display * dpy, GLXContext ctx, int attribute, int *value),
|
|
|
|
(dpy, ctx, attribute, value), glXQueryContext)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *ctx = (struct glx_context *) ctx_user;
|
|
|
|
|
2011-12-07 19:37:01 +00:00
|
|
|
return (ctx == NULL) ? None : ctx->xid;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void
|
2011-12-07 21:31:27 +00:00
|
|
|
glXFreeContextEXT(Display *dpy, GLXContext ctx)
|
|
|
|
{
|
|
|
|
struct glx_context *gc = (struct glx_context *) ctx;
|
|
|
|
|
|
|
|
if (gc == NULL || gc->xid == None)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* The GLX_EXT_import_context spec says:
|
|
|
|
*
|
|
|
|
* "glXFreeContext does not free the server-side context information or
|
|
|
|
* the XID associated with the server-side context."
|
|
|
|
*
|
|
|
|
* Don't send any protocol. Just destroy the client-side tracking of the
|
|
|
|
* context. Also, only release the context structure if it's not current.
|
|
|
|
*/
|
|
|
|
__glXLock();
|
|
|
|
if (gc->currentDpy) {
|
|
|
|
gc->xid = None;
|
|
|
|
} else {
|
|
|
|
gc->vtable->destroy(gc);
|
|
|
|
}
|
|
|
|
__glXUnlock();
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXFBConfig *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXChooseFBConfig(Display * dpy, int screen,
|
|
|
|
const int *attribList, int *nitems)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config **config_list;
|
2009-08-12 11:41:22 +01:00
|
|
|
int list_size;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
config_list = (struct glx_config **)
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetFBConfigs(dpy, screen, &list_size);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
|
2016-09-30 11:01:28 +01:00
|
|
|
list_size = choose_fbconfig(config_list, list_size, attribList);
|
2009-08-12 11:41:22 +01:00
|
|
|
if (list_size == 0) {
|
2012-09-05 06:52:36 +01:00
|
|
|
free(config_list);
|
2009-08-12 11:41:22 +01:00
|
|
|
config_list = NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
*nitems = list_size;
|
|
|
|
return (GLXFBConfig *) config_list;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXContext
|
2010-07-28 15:07:52 +01:00
|
|
|
glXCreateNewContext(Display * dpy, GLXFBConfig fbconfig,
|
2009-08-12 11:41:22 +01:00
|
|
|
int renderType, GLXContext shareList, Bool allowDirect)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = (struct glx_config *) fbconfig;
|
2016-02-10 17:36:05 +00:00
|
|
|
struct glx_config **config_list;
|
|
|
|
int list_size;
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
if (!config) {
|
|
|
|
__glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
config_list = (struct glx_config **)
|
2016-10-11 19:42:03 +01:00
|
|
|
glXGetFBConfigs(dpy, config->screen, &list_size);
|
2016-02-10 17:36:05 +00:00
|
|
|
|
|
|
|
for (i = 0; i < list_size; i++) {
|
|
|
|
if (config_list[i] == config)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(config_list);
|
|
|
|
|
|
|
|
if (i == list_size) {
|
|
|
|
__glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-02-05 00:37:59 +00:00
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
return CreateContext(dpy, config->fbconfigID, config, shareList,
|
2022-07-01 16:50:04 +01:00
|
|
|
allowDirect, X_GLXCreateNewContext, renderType);
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXDrawable
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetCurrentReadDrawable(void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return gc->currentReadable;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXFBConfig *
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetFBConfigs(Display * dpy, int screen, int *nelements)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv = __glXInitialize(dpy);
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config **config_list = NULL;
|
|
|
|
struct glx_config *config;
|
|
|
|
unsigned num_configs = 0;
|
2009-08-12 11:41:22 +01:00
|
|
|
int i;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
*nelements = 0;
|
2010-07-28 15:28:43 +01:00
|
|
|
if (priv && (priv->screens != NULL)
|
2016-05-17 07:35:29 +01:00
|
|
|
&& (screen >= 0) && (screen < ScreenCount(dpy))
|
2010-07-28 15:28:43 +01:00
|
|
|
&& (priv->screens[screen]->configs != NULL)
|
|
|
|
&& (priv->screens[screen]->configs->fbconfigID
|
2010-02-04 23:59:51 +00:00
|
|
|
!= (int) GLX_DONT_CARE)) {
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-07-28 15:28:43 +01:00
|
|
|
for (config = priv->screens[screen]->configs; config != NULL;
|
2010-07-28 15:07:52 +01:00
|
|
|
config = config->next) {
|
|
|
|
if (config->fbconfigID != (int) GLX_DONT_CARE) {
|
2009-08-12 11:41:22 +01:00
|
|
|
num_configs++;
|
|
|
|
}
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2012-09-05 06:52:36 +01:00
|
|
|
config_list = malloc(num_configs * sizeof *config_list);
|
2010-07-28 15:07:52 +01:00
|
|
|
if (config_list != NULL) {
|
2009-08-12 11:41:22 +01:00
|
|
|
*nelements = num_configs;
|
|
|
|
i = 0;
|
2010-07-28 15:28:43 +01:00
|
|
|
for (config = priv->screens[screen]->configs; config != NULL;
|
2010-07-28 15:07:52 +01:00
|
|
|
config = config->next) {
|
|
|
|
if (config->fbconfigID != (int) GLX_DONT_CARE) {
|
|
|
|
config_list[i] = config;
|
2009-08-12 11:41:22 +01:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-07-28 15:07:52 +01:00
|
|
|
|
|
|
|
return (GLXFBConfig *) config_list;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC int
|
2010-07-28 15:07:52 +01:00
|
|
|
glXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig,
|
2009-08-12 11:41:22 +01:00
|
|
|
int attribute, int *value)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig);
|
|
|
|
|
|
|
|
if (config == NULL)
|
|
|
|
return GLXBadFBConfig;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
return glx_config_get(config, attribute, value);
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC XVisualInfo *
|
2010-07-28 15:07:52 +01:00
|
|
|
glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
XVisualInfo visualTemplate;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = (struct glx_config *) fbconfig;
|
2009-08-12 11:41:22 +01:00
|
|
|
int count;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2021-04-12 16:33:17 +01:00
|
|
|
if (!config)
|
|
|
|
return NULL;
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2004-10-25 22:09:16 +01:00
|
|
|
** Get a list of all visuals, return if list is empty
|
|
|
|
*/
|
2010-07-28 15:07:52 +01:00
|
|
|
visualTemplate.visualid = config->visualID;
|
2009-08-12 11:41:22 +01:00
|
|
|
return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifndef GLX_USE_APPLEGL
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** GLX_SGI_swap_control
|
|
|
|
*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int
|
|
|
|
glXSwapIntervalSGI(int interval)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
|
|
|
xGLXVendorPrivateReq *req;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2020-07-16 22:29:26 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-04-23 05:55:46 +01:00
|
|
|
struct glx_screen *psc = gc->psc;
|
2020-07-16 22:29:26 +01:00
|
|
|
#endif
|
2009-08-12 11:41:22 +01:00
|
|
|
Display *dpy;
|
|
|
|
CARD32 *interval_ptr;
|
2004-10-25 22:09:16 +01:00
|
|
|
CARD8 opcode;
|
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc == &dummyContext) {
|
2004-10-25 22:09:16 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
}
|
2009-08-12 11:41:22 +01:00
|
|
|
|
|
|
|
if (interval <= 0) {
|
2004-10-25 22:09:16 +01:00
|
|
|
return GLX_BAD_VALUE;
|
|
|
|
}
|
|
|
|
|
2020-07-16 22:29:26 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2014-02-07 12:43:57 +00:00
|
|
|
if (gc->isDirect && psc && psc->driScreen &&
|
|
|
|
psc->driScreen->setSwapInterval) {
|
2010-07-23 03:36:37 +01:00
|
|
|
__GLXDRIdrawable *pdraw =
|
2021-05-03 13:38:02 +01:00
|
|
|
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
2017-02-02 17:06:27 +00:00
|
|
|
/* Simply ignore the command if the GLX drawable has been destroyed but
|
|
|
|
* the context is still bound.
|
|
|
|
*/
|
|
|
|
if (pdraw)
|
|
|
|
psc->driScreen->setSwapInterval(pdraw, interval);
|
2009-11-10 21:28:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-04-01 08:10:28 +01:00
|
|
|
#endif
|
2009-11-10 21:28:01 +00:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
dpy = gc->currentDpy;
|
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send the glXSwapIntervalSGI request */
|
|
|
|
LockDisplay(dpy);
|
2009-08-12 11:41:22 +01:00
|
|
|
GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
|
2004-10-25 22:09:16 +01:00
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivate;
|
|
|
|
req->vendorCode = X_GLXvop_SwapIntervalSGI;
|
|
|
|
req->contextTag = gc->currentContextTag;
|
|
|
|
|
2006-08-31 00:15:02 +01:00
|
|
|
interval_ptr = (CARD32 *) (req + 1);
|
2004-10-25 22:09:16 +01:00
|
|
|
*interval_ptr = interval;
|
|
|
|
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
|
|
|
XFlush(dpy);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** GLX_MESA_swap_control
|
|
|
|
*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int
|
|
|
|
glXSwapIntervalMESA(unsigned int interval)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-19 21:39:53 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2020-09-09 20:54:21 +01:00
|
|
|
if (interval > INT_MAX)
|
|
|
|
return GLX_BAD_VALUE;
|
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc != &dummyContext && gc->isDirect) {
|
2021-04-23 05:55:46 +01:00
|
|
|
struct glx_screen *psc = gc->psc;
|
2014-02-07 12:43:57 +00:00
|
|
|
if (psc && psc->driScreen && psc->driScreen->setSwapInterval) {
|
2010-07-23 03:36:37 +01:00
|
|
|
__GLXDRIdrawable *pdraw =
|
2021-05-03 13:38:02 +01:00
|
|
|
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
2017-02-02 17:06:27 +00:00
|
|
|
|
|
|
|
/* Simply ignore the command if the GLX drawable has been destroyed but
|
|
|
|
* the context is still bound.
|
|
|
|
*/
|
|
|
|
if (!pdraw)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return psc->driScreen->setSwapInterval(pdraw, interval);
|
2009-11-10 21:28:01 +00:00
|
|
|
}
|
|
|
|
}
|
2010-04-01 08:10:28 +01:00
|
|
|
#endif
|
2009-11-10 21:28:01 +00:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
}
|
2006-03-09 16:25:46 +00:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int
|
|
|
|
glXGetSwapIntervalMESA(void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-19 21:39:53 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc != &dummyContext && gc->isDirect) {
|
2021-04-23 05:55:46 +01:00
|
|
|
struct glx_screen *psc = gc->psc;
|
2014-02-07 12:43:57 +00:00
|
|
|
if (psc && psc->driScreen && psc->driScreen->getSwapInterval) {
|
2010-07-23 03:36:37 +01:00
|
|
|
__GLXDRIdrawable *pdraw =
|
2021-05-03 13:38:02 +01:00
|
|
|
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
2017-02-02 17:06:27 +00:00
|
|
|
if (pdraw)
|
|
|
|
return psc->driScreen->getSwapInterval(pdraw);
|
2009-11-10 21:28:01 +00:00
|
|
|
}
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 19:00:35 +01:00
|
|
|
/*
|
|
|
|
** GLX_EXT_swap_control
|
|
|
|
*/
|
|
|
|
_X_HIDDEN void
|
|
|
|
glXSwapIntervalEXT(Display *dpy, GLXDrawable drawable, int interval)
|
|
|
|
{
|
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2020-09-09 19:00:35 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Strictly, this should throw an error if drawable is not a Window or
|
|
|
|
* GLXWindow. We don't actually track that, so, oh well.
|
|
|
|
*/
|
|
|
|
if (!pdraw) {
|
|
|
|
__glXSendError(dpy, BadWindow, drawable, 0, True);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-09 20:14:30 +01:00
|
|
|
if (interval < 0 &&
|
|
|
|
!__glXExtensionBitIsEnabled(pdraw->psc, EXT_swap_control_tear_bit)) {
|
2020-09-09 19:00:35 +01:00
|
|
|
__glXSendError(dpy, BadValue, interval, 0, True);
|
|
|
|
return;
|
|
|
|
}
|
2021-02-22 05:57:01 +00:00
|
|
|
if (pdraw->psc->driScreen->setSwapInterval)
|
|
|
|
pdraw->psc->driScreen->setSwapInterval(pdraw, interval);
|
2020-09-09 19:00:35 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** GLX_SGI_video_sync
|
|
|
|
*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int
|
|
|
|
glXGetVideoSyncSGI(unsigned int *count)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2020-07-16 22:29:26 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2009-09-16 07:23:09 +01:00
|
|
|
int64_t ust, msc, sbc;
|
|
|
|
int ret;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2021-04-23 05:55:46 +01:00
|
|
|
struct glx_screen *psc = gc->psc;
|
2009-09-16 07:23:09 +01:00
|
|
|
__GLXDRIdrawable *pdraw;
|
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc == &dummyContext)
|
2009-09-16 07:23:09 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2010-07-28 20:33:09 +01:00
|
|
|
if (!gc->isDirect)
|
2010-04-01 08:10:28 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2020-11-16 18:24:23 +00:00
|
|
|
if (!gc->currentDrawable)
|
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2021-05-03 13:38:02 +01:00
|
|
|
pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
|
|
|
|
* FIXME: there should be a GLX encoding for this call. I can find no
|
|
|
|
* FIXME: documentation for the GLX encoding.
|
|
|
|
*/
|
2014-02-07 12:43:57 +00:00
|
|
|
if (psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
|
2009-09-16 07:23:09 +01:00
|
|
|
ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
|
|
|
|
*count = (unsigned) msc;
|
|
|
|
return (ret == True) ? 0 : GLX_BAD_CONTEXT;
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int
|
|
|
|
glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-04-23 05:55:46 +01:00
|
|
|
struct glx_screen *psc = gc->psc;
|
2009-09-16 07:23:09 +01:00
|
|
|
__GLXDRIdrawable *pdraw;
|
|
|
|
int64_t ust, msc, sbc;
|
|
|
|
int ret;
|
2020-07-16 22:29:26 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (divisor <= 0 || remainder < 0)
|
|
|
|
return GLX_BAD_VALUE;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc == &dummyContext)
|
2009-09-16 07:23:09 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2010-04-01 08:10:28 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-07-28 20:33:09 +01:00
|
|
|
if (!gc->isDirect)
|
2010-04-01 08:10:28 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2020-11-16 18:24:23 +00:00
|
|
|
if (!gc->currentDrawable)
|
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
|
2021-05-03 13:38:02 +01:00
|
|
|
pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2014-02-07 12:43:57 +00:00
|
|
|
if (psc && psc->driScreen && psc->driScreen->waitForMSC) {
|
2009-09-16 07:23:09 +01:00
|
|
|
ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
|
|
|
|
&sbc);
|
|
|
|
*count = (unsigned) msc;
|
|
|
|
return (ret == True) ? 0 : GLX_BAD_CONTEXT;
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return GLX_BAD_CONTEXT;
|
|
|
|
}
|
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif /* GLX_USE_APPLEGL */
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
** GLX_SGIX_fbconfig
|
|
|
|
** Many of these functions are aliased to GLX 1.3 entry points in the
|
|
|
|
** GLX_functions table.
|
|
|
|
*/
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
|
|
|
|
(Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
|
|
|
|
(dpy, config, attribute, value), glXGetFBConfigAttrib)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
|
2009-09-29 16:58:47 +01:00
|
|
|
(Display * dpy, int screen, int *attrib_list,
|
|
|
|
int *nelements), (dpy, screen, attrib_list, nelements),
|
|
|
|
glXChooseFBConfig)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
|
2009-09-29 16:58:47 +01:00
|
|
|
(Display * dpy, GLXFBConfigSGIX config),
|
|
|
|
(dpy, config), glXGetVisualFromFBConfig)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXPixmap
|
2009-09-29 16:58:47 +01:00
|
|
|
glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
|
2010-07-28 15:07:52 +01:00
|
|
|
GLXFBConfigSGIX fbconfig,
|
2009-09-29 16:58:47 +01:00
|
|
|
Pixmap pixmap)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifndef GLX_USE_APPLEGL
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXVendorPrivateWithReplyReq *vpreq;
|
|
|
|
xGLXCreateGLXPixmapWithConfigSGIXReq *req;
|
|
|
|
GLXPixmap xid = None;
|
|
|
|
CARD8 opcode;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = (struct glx_config *) fbconfig;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((dpy == NULL) || (config == NULL)) {
|
|
|
|
return None;
|
|
|
|
}
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
2010-07-28 15:07:52 +01:00
|
|
|
if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config))
|
2010-04-01 19:01:31 +01:00
|
|
|
return None;
|
|
|
|
return pixmap;
|
|
|
|
#else
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
psc = GetGLXScreenConfigs(dpy, config->screen);
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((psc != NULL)
|
|
|
|
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
|
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode) {
|
|
|
|
return None;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/* Send the glXCreateGLXPixmapWithConfigSGIX request */
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReqExtra(GLXVendorPrivateWithReply,
|
|
|
|
sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
|
|
|
|
sz_xGLXVendorPrivateWithReplyReq, vpreq);
|
|
|
|
req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivateWithReply;
|
|
|
|
req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
|
2010-07-28 15:07:52 +01:00
|
|
|
req->screen = config->screen;
|
|
|
|
req->fbconfig = config->fbconfigID;
|
2009-08-12 11:41:22 +01:00
|
|
|
req->pixmap = pixmap;
|
|
|
|
req->glxpixmap = xid = XAllocID(dpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return xid;
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXContext
|
2009-08-12 11:41:22 +01:00
|
|
|
glXCreateContextWithConfigSGIX(Display * dpy,
|
2010-07-28 15:07:52 +01:00
|
|
|
GLXFBConfigSGIX fbconfig, int renderType,
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXContext shareList, Bool allowDirect)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXContext gc = NULL;
|
2010-07-28 15:07:52 +01:00
|
|
|
struct glx_config *config = (struct glx_config *) fbconfig;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((dpy == NULL) || (config == NULL)) {
|
|
|
|
return None;
|
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-07-28 15:07:52 +01:00
|
|
|
psc = GetGLXScreenConfigs(dpy, config->screen);
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((psc != NULL)
|
|
|
|
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
|
2010-07-28 15:07:52 +01:00
|
|
|
gc = CreateContext(dpy, config->fbconfigID, config, shareList,
|
2010-02-05 00:43:46 +00:00
|
|
|
allowDirect,
|
2022-07-01 16:50:04 +01:00
|
|
|
X_GLXvop_CreateContextWithConfigSGIX, renderType);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return gc;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXFBConfigSGIX
|
2009-08-12 11:41:22 +01:00
|
|
|
glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display *priv;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc = NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2011-05-27 01:19:03 +01:00
|
|
|
if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success)
|
2009-08-12 11:41:22 +01:00
|
|
|
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
|
2010-02-04 23:59:51 +00:00
|
|
|
&& (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
|
2010-07-28 15:07:52 +01:00
|
|
|
return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs,
|
|
|
|
vis->visualid);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return NULL;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifndef GLX_USE_APPLEGL
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** GLX_OML_sync_control
|
|
|
|
*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN Bool
|
|
|
|
glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
|
|
|
|
int64_t *ust, int64_t *msc, int64_t *sbc)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_display * const priv = __glXInitialize(dpy);
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2020-07-16 22:29:26 +01:00
|
|
|
int ret;
|
2009-09-16 07:23:09 +01:00
|
|
|
__GLXDRIdrawable *pdraw;
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc;
|
2020-07-16 22:29:26 +01:00
|
|
|
#endif
|
2009-08-12 11:41:22 +01:00
|
|
|
|
2009-09-16 07:23:09 +01:00
|
|
|
if (!priv)
|
|
|
|
return False;
|
2009-08-12 11:41:22 +01:00
|
|
|
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2010-07-23 03:36:37 +01:00
|
|
|
psc = pdraw ? pdraw->psc : NULL;
|
|
|
|
if (pdraw && psc->driScreen->getDrawableMSC) {
|
2009-09-16 07:23:09 +01:00
|
|
|
ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
2018-12-14 13:20:10 +00:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2008-03-09 03:28:01 +00:00
|
|
|
_X_HIDDEN GLboolean
|
2013-12-15 10:37:55 +00:00
|
|
|
__glxGetMscRate(struct glx_screen *psc,
|
2010-07-21 19:09:49 +01:00
|
|
|
int32_t * numerator, int32_t * denominator)
|
2007-11-06 19:34:15 +00:00
|
|
|
{
|
2018-12-14 13:20:10 +00:00
|
|
|
#if !defined(GLX_USE_WINDOWSGL)
|
2009-08-12 11:41:22 +01:00
|
|
|
XF86VidModeModeLine mode_line;
|
|
|
|
int dot_clock;
|
|
|
|
int i;
|
2010-02-04 23:47:54 +00:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
|
|
|
|
XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
|
|
|
|
unsigned n = dot_clock * 1000;
|
|
|
|
unsigned d = mode_line.vtotal * mode_line.htotal;
|
|
|
|
|
2007-11-06 19:34:15 +00:00
|
|
|
# define V_INTERLACE 0x010
|
|
|
|
# define V_DBLSCAN 0x020
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (mode_line.flags & V_INTERLACE)
|
|
|
|
n *= 2;
|
|
|
|
else if (mode_line.flags & V_DBLSCAN)
|
|
|
|
d *= 2;
|
|
|
|
|
|
|
|
/* The OML_sync_control spec requires that if the refresh rate is a
|
|
|
|
* whole number, that the returned numerator be equal to the refresh
|
|
|
|
* rate and the denominator be 1.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (n % d == 0) {
|
|
|
|
n /= d;
|
|
|
|
d = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
|
|
|
|
|
|
|
|
/* This is a poor man's way to reduce a fraction. It's far from
|
|
|
|
* perfect, but it will work well enough for this situation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i = 0; f[i] != 0; i++) {
|
|
|
|
while (n % f[i] == 0 && d % f[i] == 0) {
|
|
|
|
d /= f[i];
|
|
|
|
n /= f[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*numerator = n;
|
|
|
|
*denominator = d;
|
|
|
|
|
|
|
|
return True;
|
|
|
|
}
|
2018-12-14 13:20:10 +00:00
|
|
|
#endif
|
2010-02-04 23:47:54 +00:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
return False;
|
2007-11-06 19:34:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine the refresh rate of the specified drawable and display.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \param dpy Display whose refresh rate is to be determined.
|
|
|
|
* \param drawable Drawable whose refresh rate is to be determined.
|
|
|
|
* \param numerator Numerator of the refresh rate.
|
|
|
|
* \param demoninator Denominator of the refresh rate.
|
|
|
|
* \return If the refresh rate for the specified display and drawable could
|
|
|
|
* be calculated, True is returned. Otherwise False is returned.
|
2009-08-12 11:41:22 +01:00
|
|
|
*
|
2004-10-25 22:09:16 +01:00
|
|
|
* \note This function is implemented entirely client-side. A lot of other
|
|
|
|
* functionality is required to export GLX_OML_sync_control, so on
|
|
|
|
* XFree86 this function can be called for direct-rendering contexts
|
|
|
|
* when GLX_OML_sync_control appears in the client extension string.
|
|
|
|
*/
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN Bool
|
|
|
|
glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
|
|
|
|
int32_t * numerator, int32_t * denominator)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2018-12-11 16:20:40 +00:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) && !defined(GLX_USE_WINDOWSGL)
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable);
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
if (draw == NULL)
|
|
|
|
return False;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2013-12-15 10:37:55 +00:00
|
|
|
return __glxGetMscRate(draw->psc, numerator, denominator);
|
2004-10-25 22:09:16 +01:00
|
|
|
#else
|
2007-11-06 19:34:15 +00:00
|
|
|
(void) dpy;
|
|
|
|
(void) drawable;
|
2004-10-25 22:09:16 +01:00
|
|
|
(void) numerator;
|
|
|
|
(void) denominator;
|
|
|
|
#endif
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN int64_t
|
|
|
|
glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
|
|
|
|
int64_t target_msc, int64_t divisor, int64_t remainder)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-06-07 11:33:33 +01:00
|
|
|
if (gc == &dummyContext) /* no GLX for this */
|
2009-09-16 07:23:09 +01:00
|
|
|
return -1;
|
|
|
|
|
2010-04-01 08:10:28 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-07-28 20:33:09 +01:00
|
|
|
if (!pdraw || !gc->isDirect)
|
2010-04-01 08:10:28 +01:00
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
|
|
|
|
* error", but it also says "It [glXSwapBuffersMscOML] will return a value
|
|
|
|
* of -1 if the function failed because of errors detected in the input
|
|
|
|
* parameters"
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if (divisor < 0 || remainder < 0 || target_msc < 0)
|
2004-10-25 22:09:16 +01:00
|
|
|
return -1;
|
2009-08-12 11:41:22 +01:00
|
|
|
if (divisor > 0 && remainder >= divisor)
|
2004-10-25 22:09:16 +01:00
|
|
|
return -1;
|
|
|
|
|
2010-03-22 23:39:11 +00:00
|
|
|
if (target_msc == 0 && divisor == 0 && remainder == 0)
|
|
|
|
remainder = 1;
|
|
|
|
|
2009-09-16 07:23:09 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
|
|
|
if (psc->driScreen && psc->driScreen->swapBuffers)
|
|
|
|
return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
|
2012-11-13 16:06:37 +00:00
|
|
|
remainder, False);
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
2009-09-16 07:23:09 +01:00
|
|
|
|
|
|
|
return -1;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN Bool
|
|
|
|
glXWaitForMscOML(Display *dpy, GLXDrawable drawable, int64_t target_msc,
|
|
|
|
int64_t divisor, int64_t remainder, int64_t *ust,
|
|
|
|
int64_t *msc, int64_t *sbc)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
|
2009-08-12 11:41:22 +01:00
|
|
|
int ret;
|
2010-08-09 14:47:26 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
|
|
|
|
* error", but the return type in the spec is Bool.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if (divisor < 0 || remainder < 0 || target_msc < 0)
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
2009-08-12 11:41:22 +01:00
|
|
|
if (divisor > 0 && remainder >= divisor)
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
|
|
|
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2009-09-16 07:23:09 +01:00
|
|
|
if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
|
|
|
|
ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder,
|
|
|
|
ust, msc, sbc);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
2009-09-16 07:23:09 +01:00
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN Bool
|
|
|
|
glXWaitForSbcOML(Display *dpy, GLXDrawable drawable, int64_t target_sbc,
|
|
|
|
int64_t *ust, int64_t *msc, int64_t *sbc)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2010-04-02 08:12:59 +01:00
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
|
2009-08-12 11:41:22 +01:00
|
|
|
int ret;
|
2010-08-09 14:47:26 +01:00
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
|
|
|
|
* error", but the return type in the spec is Bool.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
if (target_sbc < 0)
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
2010-04-02 08:12:59 +01:00
|
|
|
|
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2010-02-19 20:28:26 +00:00
|
|
|
if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) {
|
2009-09-16 07:23:09 +01:00
|
|
|
ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-04-02 08:12:59 +01:00
|
|
|
#endif
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*@}*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mesa extension stubs. These will help reduce portability problems.
|
|
|
|
*/
|
|
|
|
/*@{*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Release all buffers associated with the specified GLX drawable.
|
|
|
|
*
|
|
|
|
* \todo
|
|
|
|
* This function was intended for stand-alone Mesa. The issue there is that
|
|
|
|
* the library doesn't get any notification when a window is closed. In
|
|
|
|
* DRI there is a similar but slightly different issue. When GLX 1.3 is
|
|
|
|
* supported, there are 3 different functions to destroy a drawable. It
|
|
|
|
* should be possible to create GLX protocol (or have it determine which
|
|
|
|
* protocol to use based on the type of the drawable) to have one function
|
|
|
|
* do the work of 3. For the direct-rendering case, this function could
|
|
|
|
* just call the driver's \c __DRIdrawableRec::destroyDrawable function.
|
|
|
|
* This would reduce the frequency with which \c __driGarbageCollectDrawables
|
|
|
|
* would need to be used. This really should be done as part of the new DRI
|
|
|
|
* interface work.
|
|
|
|
*
|
|
|
|
* \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
|
|
|
|
* __driGarbageCollectDrawables
|
|
|
|
* glXDestroyGLXPixmap
|
|
|
|
* glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
|
|
|
|
* glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
|
|
|
|
*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN Bool
|
|
|
|
glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
|
|
|
(void) dpy;
|
|
|
|
(void) d;
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC GLXPixmap
|
2009-08-12 11:41:22 +01:00
|
|
|
glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
|
|
|
|
Pixmap pixmap, Colormap cmap)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
|
|
|
(void) dpy;
|
|
|
|
(void) visual;
|
|
|
|
(void) pixmap;
|
|
|
|
(void) cmap;
|
|
|
|
return 0;
|
|
|
|
}
|
2009-08-12 11:41:22 +01:00
|
|
|
|
2006-08-29 16:38:19 +01:00
|
|
|
/*@}*/
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2006-08-29 16:38:19 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GLX_MESA_copy_sub_buffer
|
|
|
|
*/
|
2006-03-31 16:48:04 +01:00
|
|
|
#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN void
|
|
|
|
glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
|
|
|
|
int x, int y, int width, int height)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
xGLXVendorPrivateReq *req;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc;
|
2009-08-12 11:41:22 +01:00
|
|
|
GLXContextTag tag;
|
|
|
|
CARD32 *drawable_ptr;
|
|
|
|
INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
|
|
|
|
CARD8 opcode;
|
2006-03-31 16:48:04 +01:00
|
|
|
|
2010-07-26 20:50:02 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2009-08-12 11:41:22 +01:00
|
|
|
if (pdraw != NULL) {
|
2010-07-28 15:28:43 +01:00
|
|
|
struct glx_screen *psc = pdraw->psc;
|
2009-08-12 11:41:22 +01:00
|
|
|
if (psc->driScreen->copySubBuffer != NULL) {
|
2012-11-13 16:06:37 +00:00
|
|
|
(*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height, True);
|
2009-08-12 11:41:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2006-03-31 16:48:04 +01:00
|
|
|
#endif
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode)
|
|
|
|
return;
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
/*
|
2006-03-31 16:48:04 +01:00
|
|
|
** The calling thread may or may not have a current context. If it
|
|
|
|
** does, send the context tag so the server can do a flush.
|
|
|
|
*/
|
2009-08-12 11:41:22 +01:00
|
|
|
gc = __glXGetCurrentContext();
|
2016-06-07 11:33:33 +01:00
|
|
|
if ((gc != &dummyContext) && (dpy == gc->currentDpy) &&
|
2009-08-12 11:41:22 +01:00
|
|
|
((drawable == gc->currentDrawable) ||
|
|
|
|
(drawable == gc->currentReadable))) {
|
|
|
|
tag = gc->currentContextTag;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivate;
|
|
|
|
req->vendorCode = X_GLXvop_CopySubBufferMESA;
|
|
|
|
req->contextTag = tag;
|
|
|
|
|
|
|
|
drawable_ptr = (CARD32 *) (req + 1);
|
|
|
|
x_ptr = (INT32 *) (drawable_ptr + 1);
|
|
|
|
y_ptr = (INT32 *) (drawable_ptr + 2);
|
|
|
|
w_ptr = (INT32 *) (drawable_ptr + 3);
|
|
|
|
h_ptr = (INT32 *) (drawable_ptr + 4);
|
|
|
|
|
|
|
|
*drawable_ptr = drawable;
|
|
|
|
*x_ptr = x;
|
|
|
|
*y_ptr = y;
|
|
|
|
*w_ptr = width;
|
|
|
|
*h_ptr = height;
|
|
|
|
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2006-03-31 16:48:04 +01:00
|
|
|
}
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-05-21 15:36:56 +01:00
|
|
|
/*@{*/
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN void
|
|
|
|
glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
|
|
|
|
const int *attrib_list)
|
2010-05-21 15:36:56 +01:00
|
|
|
{
|
2021-03-19 17:39:01 +00:00
|
|
|
xGLXVendorPrivateReq *req;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2021-03-19 17:39:01 +00:00
|
|
|
CARD32 *drawable_ptr;
|
|
|
|
INT32 *buffer_ptr;
|
|
|
|
CARD32 *num_attrib_ptr;
|
|
|
|
CARD32 *attrib_ptr;
|
|
|
|
CARD8 opcode;
|
|
|
|
unsigned int i = 0;
|
|
|
|
|
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2021-03-19 17:39:01 +00:00
|
|
|
if (pdraw != NULL) {
|
|
|
|
struct glx_screen *psc = pdraw->psc;
|
|
|
|
if (psc->driScreen->bindTexImage != NULL)
|
|
|
|
(*psc->driScreen->bindTexImage) (pdraw, buffer, attrib_list);
|
2010-05-21 15:36:56 +01:00
|
|
|
|
|
|
|
return;
|
2021-03-19 17:39:01 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (attrib_list) {
|
|
|
|
while (attrib_list[i * 2] != None)
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivate;
|
|
|
|
req->vendorCode = X_GLXvop_BindTexImageEXT;
|
|
|
|
req->contextTag = gc->currentContextTag;
|
|
|
|
|
|
|
|
drawable_ptr = (CARD32 *) (req + 1);
|
|
|
|
buffer_ptr = (INT32 *) (drawable_ptr + 1);
|
|
|
|
num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
|
|
|
|
attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
|
|
|
|
|
|
|
|
*drawable_ptr = drawable;
|
|
|
|
*buffer_ptr = buffer;
|
|
|
|
*num_attrib_ptr = (CARD32) i;
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
if (attrib_list) {
|
|
|
|
while (attrib_list[i * 2] != None) {
|
|
|
|
*attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
|
|
|
|
*attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2010-05-21 15:36:56 +01:00
|
|
|
|
2021-03-19 17:39:01 +00:00
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2010-05-21 15:36:56 +01:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:40:19 +01:00
|
|
|
_X_HIDDEN void
|
|
|
|
glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
|
2010-05-21 15:36:56 +01:00
|
|
|
{
|
2021-03-19 17:39:01 +00:00
|
|
|
xGLXVendorPrivateReq *req;
|
2010-07-28 16:16:00 +01:00
|
|
|
struct glx_context *gc = __glXGetCurrentContext();
|
2021-03-19 17:39:01 +00:00
|
|
|
CARD32 *drawable_ptr;
|
|
|
|
INT32 *buffer_ptr;
|
|
|
|
CARD8 opcode;
|
|
|
|
|
|
|
|
#ifdef GLX_DIRECT_RENDERING
|
2021-05-03 13:38:02 +01:00
|
|
|
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
|
2021-03-19 17:39:01 +00:00
|
|
|
if (pdraw != NULL) {
|
|
|
|
struct glx_screen *psc = pdraw->psc;
|
|
|
|
if (psc->driScreen->releaseTexImage != NULL)
|
|
|
|
(*psc->driScreen->releaseTexImage) (pdraw, buffer);
|
2010-05-21 15:36:56 +01:00
|
|
|
|
|
|
|
return;
|
2021-03-19 17:39:01 +00:00
|
|
|
}
|
|
|
|
#endif
|
2010-05-21 15:36:56 +01:00
|
|
|
|
2021-03-19 17:39:01 +00:00
|
|
|
opcode = __glXSetupForCommand(dpy);
|
|
|
|
if (!opcode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LockDisplay(dpy);
|
|
|
|
GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
|
|
|
|
req->reqType = opcode;
|
|
|
|
req->glxCode = X_GLXVendorPrivate;
|
|
|
|
req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
|
|
|
|
req->contextTag = gc->currentContextTag;
|
|
|
|
|
|
|
|
drawable_ptr = (CARD32 *) (req + 1);
|
|
|
|
buffer_ptr = (INT32 *) (drawable_ptr + 1);
|
|
|
|
|
|
|
|
*drawable_ptr = drawable;
|
|
|
|
*buffer_ptr = buffer;
|
|
|
|
|
|
|
|
UnlockDisplay(dpy);
|
|
|
|
SyncHandle();
|
2010-05-21 15:36:56 +01:00
|
|
|
}
|
|
|
|
|
2006-08-29 16:38:19 +01:00
|
|
|
/*@}*/
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif /* GLX_USE_APPLEGL */
|
|
|
|
|
2004-10-25 22:09:16 +01:00
|
|
|
/*
|
|
|
|
** glXGetProcAddress support
|
|
|
|
*/
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
struct name_address_pair
|
|
|
|
{
|
2004-10-25 22:09:16 +01:00
|
|
|
const char *Name;
|
|
|
|
GLvoid *Address;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
|
|
|
|
#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
|
|
|
|
|
|
|
|
static const struct name_address_pair GLX_functions[] = {
|
|
|
|
/*** GLX_VERSION_1_0 ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXChooseVisual),
|
|
|
|
GLX_FUNCTION(glXCopyContext),
|
|
|
|
GLX_FUNCTION(glXCreateContext),
|
|
|
|
GLX_FUNCTION(glXCreateGLXPixmap),
|
|
|
|
GLX_FUNCTION(glXDestroyContext),
|
|
|
|
GLX_FUNCTION(glXDestroyGLXPixmap),
|
|
|
|
GLX_FUNCTION(glXGetConfig),
|
|
|
|
GLX_FUNCTION(glXGetCurrentContext),
|
|
|
|
GLX_FUNCTION(glXGetCurrentDrawable),
|
|
|
|
GLX_FUNCTION(glXIsDirect),
|
|
|
|
GLX_FUNCTION(glXMakeCurrent),
|
|
|
|
GLX_FUNCTION(glXQueryExtension),
|
|
|
|
GLX_FUNCTION(glXQueryVersion),
|
|
|
|
GLX_FUNCTION(glXSwapBuffers),
|
|
|
|
GLX_FUNCTION(glXUseXFont),
|
|
|
|
GLX_FUNCTION(glXWaitGL),
|
|
|
|
GLX_FUNCTION(glXWaitX),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_VERSION_1_1 ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXGetClientString),
|
|
|
|
GLX_FUNCTION(glXQueryExtensionsString),
|
|
|
|
GLX_FUNCTION(glXQueryServerString),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_VERSION_1_2 ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXGetCurrentDisplay),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_VERSION_1_3 ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXChooseFBConfig),
|
|
|
|
GLX_FUNCTION(glXCreateNewContext),
|
|
|
|
GLX_FUNCTION(glXCreatePbuffer),
|
|
|
|
GLX_FUNCTION(glXCreatePixmap),
|
|
|
|
GLX_FUNCTION(glXCreateWindow),
|
|
|
|
GLX_FUNCTION(glXDestroyPbuffer),
|
|
|
|
GLX_FUNCTION(glXDestroyPixmap),
|
|
|
|
GLX_FUNCTION(glXDestroyWindow),
|
|
|
|
GLX_FUNCTION(glXGetCurrentReadDrawable),
|
|
|
|
GLX_FUNCTION(glXGetFBConfigAttrib),
|
|
|
|
GLX_FUNCTION(glXGetFBConfigs),
|
|
|
|
GLX_FUNCTION(glXGetSelectedEvent),
|
|
|
|
GLX_FUNCTION(glXGetVisualFromFBConfig),
|
|
|
|
GLX_FUNCTION(glXMakeContextCurrent),
|
|
|
|
GLX_FUNCTION(glXQueryContext),
|
|
|
|
GLX_FUNCTION(glXQueryDrawable),
|
|
|
|
GLX_FUNCTION(glXSelectEvent),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2020-09-09 18:28:02 +01:00
|
|
|
/*** GLX_SGIX_fbconfig ***/
|
|
|
|
GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
|
|
|
|
GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
|
|
|
|
GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
|
|
|
|
GLX_FUNCTION(glXCreateContextWithConfigSGIX),
|
|
|
|
GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
|
|
|
|
GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
|
|
|
|
|
|
|
|
/*** GLX_ARB_get_proc_address ***/
|
|
|
|
GLX_FUNCTION(glXGetProcAddressARB),
|
|
|
|
|
|
|
|
/*** GLX 1.4 ***/
|
|
|
|
GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
|
|
|
|
|
2010-04-01 19:01:31 +01:00
|
|
|
#ifndef GLX_USE_APPLEGL
|
2004-10-25 22:09:16 +01:00
|
|
|
/*** GLX_SGI_swap_control ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXSwapIntervalSGI),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_SGI_video_sync ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXGetVideoSyncSGI),
|
|
|
|
GLX_FUNCTION(glXWaitVideoSyncSGI),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_SGI_make_current_read ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
|
|
|
|
GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_EXT_import_context ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXFreeContextEXT),
|
|
|
|
GLX_FUNCTION(glXGetContextIDEXT),
|
|
|
|
GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
|
|
|
|
GLX_FUNCTION(glXImportContextEXT),
|
|
|
|
GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_SGIX_pbuffer ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXCreateGLXPbufferSGIX),
|
|
|
|
GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
|
|
|
|
GLX_FUNCTION(glXQueryGLXPbufferSGIX),
|
|
|
|
GLX_FUNCTION(glXSelectEventSGIX),
|
|
|
|
GLX_FUNCTION(glXGetSelectedEventSGIX),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_MESA_copy_sub_buffer ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXCopySubBufferMESA),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_MESA_pixmap_colormap ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXCreateGLXPixmapMESA),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_MESA_release_buffers ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXReleaseBuffersMESA),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_MESA_swap_control ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXSwapIntervalMESA),
|
|
|
|
GLX_FUNCTION(glXGetSwapIntervalMESA),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
|
|
|
/*** GLX_OML_sync_control ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXWaitForSbcOML),
|
|
|
|
GLX_FUNCTION(glXWaitForMscOML),
|
|
|
|
GLX_FUNCTION(glXSwapBuffersMscOML),
|
|
|
|
GLX_FUNCTION(glXGetMscRateOML),
|
|
|
|
GLX_FUNCTION(glXGetSyncValuesOML),
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2006-02-07 00:39:56 +00:00
|
|
|
/*** GLX_EXT_texture_from_pixmap ***/
|
2020-09-09 17:40:19 +01:00
|
|
|
GLX_FUNCTION(glXBindTexImageEXT),
|
|
|
|
GLX_FUNCTION(glXReleaseTexImageEXT),
|
2020-09-09 19:00:35 +01:00
|
|
|
|
|
|
|
/*** GLX_EXT_swap_control ***/
|
|
|
|
GLX_FUNCTION(glXSwapIntervalEXT),
|
2010-04-01 19:01:31 +01:00
|
|
|
#endif
|
2006-02-07 00:39:56 +00:00
|
|
|
|
2014-06-02 18:52:15 +01:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_DRM)
|
2004-10-25 22:09:16 +01:00
|
|
|
/*** DRI configuration ***/
|
2009-08-12 11:41:22 +01:00
|
|
|
GLX_FUNCTION(glXGetScreenDriver),
|
|
|
|
GLX_FUNCTION(glXGetDriverConfig),
|
2004-10-25 22:09:16 +01:00
|
|
|
#endif
|
|
|
|
|
2011-11-30 19:12:49 +00:00
|
|
|
/*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/
|
|
|
|
GLX_FUNCTION(glXCreateContextAttribsARB),
|
|
|
|
|
2013-02-16 06:35:24 +00:00
|
|
|
/*** GLX_MESA_query_renderer ***/
|
|
|
|
GLX_FUNCTION(glXQueryRendererIntegerMESA),
|
|
|
|
GLX_FUNCTION(glXQueryRendererStringMESA),
|
|
|
|
GLX_FUNCTION(glXQueryCurrentRendererIntegerMESA),
|
|
|
|
GLX_FUNCTION(glXQueryCurrentRendererStringMESA),
|
|
|
|
|
2009-08-12 11:41:22 +01:00
|
|
|
{NULL, NULL} /* end of list */
|
2004-10-25 22:09:16 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const GLvoid *
|
|
|
|
get_glx_proc_address(const char *funcName)
|
|
|
|
{
|
|
|
|
GLuint i;
|
|
|
|
|
|
|
|
/* try static functions */
|
|
|
|
for (i = 0; GLX_functions[i].Name; i++) {
|
|
|
|
if (strcmp(GLX_functions[i].Name, funcName) == 0)
|
2009-08-12 11:41:22 +01:00
|
|
|
return GLX_functions[i].Address;
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the address of a named GL function. This is the pre-GLX 1.4 name for
|
|
|
|
* \c glXGetProcAddress.
|
|
|
|
*
|
|
|
|
* \param procName Name of a GL or GLX function.
|
|
|
|
* \returns A pointer to the named function
|
|
|
|
*
|
|
|
|
* \sa glXGetProcAddress
|
|
|
|
*/
|
2016-05-11 19:01:53 +01:00
|
|
|
_GLX_PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
|
2004-10-25 22:09:16 +01:00
|
|
|
{
|
2009-08-12 11:41:22 +01:00
|
|
|
typedef void (*gl_function) (void);
|
2004-10-25 22:09:16 +01:00
|
|
|
gl_function f;
|
|
|
|
|
|
|
|
|
|
|
|
/* Search the table of GLX and internal functions first. If that
|
|
|
|
* fails and the supplied name could be a valid core GL name, try
|
|
|
|
* searching the core GL function table. This check is done to prevent
|
|
|
|
* DRI based drivers from searching the core GL function table for
|
|
|
|
* internal API functions.
|
|
|
|
*/
|
|
|
|
f = (gl_function) get_glx_proc_address((const char *) procName);
|
2009-08-12 11:41:22 +01:00
|
|
|
if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
|
|
|
|
&& (procName[2] != 'X')) {
|
2017-04-13 17:17:45 +01:00
|
|
|
#ifdef GLX_INDIRECT_RENDERING
|
2010-12-26 10:24:13 +00:00
|
|
|
f = (gl_function) __indirect_get_proc_address((const char *) procName);
|
2012-01-24 16:34:42 +00:00
|
|
|
#endif
|
2010-12-26 10:24:13 +00:00
|
|
|
if (!f)
|
|
|
|
f = (gl_function) _glapi_get_proc_address((const char *) procName);
|
2021-03-18 15:36:12 +00:00
|
|
|
#ifdef GLX_USE_APPLEGL
|
|
|
|
if (!f)
|
|
|
|
f = applegl_get_proc_address((const char *) procName);
|
|
|
|
#endif
|
2004-10-25 22:09:16 +01:00
|
|
|
}
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the address of a named GL function. This is the GLX 1.4 name for
|
|
|
|
* \c glXGetProcAddressARB.
|
|
|
|
*
|
|
|
|
* \param procName Name of a GL or GLX function.
|
|
|
|
* \returns A pointer to the named function
|
|
|
|
*
|
|
|
|
* \sa glXGetProcAddressARB
|
|
|
|
*/
|
2016-12-05 19:52:44 +00:00
|
|
|
_GLX_PUBLIC
|
|
|
|
GLX_ALIAS(__GLXextFuncPtr, glXGetProcAddress,
|
|
|
|
(const GLubyte * procName),
|
|
|
|
(procName), glXGetProcAddressARB)
|
2004-10-25 22:09:16 +01:00
|
|
|
|
2016-03-03 17:43:53 +00:00
|
|
|
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
|
|
|
|
2016-11-02 17:59:22 +00:00
|
|
|
PUBLIC int
|
2016-03-03 17:43:53 +00:00
|
|
|
MesaGLInteropGLXQueryDeviceInfo(Display *dpy, GLXContext context,
|
2016-05-30 10:56:33 +01:00
|
|
|
struct mesa_glinterop_device_info *out)
|
2016-03-03 17:43:53 +00:00
|
|
|
{
|
|
|
|
struct glx_context *gc = (struct glx_context*)context;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
__glXLock();
|
|
|
|
|
|
|
|
if (!gc || gc->xid == None || !gc->isDirect) {
|
|
|
|
__glXUnlock();
|
|
|
|
return MESA_GLINTEROP_INVALID_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gc->vtable->interop_query_device_info) {
|
|
|
|
__glXUnlock();
|
|
|
|
return MESA_GLINTEROP_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = gc->vtable->interop_query_device_info(gc, out);
|
|
|
|
__glXUnlock();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-11-02 17:59:22 +00:00
|
|
|
PUBLIC int
|
2016-03-03 17:43:53 +00:00
|
|
|
MesaGLInteropGLXExportObject(Display *dpy, GLXContext context,
|
2016-05-30 10:56:33 +01:00
|
|
|
struct mesa_glinterop_export_in *in,
|
|
|
|
struct mesa_glinterop_export_out *out)
|
2016-03-03 17:43:53 +00:00
|
|
|
{
|
|
|
|
struct glx_context *gc = (struct glx_context*)context;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
__glXLock();
|
|
|
|
|
|
|
|
if (!gc || gc->xid == None || !gc->isDirect) {
|
|
|
|
__glXUnlock();
|
|
|
|
return MESA_GLINTEROP_INVALID_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gc->vtable->interop_export_object) {
|
|
|
|
__glXUnlock();
|
|
|
|
return MESA_GLINTEROP_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = gc->vtable->interop_export_object(gc, in, out);
|
|
|
|
__glXUnlock();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) */
|