Xv.c revision dc088bc7
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 else if (rep.num_adaptors != 0) { 196 status = XvBadReply; 197 goto out; 198 } 199 200 /* GET INPUT ADAPTORS */ 201 202 if (rep.num_adaptors == 0) { 203 /* If there are no adaptors, there's nothing more to do. */ 204 status = Success; 205 goto out; 206 } 207 208 u.buffer = buffer; 209 end = buffer + size; 210 211 if ((pas = Xcalloc(rep.num_adaptors, sizeof(XvAdaptorInfo))) == NULL) { 212 status = XvBadAlloc; 213 goto out; 214 } 215 216 /* INIT ADAPTOR FIELDS */ 217 218 pa = pas; 219 for (unsigned int ii = 0; ii < rep.num_adaptors; ii++) { 220 char *name; 221 222 if (u.buffer + sz_xvAdaptorInfo > end) { 223 status = XvBadReply; 224 goto out; 225 } 226 pa->type = (char) u.pa->type; 227 pa->base_id = u.pa->base_id; 228 pa->num_ports = u.pa->num_ports; 229 pa->num_formats = u.pa->num_formats; 230 pa->num_adaptors = rep.num_adaptors - ii; 231 232 /* GET ADAPTOR NAME */ 233 234 size = u.pa->name_size; 235 u.buffer += pad_to_int32(sz_xvAdaptorInfo); 236 237 if (u.buffer + size > end) { 238 status = XvBadReply; 239 goto out; 240 } 241 if ((name = Xmalloc(size + 1)) == NULL) { 242 status = XvBadAlloc; 243 goto out; 244 } 245 (void) strncpy(name, u.string, size); 246 name[size] = '\0'; 247 pa->name = name; 248 249 u.buffer += pad_to_int32(size); 250 251 /* GET FORMATS */ 252 253 if ((pfs = Xcalloc(pa->num_formats, sizeof(XvFormat))) == NULL) { 254 status = XvBadAlloc; 255 goto out; 256 } 257 258 pf = pfs; 259 for (unsigned int jj = 0; jj < pa->num_formats; jj++) { 260 if (u.buffer + sz_xvFormat > end) { 261 Xfree(pfs); 262 status = XvBadReply; 263 goto out; 264 } 265 pf->depth = (char) u.pf->depth; 266 pf->visual_id = u.pf->visual; 267 pf++; 268 269 u.buffer += pad_to_int32(sz_xvFormat); 270 } 271 272 pa->formats = pfs; 273 274 pa++; 275 276 } 277 278 status = Success; 279 280 out: 281 if (status != Success) { 282 XvFreeAdaptorInfo(pas); 283 pas = NULL; 284 } 285 286 *p_nAdaptors = rep.num_adaptors; 287 *p_pAdaptors = pas; 288 289 Xfree(buffer); 290 UnlockDisplay(dpy); 291 SyncHandle(); 292 293 return status; 294} 295 296 297void 298XvFreeAdaptorInfo(XvAdaptorInfo *pAdaptors) 299{ 300 XvAdaptorInfo *pa; 301 302 if (!pAdaptors) 303 return; 304 305 pa = pAdaptors; 306 307 for (unsigned int ii = 0; ii < pAdaptors->num_adaptors; ii++, pa++) { 308 if (pa->name) { 309 Xfree(pa->name); 310 } 311 if (pa->formats) { 312 Xfree(pa->formats); 313 } 314 } 315 316 Xfree(pAdaptors); 317} 318 319int 320XvQueryEncodings( 321 Display *dpy, 322 XvPortID port, 323 unsigned int *p_nEncodings, 324 XvEncodingInfo ** p_pEncodings) 325{ 326 XExtDisplayInfo *info = xv_find_display(dpy); 327 xvQueryEncodingsReq *req; 328 xvQueryEncodingsReply rep; 329 size_t size; 330 XvEncodingInfo *pes = NULL, *pe; 331 char *buffer = NULL; 332 char *end; 333 union { 334 char *buffer; 335 char *string; 336 xvEncodingInfo *pe; 337 } u; 338 int status; 339 340 XvCheckExtension(dpy, info, XvBadExtension); 341 342 LockDisplay(dpy); 343 344 XvGetReq(QueryEncodings, req); 345 req->port = (CARD32) port; 346 347 /* READ THE REPLY */ 348 349 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 350 rep.num_encodings = 0; 351 status = XvBadReply; 352 goto out; 353 } 354 355 size = rep.length << 2; 356 if (size > 0) { 357 if ((buffer = Xmalloc(size)) == NULL) { 358 _XEatDataWords(dpy, rep.length); 359 status = XvBadAlloc; 360 goto out; 361 } 362 _XRead(dpy, buffer, (long) size); 363 } 364 else if (rep.num_encodings != 0) { 365 status = XvBadReply; 366 goto out; 367 } 368 369 /* GET ENCODINGS */ 370 371 if (rep.num_encodings == 0) { 372 /* If there are no encodings, there's nothing more to do. */ 373 status = Success; 374 goto out; 375 } 376 377 u.buffer = buffer; 378 end = buffer + size; 379 380 if ((pes = Xcalloc(rep.num_encodings, sizeof(XvEncodingInfo))) == NULL) { 381 status = XvBadAlloc; 382 goto out; 383 } 384 385 /* INITIALIZE THE ENCODING POINTER */ 386 387 pe = pes; 388 for (unsigned int jj = 0; jj < rep.num_encodings; jj++) { 389 char *name; 390 391 if (u.buffer + sz_xvEncodingInfo > end) { 392 status = XvBadReply; 393 goto out; 394 } 395 pe->encoding_id = u.pe->encoding; 396 pe->width = u.pe->width; 397 pe->height = u.pe->height; 398 pe->rate.numerator = u.pe->rate.numerator; 399 pe->rate.denominator = u.pe->rate.denominator; 400 pe->num_encodings = rep.num_encodings - jj; 401 402 size = u.pe->name_size; 403 u.buffer += pad_to_int32(sz_xvEncodingInfo); 404 405 if (u.buffer + size > end) { 406 status = XvBadReply; 407 goto out; 408 } 409 if ((name = Xmalloc(size + 1)) == NULL) { 410 status = XvBadAlloc; 411 goto out; 412 } 413 strncpy(name, u.string, size); 414 name[size] = '\0'; 415 pe->name = name; 416 pe++; 417 418 u.buffer += pad_to_int32(size); 419 } 420 421 status = Success; 422 423 out: 424 if (status != Success) { 425 XvFreeEncodingInfo(pes); 426 pes = NULL; 427 } 428 429 *p_nEncodings = rep.num_encodings; 430 *p_pEncodings = pes; 431 432 Xfree(buffer); 433 UnlockDisplay(dpy); 434 SyncHandle(); 435 436 return (Success); 437} 438 439void 440XvFreeEncodingInfo(XvEncodingInfo *pEncodings) 441{ 442 XvEncodingInfo *pe; 443 444 if (!pEncodings) 445 return; 446 447 pe = pEncodings; 448 449 for (unsigned long ii = 0; ii < pEncodings->num_encodings; ii++, pe++) { 450 if (pe->name) 451 Xfree(pe->name); 452 } 453 454 Xfree(pEncodings); 455} 456 457int 458XvPutVideo( 459 Display *dpy, 460 XvPortID port, 461 Drawable d, 462 GC gc, 463 int vx, int vy, 464 unsigned int vw, unsigned int vh, 465 int dx, int dy, 466 unsigned int dw, unsigned int dh) 467{ 468 XExtDisplayInfo *info = xv_find_display(dpy); 469 xvPutVideoReq *req; 470 471 XvCheckExtension(dpy, info, XvBadExtension); 472 473 LockDisplay(dpy); 474 475 FlushGC(dpy, gc); 476 477 XvGetReq(PutVideo, req); 478 479 req->port = (CARD32) port; 480 req->drawable = (CARD32) d; 481 req->gc = (CARD32) gc->gid; 482 req->vid_x = (INT16) vx; 483 req->vid_y = (INT16) vy; 484 req->vid_w = (CARD16) vw; 485 req->vid_h = (CARD16) vh; 486 req->drw_x = (INT16) dx; 487 req->drw_y = (INT16) dy; 488 req->drw_w = (CARD16) dw; 489 req->drw_h = (CARD16) dh; 490 491 UnlockDisplay(dpy); 492 SyncHandle(); 493 494 return Success; 495} 496 497int 498XvPutStill( 499 Display *dpy, 500 XvPortID port, 501 Drawable d, 502 GC gc, 503 int vx, int vy, 504 unsigned int vw, unsigned int vh, 505 int dx, int dy, 506 unsigned int dw, unsigned int dh) 507{ 508 XExtDisplayInfo *info = xv_find_display(dpy); 509 xvPutStillReq *req; 510 511 XvCheckExtension(dpy, info, XvBadExtension); 512 513 LockDisplay(dpy); 514 515 FlushGC(dpy, gc); 516 517 XvGetReq(PutStill, req); 518 req->port = (CARD32) port; 519 req->drawable = (CARD32) d; 520 req->gc = (CARD32) gc->gid; 521 req->vid_x = (INT16) vx; 522 req->vid_y = (INT16) vy; 523 req->vid_w = (CARD16) vw; 524 req->vid_h = (CARD16) vh; 525 req->drw_x = (INT16) dx; 526 req->drw_y = (INT16) dy; 527 req->drw_w = (CARD16) dw; 528 req->drw_h = (CARD16) dh; 529 530 UnlockDisplay(dpy); 531 SyncHandle(); 532 533 return Success; 534} 535 536int 537XvGetVideo( 538 Display *dpy, 539 XvPortID port, 540 Drawable d, 541 GC gc, 542 int vx, int vy, 543 unsigned int vw, unsigned int vh, 544 int dx, int dy, 545 unsigned int dw, unsigned int dh) 546{ 547 XExtDisplayInfo *info = xv_find_display(dpy); 548 xvGetVideoReq *req; 549 550 XvCheckExtension(dpy, info, XvBadExtension); 551 552 LockDisplay(dpy); 553 554 FlushGC(dpy, gc); 555 556 XvGetReq(GetVideo, req); 557 req->port = (CARD32) port; 558 req->drawable = (CARD32) d; 559 req->gc = (CARD32) gc->gid; 560 req->vid_x = (INT16) vx; 561 req->vid_y = (INT16) vy; 562 req->vid_w = (CARD16) vw; 563 req->vid_h = (CARD16) vh; 564 req->drw_x = (INT16) dx; 565 req->drw_y = (INT16) dy; 566 req->drw_w = (CARD16) dw; 567 req->drw_h = (CARD16) dh; 568 569 UnlockDisplay(dpy); 570 SyncHandle(); 571 572 return Success; 573} 574 575int 576XvGetStill( 577 Display *dpy, 578 XvPortID port, 579 Drawable d, 580 GC gc, 581 int vx, int vy, 582 unsigned int vw, unsigned int vh, 583 int dx, int dy, 584 unsigned int dw, unsigned int dh) 585{ 586 XExtDisplayInfo *info = xv_find_display(dpy); 587 xvGetStillReq *req; 588 589 XvCheckExtension(dpy, info, XvBadExtension); 590 591 LockDisplay(dpy); 592 593 FlushGC(dpy, gc); 594 595 XvGetReq(GetStill, req); 596 req->port = (CARD32) port; 597 req->drawable = (CARD32) d; 598 req->gc = (CARD32) gc->gid; 599 req->vid_x = (INT16) vx; 600 req->vid_y = (INT16) vy; 601 req->vid_w = (CARD16) vw; 602 req->vid_h = (CARD16) vh; 603 req->drw_x = (INT16) dx; 604 req->drw_y = (INT16) dy; 605 req->drw_w = (CARD16) dw; 606 req->drw_h = (CARD16) dh; 607 608 UnlockDisplay(dpy); 609 SyncHandle(); 610 611 return Success; 612} 613 614int 615XvStopVideo(Display *dpy, XvPortID port, Drawable draw) 616{ 617 XExtDisplayInfo *info = xv_find_display(dpy); 618 xvStopVideoReq *req; 619 620 XvCheckExtension(dpy, info, XvBadExtension); 621 622 LockDisplay(dpy); 623 624 XvGetReq(StopVideo, req); 625 req->port = (CARD32) port; 626 req->drawable = (CARD32) draw; 627 628 UnlockDisplay(dpy); 629 SyncHandle(); 630 631 return Success; 632} 633 634int 635XvGrabPort(Display *dpy, XvPortID port, Time time) 636{ 637 XExtDisplayInfo *info = xv_find_display(dpy); 638 int result; 639 xvGrabPortReply rep; 640 xvGrabPortReq *req; 641 642 XvCheckExtension(dpy, info, XvBadExtension); 643 644 LockDisplay(dpy); 645 646 XvGetReq(GrabPort, req); 647 req->port = (CARD32) port; 648 req->time = (CARD32) time; 649 650 if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == 0) 651 rep.result = GrabSuccess; 652 653 result = rep.result; 654 655 UnlockDisplay(dpy); 656 SyncHandle(); 657 658 return result; 659} 660 661int 662XvUngrabPort(Display *dpy, XvPortID port, Time time) 663{ 664 XExtDisplayInfo *info = xv_find_display(dpy); 665 xvUngrabPortReq *req; 666 667 XvCheckExtension(dpy, info, XvBadExtension); 668 669 LockDisplay(dpy); 670 671 XvGetReq(UngrabPort, req); 672 req->port = (CARD32) port; 673 req->time = (CARD32) time; 674 675 UnlockDisplay(dpy); 676 SyncHandle(); 677 678 return Success; 679} 680 681int 682XvSelectVideoNotify(Display *dpy, Drawable drawable, Bool onoff) 683{ 684 XExtDisplayInfo *info = xv_find_display(dpy); 685 xvSelectVideoNotifyReq *req; 686 687 XvCheckExtension(dpy, info, XvBadExtension); 688 689 LockDisplay(dpy); 690 691 XvGetReq(SelectVideoNotify, req); 692 req->drawable = (CARD32) drawable; 693 req->onoff = (BOOL) onoff; 694 695 UnlockDisplay(dpy); 696 SyncHandle(); 697 698 return Success; 699} 700 701int 702XvSelectPortNotify(Display *dpy, XvPortID port, Bool onoff) 703{ 704 XExtDisplayInfo *info = xv_find_display(dpy); 705 xvSelectPortNotifyReq *req; 706 707 XvCheckExtension(dpy, info, XvBadExtension); 708 709 LockDisplay(dpy); 710 711 XvGetReq(SelectPortNotify, req); 712 req->port = (CARD32) port; 713 req->onoff = (BOOL) onoff; 714 715 UnlockDisplay(dpy); 716 SyncHandle(); 717 718 return Success; 719} 720 721int 722XvSetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int value) 723{ 724 XExtDisplayInfo *info = xv_find_display(dpy); 725 xvSetPortAttributeReq *req; 726 727 XvCheckExtension(dpy, info, XvBadExtension); 728 729 LockDisplay(dpy); 730 731 XvGetReq(SetPortAttribute, req); 732 req->port = (CARD32) port; 733 req->attribute = (CARD32) attribute; 734 req->value = value; 735 736 UnlockDisplay(dpy); 737 SyncHandle(); 738 739 return (Success); 740} 741 742int 743XvGetPortAttribute(Display *dpy, XvPortID port, Atom attribute, int *p_value) 744{ 745 XExtDisplayInfo *info = xv_find_display(dpy); 746 xvGetPortAttributeReq *req; 747 xvGetPortAttributeReply rep; 748 int status; 749 750 XvCheckExtension(dpy, info, XvBadExtension); 751 752 LockDisplay(dpy); 753 754 XvGetReq(GetPortAttribute, req); 755 req->port = (CARD32) port; 756 req->attribute = (CARD32) attribute; 757 758 /* READ THE REPLY */ 759 760 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 761 status = XvBadReply; 762 } 763 else { 764 *p_value = rep.value; 765 status = Success; 766 } 767 768 UnlockDisplay(dpy); 769 SyncHandle(); 770 771 return status; 772} 773 774int 775XvQueryBestSize( 776 Display *dpy, 777 XvPortID port, 778 Bool motion, 779 unsigned int vid_w, 780 unsigned int vid_h, 781 unsigned int drw_w, 782 unsigned int drw_h, 783 unsigned int *p_actual_width, 784 unsigned int *p_actual_height) 785{ 786 XExtDisplayInfo *info = xv_find_display(dpy); 787 xvQueryBestSizeReq *req; 788 xvQueryBestSizeReply rep; 789 int status; 790 791 XvCheckExtension(dpy, info, XvBadExtension); 792 793 LockDisplay(dpy); 794 795 XvGetReq(QueryBestSize, req); 796 req->port = (CARD32) port; 797 req->motion = (CARD8) motion; 798 req->vid_w = (CARD16) vid_w; 799 req->vid_h = (CARD16) vid_h; 800 req->drw_w = (CARD16) drw_w; 801 req->drw_h = (CARD16) drw_h; 802 803 /* READ THE REPLY */ 804 805 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 806 status = XvBadReply; 807 } 808 else { 809 *p_actual_width = rep.actual_width; 810 *p_actual_height = rep.actual_height; 811 status = Success; 812 } 813 814 UnlockDisplay(dpy); 815 SyncHandle(); 816 817 return status; 818} 819 820 821XvAttribute * 822XvQueryPortAttributes(Display *dpy, XvPortID port, int *num) 823{ 824 XExtDisplayInfo *info = xv_find_display(dpy); 825 xvQueryPortAttributesReq *req; 826 xvQueryPortAttributesReply rep; 827 XvAttribute *ret = NULL; 828 829 *num = 0; 830 831 XvCheckExtension(dpy, info, NULL); 832 833 LockDisplay(dpy); 834 835 XvGetReq(QueryPortAttributes, req); 836 req->port = (CARD32) port; 837 838 /* READ THE REPLY */ 839 840 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 841 goto out; 842 } 843 844 /* 845 * X server sends data packed as: 846 * attribute1, name1, attribute2, name2, ... 847 * We allocate a single buffer large enough to hold them all and 848 * then de-interleave the data so we return it to clients as: 849 * attribute1, attribute2, ..., name1, name2, ... 850 * so that clients may refer to attributes as a simple array of 851 * structs: attributes[0], attributes[1], ... 852 * and free it as a single/simple buffer. 853 */ 854 855 if (rep.num_attributes) { 856 /* limit each part to no more than one half the max size */ 857 if ((rep.num_attributes < ((INT_MAX / 2) / sizeof(XvAttribute))) && 858 (rep.text_size < (INT_MAX / 2) - 1)) { 859 unsigned long size; 860 861 size = (rep.num_attributes * sizeof(XvAttribute)) + 862 rep.text_size + 1; 863 ret = Xmalloc(size); 864 } 865 866 if (ret != NULL) { 867 char *marker = (char *) (&ret[rep.num_attributes]); 868 xvAttributeInfo Info; 869 870 /* keep track of remaining room for text strings */ 871 unsigned long size = rep.text_size; 872 873 for (unsigned int i = 0; i < rep.num_attributes; i++) { 874 _XRead(dpy, (char *) (&Info), sz_xvAttributeInfo); 875 ret[i].flags = (int) Info.flags; 876 ret[i].min_value = Info.min; 877 ret[i].max_value = Info.max; 878 ret[i].name = marker; 879 if (Info.size <= size) { 880 _XRead(dpy, marker, Info.size); 881 marker += Info.size; 882 size -= Info.size; 883 } 884 (*num)++; 885 } 886 887 /* ensure final string is nil-terminated to avoid exposure of 888 uninitialized memory */ 889 *marker = '\0'; 890 } 891 else 892 _XEatDataWords(dpy, rep.length); 893 } 894 895 out: 896 UnlockDisplay(dpy); 897 SyncHandle(); 898 899 return ret; 900} 901 902XvImageFormatValues * 903XvListImageFormats(Display *dpy, XvPortID port, int *num) 904{ 905 XExtDisplayInfo *info = xv_find_display(dpy); 906 xvListImageFormatsReq *req; 907 xvListImageFormatsReply rep; 908 XvImageFormatValues *ret = NULL; 909 910 *num = 0; 911 912 XvCheckExtension(dpy, info, NULL); 913 914 LockDisplay(dpy); 915 916 XvGetReq(ListImageFormats, req); 917 req->port = (CARD32) port; 918 919 /* READ THE REPLY */ 920 921 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == 0) { 922 goto out; 923 } 924 925 if (rep.num_formats) { 926 if (rep.num_formats < (INT_MAX / sizeof(XvImageFormatValues))) 927 ret = Xcalloc(rep.num_formats, sizeof(XvImageFormatValues)); 928 929 if (ret != NULL) { 930 for (unsigned int i = 0; i < rep.num_formats; i++) { 931 xvImageFormatInfo Info; 932 933 _XRead(dpy, (char *) (&Info), sz_xvImageFormatInfo); 934 ret[i].id = (int) Info.id; 935 ret[i].type = Info.type; 936 ret[i].byte_order = Info.byte_order; 937 memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16); 938 ret[i].bits_per_pixel = Info.bpp; 939 ret[i].format = Info.format; 940 ret[i].num_planes = Info.num_planes; 941 ret[i].depth = Info.depth; 942 ret[i].red_mask = Info.red_mask; 943 ret[i].green_mask = Info.green_mask; 944 ret[i].blue_mask = Info.blue_mask; 945 ret[i].y_sample_bits = Info.y_sample_bits; 946 ret[i].u_sample_bits = Info.u_sample_bits; 947 ret[i].v_sample_bits = Info.v_sample_bits; 948 ret[i].horz_y_period = Info.horz_y_period; 949 ret[i].horz_u_period = Info.horz_u_period; 950 ret[i].horz_v_period = Info.horz_v_period; 951 ret[i].vert_y_period = Info.vert_y_period; 952 ret[i].vert_u_period = Info.vert_u_period; 953 ret[i].vert_v_period = Info.vert_v_period; 954 memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32); 955 ret[i].scanline_order = Info.scanline_order; 956 (*num)++; 957 } 958 } 959 else 960 _XEatDataWords(dpy, rep.length); 961 } 962 963 out: 964 UnlockDisplay(dpy); 965 SyncHandle(); 966 967 return ret; 968} 969 970XvImage * 971XvCreateImage( 972 Display *dpy, 973 XvPortID port, 974 int id, 975 char *data, 976 int width, 977 int height) 978{ 979 XExtDisplayInfo *info = xv_find_display(dpy); 980 xvQueryImageAttributesReq *req; 981 xvQueryImageAttributesReply rep; 982 XvImage *ret = NULL; 983 984 XvCheckExtension(dpy, info, NULL); 985 986 LockDisplay(dpy); 987 988 XvGetReq(QueryImageAttributes, req); 989 req->id = (CARD32) id; 990 req->port = (CARD32) port; 991 req->width = (CARD16) width; 992 req->height = (CARD16) height; 993 994 /* READ THE REPLY */ 995 996 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 997 goto out; 998 } 999 1000 if (rep.num_planes < ((INT_MAX >> 3) - sizeof(XvImage))) 1001 ret = Xmalloc(sizeof(XvImage) + (rep.num_planes << 3)); 1002 1003 if (ret != NULL) { 1004 ret->id = id; 1005 ret->width = rep.width; 1006 ret->height = rep.height; 1007 ret->data_size = (int) rep.data_size; 1008 ret->num_planes = (int) rep.num_planes; 1009 ret->pitches = (int *) (&ret[1]); 1010 ret->offsets = ret->pitches + rep.num_planes; 1011 ret->data = data; 1012 ret->obdata = NULL; 1013 _XRead(dpy, (char *) (ret->pitches), rep.num_planes << 2); 1014 _XRead(dpy, (char *) (ret->offsets), rep.num_planes << 2); 1015 } 1016 else 1017 _XEatDataWords(dpy, rep.length); 1018 1019 out: 1020 UnlockDisplay(dpy); 1021 SyncHandle(); 1022 1023 return ret; 1024} 1025 1026XvImage * 1027XvShmCreateImage( 1028 Display *dpy, 1029 XvPortID port, 1030 int id, 1031 char *data, 1032 int width, 1033 int height, 1034 XShmSegmentInfo *shminfo) 1035{ 1036 XvImage *ret; 1037 1038 ret = XvCreateImage(dpy, port, id, data, width, height); 1039 1040 if (ret) 1041 ret->obdata = (XPointer) shminfo; 1042 1043 return ret; 1044} 1045 1046int 1047XvPutImage( 1048 Display *dpy, 1049 XvPortID port, 1050 Drawable d, 1051 GC gc, 1052 XvImage *image, 1053 int src_x, int src_y, 1054 unsigned int src_w, unsigned int src_h, 1055 int dest_x, int dest_y, 1056 unsigned int dest_w, unsigned int dest_h) 1057{ 1058 XExtDisplayInfo *info = xv_find_display(dpy); 1059 xvPutImageReq *req; 1060 unsigned int len; 1061 1062 XvCheckExtension(dpy, info, XvBadExtension); 1063 1064 LockDisplay(dpy); 1065 1066 FlushGC(dpy, gc); 1067 1068 XvGetReq(PutImage, req); 1069 1070 req->port = (CARD32) port; 1071 req->drawable = (CARD32) d; 1072 req->gc = (CARD32) gc->gid; 1073 req->id = (CARD32) image->id; 1074 req->src_x = (INT16) src_x; 1075 req->src_y = (INT16) src_y; 1076 req->src_w = (CARD16) src_w; 1077 req->src_h = (CARD16) src_h; 1078 req->drw_x = (INT16) dest_x; 1079 req->drw_y = (INT16) dest_y; 1080 req->drw_w = (CARD16) dest_w; 1081 req->drw_h = (CARD16) dest_h; 1082 req->width = (CARD16) image->width; 1083 req->height = (CARD16) image->height; 1084 1085 len = ((unsigned int) image->data_size + 3) >> 2; 1086 SetReqLen(req, len, len); 1087 1088 /* Yes it's kindof lame that we are sending the whole thing, 1089 but for video all of it may be needed even if displaying 1090 only a subsection, and I don't want to go through the 1091 trouble of creating subregions to send */ 1092 Data(dpy, (char *) image->data, image->data_size); 1093 1094 UnlockDisplay(dpy); 1095 SyncHandle(); 1096 1097 return Success; 1098} 1099 1100int 1101XvShmPutImage( 1102 Display *dpy, 1103 XvPortID port, 1104 Drawable d, 1105 GC gc, 1106 XvImage *image, 1107 int src_x, int src_y, 1108 unsigned int src_w, unsigned int src_h, 1109 int dest_x, int dest_y, 1110 unsigned int dest_w, unsigned int dest_h, 1111 Bool send_event) 1112{ 1113 XExtDisplayInfo *info = xv_find_display(dpy); 1114 XShmSegmentInfo *shminfo = (XShmSegmentInfo *) image->obdata; 1115 xvShmPutImageReq *req; 1116 1117 XvCheckExtension(dpy, info, XvBadExtension); 1118 1119 LockDisplay(dpy); 1120 1121 FlushGC(dpy, gc); 1122 1123 XvGetReq(ShmPutImage, req); 1124 1125 req->port = (CARD32) port; 1126 req->drawable = (CARD32) d; 1127 req->gc = (CARD32) gc->gid; 1128 req->shmseg = (CARD32) shminfo->shmseg; 1129 req->id = (CARD32) image->id; 1130 req->src_x = (INT16) src_x; 1131 req->src_y = (INT16) src_y; 1132 req->src_w = (CARD16) src_w; 1133 req->src_h = (CARD16) src_h; 1134 req->drw_x = (INT16) dest_x; 1135 req->drw_y = (INT16) dest_y; 1136 req->drw_w = (CARD16) dest_w; 1137 req->drw_h = (CARD16) dest_h; 1138 req->offset = (CARD32) (image->data - shminfo->shmaddr); 1139 req->width = (CARD16) image->width; 1140 req->height = (CARD16) image->height; 1141 req->send_event = (CARD8) send_event; 1142 1143 UnlockDisplay(dpy); 1144 SyncHandle(); 1145 1146 return Success; 1147} 1148 1149 1150static Bool 1151xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) 1152{ 1153 XExtDisplayInfo *info = xv_find_display(dpy); 1154 XvEvent *re = (XvEvent *) host; 1155 xvEvent *event = (xvEvent *) wire; 1156 1157 XvCheckExtension(dpy, info, False); 1158 1159 switch ((event->u.u.type & 0x7F) - info->codes->first_event) { 1160 case XvVideoNotify: 1161 re->xvvideo.type = event->u.u.type & 0x7f; 1162 re->xvvideo.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 1163 re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); 1164 re->xvvideo.display = dpy; 1165 re->xvvideo.time = event->u.videoNotify.time; 1166 re->xvvideo.reason = event->u.videoNotify.reason; 1167 re->xvvideo.drawable = event->u.videoNotify.drawable; 1168 re->xvvideo.port_id = event->u.videoNotify.port; 1169 break; 1170 case XvPortNotify: 1171 re->xvport.type = event->u.u.type & 0x7f; 1172 re->xvport.serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 1173 re->xvport.send_event = ((event->u.u.type & 0x80) != 0); 1174 re->xvport.display = dpy; 1175 re->xvport.time = event->u.portNotify.time; 1176 re->xvport.port_id = event->u.portNotify.port; 1177 re->xvport.attribute = event->u.portNotify.attribute; 1178 re->xvport.value = event->u.portNotify.value; 1179 break; 1180 default: 1181 return False; 1182 } 1183 1184 return (True); 1185} 1186