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