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(to_screen_from_sna(sna), &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 init_video_region(&clip, draw, drw_x, drw_y, drw_w, drw_h); 478 479 DBG(("%s: always_on_top=%d\n", __FUNCTION__, video->AlwaysOnTop)); 480 if (!video->AlwaysOnTop) { 481 ValidateGC(draw, gc); 482 RegionIntersect(&clip, &clip, gc->pCompositeClip); 483 } 484 if (box_empty(&clip.extents)) 485 goto invisible; 486 487 DBG(("%s: src=(%d, %d),(%d, %d), dst=(%d, %d),(%d, %d), id=%d, sizep=%dx%d, sync?=%d\n", 488 __FUNCTION__, 489 src_x, src_y, src_w, src_h, 490 drw_x, drw_y, drw_w, drw_h, 491 format->id, width, height, sync)); 492 493 DBG(("%s: region %d:(%d, %d), (%d, %d)\n", __FUNCTION__, 494 region_num_rects(&clip), 495 clip.extents.x1, clip.extents.y1, 496 clip.extents.x2, clip.extents.y2)); 497 498 sna_video_frame_init(video, format->id, width, height, &frame); 499 500 if (!sna_video_clip_helper(video, &frame, &crtc, &dstBox, 501 src_x, src_y, draw->x + drw_x, draw->y + drw_y, 502 src_w, src_h, drw_w, drw_h, 503 &clip)) 504 goto invisible; 505 506 if (!crtc) 507 goto invisible; 508 509 /* overlay can't handle rotation natively, store it for the copy func */ 510 sna_video_frame_set_rotation(video, &frame, crtc->rotation); 511 512 if (xvmc_passthrough(format->id)) { 513 DBG(("%s: using passthough, name=%d\n", 514 __FUNCTION__, *(uint32_t *)buf)); 515 516 if (*(uint32_t*)buf == 0) 517 goto invisible; 518 519 frame.bo = kgem_create_for_name(&sna->kgem, *(uint32_t*)buf); 520 if (frame.bo == NULL) { 521 DBG(("%s: failed to open bo\n", __FUNCTION__)); 522 return BadAlloc; 523 } 524 525 if (kgem_bo_size(frame.bo) < frame.size) { 526 DBG(("%s: bo size=%d, expected=%d\n", 527 __FUNCTION__, kgem_bo_size(frame.bo), frame.size)); 528 kgem_bo_destroy(&sna->kgem, frame.bo); 529 return BadAlloc; 530 } 531 532 frame.image.x1 = 0; 533 frame.image.y1 = 0; 534 frame.image.x2 = frame.width; 535 frame.image.y2 = frame.height; 536 } else { 537 frame.bo = sna_video_buffer(video, &frame); 538 if (frame.bo == NULL) { 539 DBG(("%s: failed to allocate video bo\n", __FUNCTION__)); 540 return BadAlloc; 541 } 542 543 if (!sna_video_copy_data(video, &frame, buf)) { 544 DBG(("%s: failed to copy video data\n", __FUNCTION__)); 545 return BadAlloc; 546 } 547 } 548 549 ret = Success; 550 if (sna_video_overlay_show 551 (sna, video, &frame, crtc, &dstBox, src_w, src_h, drw_w, drw_h)) { 552 sna_video_fill_colorkey(video, &clip); 553 sna_window_set_port((WindowPtr)draw, port); 554 } else { 555 DBG(("%s: failed to show video frame\n", __FUNCTION__)); 556 ret = BadAlloc; 557 } 558 559 frame.bo->domain = DOMAIN_NONE; 560 if (xvmc_passthrough(format->id)) 561 kgem_bo_destroy(&sna->kgem, frame.bo); 562 else 563 sna_video_buffer_fini(video); 564 565 return ret; 566 567invisible: 568 /* 569 * If the video isn't visible on any CRTC, turn it off 570 */ 571#if XORG_XV_VERSION < 2 572 sna_video_overlay_stop(client, port, draw); 573#else 574 sna_video_overlay_stop(port, draw); 575#endif 576 return Success; 577} 578 579static int 580sna_video_overlay_query(ddQueryImageAttributes_ARGS) 581{ 582 struct sna_video *video = port->devPriv.ptr; 583 struct sna_video_frame frame; 584 struct sna *sna = video->sna; 585 int size, tmp; 586 587 DBG(("%s: w is %d, h is %d\n", __FUNCTION__, *w, *h)); 588 589 if (sna->kgem.gen < 021) { 590 if (*w > IMAGE_MAX_WIDTH_LEGACY) 591 *w = IMAGE_MAX_WIDTH_LEGACY; 592 if (*h > IMAGE_MAX_HEIGHT_LEGACY) 593 *h = IMAGE_MAX_HEIGHT_LEGACY; 594 } else { 595 if (*w > IMAGE_MAX_WIDTH) 596 *w = IMAGE_MAX_WIDTH; 597 if (*h > IMAGE_MAX_HEIGHT) 598 *h = IMAGE_MAX_HEIGHT; 599 } 600 601 *w = (*w + 1) & ~1; 602 if (offsets) 603 offsets[0] = 0; 604 605 switch (format->id) { 606 case FOURCC_XVMC: 607 *h = (*h + 1) & ~1; 608 sna_video_frame_init(video, format->id, *w, *h, &frame); 609 sna_video_frame_set_rotation(video, &frame, RR_Rotate_0); 610 size = sizeof(uint32_t); 611 if (pitches) { 612 pitches[0] = frame.pitch[1]; 613 pitches[1] = frame.pitch[0]; 614 pitches[2] = frame.pitch[0]; 615 } 616 if (offsets) { 617 offsets[1] = frame.UBufOffset; 618 offsets[2] = frame.VBufOffset; 619 } 620 break; 621 622 /* IA44 is for XvMC only */ 623 case FOURCC_IA44: 624 case FOURCC_AI44: 625 if (pitches) 626 pitches[0] = *w; 627 size = *w * *h; 628 break; 629 case FOURCC_YV12: 630 case FOURCC_I420: 631 *h = (*h + 1) & ~1; 632 size = (*w + 3) & ~3; 633 if (pitches) 634 pitches[0] = size; 635 size *= *h; 636 if (offsets) 637 offsets[1] = size; 638 tmp = ((*w >> 1) + 3) & ~3; 639 if (pitches) 640 pitches[1] = pitches[2] = tmp; 641 tmp *= (*h >> 1); 642 size += tmp; 643 if (offsets) 644 offsets[2] = size; 645 size += tmp; 646#if 0 647 if (pitches) 648 ErrorF("pitch 0 is %d, pitch 1 is %d, pitch 2 is %d\n", 649 pitches[0], pitches[1], pitches[2]); 650 if (offsets) 651 ErrorF("offset 1 is %d, offset 2 is %d\n", offsets[1], 652 offsets[2]); 653 if (offsets) 654 ErrorF("size is %d\n", size); 655#endif 656 break; 657 case FOURCC_UYVY: 658 case FOURCC_YUY2: 659 default: 660 size = *w << 1; 661 if (pitches) 662 pitches[0] = size; 663 size *= *h; 664 break; 665 } 666 667 return size; 668} 669 670static int sna_video_overlay_color_key(struct sna *sna) 671{ 672 ScrnInfoPtr scrn = sna->scrn; 673 int color_key; 674 675 if (xf86GetOptValInteger(sna->Options, OPTION_VIDEO_KEY, 676 &color_key)) { 677 } else if (xf86GetOptValInteger(sna->Options, OPTION_COLOR_KEY, 678 &color_key)) { 679 } else { 680 color_key = 681 (1 << scrn->offset.red) | 682 (1 << scrn->offset.green) | 683 (((scrn->mask.blue >> scrn->offset.blue) - 1) << scrn->offset.blue); 684 } 685 686 return color_key & ((1 << scrn->depth) - 1); 687} 688 689void sna_video_overlay_setup(struct sna *sna, ScreenPtr screen) 690{ 691 XvAdaptorPtr adaptor; 692 struct sna_video *video; 693 XvPortPtr port; 694 695 if (sna->flags & SNA_IS_HOSTED) 696 return; 697 698 if (!sna_has_overlay(sna)) 699 return; 700 701 DBG(("%s()\n", __FUNCTION__)); 702 703 adaptor = sna_xv_adaptor_alloc(sna); 704 if (adaptor == NULL) 705 return; 706 707 video = calloc(1, sizeof(*video)); 708 port = calloc(1, sizeof(*port)); 709 if (video == NULL || port == NULL) { 710 free(video); 711 free(port); 712 sna->xv.num_adaptors--; 713 return; 714 } 715 716 adaptor->type = XvInputMask | XvImageMask; 717 adaptor->pScreen = screen; 718 adaptor->name = (char *)"Intel(R) Video Overlay"; 719 adaptor->nEncodings = 1; 720 adaptor->pEncodings = xnfalloc(sizeof(XvEncodingRec)); 721 adaptor->pEncodings[0].id = 0; 722 adaptor->pEncodings[0].pScreen = screen; 723 adaptor->pEncodings[0].name = (char *)"XV_IMAGE"; 724 adaptor->pEncodings[0].width = sna->kgem.gen < 021 ? IMAGE_MAX_WIDTH_LEGACY : IMAGE_MAX_WIDTH; 725 adaptor->pEncodings[0].height = sna->kgem.gen < 021 ? IMAGE_MAX_HEIGHT_LEGACY : IMAGE_MAX_HEIGHT; 726 adaptor->pEncodings[0].rate.numerator = 1; 727 adaptor->pEncodings[0].rate.denominator = 1; 728 adaptor->pFormats = Formats; 729 adaptor->nFormats = sna_xv_fixup_formats(screen, Formats, 730 ARRAY_SIZE(Formats)); 731 adaptor->nAttributes = NUM_ATTRIBUTES; 732 if (HAS_GAMMA(sna)) 733 adaptor->nAttributes += GAMMA_ATTRIBUTES; 734 adaptor->pAttributes = (XvAttributeRec *)Attributes; 735 adaptor->nImages = ARRAY_SIZE(Images); 736 adaptor->pImages = (XvImageRec *)Images; 737#if XORG_XV_VERSION < 2 738 adaptor->ddAllocatePort = sna_xv_alloc_port; 739 adaptor->ddFreePort = sna_xv_free_port; 740#endif 741 adaptor->ddPutVideo = NULL; 742 adaptor->ddPutStill = NULL; 743 adaptor->ddGetVideo = NULL; 744 adaptor->ddGetStill = NULL; 745 adaptor->ddStopVideo = sna_video_overlay_stop; 746 adaptor->ddSetPortAttribute = sna_video_overlay_set_attribute; 747 adaptor->ddGetPortAttribute = sna_video_overlay_get_attribute; 748 adaptor->ddQueryBestSize = sna_video_overlay_best_size; 749 adaptor->ddPutImage = sna_video_overlay_put_image; 750 adaptor->ddQueryImageAttributes = sna_video_overlay_query; 751 752 adaptor->nPorts = 1; 753 adaptor->pPorts = port; 754 adaptor->base_id = port->id = FakeClientID(0); 755 AddResource(port->id, XvGetRTPort(), port); 756 757 port->pAdaptor = adaptor; 758 port->pNotify = NULL; 759 port->pDraw = NULL; 760 port->client = NULL; 761 port->grab.client = NULL; 762 port->time = currentTime; 763 port->devPriv.ptr = video; 764 765 video->sna = sna; 766 if (sna->kgem.gen >= 040) 767 /* Actually the alignment is 64 bytes, too. But the 768 * stride must be at least 512 bytes. Take the easy fix 769 * and align on 512 bytes unconditionally. */ 770 video->alignment = 512; 771 else if (sna->kgem.gen < 021) 772 /* Harsh, errata on these chipsets limit the stride 773 * to be a multiple of 256 bytes. 774 */ 775 video->alignment = 256; 776 else 777 video->alignment = 64; 778 video->color_key = sna_video_overlay_color_key(sna); 779 video->brightness = -19; /* (255/219) * -16 */ 780 video->contrast = 75; /* 255/219 * 64 */ 781 video->saturation = 146; /* 128/112 * 128 */ 782 video->desired_crtc = NULL; 783 video->gamma5 = 0xc0c0c0; 784 video->gamma4 = 0x808080; 785 video->gamma3 = 0x404040; 786 video->gamma2 = 0x202020; 787 video->gamma1 = 0x101010; 788 video->gamma0 = 0x080808; 789 RegionNull(&video->clip); 790 791 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 792 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 793 xvContrast = MAKE_ATOM("XV_CONTRAST"); 794 xvSaturation = MAKE_ATOM("XV_SATURATION"); 795 796 /* Allow the pipe to be switched from pipe A to B when in clone mode */ 797 xvPipe = MAKE_ATOM("XV_PIPE"); 798 xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP"); 799 800 if (HAS_GAMMA(sna)) { 801 xvGamma0 = MAKE_ATOM("XV_GAMMA0"); 802 xvGamma1 = MAKE_ATOM("XV_GAMMA1"); 803 xvGamma2 = MAKE_ATOM("XV_GAMMA2"); 804 xvGamma3 = MAKE_ATOM("XV_GAMMA3"); 805 xvGamma4 = MAKE_ATOM("XV_GAMMA4"); 806 xvGamma5 = MAKE_ATOM("XV_GAMMA5"); 807 } 808 809 sna_video_overlay_update_attrs(video); 810 811 DBG(("%s: '%s' initialized %d ports\n", __FUNCTION__, adaptor->name, adaptor->nPorts)); 812} 813