Xephyr: GLX: Support MakeContextCurrent and MakeCurrentReadSGI

We need to pass these requests through to the host server in the same
way we do glXMakeCurrent.  Generalise the existing MakeCurrent
submission into once that will send MakeCurrent, MakeContextCurrent or
MakeCurrentReadSGI, depending on the request and the host server's
capabilities, and add decoding/hijack support for incoming
MakeContextCurrent and MakeCurrentReadSGI requests.

Fixes Clutter → Xephyr → VirtualBox.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Daniel Stone 2012-09-07 18:10:35 +01:00
parent 0b02150c27
commit 11afebc92c
3 changed files with 153 additions and 30 deletions

View File

@ -65,6 +65,10 @@ int ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXGetString(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXGetStringSwap(__GLXclientState * a_cl, GLbyte * a_pc);
int ephyrGLXGetIntegerv(__GLXclientState * a_cl, GLbyte * a_pc);
@ -123,14 +127,24 @@ ephyrHijackGLXExtension(void)
dispatch_functions[61][0] = ephyrGLXGetIntegerv;
dispatch_functions[61][1] = ephyrGLXGetIntegervSwap;
dispatch_functions[X_GLXMakeContextCurrent][0] =
ephyrGLXMakeContextCurrent;
dispatch_functions[X_GLXMakeContextCurrent][1] =
ephyrGLXMakeContextCurrentSwap;
/*
* hijack some vendor priv entry point dispatch functions
*/
dispatch_functions = VendorPriv_dispatch_info.dispatch_functions;
dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX;
dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap;
dispatch_functions[89][0] = ephyrGLXMakeCurrentReadSGI;
dispatch_functions[89][1] = ephyrGLXMakeCurrentReadSGISwap;
EPHYR_LOG("hijacked glx entry points to forward requests to host X\n");
return TRUE;
}
@ -505,26 +519,34 @@ ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc)
}
static int
ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap)
ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLXDrawable write,
GLXDrawable read, GLXContextTag ctx,
GLXContextTag old_ctx, Bool a_do_swap)
{
int res = BadImplementation;
xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
xGLXMakeCurrentReply reply;
DrawablePtr drawable = NULL;
GLXContextTag contextTag = 0;
int rc = 0;
DrawablePtr drawableR = NULL, drawableW = NULL;
GLXContextTag new_ctx = 0;
EPHYR_LOG("enter\n");
rc = dixLookupDrawable(&drawable,
req->drawable, a_cl->client, 0, DixReadAccess);
EPHYR_RETURN_VAL_IF_FAIL(drawable, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(drawable->pScreen, BadValue);
EPHYR_LOG("screen nummber requested:%d\n", drawable->pScreen->myNum);
res = dixLookupDrawable(&drawableW, write, a_cl->client, 0, DixReadAccess);
EPHYR_RETURN_VAL_IF_FAIL(drawableW, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(drawableW->pScreen, BadValue);
EPHYR_LOG("screen nummber requested:%d\n", drawableW->pScreen->myNum);
if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawable->pScreen->myNum),
req->context,
req->oldContextTag,
(int *) &contextTag)) {
if (read != write) {
res = dixLookupDrawable(&drawableR, read, a_cl->client, 0,
DixReadAccess);
EPHYR_RETURN_VAL_IF_FAIL(drawableR, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(drawableR->pScreen, BadValue);
}
else {
drawableR = drawableW;
}
if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawableW->pScreen->myNum),
hostx_get_window(drawableR->pScreen->myNum),
ctx, old_ctx, (int *) &new_ctx)) {
EPHYR_LOG_ERROR("ephyrHostGLXMakeCurrent() failed\n");
goto out;
}
@ -532,7 +554,7 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap)
.type = X_Reply,
.sequenceNumber = a_cl->client->sequence,
.length = 0,
.contextTag = contextTag
.contextTag = new_ctx
};
if (a_do_swap) {
__GLX_DECLARE_SWAP_VARIABLES;
@ -551,13 +573,71 @@ ephyrGLXMakeCurrentReal(__GLXclientState * a_cl, GLbyte * a_pc, Bool a_do_swap)
int
ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc)
{
return ephyrGLXMakeCurrentReal(a_cl, a_pc, FALSE);
xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable,
req->context, req->oldContextTag, FALSE);
}
int
ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc)
{
return ephyrGLXMakeCurrentReal(a_cl, a_pc, TRUE);
xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
__GLX_DECLARE_SWAP_VARIABLES;
__GLX_SWAP_INT(&req->drawable);
__GLX_SWAP_INT(&req->context);
__GLX_SWAP_INT(&req->oldContextTag);
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable,
req->context, req->oldContextTag, TRUE);
}
int
ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc)
{
xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc;
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable,
req->context, req->oldContextTag, FALSE);
}
int
ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc)
{
xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc;
__GLX_DECLARE_SWAP_VARIABLES;
__GLX_SWAP_INT(&req->drawable);
__GLX_SWAP_INT(&req->readable);
__GLX_SWAP_INT(&req->context);
__GLX_SWAP_INT(&req->oldContextTag);
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable,
req->context, req->oldContextTag, TRUE);
}
int
ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc)
{
xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc;
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable,
req->context, req->oldContextTag, FALSE);
}
int
ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc)
{
xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc;
__GLX_DECLARE_SWAP_VARIABLES;
__GLX_SWAP_INT(&req->drawable);
__GLX_SWAP_INT(&req->readdrawable);
__GLX_SWAP_INT(&req->context);
__GLX_SWAP_INT(&req->oldContextTag);
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable,
req->context, req->oldContextTag, TRUE);
}
static int

