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