[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