View File

@ -52,6 +52,8 @@
#include "ephyrlog.h"
#include "hostx.h"
static int glx_major, glx_minor;
enum VisualConfRequestType {
EPHYR_GET_FB_CONFIG,
EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX,
@ -99,6 +101,12 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor)
EPHYR_RETURN_VAL_IF_FAIL(a_major && a_minor, FALSE);
EPHYR_LOG("enter\n");
if (glx_major) {
*a_major = glx_major;
*a_minor = glx_minor;
return TRUE;
}
if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) {
EPHYR_LOG_ERROR("failed to get major opcode\n");
goto out;
@ -117,8 +125,8 @@ ephyrHostGLXQueryVersion(int *a_major, int *a_minor)
UnlockDisplay(dpy);
SyncHandle();
*a_major = reply.majorVersion;
*a_minor = reply.minorVersion;
*a_major = glx_major = reply.majorVersion;
*a_minor = glx_minor = reply.minorVersion;
EPHYR_LOG("major:%d, minor:%d\n", *a_major, *a_minor);
@ -512,20 +520,19 @@ ephyrHostDestroyContext(int a_ctxt_id)
}
Bool
ephyrHostGLXMakeCurrent(int a_drawable,
ephyrHostGLXMakeCurrent(int a_drawable, int a_readable,
int a_glx_ctxt_id, int a_old_ctxt_tag, int *a_ctxt_tag)
{
Bool is_ok = FALSE;
Display *dpy = hostx_get_display();
int32_t major_opcode = 0;
int remote_glx_ctxt_id = 0;
xGLXMakeCurrentReq *req;
xGLXMakeCurrentReply reply;
EPHYR_RETURN_VAL_IF_FAIL(a_ctxt_tag, FALSE);
EPHYR_LOG("enter. drawable:%d, context:%d, oldtag:%d\n",
a_drawable, a_glx_ctxt_id, a_old_ctxt_tag);
EPHYR_LOG("enter. drawable:%d, read:%d, context:%d, oldtag:%d\n",
a_drawable, a_readable, a_glx_ctxt_id, a_old_ctxt_tag);
if (!ephyrHostGLXGetMajorOpcode(&major_opcode)) {
EPHYR_LOG_ERROR("failed to get major opcode\n");
@ -538,12 +545,48 @@ ephyrHostGLXMakeCurrent(int a_drawable,
LockDisplay(dpy);
GetReq(GLXMakeCurrent, req);
req->reqType = major_opcode;
req->glxCode = X_GLXMakeCurrent;
req->drawable = a_drawable;
req->context = remote_glx_ctxt_id;
req->oldContextTag = a_old_ctxt_tag;
/* If both drawables are the same, use the old MakeCurrent request.
* Otherwise, if we have GLX 1.3 or higher, use the MakeContextCurrent
* request which supports separate read and draw targets. Failing that,
* try the SGI MakeCurrentRead extension. Logic cribbed from Mesa. */
if (a_drawable == a_readable) {
xGLXMakeCurrentReq *req;
GetReq(GLXMakeCurrent, req);
req->reqType = major_opcode;
req->glxCode = X_GLXMakeCurrent;
req->drawable = a_drawable;
req->context = remote_glx_ctxt_id;
req->oldContextTag = a_old_ctxt_tag;
}
else if (glx_major > 1 || glx_minor >= 3) {
xGLXMakeContextCurrentReq *req;
GetReq(GLXMakeContextCurrent, req);
req->reqType = major_opcode;
req->glxCode = X_GLXMakeContextCurrent;
req->drawable = a_drawable;
req->readdrawable = a_readable;
req->context = remote_glx_ctxt_id;
req->oldContextTag = a_old_ctxt_tag;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXMakeCurrentReadSGIReq *req;
GetReqExtra(GLXVendorPrivateWithReply,
(sz_xGLXMakeCurrentReadSGIReq -
sz_xGLXVendorPrivateWithReplyReq),
vpreq);
req = (xGLXMakeCurrentReadSGIReq *) vpreq;
req->reqType = major_opcode;
req->glxCode = X_GLXVendorPrivateWithReply;
req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
req->drawable = a_drawable;
req->readable = a_readable;
req->context = remote_glx_ctxt_id;
req->oldContextTag = a_old_ctxt_tag;
}
memset(&reply, 0, sizeof(reply));
if (!_XReply(dpy, (xReply *) & reply, 0, False)) {

View File

@ -61,7 +61,7 @@ Bool ephyrHostGLXCreateContext(int a_screen,
Bool ephyrHostDestroyContext(int a_ctxt_id);
Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_glx_ctxt_id,
Bool ephyrHostGLXMakeCurrent(int a_drawable, int a_readable, int a_glx_ctxt_id,
int a_olg_ctxt_tag, int *a_ctxt_tag);
Bool ephyrHostGetIntegerValue(int a_current_context_tag, int a_int, int *a_val);