diff options
Diffstat (limited to 'hw/kdrive/ephyr/ephyrhostglx.c')
-rw-r--r-- | hw/kdrive/ephyr/ephyrhostglx.c | 121 |
1 files changed, 95 insertions, 26 deletions
diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 6b9da6fb1..392489a00 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); @@ -431,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", @@ -456,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(); @@ -512,20 +546,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 +571,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)) { |