xserver: Branch 'master' - 4 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Oct 4 11:38:45 PDT 2012


 Xi/xiselectev.c                |    9 +-
 hw/kdrive/ephyr/ephyrglxext.c  |  179 ++++++++++++++++++++++++++++++++++++-----
 hw/kdrive/ephyr/ephyrhostglx.c |  121 +++++++++++++++++++++------
 hw/kdrive/ephyr/ephyrhostglx.h |    9 +-
 4 files changed, 268 insertions(+), 50 deletions(-)

New commits:
commit f179b13b91c8891254d31345ee04e773839e6b87
Merge: 4dd5989... 3d2b768...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Oct 4 11:39:46 2012 -0700

    Merge remote-tracking branch 'daniels/master'

commit 3d2b768efae9936c6929c2bc13c7a1acc074ecd3
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Fri Sep 7 18:17:46 2012 +0100

    Touch: Fix duplicate TouchBegin selection with virtual devices
    
    Given the following scenario:
      1) client A selects for TouchBegin on window W for device D
      2) client B selects for TouchBegin on window W for XIAllDevices
      3) client C selects for TouchBegin on window W with device E
    
    Step 3 will fail with BadImplementation, because attempting to look up
    XIAllDevices or XIAllMasterDevices with dixLookupDevices doesn't work.
    This should succeed (or, if it was selecting for device D, fail with
    BadAccess as it would be a duplicate selection).
    
    Fix this by performing the appropriate lookup for virtual devices.
    
    Signed-off-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Chase Douglas <chase.douglas at ubuntu.com>

diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c
index 0e45cb8..ab1b624 100644
--- a/Xi/xiselectev.c
+++ b/Xi/xiselectev.c
@@ -180,8 +180,13 @@ ProcXISelectEvents(ClientPtr client)
                     if (CLIENT_ID(iclient->resource) == client->index)
                         continue;
 
-                    dixLookupDevice(&tmp, evmask->deviceid, serverClient,
-                                    DixReadAccess);
+                    if (evmask->deviceid == XIAllDevices)
+                        tmp = inputInfo.all_devices;
+                    else if (evmask->deviceid == XIAllMasterDevices)
+                        tmp = inputInfo.all_master_devices;
+                    else
+                        dixLookupDevice(&tmp, evmask->deviceid, serverClient,
+                                        DixReadAccess);
                     if (!tmp)
                         return BadImplementation;       /* this shouldn't happen */
 
commit e3903a9383351b061b1a99dfc653ca50de764ec4
Author: Frederic Plourde <frederic.plourde at collabora.com>
Date:   Wed Sep 12 10:48:32 2012 -0400

    Add glXCreateNewContext support in Xephyr #54798
    
    Similar to how we intercept and pass through CreateContext, also pass
    through newer CreateNewContext requests.
    
    Fixes Clutter → Xephyr → VirtualBox.
    
    Signed-off-by: Frederic Plourde <frederic.plourde at collabora.com>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c
