From 4dd4be99df38b70d43b02d9cb19e09e0ed94462b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 30 Aug 2007 23:54:49 +0200 Subject: [PATCH] Xephyr: Make glxinfo work on the ATI R200 free driver. * hw/kdrive/ephyr/ephyr.c: (EphyrDuplicateVisual): when duplicating the visual, copy the color component masks and the class from the hostX (EphyrMirrorHostVisuals): don't mix blue and green mask. * hw/kdrive/ephyr/ephyrdri.c: add more logs. (ephyrDRICreateDrawable): actually implement this. for the moment it creates a DRI drawable for the hostX window, no matter what drawable this call was issued for. (ephyrDRIGetDrawableInfo): actually implemented this. for the moment the drawable info queried for its attrs is the Xephyr main main window. * hw/kdrive/ephyr/ephyrdriext.c: (ProcXF86DRIGetDrawableInfo): properly hook this dispatch function to the ephyrDRIGetDrawableInfo() function. * hw/kdrive/ephyr/ephyrglxext.c: add a bunch of GLX implementation hooks here. Hijack some of the xserver GLX hooks with them. Still need to properly support byteswapped clients though. * hw/kdrive/ephyr/ephyrhostglx.c,h: actually implemented the protocol level forwarding functions used by the GLX entr points in ephyrglxext.c. Here as well, there are a bunch of them, but we are far from having implemented all the GLX calls. * hw/kdrive/ephyr/hostx.c,h: (hostx_get_window_attributes): added this new entry point (hostx_allocate_resource_id_peer): added this to keep track of resource IDs peers: one member of the peer is in Xephyr, the other is in host X. (hostx_get_resource_id_peer): ditto. --- hw/kdrive/ephyr/ephyr.c | 6 +- hw/kdrive/ephyr/ephyrdri.c | 63 +++++-- hw/kdrive/ephyr/ephyrdri.h | 2 +- hw/kdrive/ephyr/ephyrdriext.c | 35 ++-- hw/kdrive/ephyr/ephyrglxext.c | 317 ++++++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostglx.c | 284 ++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostglx.h | 25 +++ hw/kdrive/ephyr/hostx.c | 93 ++++++++++ hw/kdrive/ephyr/hostx.h | 16 ++ 9 files changed, 801 insertions(+), 40 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index df91f83fb..97eac51d9 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -1095,6 +1095,10 @@ EphyrDuplicateVisual (unsigned int a_screen, /*copy the visual found*/ memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; new_visual.vid = a_new_id ; + new_visual.class = a_class ; + new_visual.redMask = a_red_mask ; + new_visual.greenMask = a_green_mask ; + new_visual.blueMask = a_blue_mask ; found_visual = TRUE ; EPHYR_LOG ("found a visual that matches visual id: %d\n", a_new_id) ; @@ -1195,8 +1199,8 @@ EphyrMirrorHostVisuals (void) visuals[i].bits_per_rgb, visuals[i].colormap_size, visuals[i].red_mask, - visuals[i].blue_mask, visuals[i].green_mask, + visuals[i].blue_mask, visuals[i].visualid)) { EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n", (int)visuals[i].visualid) ; diff --git a/hw/kdrive/ephyr/ephyrdri.c b/hw/kdrive/ephyr/ephyrdri.c index 54ad2c0b6..95ace7c25 100644 --- a/hw/kdrive/ephyr/ephyrdri.c +++ b/hw/kdrive/ephyr/ephyrdri.c @@ -40,6 +40,8 @@ #include "ephyrdri.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" +#include "dixstruct.h" +#include "pixmapstr.h" #ifndef TRUE #define TRUE 1 @@ -55,9 +57,10 @@ ephyrDRIQueryDirectRenderingCapable (int a_screen, Bool *a_is_capable) Display *dpy=hostx_get_display () ; Bool is_ok=FALSE ; + EPHYR_RETURN_VAL_IF_FAIL (a_is_capable, FALSE) ; EPHYR_LOG ("enter\n") ; is_ok = XF86DRIQueryDirectRenderingCapable (dpy, a_screen, a_is_capable) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave. is_capable:%d, is_ok=%d\n", *a_is_capable, is_ok) ; return is_ok ; } @@ -70,9 +73,16 @@ ephyrDRIOpenConnection (int a_screen, Display *dpy = hostx_get_display () ; Bool is_ok=FALSE ; - EPHYR_LOG ("enter\n") ; + EPHYR_RETURN_VAL_IF_FAIL (a_bus_id_string, FALSE) ; + EPHYR_LOG ("enter. screen:%d\n", a_screen) ; is_ok = XF86DRIOpenConnection (dpy, a_screen, a_sarea, a_bus_id_string) ; - EPHYR_LOG ("leave\n") ; + if (*a_bus_id_string) { + EPHYR_LOG ("leave. bus_id_string:%s, is_ok:%d\n", + *a_bus_id_string, is_ok) ; + } else { + EPHYR_LOG ("leave. bus_id_string:null, is_ok:%d\n", + is_ok) ; + } return is_ok ; } @@ -84,7 +94,7 @@ ephyrDRIAuthConnection (int a_screen, drm_magic_t a_magic) EPHYR_LOG ("enter\n") ; is_ok = XF86DRIAuthConnection (dpy, a_screen, a_magic) ; - EPHYR_LOG ("leave\n") ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; return is_ok ; } @@ -140,7 +150,7 @@ ephyrDRICreateContext (int a_screen, Bool is_ok=FALSE ; Visual v; - EPHYR_LOG ("enter\n") ; + EPHYR_LOG ("enter. screen:%d, visual:%d\n", a_screen, a_visual_id) ; memset (&v, 0, sizeof (v)) ; v.visualid = a_visual_id ; is_ok = XF86DRICreateContext (dpy, @@ -170,10 +180,14 @@ ephyrDRICreateDrawable (int a_screen, int a_drawable, drm_drawable_t *a_hw_drawable) { + Bool is_ok=FALSE; + Display *dpy=hostx_get_display () ; + int host_win=hostx_get_window () ; + EPHYR_LOG ("enter\n") ; - EPHYR_LOG_ERROR ("not implemented yet\n") ; - EPHYR_LOG ("leave\n") ; - return FALSE ; + is_ok = XF86DRICreateDrawable (dpy, a_screen, host_win, a_hw_drawable) ; + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + return is_ok ; } Bool @@ -187,7 +201,7 @@ ephyrDRIDestroyDrawable (int a_screen, int a_drawable) Bool ephyrDRIGetDrawableInfo (int a_screen, - int a_drawable, + void *a_drawable, unsigned int *a_index, unsigned int *a_stamp, int *a_x, @@ -198,13 +212,38 @@ ephyrDRIGetDrawableInfo (int a_screen, drm_clip_rect_t **a_clip_rects, int *a_back_x, int *a_back_y, - int *num_back_clip_rects, + int *a_num_back_clip_rects, drm_clip_rect_t **a_back_clip_rects) { + Bool is_ok=FALSE; + DrawablePtr drawable = a_drawable ; + EphyrHostWindowAttributes attrs ; + + EPHYR_RETURN_VAL_IF_FAIL (drawable && a_x && a_y && a_w && a_h + && a_num_clip_rects, + FALSE) ; + EPHYR_LOG ("enter\n") ; - EPHYR_LOG_ERROR ("not implemented yet\n") ; + memset (&attrs, 0, sizeof (attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (), &attrs)) { + EPHYR_LOG_ERROR ("failed to query host window attributes\n") ; + goto out; + } + *a_x = drawable->x + attrs.x; + *a_y = drawable->y + attrs.y; + *a_w = drawable->width + attrs.width ; + *a_h = drawable->height + attrs.height ; + *a_num_clip_rects = 0 ; + *a_clip_rects = NULL ; + *a_back_x = 0; + *a_back_y = 0 ; + *a_num_back_clip_rects = 0 ; + *a_back_clip_rects = NULL ; + + is_ok = TRUE ; +out: EPHYR_LOG ("leave\n") ; - return FALSE ; + return is_ok ; } Bool diff --git a/hw/kdrive/ephyr/ephyrdri.h b/hw/kdrive/ephyr/ephyrdri.h index d77467f99..ffbbb8e83 100644 --- a/hw/kdrive/ephyr/ephyrdri.h +++ b/hw/kdrive/ephyr/ephyrdri.h @@ -51,7 +51,7 @@ Bool ephyrDRICreateDrawable (int a_screen, drm_drawable_t *a_hw_drawable) ; Bool ephyrDRIDestroyDrawable (int a_screen, int a_drawable) ; Bool ephyrDRIGetDrawableInfo (int a_screen, - int a_drawable, + void* /*DrawablePtr*/ a_drawable, unsigned int *a_index, unsigned int *a_stamp, int *a_x, diff --git a/hw/kdrive/ephyr/ephyrdriext.c b/hw/kdrive/ephyr/ephyrdriext.c index ac68054a3..d54da2164 100644 --- a/hw/kdrive/ephyr/ephyrdriext.c +++ b/hw/kdrive/ephyr/ephyrdriext.c @@ -447,11 +447,10 @@ static int ProcXF86DRIGetDrawableInfo (register ClientPtr client) { xXF86DRIGetDrawableInfoReply rep; - DrawablePtr pDrawable; - int X, Y, W, H; + DrawablePtr drawable; + int X, Y, W, H, backX, backY, rc; drm_clip_rect_t * pClipRects, *pClippedRects; drm_clip_rect_t * pBackClipRects; - int backX, backY, rc; EPHYR_LOG ("enter\n") ; REQUEST(xXF86DRIGetDrawableInfoReq); @@ -469,25 +468,25 @@ ProcXF86DRIGetDrawableInfo (register ClientPtr client) * We must properly do the mapping * between xephyr drawable and the host drawable */ - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, + DixReadAccess); if (rc != Success) return rc; if (!ephyrDRIGetDrawableInfo (stuff->screen, - 0 /*should be the drawable in hostx*/, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &pClipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &pBackClipRects)) { + drawable/*should be the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { return BadValue; } diff --git a/hw/kdrive/ephyr/ephyrglxext.c b/hw/kdrive/ephyr/ephyrglxext.c index c4e5ba4d4..fbac6aa9a 100644 --- a/hw/kdrive/ephyr/ephyrglxext.c +++ b/hw/kdrive/ephyr/ephyrglxext.c @@ -37,7 +37,9 @@ #include #include "GL/glx/glxserver.h" #include "GL/glx/indirect_table.h" +#include "GL/glx/indirect_util.h" #include "GL/glx/unpack.h" +#include "hostx.h" #ifdef XEPHYR_DRI @@ -61,6 +63,18 @@ int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; 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 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 ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; Bool ephyrHijackGLXExtension (void) @@ -83,7 +97,6 @@ ephyrHijackGLXExtension (void) dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; - dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; @@ -91,6 +104,24 @@ ephyrHijackGLXExtension (void) dispatch_functions[X_GLXQueryServerString][1] = ephyrGLXQueryServerStringSwap ; + dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; + dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; + + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; + dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; + + dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; + dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; + + dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; + dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; + + dispatch_functions[73][0] = ephyrGLXGetString ; + dispatch_functions[73][1] = ephyrGLXGetStringSwap ; + + dispatch_functions[61][0] = ephyrGLXGetIntegerv ; + dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; + /* * hijack some vendor priv entry point dispatch functions */ @@ -332,6 +363,7 @@ ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXGetStringFromServer (req->screen, req->name, + EPHYR_HOST_GLX_QueryServerString, &server_string)) { EPHYR_LOG_ERROR ("failed to query string from host\n") ; goto out ; @@ -377,5 +409,288 @@ ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; } +static int +ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) +{ + int res=BadImplementation; + EphyrHostWindowAttributes host_w_attrs ; + __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->visual); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG ("context creation requested. localid:%d, " + "screen:%d, visual:%d, direct:%d\n", + (int)a_req->context, (int)a_req->screen, + (int)a_req->visual, (int)a_req->isDirect) ; + + memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (), &host_w_attrs)) { + EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; + goto out ; + } + + EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; + + if (!ephyrHostGLXCreateContext (a_req->screen, + host_w_attrs.visualid, + a_req->context, + a_req->shareList, + a_req->isDirect)) { + EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; + goto out ; + } + res = Success; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + + return ephyrGLXCreateContextReal (req, FALSE) ; +} + +int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + return ephyrGLXCreateContextReal (req, TRUE) ; +} + +static int +ephyrGLXDestroyContextReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; + + EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; + if (!ephyrHostDestroyContext (req->context)) { + EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; + client->errorValue = req->context ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + xGLXMakeCurrentReply reply ; + + EPHYR_LOG ("enter\n") ; + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostGLXMakeCurrent (hostx_get_window (), + req->context, + req->oldContextTag, + (int*)&reply.contextTag)) { + EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; + goto out; + } + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = a_cl->client->sequence; + if (a_do_swap) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.contextTag); + } + WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + ClientPtr client=NULL ; + int context_tag=0, name=0, res=BadImplementation, length=0 ; + char *string=NULL; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + client = a_cl->client ; + + if (a_do_swap) { + __GLX_SWAP_INT (a_pc + 4); + __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); + } + context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; + a_pc += __GLX_SINGLE_HDR_SIZE; + name = *(GLenum*)(a_pc + 0); + EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; + if (!ephyrHostGLXGetStringFromServer (context_tag, + name, + EPHYR_HOST_GLX_GetString, + &string)) { + EPHYR_LOG_ERROR ("failed to get string from server\n") ; + goto out ; + } + if (string) { + length = strlen (string) ; + EPHYR_LOG ("got string: string:%s\n", string) ; + } else { + EPHYR_LOG ("got string: string (null)\n") ; + } + __GLX_BEGIN_REPLY (length); + __GLX_PUT_SIZE (length); + __GLX_SEND_HEADER (); + if (a_do_swap) { + __GLX_SWAP_REPLY_SIZE (); + __GLX_SWAP_REPLY_HEADER (); + } + WriteToClient (client, length, (char *)string); + + res = Success ; +out: + EPHYR_LOG ("enter\n") ; + return res ; +} + +int +ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; + GLenum int_name ; + int value=0 ; + GLint answer_buf_room[200]; + GLint *buf=NULL ; + + a_pc += __GLX_SINGLE_HDR_SIZE; + + int_name = *(GLenum*) (a_pc+0) ; + if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { + EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; + goto out ; + } + buf = __glXGetAnswerBuffer (a_cl, sizeof (value), + answer_buf_room, + sizeof (answer_buf_room), + 4) ; + + if (!buf) { + EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; + res = BadAlloc ; + goto out ; + } + __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; + res = Success ; +out: + return res ; +} + +int +ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; + xGLXIsDirectReply reply; + int is_direct=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { + EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; + goto out ; + } + reply.isDirect = is_direct ; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); + res = Success ; +out: + return res ; +} + +int +ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; +} + #endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrhostglx.c b/hw/kdrive/ephyr/ephyrhostglx.c index 83e06a85b..843a0e523 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.c +++ b/hw/kdrive/ephyr/ephyrhostglx.c @@ -36,10 +36,10 @@ #include #include #include -#include "hostx.h" #include "ephyrhostglx.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" +#include "hostx.h" #ifdef XEPHYR_DRI enum VisualConfRequestType { @@ -107,6 +107,7 @@ out: * the real protocol packets used to request a string from the server have * an identical binary layout. The only difference between them is the * meaning of the \c for_whom field and the value of the \c glxCode. + * (this has been copied from the mesa source code) */ typedef struct GLXGenericGetString { CARD8 reqType; @@ -124,20 +125,33 @@ typedef struct GLXGenericGetString { Bool ephyrHostGLXGetStringFromServer (int a_screen_number, int a_string_name, + enum EphyrHostGLXGetStringOps a_op, char **a_string) { + Bool is_ok=FALSE ; Display *dpy = hostx_get_display () ; xGLXGenericGetStringReq *req=NULL; xGLXSingleReply reply; - int length=0, numbytes=0, major_opcode=0; + int length=0, numbytes=0, major_opcode=0, get_string_op=0; EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ; EPHYR_LOG ("enter\n") ; + switch (a_op) { + case EPHYR_HOST_GLX_QueryServerString: + get_string_op = X_GLXQueryServerString; + break ; + case EPHYR_HOST_GLX_GetString: + get_string_op = X_GLsop_GetString; + break ; + default: + EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ; + goto out ; + } if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { EPHYR_LOG_ERROR ("failed to get major opcode\n") ; - return FALSE ; + goto out ; } EPHYR_LOG ("major opcode: %d\n", major_opcode) ; @@ -150,7 +164,7 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, */ GetReq (GLXGenericGetString, req); req->reqType = major_opcode; - req->glxCode = X_GLXQueryServerString; + req->glxCode = get_string_op; req->for_whom = a_screen_number; req->name = a_string_name; @@ -162,18 +176,21 @@ ephyrHostGLXGetStringFromServer (int a_screen_number, *a_string = (char *) Xmalloc( numbytes ); if (*a_string != NULL) { if (_XRead (dpy, *a_string, numbytes)) { + UnlockDisplay (dpy); + SyncHandle (); EPHYR_LOG_ERROR ("read failed\n") ; + goto out ; } length -= numbytes; } - _XEatData (dpy, length) ; - UnlockDisplay (dpy); SyncHandle (); + is_ok = TRUE ; +out: EPHYR_LOG ("leave\n") ; - return TRUE ; + return is_ok ; } static Bool @@ -378,5 +395,258 @@ out: return is_ok ; } +Bool +ephyrHostGLXCreateContext (int a_screen, + int a_visual_id, + int a_context_id, + int a_share_list_ctxt_id, + Bool a_direct) +{ + 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) ; + + if (!hostx_allocate_resource_id_peer (a_context_id, &remote_context_id)) { + EPHYR_LOG_ERROR ("failed to peer the context id %d host X", + remote_context_id) ; + goto out ; + } + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + + 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 = a_screen; + req->shareList = a_share_list_ctxt_id; + req->isDirect = a_direct; + + is_ok = TRUE ; + +out: + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostDestroyContext (int a_ctxt_id) +{ + Bool is_ok=FALSE; + Display *dpy=hostx_get_display (); + int major_opcode=0, remote_ctxt_id=0 ; + xGLXDestroyContextReq *req=NULL; + + EPHYR_LOG ("enter:%d\n", a_ctxt_id) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + EPHYR_LOG ("host context id:%d\n", remote_ctxt_id) ; + + LockDisplay (dpy); + GetReq (GLXDestroyContext,req); + req->reqType = major_opcode; + req->glxCode = X_GLXDestroyContext; + req->context = remote_ctxt_id; + UnlockDisplay (dpy); + SyncHandle (); + + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostGLXMakeCurrent (int a_drawable, + 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) ; + + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_glx_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + + 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; + + memset (&reply, 0, sizeof (reply)) ; + if (!_XReply (dpy, (xReply*)&reply, 0, False)) { + EPHYR_LOG_ERROR ("failed to get reply from host\n") ; + goto out ; + } + *a_ctxt_tag = reply.contextTag ; + is_ok = TRUE ; + +out: + UnlockDisplay (dpy); + SyncHandle (); + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +#define X_GLXSingle 0 + +#define __EPHYR_GLX_SINGLE_PUT_CHAR(offset,a) \ + *((INT8 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_SHORT(offset,a) \ + *((INT16 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_LONG(offset,a) \ + *((INT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_PUT_FLOAT(offset,a) \ + *((FLOAT32 *) (pc + offset)) = a + +#define EPHYR_GLX_SINGLE_READ_XREPLY() \ + (void) _XReply(dpy, (xReply*) &reply, 0, False) + +#define EPHYR_GLX_SINGLE_GET_RETVAL(a,cast) \ + a = (cast) reply.retval + +#define EPHYR_GLX_SINGLE_GET_SIZE(a) \ + a = (GLint) reply.size + +#define EPHYR_GLX_SINGLE_GET_CHAR(p) \ + *p = *(GLbyte *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_SHORT(p) \ + *p = *(GLshort *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_LONG(p) \ + *p = *(GLint *)&reply.pad3; + +#define EPHYR_GLX_SINGLE_GET_FLOAT(p) \ + *p = *(GLfloat *)&reply.pad3; + +Bool +ephyrHostGetIntegerValue (int a_current_context_tag, int a_int, int *a_val) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + int major_opcode=0, size=0; + xGLXSingleReq *req=NULL; + xGLXSingleReply reply; + unsigned char* pc=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_val, FALSE) ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + LockDisplay (dpy) ; + GetReqExtra (GLXSingle, 4, req) ; + req->reqType = major_opcode ; + req->glxCode = X_GLsop_GetIntegerv ; + req->contextTag = a_current_context_tag; + pc = ((unsigned char *)(req) + sz_xGLXSingleReq) ; + EPHYR_GLX_SINGLE_PUT_LONG (0, a_int) ; + EPHYR_GLX_SINGLE_READ_XREPLY () ; + EPHYR_GLX_SINGLE_GET_SIZE (size) ; + if (!size) { + UnlockDisplay (dpy) ; + SyncHandle () ; + EPHYR_LOG_ERROR ("X_GLsop_GetIngerv failed\n") ; + goto out ; + } + EPHYR_GLX_SINGLE_GET_LONG (a_val) ; + UnlockDisplay (dpy) ; + SyncHandle () ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) +{ + Bool is_ok=FALSE; + Display *dpy = hostx_get_display () ; + xGLXIsDirectReq *req=NULL; + xGLXIsDirectReply reply; + int major_opcode=0, remote_glx_ctxt_id=0; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) { + EPHYR_LOG_ERROR ("failed to get major opcode\n") ; + goto out ; + } + if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_glx_ctxt_id)) { + EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ; + goto out ; + } + memset (&reply, 0, sizeof (reply)) ; + + /* Send the glXIsDirect request */ + LockDisplay (dpy); + GetReq (GLXIsDirect,req); + req->reqType = major_opcode; + req->glxCode = X_GLXIsDirect; + req->context = remote_glx_ctxt_id; + if (!_XReply (dpy, (xReply*) &reply, 0, False)) { + EPHYR_LOG_ERROR ("fail in reading reply from host\n") ; + UnlockDisplay (dpy); + SyncHandle (); + goto out ; + } + UnlockDisplay (dpy); + SyncHandle (); + *a_is_direct = reply.isDirect ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + #endif /*XEPHYR_DRI*/ diff --git a/hw/kdrive/ephyr/ephyrhostglx.h b/hw/kdrive/ephyr/ephyrhostglx.h index 1040f6c61..6db362f30 100644 --- a/hw/kdrive/ephyr/ephyrhostglx.h +++ b/hw/kdrive/ephyr/ephyrhostglx.h @@ -28,9 +28,16 @@ #ifndef __EPHYRHOSTGLX_H__ #define __EPHYRHOSTGLX_H__ +enum EphyrHostGLXGetStringOps { + EPHYR_HOST_GLX_UNDEF, + EPHYR_HOST_GLX_QueryServerString, + EPHYR_HOST_GLX_GetString, +}; + Bool ephyrHostGLXQueryVersion (int *a_maj, int *a_min) ; Bool ephyrHostGLXGetStringFromServer (int a_screen_number, int a_string_name, + enum EphyrHostGLXGetStringOps a_op, char **a_string) ; Bool ephyrHostGLXGetVisualConfigs (int a_screen, int32_t *a_num_visuals, @@ -46,6 +53,24 @@ ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen, 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_context_id, + int a_shared_list_ctx_id, + Bool a_direct) ; + +Bool ephyrHostDestroyContext (int a_ctxt_id) ; + +Bool ephyrHostGLXMakeCurrent (int a_drawable, 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) ; + +Bool ephyrHostIsContextDirect (int a_ctxt_id, + int *a_is_direct) ; + #endif /*__EPHYRHOSTGLX_H__*/ diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 17712cd5b..51fda478f 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -969,6 +969,27 @@ hostx_get_window(void) return HostX.win ; } +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs) +{ + XWindowAttributes attrs ; + + memset (&attrs, 0, sizeof (attrs)) ; + + if (!XGetWindowAttributes (hostx_get_display (), + a_window, + &attrs)) { + return FALSE ; + } + a_attrs->x = attrs.x ; + a_attrs->y = attrs.y ; + a_attrs->width = attrs.width ; + a_attrs->height = attrs.height ; + if (attrs.visual) + a_attrs->visualid = attrs.visual->visualid ; + return TRUE ; +} + int hostx_get_extension_info (const char *a_ext_name, int *a_major_opcode, @@ -1039,3 +1060,75 @@ out: } +typedef struct { + int is_valid ; + int local_id ; + int remote_id ; +} ResourcePair ; + +#define RESOURCE_PEERS_SIZE 1024*10 +static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ; + +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + Display *dpy=hostx_get_display (); + + /* + * first make sure a resource peer + * does not exist already for + * a_local_resource_id + */ + for (i=0; iremote_id = XAllocID (dpy); + peer->local_id = a_local_resource_id ; + peer->is_valid = TRUE ; + } + } + if (peer) { + *a_remote_resource_id = peer->remote_id ; + return TRUE ; + } + return FALSE ; +} + +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) +{ + int i=0 ; + ResourcePair *peer=NULL ; + for (i=0; iremote_id ; + return TRUE ; + } + return FALSE ; +} + diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index a44b52030..51a5f6832 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -104,6 +104,12 @@ typedef struct { int bits_per_rgb; } EphyrHostVisualInfo; +typedef struct { + int x, y; + int width, height ; + int visualid ; +} EphyrHostWindowAttributes; + int hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height); @@ -190,6 +196,9 @@ hostx_get_display(void) ; int hostx_get_window(void) ; +int +hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attr) ; + int hostx_get_extension_info (const char *a_ext_name, int *a_major_opcode, @@ -198,4 +207,11 @@ hostx_get_extension_info (const char *a_ext_name, int hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals, int *a_num_entries) ; +int +hostx_allocate_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; +int +hostx_get_resource_id_peer (int a_local_resource_id, + int *a_remote_resource_id) ; + #endif