vmwgfx_tex_video.c revision 3bfa90b6
1/* 2 * Copyright 2009-2011 VMWare, Inc. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Author: Thomas Hellstrom <thellstrom@vmware.com> 26 * Author: Zack Rusin <zackr@vmware.com> 27 */ 28 29#include "vmwgfx_driver.h" 30#include "vmwgfx_drmi.h" 31#include "vmwgfx_saa.h" 32 33#include <xf86xv.h> 34#include <X11/extensions/Xv.h> 35#include <fourcc.h> 36#include <xa_tracker.h> 37#include <xa_context.h> 38#include <math.h> 39 40/*XXX get these from pipe's texture limits */ 41#define IMAGE_MAX_WIDTH 2048 42#define IMAGE_MAX_HEIGHT 2048 43 44#define RES_720P_X 1280 45#define RES_720P_Y 720 46 47 48#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 49 50/* 51 * ITU-R BT.601, BT.709 transfer matrices. 52 * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] 53 * and [Pb, Pr] components are in the range [-0.5, 0.5]. 54 * 55 * The matrices are transposed to fit the xa conversion matrix format. 56 */ 57 58static const float bt_601[] = { 59 1.f, 1.f, 1.f, 0.f, 60 0.f, -0.344136f, 1.772f, 0.f, 61 1.402f, -0.714136f, 0.f, 0.f 62}; 63 64static const float bt_709[] = { 65 1.f, 1.f, 1.f, 0.f, 66 0.f, -0.187324f, 1.8556f, 0.f, 67 1.5748f, -0.468124f, 0.f, 0.f 68}; 69 70static Atom xvBrightness, xvContrast, xvSaturation, xvHue; 71 72#define NUM_TEXTURED_ATTRIBUTES 4 73static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { 74 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, 75 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, 76 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, 77 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"} 78}; 79 80#define NUM_FORMATS 3 81static XF86VideoFormatRec Formats[NUM_FORMATS] = { 82 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 83}; 84 85static XF86VideoEncodingRec DummyEncoding[1] = { 86 { 87 0, 88 "XV_IMAGE", 89 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 90 {1, 1} 91 } 92}; 93 94#define NUM_IMAGES 3 95static XF86ImageRec Images[NUM_IMAGES] = { 96 XVIMAGE_UYVY, 97 XVIMAGE_YUY2, 98 XVIMAGE_YV12, 99}; 100 101struct xorg_xv_port_priv { 102 struct xa_tracker *xat; 103 struct xa_context *r; 104 struct xa_fence *fence; 105 106 RegionRec clip; 107 108 int brightness; 109 int contrast; 110 int saturation; 111 int hue; 112 113 int current_set; 114 struct vmwgfx_dmabuf *bounce[2][3]; 115 struct xa_surface *yuv[3]; 116 117 int drm_fd; 118 119 Bool hdtv; 120 float uv_offset; 121 float uv_scale; 122 float y_offset; 123 float y_scale; 124 float rgb_offset; 125 float rgb_scale; 126 float sinhue; 127 float coshue; 128 float cm[16]; 129}; 130 131/* 132 * vmwgfx_update_conversion_matrix - Compute the effective color conversion 133 * matrix. 134 * 135 * Applies yuv- and resulting rgb scales and offsets to compute the correct 136 * color conversion matrix. These scales and offsets are properties of the 137 * video stream and can be adjusted using XV properties as well. 138 */ 139static void 140vmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) 141{ 142 int i; 143 float *cm = priv->cm; 144 static const float *bt; 145 146 bt = (priv->hdtv) ? bt_709 : bt_601; 147 148 memcpy(cm, bt, sizeof(bt_601)); 149 150 /* 151 * Apply hue rotation 152 */ 153 cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8]; 154 cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8]; 155 cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9]; 156 cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9]; 157 cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10]; 158 cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10]; 159 160 /* 161 * Adjust for yuv scales in input and rgb scale in the converted output. 162 */ 163 for(i = 0; i < 3; ++i) { 164 cm[i] *= (priv->y_scale*priv->rgb_scale); 165 cm[i+4] *= (priv->uv_scale*priv->rgb_scale); 166 cm[i+8] *= (priv->uv_scale*priv->rgb_scale); 167 } 168 169 /* 170 * Adjust for yuv offsets in input and rgb offset in the converted output. 171 */ 172 for (i = 0; i < 3; ++i) 173 cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset 174 - priv->rgb_offset*priv->rgb_scale; 175 176 /* 177 * Alpha is 1, unconditionally. 178 */ 179 cm[15] = 1.f; 180} 181 182 183static void 184stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 185{ 186 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 187 int i, j; 188 189 REGION_EMPTY(pScrn->pScreen, &priv->clip); 190 if (shutdown) { 191 192 /* 193 * No need to destroy the xa context or xa tracker since 194 * they are copied from the screen resources. 195 */ 196 197 xa_fence_destroy(priv->fence); 198 priv->fence = NULL; 199 200 for (i=0; i<3; ++i) { 201 if (priv->yuv[i]) { 202 xa_surface_destroy(priv->yuv[i]); 203 priv->yuv[i] = NULL; 204 } 205 for (j=0; j<2; ++j) { 206 if (priv->bounce[j][i]) { 207 vmwgfx_dmabuf_destroy(priv->bounce[j][i]); 208 priv->bounce[0][i] = NULL; 209 } 210 } 211 } 212 } 213} 214 215static int 216set_port_attribute(ScrnInfoPtr pScrn, 217 Atom attribute, INT32 value, pointer data) 218{ 219 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 220 221 if (attribute == xvBrightness) { 222 if ((value < -1000) || (value > 1000)) 223 return BadValue; 224 225 priv->brightness = value; 226 priv->y_offset = -((float) value)/1000.f; 227 228 } else if (attribute == xvContrast) { 229 if ((value < -1000) || (value > 1000)) 230 return BadValue; 231 232 priv->contrast = value; 233 priv->rgb_scale = ((float) value + 1000.f)/1000.f; 234 235 } else if (attribute == xvSaturation) { 236 if ((value < -1000) || (value > 1000)) 237 return BadValue; 238 239 priv->saturation = value; 240 priv->uv_scale = ((float) value + 1000.f)/1000.f; 241 242 } else if (attribute == xvHue) { 243 double hue_angle; 244 245 if ((value < -1000) || (value > 1000)) 246 return BadValue; 247 248 priv->hue = value; 249 hue_angle = (double) value * M_PI / 1000.; 250 priv->sinhue = sin(hue_angle); 251 priv->coshue = cos(hue_angle); 252 253 } else 254 return BadMatch; 255 256 vmwgfx_update_conversion_matrix(priv); 257 return Success; 258} 259 260static int 261get_port_attribute(ScrnInfoPtr pScrn, 262 Atom attribute, INT32 * value, pointer data) 263{ 264 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; 265 266 if (attribute == xvBrightness) 267 *value = priv->brightness; 268 else if (attribute == xvContrast) 269 *value = priv->contrast; 270 else if (attribute == xvSaturation) 271 *value = priv->saturation; 272 else if (attribute == xvHue) 273 *value = priv->hue; 274 else 275 return BadMatch; 276 277 return Success; 278} 279 280static void 281query_best_size(ScrnInfoPtr pScrn, 282 Bool motion, 283 short vid_w, short vid_h, 284 short drw_w, short drw_h, 285 unsigned int *p_w, unsigned int *p_h, pointer data) 286{ 287 if (vid_w > (drw_w << 1)) 288 drw_w = vid_w >> 1; 289 if (vid_h > (drw_h << 1)) 290 drw_h = vid_h >> 1; 291 292 *p_w = drw_w; 293 *p_h = drw_h; 294} 295 296static int 297check_yuv_surfaces(struct xorg_xv_port_priv *priv, int id, 298 int width, int height) 299{ 300 struct xa_surface **yuv = priv->yuv; 301 struct vmwgfx_dmabuf **bounce = priv->bounce[priv->current_set]; 302 int ret = 0; 303 int i; 304 size_t size; 305 306 for (i=0; i<3; ++i) { 307 308 /* 309 * Adjust u,v texture size and DMA buffer to what's required by 310 * the format. 311 */ 312 if (i == 1) { 313 switch(id) { 314 case FOURCC_YV12: 315 height /= 2; 316 /* Fall through */ 317 case FOURCC_YUY2: 318 case FOURCC_UYVY: 319 width /= 2; 320 break; 321 default: 322 break; 323 } 324 } 325 326 if (!yuv[i]) 327 yuv[i] = xa_surface_create(priv->xat, width, height, 8, 328 xa_type_yuv_component, 329 xa_format_unknown, 0); 330 else 331 ret = xa_surface_redefine(yuv[i], width, height, 8, 332 xa_type_yuv_component, 333 xa_format_unknown, 0, 0); 334 if (ret || !yuv[i]) 335 return BadAlloc; 336 337 size = width * height; 338 339 if (bounce[i] && (bounce[i]->size < size || 340 bounce[i]->size > 2*size)) { 341 vmwgfx_dmabuf_destroy(bounce[i]); 342 bounce[i] = NULL; 343 } 344 345 if (!bounce[i]) { 346 bounce[i] = vmwgfx_dmabuf_alloc(priv->drm_fd, size); 347 if (!bounce[i]) 348 return BadAlloc; 349 } 350 } 351 return Success; 352} 353 354static int 355query_image_attributes(ScrnInfoPtr pScrn, 356 int id, 357 unsigned short *w, unsigned short *h, 358 int *pitches, int *offsets) 359{ 360 int size, tmp; 361 362 if (*w > IMAGE_MAX_WIDTH) 363 *w = IMAGE_MAX_WIDTH; 364 if (*h > IMAGE_MAX_HEIGHT) 365 *h = IMAGE_MAX_HEIGHT; 366 367 *w = (*w + 1) & ~1; 368 if (offsets) 369 offsets[0] = 0; 370 371 switch (id) { 372 case FOURCC_YV12: 373 *h = (*h + 1) & ~1; 374 size = (*w + 3) & ~3; 375 if (pitches) { 376 pitches[0] = size; 377 } 378 size *= *h; 379 if (offsets) { 380 offsets[1] = size; 381 } 382 tmp = ((*w >> 1) + 3) & ~3; 383 if (pitches) { 384 pitches[1] = pitches[2] = tmp; 385 } 386 tmp *= (*h >> 1); 387 size += tmp; 388 if (offsets) { 389 offsets[2] = size; 390 } 391 size += tmp; 392 break; 393 case FOURCC_UYVY: 394 case FOURCC_YUY2: 395 default: 396 size = *w << 1; 397 if (pitches) 398 pitches[0] = size; 399 size *= *h; 400 break; 401 } 402 403 return size; 404} 405 406static int 407copy_packed_data(ScrnInfoPtr pScrn, 408 struct xorg_xv_port_priv *port, 409 int id, 410 unsigned char *buf, 411 int left, 412 int top, 413 unsigned short w, unsigned short h) 414{ 415 int i; 416 struct vmwgfx_dmabuf **bounce = port->bounce[port->current_set]; 417 char *ymap, *vmap, *umap; 418 unsigned char y1, y2, u, v; 419 int yidx, uidx, vidx; 420 int y_array_size = w * h; 421 int ret = BadAlloc; 422 423 /* 424 * Here, we could use xa_surface_[map|unmap], but given the size of 425 * the yuv textures, that could stress the xa tracker dma buffer pool, 426 * particularaly with multiple videos rendering simultaneously. 427 * 428 * Instead, cheat and allocate vmwgfx dma buffers directly. 429 */ 430 431 ymap = (char *)vmwgfx_dmabuf_map(bounce[0]); 432 if (!ymap) 433 return BadAlloc; 434 umap = (char *)vmwgfx_dmabuf_map(bounce[1]); 435 if (!umap) 436 goto out_no_umap; 437 vmap = (char *)vmwgfx_dmabuf_map(bounce[2]); 438 if (!vmap) 439 goto out_no_vmap; 440 441 442 yidx = uidx = vidx = 0; 443 444 switch (id) { 445 case FOURCC_YV12: { 446 int pitches[3], offsets[3]; 447 unsigned char *y, *u, *v; 448 query_image_attributes(pScrn, FOURCC_YV12, 449 &w, &h, pitches, offsets); 450 451 y = buf + offsets[0]; 452 v = buf + offsets[1]; 453 u = buf + offsets[2]; 454 memcpy(ymap, y, w*h); 455 memcpy(vmap, v, w*h/4); 456 memcpy(umap, u, w*h/4); 457 break; 458 } 459 case FOURCC_UYVY: 460 for (i = 0; i < y_array_size; i +=2 ) { 461 /* extracting two pixels */ 462 u = buf[0]; 463 y1 = buf[1]; 464 v = buf[2]; 465 y2 = buf[3]; 466 buf += 4; 467 468 ymap[yidx++] = y1; 469 ymap[yidx++] = y2; 470 umap[uidx++] = u; 471 vmap[vidx++] = v; 472 } 473 break; 474 case FOURCC_YUY2: 475 for (i = 0; i < y_array_size; i +=2 ) { 476 /* extracting two pixels */ 477 y1 = buf[0]; 478 u = buf[1]; 479 y2 = buf[2]; 480 v = buf[3]; 481 482 buf += 4; 483 484 ymap[yidx++] = y1; 485 ymap[yidx++] = y2; 486 umap[uidx++] = u; 487 vmap[vidx++] = v; 488 } 489 break; 490 default: 491 ret = BadAlloc; 492 break; 493 } 494 495 ret = Success; 496 vmwgfx_dmabuf_unmap(bounce[2]); 497 out_no_vmap: 498 vmwgfx_dmabuf_unmap(bounce[1]); 499 out_no_umap: 500 vmwgfx_dmabuf_unmap(bounce[0]); 501 502 if (ret == Success) { 503 struct xa_surface *srf; 504 struct vmwgfx_dmabuf *buf; 505 uint32_t handle; 506 unsigned int stride; 507 BoxRec box; 508 RegionRec reg; 509 510 box.x1 = 0; 511 box.x2 = w; 512 box.y1 = 0; 513 box.y2 = h; 514 515 REGION_INIT(pScrn->pScreen, ®, &box, 1); 516 517 for (i=0; i<3; ++i) { 518 srf = port->yuv[i]; 519 buf = bounce[i]; 520 521 if (i == 1) { 522 switch(id) { 523 case FOURCC_YV12: 524 h /= 2; 525 /* Fall through */ 526 case FOURCC_YUY2: 527 case FOURCC_UYVY: 528 w /= 2; 529 break; 530 default: 531 break; 532 } 533 534 box.x1 = 0; 535 box.x2 = w; 536 box.y1 = 0; 537 box.y2 = h; 538 539 REGION_RESET(pScrn->pScreen, ®, &box); 540 } 541 542 if (xa_surface_handle(srf, &handle, &stride) != 0) { 543 ret = BadAlloc; 544 break; 545 } 546 547 if (vmwgfx_dma(0, 0, ®, buf, w, handle, 1) != 0) { 548 ret = BadAlloc; 549 break; 550 } 551 } 552 REGION_UNINIT(pScrn->pScreen, ®); 553 } 554 555 return ret; 556} 557 558 559static int 560display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, 561 RegionPtr dstRegion, 562 int src_x, int src_y, int src_w, int src_h, 563 int dst_x, int dst_y, int dst_w, int dst_h, 564 PixmapPtr pPixmap) 565{ 566 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap); 567 Bool hdtv; 568 RegionRec reg; 569 int ret = BadAlloc; 570 int blit_ret; 571 572 REGION_NULL(pScreen, ®); 573 574 if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) 575 goto out_no_dst; 576 577 hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); 578 if (hdtv != pPriv->hdtv) { 579 pPriv->hdtv = hdtv; 580 vmwgfx_update_conversion_matrix(pPriv); 581 } 582 583#ifdef COMPOSITE 584 585 /* 586 * For redirected windows, we need to fix up the destination coordinates. 587 */ 588 589 REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x, 590 -pPixmap->screen_y); 591 dst_x -= pPixmap->screen_x; 592 dst_y -= pPixmap->screen_y; 593#endif 594 595 /* 596 * Throttle on previous blit. 597 */ 598 599 if (pPriv->fence) { 600 (void) xa_fence_wait(pPriv->fence, 1000000000ULL); 601 xa_fence_destroy(pPriv->fence); 602 pPriv->fence = NULL; 603 } 604 605 DamageRegionAppend(&pPixmap->drawable, dstRegion); 606 607 blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h, 608 dst_x, dst_y, dst_w, dst_h, 609 (struct xa_box *)REGION_RECTS(dstRegion), 610 REGION_NUM_RECTS(dstRegion), 611 pPriv->cm, 612 vpix->hw, pPriv->yuv); 613 614 saa_pixmap_dirty(pPixmap, TRUE, dstRegion); 615 DamageRegionProcessPending(&pPixmap->drawable); 616 ret = Success; 617 618 if (!blit_ret) { 619 ret = Success; 620 pPriv->fence = xa_fence_get(pPriv->r); 621 } else 622 ret = BadAlloc; 623 624 out_no_dst: 625 REGION_UNINIT(pScreen, ®); 626 return ret; 627} 628 629static int 630put_image(ScrnInfoPtr pScrn, 631 short src_x, short src_y, 632 short drw_x, short drw_y, 633 short src_w, short src_h, 634 short drw_w, short drw_h, 635 int id, unsigned char *buf, 636 short width, short height, 637 Bool sync, RegionPtr clipBoxes, pointer data, 638 DrawablePtr pDraw) 639{ 640 struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; 641 ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 642 PixmapPtr pPixmap; 643 INT32 x1, x2, y1, y2; 644 BoxRec dstBox; 645 int ret; 646 647 /* Clip */ 648 x1 = src_x; 649 x2 = src_x + src_w; 650 y1 = src_y; 651 y2 = src_y + src_h; 652 653 dstBox.x1 = drw_x; 654 dstBox.x2 = drw_x + drw_w; 655 dstBox.y1 = drw_y; 656 dstBox.y2 = drw_y + drw_h; 657 658 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 659 width, height)) 660 return Success; 661 662 ret = check_yuv_surfaces(pPriv, id, width, height); 663 if (ret) 664 return ret; 665 666 ret = copy_packed_data(pScrn, pPriv, id, buf, 667 src_x, src_y, width, height); 668 if (ret) 669 return ret; 670 671 if (pDraw->type == DRAWABLE_WINDOW) { 672 pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); 673 } else { 674 pPixmap = (PixmapPtr)pDraw; 675 } 676 677 display_video(pScrn->pScreen, pPriv, id, clipBoxes, 678 src_x, src_y, src_w, src_h, 679 drw_x, drw_y, 680 drw_w, drw_h, pPixmap); 681 682 pPriv->current_set = (pPriv->current_set + 1) & 1; 683 return Success; 684} 685 686static struct xorg_xv_port_priv * 687port_priv_create(struct xa_tracker *xat, struct xa_context *r, 688 int drm_fd) 689{ 690 struct xorg_xv_port_priv *priv = NULL; 691 692 priv = calloc(1, sizeof(struct xorg_xv_port_priv)); 693 694 if (!priv) 695 return NULL; 696 697 priv->r = r; 698 priv->xat = xat; 699 priv->drm_fd = drm_fd; 700 REGION_NULL(pScreen, &priv->clip); 701 priv->hdtv = FALSE; 702 priv->uv_offset = 0.5f; 703 priv->uv_scale = 1.f; 704 priv->y_offset = 0.f; 705 priv->y_scale = 1.f; 706 priv->rgb_offset = 0.f; 707 priv->rgb_scale = 1.f; 708 priv->sinhue = 0.f; 709 priv->coshue = 1.f; 710 711 vmwgfx_update_conversion_matrix(priv); 712 713 return priv; 714} 715 716static void 717vmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) 718{ 719 if (free_ports) { 720 int i; 721 722 for(i=0; i<adaptor->nPorts; ++i) { 723 free(adaptor->pPortPrivates[i].ptr); 724 } 725 } 726 727 free(adaptor->pAttributes); 728 free(adaptor->pPortPrivates); 729 xf86XVFreeVideoAdaptorRec(adaptor); 730} 731 732static XF86VideoAdaptorPtr 733xorg_setup_textured_adapter(ScreenPtr pScreen) 734{ 735 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 736 modesettingPtr ms = modesettingPTR(pScrn); 737 XF86VideoAdaptorPtr adapt; 738 XF86AttributePtr attrs; 739 DevUnion *dev_unions; 740 int nports = 16, i; 741 int nattributes; 742 struct xa_context *xar; 743 744 /* 745 * Use the XA default context since we don't expect the X server 746 * to render from multiple threads. 747 */ 748 749 xar = xa_context_default(ms->xat); 750 nattributes = NUM_TEXTURED_ATTRIBUTES; 751 752 adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); 753 dev_unions = calloc(nports, sizeof(DevUnion)); 754 attrs = calloc(nattributes, sizeof(XF86AttributeRec)); 755 if (adapt == NULL || dev_unions == NULL || attrs == NULL) { 756 free(adapt); 757 free(dev_unions); 758 free(attrs); 759 return NULL; 760 } 761 762 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 763 adapt->flags = 0; 764 adapt->name = "XA G3D Textured Video"; 765 adapt->nEncodings = 1; 766 adapt->pEncodings = DummyEncoding; 767 adapt->nFormats = NUM_FORMATS; 768 adapt->pFormats = Formats; 769 adapt->nPorts = 0; 770 adapt->pPortPrivates = dev_unions; 771 adapt->nAttributes = nattributes; 772 adapt->pAttributes = attrs; 773 memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec)); 774 adapt->nImages = NUM_IMAGES; 775 adapt->pImages = Images; 776 adapt->PutVideo = NULL; 777 adapt->PutStill = NULL; 778 adapt->GetVideo = NULL; 779 adapt->GetStill = NULL; 780 adapt->StopVideo = stop_video; 781 adapt->SetPortAttribute = set_port_attribute; 782 adapt->GetPortAttribute = get_port_attribute; 783 adapt->QueryBestSize = query_best_size; 784 adapt->PutImage = put_image; 785 adapt->QueryImageAttributes = query_image_attributes; 786 787 788 for (i = 0; i < nports; i++) { 789 struct xorg_xv_port_priv *priv = 790 port_priv_create(ms->xat, xar, ms->fd); 791 792 adapt->pPortPrivates[i].ptr = (pointer) (priv); 793 adapt->nPorts++; 794 } 795 796 return adapt; 797} 798 799void 800xorg_xv_init(ScreenPtr pScreen) 801{ 802 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 803 modesettingPtr ms = modesettingPTR(pScrn); 804 XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL; 805 XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL; 806 int num_adaptors; 807 808 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 809 new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); 810 if (new_adaptors == NULL) 811 return; 812 813 memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); 814 adaptors = new_adaptors; 815 816 /* Add the adaptors supported by our hardware. First, set up the atoms 817 * that will be used by both output adaptors. 818 */ 819 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 820 xvContrast = MAKE_ATOM("XV_CONTRAST"); 821 xvSaturation = MAKE_ATOM("XV_SATURATION"); 822 xvHue = MAKE_ATOM("XV_HUE"); 823 824 if (ms->xat) { 825 textured_adapter = xorg_setup_textured_adapter(pScreen); 826 if (textured_adapter) 827 adaptors[num_adaptors++] = textured_adapter; 828 } else { 829 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 830 "No 3D acceleration. Not setting up textured video.\n"); 831 } 832 833 overlay_adaptor = vmw_video_init_adaptor(pScrn); 834 if (overlay_adaptor) 835 adaptors[num_adaptors++] = overlay_adaptor; 836 837 if (num_adaptors) { 838 Bool ret; 839 ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors); 840 if (textured_adapter) 841 vmwgfx_free_textured_adaptor(textured_adapter, !ret); 842 if (overlay_adaptor) 843 vmw_video_free_adaptor(overlay_adaptor, !ret); 844 if (!ret) 845 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 846 "Failed to initialize Xv.\n"); 847 } else { 848 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 849 "Disabling Xv because no adaptors could be initialized.\n"); 850 } 851} 852