[PATCH] Xephyr: GLX: Support MakeContextCurrent and MakeCurrentReadSGI

Daniel Stone daniel at fooishbar.org
Fri Sep 7 10:30:37 PDT 2012


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 at fooishbar.org>
Cc: Ian Romanick <ian.d.romanick at intel.com>
Cc: Dave Airlie <airlied at gmail.com>
---
 hw/kdrive/ephyr/ephyrglxext.c  |  116 +++++++++++++++++++++++++++++++++-------
 hw/kdrive/ephyr/ephyrhostglx.c |   67 ++++++++++++++++++-----
 hw/kdrive/ephyr/ephyrhostglx.h |    2 +-
 3 files changed, 154 insertions(+), 31 deletions(-)

diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c
index df285cf..892d99f 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 6b9da6f..b1f729a 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 9c60120..9aa8bdc 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);
-- 
1.7.10.4



More information about the xorg-devel mailing list