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