vmwgfx_overlay.c revision 22f7e8e5
1/* 2 * Copyright 2007-2011 by VMware, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the copyright holder(s) 23 * and author(s) shall not be used in advertising or otherwise to promote 24 * the sale, use or other dealings in this Software without prior written 25 * authorization from the copyright holder(s) and author(s). 26 * 27 */ 28 29/* 30 * vmwarevideo.c -- 31 * 32 * Xv extension support. 33 * See http://www.xfree86.org/current/DESIGN16.html 34 * 35 */ 36 37 38#include "xf86xv.h" 39#include "fourcc.h" 40#define debug_printf(...) 41 42/* 43 * We can't incude svga_types.h due to conflicting types for Bool. 44 */ 45typedef int64_t int64; 46typedef uint64_t uint64; 47 48typedef int32_t int32; 49typedef uint32_t uint32; 50 51typedef int16_t int16; 52typedef uint16_t uint16; 53 54typedef int8_t int8; 55typedef uint8_t uint8; 56 57#include "../src/svga_reg.h" 58#include "../src/svga_escape.h" 59#include "../src/svga_overlay.h" 60 61#include <X11/extensions/Xv.h> 62 63#include "xf86drm.h" 64#include "vmwgfx_drm.h" 65#include "vmwgfx_drmi.h" 66#include "vmwgfx_driver.h" 67#include "vmwgfx_hosted.h" 68 69#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 70 71/* 72 * Number of videos that can be played simultaneously 73 */ 74#define VMWARE_VID_NUM_PORTS 1 75 76/* 77 * Using a dark shade as the default colorKey 78 */ 79#define VMWARE_VIDEO_COLORKEY 0x100701 80 81/* 82 * Maximum dimensions 83 */ 84#define VMWARE_VID_MAX_WIDTH 2048 85#define VMWARE_VID_MAX_HEIGHT 2048 86 87#define VMWARE_VID_NUM_ENCODINGS 1 88static XF86VideoEncodingRec vmwareVideoEncodings[] = 89{ 90 { 91 0, 92 "XV_IMAGE", 93 VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, 94 {1, 1} 95 } 96}; 97 98#define VMWARE_VID_NUM_FORMATS 2 99static XF86VideoFormatRec vmwareVideoFormats[] = 100{ 101 { 16, TrueColor}, 102 { 24, TrueColor} 103}; 104 105#define VMWARE_VID_NUM_IMAGES 3 106static XF86ImageRec vmwareVideoImages[] = 107{ 108 XVIMAGE_YV12, 109 XVIMAGE_YUY2, 110 XVIMAGE_UYVY 111}; 112 113#define VMWARE_VID_NUM_ATTRIBUTES 2 114static XF86AttributeRec vmwareVideoAttributes[] = 115{ 116 { 117 XvGettable | XvSettable, 118 0x000000, 119 0xffffff, 120 "XV_COLORKEY" 121 }, 122 { 123 XvGettable | XvSettable, 124 0, 125 1, 126 "XV_AUTOPAINT_COLORKEY" 127 } 128}; 129 130/* 131 * Video frames are stored in a circular list of buffers. 132 * Must be power or two, See vmw_video_port_play. 133 */ 134#define VMWARE_VID_NUM_BUFFERS 1 135 136/* 137 * Defines the structure used to hold and pass video data to the host 138 */ 139struct vmw_video_buffer 140{ 141 int size; 142 void *data; 143 struct vmwgfx_dmabuf *buf; 144}; 145 146 147/** 148 * Structure representing a single video stream, aka port. 149 * 150 * Ports maps one to one to a SVGA stream. Port is just 151 * what Xv calls a SVGA stream. 152 */ 153struct vmwgfx_overlay_port 154{ 155 /* 156 * Function prototype same as XvPutImage. 157 * 158 * This is either set to vmw_video_port_init or vmw_video_port_play. 159 * At init this function is set to port_init. In port_init we set it 160 * to port_play and call it, after initializing the struct. 161 */ 162 int (*play)(ScrnInfoPtr, struct vmwgfx_overlay_port *, 163 short, short, short, short, short, 164 short, short, short, int, unsigned char*, 165 short, short, RegionPtr); 166 167 /* values to go into the SVGAOverlayUnit */ 168 uint32 streamId; 169 uint32 colorKey; 170 uint32 flags; 171 172 /* round robin of buffers */ 173 unsigned currBuf; 174 struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS]; 175 176 /* properties that applies to all buffers */ 177 int size; 178 int pitches[3]; 179 int offsets[3]; 180 181 /* things for X */ 182 RegionRec clipBoxes; 183 Bool isAutoPaintColorkey; 184 int drm_fd; 185}; 186 187/* 188 * Callback functions exported to Xv, prefixed with vmw_xv_*. 189 */ 190static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, 191 short drw_x, short drw_y, short src_w, short src_h, 192 short drw_w, short drw_h, int image, 193 unsigned char *buf, short width, short height, 194 Bool sync, RegionPtr clipBoxes, pointer data, 195 DrawablePtr dst); 196static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); 197static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, 198 unsigned short *width, 199 unsigned short *height, int *pitches, 200 int *offsets); 201static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, 202 INT32 value, pointer data); 203static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, 204 INT32 *value, pointer data); 205static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, 206 short vid_w, short vid_h, short drw_w, 207 short drw_h, unsigned int *p_w, 208 unsigned int *p_h, pointer data); 209 210 211/* 212 * Local functions. 213 */ 214static int vmw_video_port_init(ScrnInfoPtr pScrn, 215 struct vmwgfx_overlay_port *port, 216 short src_x, short src_y, short drw_x, 217 short drw_y, short src_w, short src_h, 218 short drw_w, short drw_h, int format, 219 unsigned char *buf, short width, 220 short height, RegionPtr clipBoxes); 221static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, 222 short src_x, short src_y, short drw_x, 223 short drw_y, short src_w, short src_h, 224 short drw_w, short drw_h, int format, 225 unsigned char *buf, short width, 226 short height, RegionPtr clipBoxes); 227static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port); 228 229static int vmw_video_buffer_alloc(int drm_fd, int size, 230 struct vmw_video_buffer *out); 231static int vmw_video_buffer_free(struct vmw_video_buffer *out); 232 233 234static struct vmwgfx_overlay_port * 235vmwgfx_overlay_port_create(int drm_fd, ScreenPtr pScreen) 236{ 237 struct vmwgfx_overlay_port *port = calloc(1, sizeof(*port)); 238 239 if (!port) 240 return NULL; 241 242 port->drm_fd = drm_fd; 243 port->play = vmw_video_port_init; 244 port->flags = SVGA_VIDEO_FLAG_COLORKEY; 245 port->colorKey = VMWARE_VIDEO_COLORKEY; 246 port->isAutoPaintColorkey = TRUE; 247 return port; 248} 249 250void 251vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) 252{ 253 if (free_ports) { 254 int i; 255 256 for(i=0; i<adaptor->nPorts; ++i) { 257 free(adaptor->pPortPrivates[i].ptr); 258 } 259 } 260 261 free(adaptor->pPortPrivates); 262 xf86XVFreeVideoAdaptorRec(adaptor); 263} 264 265/* 266 *----------------------------------------------------------------------------- 267 * 268 * vmw_video_init_adaptor -- 269 * 270 * Initializes a XF86VideoAdaptor structure with the capabilities and 271 * functions supported by this video driver. 272 * 273 * Results: 274 * On success initialized XF86VideoAdaptor struct or NULL on error 275 * 276 * Side effects: 277 * None. 278 * 279 *----------------------------------------------------------------------------- 280 */ 281 282XF86VideoAdaptorPtr 283vmw_video_init_adaptor(ScrnInfoPtr pScrn) 284{ 285 XF86VideoAdaptorPtr adaptor; 286 modesettingPtr ms = modesettingPTR(pScrn); 287 int i; 288 DevUnion *dev_unions; 289 uint32_t ntot, nfree; 290 291 if (vmwgfx_is_hosted(ms->hdriver)) 292 return NULL; 293 294 if (vmwgfx_num_streams(ms->fd, &ntot, &nfree) != 0) { 295 debug_printf("No stream ioctl support\n"); 296 return NULL; 297 } 298 if (nfree == 0) { 299 debug_printf("No free streams\n"); 300 return NULL; 301 } 302 adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); 303 dev_unions = calloc(VMWARE_VID_NUM_PORTS, sizeof(DevUnion)); 304 if (adaptor == NULL || dev_unions == NULL) { 305 xf86XVFreeVideoAdaptorRec(adaptor); 306 free(dev_unions); 307 return NULL; 308 } 309 310 adaptor->type = XvInputMask | XvImageMask | XvWindowMask; 311 312 /** 313 * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the 314 * crtc/output based modesetting, the viewport is not updated on 315 * RandR modeswitches. Hence the video may incorrectly be clipped away. 316 * The correct approach, (if needed) would be to clip against the 317 * scanout area union of all active crtcs. Revisit if needed. 318 */ 319 320 adaptor->flags = VIDEO_OVERLAID_IMAGES; 321 adaptor->name = "VMware Overlay Video Engine"; 322 adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; 323 adaptor->pEncodings = vmwareVideoEncodings; 324 adaptor->nFormats = VMWARE_VID_NUM_FORMATS; 325 adaptor->pFormats = vmwareVideoFormats; 326 adaptor->nPorts = VMWARE_VID_NUM_PORTS; 327 adaptor->pPortPrivates = dev_unions; 328 329 for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { 330 struct vmwgfx_overlay_port *priv = 331 vmwgfx_overlay_port_create(ms->fd, pScrn->pScreen); 332 333 adaptor->pPortPrivates[i].ptr = (pointer) priv; 334 } 335 336 adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; 337 adaptor->pAttributes = vmwareVideoAttributes; 338 adaptor->nImages = VMWARE_VID_NUM_IMAGES; 339 adaptor->pImages = vmwareVideoImages; 340 341 adaptor->PutVideo = NULL; 342 adaptor->PutStill = NULL; 343 adaptor->GetVideo = NULL; 344 adaptor->GetStill = NULL; 345 adaptor->StopVideo = vmw_xv_stop_video; 346 adaptor->SetPortAttribute = vmw_xv_set_port_attribute; 347 adaptor->GetPortAttribute = vmw_xv_get_port_attribute; 348 adaptor->QueryBestSize = vmw_xv_query_best_size; 349 adaptor->PutImage = vmw_xv_put_image; 350 adaptor->QueryImageAttributes = vmw_xv_query_image_attributes; 351 352 return adaptor; 353} 354 355 356/* 357 *----------------------------------------------------------------------------- 358 * 359 * vmw_video_port_init -- 360 * 361 * Initializes a video stream in response to the first PutImage() on a 362 * video stream. The process goes as follows: 363 * - Figure out characteristics according to format 364 * - Allocate offscreen memory 365 * - Pass on video to Play() functions 366 * 367 * Results: 368 * Success or XvBadAlloc on failure. 369 * 370 * Side effects: 371 * Video stream is initialized and its first frame sent to the host 372 * (done by VideoPlay() function called at the end) 373 * 374 *----------------------------------------------------------------------------- 375 */ 376 377static int 378vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, 379 short src_x, short src_y, short drw_x, 380 short drw_y, short src_w, short src_h, 381 short drw_w, short drw_h, int format, 382 unsigned char *buf, short width, 383 short height, RegionPtr clipBoxes) 384{ 385 unsigned short w, h; 386 int i, ret; 387 388 debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format); 389 390 ret = vmwgfx_claim_stream(port->drm_fd, &port->streamId); 391 if (ret != 0) 392 return XvBadAlloc; 393 394 w = width; 395 h = height; 396 /* init all the format attributes, used for buffers */ 397 port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, 398 port->pitches, port->offsets); 399 400 if (port->size == -1) { 401 ret = XvBadAlloc; 402 goto out_bad_size; 403 } 404 405 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) { 406 ret = vmw_video_buffer_alloc(port->drm_fd, port->size, &port->bufs[i]); 407 if (ret != Success) 408 goto out_no_buffer; 409 } 410 411 port->currBuf = 0; 412 REGION_NULL(pScrn->pScreen, &port->clipBoxes); 413 port->play = vmw_video_port_play; 414 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, 415 drw_w, drw_h, format, buf, width, height, clipBoxes); 416 417 out_no_buffer: 418 while(i-- != 0) { 419 vmw_video_buffer_free(&port->bufs[i]); 420 } 421 out_bad_size: 422 (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); 423 424 return ret; 425} 426 427 428/* 429 *----------------------------------------------------------------------------- 430 * 431 * vmw_video_port_play -- 432 * 433 * Sends all the attributes associated with the video frame using the 434 * FIFO ESCAPE mechanism to the host. 435 * 436 * Results: 437 * Always returns Success. 438 * 439 * Side effects: 440 * None. 441 * 442 *----------------------------------------------------------------------------- 443 */ 444 445static int 446vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, 447 short src_x, short src_y, short drw_x, 448 short drw_y, short src_w, short src_h, 449 short drw_w, short drw_h, int format, 450 unsigned char *buf, short width, 451 short height, RegionPtr clipBoxes) 452{ 453 struct drm_vmw_control_stream_arg arg; 454 unsigned short w, h; 455 int size; 456 int ret; 457 458 debug_printf("\t%s: enter\n", __func__); 459 460 w = width; 461 h = height; 462 463 /* we don't update the ports size */ 464 size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, 465 port->pitches, port->offsets); 466 467 if (size != port->size) { 468 vmw_xv_stop_video(pScrn, port, TRUE); 469 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, 470 src_h, drw_w, drw_h, format, buf, width, height, 471 clipBoxes); 472 } 473 474 memcpy(port->bufs[port->currBuf].data, buf, port->size); 475 476 memset(&arg, 0, sizeof(arg)); 477 478 arg.stream_id = port->streamId; 479 arg.enabled = TRUE; 480 arg.flags = port->flags; 481 arg.color_key = port->colorKey; 482 arg.handle = port->bufs[port->currBuf].buf->handle; 483 arg.format = format; 484 arg.size = port->size; 485 arg.width = w; 486 arg.height = h; 487 arg.src.x = src_x; 488 arg.src.y = src_y; 489 arg.src.w = src_w; 490 arg.src.h = src_h; 491 arg.dst.x = drw_x; 492 arg.dst.y = drw_y; 493 arg.dst.w = drw_w; 494 arg.dst.h = drw_h; 495 arg.pitch[0] = port->pitches[0]; 496 arg.pitch[1] = port->pitches[1]; 497 arg.pitch[2] = port->pitches[2]; 498 arg.offset = 0; 499 500 /* 501 * Update the clipList and paint the colorkey, if required. 502 */ 503 if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) { 504 REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); 505 if (port->isAutoPaintColorkey) 506 xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); 507 } 508 509 xorg_flush(pScrn->pScreen); 510 ret = drmCommandWrite(port->drm_fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); 511 if (ret) { 512 vmw_video_port_cleanup(pScrn, port); 513 return XvBadAlloc; 514 } 515 516 if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) 517 port->currBuf = 0; 518 519 return Success; 520} 521 522 523/* 524 *----------------------------------------------------------------------------- 525 * 526 * vmw_video_port_cleanup -- 527 * 528 * Frees up all resources (if any) taken by a video stream. 529 * 530 * Results: 531 * None. 532 * 533 * Side effects: 534 * Same as above. 535 * 536 *----------------------------------------------------------------------------- 537 */ 538 539static void 540vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port) 541{ 542 int i; 543 544 debug_printf("\t%s: enter\n", __func__); 545 546 if (port->play == vmw_video_port_init) 547 return; 548 549 port->play = vmw_video_port_init; 550 (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); 551 552 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) { 553 vmw_video_buffer_free(&port->bufs[i]); 554 } 555 556 REGION_UNINIT(pScreen->pScreen, &port->clipBoxes); 557} 558 559 560/* 561 *----------------------------------------------------------------------------- 562 * 563 * vmw_video_buffer_alloc -- 564 * 565 * Allocates and map a kernel buffer to be used as data storage. 566 * 567 * Results: 568 * XvBadAlloc on failure, otherwise Success. 569 * 570 * Side effects: 571 * Calls into the kernel, sets members of out. 572 * 573 *----------------------------------------------------------------------------- 574 */ 575 576static int 577vmw_video_buffer_alloc(int drm_fd, int size, 578 struct vmw_video_buffer *out) 579{ 580 out->buf = vmwgfx_dmabuf_alloc(drm_fd, size); 581 if (!out->buf) 582 return XvBadAlloc; 583 584 out->data = vmwgfx_dmabuf_map(out->buf); 585 if (!out->data) { 586 vmwgfx_dmabuf_destroy(out->buf); 587 out->buf = NULL; 588 return XvBadAlloc; 589 } 590 591 out->size = size; 592 debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size); 593 594 return Success; 595} 596 597 598/* 599 *----------------------------------------------------------------------------- 600 * 601 * vmw_video_buffer_free -- 602 * 603 * Frees and unmaps an allocated kernel buffer. 604 * 605 * Results: 606 * Success. 607 * 608 * Side effects: 609 * Calls into the kernel, sets members of out to 0. 610 * 611 *----------------------------------------------------------------------------- 612 */ 613 614static int 615vmw_video_buffer_free(struct vmw_video_buffer *out) 616{ 617 if (out->size == 0) 618 return Success; 619 620 vmwgfx_dmabuf_unmap(out->buf); 621 vmwgfx_dmabuf_destroy(out->buf); 622 623 out->buf = NULL; 624 out->data = NULL; 625 out->size = 0; 626 627 debug_printf("\t\t%s: freed buffer %p\n", __func__, out); 628 629 return Success; 630} 631 632 633/* 634 *----------------------------------------------------------------------------- 635 * 636 * vmw_xv_put_image -- 637 * 638 * Main video playback function. It copies the passed data which is in 639 * the specified format (e.g. FOURCC_YV12) into the overlay. 640 * 641 * If sync is TRUE the driver should not return from this 642 * function until it is through reading the data from buf. 643 * 644 * Results: 645 * Success or XvBadAlloc on failure 646 * 647 * Side effects: 648 * Video port will be played(initialized if 1st frame) on success 649 * or will fail on error. 650 * 651 *----------------------------------------------------------------------------- 652 */ 653 654static int 655vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, 656 short drw_x, short drw_y, short src_w, short src_h, 657 short drw_w, short drw_h, int format, 658 unsigned char *buf, short width, short height, 659 Bool sync, RegionPtr clipBoxes, pointer data, 660 DrawablePtr dst) 661{ 662 struct vmwgfx_overlay_port *port = data; 663 664 debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, 665 src_x, src_y, src_w, src_h, 666 drw_x, drw_y, drw_w, drw_h, 667 width, height); 668 669 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, 670 drw_w, drw_h, format, buf, width, height, clipBoxes); 671} 672 673 674/* 675 *----------------------------------------------------------------------------- 676 * 677 * vmw_xv_stop_video -- 678 * 679 * Called when we should stop playing video for a particular stream. If 680 * Cleanup is FALSE, the "stop" operation is only temporary, and thus we 681 * don't do anything. If Cleanup is TRUE we kill the video port by 682 * sending a message to the host and freeing up the stream. 683 * 684 * Results: 685 * None. 686 * 687 * Side effects: 688 * See above. 689 * 690 *----------------------------------------------------------------------------- 691 */ 692 693static void 694vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 695{ 696 struct vmwgfx_overlay_port *port = data; 697 698 debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); 699 REGION_EMPTY(pScrn->pScreen, &port->clipBoxes); 700 701 if (!cleanup) 702 return; 703 704 vmw_video_port_cleanup(pScrn, port); 705} 706 707 708/* 709 *----------------------------------------------------------------------------- 710 * 711 * vmw_xv_query_image_attributes -- 712 * 713 * From the spec: This function is called to let the driver specify how data 714 * for a particular image of size width by height should be stored. 715 * Sometimes only the size and corrected width and height are needed. In 716 * that case pitches and offsets are NULL. 717 * 718 * Results: 719 * The size of the memory required for the image, or -1 on error. 720 * 721 * Side effects: 722 * None. 723 * 724 *----------------------------------------------------------------------------- 725 */ 726 727static int 728vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, 729 unsigned short *width, unsigned short *height, 730 int *pitches, int *offsets) 731{ 732 INT32 size, tmp; 733 734 if (*width > VMWARE_VID_MAX_WIDTH) { 735 *width = VMWARE_VID_MAX_WIDTH; 736 } 737 if (*height > VMWARE_VID_MAX_HEIGHT) { 738 *height = VMWARE_VID_MAX_HEIGHT; 739 } 740 741 *width = (*width + 1) & ~1; 742 if (offsets != NULL) { 743 offsets[0] = 0; 744 } 745 746 switch (format) { 747 case FOURCC_YV12: 748 *height = (*height + 1) & ~1; 749 size = (*width + 3) & ~3; 750 if (pitches) { 751 pitches[0] = size; 752 } 753 size *= *height; 754 if (offsets) { 755 offsets[1] = size; 756 } 757 tmp = ((*width >> 1) + 3) & ~3; 758 if (pitches) { 759 pitches[1] = pitches[2] = tmp; 760 } 761 tmp *= (*height >> 1); 762 size += tmp; 763 if (offsets) { 764 offsets[2] = size; 765 } 766 size += tmp; 767 break; 768 case FOURCC_UYVY: 769 case FOURCC_YUY2: 770 size = *width * 2; 771 if (pitches) { 772 pitches[0] = size; 773 } 774 size *= *height; 775 break; 776 default: 777 debug_printf("Query for invalid video format %d\n", format); 778 return -1; 779 } 780 return size; 781} 782 783 784/* 785 *----------------------------------------------------------------------------- 786 * 787 * vmw_xv_set_port_attribute -- 788 * 789 * From the spec: A port may have particular attributes such as colorKey, hue, 790 * saturation, brightness or contrast. Xv clients set these 791 * attribute values by sending attribute strings (Atoms) to the server. 792 * 793 * Results: 794 * Success if the attribute exists and XvBadAlloc otherwise. 795 * 796 * Side effects: 797 * The respective attribute gets the new value. 798 * 799 *----------------------------------------------------------------------------- 800 */ 801 802static int 803vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, 804 INT32 value, pointer data) 805{ 806 struct vmwgfx_overlay_port *port = data; 807 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); 808 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 809 810 if (attribute == xvColorKey) { 811 debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value); 812 port->colorKey = value; 813 } else if (attribute == xvAutoPaint) { 814 debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE"); 815 port->isAutoPaintColorkey = value; 816 } else { 817 return XvBadAlloc; 818 } 819 820 return Success; 821} 822 823 824/* 825 *----------------------------------------------------------------------------- 826 * 827 * vmw_xv_get_port_attribute -- 828 * 829 * From the spec: A port may have particular attributes such as hue, 830 * saturation, brightness or contrast. Xv clients get these 831 * attribute values by sending attribute strings (Atoms) to the server 832 * 833 * Results: 834 * Success if the attribute exists and XvBadAlloc otherwise. 835 * 836 * Side effects: 837 * "value" contains the requested attribute on success. 838 * 839 *----------------------------------------------------------------------------- 840 */ 841 842static int 843vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, 844 INT32 *value, pointer data) 845{ 846 struct vmwgfx_overlay_port *port = data; 847 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); 848 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 849 850 if (attribute == xvColorKey) { 851 *value = port->colorKey; 852 } else if (attribute == xvAutoPaint) { 853 *value = port->isAutoPaintColorkey; 854 } else { 855 return XvBadAlloc; 856 } 857 858 return Success; 859} 860 861 862/* 863 *----------------------------------------------------------------------------- 864 * 865 * vmw_xv_query_best_size -- 866 * 867 * From the spec: QueryBestSize provides the client with a way to query what 868 * the destination dimensions would end up being if they were to request 869 * that an area vid_w by vid_h from the video stream be scaled to rectangle 870 * of drw_w by drw_h on the screen. Since it is not expected that all 871 * hardware will be able to get the target dimensions exactly, it is 872 * important that the driver provide this function. 873 * 874 * This function seems to never be called, but to be on the safe side 875 * we apply the same logic that QueryImageAttributes has for width 876 * and height. 877 * 878 * Results: 879 * None. 880 * 881 * Side effects: 882 * None. 883 * 884 *----------------------------------------------------------------------------- 885 */ 886 887static void 888vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, 889 short vid_w, short vid_h, short drw_w, 890 short drw_h, unsigned int *p_w, 891 unsigned int *p_h, pointer data) 892{ 893 *p_w = (drw_w + 1) & ~1; 894 *p_h = drw_h; 895 896 return; 897} 898