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