1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Jason Hu <jason.hu (at) intel.com> 26 * Zhaohan Ren <zhaohan.ren (at) intel.com> 27 * Shengquan Yuan <shengquan.yuan (at) intel.com> 28 * 29 */ 30 31 #include <X11/Xutil.h> 32 #include <X11/extensions/Xrandr.h> 33 #include <va/va_backend.h> 34 #include "psb_output.h" 35 #include "psb_surface.h" 36 #include "psb_buffer.h" 37 #include "psb_x11.h" 38 #include "psb_drv_debug.h" 39 40 #include <stdio.h> 41 #include <string.h> 42 #include <stdarg.h> 43 #include "psb_surface_ext.h" 44 #include <wsbm/wsbm_manager.h> 45 #include "psb_drv_video.h" 46 #include "psb_xrandr.h" 47 #include <sys/types.h> 48 49 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData 50 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv) 51 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 52 53 static int 54 psb_x11_getWindowCoordinate(Display * display, 55 Window x11_window_id, 56 psb_x11_win_t * psX11Window, 57 int * pbIsVisible) 58 { 59 Window DummyWindow; 60 Status status; 61 XWindowAttributes sXWinAttrib; 62 63 if ((status = XGetWindowAttributes(display, 64 x11_window_id, 65 &sXWinAttrib)) == 0) { 66 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates - error %lu\n", __func__, (unsigned long)status); 67 return -1; 68 } 69 70 psX11Window->i32Left = sXWinAttrib.x; 71 psX11Window->i32Top = sXWinAttrib.y; 72 psX11Window->ui32Width = sXWinAttrib.width; 73 psX11Window->ui32Height = sXWinAttrib.height; 74 *pbIsVisible = (sXWinAttrib.map_state == IsViewable); 75 76 if (!*pbIsVisible) 77 return 0; 78 79 if (XTranslateCoordinates(display, 80 x11_window_id, 81 DefaultRootWindow(display), 82 0, 83 0, 84 &psX11Window->i32Left, 85 &psX11Window->i32Top, 86 &DummyWindow) == 0) { 87 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to tranlate X coordinates - error %lu\n", __func__, (unsigned long)status); 88 return -1; 89 } 90 91 psX11Window->i32Right = psX11Window->i32Left + psX11Window->ui32Width - 1; 92 psX11Window->i32Bottom = psX11Window->i32Top + psX11Window->ui32Height - 1; 93 94 return 0; 95 } 96 static psb_x11_clip_list_t * 97 psb_x11_createClipBoxNode(psb_x11_win_t * pRect, 98 psb_x11_clip_list_t * pClipNext) 99 { 100 psb_x11_clip_list_t * pCurrent = NULL; 101 102 pCurrent = (psb_x11_clip_list_t *)calloc(1, sizeof(psb_x11_clip_list_t)); 103 if (pCurrent) { 104 pCurrent->rect = *pRect; 105 pCurrent->next = pClipNext; 106 107 return pCurrent; 108 } else 109 return pClipNext; 110 } 111 112 void 113 psb_x11_freeWindowClipBoxList(psb_x11_clip_list_t * pHead) 114 { 115 psb_x11_clip_list_t * pNext = NULL; 116 117 while (pHead) { 118 pNext = pHead->next; 119 free(pHead); 120 pHead = pNext; 121 } 122 } 123 124 #define IS_BETWEEN_RANGE(a,b,c) ((a<=b)&&(b<=c)) 125 126 static psb_x11_clip_list_t * 127 psb_x11_substractRects(Display * display, 128 psb_x11_clip_list_t * psRegion, 129 psb_x11_win_t * psRect) 130 { 131 psb_x11_clip_list_t * psCur, * psPrev, * psFirst, * psNext; 132 psb_x11_win_t sCreateRect; 133 int display_width = (int)(DisplayWidth(display, DefaultScreen(display))) - 1; 134 int display_height = (int)(DisplayHeight(display, DefaultScreen(display))) - 1; 135 136 psFirst = psb_x11_createClipBoxNode(psRect, NULL); 137 138 if (psFirst->rect.i32Left < 0) 139 psFirst->rect.i32Left = 0; 140 else if (psFirst->rect.i32Left > display_width) 141 psFirst->rect.i32Left = display_width; 142 143 if (psFirst->rect.i32Right < 0) 144 psFirst->rect.i32Right = 0; 145 else if (psFirst->rect.i32Right > display_width) 146 psFirst->rect.i32Right = display_width; 147 148 if (psFirst->rect.i32Top < 0) 149 psFirst->rect.i32Top = 0; 150 else if (psFirst->rect.i32Top > display_height) 151 psFirst->rect.i32Top = display_height; 152 153 if (psFirst->rect.i32Bottom < 0) 154 psFirst->rect.i32Bottom = 0; 155 else if (psFirst->rect.i32Bottom > display_height) 156 psFirst->rect.i32Bottom = display_height; 157 158 while (psRegion) { 159 psCur = psFirst; 160 psPrev = NULL; 161 162 while (psCur) { 163 psNext = psCur->next; 164 165 if ((psRegion->rect.i32Left > psCur->rect.i32Left) && 166 (psRegion->rect.i32Left <= psCur->rect.i32Right)) { 167 sCreateRect.i32Right = psRegion->rect.i32Left - 1; 168 169 sCreateRect.i32Left = psCur->rect.i32Left; 170 sCreateRect.i32Top = psCur->rect.i32Top; 171 sCreateRect.i32Bottom = psCur->rect.i32Bottom; 172 173 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst); 174 175 if (!psPrev) 176 psPrev = psFirst; 177 178 psCur->rect.i32Left = psRegion->rect.i32Left; 179 } 180 181 if ((psRegion->rect.i32Right >= psCur->rect.i32Left) && 182 (psRegion->rect.i32Right < psCur->rect.i32Right)) 183 184 { 185 sCreateRect.i32Left = psRegion->rect.i32Right + 1; 186 187 sCreateRect.i32Right = psCur->rect.i32Right; 188 sCreateRect.i32Top = psCur->rect.i32Top; 189 sCreateRect.i32Bottom = psCur->rect.i32Bottom; 190 191 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst); 192 193 if (!psPrev) 194 psPrev = psFirst; 195 196 psCur->rect.i32Right = psRegion->rect.i32Right; 197 } 198 199 if ((psRegion->rect.i32Top > psCur->rect.i32Top) && 200 (psRegion->rect.i32Top <= psCur->rect.i32Bottom)) { 201 sCreateRect.i32Bottom = psRegion->rect.i32Top - 1; 202 203 sCreateRect.i32Left = psCur->rect.i32Left; 204 sCreateRect.i32Right = psCur->rect.i32Right; 205 sCreateRect.i32Top = psCur->rect.i32Top; 206 207 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst); 208 209 if (!psPrev) 210 psPrev = psFirst; 211 212 psCur->rect.i32Top = psRegion->rect.i32Top; 213 } 214 215 if ((psRegion->rect.i32Bottom >= psCur->rect.i32Top) && 216 (psRegion->rect.i32Bottom < psCur->rect.i32Bottom)) { 217 sCreateRect.i32Top = psRegion->rect.i32Bottom + 1; 218 sCreateRect.i32Left = psCur->rect.i32Left; 219 sCreateRect.i32Right = psCur->rect.i32Right; 220 sCreateRect.i32Bottom = psCur->rect.i32Bottom; 221 222 psFirst = psb_x11_createClipBoxNode(&sCreateRect, psFirst); 223 224 if (!psPrev) 225 psPrev = psFirst; 226 227 psCur->rect.i32Bottom = psRegion->rect.i32Bottom; 228 } 229 230 if ((IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Left, psRegion->rect.i32Right)) && 231 (IS_BETWEEN_RANGE(psRegion->rect.i32Left, psCur->rect.i32Right, psRegion->rect.i32Right)) && 232 (IS_BETWEEN_RANGE(psRegion->rect.i32Top, psCur->rect.i32Top, psRegion->rect.i32Bottom)) && 233 (IS_BETWEEN_RANGE(psRegion->rect.i32Top, psCur->rect.i32Bottom, psRegion->rect.i32Bottom))) { 234 if (psPrev) { 235 psPrev->next = psCur->next; 236 free(psCur); 237 psCur = psPrev; 238 } else { 239 free(psCur); 240 psCur = NULL; 241 psFirst = psNext; 242 } 243 } 244 psPrev = psCur; 245 psCur = psNext; 246 }//while(psCur) 247 psRegion = psRegion->next; 248 }//while(psRegion) 249 250 return psFirst; 251 } 252 253 static int 254 psb_x11_createWindowClipBoxList(Display * display, 255 Window x11_window_id, 256 psb_x11_clip_list_t ** ppWindowClipBoxList, 257 unsigned int * pui32NumClipBoxList) 258 { 259 Window CurrentWindow = x11_window_id; 260 Window RootWindow, ParentWindow, ChildWindow; 261 Window * pChildWindow; 262 Status XResult; 263 unsigned int i32NumChildren, i; 264 int bIsVisible; 265 unsigned int ui32NumRects = 0; 266 psb_x11_clip_list_t *psRegions = NULL; 267 psb_x11_win_t sRect; 268 269 if (!display || (!ppWindowClipBoxList) || (!pui32NumClipBoxList)) 270 return -1; 271 272 XResult = XQueryTree(display, 273 CurrentWindow, 274 &RootWindow, 275 &ParentWindow, 276 &pChildWindow, 277 &i32NumChildren); 278 if (XResult == 0) 279 return -2; 280 281 if (i32NumChildren) { 282 for (i = 0; i < i32NumChildren; i++) { 283 284 psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible); 285 if (bIsVisible) { 286 psRegions = psb_x11_createClipBoxNode(&sRect, psRegions); 287 ui32NumRects++; 288 } 289 } 290 XFree(pChildWindow); 291 i32NumChildren = 0; 292 } 293 294 while (CurrentWindow != RootWindow) { 295 ChildWindow = CurrentWindow; 296 CurrentWindow = ParentWindow; 297 298 XResult = XQueryTree(display, 299 CurrentWindow, 300 &RootWindow, 301 &ParentWindow, 302 &pChildWindow, 303 &i32NumChildren); 304 if (XResult == 0) { 305 if (i32NumChildren) 306 XFree(pChildWindow); 307 308 psb_x11_freeWindowClipBoxList(psRegions); 309 return -3; 310 } 311 312 if (i32NumChildren) { 313 unsigned int iStartWindow = 0; 314 315 for (i = 0; i < i32NumChildren; i++) { 316 if (pChildWindow[i] == ChildWindow) { 317 iStartWindow = i; 318 break; 319 } 320 } 321 322 if (i == i32NumChildren) { 323 XFree(pChildWindow); 324 psb_x11_freeWindowClipBoxList(psRegions); 325 return -4; 326 } 327 328 for (i = iStartWindow + 1; i < i32NumChildren; i++) { 329 psb_x11_getWindowCoordinate(display, pChildWindow[i], &sRect, &bIsVisible); 330 if (bIsVisible) { 331 psRegions = psb_x11_createClipBoxNode(&sRect, psRegions); 332 ui32NumRects++; 333 } 334 } 335 336 XFree(pChildWindow); 337 } 338 } 339 340 ui32NumRects = 0; 341 342 if (psRegions) { 343 psb_x11_getWindowCoordinate(display, x11_window_id, &sRect, &bIsVisible); 344 *ppWindowClipBoxList = psb_x11_substractRects(display, psRegions, &sRect); 345 psb_x11_freeWindowClipBoxList(psRegions); 346 347 psRegions = *ppWindowClipBoxList; 348 349 while (psRegions) { 350 ui32NumRects++; 351 psRegions = psRegions->next; 352 } 353 } else { 354 *ppWindowClipBoxList = psb_x11_substractRects(display, NULL, &sRect); 355 ui32NumRects = 1; 356 } 357 358 *pui32NumClipBoxList = ui32NumRects; 359 360 return 0; 361 } 362 363 static int psb_cleardrawable_stopoverlay( 364 VADriverContextP ctx, 365 Drawable draw, /* X Drawable */ 366 short destx, 367 short desty, 368 unsigned short destw, 369 unsigned short desth 370 ) 371 { 372 INIT_DRIVER_DATA; 373 INIT_OUTPUT_PRIV; 374 375 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth); 376 XSync((Display *)ctx->native_dpy, False); 377 378 driver_data->cur_displaying_surface = VA_INVALID_SURFACE; 379 driver_data->last_displaying_surface = VA_INVALID_SURFACE; 380 381 return 0; 382 } 383 384 static VAStatus psb_DisplayRGBASubpicture( 385 PsbVASurfaceRec *subpicture, 386 VADriverContextP ctx, 387 int win_width, 388 int win_height, 389 int surface_x, 390 int surface_y, 391 int surface_w, 392 int surface_h, 393 psb_extvideo_subtitle subtitle 394 ) 395 { 396 INIT_DRIVER_DATA; 397 INIT_OUTPUT_PRIV; 398 XImage *ximg = NULL; 399 Visual *visual; 400 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 401 struct _WsbmBufferObject *bo = subpicture->bo; 402 int image_width, image_height, width, height, size; 403 int srcx, srcy, srcw, srch; 404 int destx, desty, destw, desth; 405 int depth, i; 406 407 if (subpicture->fourcc != VA_FOURCC_RGBA) { 408 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid image format, ONLY support RGBA subpicture now.\n", __func__); 409 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 410 } 411 412 for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) { 413 srcx = subpicture->subpic_srcx; 414 srcy = subpicture->subpic_srcy; 415 srcw = subpicture->subpic_srcw; 416 srch = subpicture->subpic_srch; 417 418 destx = subpicture->subpic_dstx + surface_x; 419 desty = subpicture->subpic_dsty + surface_y; 420 destw = subpicture->subpic_dstw; 421 desth = subpicture->subpic_dsth; 422 423 image_width = subpicture->width; 424 image_height = subpicture->height; 425 size = subpicture->size; 426 427 //clip in image region 428 if (srcx < 0) { 429 srcw += srcx; 430 srcx = 0; 431 } 432 433 if (srcy < 0) { 434 srch += srcy; 435 srcy = 0; 436 } 437 438 if ((srcx + srcw) > image_width) 439 srcw = image_width - srcx; 440 if ((srcy + srch) > image_height) 441 srch = image_height - srcy; 442 443 //clip in drawable region 444 if (destx < 0) { 445 destw += destx; 446 destx = 0; 447 } 448 449 if (desty < 0) { 450 desth += desty; 451 desty = 0; 452 } 453 454 if ((destx + destw) > surface_w) 455 destw = surface_w - destx; 456 if ((desty + desth) > surface_h) 457 desth = surface_h - desty; 458 459 if (srcw <= destw) 460 width = srcw; 461 else 462 width = destw; 463 464 if (srch <= desth) 465 height = srch; 466 else 467 height = desth; 468 469 visual = DefaultVisual(ctx->native_dpy, 0); 470 depth = DefaultDepth(ctx->native_dpy, 0); 471 472 ximg = XCreateImage(ctx->native_dpy, visual, depth, ZPixmap, 0, NULL, image_width, image_height, 32, 0); 473 474 if (NULL == ximg) { 475 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: XCreateImage failed! at L%d\n", __func__, __LINE__); 476 return VA_STATUS_ERROR_UNKNOWN; 477 } 478 479 ximg->data = wsbmBOMap(bo, WSBM_ACCESS_READ); 480 if (NULL == ximg->data) { 481 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to map to ximg->data.\n", __func__); 482 return VA_STATUS_ERROR_ALLOCATION_FAILED; 483 } 484 485 pPriv->clear_key[i].subpic_dstx = destx; 486 pPriv->clear_key[i].subpic_dsty = desty; 487 pPriv->clear_key[i].subpic_dstw = destw; 488 pPriv->clear_key[i].subpic_dsth = desth; 489 if (psb_xrandr_extvideo_mode()) { 490 /*It is a HACK: Adjust subtitle to proper position.*/ 491 float xScale, yScale; 492 493 xScale = win_width * 1.0 / surface_w; 494 yScale = win_height * 1.0 / surface_h; 495 destx = subpicture->subpic_dstx * xScale; 496 desty = subpicture->subpic_dsty * yScale; 497 } 498 XPutImage(ctx->native_dpy, output->output_drawable, output->gc, ximg, srcx, srcy, destx, desty, width, height); 499 XSync((Display *)ctx->native_dpy, False); 500 501 if (psb_xrandr_extvideo_mode() && 502 (subtitle == ONLY_HDMI || subtitle == BOTH)) { 503 float xScale, yScale; 504 505 xScale = pPriv->extend_display_width * 1.0 / surface_w; 506 yScale = pPriv->extend_display_height * 1.0 / surface_h; 507 508 destx = subpicture->subpic_dstx * xScale; 509 desty = subpicture->subpic_dsty * yScale; 510 511 XPutImage(ctx->native_dpy, output->extend_drawable, output->extend_gc, ximg, 512 srcx, srcy, destx, desty, destw, desth); 513 XSync((Display *)ctx->native_dpy, False); 514 } 515 516 pPriv->subpic_clear_flag = 0; 517 ximg->data = NULL; 518 wsbmBOUnmap(bo); 519 if (NULL != ximg) 520 XDestroyImage(ximg); 521 } 522 return VA_STATUS_SUCCESS; 523 } 524 525 static VAStatus psb_repaint_colorkey( 526 VADriverContextP ctx, 527 Drawable draw, /* X Drawable */ 528 VASurfaceID surface, 529 int x11_window_width, 530 int x11_window_height 531 ) 532 { 533 INIT_DRIVER_DATA; 534 INIT_OUTPUT_PRIV; 535 int i, ret; 536 psb_x11_clip_list_t *pClipNext = NULL; 537 VARectangle *pVaWindowClipRects = NULL; 538 object_surface_p obj_surface = SURFACE(surface); 539 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 540 541 if (output->frame_count % 500 == 0 || driver_data->xrandr_update) { 542 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Repaint color key.\n"); 543 if (output->pClipBoxList) 544 psb_x11_freeWindowClipBoxList(output->pClipBoxList); 545 /* get window clipbox */ 546 ret = psb_x11_createWindowClipBoxList(ctx->native_dpy, draw, &output->pClipBoxList, &output->ui32NumClipBoxList); 547 if (ret != 0) { 548 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: get window clip boxes error # %d\n", __func__, ret); 549 return VA_STATUS_ERROR_UNKNOWN; 550 } 551 if (output->frame_count == 500) 552 output->frame_count = 0; 553 554 driver_data->xrandr_update = 0; 555 } 556 557 pVaWindowClipRects = (VARectangle *)calloc(1, sizeof(VARectangle) * output->ui32NumClipBoxList); 558 if (!pVaWindowClipRects) { 559 psb_x11_freeWindowClipBoxList(output->pClipBoxList); 560 return VA_STATUS_ERROR_ALLOCATION_FAILED; 561 } 562 563 memset(pVaWindowClipRects, 0, sizeof(VARectangle)*output->ui32NumClipBoxList); 564 pClipNext = output->pClipBoxList; 565 #ifdef CLIP_DEBUG 566 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Total %d clip boxes\n", __func__, output->ui32NumClipBoxList); 567 #endif 568 for (i = 0; i < output->ui32NumClipBoxList; i++) { 569 pVaWindowClipRects[i].x = pClipNext->rect.i32Left; 570 pVaWindowClipRects[i].y = pClipNext->rect.i32Top; 571 pVaWindowClipRects[i].width = pClipNext->rect.i32Right - pClipNext->rect.i32Left; 572 pVaWindowClipRects[i].height = pClipNext->rect.i32Bottom - pClipNext->rect.i32Top; 573 #ifdef CLIP_DEBUG 574 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: clip boxes Left Top (%d, %d) Right Bottom (%d, %d) width %d height %d\n", __func__, 575 pClipNext->rect.i32Left, pClipNext->rect.i32Top, 576 pClipNext->rect.i32Right, pClipNext->rect.i32Bottom, 577 pVaWindowClipRects[i].width, pVaWindowClipRects[i].height); 578 #endif 579 pClipNext = pClipNext->next; 580 } 581 582 /* repaint the color key when window size changed*/ 583 if (!obj_surface->subpictures && 584 ((pPriv->x11_window_width != x11_window_width) || 585 (pPriv->x11_window_height != x11_window_height))) { 586 pPriv->x11_window_width = x11_window_width; 587 pPriv->x11_window_height = x11_window_height; 588 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey); 589 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height); 590 XSync((Display *)ctx->native_dpy, False); 591 } 592 593 594 if ((!obj_surface->subpictures) && 595 ((output->ui32NumClipBoxList != pPriv->last_num_clipbox) || 596 (memcmp(&pVaWindowClipRects[0], &(pPriv->last_clipbox[0]), (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle)) != 0))) { 597 pPriv->last_num_clipbox = output->ui32NumClipBoxList; 598 memcpy(&pPriv->last_clipbox[0], &pVaWindowClipRects[0], (output->ui32NumClipBoxList > 16 ? 16 : output->ui32NumClipBoxList)*sizeof(VARectangle)); 599 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height); 600 XSync((Display *)ctx->native_dpy, False); 601 } 602 603 free(pVaWindowClipRects); 604 605 return VA_STATUS_SUCCESS; 606 } 607 608 static VAStatus psb_extendMode_getCoordinate( 609 PsbPortPrivPtr pPriv, 610 psb_xrandr_location extend_location, 611 short destx, 612 short desty, 613 short srcx, 614 short srcy, 615 float xScaleFactor, 616 float yScaleFactor, 617 int *x11_window_width, 618 int *x11_window_height, 619 psb_overlay_rect_p local_rect, 620 psb_overlay_rect_p extend_rect, 621 enum overlay_id_t *extend_overlay 622 ) 623 { 624 switch (extend_location) { 625 case LEFT_OF: 626 if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) { 627 *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx; 628 } 629 if (((desty + *x11_window_height) < pPriv->display_height) && 630 ((desty + *x11_window_height) < pPriv->extend_display_height)) 631 local_rect->dHeight = extend_rect->dHeight = *x11_window_height; 632 else if (pPriv->display_height < pPriv->extend_display_height) { 633 local_rect->dHeight = pPriv->display_height - desty; 634 if ((desty + *x11_window_height) > pPriv->extend_display_height) 635 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty; 636 else 637 extend_rect->dHeight = *x11_window_height; 638 } else { 639 extend_rect->dHeight = pPriv->extend_display_height - desty; 640 if ((desty + *x11_window_height) > pPriv->display_height) 641 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty; 642 else 643 local_rect->dHeight = *x11_window_height; 644 } 645 646 if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) < pPriv->extend_display_width)) { 647 local_rect->dWidth = 0; 648 extend_rect->dWidth = *x11_window_width; 649 *extend_overlay = OVERLAY_A; 650 local_rect->destx = 0; 651 } else if ((destx < pPriv->extend_display_width) && ((destx + *x11_window_width) >= pPriv->extend_display_width)) { 652 extend_rect->dWidth = pPriv->extend_display_width - destx; 653 local_rect->dWidth = *x11_window_width - extend_rect->dWidth; 654 local_rect->destx = 0; 655 } else { 656 local_rect->dWidth = *x11_window_width; 657 extend_rect->dWidth = 0; 658 local_rect->destx = destx - pPriv->extend_display_width; 659 } 660 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor); 661 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor); 662 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor); 663 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor); 664 665 local_rect->srcx = srcx + extend_rect->sWidth; 666 extend_rect->srcx = srcx; 667 local_rect->srcy = extend_rect->srcy = srcy; 668 669 extend_rect->destx = destx; 670 local_rect->desty = extend_rect->desty = desty; 671 break; 672 case RIGHT_OF: 673 if ((destx + *x11_window_width) > (pPriv->display_width + pPriv->extend_display_width)) { 674 *x11_window_width = pPriv->display_width + pPriv->extend_display_width - destx; 675 } 676 if (((desty + *x11_window_height) < pPriv->display_height) && 677 ((desty + *x11_window_height) < pPriv->extend_display_height)) 678 local_rect->dHeight = extend_rect->dHeight = *x11_window_height; 679 else if (pPriv->display_height < pPriv->extend_display_height) { 680 local_rect->dHeight = pPriv->display_height - desty; 681 if ((desty + *x11_window_height) > pPriv->extend_display_height) 682 extend_rect->dHeight = *x11_window_height = pPriv->extend_display_height - desty; 683 else 684 extend_rect->dHeight = *x11_window_height; 685 } else { 686 extend_rect->dHeight = pPriv->extend_display_height - desty; 687 if ((desty + *x11_window_height) > pPriv->display_height) 688 local_rect->dHeight = *x11_window_height = pPriv->display_height - desty; 689 else 690 local_rect->dHeight = *x11_window_height; 691 } 692 693 if ((destx < pPriv->display_width) && ((destx + *x11_window_width) < pPriv->display_width)) { 694 local_rect->dWidth = *x11_window_width; 695 extend_rect->dWidth = 0; 696 extend_rect->destx = 0; 697 } else if ((destx < pPriv->display_width) && ((destx + *x11_window_width) >= pPriv->display_width)) { 698 local_rect->dWidth = pPriv->display_width - destx; 699 extend_rect->dWidth = *x11_window_width - local_rect->dWidth; 700 extend_rect->destx = 0; 701 } else { 702 local_rect->dWidth = 0; 703 extend_rect->dWidth = *x11_window_width; 704 *extend_overlay = OVERLAY_A; 705 extend_rect->destx = destx - pPriv->display_width; 706 } 707 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor); 708 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor); 709 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor); 710 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor); 711 712 local_rect->srcx = srcx; 713 extend_rect->srcx = srcx + local_rect->sWidth; 714 local_rect->srcy = extend_rect->srcy = srcy; 715 716 local_rect->destx = destx; 717 local_rect->desty = extend_rect->desty = desty; 718 break; 719 case ABOVE: 720 if (((destx + *x11_window_width) < pPriv->display_width) && 721 ((destx + *x11_window_width) < pPriv->extend_display_width)) 722 local_rect->dWidth = extend_rect->dWidth = *x11_window_width; 723 else if (pPriv->display_width < pPriv->extend_display_width) { 724 local_rect->dWidth = pPriv->display_width - destx; 725 if ((destx + *x11_window_width) > pPriv->extend_display_width) 726 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx; 727 else 728 extend_rect->dWidth = *x11_window_width; 729 } else { 730 extend_rect->dWidth = pPriv->extend_display_width - destx; 731 if ((destx + *x11_window_width) > pPriv->display_width) 732 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx; 733 else 734 local_rect->dWidth = *x11_window_width; 735 } 736 737 if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) { 738 *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty; 739 } 740 741 if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) < pPriv->extend_display_height)) { 742 local_rect->dHeight = 0; 743 extend_rect->dHeight = *x11_window_height; 744 *extend_overlay = OVERLAY_A; 745 local_rect->desty = 0; 746 } else if ((desty < pPriv->extend_display_height) && ((desty + *x11_window_height) >= pPriv->extend_display_height)) { 747 extend_rect->dHeight = pPriv->extend_display_height - desty; 748 local_rect->dHeight = *x11_window_height - extend_rect->dHeight; 749 local_rect->desty = 0; 750 } else { 751 local_rect->dHeight = *x11_window_height; 752 extend_rect->dHeight = 0; 753 local_rect->desty = desty - pPriv->extend_display_height; 754 } 755 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor); 756 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor); 757 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor); 758 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor); 759 760 local_rect->srcy = srcy + extend_rect->sHeight; 761 extend_rect->srcy = srcy; 762 local_rect->srcx = extend_rect->srcx = srcx; 763 764 extend_rect->desty = desty; 765 local_rect->destx = extend_rect->destx = destx; 766 break; 767 case BELOW: 768 if (((destx + *x11_window_width) < pPriv->display_width) && 769 ((destx + *x11_window_width) < pPriv->extend_display_width)) 770 local_rect->dWidth = extend_rect->dWidth = *x11_window_width; 771 else if (pPriv->display_width < pPriv->extend_display_width) { 772 local_rect->dWidth = pPriv->display_width - destx; 773 if ((destx + *x11_window_width) > pPriv->extend_display_width) 774 extend_rect->dWidth = *x11_window_width = pPriv->extend_display_width - destx; 775 else 776 extend_rect->dWidth = *x11_window_width; 777 } else { 778 extend_rect->dWidth = pPriv->extend_display_width - destx; 779 if ((destx + *x11_window_width) > pPriv->display_width) 780 local_rect->dWidth = *x11_window_width = pPriv->display_width - destx; 781 else 782 local_rect->dWidth = *x11_window_width; 783 } 784 785 if ((desty + *x11_window_height) > (pPriv->display_height + pPriv->extend_display_height)) { 786 *x11_window_height = pPriv->display_height + pPriv->extend_display_height - desty; 787 } 788 789 if ((desty < pPriv->display_height) && ((desty + *x11_window_height) < pPriv->display_height)) { 790 local_rect->dHeight = *x11_window_height; 791 extend_rect->dHeight = 0; 792 extend_rect->desty = 0; 793 } else if ((desty < pPriv->display_height) && ((desty + *x11_window_height) >= pPriv->display_height)) { 794 local_rect->dHeight = pPriv->display_height - desty; 795 extend_rect->dHeight = *x11_window_height - local_rect->dHeight; 796 extend_rect->desty = 0; 797 } else { 798 local_rect->dHeight = 0; 799 extend_rect->dHeight = *x11_window_height; 800 *extend_overlay = OVERLAY_A; 801 extend_rect->desty = desty - pPriv->display_height; 802 } 803 local_rect->sWidth = (unsigned short)(local_rect->dWidth * xScaleFactor); 804 local_rect->sHeight = (unsigned short)(local_rect->dHeight * yScaleFactor); 805 extend_rect->sWidth = (unsigned short)(extend_rect->dWidth * xScaleFactor); 806 extend_rect->sHeight = (unsigned short)(extend_rect->dHeight * yScaleFactor); 807 808 local_rect->srcy = srcy; 809 extend_rect->srcy = srcy + local_rect->sHeight; 810 local_rect->srcx = extend_rect->srcx = srcx; 811 812 local_rect->desty = desty; 813 local_rect->destx = extend_rect->destx = destx; 814 break; 815 case NORMAL: 816 default: 817 break; 818 } 819 return VA_STATUS_SUCCESS; 820 } 821 822 static void psb_init_subpicture(VADriverContextP ctx, PsbPortPrivPtr pPriv) 823 { 824 INIT_DRIVER_DATA; 825 struct drm_psb_register_rw_arg regs; 826 unsigned int subpicture_enable_mask = REGRWBITS_DSPACNTR; 827 828 if (!pPriv->subpicture_enabled) { 829 if (psb_xrandr_hdmi_enabled()) 830 subpicture_enable_mask |= REGRWBITS_DSPBCNTR; 831 if (psb_xrandr_mipi1_enabled()) 832 subpicture_enable_mask |= REGRWBITS_DSPCCNTR; 833 834 memset(®s, 0, sizeof(regs)); 835 regs.subpicture_enable_mask = subpicture_enable_mask; 836 pPriv->subpicture_enable_mask = subpicture_enable_mask; 837 pPriv->subpicture_enabled = 1; 838 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 839 } 840 } 841 842 static void psb_clear_subpictures( 843 VADriverContextP ctx, 844 PsbPortPrivPtr pPriv, 845 int win_width, 846 int win_height, 847 object_surface_p obj_surface 848 ) 849 { 850 INIT_OUTPUT_PRIV; 851 PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures; 852 int i; 853 854 if (subpicture == NULL) { 855 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Surface has no subpicture to render.\n"); 856 return; 857 } 858 859 for (i = 0; subpicture != NULL; subpicture = subpicture->next, i++) { 860 if ((subpicture->subpic_dstx != pPriv->clear_key[i].subpic_dstx) || 861 (subpicture->subpic_dsty != pPriv->clear_key[i].subpic_dsty) || 862 (subpicture->subpic_dstw != pPriv->clear_key[i].subpic_dstw) || 863 (subpicture->subpic_dsth != pPriv->clear_key[i].subpic_dsth)) { 864 XSetForeground((Display *)ctx->native_dpy, output->gc, 0); 865 XFillRectangle((Display *)ctx->native_dpy, output->output_drawable, output->gc, 0, 0, win_width, win_height); 866 XSync((Display *)ctx->native_dpy, False); 867 if (psb_xrandr_extvideo_mode()) { 868 XSetForeground((Display *)ctx->native_dpy, output->extend_gc, 0); 869 XFillRectangle((Display *)ctx->native_dpy, output->extend_drawable, output->extend_gc, 870 0, 0, pPriv->extend_display_width, pPriv->extend_display_height); 871 XSync((Display *)ctx->native_dpy, False); 872 } 873 pPriv->subpic_clear_flag = 1; 874 } 875 } 876 return; 877 } 878 879 VAStatus psb_putsurface_coverlay( 880 VADriverContextP ctx, 881 VASurfaceID surface, 882 Drawable draw, /* X Drawable */ 883 short srcx, 884 short srcy, 885 unsigned short srcw, 886 unsigned short srch, 887 short destx, 888 short desty, 889 unsigned short destw, 890 unsigned short desth, 891 VARectangle *cliprects, /* client supplied clip list */ 892 unsigned int number_cliprects, /* number of clip rects in the clip list */ 893 unsigned int flags /* de-interlacing flags */ 894 ) 895 { 896 INIT_DRIVER_DATA; 897 INIT_OUTPUT_PRIV; 898 int ret; 899 int x11_window_width = destw, x11_window_height = desth; 900 psb_xrandr_location extend_location; 901 object_surface_p obj_surface = SURFACE(surface); 902 PsbPortPrivRec *pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 903 int primary_crtc_x, primary_crtc_y, extend_crtc_x, extend_crtc_y; 904 enum pipe_id_t local_pipe = PIPEA, extend_pipe = PIPEB; 905 int surfacex = destx, surfacey = desty; 906 float xScaleFactor, yScaleFactor; 907 Rotation rotation = RR_Rotate_0; 908 psb_output_device local_device, extend_device; 909 psb_extvideo_subtitle subtitle; 910 911 if (flags & VA_CLEAR_DRAWABLE) { 912 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color); 913 psb_cleardrawable_stopoverlay(ctx, draw, destx, desty, destw, desth); 914 915 return VA_STATUS_SUCCESS; 916 } 917 918 if (output->frame_count % 500 == 0 || driver_data->xrandr_update) { 919 /* get window screen coordination */ 920 ret = psb_x11_getWindowCoordinate(ctx->native_dpy, draw, &output->winRect, &output->bIsVisible); 921 if (ret != 0) { 922 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get X11 window coordinates error # %d\n", __func__, ret); 923 return VA_STATUS_ERROR_UNKNOWN; 924 } 925 } 926 927 if (!output->bIsVisible) { 928 return VA_STATUS_SUCCESS; 929 } 930 931 if (NULL == obj_surface) { 932 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Invalid surface id 0x%08x.\n", __func__, surface); 933 return VA_STATUS_ERROR_INVALID_SURFACE; 934 } 935 936 if (output->output_drawable != draw) { 937 output->output_drawable = draw; 938 } 939 940 if (!output->gc) { 941 output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL); 942 /* paint the color key */ 943 if (!obj_surface->subpictures && !driver_data->overlay_auto_paint_color_key) { 944 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey); 945 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height); 946 XSync((Display *)ctx->native_dpy, False); 947 } 948 } 949 950 if (driver_data->use_xrandr_thread && !driver_data->xrandr_thread_id) { 951 ret = psb_xrandr_thread_create(ctx); 952 if (ret != 0) { 953 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to create psb xrandr thread error # %d\n", __func__, ret); 954 return VA_STATUS_ERROR_UNKNOWN; 955 } 956 } 957 958 ret = psb_xrandr_local_crtc_coordinate(&local_device, &primary_crtc_x, &primary_crtc_y, &pPriv->display_width, &pPriv->display_height, &rotation); 959 if (ret != VA_STATUS_SUCCESS) { 960 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get primary crtc coordinates error # %d\n", __func__, ret); 961 return VA_STATUS_ERROR_UNKNOWN; 962 } 963 switch (local_device) { 964 case LVDS0: 965 case MIPI0: 966 local_pipe = PIPEA; 967 break; 968 /* single HDMI */ 969 case HDMI: 970 local_pipe = PIPEB; 971 break; 972 case MIPI1: 973 local_pipe = PIPEC; 974 break; 975 } 976 977 if (!psb_xrandr_single_mode()) { 978 979 ret = psb_xrandr_extend_crtc_coordinate(&extend_device, &extend_crtc_x, &extend_crtc_y, 980 &pPriv->extend_display_width, &pPriv->extend_display_height, &extend_location, &rotation); 981 if (ret != VA_STATUS_SUCCESS) { 982 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend crtc coordinates error # %d\n", __func__, ret); 983 return VA_STATUS_ERROR_UNKNOWN; 984 } 985 986 switch (extend_device) { 987 case HDMI: 988 extend_pipe = PIPEB; 989 break; 990 case MIPI1: 991 extend_pipe = PIPEC; 992 break; 993 default: 994 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to get extend pipe\n", __func__); 995 break; 996 } 997 } 998 999 /*clip in the window area*/ 1000 if (destx < 0) { 1001 x11_window_width += destx; 1002 destx = 0; 1003 } 1004 1005 if (desty < 0) { 1006 x11_window_height += desty; 1007 desty = 0; 1008 } 1009 1010 if (srcx < 0) { 1011 srcw += srcx; 1012 srcx = 0; 1013 } 1014 1015 if (srcy < 0) { 1016 srch += srcy; 1017 srcy = 0; 1018 } 1019 1020 if ((destx + x11_window_width) > output->winRect.ui32Width) 1021 x11_window_width = output->winRect.ui32Width - destx; 1022 1023 if ((desty + x11_window_height) > output->winRect.ui32Height) 1024 x11_window_height = output->winRect.ui32Height - desty; 1025 1026 /*translate destx, desty into screen coordinate*/ 1027 destx += output->winRect.i32Left; 1028 desty += output->winRect.i32Top; 1029 1030 /*clip in the screen area*/ 1031 xScaleFactor = srcw * 1.0 / x11_window_width; 1032 yScaleFactor = srch * 1.0 / x11_window_height; 1033 1034 if (destx < 0) { 1035 x11_window_width += destx; 1036 srcx = (short)((-destx) * xScaleFactor); 1037 destx = 0; 1038 } 1039 1040 if (desty < 0) { 1041 x11_window_height += desty; 1042 srcy = (short)((-desty) * yScaleFactor); 1043 desty = 0; 1044 } 1045 1046 /* display by overlay */ 1047 if (psb_xrandr_single_mode() || IS_MRST(driver_data)) { 1048 if ((destx + x11_window_width) > pPriv->display_width) { 1049 x11_window_width = pPriv->display_width - destx; 1050 srcw = (unsigned short)(x11_window_width * xScaleFactor); 1051 } 1052 1053 if ((desty + x11_window_height) > pPriv->display_height) { 1054 x11_window_height = pPriv->display_height - desty; 1055 srch = (unsigned short)(x11_window_height * yScaleFactor); 1056 } 1057 1058 if (!driver_data->overlay_auto_paint_color_key) { 1059 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height); 1060 if (ret != 0) { 1061 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret); 1062 return VA_STATUS_ERROR_UNKNOWN; 1063 } 1064 } 1065 1066 psb_putsurface_overlay( 1067 ctx, surface, srcx, srcy, srcw, srch, 1068 /* screen coordinate */ 1069 destx, desty, x11_window_width, x11_window_height, 1070 flags, OVERLAY_A, local_pipe); 1071 } else if (psb_xrandr_clone_mode()) { 1072 psb_overlay_rect_t local_rect, extend_rect; 1073 1074 if (output->extend_drawable) { 1075 XDestroyWindow(ctx->native_dpy, output->extend_drawable); 1076 output->extend_drawable = 0; 1077 XFreeGC((Display *)ctx->native_dpy, output->extend_gc); 1078 output->extend_gc = 0; 1079 } 1080 1081 if (((destx + x11_window_width) < pPriv->display_width) && 1082 ((destx + x11_window_width) < pPriv->extend_display_width)) 1083 local_rect.dWidth = extend_rect.dWidth = x11_window_width; 1084 else if (pPriv->display_width < pPriv->extend_display_width) { 1085 local_rect.dWidth = pPriv->display_width - destx; 1086 if ((destx + x11_window_width) > pPriv->extend_display_width) 1087 extend_rect.dWidth = x11_window_width = pPriv->extend_display_width - destx; 1088 else 1089 extend_rect.dWidth = x11_window_width; 1090 } else { 1091 extend_rect.dWidth = pPriv->extend_display_width - destx; 1092 if ((destx + x11_window_width) > pPriv->display_width) 1093 local_rect.dWidth = x11_window_width = pPriv->display_width - destx; 1094 else 1095 local_rect.dWidth = x11_window_width; 1096 } 1097 1098 if (((desty + x11_window_height) < pPriv->display_height) && 1099 ((desty + x11_window_height) < pPriv->extend_display_height)) 1100 local_rect.dHeight = extend_rect.dHeight = x11_window_height; 1101 else if (pPriv->display_height < pPriv->extend_display_height) { 1102 local_rect.dHeight = pPriv->display_height - desty; 1103 if ((desty + x11_window_height) > pPriv->extend_display_height) 1104 extend_rect.dHeight = x11_window_height = pPriv->extend_display_height - desty; 1105 else 1106 extend_rect.dHeight = x11_window_height; 1107 } else { 1108 extend_rect.dHeight = pPriv->extend_display_height - desty; 1109 if ((desty + x11_window_height) > pPriv->display_height) 1110 local_rect.dHeight = x11_window_height = pPriv->display_height - desty; 1111 else 1112 local_rect.dHeight = x11_window_height; 1113 } 1114 if ((driver_data->mipi0_rotation != VA_ROTATION_NONE) || 1115 (driver_data->hdmi_rotation != VA_ROTATION_NONE)) { 1116 local_rect.sWidth = srcw; 1117 local_rect.sHeight = srch; 1118 extend_rect.sWidth = srcw; 1119 extend_rect.sHeight = srch; 1120 } else { 1121 local_rect.sWidth = (unsigned short)(local_rect.dWidth * xScaleFactor); 1122 local_rect.sHeight = (unsigned short)(local_rect.dHeight * yScaleFactor); 1123 extend_rect.sWidth = (unsigned short)(extend_rect.dWidth * xScaleFactor); 1124 extend_rect.sHeight = (unsigned short)(extend_rect.dHeight * yScaleFactor); 1125 } 1126 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height); 1127 if (ret != 0) { 1128 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret); 1129 return VA_STATUS_ERROR_UNKNOWN; 1130 } 1131 psb_putsurface_overlay( 1132 ctx, surface, srcx, srcy, extend_rect.sWidth, extend_rect.sHeight, 1133 /* screen coordinate */ 1134 destx, desty, extend_rect.dWidth, extend_rect.dHeight, 1135 flags, OVERLAY_C, extend_pipe); 1136 psb_putsurface_overlay( 1137 ctx, surface, srcx, srcy, local_rect.sWidth, local_rect.sHeight, 1138 /* screen coordinate */ 1139 destx, desty, local_rect.dWidth, local_rect.dHeight, 1140 flags, OVERLAY_A, local_pipe); 1141 } else if (psb_xrandr_extend_mode()) { 1142 if (driver_data->extend_fullscreen) { 1143 switch (extend_location) { 1144 case RIGHT_OF: 1145 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, pPriv->display_width, 0, pPriv->extend_display_width, pPriv->extend_display_height); 1146 break; 1147 case BELOW: 1148 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, pPriv->display_height, pPriv->extend_display_width, pPriv->extend_display_height); 1149 break; 1150 case LEFT_OF: 1151 case ABOVE: 1152 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height); 1153 break; 1154 default: 1155 break; 1156 1157 } 1158 XSetForeground((Display *)ctx->native_dpy, output->gc, pPriv->colorKey); 1159 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, pPriv->extend_display_width, pPriv->extend_display_height); 1160 XFlush(ctx->native_dpy); 1161 1162 psb_putsurface_overlay( 1163 ctx, surface, srcx, srcy, srcw, srch, 1164 /* screen coordinate */ 1165 0, 0, pPriv->extend_display_width, pPriv->extend_display_height, 1166 flags, OVERLAY_A, PIPEB); 1167 } else { 1168 psb_overlay_rect_t local_rect, extend_rect; 1169 enum overlay_id_t extend_overlay = OVERLAY_C; 1170 1171 if (output->extend_drawable) { 1172 XDestroyWindow(ctx->native_dpy, output->extend_drawable); 1173 output->extend_drawable = 0; 1174 XFreeGC((Display *)ctx->native_dpy, output->extend_gc); 1175 output->extend_gc = 0; 1176 } 1177 memset(&local_rect, 0, sizeof(psb_overlay_rect_t)); 1178 memset(&extend_rect, 0, sizeof(psb_overlay_rect_t)); 1179 psb_extendMode_getCoordinate(pPriv, extend_location, destx, desty, srcx, srcy, 1180 xScaleFactor, yScaleFactor, &x11_window_width, &x11_window_height, 1181 &local_rect, &extend_rect, &extend_overlay); 1182 1183 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height); 1184 if (ret != 0) { 1185 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret); 1186 return VA_STATUS_ERROR_UNKNOWN; 1187 } 1188 1189 if ((extend_rect.dWidth > 0) && (extend_rect.dHeight > 0)) { 1190 psb_putsurface_overlay( 1191 ctx, surface, 1192 extend_rect.srcx, extend_rect.srcy, extend_rect.sWidth, extend_rect.sHeight, 1193 extend_rect.destx, extend_rect.desty, extend_rect.dWidth, extend_rect.dHeight, 1194 flags, extend_overlay, extend_pipe); 1195 } 1196 if ((local_rect.dWidth > 0) && (local_rect.dHeight > 0)) { 1197 psb_putsurface_overlay( 1198 ctx, surface, 1199 local_rect.srcx, local_rect.srcy, local_rect.sWidth, local_rect.sHeight, 1200 local_rect.destx, local_rect.desty, local_rect.dWidth, local_rect.dHeight, 1201 flags, OVERLAY_A, local_pipe); 1202 } 1203 } 1204 } else if (psb_xrandr_extvideo_mode()) { 1205 unsigned int xres, yres, xoffset, yoffset, overscanmode, pannelfitting, x, y; 1206 psb_extvideo_center center; 1207 1208 psb_xrandr_extvideo_prop(&xres, &yres, &xoffset, &yoffset, ¢er, &subtitle, &overscanmode, &pannelfitting); 1209 x = xoffset; 1210 y = yoffset; 1211 1212 switch (extend_location) { 1213 case RIGHT_OF: 1214 x += pPriv->display_width; 1215 break; 1216 case BELOW: 1217 y += pPriv->display_height; 1218 break; 1219 case NORMAL: 1220 break; 1221 case LEFT_OF: 1222 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) { 1223 destx += pPriv->extend_display_width; 1224 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height); 1225 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height); 1226 XFlush(ctx->native_dpy); 1227 } 1228 destx = destx - pPriv->extend_display_width; 1229 break; 1230 case ABOVE: 1231 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) { 1232 desty += pPriv->extend_display_height; 1233 XMoveResizeWindow(ctx->native_dpy, output->output_drawable, destx, desty, x11_window_width, x11_window_height); 1234 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, 0, 0, x11_window_width, x11_window_height); 1235 XFlush(ctx->native_dpy); 1236 } 1237 desty = desty - pPriv->extend_display_height; 1238 break; 1239 } 1240 if ((destx + x11_window_width) > pPriv->display_width) 1241 x11_window_width = pPriv->display_width - destx; 1242 if ((desty + x11_window_height) > pPriv->display_height) 1243 x11_window_height = pPriv->display_height - desty; 1244 1245 if (driver_data->xrandr_dirty & PSB_NEW_EXTVIDEO) { 1246 Window extend_win; 1247 extend_win = psb_xrandr_create_full_screen_window(x, y, xres, yres); 1248 if (output->extend_drawable != extend_win) { 1249 output->extend_drawable = extend_win; 1250 if (output->extend_gc) 1251 XFreeGC((Display *)ctx->native_dpy, output->extend_gc); 1252 output->extend_gc = XCreateGC((Display *)ctx->native_dpy, extend_win, 0, NULL); 1253 1254 /* paint the color key */ 1255 if (!obj_surface->subpictures) { 1256 XSetForeground((Display *)ctx->native_dpy, output->extend_gc, pPriv->colorKey); 1257 XFillRectangle((Display *)ctx->native_dpy, extend_win, output->extend_gc, 0, 0, xres, yres); 1258 XSync((Display *)ctx->native_dpy, False); 1259 } 1260 } 1261 driver_data->xrandr_dirty &= ~PSB_NEW_EXTVIDEO; 1262 } 1263 1264 ret = psb_repaint_colorkey(ctx, draw, surface, x11_window_width, x11_window_height); 1265 if (ret != 0) { 1266 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to repaint color key error # %d\n", __func__, ret); 1267 return VA_STATUS_ERROR_UNKNOWN; 1268 } 1269 1270 psb_putsurface_overlay( 1271 ctx, surface, srcx, srcy, srcw, srch, 1272 /* screen coordinate */ 1273 xoffset, yoffset, xres, yres, 1274 flags, OVERLAY_C, PIPEB); 1275 psb_putsurface_overlay( 1276 ctx, surface, srcx, srcy, srcw, srch, 1277 /* screen coordinate */ 1278 destx, desty, 1279 x11_window_width, x11_window_height, 1280 flags, OVERLAY_A, local_pipe); 1281 } 1282 1283 /*Init Overlay subpicuture blending and make proper clear.*/ 1284 if (pPriv->is_mfld && obj_surface->subpictures) { 1285 PsbVASurfaceRec *subpicture = (PsbVASurfaceRec *)obj_surface->subpictures; 1286 1287 psb_init_subpicture(ctx, pPriv); 1288 /*clear changed subpicture zones in drawable.*/ 1289 psb_clear_subpictures(ctx, pPriv, x11_window_width, x11_window_height, obj_surface); 1290 if (pPriv->subpic_clear_flag) { 1291 psb_DisplayRGBASubpicture(subpicture, ctx, x11_window_width, x11_window_height, 1292 surfacex, surfacey, obj_surface->width, obj_surface->height, subtitle); 1293 } 1294 } 1295 1296 output->frame_count++; 1297 1298 return VA_STATUS_SUCCESS; 1299 } 1300