glx: Lift sending the MakeCurrent request to top-level code
authorAdam Jackson <ajax@redhat.com>
Tue, 14 Nov 2017 20:13:04 +0000 (15:13 -0500)
committerAdam Jackson <ajax@redhat.com>
Tue, 24 Sep 2019 00:39:01 +0000 (20:39 -0400)
commit999c2aed8826f403b071f52b040ce25b56d35f9d
tree09458e714f9954fc30ee54009781a778973e2178
parent01e437988d7b34065059cc1715aedd09adaf5cdd
glx: Lift sending the MakeCurrent request to top-level code

Somewhat terrifyingly, we never sent this for direct contexts, which
means the server never knew the context/drawable bindings. To handle
this sanely, pull the request code up out of the indirect backend, and
rewrite the context switch path to call it as appropriate.  This
attempts to preserve the existing behavior of not calling unbind() on
the context if its refcount would not drop to zero.

Of course, you can't just do this indiscriminately, because this is GLX
and extant X servers have bugs and everything is terrible. To wit:

- For 1.20.x prior to 1.20.6, you can bind a direct context once, but
the second time you try to modify the context's binding you will get
GLXBadContextTag. This includes unbinding the context. And "deleting"
the context will leak memory, because it will still appear to be
current.

- For 1.19 and earlier, glXMakeCurrent(dpy, None, ctx) should be legal
for GL 3.0+ contexts, but the server will throw BadMatch.

To guard against this, we only send the request for indirect contexts
unless the server is known good, and only mention one context at a time
in such a request; if switching between contexts, we first unbind the
old, and then bind the new. Note that the second VendorRelease() version
is to catch XFree86 4.x and Xorg [67].x, which almost certainly have the
above bugs. Other servers might report different version numbers here,
but we can't do direct rendering against them, so this should be safe.

Fixes glx-make-context, glx-multi-window-single-context and
glx-query-drawable-glx_fbconfig_id-window. Sufficiently old piglit will
regress on glx-make-glxdrawable-current (throwing BadMatch), which is
fixed by mesa/piglit!116.
src/glx/glxcurrent.c
src/glx/indirect_glx.c