sna_video.c revision 42542f5f
1/*************************************************************************** 2 3 Copyright 2000 Intel Corporation. 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 INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 23 THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 **************************************************************************/ 26 27/* 28 * i830_video.c: i830/i845 Xv driver. 29 * 30 * Copyright © 2002 by Alan Hourihane and David Dawes 31 * 32 * Authors: 33 * Alan Hourihane <alanh@tungstengraphics.com> 34 * David Dawes <dawes@xfree86.org> 35 * 36 * Derived from i810 Xv driver: 37 * 38 * Authors of i810 code: 39 * Jonathan Bian <jonathan.bian@intel.com> 40 * Offscreen Images: 41 * Matt Sottek <matthew.j.sottek@intel.com> 42 */ 43 44#ifdef HAVE_CONFIG_H 45#include "config.h" 46#endif 47 48#include <inttypes.h> 49#include <math.h> 50#include <string.h> 51#include <assert.h> 52#include <errno.h> 53 54#include <sys/mman.h> 55 56#include "sna.h" 57#include "sna_reg.h" 58#include "sna_video.h" 59 60#include "intel_options.h" 61 62#include <xf86xv.h> 63 64#ifdef SNA_XVMC 65#define _SNA_XVMC_SERVER_ 66#include "sna_video_hwmc.h" 67#else 68static inline void sna_video_xvmc_setup(struct sna *sna, ScreenPtr ptr) 69{ 70 DBG(("%s: XvMC not compiled in\n", __FUNCTION__)); 71} 72#endif 73 74void sna_video_free_buffers(struct sna_video *video) 75{ 76 unsigned int i; 77 78 for (i = 0; i < ARRAY_SIZE(video->old_buf); i++) { 79 if (video->old_buf[i]) { 80 kgem_bo_destroy(&video->sna->kgem, video->old_buf[i]); 81 video->old_buf[i] = NULL; 82 } 83 } 84 85 if (video->buf) { 86 kgem_bo_destroy(&video->sna->kgem, video->buf); 87 video->buf = NULL; 88 } 89} 90 91struct kgem_bo * 92sna_video_buffer(struct sna_video *video, 93 struct sna_video_frame *frame) 94{ 95 /* Free the current buffer if we're going to have to reallocate */ 96 if (video->buf && __kgem_bo_size(video->buf) < frame->size) 97 sna_video_free_buffers(video); 98 99 if (video->buf && video->buf->scanout) { 100 if (frame->width != video->width || 101 frame->height != video->height || 102 frame->id != video->format) 103 sna_video_free_buffers(video); 104 } 105 106 if (video->buf == NULL) { 107 if (video->tiled) { 108 video->buf = kgem_create_2d(&video->sna->kgem, 109 frame->width, frame->height, 32, 110 I915_TILING_X, CREATE_EXACT); 111 } else { 112 video->buf = kgem_create_linear(&video->sna->kgem, frame->size, 113 CREATE_GTT_MAP); 114 } 115 } 116 117 video->width = frame->width; 118 video->height = frame->height; 119 video->format = frame->id; 120 121 return video->buf; 122} 123 124void sna_video_buffer_fini(struct sna_video *video) 125{ 126 struct kgem_bo *bo; 127 128 bo = video->old_buf[1]; 129 video->old_buf[1] = video->old_buf[0]; 130 video->old_buf[0] = video->buf; 131 video->buf = bo; 132} 133 134bool 135sna_video_clip_helper(struct sna_video *video, 136 struct sna_video_frame *frame, 137 xf86CrtcPtr *crtc_ret, 138 BoxPtr dst, 139 short src_x, short src_y, 140 short drw_x, short drw_y, 141 short src_w, short src_h, 142 short drw_w, short drw_h, 143 RegionPtr reg) 144{ 145 bool ret; 146 RegionRec crtc_region_local; 147 RegionPtr crtc_region = reg; 148 INT32 x1, x2, y1, y2; 149 xf86CrtcPtr crtc; 150 151 x1 = src_x; 152 x2 = src_x + src_w; 153 y1 = src_y; 154 y2 = src_y + src_h; 155 156 dst->x1 = drw_x; 157 dst->x2 = drw_x + drw_w; 158 dst->y1 = drw_y; 159 dst->y2 = drw_y + drw_h; 160 161 /* 162 * For overlay video, compute the relevant CRTC and 163 * clip video to that 164 */ 165 crtc = sna_covering_crtc(video->sna, dst, video->desired_crtc); 166 167 /* For textured video, we don't actually want to clip at all. */ 168 if (crtc && !video->textured) { 169 crtc_region_local.extents = crtc->bounds; 170 crtc_region_local.data = NULL; 171 crtc_region = &crtc_region_local; 172 RegionIntersect(crtc_region, crtc_region, reg); 173 } 174 *crtc_ret = crtc; 175 176 ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, 177 crtc_region, frame->width, frame->height); 178 if (crtc_region != reg) 179 RegionUninit(crtc_region); 180 181 frame->src.x1 = x1 >> 16; 182 frame->src.y1 = y1 >> 16; 183 frame->src.x2 = (x2 + 0xffff) >> 16; 184 frame->src.y2 = (y2 + 0xffff) >> 16; 185 186 frame->image.x1 = frame->src.x1 & ~1; 187 frame->image.x2 = ALIGN(frame->src.x2, 2); 188 if (is_planar_fourcc(frame->id)) { 189 frame->image.y1 = frame->src.y1 & ~1; 190 frame->image.y2 = ALIGN(frame->src.y2, 2); 191 } else { 192 frame->image.y1 = frame->src.y1; 193 frame->image.y2 = frame->src.y2; 194 } 195 196 return ret; 197} 198 199void 200sna_video_frame_init(struct sna_video *video, 201 int id, short width, short height, 202 struct sna_video_frame *frame) 203{ 204 DBG(("%s: id=%d [planar? %d], width=%d, height=%d, align=%d\n", 205 __FUNCTION__, id, is_planar_fourcc(id), width, height, video->alignment)); 206 assert(width && height); 207 208 frame->bo = NULL; 209 frame->id = id; 210 frame->width = width; 211 frame->height = height; 212 frame->rotation = 0; 213} 214 215void 216sna_video_frame_set_rotation(struct sna_video *video, 217 struct sna_video_frame *frame, 218 Rotation rotation) 219{ 220 unsigned width = frame->width; 221 unsigned height = frame->height; 222 unsigned align; 223 224 DBG(("%s: rotation=%d\n", __FUNCTION__, rotation)); 225 frame->rotation = rotation; 226 227 align = video->alignment; 228#if SNA_XVMC 229 /* for i915 xvmc, hw requires 1kb aligned surfaces */ 230 if (frame->id == FOURCC_XVMC && video->sna->kgem.gen < 040 && align < 1024) 231 align = 1024; 232#endif 233 234 /* Determine the desired destination pitch (representing the 235 * chroma's pitch in the planar case). 236 */ 237 if (is_planar_fourcc(frame->id)) { 238 assert((width & 1) == 0); 239 assert((height & 1) == 0); 240 if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 241 frame->pitch[0] = ALIGN((height / 2), align); 242 frame->pitch[1] = ALIGN(height, align); 243 frame->size = width; 244 } else { 245 frame->pitch[0] = ALIGN((width / 2), align); 246 frame->pitch[1] = ALIGN(width, align); 247 frame->size = height; 248 } 249 frame->size *= frame->pitch[0] + frame->pitch[1]; 250 251 if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 252 frame->UBufOffset = (int)frame->pitch[1] * width; 253 frame->VBufOffset = 254 frame->UBufOffset + (int)frame->pitch[0] * width / 2; 255 } else { 256 frame->UBufOffset = (int)frame->pitch[1] * height; 257 frame->VBufOffset = 258 frame->UBufOffset + (int)frame->pitch[0] * height / 2; 259 } 260 } else { 261 switch (frame->id) { 262 case FOURCC_RGB888: 263 if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 264 frame->pitch[0] = ALIGN((height << 2), align); 265 frame->size = (int)frame->pitch[0] * width; 266 } else { 267 frame->pitch[0] = ALIGN((width << 2), align); 268 frame->size = (int)frame->pitch[0] * height; 269 } 270 frame->UBufOffset = frame->VBufOffset = 0; 271 break; 272 case FOURCC_RGB565: 273 if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 274 frame->pitch[0] = ALIGN((height << 1), align); 275 frame->size = (int)frame->pitch[0] * width; 276 } else { 277 frame->pitch[0] = ALIGN((width << 1), align); 278 frame->size = (int)frame->pitch[0] * height; 279 } 280 frame->UBufOffset = frame->VBufOffset = 0; 281 break; 282 283 default: 284 if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { 285 frame->pitch[0] = ALIGN((height << 1), align); 286 frame->size = (int)frame->pitch[0] * width; 287 } else { 288 frame->pitch[0] = ALIGN((width << 1), align); 289 frame->size = (int)frame->pitch[0] * height; 290 } 291 break; 292 } 293 frame->pitch[1] = 0; 294 frame->UBufOffset = 0; 295 frame->VBufOffset = 0; 296 } 297 298 assert(frame->size); 299} 300 301static void sna_memcpy_plane(struct sna_video *video, 302 uint8_t *dst, const uint8_t *src, 303 const struct sna_video_frame *frame, int sub) 304{ 305 int dstPitch = frame->pitch[!sub], srcPitch; 306 const uint8_t *s; 307 int i, j = 0; 308 int x, y, w, h; 309 310 x = frame->image.x1; 311 y = frame->image.y1; 312 w = frame->image.x2 - frame->image.x1; 313 h = frame->image.y2 - frame->image.y1; 314 if (sub) { 315 x >>= 1; w >>= 1; 316 y >>= 1; h >>= 1; 317 srcPitch = ALIGN((frame->width >> 1), 4); 318 } else 319 srcPitch = ALIGN(frame->width, 4); 320 321 src += y * srcPitch + x; 322 if (!video->textured) 323 x = y = 0; 324 325 switch (frame->rotation) { 326 case RR_Rotate_0: 327 dst += y * dstPitch + x; 328 if (srcPitch == dstPitch && srcPitch == w) 329 memcpy(dst, src, srcPitch * h); 330 else while (h--) { 331 memcpy(dst, src, w); 332 src += srcPitch; 333 dst += dstPitch; 334 } 335 break; 336 case RR_Rotate_90: 337 for (i = 0; i < h; i++) { 338 s = src; 339 for (j = 0; j < w; j++) 340 dst[i + ((x + w - j - 1) * dstPitch)] = *s++; 341 src += srcPitch; 342 } 343 break; 344 case RR_Rotate_180: 345 for (i = 0; i < h; i++) { 346 s = src; 347 for (j = 0; j < w; j++) { 348 dst[(x + w - j - 1) + 349 ((h - i - 1) * dstPitch)] = *s++; 350 } 351 src += srcPitch; 352 } 353 break; 354 case RR_Rotate_270: 355 for (i = 0; i < h; i++) { 356 s = src; 357 for (j = 0; j < w; j++) { 358 dst[(h - i - 1) + (x + j * dstPitch)] = *s++; 359 } 360 src += srcPitch; 361 } 362 break; 363 } 364} 365 366static void 367sna_copy_planar_data(struct sna_video *video, 368 const struct sna_video_frame *frame, 369 const uint8_t *src, uint8_t *dst) 370{ 371 uint8_t *d; 372 373 sna_memcpy_plane(video, dst, src, frame, 0); 374 src += frame->height * ALIGN(frame->width, 4); 375 376 if (frame->id == FOURCC_I420) 377 d = dst + frame->UBufOffset; 378 else 379 d = dst + frame->VBufOffset; 380 sna_memcpy_plane(video, d, src, frame, 1); 381 src += (frame->height >> 1) * ALIGN(frame->width >> 1, 4); 382 383 if (frame->id == FOURCC_I420) 384 d = dst + frame->VBufOffset; 385 else 386 d = dst + frame->UBufOffset; 387 sna_memcpy_plane(video, d, src, frame, 1); 388} 389 390static void 391sna_copy_packed_data(struct sna_video *video, 392 const struct sna_video_frame *frame, 393 const uint8_t *buf, 394 uint8_t *dst) 395{ 396 int pitch = frame->width << 1; 397 const uint8_t *src, *s; 398 int x, y, w, h; 399 int i, j; 400 401 if (video->textured) { 402 /* XXX support copying cropped extents */ 403 x = y = 0; 404 w = frame->width; 405 h = frame->height; 406 } else { 407 x = frame->image.x1; 408 y = frame->image.y1; 409 w = frame->image.x2 - frame->image.x1; 410 h = frame->image.y2 - frame->image.y1; 411 } 412 413 src = buf + (y * pitch) + (x << 1); 414 415 switch (frame->rotation) { 416 case RR_Rotate_0: 417 w <<= 1; 418 for (i = 0; i < h; i++) { 419 memcpy(dst, src, w); 420 src += pitch; 421 dst += frame->pitch[0]; 422 } 423 break; 424 case RR_Rotate_90: 425 h <<= 1; 426 for (i = 0; i < h; i += 2) { 427 s = src; 428 for (j = 0; j < w; j++) { 429 /* Copy Y */ 430 dst[(i + 0) + ((w - j - 1) * frame->pitch[0])] = *s; 431 s += 2; 432 } 433 src += pitch; 434 } 435 h >>= 1; 436 src = buf + (y * pitch) + (x << 1); 437 for (i = 0; i < h; i += 2) { 438 for (j = 0; j < w; j += 2) { 439 /* Copy U */ 440 dst[((i * 2) + 1) + ((w - j - 1) * frame->pitch[0])] = src[(j * 2) + 1 + (i * pitch)]; 441 dst[((i * 2) + 1) + ((w - j - 2) * frame->pitch[0])] = src[(j * 2) + 1 + ((i + 1) * pitch)]; 442 /* Copy V */ dst[((i * 2) + 3) + ((w - j - 1) * frame->pitch[0])] = src[(j * 2) + 3 + (i * pitch)]; 443 dst[((i * 2) + 3) + ((w - j - 2) * frame->pitch[0])] = src[(j * 2) + 3 + ((i + 1) * pitch)]; 444 } 445 } 446 break; 447 case RR_Rotate_180: 448 w <<= 1; 449 for (i = 0; i < h; i++) { 450 s = src; 451 for (j = 0; j < w; j += 4) { 452 dst[(w - j - 4) + ((h - i - 1) * frame->pitch[0])] = *s++; 453 dst[(w - j - 3) + ((h - i - 1) * frame->pitch[0])] = *s++; 454 dst[(w - j - 2) + ((h - i - 1) * frame->pitch[0])] = *s++; 455 dst[(w - j - 1) + ((h - i - 1) * frame->pitch[0])] = *s++; 456 } 457 src += pitch; 458 } 459 break; 460 case RR_Rotate_270: 461 h <<= 1; 462 for (i = 0; i < h; i += 2) { 463 s = src; 464 for (j = 0; j < w; j++) { 465 /* Copy Y */ 466 dst[(h - i - 2) + (j * frame->pitch[0])] = *s; 467 s += 2; 468 } 469 src += pitch; 470 } 471 h >>= 1; 472 src = buf + (y * pitch) + (x << 1); 473 for (i = 0; i < h; i += 2) { 474 for (j = 0; j < w; j += 2) { 475 /* Copy U */ 476 dst[(((h - i) * 2) - 3) + (j * frame->pitch[0])] = src[(j * 2) + 1 + (i * pitch)]; 477 dst[(((h - i) * 2) - 3) + ((j + 1) * frame->pitch[0])] = src[(j * 2) + 1 + ((i + 1) * pitch)]; 478 /* Copy V */ 479 dst[(((h - i) * 2) - 1) + (j * frame->pitch[0])] = src[(j * 2) + 3 + (i * pitch)]; 480 dst[(((h - i) * 2) - 1) + ((j + 1) * frame->pitch[0])] = src[(j * 2) + 3 + ((i + 1) * pitch)]; 481 } 482 } 483 break; 484 } 485} 486 487bool 488sna_video_copy_data(struct sna_video *video, 489 struct sna_video_frame *frame, 490 const uint8_t *buf) 491{ 492 uint8_t *dst; 493 494 DBG(("%s: handle=%d, size=%dx%d [%d], pitch=[%d,%d] rotation=%d, is-texture=%d\n", 495 __FUNCTION__, frame->bo ? frame->bo->handle : 0, 496 frame->width, frame->height, frame->size, frame->pitch[0], frame->pitch[1], 497 frame->rotation, video->textured)); 498 DBG(("%s: image=(%d, %d), (%d, %d), source=(%d, %d), (%d, %d)\n", 499 __FUNCTION__, 500 frame->image.x1, frame->image.y1, frame->image.x2, frame->image.y2, 501 frame->src.x1, frame->src.y1, frame->src.x2, frame->src.y2)); 502 assert(frame->width && frame->height); 503 assert(frame->rotation); 504 assert(frame->size); 505 506 /* In the common case, we can simply the upload in a single pwrite */ 507 if (frame->rotation == RR_Rotate_0 && !video->tiled) { 508 DBG(("%s: unrotated, untiled fast paths: is-planar?=%d\n", 509 __FUNCTION__, is_planar_fourcc(frame->id))); 510 if (is_planar_fourcc(frame->id)) { 511 int w = frame->image.x2 - frame->image.x1; 512 int h = frame->image.y2 - frame->image.y1; 513 if (ALIGN(h, 2) == frame->height && 514 ALIGN(w >> 1, 4) == frame->pitch[0] && 515 ALIGN(w, 4) == frame->pitch[1]) { 516 if (frame->bo) { 517 if (!kgem_bo_write(&video->sna->kgem, frame->bo, 518 buf, frame->size)) 519 goto use_gtt; 520 } else { 521 frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 522 KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 523 (void **)&dst); 524 if (frame->bo == NULL) 525 return false; 526 527 memcpy(dst, buf, frame->size); 528 } 529 if (frame->id != FOURCC_I420) { 530 uint32_t tmp; 531 tmp = frame->VBufOffset; 532 frame->VBufOffset = frame->UBufOffset; 533 frame->UBufOffset = tmp; 534 } 535 return true; 536 } 537 } else { 538 int x, y, w, h; 539 540 if (video->textured) { 541 /* XXX support copying cropped extents */ 542 x = y = 0; 543 w = frame->width; 544 h = frame->height; 545 } else { 546 x = frame->image.x1; 547 y = frame->image.y1; 548 w = frame->image.x2 - frame->image.x1; 549 h = frame->image.y2 - frame->image.y1; 550 } 551 552 if (w*2 == frame->pitch[0]) { 553 buf += (2U*y * frame->width) + (x << 1); 554 if (frame->bo) { 555 if (!kgem_bo_write(&video->sna->kgem, frame->bo, 556 buf, 2U*h*frame->width)) 557 goto use_gtt; 558 } else { 559 frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 560 KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 561 (void **)&dst); 562 if (frame->bo == NULL) 563 return false; 564 565 memcpy(dst, buf, 2U*h*frame->width); 566 } 567 return true; 568 } 569 } 570 571 DBG(("%s: source cropped, fallback\n", __FUNCTION__)); 572 } 573 574use_gtt: /* copy data, must use GTT so that we keep the overlay uncached */ 575 if (frame->bo) { 576 dst = kgem_bo_map__gtt(&video->sna->kgem, frame->bo); 577 if (dst == NULL) 578 return false; 579 } else { 580 frame->bo = kgem_create_buffer(&video->sna->kgem, frame->size, 581 KGEM_BUFFER_WRITE | KGEM_BUFFER_WRITE_INPLACE, 582 (void **)&dst); 583 if (frame->bo == NULL) 584 return false; 585 } 586 587 if (is_planar_fourcc(frame->id)) 588 sna_copy_planar_data(video, frame, buf, dst); 589 else 590 sna_copy_packed_data(video, frame, buf, dst); 591 592 return true; 593} 594 595XvAdaptorPtr sna_xv_adaptor_alloc(struct sna *sna) 596{ 597 XvAdaptorPtr new_adaptors; 598 599 new_adaptors = realloc(sna->xv.adaptors, 600 (sna->xv.num_adaptors+1)*sizeof(XvAdaptorRec)); 601 if (new_adaptors == NULL) 602 return NULL; 603 604 if (sna->xv.num_adaptors && new_adaptors != sna->xv.adaptors) { 605 XvAdaptorPtr adaptor = new_adaptors; 606 int i = sna->xv.num_adaptors, j; 607 while (i--) { 608 for (j = 0; j < adaptor->nPorts; j++) 609 adaptor->pPorts[j].pAdaptor = adaptor; 610 adaptor++; 611 } 612 } 613 614 sna->xv.adaptors = new_adaptors; 615 return &sna->xv.adaptors[sna->xv.num_adaptors++]; 616} 617 618int 619sna_xv_alloc_port(unsigned long port, XvPortPtr in, XvPortPtr *out) 620{ 621 *out = in; 622 return Success; 623} 624 625int 626sna_xv_free_port(XvPortPtr port) 627{ 628 return Success; 629} 630 631int 632sna_xv_fixup_formats(ScreenPtr screen, XvFormatPtr formats, int num_formats) 633{ 634 XvFormatPtr out = formats; 635 int count = 0; 636 637 while (num_formats--) { 638 int num_visuals = screen->numVisuals; 639 VisualPtr v = screen->visuals; 640 641 while (num_visuals--) { 642 if (v->class == TrueColor && 643 v->nplanes == formats->depth) { 644 int tmp = out[count].depth; 645 out[count].depth = formats->depth; 646 out[count].visual = v->vid; 647 formats->depth = tmp; 648 count++; 649 break; 650 } 651 v++; 652 } 653 654 formats++; 655 } 656 657 return count; 658} 659 660#if XORG_XV_VERSION < 2 661static int 662sna_xv_query_adaptors(ScreenPtr screen, 663 XvAdaptorPtr *adaptors, 664 int *num_adaptors) 665{ 666 struct sna *sna = to_sna_from_screen(screen); 667 668 *num_adaptors = sna->xv.num_adaptors; 669 *adaptors = sna->xv.adaptors; 670 return Success; 671} 672 673static Bool 674sna_xv_close_screen(CLOSE_SCREEN_ARGS_DECL) 675{ 676 struct sna *sna = to_sna_from_screen(screen); 677 sna_video_close(sna); 678 return TRUE; 679} 680#endif 681 682void sna_video_init(struct sna *sna, ScreenPtr screen) 683{ 684 XvScreenPtr xv; 685 686 if (noXvExtension) 687 return; 688 689 if (xf86LoaderCheckSymbol("xf86XVListGenericAdaptors")) { 690 XF86VideoAdaptorPtr *adaptors = NULL; 691 int num_adaptors = xf86XVListGenericAdaptors(sna->scrn, &adaptors); 692 if (num_adaptors) 693 xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR, 694 "Ignoring generic xf86XV adaptors"); 695 free(adaptors); 696 } 697 698 if (XvScreenInit(screen) != Success) 699 return; 700 701 xv = to_xv(screen); 702#if XORG_XV_VERSION < 2 703 xv->ddCloseScreen = sna_xv_close_screen; 704 xv->ddQueryAdaptors = sna_xv_query_adaptors; 705#endif 706 707 sna_video_textured_setup(sna, screen); 708 sna_video_sprite_setup(sna, screen); 709 sna_video_overlay_setup(sna, screen); 710 711 if (sna->xv.num_adaptors >= 2 && 712 xf86ReturnOptValBool(sna->Options, OPTION_PREFER_OVERLAY, false)) { 713 XvAdaptorRec tmp; 714 715 tmp = sna->xv.adaptors[0]; 716 sna->xv.adaptors[0] = sna->xv.adaptors[1]; 717 sna->xv.adaptors[1] = tmp; 718 } 719 720 xv->nAdaptors = sna->xv.num_adaptors; 721 xv->pAdaptors = sna->xv.adaptors; 722 723 sna_video_xvmc_setup(sna, screen); 724} 725 726void sna_video_destroy_window(WindowPtr win) 727{ 728 XvPortPtr port; 729 730 port = sna_window_get_port(win); 731 if (port) { 732#if XORG_XV_VERSION < 2 733 port->pAdaptor->ddStopVideo(NULL, port, &win->drawable); 734#else 735 port->pAdaptor->ddStopVideo(port, &win->drawable); 736#endif 737 } 738 assert(sna_window_get_port(win) == NULL); 739} 740 741void sna_video_close(struct sna *sna) 742{ 743 int i; 744 745 for (i = 0; i < sna->xv.num_adaptors; i++) { 746 free(sna->xv.adaptors[i].pPorts->devPriv.ptr); 747 free(sna->xv.adaptors[i].pPorts); 748 free(sna->xv.adaptors[i].pEncodings); 749 } 750 free(sna->xv.adaptors); 751 752 sna->xv.adaptors = NULL; 753 sna->xv.num_adaptors = 0; 754} 755