/* * Xephyr - A kdrive X server thats runs in a host X window. * Authored by Matthew Allum * * Copyright © 2007 OpenedHand Ltd * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of OpenedHand Ltd not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. OpenedHand Ltd makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: * Dodji Seketeli */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #define _HAVE_XALLOC_DECLS #include "hostx.h" #include "ephyrhostvideo.h" #include "ephyrlog.h" #ifndef TRUE #define TRUE 1 #endif /*TRUE*/ #ifndef FALSE #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 ; }; Bool EphyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) { EphyrHostXVAdaptorArray *result=NULL ; int ret=0 ; Bool is_ok=FALSE ; EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; EPHYR_LOG ("enter\n") ; result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; if (!result) goto out ; ret = XvQueryAdaptors (hostx_get_display (), DefaultRootWindow (hostx_get_display ()), &result->nb_adaptors, &result->adaptors) ; if (ret != Success) { EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; goto out ; } *a_adaptors = result ; is_ok = TRUE ; out: EPHYR_LOG ("leave\n") ; return is_ok ; } void EphyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) { if (!a_adaptors) return ; if (a_adaptors->adaptors) { XvFreeAdaptorInfo (a_adaptors->adaptors) ; a_adaptors->adaptors = NULL ; a_adaptors->nb_adaptors = 0 ; } XFree (a_adaptors) ; } int EphyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return a_this->nb_adaptors ; } EphyrHostXVAdaptor* EphyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, int a_index) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; if (a_index >= a_this->nb_adaptors) return NULL ; return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; } char EphyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->type ; } const char* EphyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; return ((XvAdaptorInfo*)a_this)->name ; } EphyrHostVideoFormat* EphyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, int *a_nb_formats) { EphyrHostVideoFormat *formats=NULL ; int nb_formats=0, i=0 ; XVisualInfo *visual_info, visual_info_template ; int nb_visual_info ; EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; 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 = ((XvAdaptorInfo*)a_this)->formats[i].visual_id; visual_info = XGetVisualInfo (hostx_get_display (), VisualIDMask, &visual_info_template, &nb_visual_info) ; formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; formats[i].visual_class = visual_info->class ; XFree (visual_info) ; } if (a_nb_formats) *a_nb_formats = nb_formats ; return formats ; } int EphyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->num_ports ; } int EphyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) { EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; return ((XvAdaptorInfo*)a_this)->base_id ; } Bool EphyrHostXVQueryEncodings (int a_port_id, EphyrHostEncoding **a_encodings, unsigned int *a_num_encodings) { EphyrHostEncoding *encodings=NULL ; XvEncodingInfo *encoding_info=NULL ; unsigned int num_encodings=0, i; int ret=0 ; EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; ret = XvQueryEncodings (hostx_get_display (), a_port_id, &num_encodings, &encoding_info) ; if (num_encodings && encoding_info) { 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) ; }