index 892d99f..22d5108 100644
--- a/hw/kdrive/ephyr/ephyrglxext.c
+++ b/hw/kdrive/ephyr/ephyrglxext.c
@@ -61,6 +61,8 @@ int ephyrGLXGetFBConfigsSGIX(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXGetFBConfigsSGIXSwap(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXCreateContext(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXCreateContextSwap(__GLXclientState * a_cl, GLbyte * a_pc);
+int ephyrGLXCreateNewContext(__GLXclientState * a_cl, GLbyte * a_pc);
+int ephyrGLXCreateNewContextSwap(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXDestroyContext(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXDestroyContextSwap(__GLXclientState * a_cl, GLbyte * a_pc);
 int ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc);
@@ -112,6 +114,9 @@ ephyrHijackGLXExtension(void)
     dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext;
     dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap;
 
+    dispatch_functions[X_GLXCreateNewContext][0] = ephyrGLXCreateNewContext;
+    dispatch_functions[X_GLXCreateNewContext][1] = ephyrGLXCreateNewContextSwap;
+
     dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext;
     dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap;
 
@@ -459,7 +464,8 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap)
     if (!ephyrHostGLXCreateContext(a_req->screen,
                                    host_w_attrs.visualid,
                                    a_req->context,
-                                   a_req->shareList, a_req->isDirect)) {
+                                   a_req->shareList, 0,
+                                   a_req->isDirect, X_GLXCreateContext)) {
         EPHYR_LOG_ERROR("ephyrHostGLXCreateContext() failed\n");
         goto out;
     }
@@ -469,6 +475,45 @@ ephyrGLXCreateContextReal(xGLXCreateContextReq * a_req, Bool a_do_swap)
     return res;
 }
 
+static int
+ephyrGLXCreateNewContextReal(xGLXCreateNewContextReq * a_req, Bool a_do_swap)
+{
+    int res = BadImplementation;
+
+    __GLX_DECLARE_SWAP_VARIABLES;
+
+    EPHYR_RETURN_VAL_IF_FAIL(a_req, BadValue);
+    EPHYR_LOG("enter\n");
+
+    if (a_do_swap) {
+        __GLX_SWAP_SHORT(&a_req->length);
+        __GLX_SWAP_INT(&a_req->context);
+        __GLX_SWAP_INT(&a_req->fbconfig);
+        __GLX_SWAP_INT(&a_req->screen);
+        __GLX_SWAP_INT(&a_req->renderType);
+        __GLX_SWAP_INT(&a_req->shareList);
+    }
+
+    EPHYR_LOG("context creation requested. localid:%d, "
+              "screen:%d, fbconfig:%d, renderType:%d, direct:%d\n",
+              (int) a_req->context, (int) a_req->screen,
+              (int) a_req->fbconfig, (int) a_req->renderType,
+              (int) a_req->isDirect);
+
+    if (!ephyrHostGLXCreateContext(a_req->screen,
+                                   a_req->fbconfig,
+                                   a_req->context,
+                                   a_req->shareList, a_req->renderType,
+                                   a_req->isDirect, X_GLXCreateNewContext)) {
+        EPHYR_LOG_ERROR("ephyrHostGLXCreateNewContext() failed\n");
+        goto out;
+    }
+    res = Success;
+ out:
+    EPHYR_LOG("leave\n");
+    return res;
+}
+
 int
 ephyrGLXCreateContext(__GLXclientState * cl, GLbyte * pc)
 {
@@ -485,6 +530,22 @@ ephyrGLXCreateContextSwap(__GLXclientState * cl, GLbyte * pc)
     return ephyrGLXCreateContextReal(req, TRUE);
 }
 
+int
+ephyrGLXCreateNewContext(__GLXclientState * cl, GLbyte * pc)
+{
+    xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
+
+    return ephyrGLXCreateNewContextReal(req, FALSE);
+}
+
+int
+ephyrGLXCreateNewContextSwap(__GLXclientState * cl, GLbyte * pc)
+{
+    xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
+
+    return ephyrGLXCreateNewContextReal(req, TRUE);
+}
+
 static int
 ephyrGLXDestroyContextReal(__GLXclientState * a_cl,
                            GLbyte * a_pc, Bool a_do_swap)
diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c
index b1f729a..392489a 100644
--- a/hw/kdrive/ephyr/ephyrhostglx.c
+++ b/hw/kdrive/ephyr/ephyrhostglx.c
@@ -439,17 +439,20 @@ ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor,
 
 Bool
 ephyrHostGLXCreateContext(int a_screen,
-                          int a_visual_id,
+                          int a_generic_id,
                           int a_context_id,
-                          int a_share_list_ctxt_id, Bool a_direct)
+                          int a_share_list_ctxt_id,
+                          int a_render_type,
+                          Bool a_direct,
+                          int code)
 {
     Bool is_ok = FALSE;
     Display *dpy = hostx_get_display();
     int major_opcode = 0, remote_context_id = 0;
-    xGLXCreateContextReq *req;
 
-    EPHYR_LOG("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n",
-              a_screen, a_visual_id, a_context_id, a_direct);
+    EPHYR_LOG("enter. screen:%d, generic_id:%d, contextid:%d, rendertype:%d, "
+                 "direct:%d\n", a_screen, a_generic_id, a_context_id,
+                 a_render_type, a_direct);
 
     if (!hostx_allocate_resource_id_peer(a_context_id, &remote_context_id)) {
         EPHYR_LOG_ERROR("failed to peer the context id %d host X",
@@ -464,15 +467,38 @@ ephyrHostGLXCreateContext(int a_screen,
 
     LockDisplay(dpy);
 
-    /* Send the glXCreateContext request */
-    GetReq(GLXCreateContext, req);
-    req->reqType = major_opcode;
-    req->glxCode = X_GLXCreateContext;
-    req->context = remote_context_id;
-    req->visual = a_visual_id;
-    req->screen = DefaultScreen(dpy);
-    req->shareList = a_share_list_ctxt_id;
-    req->isDirect = a_direct;
+    switch (code) {
+    case X_GLXCreateContext: {
+        /* Send the glXCreateContext request */
+        xGLXCreateContextReq *req;
+        GetReq(GLXCreateContext, req);
+        req->reqType = major_opcode;
+        req->glxCode = X_GLXCreateContext;
+        req->context = remote_context_id;
+        req->visual = a_generic_id;
+        req->screen = DefaultScreen(dpy);
+        req->shareList = a_share_list_ctxt_id;
+        req->isDirect = a_direct;
+    }
+
+    case X_GLXCreateNewContext: {
+        /* Send the glXCreateNewContext request */
+        xGLXCreateNewContextReq *req;
+        GetReq(GLXCreateNewContext, req);
+        req->reqType = major_opcode;
+        req->glxCode = X_GLXCreateNewContext;
+        req->context = remote_context_id;
+        req->fbconfig = a_generic_id;
+        req->screen = DefaultScreen(dpy);
+        req->renderType = a_render_type;
+        req->shareList = a_share_list_ctxt_id;
+        req->isDirect = a_direct;
+    }
+
+    default:
+        /* This should never be reached !*/
+        EPHYR_LOG("Internal error! Invalid CreateContext code!\n");
+    }
 
     UnlockDisplay(dpy);
     SyncHandle();
diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h
index 9aa8bdc..7ff515d 100644
--- a/hw/kdrive/ephyr/ephyrhostglx.h
+++ b/hw/kdrive/ephyr/ephyrhostglx.h
@@ -55,9 +55,12 @@ Bool ephyrHostGLXGetMajorOpcode(int32_t * a_opcode);
 Bool ephyrHostGLXSendClientInfo(int32_t a_major, int32_t a_minor,
                                 const char *a_extension_list);
 Bool ephyrHostGLXCreateContext(int a_screen,
-                               int a_visual_id,
+                               int a_generic_id,
                                int a_context_id,
-                               int a_shared_list_ctx_id, Bool a_direct);
+                               int a_share_list_ctxt_id,
+                               int a_render_type,
+                               Bool a_direct,
+                               int code);
 
 Bool ephyrHostDestroyContext(int a_ctxt_id);
 
commit 11afebc92ce1a7462ff2886286504425b1c8f0ba
Author: Daniel Stone <daniel at fooishbar.org>
Date:   Fri Sep 7 18:10:35 2012 +0100

    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 at fooishbar.org>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>

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);


More information about the xorg-commit mailing list