From aa478e09e25a1cb19b808e7e52b2ee155e34f03b Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Thu, 2 Aug 2007 12:49:36 +0200 Subject: [PATCH] make properties setting/query code work and hopefully complete. * hw/kdrive/ephyr/ephyrhostvideo.c,h: (EphyrHostXVQueryImageAttributes): add this call. It calls XvQueryBestSize xserver entry point. It uses the protocol level machinery because Xvlib does not expose that entry point as a C function. (EphyrHostXVQueryBestSize): added this wrapper around XvQueryBestSize(). (EphyrHostGetAtom, EphyrHostGetAtomName): added this to get an atom or atom name from the host server * hw/kdrive/ephyr/ephyrvideo.c: (EphyrSetPortAttribute): convert the atom into an host server server atom before attacking the host server with it, because in in its current form, the input atom is only valid in xephyr. This fix makes this call work. (EphyrGetPortAttribute): ditto. (EphyrQueryBestSize): implement this. (EphyrQueryImageAttributes): implement this. --- hw/kdrive/ephyr/ephyrhostvideo.c | 257 ++++++++++++++++++++++++++++++- hw/kdrive/ephyr/ephyrhostvideo.h | 30 ++++ hw/kdrive/ephyr/ephyrvideo.c | 128 ++++++++++++++- 3 files changed, 400 insertions(+), 15 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrhostvideo.c b/hw/kdrive/ephyr/ephyrhostvideo.c index ed6dbb0f3..fa1e15b70 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/hw/kdrive/ephyr/ephyrhostvideo.c @@ -29,7 +29,12 @@ #include #endif #include +#include #include +#include +#include +#include +#define _HAVE_XALLOC_DECLS #include "hostx.h" #include "ephyrhostvideo.h" @@ -43,6 +48,61 @@ #define FALSE 0 #endif /*FALSE*/ +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; +static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, + char * buf, int n); +static int xv_close_display(Display *dpy, XExtCodes *codes); +static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + struct _EphyrHostXVAdaptorArray { XvAdaptorInfo *adaptors ; unsigned int nb_adaptors ; @@ -59,7 +119,7 @@ EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) EPHYR_LOG ("enter\n") ; - result = Xcalloc (sizeof (EphyrHostXVAdaptorArray)) ; + result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; if (!result) goto out ; @@ -137,7 +197,7 @@ EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; - formats = Xcalloc (nb_formats * sizeof (EphyrHostVideoFormat)) ; + formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; for (i=0; i < nb_formats; i++) { memset (&visual_info_template, 0, sizeof (visual_info_template)) ; visual_info_template.visualid = @@ -188,7 +248,7 @@ EphyrHostXVQueryEncodings (int a_port_id, &num_encodings, &encoding_info) ; if (num_encodings && encoding_info) { - encodings = Xcalloc (num_encodings * sizeof (EphyrHostEncoding)) ; + encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; for (i=0; iu.u.type & 0x7F) - info->codes->first_event) { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return True ; +} + +Bool +EphyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) +{ + Display *dpy = hostx_get_display () ; + Bool ret=FALSE ; + XExtDisplayInfo *info = xv_find_display (dpy); + xvQueryImageAttributesReq *req=NULL; + xvQueryImageAttributesReply rep; + + EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; + + XvCheckExtension (dpy, info, FALSE); + + LockDisplay (dpy); + + XvGetReq (QueryImageAttributes, req); + req->id = a_image_id; + req->port = a_port_id; + req->width = *a_width; + req->height = *a_height; + /* + * read the reply + */ + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; + goto out ; + } + if (a_pitches && a_offsets) { + _XRead (dpy, + (char*)a_pitches, + rep.num_planes << 2); + _XRead (dpy, + (char*)a_offsets, + rep.num_planes << 2); + } else { + _XEatData(dpy, rep.length << 2); + } + *a_width = rep.width ; + *a_height = rep.height ; + *a_image_size = rep.data_size ; + + ret = TRUE ; + +out: + UnlockDisplay (dpy) ; + SyncHandle (); + return ret ; +} + +Bool +EphyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) +{ + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; + + atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); + if (atom == None) { return FALSE ; } + *a_atom = atom ; return TRUE ; } + +char* +EphyrHostGetAtomName (int a_atom) +{ + return XGetAtomName (hostx_get_display (), a_atom) ; +} + +void +EphyrHostFree (void *a_pointer) +{ + if (a_pointer) + XFree (a_pointer) ; +} + diff --git a/hw/kdrive/ephyr/ephyrhostvideo.h b/hw/kdrive/ephyr/ephyrhostvideo.h index af5456092..fa3eba0bd 100644 --- a/hw/kdrive/ephyr/ephyrhostvideo.h +++ b/hw/kdrive/ephyr/ephyrhostvideo.h @@ -84,6 +84,8 @@ typedef struct _EphyrHostImageFormat { int scanline_order; /* XvTopToBottom, XvBottomToTop */ } EphyrHostImageFormat ; +void EphyrHostFree (void *a_pointer) ; + /* * host adaptor array */ @@ -139,5 +141,33 @@ Bool EphyrHostXVSetPortAttribute (int a_port_id, Bool EphyrHostXVGetPortAttribute (int a_port_id, int a_atom, int *a_attr_value) ; +/* + *size query + */ +Bool EphyrHostXVQueryBestSize (int a_port_id, + Bool a_motion, + unsigned int a_frame_w, + unsigned int a_frame_h, + unsigned int a_drw_w, + unsigned int a_drw_h, + unsigned int *a_actual_w, + unsigned int *a_actual_h) ; + +Bool EphyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) ; +/* + * atom + */ +Bool EphyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) ; +char* EphyrHostGetAtomName (int a_atom) ; + + #endif /*__EPHYRHOSTVIDEO_H__*/ diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index eedbf1556..6f0bc8f41 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -51,6 +51,10 @@ struct _EphyrPortPriv { }; typedef struct _EphyrPortPriv EphyrPortPriv ; +static Bool EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; + +static Bool EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; + static EphyrXVPriv* EphyrXVPrivNew (void) ; static void EphyrXVPrivDelete (EphyrXVPriv *a_this) ; static Bool EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; @@ -105,6 +109,67 @@ static int EphyrQueryImageAttributes (KdScreenInfo *a_info, unsigned short *a_h, int *a_pitches, int *a_offsets); +static int s_base_port_id ; + +/************** + * + * ************/ + +static Bool +EphyrLocalAtomToHost (int a_local_atom, int *a_host_atom) +{ + char *atom_name=NULL; + int host_atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ; + + if (!ValidAtom (a_local_atom)) + return FALSE ; + + atom_name = NameForAtom (a_local_atom) ; + + if (!atom_name) + return FALSE ; + + if (!EphyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { + EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", + atom_name) ; + return FALSE ; + } + *a_host_atom = host_atom ; + return TRUE ; +} + +static Bool +EphyrHostAtomToLocal (int a_host_atom, int *a_local_atom) +{ + Bool is_ok=FALSE ; + char *atom_name=NULL ; + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; + + atom_name = EphyrHostGetAtomName (a_host_atom) ; + if (!atom_name) + goto out ; + + atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ; + if (atom == None) + goto out ; + + *a_local_atom = atom ; + is_ok = TRUE ; + +out: + if (atom_name) { + EphyrHostFree (atom_name) ; + } + return is_ok ; +} + +/************** + * + * ************/ Bool ephyrInitVideo (ScreenPtr pScreen) @@ -289,6 +354,9 @@ EphyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; continue ; } + if (!s_base_port_id) + s_base_port_id = base_port_id ; + if (!EphyrHostXVQueryEncodings (base_port_id, &encodings, &num_encodings)) { @@ -436,7 +504,7 @@ EphyrSetPortAttribute (KdScreenInfo *a_info, int a_attr_value, pointer a_port_priv) { - int res=Success ; + int res=Success, host_atom=0 ; EphyrPortPriv *port_priv = a_port_priv ; EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; @@ -448,8 +516,14 @@ EphyrSetPortAttribute (KdScreenInfo *a_info, NameForAtom (a_attr_name), a_attr_value) ; + if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + if (!EphyrHostXVSetPortAttribute (port_priv->port_number, - a_attr_name, + host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to set port attribute\n") ; res = BadMatch ; @@ -468,7 +542,7 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, int *a_attr_value, pointer a_port_priv) { - int res=Success ; + int res=Success, host_atom=0 ; EphyrPortPriv *port_priv = a_port_priv ; EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; @@ -479,8 +553,14 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, (int)a_attr_name, NameForAtom (a_attr_name)) ; + if (!EphyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + if (!EphyrHostXVGetPortAttribute (port_priv->port_number, - a_attr_name, + host_atom, a_attr_value)) { EPHYR_LOG_ERROR ("failed to get port attribute\n") ; res = BadMatch ; @@ -489,6 +569,7 @@ EphyrGetPortAttribute (KdScreenInfo *a_screen_info, res = Success ; out: + EPHYR_LOG ("leave\n") ; return res ; } @@ -503,6 +584,21 @@ EphyrQueryBestSize (KdScreenInfo *a_info, unsigned int *a_prefered_h, pointer a_port_priv) { + int res=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + res = EphyrHostXVQueryBestSize (port_priv->port_number, + a_motion, + a_src_w, a_src_h, + a_drw_w, a_drw_h, + a_prefered_w, a_prefered_h) ; + if (!res) { + EPHYR_LOG_ERROR ("Failed to query best size\n") ; + } + EPHYR_LOG ("leave\n") ; } static int @@ -537,8 +633,24 @@ EphyrQueryImageAttributes (KdScreenInfo *a_info, int *a_pitches, int *a_offsets) { - EPHYR_LOG ("enter\n") ; - return 0 ; - EPHYR_LOG ("leave\n") ; -} + int image_size=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ; + + EPHYR_LOG ("enter: dim (%dx%d), pitches: %#x, offsets: %#x\n", + *a_w, *a_h, (unsigned int)a_pitches, (unsigned int)a_offsets) ; + + if (!EphyrHostXVQueryImageAttributes (s_base_port_id, + a_id, + a_w, a_h, + &image_size, + a_pitches, a_offsets)) { + EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; + goto out ; + } + EPHYR_LOG ("image size: %d, dim (%dx%d)", image_size, *a_w, *a_h) ; + +out: + EPHYR_LOG ("leave\n") ; + return image_size ; +}