1/* 2 * Xephyr - A kdrive X server thats runs in a host X window. 3 * Authored by Matthew Allum <mallum@openedhand.com> 4 * 5 * Copyright © 2007 OpenedHand Ltd 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that 10 * copyright notice and this permission notice appear in supporting 11 * documentation, and that the name of OpenedHand Ltd not be used in 12 * advertising or publicity pertaining to distribution of the software without 13 * specific, written prior permission. OpenedHand Ltd makes no 14 * representations about the suitability of this software for any purpose. It 15 * is provided "as is" without express or implied warranty. 16 * 17 * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 * 25 * Authors: 26 * Dodji Seketeli <dodji@openedhand.com> 27 */ 28#ifdef HAVE_CONFIG_H 29#include <kdrive-config.h> 30#endif 31/* 32 * including some server headers (like kdrive-config.h) 33 * might define the macro _XSERVER64 34 * on 64 bits machines. That macro must _NOT_ be defined for Xlib 35 * client code, otherwise bad things happen. 36 * So let's undef that macro if necessary. 37 */ 38#ifdef _XSERVER64 39#undef _XSERVER64 40#endif 41#include <X11/Xutil.h> 42#include <X11/Xlibint.h> 43#include <X11/extensions/Xvlib.h> 44#include <X11/extensions/Xvproto.h> 45#include <X11/extensions/Xext.h> 46#include <X11/extensions/extutil.h> 47#define _HAVE_XALLOC_DECLS 48 49#include "hostx.h" 50#include "ephyrhostvideo.h" 51#include "ephyrlog.h" 52 53#ifndef TRUE 54#define TRUE 1 55#endif /*TRUE*/ 56 57#ifndef FALSE 58#define FALSE 0 59#endif /*FALSE*/ 60 61static XExtensionInfo _xv_info_data; 62static XExtensionInfo *xv_info = &_xv_info_data; 63static char *xv_extension_name = XvName; 64static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, 65 char * buf, int n); 66static int xv_close_display(Display *dpy, XExtCodes *codes); 67static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); 68 69static XExtensionHooks xv_extension_hooks = { 70 NULL, /* create_gc */ 71 NULL, /* copy_gc */ 72 NULL, /* flush_gc */ 73 NULL, /* free_gc */ 74 NULL, /* create_font */ 75 NULL, /* free_font */ 76 xv_close_display, /* close_display */ 77 xv_wire_to_event, /* wire_to_event */ 78 NULL, /* event_to_wire */ 79 NULL, /* error */ 80 xv_error_string /* error_string */ 81}; 82 83 84static char *xv_error_list[] = 85{ 86 "BadPort", /* XvBadPort */ 87 "BadEncoding", /* XvBadEncoding */ 88 "BadControl" /* XvBadControl */ 89}; 90 91 92#define XvCheckExtension(dpy, i, val) \ 93 XextCheckExtension(dpy, i, xv_extension_name, val) 94#define XvGetReq(name, req) \ 95 WORD64ALIGN\ 96 if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ 97 _XFlush(dpy);\ 98 req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ 99 req->reqType = info->codes->major_opcode;\ 100 req->xvReqType = xv_##name; \ 101 req->length = (SIZEOF(xv##name##Req))>>2;\ 102 dpy->bufptr += SIZEOF(xv##name##Req);\ 103 dpy->request++ 104 105static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) 106 107 108static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, 109 xv_extension_name, 110 &xv_extension_hooks, 111 XvNumEvents, NULL) 112 113static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, 114 XvNumErrors, xv_error_list) 115 116struct _EphyrHostXVAdaptorArray { 117 XvAdaptorInfo *adaptors ; 118 unsigned int nb_adaptors ; 119}; 120 121/*heavily copied from libx11*/ 122#define BUFSIZE 2048 123static void 124ephyrHostXVLogXErrorEvent (Display *a_display, 125 XErrorEvent *a_err_event, 126 FILE *a_fp) 127{ 128 char buffer[BUFSIZ]; 129 char mesg[BUFSIZ]; 130 char number[32]; 131 const char *mtype = "XlibMessage"; 132 register _XExtension *ext = (_XExtension *)NULL; 133 _XExtension *bext = (_XExtension *)NULL; 134 Display *dpy = a_display ; 135 136 XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); 137 XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); 138 (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); 139 XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", 140 mesg, BUFSIZ); 141 (void) fprintf(a_fp, mesg, a_err_event->request_code); 142 if (a_err_event->request_code < 128) { 143 sprintf(number, "%d", a_err_event->request_code); 144 XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); 145 } else { 146 for (ext = dpy->ext_procs; 147 ext && (ext->codes.major_opcode != a_err_event->request_code); 148 ext = ext->next) 149 ; 150 if (ext) 151 strcpy(buffer, ext->name); 152 else 153 buffer[0] = '\0'; 154 } 155 (void) fprintf(a_fp, " (%s)\n", buffer); 156 if (a_err_event->request_code >= 128) { 157 XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", 158 mesg, BUFSIZ); 159 fputs(" ", a_fp); 160 (void) fprintf(a_fp, mesg, a_err_event->minor_code); 161 if (ext) { 162 sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); 163 XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); 164 (void) fprintf(a_fp, " (%s)", buffer); 165 } 166 fputs("\n", a_fp); 167 } 168 if (a_err_event->error_code >= 128) { 169 /* kludge, try to find the extension that caused it */ 170 buffer[0] = '\0'; 171 for (ext = dpy->ext_procs; ext; ext = ext->next) { 172 if (ext->error_string) 173 (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, 174 buffer, BUFSIZ); 175 if (buffer[0]) { 176 bext = ext; 177 break; 178 } 179 if (ext->codes.first_error && 180 ext->codes.first_error < (int)a_err_event->error_code && 181 (!bext || ext->codes.first_error > bext->codes.first_error)) 182 bext = ext; 183 } 184 if (bext) 185 sprintf(buffer, "%s.%d", bext->name, 186 a_err_event->error_code - bext->codes.first_error); 187 else 188 strcpy(buffer, "Value"); 189 XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); 190 if (mesg[0]) { 191 fputs(" ", a_fp); 192 (void) fprintf(a_fp, mesg, a_err_event->resourceid); 193 fputs("\n", a_fp); 194 } 195 /* let extensions try to print the values */ 196 for (ext = dpy->ext_procs; ext; ext = ext->next) { 197 if (ext->error_values) 198 (*ext->error_values)(dpy, a_err_event, a_fp); 199 } 200 } else if ((a_err_event->error_code == BadWindow) || 201 (a_err_event->error_code == BadPixmap) || 202 (a_err_event->error_code == BadCursor) || 203 (a_err_event->error_code == BadFont) || 204 (a_err_event->error_code == BadDrawable) || 205 (a_err_event->error_code == BadColor) || 206 (a_err_event->error_code == BadGC) || 207 (a_err_event->error_code == BadIDChoice) || 208 (a_err_event->error_code == BadValue) || 209 (a_err_event->error_code == BadAtom)) { 210 if (a_err_event->error_code == BadValue) 211 XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", 212 mesg, BUFSIZ); 213 else if (a_err_event->error_code == BadAtom) 214 XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", 215 mesg, BUFSIZ); 216 else 217 XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", 218 mesg, BUFSIZ); 219 fputs(" ", a_fp); 220 (void) fprintf(a_fp, mesg, a_err_event->resourceid); 221 fputs("\n", a_fp); 222 } 223 XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", 224 mesg, BUFSIZ); 225 fputs(" ", a_fp); 226 (void) fprintf(a_fp, mesg, a_err_event->serial); 227 XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", 228 mesg, BUFSIZ); 229 fputs("\n ", a_fp); 230 (void) fprintf(a_fp, mesg, dpy->request); 231 fputs("\n", a_fp); 232} 233 234static int 235ephyrHostXVErrorHandler (Display *a_display, 236 XErrorEvent *a_error_event) 237{ 238 EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; 239 ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; 240 return Success ; 241} 242 243void 244ephyrHostXVInit (void) 245{ 246 static Bool s_initialized ; 247 248 if (s_initialized) 249 return ; 250 XSetErrorHandler (ephyrHostXVErrorHandler) ; 251 s_initialized = TRUE ; 252} 253 254Bool 255ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) 256{ 257 EphyrHostXVAdaptorArray *result=NULL ; 258 int ret=0 ; 259 Bool is_ok=FALSE ; 260 261 EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; 262 263 EPHYR_LOG ("enter\n") ; 264 265 result = calloc (1, sizeof (EphyrHostXVAdaptorArray)) ; 266 if (!result) 267 goto out ; 268 269 ret = XvQueryAdaptors (hostx_get_display (), 270 DefaultRootWindow (hostx_get_display ()), 271 &result->nb_adaptors, 272 &result->adaptors) ; 273 if (ret != Success) { 274 EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; 275 goto out ; 276 } 277 *a_adaptors = result ; 278 is_ok = TRUE ; 279 280out: 281 EPHYR_LOG ("leave\n") ; 282 return is_ok ; 283} 284 285void 286ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) 287{ 288 if (!a_adaptors) 289 return ; 290 if (a_adaptors->adaptors) { 291 XvFreeAdaptorInfo (a_adaptors->adaptors) ; 292 a_adaptors->adaptors = NULL ; 293 a_adaptors->nb_adaptors = 0 ; 294 } 295 XFree (a_adaptors) ; 296} 297 298int 299ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) 300{ 301 EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; 302 return a_this->nb_adaptors ; 303} 304 305EphyrHostXVAdaptor* 306ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, 307 int a_index) 308{ 309 EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; 310 311 if (a_index >= a_this->nb_adaptors) 312 return NULL ; 313 return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; 314} 315 316char 317ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) 318{ 319 EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; 320 return ((XvAdaptorInfo*)a_this)->type ; 321} 322 323const char* 324ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) 325{ 326 EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; 327 328 return ((XvAdaptorInfo*)a_this)->name ; 329} 330 331EphyrHostVideoFormat* 332ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, 333 int *a_nb_formats) 334{ 335 EphyrHostVideoFormat *formats=NULL ; 336 int nb_formats=0, i=0 ; 337 XVisualInfo *visual_info, visual_info_template ; 338 int nb_visual_info ; 339 340 EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; 341 342 nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; 343 formats = calloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; 344 for (i=0; i < nb_formats; i++) { 345 memset (&visual_info_template, 0, sizeof (visual_info_template)) ; 346 visual_info_template.visualid = 347 ((XvAdaptorInfo*)a_this)->formats[i].visual_id; 348 visual_info = XGetVisualInfo (hostx_get_display (), 349 VisualIDMask, 350 &visual_info_template, 351 &nb_visual_info) ; 352 formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; 353 formats[i].visual_class = visual_info->class ; 354 XFree (visual_info) ; 355 } 356 if (a_nb_formats) 357 *a_nb_formats = nb_formats ; 358 return formats ; 359} 360 361int 362ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) 363{ 364 EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; 365 366 return ((XvAdaptorInfo*)a_this)->num_ports ; 367} 368 369int 370ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) 371{ 372 EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; 373 374 return ((XvAdaptorInfo*)a_this)->base_id ; 375} 376 377Bool 378ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, 379 Bool *a_result) 380{ 381 EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; 382 383 if ((((XvAdaptorInfo*)a_this)->type & (XvVideoMask | XvInputMask)) == 384 (XvVideoMask | XvInputMask)) 385 *a_result = TRUE ; 386 else 387 *a_result = FALSE ; 388 return TRUE ; 389} 390 391Bool 392ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, 393 Bool *a_result) 394{ 395 if ((((XvAdaptorInfo*)a_this)->type & (XvVideoMask | XvOutputMask)) == 396 (XvVideoMask | XvOutputMask)) 397 *a_result = TRUE ; 398 else 399 *a_result = FALSE ; 400 return TRUE ; 401} 402 403Bool 404ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, 405 Bool *a_result) 406{ 407 EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; 408 409 if ((((XvAdaptorInfo*)a_this)->type & (XvStillMask | XvInputMask)) == 410 (XvStillMask | XvInputMask)) 411 *a_result = TRUE ; 412 else 413 *a_result = FALSE ; 414 return TRUE ; 415} 416 417Bool 418ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, 419 Bool *a_result) 420{ 421 EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; 422 423 if ((((XvAdaptorInfo*)a_this)->type & (XvStillMask | XvOutputMask)) == 424 (XvStillMask | XvOutputMask)) 425 *a_result = TRUE ; 426 else 427 *a_result = FALSE ; 428 return TRUE ; 429} 430 431Bool 432ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, 433 Bool *a_result) 434{ 435 EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; 436 437 if ((((XvAdaptorInfo*)a_this)->type & (XvImageMask | XvInputMask)) == 438 (XvImageMask | XvInputMask)) 439 *a_result = TRUE ; 440 else 441 *a_result = FALSE ; 442 return TRUE ; 443} 444 445Bool 446ephyrHostXVQueryEncodings (int a_port_id, 447 EphyrHostEncoding **a_encodings, 448 unsigned int *a_num_encodings) 449{ 450 EphyrHostEncoding *encodings=NULL ; 451 XvEncodingInfo *encoding_info=NULL ; 452 unsigned int num_encodings=0, i; 453 int ret=0 ; 454 455 EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; 456 457 ret = XvQueryEncodings (hostx_get_display (), 458 a_port_id, 459 &num_encodings, 460 &encoding_info) ; 461 if (num_encodings && encoding_info) { 462 encodings = calloc (num_encodings, sizeof (EphyrHostEncoding)) ; 463 for (i=0; i<num_encodings; i++) { 464 encodings[i].id = encoding_info[i].encoding_id ; 465 encodings[i].name = strdup (encoding_info[i].name) ; 466 encodings[i].width = encoding_info[i].width ; 467 encodings[i].height = encoding_info[i].height ; 468 encodings[i].rate.numerator = encoding_info[i].rate.numerator ; 469 encodings[i].rate.denominator = encoding_info[i].rate.denominator ; 470 } 471 } 472 if (encoding_info) { 473 XvFreeEncodingInfo (encoding_info) ; 474 encoding_info = NULL ; 475 } 476 *a_encodings = encodings ; 477 *a_num_encodings = num_encodings ; 478 479 if (ret != Success) 480 return FALSE ; 481 return TRUE ; 482} 483 484void 485ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, 486 int a_num_encodings) 487{ 488 int i=0 ; 489 490 if (!a_encodings) 491 return ; 492 for (i=0; i < a_num_encodings; i++) { 493 free(a_encodings[i].name) ; 494 a_encodings[i].name = NULL ; 495 } 496 free(a_encodings) ; 497} 498 499void 500ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) 501{ 502 if (!a_attributes) 503 return ; 504 XFree (a_attributes) ; 505} 506 507Bool 508ephyrHostXVQueryPortAttributes (int a_port_id, 509 EphyrHostAttribute **a_attributes, 510 int *a_num_attributes) 511{ 512 EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; 513 514 *a_attributes = 515 (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), 516 a_port_id, 517 a_num_attributes); 518 519 return TRUE ; 520} 521 522Bool 523ephyrHostXVQueryImageFormats (int a_port_id, 524 EphyrHostImageFormat **a_formats, 525 int *a_num_format) 526{ 527 XvImageFormatValues *result=NULL ; 528 529 EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; 530 531 result = XvListImageFormats (hostx_get_display (), 532 a_port_id, 533 a_num_format) ; 534 *a_formats = (EphyrHostImageFormat*) result ; 535 return TRUE ; 536 537} 538 539Bool 540ephyrHostXVSetPortAttribute (int a_port_id, 541 int a_atom, 542 int a_attr_value) 543{ 544 int res=Success ; 545 546 EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", 547 a_atom, 548 XGetAtomName (hostx_get_display (), a_atom), 549 a_attr_value) ; 550 551 res = XvSetPortAttribute (hostx_get_display (), 552 a_port_id, 553 a_atom, 554 a_attr_value) ; 555 if (res != Success) { 556 EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; 557 return FALSE ; 558 } 559 XFlush (hostx_get_display ()) ; 560 EPHYR_LOG ("leave\n") ; 561 562 return TRUE ; 563} 564 565Bool 566ephyrHostXVGetPortAttribute (int a_port_id, 567 int a_atom, 568 int *a_attr_value) 569{ 570 int res=Success ; 571 Bool ret=FALSE ; 572 573 EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; 574 575 EPHYR_LOG ("enter, a_port_id: %d, a_atomid: %d, attr_name: %s\n", 576 a_port_id, a_atom, XGetAtomName (hostx_get_display (), a_atom)) ; 577 578 res = XvGetPortAttribute (hostx_get_display (), 579 a_port_id, 580 a_atom, 581 a_attr_value) ; 582 if (res != Success) { 583 EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; 584 goto out ; 585 } 586 EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, *a_attr_value) ; 587 588 ret = TRUE ; 589 590out: 591 EPHYR_LOG ("leave\n") ; 592 return ret ; 593} 594 595Bool 596ephyrHostXVQueryBestSize (int a_port_id, 597 Bool a_motion, 598 unsigned int a_frame_w, 599 unsigned int a_frame_h, 600 unsigned int a_drw_w, 601 unsigned int a_drw_h, 602 unsigned int *a_actual_w, 603 unsigned int *a_actual_h) 604{ 605 int res=0 ; 606 Bool is_ok=FALSE ; 607 608 EPHYR_RETURN_VAL_IF_FAIL (a_actual_w && a_actual_h, FALSE) ; 609 610 EPHYR_LOG ("enter: frame (%dx%d), drw (%dx%d)\n", 611 a_frame_w, a_frame_h, 612 a_drw_w, a_drw_h) ; 613 614 res = XvQueryBestSize (hostx_get_display (), 615 a_port_id, 616 a_motion, 617 a_frame_w, a_frame_h, 618 a_drw_w, a_drw_h, 619 a_actual_w, a_actual_h) ; 620 if (res != Success) { 621 EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; 622 goto out ; 623 } 624 XSync (hostx_get_display (), FALSE) ; 625 626 EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; 627 is_ok = TRUE ; 628 629out: 630 EPHYR_LOG ("leave\n") ; 631 return is_ok ; 632} 633 634static Bool 635xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) 636{ 637 XExtDisplayInfo *info = xv_find_display (dpy); 638 XvEvent *re = (XvEvent *)host; 639 xvEvent *event = (xvEvent *)wire; 640 641 XvCheckExtension(dpy, info, False); 642 643 switch ((event->u.u.type & 0x7F) - info->codes->first_event) { 644 case XvVideoNotify: 645 re->xvvideo.type = event->u.u.type & 0x7f; 646 re->xvvideo.serial = 647 _XSetLastRequestRead(dpy, (xGenericReply *)event); 648 re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); 649 re->xvvideo.display = dpy; 650 re->xvvideo.time = event->u.videoNotify.time; 651 re->xvvideo.reason = event->u.videoNotify.reason; 652 re->xvvideo.drawable = event->u.videoNotify.drawable; 653 re->xvvideo.port_id = event->u.videoNotify.port; 654 break; 655 case XvPortNotify: 656 re->xvport.type = event->u.u.type & 0x7f; 657 re->xvport.serial = 658 _XSetLastRequestRead(dpy, (xGenericReply *)event); 659 re->xvport.send_event = ((event->u.u.type & 0x80) != 0); 660 re->xvport.display = dpy; 661 re->xvport.time = event->u.portNotify.time; 662 re->xvport.port_id = event->u.portNotify.port; 663 re->xvport.attribute = event->u.portNotify.attribute; 664 re->xvport.value = event->u.portNotify.value; 665 break; 666 default: 667 return False; 668 } 669 670 return True ; 671} 672 673Bool 674ephyrHostXVQueryImageAttributes (int a_port_id, 675 int a_image_id /*image fourcc code*/, 676 unsigned short *a_width, 677 unsigned short *a_height, 678 int *a_image_size, 679 int *a_pitches, 680 int *a_offsets) 681{ 682 Display *dpy = hostx_get_display () ; 683 Bool ret=FALSE ; 684 XExtDisplayInfo *info = xv_find_display (dpy); 685 xvQueryImageAttributesReq *req=NULL; 686 xvQueryImageAttributesReply rep; 687 688 EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; 689 EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; 690 EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; 691 692 XvCheckExtension (dpy, info, FALSE); 693 694 LockDisplay (dpy); 695 696 XvGetReq (QueryImageAttributes, req); 697 req->id = a_image_id; 698 req->port = a_port_id; 699 req->width = *a_width; 700 req->height = *a_height; 701 /* 702 * read the reply 703 */ 704 if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { 705 EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; 706 goto out ; 707 } 708 if (a_pitches && a_offsets) { 709 _XRead (dpy, 710 (char*)a_pitches, 711 rep.num_planes << 2); 712 _XRead (dpy, 713 (char*)a_offsets, 714 rep.num_planes << 2); 715 } else { 716 _XEatData(dpy, rep.length << 2); 717 } 718 *a_width = rep.width ; 719 *a_height = rep.height ; 720 *a_image_size = rep.data_size ; 721 722 ret = TRUE ; 723 724out: 725 UnlockDisplay (dpy) ; 726 SyncHandle (); 727 return ret ; 728} 729 730Bool 731ephyrHostGetAtom (const char* a_name, 732 Bool a_create_if_not_exists, 733 int *a_atom) 734{ 735 int atom=None ; 736 737 EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; 738 739 atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); 740 if (atom == None) { 741 return FALSE ; 742 } 743 *a_atom = atom ; 744 return TRUE ; 745} 746 747char* 748ephyrHostGetAtomName (int a_atom) 749{ 750 return XGetAtomName (hostx_get_display (), a_atom) ; 751} 752 753void 754ephyrHostFree (void *a_pointer) 755{ 756 if (a_pointer) 757 XFree (a_pointer) ; 758} 759 760Bool 761ephyrHostXVPutImage (int a_screen_num, 762 int a_port_id, 763 int a_image_id, 764 int a_drw_x, 765 int a_drw_y, 766 int a_drw_w, 767 int a_drw_h, 768 int a_src_x, 769 int a_src_y, 770 int a_src_w, 771 int a_src_h, 772 int a_image_width, 773 int a_image_height, 774 unsigned char *a_buf, 775 EphyrHostBox *a_clip_rects, 776 int a_clip_rect_nums ) 777{ 778 Bool is_ok=TRUE ; 779 XvImage *xv_image=NULL ; 780 GC gc=0 ; 781 XGCValues gc_values; 782 Display *dpy = hostx_get_display () ; 783 XRectangle *rects=NULL ; 784 int res = 0 ; 785 786 EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; 787 788 EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; 789 790 memset (&gc_values, 0, sizeof (gc_values)) ; 791 gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); 792 if (!gc) { 793 EPHYR_LOG_ERROR ("failed to create gc \n") ; 794 goto out ; 795 } 796 xv_image = (XvImage*) XvCreateImage (hostx_get_display (), 797 a_port_id, a_image_id, 798 NULL, a_image_width, a_image_height) ; 799 if (!xv_image) { 800 EPHYR_LOG_ERROR ("failed to create image\n") ; 801 goto out ; 802 } 803 xv_image->data = (char*)a_buf ; 804 if (a_clip_rect_nums) { 805 int i=0 ; 806 rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; 807 for (i=0; i < a_clip_rect_nums; i++) { 808 rects[i].x = a_clip_rects[i].x1 ; 809 rects[i].y = a_clip_rects[i].y1 ; 810 rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; 811 rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; 812 EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", 813 rects[i].x, rects[i].y, 814 rects[i].width, rects[i].height) ; 815 } 816 XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; 817 /*this always returns 1*/ 818 } 819 res = XvPutImage (dpy, a_port_id, 820 hostx_get_window (a_screen_num), 821 gc, xv_image, 822 a_src_x, a_src_y, a_src_w, a_src_h, 823 a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; 824 if (res != Success) { 825 EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; 826 goto out ; 827 } 828 is_ok = TRUE ; 829 830out: 831 if (xv_image) { 832 XFree (xv_image) ; 833 xv_image = NULL ; 834 } 835 if (gc) { 836 XFreeGC (dpy, gc) ; 837 gc = NULL ; 838 } 839 free(rects); 840 rects = NULL; 841 EPHYR_LOG ("leave\n") ; 842 return is_ok ; 843} 844 845Bool 846ephyrHostXVPutVideo (int a_screen_num, int a_port_id, 847 int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, 848 int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) 849{ 850 Bool is_ok=FALSE ; 851 int res=FALSE ; 852 GC gc=0 ; 853 XGCValues gc_values; 854 Display *dpy=hostx_get_display () ; 855 856 EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; 857 858 gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); 859 if (!gc) { 860 EPHYR_LOG_ERROR ("failed to create gc \n") ; 861 goto out ; 862 } 863 res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, 864 a_vid_x, a_vid_y, a_vid_w, a_vid_h, 865 a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; 866 867 if (res != Success) { 868 EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; 869 goto out ; 870 } 871 872 is_ok = TRUE ; 873 874out: 875 if (gc) { 876 XFreeGC (dpy, gc) ; 877 gc = NULL ; 878 } 879 return is_ok ; 880} 881 882Bool 883ephyrHostXVGetVideo (int a_screen_num, int a_port_id, 884 int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, 885 int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) 886{ 887 Bool is_ok=FALSE ; 888 int res=FALSE ; 889 GC gc=0 ; 890 XGCValues gc_values; 891 Display *dpy=hostx_get_display () ; 892 893 EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; 894 895 gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); 896 if (!gc) { 897 EPHYR_LOG_ERROR ("failed to create gc \n") ; 898 goto out ; 899 } 900 res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, 901 a_vid_x, a_vid_y, a_vid_w, a_vid_h, 902 a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; 903 904 if (res != Success) { 905 EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; 906 goto out ; 907 } 908 909 is_ok = TRUE ; 910 911out: 912 if (gc) { 913 XFreeGC (dpy, gc) ; 914 gc = NULL ; 915 } 916 return is_ok ; 917} 918 919Bool 920ephyrHostXVPutStill (int a_screen_num, int a_port_id, 921 int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, 922 int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) 923{ 924 Bool is_ok=FALSE ; 925 int res=FALSE ; 926 GC gc=0 ; 927 XGCValues gc_values; 928 Display *dpy=hostx_get_display () ; 929 930 EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; 931 932 gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); 933 if (!gc) { 934 EPHYR_LOG_ERROR ("failed to create gc \n") ; 935 goto out ; 936 } 937 res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, 938 a_vid_x, a_vid_y, a_vid_w, a_vid_h, 939 a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; 940 941 if (res != Success) { 942 EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; 943 goto out ; 944 } 945 946 is_ok = TRUE ; 947 948out: 949 if (gc) { 950 XFreeGC (dpy, gc) ; 951 gc = NULL ; 952 } 953 return is_ok ; 954} 955 956Bool 957ephyrHostXVGetStill (int a_screen_num, int a_port_id, 958 int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, 959 int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) 960{ 961 Bool is_ok=FALSE ; 962 int res=FALSE ; 963 GC gc=0 ; 964 XGCValues gc_values; 965 Display *dpy=hostx_get_display () ; 966 967 EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; 968 969 gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); 970 if (!gc) { 971 EPHYR_LOG_ERROR ("failed to create gc \n") ; 972 goto out ; 973 } 974 res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, 975 a_vid_x, a_vid_y, a_vid_w, a_vid_h, 976 a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; 977 978 if (res != Success) { 979 EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; 980 goto out ; 981 } 982 983 is_ok = TRUE ; 984 985out: 986 if (gc) { 987 XFreeGC (dpy, gc) ; 988 gc = NULL ; 989 } 990 return is_ok ; 991} 992 993Bool 994ephyrHostXVStopVideo (int a_screen_num, int a_port_id) 995{ 996 int ret=0 ; 997 Bool is_ok=FALSE ; 998 Display *dpy = hostx_get_display () ; 999 1000 EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; 1001 1002 EPHYR_LOG ("enter\n") ; 1003 1004 ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; 1005 if (ret != Success) { 1006 EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; 1007 goto out ; 1008 } 1009 is_ok = TRUE ; 1010 1011out: 1012 EPHYR_LOG ("leave\n") ; 1013 return is_ok ; 1014} 1015 1016