glx: Require GLX 1.3

GLX is a means to the end of direct rendered GL, really. Our indirect
protocol support has been largely untouched forever, anyone who wants it
can find it in amber. We're not going to drop or intentionally break it
(indirect support), but we're also not going to try super hard to
preserve its quirks anymore.

xserver has typically supported GLX 1.4 since 2009 (xserver 1.8, ad5c0d9e)
and unconditionally since 2016 (xserver 1.19, 36bcbf76). Assuming GLX
1.3 internally will let us fix some GLX drawable lifetime issues.

Acked-by: David Heidelberg <david.heidelberg@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20300>
This commit is contained in:
Adam Jackson 2022-12-05 14:59:22 -05:00 committed by Marge Bot
parent 19c57ea3bf
commit 4ccd253588
6 changed files with 73 additions and 322 deletions

View File

@ -96,7 +96,7 @@ __glX_send_client_info(struct glx_display *glx_dpy)
/* There are three possible flavors of the client info structure that the
* client could send to the server. The version sent depends on the
* combination of GLX versions and extensions supported by the client and
* the server. This client only supports GLX major version 1.
* the server. This client only supports GLX version >= 1.3.
*
* Server supports Client sends
* ----------------------------------------------------------------------
@ -117,9 +117,6 @@ __glX_send_client_info(struct glx_display *glx_dpy)
* requirement in this case does not seem like a limitation.
*/
if (glx_dpy->minorVersion == 0)
return;
/* Determine whether any screen on the server supports either of the
* create-context extensions.
*/

View File

