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