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 ; +}