@ -54,10 +54,6 @@
*
* This function is used to implement \c glXSelectEvent and
* \c glXSelectEventSGIX.
*
* \note
* This function dynamically determines whether to use the SGIX_pbuffer
* version of the protocol or the GLX 1.3 version of the protocol.
*/
static void
ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
@ -77,31 +73,14 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
LockDisplay(dpy);
if (priv->minorVersion >= 3) {
xGLXChangeDrawableAttributesReq *req;
xGLXChangeDrawableAttributesReq *req;
GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
output = (CARD32 *) (req + 1);
GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
output = (CARD32 *) (req + 1);
req->reqType = opcode;
req->glxCode = X_GLXChangeDrawableAttributes;
req->drawable = drawable;
req->numAttribs = (CARD32) num_attribs;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq);
output = (CARD32 *) (vpreq + 1);
vpreq->reqType = opcode;
vpreq->glxCode = X_GLXVendorPrivateWithReply;
vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
output[0] = (CARD32) drawable;
output[1] = num_attribs;
output += 2;
}
req->reqType = opcode;
req->glxCode = X_GLXChangeDrawableAttributes;
req->drawable = drawable;
req->numAttribs = (CARD32) num_attribs;
(void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
@ -209,10 +188,6 @@ DestroyDRIDrawable(Display *dpy, GLXDrawable drawable)
* This function is used to implement \c glXGetSelectedEvent and
* \c glXGetSelectedEventSGIX.
*
* \note
* This function dynamically determines whether to use the SGIX_pbuffer
* version of the protocol or the GLX 1.3 version of the protocol.
*
* \todo
* The number of attributes returned is likely to be small, probably less than
* 10. Given that, this routine should try to use an array on the stack to
@ -304,25 +279,11 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
LockDisplay(dpy);
if (priv->minorVersion >= 3) {
xGLXGetDrawableAttributesReq *req;
GetReq(GLXGetDrawableAttributes, req);
req->reqType = opcode;
req->glxCode = X_GLXGetDrawableAttributes;
req->drawable = drawable;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
data = (CARD32 *) (vpreq + 1);
data[0] = (CARD32) drawable;
vpreq->reqType = opcode;
vpreq->glxCode = X_GLXVendorPrivateWithReply;
vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
}
xGLXGetDrawableAttributesReq *req;
GetReq(GLXGetDrawableAttributes, req);
req->reqType = opcode;
req->glxCode = X_GLXGetDrawableAttributes;
req->drawable = drawable;
_XReply(dpy, (xReply *) & reply, 0, False);
@ -334,7 +295,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
length = reply.length;
if (length) {
num_attributes = (priv->minorVersion > 2) ? reply.numAttribs : length / 2;
num_attributes = reply.numAttribs;
data = malloc(length * sizeof(CARD32));
if (data == NULL) {
/* Throw data on the floor */
@ -533,10 +494,6 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
*
* This function is used to implement \c glXCreatePbuffer and
* \c glXCreateGLXPbufferSGIX.
*
* \note
* This function dynamically determines whether to use the SGIX_pbuffer
* version of the protocol or the GLX 1.3 version of the protocol.
*/
static GLXDrawable
CreatePbuffer(Display * dpy, struct glx_config *config,
@ -548,7 +505,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
CARD32 *data;
CARD8 opcode;
unsigned int i;
GLboolean glx_1_3 = GL_FALSE;
if (priv == NULL)
return None;
@ -566,46 +522,24 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
LockDisplay(dpy);
id = XAllocID(dpy);
if (priv->minorVersion >= 3) {
xGLXCreatePbufferReq *req;
unsigned int extra = (size_in_attribs) ? 0 : 2;
xGLXCreatePbufferReq *req;
unsigned int extra = (size_in_attribs) ? 0 : 2;
GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
data = (CARD32 *) (req + 1);
glx_1_3 = GL_TRUE;
req->reqType = opcode;
req->glxCode = X_GLXCreatePbuffer;
req->screen = config->screen;
req->fbconfig = config->fbconfigID;
req->pbuffer = id;
req->numAttribs = i + extra;
GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
data = (CARD32 *) (req + 1);
req->reqType = opcode;
req->glxCode = X_GLXCreatePbuffer;
req->screen = config->screen;
req->fbconfig = config->fbconfigID;
req->pbuffer = id;
req->numAttribs = i + extra;
if (!size_in_attribs) {
data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
data[(2 * i) + 1] = width;
data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
data[(2 * i) + 3] = height;
data += 4;
}
}
else {
xGLXVendorPrivateReq *vpreq;
GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
data = (CARD32 *) (vpreq + 1);
vpreq->reqType = opcode;
vpreq->glxCode = X_GLXVendorPrivate;
vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
data[0] = config->screen;
data[1] = config->fbconfigID;
data[2] = id;
data[3] = width;
data[4] = height;
data += 5;
if (!size_in_attribs) {
data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
data[(2 * i) + 1] = width;
data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
data[(2 * i) + 3] = height;
data += 4;
}
(void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
@ -615,8 +549,7 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
/* xserver created a pixmap with the same id as pbuffer */
if (!CreateDRIDrawable(dpy, config, id, id, GLX_PBUFFER_BIT, attrib_list, i)) {
CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
protocolDestroyDrawable(dpy, id, o);
protocolDestroyDrawable(dpy, id, X_GLXDestroyPbuffer);
id = None;
}
@ -628,10 +561,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
*
* This function is used to implement \c glXDestroyPbuffer and
* \c glXDestroyGLXPbufferSGIX.
*
* \note
* This function dynamically determines whether to use the SGIX_pbuffer
* version of the protocol or the GLX 1.3 version of the protocol.
*/
static void
DestroyPbuffer(Display * dpy, GLXDrawable drawable)
@ -649,27 +578,11 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable)
LockDisplay(dpy);
if (priv->minorVersion >= 3) {
xGLXDestroyPbufferReq *req;
GetReq(GLXDestroyPbuffer, req);
req->reqType = opcode;
req->glxCode = X_GLXDestroyPbuffer;
req->pbuffer = (GLXPbuffer) drawable;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
CARD32 *data;
GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
data = (CARD32 *) (vpreq + 1);
data[0] = (CARD32) drawable;
vpreq->reqType = opcode;
vpreq->glxCode = X_GLXVendorPrivateWithReply;
vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
}
xGLXDestroyPbufferReq *req;
GetReq(GLXDestroyPbuffer, req);
req->reqType = opcode;
req->glxCode = X_GLXDestroyPbuffer;
req->pbuffer = (GLXPbuffer) drawable;
UnlockDisplay(dpy);
SyncHandle();

View File

@ -363,27 +363,6 @@ CreateContext(Display *dpy, int generic_id, struct glx_config *config,
break;
}
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);
req->fbconfig = generic_id;
req->screen = config->screen;
req->renderType = renderType;
req->shareList = shareList ? shareList->xid : None;
req->isDirect = gc->isDirect;
break;
}
default:
/* What to do here? This case is the sign of an internal error. It
* should never be reachable.
@ -1423,28 +1402,12 @@ glXImportContextEXT(Display *dpy, GLXContextID contextID)
/* Send the glXQueryContextInfoEXT request */
LockDisplay(dpy);
if (priv->minorVersion >= 3) {
xGLXQueryContextReq *req;
xGLXQueryContextReq *req;
GetReq(GLXQueryContext, req);
GetReq(GLXQueryContext, req);
req->reqType = opcode;
req->glxCode = X_GLXQueryContext;
req->context = contextID;
}
else {
xGLXVendorPrivateReq *vpreq;
xGLXQueryContextInfoEXTReq *req;
GetReqExtra(GLXVendorPrivate,
sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
vpreq);
req = (xGLXQueryContextInfoEXTReq *) vpreq;
req->reqType = opcode;
req->glxCode = X_GLXVendorPrivateWithReply;
req->vendorCode = X_GLXvop_QueryContextInfoEXT;
req->context = contextID;
}
req->reqType = opcode;
req->glxCode = X_GLXQueryContext;
req->context = contextID;
if (_XReply(dpy, (xReply *) & reply, 0, False) &&
reply.n < (INT32_MAX / 2)) {
@ -1954,94 +1917,23 @@ glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
GLXFBConfigSGIX fbconfig,
Pixmap pixmap)
{
#ifndef GLX_USE_APPLEGL
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXCreateGLXPixmapWithConfigSGIXReq *req;
GLXPixmap xid = None;
CARD8 opcode;
struct glx_screen *psc;
#endif
struct glx_config *config = (struct glx_config *) fbconfig;
if ((dpy == NULL) || (config == NULL)) {
return None;
}
#ifdef GLX_USE_APPLEGL
if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config))
return None;
return pixmap;
#else
psc = GetGLXScreenConfigs(dpy, config->screen);
if ((psc != NULL)
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
opcode = __glXSetupForCommand(dpy);
if (!opcode) {
return None;
}
/* 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;
req->screen = config->screen;
req->fbconfig = config->fbconfigID;
req->pixmap = pixmap;
req->glxpixmap = xid = XAllocID(dpy);
UnlockDisplay(dpy);
SyncHandle();
}
return xid;
#endif
}
_GLX_PUBLIC GLXContext
glXCreateContextWithConfigSGIX(Display * dpy,
GLXFBConfigSGIX fbconfig, int renderType,
GLXContext shareList, Bool allowDirect)
{
GLXContext gc = NULL;
struct glx_config *config = (struct glx_config *) fbconfig;
struct glx_screen *psc;
if ((dpy == NULL) || (config == NULL)) {
return None;
}
psc = GetGLXScreenConfigs(dpy, config->screen);
if ((psc != NULL)
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
gc = CreateContext(dpy, config->fbconfigID, config, shareList,
allowDirect,
X_GLXvop_CreateContextWithConfigSGIX, renderType);
}
return gc;
return glXCreatePixmap(dpy, fbconfig, pixmap, NULL);
}
_GLX_PUBLIC GLX_ALIAS(GLXContext, glXCreateContextWithConfigSGIX,
(Display *dpy, GLXFBConfigSGIX fbconfig,
int renderType, GLXContext shareList, Bool direct),
(dpy, config, renderType, shareList, direct),
glXCreateNewContext)
_GLX_PUBLIC GLXFBConfigSGIX
glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
{
struct glx_display *priv;
struct glx_screen *psc = NULL;
int attrib_list[] = { GLX_VISUAL_ID, vis->visualid, None };
int nconfigs = 0;
if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success)
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
&& (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs,
vis->visualid);
}
return NULL;
return (GLXFBConfigSGIX)
glXChooseFBConfig(dpy, vis->screen, attrib_list, &nconfigs);
}
#ifndef GLX_USE_APPLEGL

View File

@ -707,8 +707,6 @@ static GLboolean
getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
{
xGLXGetFBConfigsReq *fb_req;
xGLXGetFBConfigsSGIXReq *sgi_req;
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXGetFBConfigsReply reply;
Display *dpy = priv->dpy;
@ -721,24 +719,10 @@ getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
LockDisplay(dpy);
psc->configs = NULL;
if (priv->minorVersion >= 3) {
GetReq(GLXGetFBConfigs, fb_req);
fb_req->reqType = priv->codes.major_opcode;
fb_req->glxCode = X_GLXGetFBConfigs;
fb_req->screen = screen;
}
else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
GetReqExtra(GLXVendorPrivateWithReply,
sz_xGLXGetFBConfigsSGIXReq -
sz_xGLXVendorPrivateWithReplyReq, vpreq);
sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
sgi_req->reqType = priv->codes.major_opcode;
sgi_req->glxCode = X_GLXVendorPrivateWithReply;
sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
sgi_req->screen = screen;
}
else
goto out;
GetReq(GLXGetFBConfigs, fb_req);
fb_req->reqType = priv->codes.major_opcode;
fb_req->glxCode = X_GLXGetFBConfigs;
fb_req->screen = screen;
if (!_XReply(dpy, (xReply *) & reply, 0, False))
goto out;
@ -876,13 +860,11 @@ __glXInitialize(Display * dpy)
dpyPriv->codes = *codes;
dpyPriv->dpy = dpy;
/* This GLX implementation requires X_GLXQueryExtensionsString
* and X_GLXQueryServerString, which are new in GLX 1.1.
*/
/* This GLX implementation requires GLX 1.3 */
if (!QueryVersion(dpy, dpyPriv->codes.major_opcode,
&majorVersion, &dpyPriv->minorVersion)
|| (majorVersion != 1)
|| (majorVersion == 1 && dpyPriv->minorVersion < 1)) {
|| (majorVersion == 1 && dpyPriv->minorVersion < 3)) {
free(dpyPriv);
return NULL;
}

View File

@ -100,40 +100,15 @@ SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id,
req->oldContextTag = gc_tag;
}
else {
struct glx_display *priv = __glXInitialize(dpy);
xGLXMakeContextCurrentReq *req;
/* If the server can support the GLX 1.3 version, we should
* perfer that. Not only that, some servers support GLX 1.3 but
* not the SGI extension.
*/
if (priv->minorVersion >= 3) {
xGLXMakeContextCurrentReq *req;
GetReq(GLXMakeContextCurrent, req);
req->reqType = opcode;
req->glxCode = X_GLXMakeContextCurrent;
req->drawable = draw;
req->readdrawable = read;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXMakeCurrentReadSGIReq *req;
GetReqExtra(GLXVendorPrivateWithReply,
sz_xGLXMakeCurrentReadSGIReq -
sz_xGLXVendorPrivateWithReplyReq, vpreq);
req = (xGLXMakeCurrentReadSGIReq *) vpreq;
req->reqType = opcode;
req->glxCode = X_GLXVendorPrivateWithReply;
req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
req->drawable = draw;
req->readable = read;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
GetReq(GLXMakeContextCurrent, req);
req->reqType = opcode;
req->glxCode = X_GLXMakeContextCurrent;
req->drawable = draw;
req->readdrawable = read;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
ret = _XReply(dpy, (xReply *) &reply, 0, False);

View File

@ -294,22 +294,14 @@ glX_send_client_info_test::common_protocol_expected_true_test(unsigned major,
EXPECT_TRUE(*value);
}
TEST_F(glX_send_client_info_test, doesnt_send_ClientInfo_for_1_0)
{
/* The glXClientInfo protocol was added in GLX 1.1. Verify that no
* glXClientInfo is sent to a GLX server that only has GLX 1.0.
*/
common_protocol_expected_false_test(1, 0, "", &ClientInfo_was_sent);
}
TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_0)
TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_3)
{
/* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
* GLX_ARB_create_context extension. Verify that no glXSetClientInfoARB is
* sent to a GLX server that only has GLX 1.0 regardless of the extension
* sent to a GLX server that only has GLX 1.3 regardless of the extension
* setting.
*/
common_protocol_expected_false_test(1, 0,
common_protocol_expected_false_test(1, 3,
"GLX_ARB_create_context",
&SetClientInfoARB_was_sent);
}
@ -318,10 +310,10 @@ TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_1)
{
/* The glXSetClientInfoARB protocol was added in GLX 1.4 with the
* GLX_ARB_create_context extension. Verify that no glXSetClientInfoARB is
* sent to a GLX server that only has GLX 1.0 regardless of the extension
* sent to a GLX server that only has GLX 1.3 regardless of the extension
* setting.
*/
common_protocol_expected_false_test(1, 1,
common_protocol_expected_false_test(1, 3,
"GLX_ARB_create_context",
&SetClientInfoARB_was_sent);
}
@ -379,14 +371,14 @@ TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfoARB_for_1_4_with_prof
&SetClientInfoARB_was_sent);
}
TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_0)
TEST_F(glX_send_client_info_test, doesnt_send_SetClientInfo2ARB_for_1_3)
{
/* The glXSetClientInfo2ARB protocol was added in GLX 1.4 with the
* GLX_ARB_create_context_profile extension. Verify that no
* glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.0
* glXSetClientInfo2ARB is sent to a GLX server that only has GLX 1.3
* regardless of the extension setting.
*/
common_protocol_expected_false_test(1, 0,
common_protocol_expected_false_test(1, 3,
"GLX_ARB_create_context_profile",
&SetClientInfo2ARB_was_sent);
}