1/*************************************************************************** 2 3 Copyright 2000-2011 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#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include "sna.h" 32#include "sna_video.h" 33 34#include <xf86drm.h> 35#include <xf86xv.h> 36#include <X11/extensions/Xv.h> 37#include <fourcc.h> 38#include <i915_drm.h> 39 40#include "intel_options.h" 41 42#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 43 44#define HAS_GAMMA(sna) ((sna)->kgem.gen >= 030) 45 46static Atom xvBrightness, xvContrast, xvSaturation, xvColorKey, xvPipe, xvAlwaysOnTop; 47static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; 48 49/* Limits for the overlay/textured video source sizes. The documented hardware 50 * limits are 2048x2048 or better for overlay and both of our textured video 51 * implementations. Additionally, on the 830 and 845, larger sizes resulted in 52 * the card hanging, so we keep the limits lower there. 53 */ 54#define IMAGE_MAX_WIDTH 2048 55#define IMAGE_MAX_HEIGHT 2048 56#define IMAGE_MAX_WIDTH_LEGACY 1024 57#define IMAGE_MAX_HEIGHT_LEGACY 1088 58 59static XvFormatRec Formats[] = { {15}, {16}, {24} }; 60 61static const XvAttributeRec Attributes[] = { 62 {XvSettable | XvGettable, 0, (1 << 24) - 1, (char *)"XV_COLORKEY"}, 63 {XvSettable | XvGettable, 0, 1, (char *)"XV_ALWAYS_ON_TOP"}, 64 {XvSettable | XvGettable, -128, 127, (char *)"XV_BRIGHTNESS"}, 65 {XvSettable | XvGettable, 0, 255, (char *)"XV_CONTRAST"}, 66 {XvSettable | XvGettable, 0, 1023, (char *)"XV_SATURATION"}, 67 {XvSettable | XvGettable, -1, 1, (char *)"XV_PIPE"}, 68#define NUM_ATTRIBUTES 6 69 70 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA0"}, 71 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA1"}, 72 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA2"}, 73 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA3"}, 74 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA4"}, 75 {XvSettable | XvGettable, 0, 0xffffff, (char *)"XV_GAMMA5"} 76#define GAMMA_ATTRIBUTES 6 77}; 78 79static const XvImageRec Images[] = { 80 XVIMAGE_YUY2, 81 XVIMAGE_YV12, 82 XVIMAGE_I420, 83 XVIMAGE_UYVY, 84 XVMC_YUV 85}; 86 87/* kernel modesetting overlay functions */ 88static bool sna_has_overlay(struct sna *sna) 89{ 90 struct drm_i915_getparam gp; 91 int has_overlay = 0; 92 int ret; 93 94 VG_CLEAR(gp); 95 gp.param = I915_PARAM_HAS_OVERLAY; 96 gp.value = &has_overlay; 97 ret = drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GETPARAM, &gp); 98 return ret == 0 && has_overlay; 99} 100 101static bool sna_video_overlay_update_attrs(struct sna_video *video) 102{ 103 struct drm_intel_overlay_attrs attrs; 104 105 DBG(("%s()\n", __FUNCTION__)); 106 107 attrs.flags = I915_OVERLAY_UPDATE_ATTRS; 108 attrs.brightness = video->brightness; 109 attrs.contrast = video->contrast; 110 attrs.saturation = video->saturation; 111 attrs.color_key = video->color_key; 112 attrs.gamma0 = video->gamma0; 113 attrs.gamma1 = video->gamma1; 114 attrs.gamma2 = video->gamma2; 115 attrs.gamma3 = video->gamma3; 116 attrs.gamma4 = video->gamma4; 117 attrs.gamma5 = video->gamma5; 118 119 if (video->AlwaysOnTop) 120 attrs.flags |= 1<<2; 121 122 return drmIoctl(video->sna->kgem.fd, DRM_IOCTL_I915_OVERLAY_ATTRS, &attrs) == 0; 123} 124 125static int sna_video_overlay_stop(ddStopVideo_ARGS) 126{ 127 struct sna_video *video = port->devPriv.ptr; 128 struct sna *sna = video->sna; 129 struct drm_intel_overlay_put_image request; 130 131 DBG(("%s()\n", __FUNCTION__)); 132 133 REGION_EMPTY(scrn->pScreen, &video->clip); 134 135 request.flags = 0; 136 (void)drmIoctl(sna->kgem.fd, 137 DRM_IOCTL_I915_OVERLAY_PUT_IMAGE, 138 &request); 139 140 if (video->bo[0]) 141 kgem_bo_destroy(&sna->kgem, video->bo[0]); 142 video->bo[0] = NULL; 143 144 sna_video_free_buffers(video); 145 sna_window_set_port((WindowPtr)draw, NULL); 146 return Success; 147} 148 149static int 150sna_video_overlay_set_attribute(ddSetPortAttribute_ARGS) 151{ 152 struct sna_video *video = port->devPriv.ptr; 153 struct sna *sna = video->sna; 154 155 DBG(("%s: set(%lx) to %d\n", __FUNCTION__, (long)attribute, (int)value)); 156 if (attribute == xvBrightness) { 157 if ((value < -128) || (value > 127)) 158 return BadValue; 159 DBG(("%s: BRIGHTNESS %d -> %d\n", __FUNCTION__, 160 video->contrast, (int)value)); 161 video->brightness = value; 162 } else if (attribute == xvContrast) { 163 if ((value < 0) || (value > 255)) 164 return BadValue; 165 DBG(("%s: CONTRAST %d -> %d\n", __FUNCTION__, 166 video->contrast, (int)value)); 167 video->contrast = value; 168 } else if (attribute == xvSaturation) { 169 if ((value < 0) || (value > 1023)) 170 return BadValue; 171 DBG(("%s: SATURATION %d -> %d\n", __FUNCTION__, 172 video->saturation, (int)value)); 173 video->saturation = value; 174 } else if (attribute == xvPipe) { 175 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); 176 if ((value < -1) || (value >= xf86_config->num_crtc)) 177 return BadValue; 178 if (value < 0) 179 video->desired_crtc = NULL; 180 else 181 video->desired_crtc = xf86_config->crtc[value]; 182 } else if (attribute == xvAlwaysOnTop) { 183 DBG(("%s: ALWAYS_ON_TOP: %d -> %d\n", __FUNCTION__, 184 video->AlwaysOnTop, !!value)); 185 video->AlwaysOnTop = !!value; 186 } else if (attribute == xvGamma0 && HAS_GAMMA(sna)) { 187 video->gamma0 = value; 188 } else if (attribute == xvGamma1 && HAS_GAMMA(sna)) { 189 video->gamma1 = value; 190 } else if (attribute == xvGamma2 && HAS_GAMMA(sna)) { 191 video->gamma2 = value; 192 } else if (attribute == xvGamma3 && HAS_GAMMA(sna)) { 193 video->gamma3 = value; 194 } else if (attribute == xvGamma4 && HAS_GAMMA(sna)) { 195 video->gamma4 = value; 196 } else if (attribute == xvGamma5 && HAS_GAMMA(sna)) { 197 video->gamma5 = value; 198 } else if (attribute == xvColorKey) { 199 video->color_key = value; 200 RegionEmpty(&video->clip); 201 DBG(("COLORKEY\n")); 202 } else 203 return BadMatch; 204 205 if ((attribute == xvGamma0 || 206 attribute == xvGamma1 || 207 attribute == xvGamma2 || 208 attribute == xvGamma3 || 209 attribute == xvGamma4 || 210 attribute == xvGamma5) && HAS_GAMMA(sna)) { 211 DBG(("%s: GAMMA\n", __FUNCTION__)); 212 } 213 214 if (!sna_video_overlay_update_attrs(video)) 215 return BadValue; 216 217 return Success; 218} 219 220static int 221sna_video_overlay_get_attribute(ddGetPortAttribute_ARGS) 222{ 223 struct sna_video *video = port->devPriv.ptr; 224 struct sna *sna = video->sna; 225 226 if (attribute == xvBrightness) { 227 *value = video->brightness; 228 } else if (attribute == xvContrast) { 229 *value = video->contrast; 230 } else if (attribute == xvSaturation) { 231 *value = video->saturation; 232 } else if (attribute == xvPipe) { 233 int c; 234 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); 235 for (c = 0; c < xf86_config->num_crtc; c++) 236 if (xf86_config->crtc[c] == video->desired_crtc) 237 break; 238 if (c == xf86_config->num_crtc) 239 c = -1; 240 *value = c; 241 } else if (attribute == xvAlwaysOnTop) { 242 *value = video->AlwaysOnTop; 243 } else if (attribute == xvGamma0 && HAS_GAMMA(sna)) { 244 *value = video->gamma0; 245 } else if (attribute == xvGamma1 && HAS_GAMMA(sna)) { 246 *value = video->gamma1; 247 } else if (attribute == xvGamma2 && HAS_GAMMA(sna)) { 248 *value = video->gamma2; 249 } else if (attribute == xvGamma3 && HAS_GAMMA(sna)) { 250 *value = video->gamma3; 251 } else if (attribute == xvGamma4 && HAS_GAMMA(sna)) { 252 *value = video->gamma4; 253 } else if (attribute == xvGamma5 && HAS_GAMMA(sna)) { 254 *value = video->gamma5; 255 } else if (attribute == xvColorKey) { 256 *value = video->color_key; 257 } else 258 return BadMatch; 259 260 return Success; 261} 262 263static int 264sna_video_overlay_best_size(ddQueryBestSize_ARGS) 265{ 266 struct sna_video *video = port->devPriv.ptr; 267 struct sna *sna = video->sna; 268 short max_w, max_h; 269 270 if (vid_w > (drw_w << 1) || vid_h > (drw_h << 1)){ 271 drw_w = vid_w >> 1; 272 drw_h = vid_h >> 1; 273 } 274 275 if (sna->kgem.gen < 021) { 276 max_w = IMAGE_MAX_WIDTH_LEGACY; 277 max_h = IMAGE_MAX_HEIGHT_LEGACY; 278 } else { 279 max_w = IMAGE_MAX_WIDTH; 280 max_h = IMAGE_MAX_HEIGHT; 281 } 282 283 while (drw_w > max_w || drw_h > max_h) { 284 drw_w >>= 1; 285 drw_h >>= 1; 286 } 287 288 *p_w = drw_w; 289 *p_h = drw_h; 290 return Success; 291} 292 293static void 294update_dst_box_to_crtc_coords(struct sna *sna, xf86CrtcPtr crtc, BoxPtr dstBox) 295{ 296 ScrnInfoPtr scrn = sna->scrn; 297 int tmp; 298 299 /* for overlay, we should take it from crtc's screen 300 * coordinate to current crtc's display mode. 301 * yeah, a bit confusing. 302 */ 303 switch (crtc->rotation & 0xf) { 304 case RR_Rotate_0: 305 dstBox->x1 -= crtc->x; 306 dstBox->x2 -= crtc->x; 307 dstBox->y1 -= crtc->y; 308 dstBox->y2 -= crtc->y; 309 break; 310 case RR_Rotate_90: 311 tmp = dstBox->x1; 312 dstBox->x1 = dstBox->y1 - crtc->x; 313 dstBox->y1 = scrn->virtualX - tmp - crtc->y; 314 tmp = dstBox->x2; 315 dstBox->x2 = dstBox->y2 - crtc->x; 316 dstBox->y2 = scrn->virtualX - tmp - crtc->y; 317 tmp = dstBox->y1; 318 dstBox->y1 = dstBox->y2; 319 dstBox->y2 = tmp; 320 break; 321 case RR_Rotate_180: 322 tmp = dstBox->x1; 323 dstBox->x1 = scrn->virtualX - dstBox->x2 - crtc->x; 324 dstBox->x2 = scrn->virtualX - tmp - crtc->x; 325 tmp = dstBox->y1; 326 dstBox->y1 = scrn->virtualY - dstBox->y2 - crtc->y; 327 dstBox->y2 = scrn->virtualY - tmp - crtc->y; 328 break; 329 case RR_Rotate_270: 330 tmp = dstBox->x1; 331 dstBox->x1 = scrn->virtualY - dstBox->y1 - crtc->x; 332 dstBox->y1 = tmp - crtc->y; 333 tmp = dstBox->x2; 334 dstBox->x2 = scrn->virtualY - dstBox->y2 - crtc->x; 335 dstBox->y2 = tmp - crtc->y; 336 tmp = dstBox->x1; 337 dstBox->x1 = dstBox->x2; 338 dstBox->x2 = tmp; 339 break; 340 } 341 342 return; 343} 344 345static bool 346sna_video_overlay_show(struct sna *sna, 347 struct sna_video *video, 348 struct sna_video_frame *frame, 349 xf86CrtcPtr crtc, 350 BoxPtr dstBox, 351 short src_w, short src_h, 352 short drw_w, short drw_h) 353{ 354 struct drm_intel_overlay_put_image request; 355 bool planar = is_planar_fourcc(frame->id); 356 float scale; 357 358 DBG(("%s: src=(%dx%d), dst=(%dx%d)\n", __FUNCTION__, 359 src_w, src_h, drw_w, drw_h)); 360 361 update_dst_box_to_crtc_coords(sna, crtc, dstBox); 362 if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 363 int tmp; 364 365 tmp = frame->width; 366 frame->width = frame->height; 367 frame->height = tmp; 368 369 tmp = drw_w; 370 drw_w = drw_h; 371 drw_h = tmp; 372 373 tmp = src_w; 374 src_w = src_h; 375 src_h = tmp; 376 } 377 378 memset(&request, 0, sizeof(request)); 379 request.flags = I915_OVERLAY_ENABLE; 380 381 request.bo_handle = frame->bo->handle; 382 if (planar) { 383 request.stride_Y = frame->pitch[1]; 384 request.stride_UV = frame->pitch[0]; 385 } else { 386 request.stride_Y = frame->pitch[0]; 387 request.stride_UV = 0; 388 } 389 request.offset_Y = 0; 390 request.offset_U = frame->UBufOffset; 391 request.offset_V = frame->VBufOffset; 392 DBG(("%s: handle=%d, stride_Y=%d, stride_UV=%d, off_Y: %i, off_U: %i, off_V: %i\n", 393 __FUNCTION__, 394 request.bo_handle, request.stride_Y, request.stride_UV, 395 request.offset_Y, request.offset_U, request.offset_V)); 396 397 request.crtc_id = sna_crtc_id(crtc); 398 request.dst_x = dstBox->x1; 399 request.dst_y = dstBox->y1; 400 request.dst_width = dstBox->x2 - dstBox->x1; 401 request.dst_height = dstBox->y2 - dstBox->y1; 402 403 DBG(("%s: crtc=%d, dst=(%d, %d)x(%d, %d)\n", 404 __FUNCTION__, request.crtc_id, 405 request.dst_x, request.dst_y, 406 request.dst_width, request.dst_height)); 407 408 request.src_width = frame->width; 409 request.src_height = frame->height; 410 /* adjust src dimensions */ 411 if (request.dst_height > 1) { 412 scale = ((float)request.dst_height - 1) / ((float)drw_h - 1); 413 request.src_scan_height = src_h * scale; 414 } else 415 request.src_scan_height = 1; 416 417 if (request.dst_width > 1) { 418 scale = ((float)request.dst_width - 1) / ((float)drw_w - 1); 419 request.src_scan_width = src_w * scale; 420 } else 421 request.src_scan_width = 1; 422 423 DBG(("%s: src=(%d, %d) scan=(%d, %d)\n", 424 __FUNCTION__, 425 request.src_width, request.src_height, 426 request.src_scan_width, request.src_scan_height)); 427 428 if (planar) { 429 request.flags |= I915_OVERLAY_YUV_PLANAR | I915_OVERLAY_YUV420; 430 } else { 431 request.flags |= I915_OVERLAY_YUV_PACKED | I915_OVERLAY_YUV422; 432 if (frame->id == FOURCC_UYVY) 433 request.flags |= I915_OVERLAY_Y_SWAP; 434 } 435 436 DBG(("%s: flags=%x\n", __FUNCTION__, request.flags)); 437 438 if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_OVERLAY_PUT_IMAGE, &request)) { 439 DBG(("%s: Putimage failed\n", __FUNCTION__)); 440 return false; 441 } 442 443 if (video->bo[0] != frame->bo) { 444 if (video->bo[0]) 445 kgem_bo_destroy(&sna->kgem, video->bo[0]); 446 video->bo[0] = kgem_bo_reference(frame->bo); 447 } 448 449 return true; 450} 451 452static int 453sna_video_overlay_put_image(ddPutImage_ARGS) 454{ 455 struct sna_video *video = port->devPriv.ptr; 456 struct sna *sna = video->sna; 457 struct sna_video_frame frame; 458 xf86CrtcPtr crtc; 459 BoxRec dstBox; 460 RegionRec clip; 461 int ret; 462 463 DBG(("%s: src: (%d,%d)(%d,%d), dst: (%d,%d)(%d,%d), width %d, height %d\n", 464 __FUNCTION__, 465 src_x, src_y, src_w, src_h, drw_x, 466 drw_y, drw_w, drw_h, width, height)); 467 468 /* If dst width and height are less than 1/8th the src size, the 469 * src/dst scale factor becomes larger than 8 and doesn't fit in 470 * the scale register. */ 471 if (src_w >= (drw_w * 8)) 472 drw_w = src_w / 7; 473 474 if (src_h >= (drw_h * 8)) 475 drw_h = src_h / 7; 476 477 clip.extents.x1 = draw->x + drw_x; 478 clip.extents.y1 = draw->y + drw_y; 479 clip.extents.x2 = clip.extents.x1 + drw_w; 480 clip.extents.y2 = clip.extents.y1 + drw_h; 481 clip.data = NULL; 482 483 DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop)); 484 if (!video->AlwaysOnTop) 485 RegionIntersect(&clip, &clip, gc->pCompositeClip); 486 if (box_empty(&clip.extents)) 487 goto invisible; 488 489 DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n", 490 __FUNCTION__, 491 src_x, src_y, src_w, src_h, 492 drw_x, drw_y, drw_w, drw_h, 493 format->id, width, height, sync)); 494 495 DBG(("%s: region %d:(%d, %d), (%d, %d)\n", __FUNCTION__, 496 region_num_rects(&clip), 497 clip.extents.x1, clip.extents.y1, 498 clip.extents.x2, clip.extents.y2)); 499 500 sna_video_frame_init(video, format->id, width, height, &frame); 501 502 if (!sna_video_clip_helper(video, &frame, &crtc, &dstBox, 503 src_x, src_y, draw->x + drw_x, draw->y + drw_y, 504 src_w, src_h, drw_w, drw_h, 505 &clip)) 506 goto invisible; 507 508 if (!crtc) 509 goto invisible; 510 511 /* overlay can't handle rotation natively, store it for the copy func */ 512 sna_video_frame_set_rotation(video, &frame, crtc->rotation); 513 514 if (xvmc_passthrough(format->id)) { 515 DBG(("%s: using passthough, name=%d\n", 516 __FUNCTION__, *(uint32_t *)buf)); 517 518 if (*(uint32_t*)buf == 0) 519 goto invisible; 520 521 frame.bo = kgem_create_for_name(&sna->kgem, *(uint32_t*)buf); 522 if (frame.bo == NULL) { 523 DBG(("%s: failed to open bo\n", __FUNCTION__)); 524 return BadAlloc; 525 } 526 527 if (kgem_bo_size(frame.bo) < frame.size) { 528 DBG(("%s: bo size=%d, expected=%d\n", 529 __FUNCTION__, kgem_bo_size(frame.bo), frame.size)); 530 kgem_bo_destroy(&sna->kgem, frame.bo); 531 return BadAlloc; 532 } 533 534 frame.image.x1 = 0; 535 frame.image.y1 = 0; 536 frame.image.x2 = frame.width; 537 frame.image.y2 = frame.height; 538 } else { 539 frame.bo = sna_video_buffer(video, &frame); 540 if (frame.bo == NULL) { 541 DBG(("%s: failed to allocate video bo\n", __FUNCTION__)); 542 return BadAlloc; 543 } 544 545 if (!sna_video_copy_data(video, &frame, buf)) { 546 DBG(("%s: failed to copy video data\n", __FUNCTION__)); 547 return BadAlloc; 548 } 549 } 550 551 ret = Success; 552 if (sna_video_overlay_show 553 (sna, video, &frame, crtc, &dstBox, src_w, src_h, drw_w, drw_h)) { 554 //xf86XVFillKeyHelperDrawable(draw, video->color_key, &clip); 555 if (!video->AlwaysOnTop && !RegionEqual(&video->clip, &clip) && 556 sna_blt_fill_boxes(sna, GXcopy, 557 __sna_pixmap_get_bo(sna->front), 558 sna->front->drawable.bitsPerPixel, 559 video->color_key, 560 region_rects(&clip), 561 region_num_rects(&clip))) 562 RegionCopy(&video->clip, &clip); 563 sna_window_set_port((WindowPtr)draw, port); 564 } else { 565 DBG(("%s: failed to show video frame\n", __FUNCTION__)); 566 ret = BadAlloc; 567 } 568 569 frame.bo->domain = DOMAIN_NONE; 570 if (xvmc_passthrough(format->id)) 571 kgem_bo_destroy(&sna->kgem, frame.bo); 572 else 573 sna_video_buffer_fini(video); 574 575 return ret; 576 577invisible: 578 /* 579 * If the video isn't visible on any CRTC, turn it off 580 */ 581#if XORG_XV_VERSION < 2 582 sna_video_overlay_stop(client, port, draw); 583#else 584 sna_video_overlay_stop(port, draw); 585#endif 586 return Success; 587} 588 589static int 590sna_video_overlay_query(ddQueryImageAttributes_ARGS) 591{ 592 struct sna_video *video = port->devPriv.ptr; 593 struct sna_video_frame frame; 594 struct sna *sna = video->sna; 595 int size, tmp; 596 597 DBG(("%s: w is %d, h is %d\n", __FUNCTION__, *w, *h)); 598 599 if (sna->kgem.gen < 021) { 600 if (*w > IMAGE_MAX_WIDTH_LEGACY) 601 *w = IMAGE_MAX_WIDTH_LEGACY; 602 if (*h > IMAGE_MAX_HEIGHT_LEGACY) 603 *h = IMAGE_MAX_HEIGHT_LEGACY; 604 } else { 605 if (*w > IMAGE_MAX_WIDTH) 606 *w = IMAGE_MAX_WIDTH; 607 if (*h > IMAGE_MAX_HEIGHT) 608 *h = IMAGE_MAX_HEIGHT; 609 } 610 611 *w = (*w + 1) & ~1; 612 if (offsets) 613 offsets[0] = 0; 614 615 switch (format->id) { 616 case FOURCC_XVMC: 617 *h = (*h + 1) & ~1; 618 sna_video_frame_init(video, format->id, *w, *h, &frame); 619 sna_video_frame_set_rotation(video, &frame, RR_Rotate_0); 620 size = sizeof(uint32_t); 621 if (pitches) { 622 pitches[0] = frame.pitch[1]; 623 pitches[1] = frame.pitch[0]; 624 pitches[2] = frame.pitch[0]; 625 } 626 if (offsets) { 627 offsets[1] = frame.UBufOffset; 628 offsets[2] = frame.VBufOffset; 629 } 630 break; 631 632 /* IA44 is for XvMC only */ 633 case FOURCC_IA44: 634 case FOURCC_AI44: 635 if (pitches) 636 pitches[0] = *w; 637 size = *w * *h; 638 break; 639 case FOURCC_YV12: 640 case FOURCC_I420: 641 *h = (*h + 1) & ~1; 642 size = (*w + 3) & ~3; 643 if (pitches) 644 pitches[0] = size; 645 size *= *h; 646 if (offsets) 647 offsets[1] = size; 648 tmp = ((*w >> 1) + 3) & ~3; 649 if (pitches) 650 pitches[1] = pitches[2] = tmp; 651 tmp *= (*h >> 1); 652 size += tmp; 653 if (offsets) 654 offsets[2] = size; 655 size += tmp; 656#if 0 657 if (pitches) 658 ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", 659 pitches[0], pitches[1], pitches[2]); 660 if (offsets) 661 ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], 662 offsets[2]); 663 if (offsets) 664 ErrorF("size is %d\n", size); 665#endif 666 break; 667 case FOURCC_UYVY: 668 case FOURCC_YUY2: 669 default: 670 size = *w << 1; 671 if (pitches) 672 pitches[0] = size; 673 size *= *h; 674 break; 675 } 676 677 return size; 678} 679 680static int sna_video_overlay_color_key(struct sna *sna) 681{ 682 ScrnInfoPtr scrn = sna->scrn; 683 int color_key; 684 685 if (xf86GetOptValInteger(sna->Options, OPTION_VIDEO_KEY, 686 &color_key)) { 687 } else if (xf86GetOptValInteger(sna->Options, OPTION_COLOR_KEY, 688 &color_key)) { 689 } else { 690 color_key = 691 (1 << scrn->offset.red) | 692 (1 << scrn->offset.green) | 693 (((scrn->mask.blue >> scrn->offset.blue) - 1) << scrn->offset.blue); 694 } 695 696 return color_key & ((1 << scrn->depth) - 1); 697} 698 699void sna_video_overlay_setup(struct sna *sna, ScreenPtr screen) 700{ 701 XvAdaptorPtr adaptor; 702 struct sna_video *video; 703 XvPortPtr port; 704 705 if (sna->flags & SNA_IS_HOSTED) 706 return; 707 708 if (!sna_has_overlay(sna)) 709 return; 710 711 DBG(("%s()\n", __FUNCTION__)); 712 713 adaptor = sna_xv_adaptor_alloc(sna); 714 if (adaptor == NULL) 715 return; 716 717 video = calloc(1, sizeof(*video)); 718 port = calloc(1, sizeof(*port)); 719 if (video == NULL || port == NULL) { 720 free(video); 721 free(port); 722 sna->xv.num_adaptors--; 723 return; 724 } 725 726 adaptor->type = XvInputMask | XvImageMask; 727 adaptor->pScreen = screen; 728 adaptor->name = (char *)"Intel(R) Video Overlay"; 729 adaptor->nEncodings = 1; 730 adaptor->pEncodings = xnfalloc(sizeof(XvEncodingRec)); 731 adaptor->pEncodings[0].id = 0; 732 adaptor->pEncodings[0].pScreen = screen; 733 adaptor->pEncodings[0].name = (char *)"XV_IMAGE"; 734 adaptor->pEncodings[0].width = sna->kgem.gen < 021 ? IMAGE_MAX_WIDTH_LEGACY : IMAGE_MAX_WIDTH; 735 adaptor->pEncodings[0].height = sna->kgem.gen < 021 ? IMAGE_MAX_HEIGHT_LEGACY : IMAGE_MAX_HEIGHT; 736 adaptor->pEncodings[0].rate.numerator = 1; 737 adaptor->pEncodings[0].rate.denominator = 1; 738 adaptor->pFormats = Formats; 739 adaptor->nFormats = sna_xv_fixup_formats(screen, Formats, 740 ARRAY_SIZE(Formats)); 741 adaptor->nAttributes = NUM_ATTRIBUTES; 742 if (HAS_GAMMA(sna)) 743 adaptor->nAttributes += GAMMA_ATTRIBUTES; 744 adaptor->pAttributes = (XvAttributeRec *)Attributes; 745 adaptor->nImages = ARRAY_SIZE(Images); 746 adaptor->pImages = (XvImageRec *)Images; 747#if XORG_XV_VERSION < 2 748 adaptor->ddAllocatePort = sna_xv_alloc_port; 749 adaptor->ddFreePort = sna_xv_free_port; 750#endif 751 adaptor->ddPutVideo = NULL; 752 adaptor->ddPutStill = NULL; 753 adaptor->ddGetVideo = NULL; 754 adaptor->ddGetStill = NULL; 755 adaptor->ddStopVideo = sna_video_overlay_stop; 756 adaptor->ddSetPortAttribute = sna_video_overlay_set_attribute; 757 adaptor->ddGetPortAttribute = sna_video_overlay_get_attribute; 758 adaptor->ddQueryBestSize = sna_video_overlay_best_size; 759 adaptor->ddPutImage = sna_video_overlay_put_image; 760 adaptor->ddQueryImageAttributes = sna_video_overlay_query; 761 762 adaptor->nPorts = 1; 763 adaptor->pPorts = port; 764 adaptor->base_id = port->id = FakeClientID(0); 765 AddResource(port->id, XvGetRTPort(), port); 766 767 port->pAdaptor = adaptor; 768 port->pNotify = NULL; 769 port->pDraw = NULL; 770 port->client = NULL; 771 port->grab.client = NULL; 772 port->time = currentTime; 773 port->devPriv.ptr = video; 774 775 video->sna = sna; 776 if (sna->kgem.gen >= 040) 777 /* Actually the alignment is 64 bytes, too. But the 778 * stride must be at least 512 bytes. Take the easy fix 779 * and align on 512 bytes unconditionally. */ 780 video->alignment = 512; 781 else if (sna->kgem.gen < 021) 782 /* Harsh, errata on these chipsets limit the stride 783 * to be a multiple of 256 bytes. 784 */ 785 video->alignment = 256; 786 else 787 video->alignment = 64; 788 video->color_key = sna_video_overlay_color_key(sna); 789 video->brightness = -19; /* (255/219) * -16 */ 790 video->contrast = 75; /* 255/219 * 64 */ 791 video->saturation = 146; /* 128/112 * 128 */ 792 video->desired_crtc = NULL; 793 video->gamma5 = 0xc0c0c0; 794 video->gamma4 = 0x808080; 795 video->gamma3 = 0x404040; 796 video->gamma2 = 0x202020; 797 video->gamma1 = 0x101010; 798 video->gamma0 = 0x080808; 799 RegionNull(&video->clip); 800 801 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 802 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 803 xvContrast = MAKE_ATOM("XV_CONTRAST"); 804 xvSaturation = MAKE_ATOM("XV_SATURATION"); 805 806 /* Allow the pipe to be switched from pipe A to B when in clone mode */ 807 xvPipe = MAKE_ATOM("XV_PIPE"); 808 xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP"); 809 810 if (HAS_GAMMA(sna)) { 811 xvGamma0 = MAKE_ATOM("XV_GAMMA0"); 812 xvGamma1 = MAKE_ATOM("XV_GAMMA1"); 813 xvGamma2 = MAKE_ATOM("XV_GAMMA2"); 814 xvGamma3 = MAKE_ATOM("XV_GAMMA3"); 815 xvGamma4 = MAKE_ATOM("XV_GAMMA4"); 816 xvGamma5 = MAKE_ATOM("XV_GAMMA5"); 817 } 818 819 sna_video_overlay_update_attrs(video); 820 821 DBG(("%s: '%s' initialized %d ports\n", __FUNCTION__, adaptor->name, adaptor->nPorts)); 822} 823