summaryrefslogtreecommitdiff
path: root/hw/kdrive/ephyr/ephyrhostglx.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/ephyr/ephyrhostglx.c')
-rw-r--r--hw/kdrive/ephyr/ephyrhostglx.c121
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)) {