[PATCH] Xephyr: GLX: Support MakeContextCurrent and MakeCurrentReadSGI

Ian Romanick idr at freedesktop.org
Thu Sep 13 07:11:02 PDT 2012


On 09/07/2012 08:30 PM, Daniel Stone wrote:
> 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.

I'm not very familiar with Xephyr, but these changes look sensible.

> Signed-off-by: Daniel Stone <daniel at fooishbar.org>
> Cc: Ian Romanick <ian.d.romanick at intel.com>

Reviewed-by: 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);
>



More information about the xorg-devel mailing list