intel_video.c revision 13496ba1
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/* 45 * XXX Could support more formats. 46 */ 47 48#ifdef HAVE_CONFIG_H 49#include "config.h" 50#endif 51 52#include <inttypes.h> 53#include <math.h> 54#include <string.h> 55#include <assert.h> 56#include <errno.h> 57 58#include "xorg-server.h" 59#include "xf86.h" 60#include "xf86_OSproc.h" 61#include "compiler.h" 62#include "xf86Pci.h" 63#include "xf86fbman.h" 64#include "xf86drm.h" 65#include "regionstr.h" 66#include "randrstr.h" 67#include "windowstr.h" 68#include "damage.h" 69#include "intel.h" 70#include "intel_video.h" 71#include "i830_reg.h" 72#include "xf86xv.h" 73#include <X11/extensions/Xv.h> 74#include "dixstruct.h" 75#include "fourcc.h" 76 77#ifdef INTEL_XVMC 78#define _INTEL_XVMC_SERVER_ 79#include "intel_xvmc.h" 80#endif 81#include "intel_uxa.h" 82#include "intel_video_overlay.h" 83 84Atom intel_xv_Brightness, intel_xv_Contrast, intel_xv_Saturation, intel_xv_ColorKey, intel_xv_Pipe; 85Atom intel_xv_Gamma0, intel_xv_Gamma1, intel_xv_Gamma2, intel_xv_Gamma3, intel_xv_Gamma4, intel_xv_Gamma5; 86Atom intel_xv_SyncToVblank; 87 88/* client libraries expect an encoding */ 89const XF86VideoEncodingRec intel_xv_dummy_encoding[1] = { 90 { 91 0, 92 "XV_IMAGE", 93 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, 94 {1, 1} 95 } 96}; 97 98XF86VideoFormatRec intel_xv_formats[NUM_FORMATS] = { 99 {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 100}; 101 102XF86AttributeRec intel_xv_attributes[NUM_ATTRIBUTES] = { 103 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 104 {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, 105 {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, 106 {XvSettable | XvGettable, 0, 1023, "XV_SATURATION"}, 107 {XvSettable | XvGettable, -1, 1, "XV_PIPE"} 108}; 109 110#define GAMMA_ATTRIBUTES 6 111XF86AttributeRec intel_xv_gamma_attributes[GAMMA_ATTRIBUTES] = { 112 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, 113 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"}, 114 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"}, 115 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"}, 116 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"}, 117 {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} 118}; 119 120#ifdef INTEL_XVMC 121#define NUM_IMAGES 5 122#define XVMC_IMAGE 1 123#else 124#define NUM_IMAGES 4 125#define XVMC_IMAGE 0 126#endif 127 128XF86ImageRec intel_xv_images[NUM_IMAGES] = { 129 XVIMAGE_YUY2, 130 XVIMAGE_YV12, 131 XVIMAGE_I420, 132 XVIMAGE_UYVY, 133#ifdef INTEL_XVMC 134 { 135 /* 136 * Below, a dummy picture type that is used in XvPutImage only to do 137 * an overlay update. Introduced for the XvMC client lib. 138 * Defined to have a zero data size. 139 */ 140 FOURCC_XVMC, 141 XvYUV, 142 LSBFirst, 143 {'X', 'V', 'M', 'C', 144 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 145 0x38, 0x9B, 0x71}, 146 12, 147 XvPlanar, 148 3, 149 0, 0, 0, 0, 150 8, 8, 8, 151 1, 2, 2, 152 1, 2, 2, 153 {'Y', 'V', 'U', 154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 156 XvTopToBottom}, 157#endif 158}; 159 160void intel_video_init(ScreenPtr screen) 161{ 162 ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 163 intel_screen_private *intel = intel_get_screen_private(scrn); 164 XF86VideoAdaptorPtr *adaptors = NULL, *newAdaptors = NULL; 165 XF86VideoAdaptorPtr overlayAdaptor = NULL, texturedAdaptor = NULL; 166 int num_adaptors = xf86XVListGenericAdaptors(scrn, &adaptors); 167 168 /* Give our adaptor list enough space for the overlay and/or texture video 169 * adaptors. 170 */ 171 newAdaptors = realloc(adaptors, 172 (num_adaptors + 3) * sizeof(XF86VideoAdaptorPtr)); 173 174 if (newAdaptors == NULL) { 175 free(adaptors); 176 return; 177 } 178 adaptors = newAdaptors; 179 180 /* Add the adaptors supported by our hardware. First, set up the atoms 181 * that will be used by both output adaptors. 182 */ 183 intel_xv_Brightness = MAKE_ATOM("XV_BRIGHTNESS"); 184 intel_xv_Contrast = MAKE_ATOM("XV_CONTRAST"); 185 186 /* Set up textured video if we can do it at this depth and we are on 187 * supported hardware. 188 */ 189 if (!intel->force_fallback && 190 scrn->bitsPerPixel >= 16 && 191 INTEL_INFO(intel)->gen >= 030 && 192 INTEL_INFO(intel)->gen < 0100) { 193 texturedAdaptor = intel_uxa_video_setup_image_textured(screen); 194 if (texturedAdaptor != NULL) { 195 xf86DrvMsg(scrn->scrnIndex, X_INFO, 196 "Set up textured video\n"); 197 } else { 198 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 199 "Failed to set up textured video\n"); 200 } 201 } 202 203 overlayAdaptor = intel_video_overlay_setup_image(screen); 204 205 if (intel->use_overlay) { 206 if (overlayAdaptor != NULL) { 207 xf86DrvMsg(scrn->scrnIndex, X_INFO, 208 "Set up overlay video\n"); 209 } else { 210 xf86DrvMsg(scrn->scrnIndex, X_ERROR, 211 "Failed to set up overlay video\n"); 212 } 213 } 214 215 if (overlayAdaptor && intel->XvPreferOverlay) 216 adaptors[num_adaptors++] = overlayAdaptor; 217 218 if (texturedAdaptor) 219 adaptors[num_adaptors++] = texturedAdaptor; 220 221 if (overlayAdaptor && !intel->XvPreferOverlay) 222 adaptors[num_adaptors++] = overlayAdaptor; 223 224 if (num_adaptors) { 225 xf86XVScreenInit(screen, adaptors, num_adaptors); 226 } else { 227 xf86DrvMsg(scrn->scrnIndex, X_WARNING, 228 "Disabling Xv because no adaptors could be initialized.\n"); 229 intel->XvEnabled = FALSE; 230 } 231 232#ifdef INTEL_XVMC 233 if (texturedAdaptor) 234 intel_xvmc_adaptor_init(screen); 235#endif 236 237 free(adaptors); 238} 239 240void intel_free_video_buffers(intel_adaptor_private *adaptor_priv) 241{ 242 int i; 243 244 for (i = 0; i < 2; i++) { 245 if (adaptor_priv->old_buf[i]) { 246 drm_intel_bo_disable_reuse(adaptor_priv->old_buf[i]); 247 drm_intel_bo_unreference(adaptor_priv->old_buf[i]); 248 adaptor_priv->old_buf[i] = NULL; 249 } 250 } 251 252 if (adaptor_priv->buf) { 253 drm_intel_bo_unreference(adaptor_priv->buf); 254 adaptor_priv->buf = NULL; 255 } 256} 257 258int 259intel_video_get_port_attribute(ScrnInfoPtr scrn, 260 Atom attribute, INT32 * value, pointer data) 261{ 262 intel_screen_private *intel = intel_get_screen_private(scrn); 263 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 264 265 if (attribute == intel_xv_Brightness) { 266 *value = adaptor_priv->brightness; 267 } else if (attribute == intel_xv_Contrast) { 268 *value = adaptor_priv->contrast; 269 } else if (attribute == intel_xv_Saturation) { 270 *value = adaptor_priv->saturation; 271 } else if (attribute == intel_xv_Pipe) { 272 int c; 273 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 274 for (c = 0; c < xf86_config->num_crtc; c++) 275 if (xf86_config->crtc[c] == adaptor_priv->desired_crtc) 276 break; 277 if (c == xf86_config->num_crtc) 278 c = -1; 279 *value = c; 280 } else if (attribute == intel_xv_Gamma0 && (INTEL_INFO(intel)->gen >= 030)) { 281 *value = adaptor_priv->gamma0; 282 } else if (attribute == intel_xv_Gamma1 && (INTEL_INFO(intel)->gen >= 030)) { 283 *value = adaptor_priv->gamma1; 284 } else if (attribute == intel_xv_Gamma2 && (INTEL_INFO(intel)->gen >= 030)) { 285 *value = adaptor_priv->gamma2; 286 } else if (attribute == intel_xv_Gamma3 && (INTEL_INFO(intel)->gen >= 030)) { 287 *value = adaptor_priv->gamma3; 288 } else if (attribute == intel_xv_Gamma4 && (INTEL_INFO(intel)->gen >= 030)) { 289 *value = adaptor_priv->gamma4; 290 } else if (attribute == intel_xv_Gamma5 && (INTEL_INFO(intel)->gen >= 030)) { 291 *value = adaptor_priv->gamma5; 292 } else if (attribute == intel_xv_ColorKey) { 293 *value = adaptor_priv->colorKey; 294 } else if (attribute == intel_xv_SyncToVblank) { 295 *value = adaptor_priv->SyncToVblank; 296 } else 297 return BadMatch; 298 299 return Success; 300} 301 302void 303intel_video_query_best_size(ScrnInfoPtr scrn, 304 Bool motion, 305 short vid_w, short vid_h, 306 short drw_w, short drw_h, 307 unsigned int *p_w, unsigned int *p_h, pointer data) 308{ 309 if (vid_w > (drw_w << 1)) 310 drw_w = vid_w >> 1; 311 if (vid_h > (drw_h << 1)) 312 drw_h = vid_h >> 1; 313 314 *p_w = drw_w; 315 *p_h = drw_h; 316} 317 318static Bool 319intel_video_copy_packed_data(intel_adaptor_private *adaptor_priv, 320 unsigned char *buf, 321 int srcPitch, int dstPitch, int top, int left, int h, int w) 322{ 323 unsigned char *src, *dst, *dst_base; 324 int i, j; 325 unsigned char *s; 326 327#if 0 328 ErrorF("intel_video_copy_packed_data: (%d,%d) (%d,%d)\n" 329 "srcPitch: %d, dstPitch: %d\n", top, left, h, w, 330 srcPitch, dstPitch); 331#endif 332 333 src = buf + (top * srcPitch) + (left << 1); 334 335 if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 336 return FALSE; 337 338 dst_base = adaptor_priv->buf->virtual; 339 340 dst = dst_base + adaptor_priv->YBufOffset; 341 342 switch (adaptor_priv->rotation) { 343 case RR_Rotate_0: 344 w <<= 1; 345 for (i = 0; i < h; i++) { 346 memcpy(dst, src, w); 347 src += srcPitch; 348 dst += dstPitch; 349 } 350 break; 351 case RR_Rotate_90: 352 h <<= 1; 353 for (i = 0; i < h; i += 2) { 354 s = src; 355 for (j = 0; j < w; j++) { 356 /* Copy Y */ 357 dst[(i + 0) + ((w - j - 1) * dstPitch)] = *s++; 358 (void)*s++; 359 } 360 src += srcPitch; 361 } 362 h >>= 1; 363 src = buf + (top * srcPitch) + (left << 1); 364 for (i = 0; i < h; i += 2) { 365 for (j = 0; j < w; j += 2) { 366 /* Copy U */ 367 dst[((i * 2) + 1) + ((w - j - 1) * dstPitch)] = 368 src[(j * 2) + 1 + (i * srcPitch)]; 369 dst[((i * 2) + 1) + ((w - j - 2) * dstPitch)] = 370 src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 371 /* Copy V */ 372 dst[((i * 2) + 3) + ((w - j - 1) * dstPitch)] = 373 src[(j * 2) + 3 + (i * srcPitch)]; 374 dst[((i * 2) + 3) + ((w - j - 2) * dstPitch)] = 375 src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 376 } 377 } 378 break; 379 case RR_Rotate_180: 380 w <<= 1; 381 for (i = 0; i < h; i++) { 382 s = src; 383 for (j = 0; j < w; j += 4) { 384 dst[(w - j - 4) + ((h - i - 1) * dstPitch)] = 385 *s++; 386 dst[(w - j - 3) + ((h - i - 1) * dstPitch)] = 387 *s++; 388 dst[(w - j - 2) + ((h - i - 1) * dstPitch)] = 389 *s++; 390 dst[(w - j - 1) + ((h - i - 1) * dstPitch)] = 391 *s++; 392 } 393 src += srcPitch; 394 } 395 break; 396 case RR_Rotate_270: 397 h <<= 1; 398 for (i = 0; i < h; i += 2) { 399 s = src; 400 for (j = 0; j < w; j++) { 401 /* Copy Y */ 402 dst[(h - i - 2) + (j * dstPitch)] = *s++; 403 (void)*s++; 404 } 405 src += srcPitch; 406 } 407 h >>= 1; 408 src = buf + (top * srcPitch) + (left << 1); 409 for (i = 0; i < h; i += 2) { 410 for (j = 0; j < w; j += 2) { 411 /* Copy U */ 412 dst[(((h - i) * 2) - 3) + (j * dstPitch)] = 413 src[(j * 2) + 1 + (i * srcPitch)]; 414 dst[(((h - i) * 2) - 3) + 415 ((j + 1) * dstPitch)] = 416 src[(j * 2) + 1 + ((i + 1) * srcPitch)]; 417 /* Copy V */ 418 dst[(((h - i) * 2) - 1) + (j * dstPitch)] = 419 src[(j * 2) + 3 + (i * srcPitch)]; 420 dst[(((h - i) * 2) - 1) + 421 ((j + 1) * dstPitch)] = 422 src[(j * 2) + 3 + ((i + 1) * srcPitch)]; 423 } 424 } 425 break; 426 } 427 428 drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 429 return TRUE; 430} 431 432static void intel_memcpy_plane(unsigned char *dst, unsigned char *src, 433 int height, int width, 434 int dstPitch, int srcPitch, Rotation rotation) 435{ 436 int i, j = 0; 437 unsigned char *s; 438 439 switch (rotation) { 440 case RR_Rotate_0: 441 /* optimise for the case of no clipping */ 442 if (srcPitch == dstPitch && srcPitch == width) 443 memcpy(dst, src, srcPitch * height); 444 else 445 for (i = 0; i < height; i++) { 446 memcpy(dst, src, width); 447 src += srcPitch; 448 dst += dstPitch; 449 } 450 break; 451 case RR_Rotate_90: 452 for (i = 0; i < height; i++) { 453 s = src; 454 for (j = 0; j < width; j++) { 455 dst[(i) + ((width - j - 1) * dstPitch)] = *s++; 456 } 457 src += srcPitch; 458 } 459 break; 460 case RR_Rotate_180: 461 for (i = 0; i < height; i++) { 462 s = src; 463 for (j = 0; j < width; j++) { 464 dst[(width - j - 1) + 465 ((height - i - 1) * dstPitch)] = *s++; 466 } 467 src += srcPitch; 468 } 469 break; 470 case RR_Rotate_270: 471 for (i = 0; i < height; i++) { 472 s = src; 473 for (j = 0; j < width; j++) { 474 dst[(height - i - 1) + (j * dstPitch)] = *s++; 475 } 476 src += srcPitch; 477 } 478 break; 479 } 480} 481 482static Bool 483intel_video_copy_planar_data(intel_adaptor_private *adaptor_priv, 484 unsigned char *buf, int srcPitch, int srcPitch2, 485 int dstPitch, int dstPitch2, 486 int srcH, int top, int left, 487 int h, int w, int id) 488{ 489 unsigned char *src1, *src2, *src3, *dst_base, *dst1, *dst2, *dst3; 490 491#if 0 492 ErrorF("intel_video_copy_planar_data: srcPitch %d, srcPitch %d, dstPitch %d\n" 493 "nlines %d, npixels %d, top %d, left %d\n", 494 srcPitch, srcPitch2, dstPitch, h, w, top, left); 495#endif 496 497 /* Copy Y data */ 498 src1 = buf + (top * srcPitch) + left; 499#if 0 500 ErrorF("src1 is %p, offset is %ld\n", src1, 501 (unsigned long)src1 - (unsigned long)buf); 502#endif 503 504 if (drm_intel_gem_bo_map_gtt(adaptor_priv->buf)) 505 return FALSE; 506 507 dst_base = adaptor_priv->buf->virtual; 508 509 dst1 = dst_base + adaptor_priv->YBufOffset; 510 511 intel_memcpy_plane(dst1, src1, h, w, dstPitch2, srcPitch, 512 adaptor_priv->rotation); 513 514 /* Copy V data for YV12, or U data for I420 */ 515 src2 = buf + /* start of YUV data */ 516 (srcH * srcPitch) + /* move over Luma plane */ 517 ((top >> 1) * srcPitch2) + /* move down from by top lines */ 518 (left >> 1); /* move left by left pixels */ 519 520#if 0 521 ErrorF("src2 is %p, offset is %ld\n", src2, 522 (unsigned long)src2 - (unsigned long)buf); 523#endif 524 if (id == FOURCC_I420) 525 dst2 = dst_base + adaptor_priv->UBufOffset; 526 else 527 dst2 = dst_base + adaptor_priv->VBufOffset; 528 529 intel_memcpy_plane(dst2, src2, h / 2, w / 2, 530 dstPitch, srcPitch2, adaptor_priv->rotation); 531 532 /* Copy U data for YV12, or V data for I420 */ 533 src3 = buf + /* start of YUV data */ 534 (srcH * srcPitch) + /* move over Luma plane */ 535 ((srcH >> 1) * srcPitch2) + /* move over Chroma plane */ 536 ((top >> 1) * srcPitch2) + /* move down from by top lines */ 537 (left >> 1); /* move left by left pixels */ 538#if 0 539 ErrorF("src3 is %p, offset is %ld\n", src3, 540 (unsigned long)src3 - (unsigned long)buf); 541#endif 542 if (id == FOURCC_I420) 543 dst3 = dst_base + adaptor_priv->VBufOffset; 544 else 545 dst3 = dst_base + adaptor_priv->UBufOffset; 546 547 intel_memcpy_plane(dst3, src3, h / 2, w / 2, 548 dstPitch, srcPitch2, adaptor_priv->rotation); 549 550 drm_intel_gem_bo_unmap_gtt(adaptor_priv->buf); 551 return TRUE; 552} 553 554void 555intel_setup_dst_params(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, short width, 556 short height, int *dstPitch, int *dstPitch2, int *size, 557 int id) 558{ 559 intel_screen_private *intel = intel_get_screen_private(scrn); 560 int pitchAlign; 561 562 /* Only needs to be DWORD-aligned for textured on i915, but overlay has 563 * stricter requirements. 564 */ 565 if (adaptor_priv->textured) { 566 pitchAlign = 4; 567 } else { 568 if (INTEL_INFO(intel)->gen >= 040) 569 /* Actually the alignment is 64 bytes, too. But the 570 * stride must be at least 512 bytes. Take the easy fix 571 * and align on 512 bytes unconditionally. */ 572 pitchAlign = 512; 573 else if (IS_I830(intel) || IS_845G(intel)) 574 /* Harsh, errata on these chipsets limit the stride to be 575 * a multiple of 256 bytes. 576 */ 577 pitchAlign = 256; 578 else 579 pitchAlign = 64; 580 } 581 582#if INTEL_XVMC 583 /* for i915 xvmc, hw requires 1kb aligned surfaces */ 584 if ((id == FOURCC_XVMC) && IS_GEN3(intel)) 585 pitchAlign = 1024; 586#endif 587 588 /* Determine the desired destination pitch (representing the chroma's pitch, 589 * in the planar case. 590 */ 591 if (is_planar_fourcc(id)) { 592 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 593 *dstPitch = ALIGN((height / 2), pitchAlign); 594 *dstPitch2 = ALIGN(height, pitchAlign); 595 *size = *dstPitch * width * 3; 596 } else { 597 *dstPitch = ALIGN((width / 2), pitchAlign); 598 *dstPitch2 = ALIGN(width, pitchAlign); 599 *size = *dstPitch * height * 3; 600 } 601 } else { 602 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 603 *dstPitch = ALIGN((height << 1), pitchAlign); 604 *size = *dstPitch * width; 605 } else { 606 *dstPitch = ALIGN((width << 1), pitchAlign); 607 *size = *dstPitch * height; 608 } 609 *dstPitch2 = 0; 610 } 611#if 0 612 ErrorF("srcPitch: %d, dstPitch: %d, size: %d\n", srcPitch, *dstPitch, 613 size); 614#endif 615 616 adaptor_priv->YBufOffset = 0; 617 618 if (adaptor_priv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 619 adaptor_priv->UBufOffset = 620 adaptor_priv->YBufOffset + (*dstPitch2 * width); 621 adaptor_priv->VBufOffset = 622 adaptor_priv->UBufOffset + (*dstPitch * width / 2); 623 } else { 624 adaptor_priv->UBufOffset = 625 adaptor_priv->YBufOffset + (*dstPitch2 * height); 626 adaptor_priv->VBufOffset = 627 adaptor_priv->UBufOffset + (*dstPitch * height / 2); 628 } 629} 630 631static Bool 632intel_setup_video_buffer(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 633 int alloc_size, int id, unsigned char *buf) 634{ 635 intel_screen_private *intel = intel_get_screen_private(scrn); 636 637 /* Free the current buffer if we're going to have to reallocate */ 638 if (adaptor_priv->buf && adaptor_priv->buf->size < alloc_size) 639 intel_free_video_buffers(adaptor_priv); 640 641 if (adaptor_priv->buf == NULL) { 642 adaptor_priv->buf = drm_intel_bo_alloc(intel->bufmgr, "xv buffer", 643 alloc_size, 4096); 644 if (adaptor_priv->buf == NULL) 645 return FALSE; 646 647 adaptor_priv->reusable = TRUE; 648 } 649 650 return TRUE; 651} 652 653Bool 654intel_video_copy_data(ScrnInfoPtr scrn, intel_adaptor_private *adaptor_priv, 655 short width, short height, int *dstPitch, int *dstPitch2, 656 int top, int left, int npixels, int nlines, 657 int id, unsigned char *buf) 658{ 659 int srcPitch = 0, srcPitch2 = 0; 660 int size; 661 662 if (is_planar_fourcc(id)) { 663 srcPitch = ALIGN(width, 0x4); 664 srcPitch2 = ALIGN((width >> 1), 0x4); 665 } else { 666 srcPitch = width << 1; 667 } 668 669 intel_setup_dst_params(scrn, adaptor_priv, width, height, dstPitch, 670 dstPitch2, &size, id); 671 672 if (!intel_setup_video_buffer(scrn, adaptor_priv, size, id, buf)) 673 return FALSE; 674 675 /* copy data */ 676 if (is_planar_fourcc(id)) { 677 return intel_video_copy_planar_data(adaptor_priv, buf, srcPitch, srcPitch2, 678 *dstPitch, *dstPitch2, 679 height, top, left, nlines, 680 npixels, id); 681 } else { 682 return intel_video_copy_packed_data(adaptor_priv, buf, srcPitch, *dstPitch, top, left, 683 nlines, npixels); 684 } 685} 686 687int is_planar_fourcc(int id) 688{ 689 switch (id) { 690 case FOURCC_YV12: 691 case FOURCC_I420: 692#ifdef INTEL_XVMC 693 case FOURCC_XVMC: 694#endif 695 return 1; 696 case FOURCC_UYVY: 697 case FOURCC_YUY2: 698 return 0; 699 default: 700 ErrorF("Unknown format 0x%x\n", id); 701 return 0; 702 } 703} 704 705Bool 706intel_clip_video_helper(ScrnInfoPtr scrn, 707 intel_adaptor_private *adaptor_priv, 708 xf86CrtcPtr * crtc_ret, 709 BoxPtr dst, 710 short src_x, short src_y, 711 short drw_x, short drw_y, 712 short src_w, short src_h, 713 short drw_w, short drw_h, 714 int id, 715 int *top, int* left, int* npixels, int *nlines, 716 RegionPtr reg, INT32 width, INT32 height) 717{ 718 Bool ret; 719 RegionRec crtc_region_local; 720 RegionPtr crtc_region = reg; 721 BoxRec crtc_box; 722 INT32 x1, x2, y1, y2; 723 xf86CrtcPtr crtc; 724 725 x1 = src_x; 726 x2 = src_x + src_w; 727 y1 = src_y; 728 y2 = src_y + src_h; 729 730 dst->x1 = drw_x; 731 dst->x2 = drw_x + drw_w; 732 dst->y1 = drw_y; 733 dst->y2 = drw_y + drw_h; 734 735 /* 736 * For overlay video, compute the relevant CRTC and 737 * clip video to that 738 */ 739 crtc = intel_covering_crtc(scrn, dst, adaptor_priv->desired_crtc, 740 &crtc_box); 741 742 /* For textured video, we don't actually want to clip at all. */ 743 if (crtc && !adaptor_priv->textured) { 744 REGION_INIT(screen, &crtc_region_local, &crtc_box, 1); 745 crtc_region = &crtc_region_local; 746 REGION_INTERSECT(screen, crtc_region, crtc_region, 747 reg); 748 } 749 *crtc_ret = crtc; 750 751 ret = xf86XVClipVideoHelper(dst, &x1, &x2, &y1, &y2, 752 crtc_region, width, height); 753 if (crtc_region != reg) 754 REGION_UNINIT(screen, &crtc_region_local); 755 756 *top = y1 >> 16; 757 *left = (x1 >> 16) & ~1; 758 *npixels = ALIGN(((x2 + 0xffff) >> 16), 2) - *left; 759 if (is_planar_fourcc(id)) { 760 *top &= ~1; 761 *nlines = ALIGN(((y2 + 0xffff) >> 16), 2) - *top; 762 } else 763 *nlines = ((y2 + 0xffff) >> 16) - *top; 764 765 return ret; 766} 767 768int 769intel_video_query_image_attributes(ScrnInfoPtr scrn, 770 int id, 771 unsigned short *w, unsigned short *h, 772 int *pitches, int *offsets) 773{ 774 intel_screen_private *intel = intel_get_screen_private(scrn); 775 int size, tmp; 776 777#if 0 778 ErrorF("intel_video_query_image_attributes: w is %d, h is %d\n", *w, *h); 779#endif 780 781 if (IS_845G(intel) || IS_I830(intel)) { 782 if (*w > IMAGE_MAX_WIDTH_LEGACY) 783 *w = IMAGE_MAX_WIDTH_LEGACY; 784 if (*h > IMAGE_MAX_HEIGHT_LEGACY) 785 *h = IMAGE_MAX_HEIGHT_LEGACY; 786 } else { 787 if (*w > IMAGE_MAX_WIDTH) 788 *w = IMAGE_MAX_WIDTH; 789 if (*h > IMAGE_MAX_HEIGHT) 790 *h = IMAGE_MAX_HEIGHT; 791 } 792 793 *w = (*w + 1) & ~1; 794 if (offsets) 795 offsets[0] = 0; 796 797 switch (id) { 798 /* IA44 is for XvMC only */ 799 case FOURCC_IA44: 800 case FOURCC_AI44: 801 if (pitches) 802 pitches[0] = *w; 803 size = *w * *h; 804 break; 805 case FOURCC_YV12: 806 case FOURCC_I420: 807 *h = (*h + 1) & ~1; 808 size = (*w + 3) & ~3; 809 if (pitches) 810 pitches[0] = size; 811 size *= *h; 812 if (offsets) 813 offsets[1] = size; 814 tmp = ((*w >> 1) + 3) & ~3; 815 if (pitches) 816 pitches[1] = pitches[2] = tmp; 817 tmp *= (*h >> 1); 818 size += tmp; 819 if (offsets) 820 offsets[2] = size; 821 size += tmp; 822#if 0 823 if (pitches) 824 ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", 825 pitches[0], pitches[1], pitches[2]); 826 if (offsets) 827 ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], 828 offsets[2]); 829 if (offsets) 830 ErrorF("size is %d\n", size); 831#endif 832 break; 833#ifdef INTEL_XVMC 834 case FOURCC_XVMC: 835 *h = (*h + 1) & ~1; 836 size = sizeof(struct intel_xvmc_command); 837 if (pitches) 838 pitches[0] = size; 839 break; 840#endif 841 case FOURCC_UYVY: 842 case FOURCC_YUY2: 843 default: 844 size = *w << 1; 845 if (pitches) 846 pitches[0] = size; 847 size *= *h; 848 break; 849 } 850 851 return size; 852} 853 854void intel_video_stop_video(ScrnInfoPtr scrn, pointer data, Bool shutdown) 855{ 856 intel_adaptor_private *adaptor_priv = (intel_adaptor_private *) data; 857 858 if (adaptor_priv->textured) 859 return; 860 861 REGION_EMPTY(scrn->pScreen, &adaptor_priv->clip); 862 863 if (shutdown) { 864 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) 865 intel_video_overlay_off(intel_get_screen_private(scrn)); 866 867 intel_free_video_buffers(adaptor_priv); 868 adaptor_priv->videoStatus = 0; 869 } else { 870 if (adaptor_priv->videoStatus & CLIENT_VIDEO_ON) { 871 adaptor_priv->videoStatus |= OFF_TIMER; 872 adaptor_priv->offTime = currentTime.milliseconds + OFF_DELAY; 873 } 874 } 875 876} 877 878void 879intel_video_block_handler(intel_screen_private *intel) 880{ 881 intel_adaptor_private *adaptor_priv; 882 883 /* no overlay */ 884 if (intel->adaptor == NULL) 885 return; 886 887 adaptor_priv = intel_get_adaptor_private(intel); 888 if (adaptor_priv->videoStatus & OFF_TIMER) { 889 Time now = currentTime.milliseconds; 890 if (adaptor_priv->offTime < now) { 891 /* Turn off the overlay */ 892 intel_video_overlay_off(intel); 893 intel_free_video_buffers(adaptor_priv); 894 adaptor_priv->videoStatus = 0; 895 } 896 } 897} 898