Xv.c revision 949d0342
1/*********************************************************** 2Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, 3and the Massachusetts Institute of Technology, Cambridge, Massachusetts. 4 5 All Rights Reserved 6 7Permission to use, copy, modify, and distribute this software and its 8documentation for any purpose and without fee is hereby granted, 9provided that the above copyright notice appear in all copies and that 10both that copyright notice and this permission notice appear in 11supporting documentation, and that the names of Digital or MIT not be 12used in advertising or publicity pertaining to distribution of the 13software without specific, written prior permission. 14 15DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 16ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 17DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 18ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 19WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 20ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 21SOFTWARE. 22 23******************************************************************/ 24/* 25** File: 26** 27** Xv.c --- Xv library extension module. 28** 29** Author: 30** 31** David Carver (Digital Workstation Engineering/Project Athena) 32** 33** Revisions: 34** 35** 26.06.91 Carver 36** - changed XvFreeAdaptors to XvFreeAdaptorInfo 37** - changed XvFreeEncodings to XvFreeEncodingInfo 38** 39** 11.06.91 Carver 40** - changed SetPortControl to SetPortAttribute 41** - changed GetPortControl to GetPortAttribute 42** - changed QueryBestSize 43** 44** 15.05.91 Carver 45** - version 2.0 upgrade 46** 47** 240.01.91 Carver 48** - version 1.4 upgrade 49** 50*/ 51 52#ifdef HAVE_CONFIG_H 53# include "config.h" 54#endif 55 56#include <stdio.h> 57#include "Xvlibint.h" 58#include <X11/extensions/Xext.h> 59#include <X11/extensions/extutil.h> 60#include <X11/extensions/XShm.h> 61#include <limits.h> 62 63static XExtensionInfo _xv_info_data; 64static XExtensionInfo *xv_info = &_xv_info_data; 65static const char *xv_extension_name = XvName; 66 67#define XvCheckExtension(dpy, i, val) \ 68 XextCheckExtension(dpy, i, xv_extension_name, val) 69 70#define pad_to_int32(bytes) (((bytes) + 3) & ~3U) 71 72static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, 73 char *buf, int n); 74static int xv_close_display(Display *dpy, XExtCodes *codes); 75static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); 76 77static XExtensionHooks xv_extension_hooks = { 78 NULL, /* create_gc */ 79 NULL, /* copy_gc */ 80 NULL, /* flush_gc */ 81 NULL, /* free_gc */ 82 NULL, /* create_font */ 83 NULL, /* free_font */ 84 xv_close_display, /* close_display */ 85 xv_wire_to_event, /* wire_to_event */ 86 NULL, /* event_to_wire */ 87 NULL, /* error */ 88 xv_error_string /* error_string */ 89}; 90 91 92static const char *xv_error_list[] = { 93 "BadPort", /* XvBadPort */ 94 "BadEncoding", /* XvBadEncoding */ 95 "BadControl" /* XvBadControl */ 96}; 97 98static XEXT_GENERATE_CLOSE_DISPLAY(xv_close_display, xv_info) 99 100static XEXT_GENERATE_FIND_DISPLAY(xv_find_display, xv_info, 101 xv_extension_name, &xv_extension_hooks, 102 XvNumEvents, NULL) 103 104static XEXT_GENERATE_ERROR_STRING(xv_error_string, xv_extension_name, 105 XvNumErrors, xv_error_list) 106 107 108int 109XvQueryExtension( 110 Display *dpy, 111 unsigned int *p_version, 112 unsigned int *p_revision, 113 unsigned int *p_requestBase, 114 unsigned int *p_eventBase, 115 unsigned int *p_errorBase) 116{ 117 XExtDisplayInfo *info = xv_find_display(dpy); 118 xvQueryExtensionReq *req; 119 xvQueryExtensionReply rep; 120 int status; 121 122 XvCheckExtension(dpy, info, XvBadExtension); 123 124 LockDisplay(dpy); 125 126 XvGetReq(QueryExtension, req); 127 128 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 129 status = XvBadExtension; 130 goto out; 131 } 132 133 *p_version = rep.version; 134 *p_revision = rep.revision; 135 *p_requestBase = (unsigned int) info->codes->major_opcode; 136 *p_eventBase = (unsigned int) info->codes->first_event; 137 *p_errorBase = (unsigned int) info->codes->first_error; 138 139 status = Success; 140 141 out: 142 UnlockDisplay(dpy); 143 SyncHandle(); 144 145 return status; 146} 147 148int 149XvQueryAdaptors( 150 Display *dpy, 151 Window window, 152 unsigned int *p_nAdaptors, 153 XvAdaptorInfo **p_pAdaptors) 154{ 155 XExtDisplayInfo *info = xv_find_display(dpy); 156 xvQueryAdaptorsReq *req; 157 xvQueryAdaptorsReply rep; 158 size_t size; 159 XvAdaptorInfo *pas = NULL, *pa; 160 XvFormat *pfs, *pf; 161 char *buffer = NULL; 162 char *end; 163 union { 164 char *buffer; 165 char *string; 166 xvAdaptorInfo *pa; 167 xvFormat *pf; 168 } u; 169 int status; 170 171 XvCheckExtension(dpy, info, XvBadExtension); 172 173 LockDisplay(dpy); 174 175 XvGetReq(QueryAdaptors, req); 176 req->window = (CARD32) window; 177 178 /* READ THE REPLY */ 179 180 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 181 rep.num_adaptors = 0; 182 status = XvBadReply; 183 goto out; 184 } 185 186 size = rep.length << 2; 187 if (size > 0) { 188 if ((buffer = Xmalloc(size)) == NULL) { 189 _XEatDataWords(dpy, rep.length); 190 status = XvBadAlloc; 191 goto out; 192 } 193 _XRead(dpy, buffer, (long) size); 194 } 195 196 /* GET INPUT ADAPTORS */ 197 198 if (rep.num_adaptors == 0) { 199 /* If there are no adaptors, there's nothing more to do. */ 200 status = Success; 201 goto out; 202 } 203 204 u.buffer = buffer; 205 end = buffer + size; 206 207 size = rep.num_adaptors * sizeof(XvAdaptorInfo); 208 if ((pas = Xmalloc(size)) == NULL) { 209 status = XvBadAlloc; 210 goto out; 211 } 212 213 /* INIT ADAPTOR FIELDS */ 214 215 pa = pas; 216 for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) { 217 pa->num_adaptors = 0; 218 pa->name = (char *) NULL; 219 pa->formats = (XvFormat *) NULL; 220 pa++; 221 } 222 223 pa = pas; 224 for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) { 225 char *name; 226 227 if (u.buffer + sz_xvAdaptorInfo > end) { 228 status = XvBadReply; 229 goto out; 230 } 231 pa->type = (char) u.pa->type; 232 pa->base_id = u.pa->base_id; 233 pa->num_ports = u.pa->num_ports; 234 pa->num_formats = u.pa->num_formats; 235 pa->num_adaptors = rep.num_adaptors - ii; 236 237 /* GET ADAPTOR NAME */ 238 239 size = u.pa->name_size; 240 u.buffer += pad_to_int32(sz_xvAdaptorInfo); 241 242 if (u.buffer + size > end) { 243 status = XvBadReply; 244 goto out; 245 } 246 if ((name = Xmalloc(size + 1)) == NULL) { 247 status = XvBadAlloc; 248 goto out; 249 } 250 (void) strncpy(name, u.string, size); 251 name[size] = '\0'; 252 pa->name = name; 253 254 u.buffer += pad_to_int32(size); 255 256 /* GET FORMATS */ 257 258 size = pa->num_formats * sizeof(XvFormat); 259 if ((pfs = Xmalloc(size)) == NULL) { 260 status = XvBadAlloc; 261 goto out; 262 } 263 264 pf = pfs; 265 for (unsigned int jj = 0; jj < pa->num_formats; jj++) { 266 if (u.buffer + sz_xvFormat > end) { 267 Xfree(pfs); 268 status = XvBadReply; 269 goto out; 270 } 271 pf->depth = (char) u.pf->depth; 272 pf->visual_id = u.pf->visual; 273 pf++; 274 275 u.buffer += pad_to_int32(sz_xvFormat); 276 } 277 278 pa->formats = pfs; 279 280 pa++; 281 282 } 283 284 status = Success; 285 286 out: 287 if (status != Success) { 288 XvFreeAdaptorInfo(pas); 289 pas = NULL; 290 } 291 292 *p_nAdaptors = rep.num_adaptors; 293 *p_pAdaptors = pas; 294 295 Xfree(buffer); 296 UnlockDisplay(dpy); 297 SyncHandle(); 298 299 return status; 300} 301 302 303void 304XvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors) 305{ 306 XvAdaptorInfo *pa; 307 308 if (!pAdaptors) 309 return; 310 311 pa = pAdaptors; 312 313 for (unsigned int ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) { 314 if (pa->name) { 315 Xfree(pa->name); 316 } 317 if (pa->formats) { 318 Xfree(pa->formats); 319 } 320 } 321 322 Xfree(pAdaptors); 323} 324 325int 326XvQueryEncodings( 327 Display *dpy, 328 XvPortID port, 329 unsigned int *p_nEncodings, 330 XvEncodingInfo ** p_pEncodings) 331{ 332 XExtDisplayInfo *info = xv_find_display(dpy); 333 xvQueryEncodingsReq *req; 334 xvQueryEncodingsReply rep; 335 size_t size; 336 XvEncodingInfo *pes = NULL, *pe; 337 char *buffer = NULL; 338 char *end; 339 union { 340 char *buffer; 341 char *string; 342 xvEncodingInfo *pe; 343 } u; 344 int status; 345 346 XvCheckExtension(dpy, info, XvBadExtension); 347 348 LockDisplay(dpy); 349 350 XvGetReq(QueryEncodings, req); 351 req->port = (CARD32) port; 352 353 /* READ THE REPLY */ 354 355 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 356 rep.num_encodings = 0; 357 status = XvBadReply; 358 goto out; 359 } 360 361 size = rep.length << 2; 362 if (size > 0) { 363 if ((buffer = Xmalloc(size)) == NULL) { 364 _XEatDataWords(dpy, rep.length); 365 status = XvBadAlloc; 366 goto out; 367 } 368 _XRead(dpy, buffer, (long) size); 369 } 370 371 /* GET ENCODINGS */ 372 373 if (rep.num_encodings == 0) { 374 /* If there are no encodings, there's nothing more to do. */ 375 status = Success; 376 goto out; 377 } 378 379 u.buffer = buffer; 380 end = buffer + size; 381 382 size = rep.num_encodings * sizeof(XvEncodingInfo); 383 if ((pes = Xmalloc(size)) == NULL) { 384 status = XvBadAlloc; 385 goto out; 386 } 387 388 /* INITIALIZE THE ENCODING POINTER */ 389 390 pe = pes; 391 for (unsigned int jj = 0; jj < rep.num_encodings; jj++) { 392 pe->name = (char *) NULL; 393 pe->num_encodings = 0; 394 pe++; 395 } 396 397 pe = pes; 398 for (unsigned int jj = 0; jj < rep.num_encodings; jj++) { 399 char *name; 400 401 if (u.buffer + sz_xvEncodingInfo > end) { 402 status = XvBadReply; 403 goto out; 404 } 405 pe->encoding_id = u.pe->encoding; 406 pe->width = u.pe->width; 407 pe->height = u.pe->height; 408 pe->rate.numerator = u.pe->rate.numerator; 409 pe->rate.denominator = u.pe->rate.denominator; 410 pe->num_encodings = rep.num_encodings - jj; 411 412 size = u.pe->name_size; 413 u.buffer += pad_to_int32(sz_xvEncodingInfo); 414 415 if (u.buffer + size > end) { 416 status = XvBadReply; 417 goto out; 418 } 419 if ((name = Xmalloc(size + 1)) == NULL) { 420 status = XvBadAlloc; 421 goto out; 422 } 423 strncpy(name, u.string, size); 424 name[size] = '\0'; 425 pe->name = name; 426 pe++; 427 428 u.buffer += pad_to_int32(size); 429 } 430 431 status = Success; 432 433 out: 434 if (status != Success) { 435 XvFreeEncodingInfo(pes); 436 pes = NULL; 437 } 438 439 *p_nEncodings = rep.num_encodings; 440 *p_pEncodings = pes; 441 442 Xfree(buffer); 443 UnlockDisplay(dpy); 444 SyncHandle(); 445 446 return (Success); 447} 448 449void 450XvFreeEncodingInfo(XvEncodingInfo *pEncodings) 451{ 452 XvEncodingInfo *pe; 453 454 if (!pEncodings) 455 return; 456 457 pe = pEncodings; 458 459 for (unsigned long ii = 0; ii < pEncodings->num_encodings; ii++, pe++) { 460 if (pe->name) 461 Xfree(pe->name); 462 } 463 464 Xfree(pEncodings); 465} 466 467int 468XvPutVideo( 469 Display *dpy, 470 XvPortID port, 471 Drawable d, 472 GC gc, 473 int vx, int vy, 474 unsigned int vw, unsigned int vh, 475 int dx, int dy, 476 unsigned int dw, unsigned int dh) 477{ 478 XExtDisplayInfo *info = xv_find_display(dpy); 479 xvPutVideoReq *req; 480 481 XvCheckExtension(dpy, info, XvBadExtension); 482 483 LockDisplay(dpy); 484 485 FlushGC(dpy, gc); 486 487 XvGetReq(PutVideo, req); 488 489 req->port = (CARD32) port; 490 req->drawable = (CARD32) d; 491 req->gc = (CARD32) gc->gid; 492 req->vid_x = (INT16) vx; 493 req->vid_y = (INT16) vy; 494 req->vid_w = (CARD16) vw; 495 req->vid_h = (CARD16) vh; 496 req->drw_x = (INT16) dx; 497 req->drw_y = (INT16) dy; 498 req->drw_w = (CARD16) dw; 499 req->drw_h = (CARD16) dh; 500 501 UnlockDisplay(dpy); 502 SyncHandle(); 503 504 return Success; 505} 506 507int 508XvPutStill( 509 Display *dpy, 510 XvPortID port, 511 Drawable d, 512 GC gc, 513 int vx, int vy, 514 unsigned int vw, unsigned int vh, 515 int dx, int dy, 516 unsigned int dw, unsigned int dh) 517{ 518 XExtDisplayInfo *info = xv_find_display(dpy); 519 xvPutStillReq *req; 520 521 XvCheckExtension(dpy, info, XvBadExtension); 522 523 LockDisplay(dpy); 524 525 FlushGC(dpy, gc); 526 527 XvGetReq(PutStill, req); 528 req->port = (CARD32) port; 529 req->drawable = (CARD32) d; 530 req->gc = (CARD32) gc->gid; 531 req->vid_x = (INT16) vx; 532 req->vid_y = (INT16) vy; 533 req->vid_w = (CARD16) vw; 534 req->vid_h = (CARD16) vh; 535 req->drw_x = (INT16) dx; 536 req->drw_y = (INT16) dy; 537 req->drw_w = (CARD16) dw; 538 req->drw_h = (CARD16) dh; 539 540 UnlockDisplay(dpy); 541 SyncHandle(); 542 543 return Success; 544} 545 546int 547XvGetVideo( 548 Display *dpy, 549 XvPortID port, 550 Drawable d, 551 GC gc, 552 int vx, int vy, 553 unsigned int vw, unsigned int vh, 554 int dx, int dy, 555 unsigned int dw, unsigned int dh) 556{ 557 XExtDisplayInfo *info = xv_find_display(dpy); 558 xvGetVideoReq *req; 559 560 XvCheckExtension(dpy, info, XvBadExtension); 561 562 LockDisplay(dpy); 563 564 FlushGC(dpy, gc); 565 566 XvGetReq(GetVideo, req); 567 req->port = (CARD32) port; 568 req->drawable = (CARD32) d; 569 req->gc = (CARD32) gc->gid; 570 req->vid_x = (INT16) vx; 571 req->vid_y = (INT16) vy; 572 req->vid_w = (CARD16) vw; 573 req->vid_h = (CARD16) vh; 574 req->drw_x = (INT16) dx; 575 req->drw_y = (INT16) dy; 576 req->drw_w = (CARD16) dw; 577 req->drw_h = (CARD16) dh; 578 579 UnlockDisplay(dpy); 580 SyncHandle(); 581 582 return Success; 583} 584 585int 586XvGetStill( 587 Display *dpy, 588 XvPortID port, 589 Drawable d, 590 GC gc, 591 int vx, int vy, 592 unsigned int vw, unsigned int vh, 593 int dx, int dy, 594 unsigned int dw, unsigned int dh) 595{ 596 XExtDisplayInfo *info = xv_find_display(dpy); 597 xvGetStillReq *req; 598 599 XvCheckExtension(dpy, info, XvBadExtension); 600 601 LockDisplay(dpy); 602 603 FlushGC(dpy, gc); 604 605 XvGetReq(GetStill, req); 606 req->port = (CARD32) port; 607 req->drawable = (CARD32) d; 608 req->gc = (CARD32) gc->gid; 609 req->vid_x = (INT16) vx; 610 req->vid_y = (INT16) vy; 611 req->vid_w = (CARD16) vw; 612 req->vid_h = (CARD16) vh; 613 req->drw_x = (INT16) dx; 614 req->drw_y = (INT16) dy; 615 req->drw_w = (CARD16) dw; 616 req->drw_h = (CARD16) dh; 617 618 UnlockDisplay(dpy); 619 SyncHandle(); 620 621 return Success; 622} 623 624int 625XvStopVideo(Display *dpy, XvPortID port, Drawable draw) 626{ 627 XExtDisplayInfo *info = xv_find_display(dpy); 628 xvStopVideoReq *req; 629 630 XvCheckExtension(dpy, info, XvBadExtension); 631 632 LockDisplay(dpy); 633 634 XvGetReq(StopVideo, req); 635 req->port = (CARD32) port; 636 req->drawable = (CARD32) draw; 637 638 UnlockDisplay(dpy); 639 SyncHandle(); 640 641 return Success; 642} 643 644int 645XvGrabPort(Display *dpy, XvPortID port, Time time) 646{ 647 XExtDisplayInfo *info = xv_find_display(dpy); 648 int result; 649 xvGrabPortReply rep; 650 xvGrabPortReq *req; 651 652 XvCheckExtension(dpy, info, XvBadExtension); 653 654 LockDisplay(dpy); 655 656 XvGetReq(GrabPort, req); 657 req->port = (CARD32) port; 658 req->time = (CARD32) time; 659 660 if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0) 661 rep.result = GrabSuccess; 662 663 result = rep.result; 664 665 UnlockDisplay(dpy); 666 SyncHandle(); 667 668 return result; 669} 670 671int 672XvUngrabPort(Display *dpy, XvPortID port, Time time) 673{ 674 XExtDisplayInfo *info = xv_find_display(dpy); 675 xvUngrabPortReq *req; 676 677 XvCheckExtension(dpy, info, XvBadExtension); 678 679 LockDisplay(dpy); 680 681 XvGetReq(UngrabPort, req); 682 req->port = (CARD32) port; 683 req->time = (CARD32) time; 684 685 UnlockDisplay(dpy); 686 SyncHandle(); 687 688 return Success; 689} 690 691int 692XvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff) 693{ 694 XExtDisplayInfo *info = xv_find_display(dpy); 695 xvSelectVideoNotifyReq *req; 696 697 XvCheckExtension(dpy, info, XvBadExtension); 698 699 LockDisplay(dpy); 700 701 XvGetReq(SelectVideoNotify, req); 702 req->drawable = (CARD32) drawable; 703 req->onoff = (BOOL) onoff; 704 705 UnlockDisplay(dpy); 706 SyncHandle(); 707 708 return Success; 709} 710 711int 712XvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff) 713{ 714 XExtDisplayInfo *info = xv_find_display(dpy); 715 xvSelectPortNotifyReq *req; 716 717 XvCheckExtension(dpy, info, XvBadExtension); 718 719 LockDisplay(dpy); 720 721 XvGetReq(SelectPortNotify, req); 722 req->port = (CARD32) port; 723 req->onoff = (BOOL) onoff; 724 725 UnlockDisplay(dpy); 726 SyncHandle(); 727 728 return Success; 729} 730 731int 732XvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value) 733{ 734 XExtDisplayInfo *info = xv_find_display(dpy); 735 xvSetPortAttributeReq *req; 736 737 XvCheckExtension(dpy, info, XvBadExtension); 738 739 LockDisplay(dpy); 740 741 XvGetReq(SetPortAttribute, req); 742 req->port = (CARD32) port; 743 req->attribute = (CARD32) attribute; 744 req->value = value; 745 746 UnlockDisplay(dpy); 747 SyncHandle(); 748 749 return (Success); 750} 751 752int 753XvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value) 754{ 755 XExtDisplayInfo *info = xv_find_display(dpy); 756 xvGetPortAttributeReq *req; 757 xvGetPortAttributeReply rep; 758 int status; 759 760 XvCheckExtension(dpy, info, XvBadExtension); 761 762 LockDisplay(dpy); 763 764 XvGetReq(GetPortAttribute, req); 765 req->port = (CARD32) port; 766 req->attribute = (CARD32) attribute; 767 768 /* READ THE REPLY */ 769 770 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 771 status = XvBadReply; 772 } 773 else { 774 *p_value = rep.value; 775 status = Success; 776 } 777 778 UnlockDisplay(dpy); 779 SyncHandle(); 780 781 return status; 782} 783 784int 785XvQueryBestSize( 786 Display *dpy, 787 XvPortID port, 788 Bool motion, 789 unsigned int vid_w, 790 unsigned int vid_h, 791 unsigned int drw_w, 792 unsigned int drw_h, 793 unsigned int *p_actual_width, 794 unsigned int *p_actual_height) 795{ 796 XExtDisplayInfo *info = xv_find_display(dpy); 797 xvQueryBestSizeReq *req; 798 xvQueryBestSizeReply rep; 799 int status; 800 801 XvCheckExtension(dpy, info, XvBadExtension); 802 803 LockDisplay(dpy); 804 805 XvGetReq(QueryBestSize, req); 806 req->port = (CARD32) port; 807 req->motion = (CARD8) motion; 808 req->vid_w = (CARD16) vid_w; 809 req->vid_h = (CARD16) vid_h; 810 req->drw_w = (CARD16) drw_w; 811 req->drw_h = (CARD16) drw_h; 812 813 /* READ THE REPLY */ 814 815 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 816 status = XvBadReply; 817 } 818 else { 819 *p_actual_width = rep.actual_width; 820 *p_actual_height = rep.actual_height; 821 status = Success; 822 } 823 824 UnlockDisplay(dpy); 825 SyncHandle(); 826 827 return status; 828} 829 830 831XvAttribute * 832XvQueryPortAttributes(Display *dpy, XvPortID port, int *num) 833{ 834 XExtDisplayInfo *info = xv_find_display(dpy); 835 xvQueryPortAttributesReq *req; 836 xvQueryPortAttributesReply rep; 837 XvAttribute *ret = NULL; 838 839 *num = 0; 840 841 XvCheckExtension(dpy, info, NULL); 842 843 LockDisplay(dpy); 844 845 XvGetReq(QueryPortAttributes, req); 846 req->port = (CARD32) port; 847 848 /* READ THE REPLY */ 849 850 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 851 goto out; 852 } 853 854 /* 855 * X server sends data packed as: 856 * attribute1, name1, attribute2, name2, ... 857 * We allocate a single buffer large enough to hold them all and 858 * then de-interleave the data so we return it to clients as: 859 * attribute1, attribute2, ..., name1, name2, ... 860 * so that clients may refer to attributes as a simple array of 861 * structs: attributes[0], attributes[1], ... 862 * and free it as a single/simple buffer. 863 */ 864 865 if (rep.num_attributes) { 866 /* limit each part to no more than one half the max size */ 867 if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) && 868 (rep.text_size < (INT_MAX / 2) - 1)) { 869 unsigned long size; 870 871 size = (rep.num_attributes * sizeof(XvAttribute)) + 872 rep.text_size + 1; 873 ret = Xmalloc(size); 874 } 875 876 if (ret != NULL) { 877 char *marker = (char *) (&ret[rep.num_attributes]); 878 xvAttributeInfo Info; 879 880 /* keep track of remaining room for text strings */ 881 unsigned long size = rep.text_size; 882 883 for (unsigned int i = 0; i < rep.num_attributes; i++) { 884 _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo); 885 ret[i].flags = (int) Info.flags; 886 ret[i].min_value = Info.min; 887 ret[i].max_value = Info.max; 888 ret[i].name = marker; 889 if (Info.size <= size) { 890 _XRead(dpy, marker, Info.size); 891 marker += Info.size; 892 size -= Info.size; 893 } 894 (*num)++; 895 } 896 897 /* ensure final string is nil-terminated to avoid exposure of 898 uninitialized memory */ 899 *marker = '\0'; 900 } 901 else 902 _XEatDataWords(dpy, rep.length); 903 } 904 905 out: 906 UnlockDisplay(dpy); 907 SyncHandle(); 908 909 return ret; 910} 911 912XvImageFormatValues * 913XvListImageFormats(Display *dpy, XvPortID port, int *num) 914{ 915 XExtDisplayInfo *info = xv_find_display(dpy); 916 xvListImageFormatsReq *req; 917 xvListImageFormatsReply rep; 918 XvImageFormatValues *ret = NULL; 919 920 *num = 0; 921 922 XvCheckExtension(dpy, info, NULL); 923 924 LockDisplay(dpy); 925 926 XvGetReq(ListImageFormats, req); 927 req->port = (CARD32) port; 928 929 /* READ THE REPLY */ 930 931 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 932 goto out; 933 } 934 935 if (rep.num_formats) { 936 if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues))) 937 ret = Xmalloc(rep.num_formats * sizeof(XvImageFormatValues)); 938 939 if (ret != NULL) { 940 for (unsigned int i = 0; i < rep.num_formats; i++) { 941 xvImageFormatInfo Info; 942 943 _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo); 944 ret[i].id = (int) Info.id; 945 ret[i].type = Info.type; 946 ret[i].byte_order = Info.byte_order; 947 memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16); 948 ret[i].bits_per_pixel = Info.bpp; 949 ret[i].format = Info.format; 950 ret[i].num_planes = Info.num_planes; 951 ret[i].depth = Info.depth; 952 ret[i].red_mask = Info.red_mask; 953 ret[i].green_mask = Info.green_mask; 954 ret[i].blue_mask = Info.blue_mask; 955 ret[i].y_sample_bits = Info.y_sample_bits; 956 ret[i].u_sample_bits = Info.u_sample_bits; 957 ret[i].v_sample_bits = Info.v_sample_bits; 958 ret[i].horz_y_period = Info.horz_y_period; 959 ret[i].horz_u_period = Info.horz_u_period; 960 ret[i].horz_v_period = Info.horz_v_period; 961 ret[i].vert_y_period = Info.vert_y_period; 962 ret[i].vert_u_period = Info.vert_u_period; 963 ret[i].vert_v_period = Info.vert_v_period; 964 memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32); 965 ret[i].scanline_order = Info.scanline_order; 966 (*num)++; 967 } 968 } 969 else 970 _XEatDataWords(dpy, rep.length); 971 } 972 973 out: 974 UnlockDisplay(dpy); 975 SyncHandle(); 976 977 return ret; 978} 979 980XvImage * 981XvCreateImage( 982 Display *dpy, 983 XvPortID port, 984 int id, 985 char *data, 986 int width, 987 int height) 988{ 989 XExtDisplayInfo *info = xv_find_display(dpy); 990 xvQueryImageAttributesReq *req; 991 xvQueryImageAttributesReply rep; 992 XvImage *ret = NULL; 993 994 XvCheckExtension(dpy, info, NULL); 995 996 LockDisplay(dpy); 997 998 XvGetReq(QueryImageAttributes, req); 999 req->id = (CARD32) id; 1000 req->port = (CARD32) port; 1001 req->width = (CARD16) width; 1002 req->height = (CARD16) height; 1003 1004 /* READ THE REPLY */ 1005 1006 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 1007 goto out; 1008 } 1009 1010 if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage))) 1011 ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3)); 1012 1013 if (ret != NULL) { 1014 ret->id = id; 1015 ret->width = rep.width; 1016 ret->height = rep.height; 1017 ret->data_size = (int) rep.data_size; 1018 ret->num_planes = (int) rep.num_planes; 1019 ret->pitches = (int *) (&ret[1]); 1020 ret->offsets = ret->pitches + rep.num_planes; 1021 ret->data = data; 1022 ret->obdata = NULL; 1023 _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2); 1024 _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2); 1025 } 1026 else 1027 _XEatDataWords(dpy, rep.length); 1028 1029 out: 1030 UnlockDisplay(dpy); 1031 SyncHandle(); 1032 1033 return ret; 1034} 1035 1036XvImage * 1037XvShmCreateImage( 1038 Display *dpy, 1039 XvPortID port, 1040 int id, 1041 char *data, 1042 int width, 1043 int height, 1044 XShmSegmentInfo *shminfo) 1045{ 1046 XvImage *ret; 1047 1048 ret = XvCreateImage(dpy, port, id, data, width, height); 1049 1050 if (ret) 1051 ret->obdata = (XPointer) shminfo; 1052 1053 return ret; 1054} 1055 1056int 1057XvPutImage( 1058 Display *dpy, 1059 XvPortID port, 1060 Drawable d, 1061 GC gc, 1062 XvImage *image, 1063 int src_x, int src_y, 1064 unsigned int src_w, unsigned int src_h, 1065 int dest_x, int dest_y, 1066 unsigned int dest_w, unsigned int dest_h) 1067{ 1068 XExtDisplayInfo *info = xv_find_display(dpy); 1069 xvPutImageReq *req; 1070 unsigned int len; 1071 1072 XvCheckExtension(dpy, info, XvBadExtension); 1073 1074 LockDisplay(dpy); 1075 1076 FlushGC(dpy, gc); 1077 1078 XvGetReq(PutImage, req); 1079 1080 req->port = (CARD32) port; 1081 req->drawable = (CARD32) d; 1082 req->gc = (CARD32) gc->gid; 1083 req->id = (CARD32) image->id; 1084 req->src_x = (INT16) src_x; 1085 req->src_y = (INT16) src_y; 1086 req->src_w = (CARD16) src_w; 1087 req->src_h = (CARD16) src_h; 1088 req->drw_x = (INT16) dest_x; 1089 req->drw_y = (INT16) dest_y; 1090 req->drw_w = (CARD16) dest_w; 1091 req->drw_h = (CARD16) dest_h; 1092 req->width = (CARD16) image->width; 1093 req->height = (CARD16) image->height; 1094 1095 len = ((unsigned int) image->data_size + 3) >> 2; 1096 SetReqLen(req, len, len); 1097 1098 /* Yes it's kindof lame that we are sending the whole thing, 1099 but for video all of it may be needed even if displaying 1100 only a subsection, and I don't want to go through the 1101 trouble of creating subregions to send */ 1102 Data(dpy, (char *) image->data, image->data_size); 1103 1104 UnlockDisplay(dpy); 1105 SyncHandle(); 1106 1107 return Success; 1108} 1109 1110int 1111XvShmPutImage( 1112 Display *dpy, 1113 XvPortID port, 1114 Drawable d, 1115 GC gc, 1116 XvImage *image, 1117 int src_x, int src_y, 1118 unsigned int src_w, unsigned int src_h, 1119 int dest_x, int dest_y, 1120 unsigned int dest_w, unsigned int dest_h, 1121 Bool send_event) 1122{ 1123 XExtDisplayInfo *info = xv_find_display(dpy); 1124 XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata; 1125 xvShmPutImageReq *req; 1126 1127 XvCheckExtension(dpy, info, XvBadExtension); 1128 1129 LockDisplay(dpy); 1130 1131 FlushGC(dpy, gc); 1132 1133 XvGetReq(ShmPutImage, req); 1134 1135 req->port = (CARD32) port; 1136 req->drawable = (CARD32) d; 1137 req->gc = (CARD32) gc->gid; 1138 req->shmseg = (CARD32) shminfo->shmseg; 1139 req->id = (CARD32) image->id; 1140 req->src_x = (INT16) src_x; 1141 req->src_y = (INT16) src_y; 1142 req->src_w = (CARD16) src_w; 1143 req->src_h = (CARD16) src_h; 1144 req->drw_x = (INT16) dest_x; 1145 req->drw_y = (INT16) dest_y; 1146 req->drw_w = (CARD16) dest_w; 1147 req->drw_h = (CARD16) dest_h; 1148 req->offset = (CARD32) (image->data - shminfo->shmaddr); 1149 req->width = (CARD16) image->width; 1150 req->height = (CARD16) image->height; 1151 req->send_event = (CARD8) send_event; 1152 1153 UnlockDisplay(dpy); 1154 SyncHandle(); 1155 1156 return Success; 1157} 1158 1159 1160static Bool 1161xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) 1162{ 1163 XExtDisplayInfo *info = xv_find_display(dpy); 1164 XvEvent *re = (XvEvent *) host; 1165 xvEvent *event = (xvEvent *) wire; 1166 1167 XvCheckExtension(dpy, info, False); 1168 1169 switch ((event->u.u.type & 0x7F) - info->codes->first_event) { 1170 case XvVideoNotify: 1171 re->xvvideo.type = event->u.u.type & 0x7f; 1172 re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 1173 re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); 1174 re->xvvideo.display = dpy; 1175 re->xvvideo.time = event->u.videoNotify.time; 1176 re->xvvideo.reason = event->u.videoNotify.reason; 1177 re->xvvideo.drawable = event->u.videoNotify.drawable; 1178 re->xvvideo.port_id = event->u.videoNotify.port; 1179 break; 1180 case XvPortNotify: 1181 re->xvport.type = event->u.u.type & 0x7f; 1182 re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 1183 re->xvport.send_event = ((event->u.u.type & 0x80) != 0); 1184 re->xvport.display = dpy; 1185 re->xvport.time = event->u.portNotify.time; 1186 re->xvport.port_id = event->u.portNotify.port; 1187 re->xvport.attribute = event->u.portNotify.attribute; 1188 re->xvport.value = event->u.portNotify.value; 1189 break; 1190 default: 1191 return False; 1192 } 1193 1194 return (True); 1195} 1196