summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2012-09-07 18:10:35 +0100
committerDaniel Stone <daniel@fooishbar.org>2012-09-25 17:16:15 +1000
commit11afebc92ce1a7462ff2886286504425b1c8f0ba (patch)
treeac179c00186b0beecda5afba0ad16ab445135892
parent0b02150c27e98f996e10d7489f9f67a30e4e3497 (diff)
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>
-rw-r--r--hw/kdrive/ephyr/ephyrglxext.c116
-rw-r--r--hw/kdrive/ephyr/ephyrhostglx.c67
-rw-r--r--hw/kdrive/ephyr/ephyrhostglx.h2
3 files changed, 154 insertions, 31 deletions
diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c
index df285cfcb..892d99f30 100644
--- a/hw/kdrive/ephyr/ephyrglxext.c
+++ b/hw/kdrive/ephyr/ephyrglxext.c
@@ -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);
-
- if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawable->pScreen->myNum),
- req->context,
- req->oldContextTag,
- (int *) &contextTag)) {
+ 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 (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
diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c
index 6b9da6fb1..b1f729a1f 100644
--- a/hw/kdrive/ephyr/ephyrhostglx.c
+++ b/hw/kdrive/ephyr/ephyrhostglx.c
@@ -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)) {
diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h
index 9c6012070..9aa8bdc4e 100644
--- a/hw/kdrive/ephyr/ephyrhostglx.h
+++ b/hw/kdrive/ephyr/ephyrhostglx.h
@@ -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);