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 * Shengquan Yuan <shengquan.yuan (at) intel.com> 26 * Zhaohan Ren <zhaohan.ren (at) intel.com> 27 * 28 */ 29 30 31 #include <va/va_backend.h> 32 #include "psb_surface.h" 33 #include "psb_output.h" 34 #include "psb_surface_ext.h" 35 #include "psb_x11.h" 36 #include "psb_xrandr.h" 37 #include "psb_drv_debug.h" 38 39 #include <X11/extensions/dpms.h> 40 41 #include <wsbm/wsbm_manager.h> 42 43 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 44 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv) 45 46 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 47 48 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw); 49 50 int (*oldHandler)(Display *, XErrorEvent *) = 0; 51 static int XErrorFlag = 1; 52 static int psb_XErrorHandler(Display *dpy, XErrorEvent *event) 53 { 54 drv_debug_msg(VIDEO_DEBUG_GENERAL, "XErrorEvent caught in psb_XErrorHandler in psb_xvva.c\n"); 55 if (event->type == 0 && event->request_code == 132 && event->error_code == 11 /* BadAlloc */) { 56 XErrorFlag = 1; 57 return 0; 58 } 59 return oldHandler(dpy, event); 60 } 61 62 static int GetPortId(VADriverContextP ctx, psb_x11_output_p output) 63 { 64 int i, j, k; 65 unsigned int numAdapt; 66 int numImages; 67 XvImageFormatValues *formats; 68 XvAdaptorInfo *info; 69 int ret, grab_ret; 70 Display *dpy = (Display *)ctx->native_dpy; 71 72 ret = XvQueryAdaptors(dpy, DefaultRootWindow(dpy), &numAdapt, &info); 73 /*Force overlay port num equal to one. OverlayC can't be used independently now.*/ 74 /* check for numAdapt before modifying the info[1]. Without this check 75 * it will cause a memory corruption leading to segfaults */ 76 if (numAdapt > 1) 77 info[1].num_ports = 1; 78 79 if (Success != ret) { 80 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't find Xvideo adaptor\n"); 81 return -1; 82 } 83 84 grab_ret = XGrabServer(ctx->native_dpy); 85 for (i = 0; i < numAdapt; i++) { 86 if ((info[i].type & XvImageMask) == 0) 87 continue; 88 89 formats = XvListImageFormats(dpy, info[i].base_id, &numImages); 90 for (j = 0; j < numImages; j++) { 91 if (formats[j].id != FOURCC_XVVA) continue; 92 for (k = 0; k < info[i].num_ports; k++) { 93 int ret = XvGrabPort(dpy, info[i].base_id + k, CurrentTime); 94 95 if (Success == ret) { 96 /* for textured adaptor 0 */ 97 if (i == 0) 98 output->textured_portID = info[i].base_id + k; 99 /* for overlay adaptor 1 */ 100 if (i == 1) 101 output->overlay_portID = info[i].base_id + k; 102 break; 103 } 104 } 105 } 106 XFree(formats); 107 } 108 109 if (grab_ret != 0) 110 XUngrabServer(ctx->native_dpy); 111 112 if ((output->textured_portID == 0) && (output->overlay_portID == 0)) { 113 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Can't detect any usable Xv XVVA port\n"); 114 return -1; 115 } 116 117 return 0; 118 } 119 120 121 VAStatus psb_init_xvideo(VADriverContextP ctx, psb_x11_output_p output) 122 { 123 #ifdef _FOR_FPGA_ 124 return VA_STATUS_SUCCESS; 125 #endif 126 127 INIT_DRIVER_DATA; 128 int dummy, ret; 129 130 output->textured_portID = output->overlay_portID = 0; 131 if (GetPortId(ctx, output)) { 132 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab Xvideo port failed, fallback to software vaPutSurface.\n"); 133 return VA_STATUS_ERROR_ALLOCATION_FAILED; 134 } 135 136 if (output->textured_portID) 137 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected textured Xvideo port_id = %d.\n", (unsigned int)output->textured_portID); 138 if (output->overlay_portID) 139 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected overlay Xvideo port_id = %d.\n", (unsigned int)output->overlay_portID); 140 141 output->sprite_enabled = 0; 142 if (getenv("PSB_SPRITE_ENABLE")) { 143 drv_debug_msg(VIDEO_DEBUG_GENERAL, "use sprite plane to playback rotated protected video\n"); 144 output->sprite_enabled = 1; 145 } 146 147 output->ignore_dpm = 1; 148 if (getenv("PSB_VIDEO_DPMS_HACK")) { 149 if (DPMSQueryExtension((Display *)ctx->native_dpy, &dummy, &dummy) 150 && DPMSCapable((Display *)ctx->native_dpy)) { 151 BOOL onoff; 152 CARD16 state; 153 154 DPMSInfo((Display *)ctx->native_dpy, &state, &onoff); 155 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled", 156 (state == DPMSModeOn) ? "on" : ( 157 (state == DPMSModeOff) ? "off" : ( 158 (state == DPMSModeStandby) ? "standby" : ( 159 (state == DPMSModeSuspend) ? "suspend" : "unknow")))); 160 if (onoff) 161 output->ignore_dpm = 0; 162 } 163 } 164 165 /* by default, overlay Xv */ 166 if (output->textured_portID) 167 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 168 if (output->overlay_portID) 169 driver_data->output_method = PSB_PUTSURFACE_OVERLAY; 170 171 ret = psb_xrandr_init(ctx); 172 if (ret != 0) { 173 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to initialize psb xrandr error # %d\n", __func__, ret); 174 return VA_STATUS_ERROR_UNKNOWN; 175 } 176 177 return VA_STATUS_SUCCESS; 178 } 179 180 181 VAStatus psb_deinit_xvideo(VADriverContextP ctx) 182 { 183 INIT_DRIVER_DATA; 184 INIT_OUTPUT_PRIV; 185 186 if (output->gc) { 187 XFreeGC((Display *)ctx->native_dpy, output->gc); 188 output->gc = NULL; 189 } 190 191 if (output->extend_gc) { 192 XFreeGC((Display *)ctx->native_dpy, output->extend_gc); 193 output->extend_gc = NULL; 194 } 195 196 if (output->textured_xvimage) { 197 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for texture Xv\n"); 198 XFree(output->textured_xvimage); 199 output->textured_xvimage = NULL; 200 } 201 202 if (output->overlay_xvimage) { 203 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for overlay Xv\n"); 204 XFree(output->overlay_xvimage); 205 output->textured_xvimage = NULL; 206 } 207 208 if (output->textured_portID) { 209 if ((output->using_port == USING_TEXTURE_PORT) && output->output_drawable 210 && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) { 211 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop textured Xvideo\n"); 212 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, output->output_drawable); 213 } 214 215 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab textured Xvideo port\n"); 216 XvUngrabPort((Display *)ctx->native_dpy, output->textured_portID, CurrentTime); 217 output->textured_portID = 0; 218 } 219 220 if (output->overlay_portID) { 221 if ((output->using_port == USING_OVERLAY_PORT) && output->output_drawable 222 && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) { 223 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop overlay Xvideo\n"); 224 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, output->output_drawable); 225 } 226 227 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab overlay Xvideo port\n"); 228 XvUngrabPort((Display *)ctx->native_dpy, output->overlay_portID, CurrentTime); 229 output->overlay_portID = 0; 230 } 231 232 if (driver_data->use_xrandr_thread && driver_data->xrandr_thread_id) { 233 psb_xrandr_thread_exit(); 234 pthread_join(driver_data->xrandr_thread_id, NULL); 235 driver_data->xrandr_thread_id = 0; 236 } 237 psb_xrandr_deinit(); 238 239 output->using_port = 0; 240 output->output_drawable = 0; 241 output->extend_drawable = 0; 242 #ifndef _FOR_FPGA_ 243 XSync((Display *)ctx->native_dpy, False); 244 #endif 245 return VA_STATUS_SUCCESS; 246 } 247 248 249 static void psb_surface_init( 250 psb_driver_data_p driver_data, 251 PsbVASurfaceRec *srf, 252 int fourcc, int bpp, int w, int h, int stride, int size, unsigned int pre_add, 253 struct _WsbmBufferObject *bo, int flags 254 ) 255 { 256 memset(srf, 0, sizeof(*srf)); 257 258 srf->fourcc = fourcc; 259 srf->bo = bo; 260 if (bo != NULL) { 261 srf->bufid = wsbmKBufHandle(wsbmKBuf(bo)); 262 srf->pl_flags = wsbmBOPlacementHint(bo); 263 } 264 265 /* 266 if (srf->pl_flags & DRM_PSB_FLAG_MEM_CI) 267 srf->reserved_phyaddr = driver_data->camera_phyaddr; 268 if (srf->pl_flags & DRM_PSB_FLAG_MEM_RAR) 269 srf->reserved_phyaddr = driver_data->rar_phyaddr; 270 */ 271 srf->bytes_pp = bpp; 272 273 srf->width = w; 274 srf->pre_add = pre_add; 275 if ((flags == VA_TOP_FIELD) || (flags == VA_BOTTOM_FIELD)) { 276 if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY 277 || driver_data->output_method == PSB_PUTSURFACE_OVERLAY) { 278 srf->height = h; 279 srf->stride = stride; 280 } else { 281 srf->height = h / 2; 282 srf->stride = stride * 2; 283 } 284 if (flags == VA_BOTTOM_FIELD) 285 srf->pre_add += stride; 286 } else { 287 srf->height = h; 288 srf->stride = stride; 289 } 290 291 srf->size = size; 292 293 if (flags == VA_CLEAR_DRAWABLE) { 294 srf->clear_color = driver_data->clear_color; /* color */ 295 return; 296 } 297 } 298 299 #if 0 300 301 #define WINDOW 1 302 #define PIXMAP 0 303 304 /* return 0 for no rotation, 1 for rotation occurs */ 305 /* XRRGetScreenInfo has significant performance drop */ 306 static int psb__CheckCurrentRotation(VADriverContextP ctx) 307 { 308 Rotation current_rotation; 309 XRRScreenConfiguration *scrn_cfg; 310 scrn_cfg = XRRGetScreenInfo((Display *)ctx->native_dpy, DefaultRootWindow((Display *)ctx->native_dpy)); 311 XRRConfigCurrentConfiguration(scrn_cfg, ¤t_rotation); 312 XRRFreeScreenConfigInfo(scrn_cfg); 313 return (current_rotation & 0x0f); 314 } 315 316 /* Check drawable type, 1 for window, 0 for pixmap 317 * Have significant performance drop in XFCE environment 318 */ 319 static void psb__CheckDrawableType(Display *dpy, Window win, Drawable draw, int *type_ret) 320 { 321 322 unsigned int child_num; 323 Window root_return; 324 Window parent_return; 325 Window *child_return; 326 int i; 327 328 if (win == draw) { 329 *type_ret = 1; 330 return; 331 } 332 333 XQueryTree(dpy, win, &root_return, &parent_return, &child_return, &child_num); 334 335 if (!child_num) 336 return; 337 338 for (i = 0; i < child_num; i++) 339 psb__CheckDrawableType(dpy, child_return[i], draw, type_ret); 340 } 341 #endif 342 343 344 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw) 345 { 346 INIT_DRIVER_DATA; 347 INIT_OUTPUT_PRIV; 348 Atom xvDrawable = XInternAtom((Display *)ctx->native_dpy, "XV_DRAWABLE", 0); 349 int val = 0; 350 351 driver_data->drawable_info = 0; 352 if (output->overlay_portID) { 353 XvSetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, draw); 354 XvGetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, &val); 355 } else if (output->textured_portID) { 356 XvSetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, draw); 357 XvGetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, &val); 358 } 359 driver_data->drawable_info = val; 360 361 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Get xvDrawable = 0x%08x\n", val); 362 363 if (driver_data->drawable_info == XVDRAWABLE_INVALID_DRAWABLE) 364 return -1; 365 366 return 0; 367 } 368 369 static int psb__CheckPutSurfaceXvPort( 370 VADriverContextP ctx, 371 VASurfaceID surface, 372 Drawable draw, /* X Drawable */ 373 short srcx, 374 short srcy, 375 unsigned short srcw, 376 unsigned short srch, 377 short destx, 378 short desty, 379 unsigned short destw, 380 unsigned short desth, 381 VARectangle *cliprects, /* client supplied clip list */ 382 unsigned int number_cliprects, /* number of clip rects in the clip list */ 383 unsigned int flags /* de-interlacing flags */ 384 ) 385 { 386 INIT_DRIVER_DATA; 387 INIT_OUTPUT_PRIV; 388 object_surface_p obj_surface = SURFACE(surface); 389 uint32_t buf_pl; 390 391 /* silent klockwork */ 392 if (obj_surface && obj_surface->psb_surface) 393 buf_pl = obj_surface->psb_surface->buf.pl_flags; 394 else 395 return -1; 396 397 if (flags & VA_CLEAR_DRAWABLE) 398 return 0; 399 400 if (output->overlay_portID == 0) { /* no overlay usable */ 401 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 402 return 0; 403 } 404 405 if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) { 406 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Overlay Xvideo for PutSurface\n"); 407 return 0; 408 } 409 410 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE)) { 411 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Textured Xvideo for PutSurface\n"); 412 return 0; 413 } 414 415 if (((buf_pl & (WSBM_PL_FLAG_TT)) == 0) /* buf not in TT/RAR or CI */ 416 || (obj_surface->width > 1920) /* overlay have isue to support >1920xXXX resolution */ 417 || (obj_surface->subpic_count > 0) /* overlay can't support subpicture */ 418 /* || (flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD))*/ 419 ) { 420 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 421 return 0; 422 } 423 424 425 /* Here should be overlay XV by defaut after overlay is stable */ 426 driver_data->output_method = PSB_PUTSURFACE_OVERLAY; 427 /* driver_data->output_method = PSB_PUTSURFACE_TEXTURE; */ 428 429 /* 430 *Query Overlay Adaptor by XvDrawable Attribute to know current 431 * Xrandr information:rotation/downscaling 432 * also set target drawable(window vs pixmap) into XvDrawable 433 * to levage Xserver to determiate it is Pixmap or Window 434 */ 435 /* 436 *ROTATE_90: 0x2, ROTATE_180: 0x4, ROTATE_270:0x8 437 *Overlay adopator can support video rotation, 438 *but its performance is lower than texture video path. 439 *When video protection and rotation are required (use RAR buffer), 440 *only overlay adaptor will be used. 441 *other attribute like down scaling and pixmap, use texture adaptor 442 */ 443 if (driver_data->drawable_info 444 & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) { 445 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 446 } 447 448 if (driver_data->drawable_info & (XVDRAWABLE_PIXMAP | XVDRAWABLE_REDIRECT_WINDOW)) 449 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 450 451 if (srcw >= destw * 8 || srch >= desth * 8) 452 driver_data->output_method = PSB_PUTSURFACE_TEXTURE; 453 454 return 0; 455 } 456 457 458 static int psb__CheckGCXvImage( 459 VADriverContextP ctx, 460 VASurfaceID surface, 461 Drawable draw, 462 XvImage **xvImage, 463 XvPortID *port_id, 464 unsigned int flags /* de-interlacing flags */ 465 ) 466 { 467 INIT_DRIVER_DATA; 468 INIT_OUTPUT_PRIV; 469 object_surface_p obj_surface = SURFACE(surface); /* surface already checked */ 470 471 if (output->output_drawable != draw) { 472 if (output->gc) 473 XFreeGC((Display *)ctx->native_dpy, output->gc); 474 output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL); 475 output->output_drawable = draw; 476 } 477 478 if (flags & VA_CLEAR_DRAWABLE) { 479 if (output->textured_portID && (output->using_port == USING_TEXTURE_PORT)) { 480 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop textured Xvideo\n"); 481 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw); 482 } 483 484 if (output->overlay_portID && (output->using_port == USING_OVERLAY_PORT)) { 485 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop overlay Xvideo\n"); 486 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw); 487 } 488 489 output->using_port = 0; 490 491 XSetForeground((Display *)ctx->native_dpy, output->gc, driver_data->clear_color); 492 493 return 0; 494 } 495 496 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) || 497 (driver_data->output_method == PSB_PUTSURFACE_OVERLAY)) { 498 /* use OVERLAY XVideo */ 499 if (obj_surface && 500 ((output->output_width != obj_surface->width) || 501 (output->output_height != obj_surface->height) || 502 (!output->overlay_xvimage))) { 503 504 if (output->overlay_xvimage) 505 XFree(output->overlay_xvimage); 506 507 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n"); 508 output->overlay_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->overlay_portID, 509 FOURCC_XVVA, 0, 510 obj_surface->width, obj_surface->height); 511 512 output->overlay_xvimage->data = (char *) & output->imgdata_vasrf; 513 output->output_width = obj_surface->width; 514 output->output_height = obj_surface->height; 515 } 516 *xvImage = output->overlay_xvimage; 517 *port_id = output->overlay_portID; 518 519 if ((output->textured_portID) && (output->using_port == USING_TEXTURE_PORT)) { /* stop texture port */ 520 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using overlay xvideo, stop textured xvideo\n"); 521 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw); 522 XSync((Display *)ctx->native_dpy, False); 523 } 524 output->using_port = USING_OVERLAY_PORT; 525 526 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Overlay Xvideo (%d) for PutSurface\n", output->textured_portID); 527 528 return 0; 529 } 530 531 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE) || 532 (driver_data->output_method == PSB_PUTSURFACE_TEXTURE)) { 533 /* use Textured XVideo */ 534 if (obj_surface && 535 ((output->output_width != obj_surface->width) || 536 (output->output_height != obj_surface->height || 537 (!output->textured_xvimage)))) { 538 if (output->textured_xvimage) 539 XFree(output->textured_xvimage); 540 541 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n"); 542 output->textured_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->textured_portID, FOURCC_XVVA, 0, 543 obj_surface->width, obj_surface->height); 544 output->textured_xvimage->data = (char *) & output->imgdata_vasrf; 545 output->output_width = obj_surface->width; 546 output->output_height = obj_surface->height; 547 548 } 549 550 *xvImage = output->textured_xvimage; 551 *port_id = output->textured_portID; 552 553 if ((output->overlay_portID) && (output->using_port == USING_OVERLAY_PORT)) { /* stop overlay port */ 554 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using textured xvideo, stop Overlay xvideo\n"); 555 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw); 556 XSync((Display *)ctx->native_dpy, False); 557 558 output->using_port = USING_TEXTURE_PORT; 559 } 560 561 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Texture Xvideo (%d) for PutSurface\n", output->textured_portID); 562 563 return 0; 564 } 565 566 return 0; 567 } 568 569 static int psb_force_dpms_on(VADriverContextP ctx) 570 { 571 BOOL onoff; 572 CARD16 state; 573 574 DPMSInfo((Display *)ctx->native_dpy, &state, &onoff); 575 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled", 576 (state == DPMSModeOn) ? "on" : ( 577 (state == DPMSModeOff) ? "off" : ( 578 (state == DPMSModeStandby) ? "standby" : ( 579 (state == DPMSModeSuspend) ? "suspend" : "unknow")))); 580 if (onoff && (state != DPMSModeOn)) { 581 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is enabled, and monitor isn't DPMSModeOn, force it on\n"); 582 DPMSForceLevel((Display *)ctx->native_dpy, DPMSModeOn); 583 } 584 585 return 0; 586 } 587 588 VAStatus psb_check_rotatesurface( 589 VADriverContextP ctx, 590 unsigned short rotate_width, 591 unsigned short rotate_height, 592 unsigned int protected, 593 int fourcc 594 ) 595 { 596 INIT_DRIVER_DATA; 597 INIT_OUTPUT_PRIV; 598 VAStatus vaStatus = VA_STATUS_SUCCESS; 599 object_surface_p obj_rotate_surface; 600 unsigned int flags = protected? IS_PROTECTED : 0; 601 602 if (output->rotate_surface) { 603 obj_rotate_surface = SURFACE(output->rotate_surfaceID); 604 if (obj_rotate_surface && 605 ((obj_rotate_surface->width != rotate_width) 606 || (obj_rotate_surface->height != rotate_height))) { 607 psb_surface_destroy(output->rotate_surface); 608 free(output->rotate_surface); 609 object_heap_free(&driver_data->surface_heap, (object_base_p)obj_rotate_surface); 610 output->rotate_surface = NULL; 611 } 612 } 613 if (output->rotate_surface == NULL) { 614 output->rotate_surfaceID = object_heap_allocate(&driver_data->surface_heap); 615 obj_rotate_surface = SURFACE(output->rotate_surfaceID); 616 if (NULL == obj_rotate_surface) { 617 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 618 DEBUG_FAILURE; 619 620 return VA_STATUS_ERROR_ALLOCATION_FAILED; 621 } 622 623 obj_rotate_surface->surface_id = output->rotate_surfaceID; 624 obj_rotate_surface->context_id = -1; 625 obj_rotate_surface->width = rotate_width; 626 obj_rotate_surface->height = rotate_height; 627 obj_rotate_surface->subpictures = NULL; 628 obj_rotate_surface->subpic_count = 0; 629 obj_rotate_surface->derived_imgcnt = 0; 630 output->rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 631 if (NULL == output->rotate_surface) { 632 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface); 633 obj_rotate_surface->surface_id = VA_INVALID_SURFACE; 634 635 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 636 637 DEBUG_FAILURE; 638 639 return VA_STATUS_ERROR_ALLOCATION_FAILED; 640 } 641 642 flags |= IS_ROTATED; 643 vaStatus = psb_surface_create(driver_data, rotate_width, rotate_height, 644 fourcc, flags, output->rotate_surface); 645 if (VA_STATUS_SUCCESS != vaStatus) { 646 free(obj_rotate_surface->psb_surface); 647 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface); 648 obj_rotate_surface->surface_id = VA_INVALID_SURFACE; 649 650 DEBUG_FAILURE; 651 return vaStatus; 652 } 653 obj_rotate_surface->psb_surface = output->rotate_surface; 654 } 655 return vaStatus; 656 } 657 658 VAStatus psb_putsurface_xvideo( 659 VADriverContextP ctx, 660 VASurfaceID surface, 661 Drawable draw, 662 short srcx, 663 short srcy, 664 unsigned short srcw, 665 unsigned short srch, 666 short destx, 667 short desty, 668 unsigned short destw, 669 unsigned short desth, 670 VARectangle *cliprects, /* client supplied clip list */ 671 unsigned int number_cliprects, /* number of clip rects in the clip list */ 672 unsigned int flags /* de-interlacing flags */ 673 ) 674 { 675 INIT_DRIVER_DATA; 676 INIT_OUTPUT_PRIV; 677 VAStatus vaStatus = VA_STATUS_SUCCESS; 678 PsbVASurfaceRec *subpic_surface; 679 PsbXvVAPutSurfacePtr vaPtr; 680 XvPortID portID = 0; 681 XvImage *xvImage = NULL; 682 object_surface_p obj_surface = SURFACE(surface); 683 psb_surface_p psb_surface; 684 int i = 0, j; 685 686 687 if (obj_surface) /* silent klockwork, we already check it */ 688 psb_surface = obj_surface->psb_surface; 689 else 690 return VA_STATUS_ERROR_UNKNOWN; 691 692 /* Catch X protocol errors with our own error handler */ 693 if (oldHandler == 0) 694 oldHandler = XSetErrorHandler(psb_XErrorHandler); 695 696 if (XErrorFlag == 1) { 697 if (psb_CheckDrawable(ctx, draw) != 0) { 698 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n"); 699 return VA_STATUS_ERROR_UNKNOWN; 700 } 701 702 drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n"); 703 XErrorFlag = 0; 704 } 705 706 /* check display configuration for every 100 frames */ 707 if ((driver_data->frame_count % 100) == 0) { 708 if (psb_CheckDrawable(ctx, draw) != 0) { 709 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n"); 710 return VA_STATUS_ERROR_UNKNOWN; 711 } 712 drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n"); 713 } 714 715 716 717 psb__CheckPutSurfaceXvPort(ctx, surface, draw, 718 srcx, srcy, srcw, srch, 719 destx, desty, destw, desth, 720 cliprects, number_cliprects, flags); 721 psb__CheckGCXvImage(ctx, surface, draw, &xvImage, &portID, flags); 722 723 if (flags & VA_CLEAR_DRAWABLE) { 724 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color); 725 726 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth); 727 XSync((Display *)ctx->native_dpy, False); 728 729 XFreeGC((Display *)ctx->native_dpy, output->gc); 730 output->gc = NULL; 731 output->output_drawable = 0; 732 733 XSync((Display *)ctx->native_dpy, False); 734 735 driver_data->cur_displaying_surface = VA_INVALID_SURFACE; 736 driver_data->last_displaying_surface = VA_INVALID_SURFACE; 737 obj_surface->display_timestamp = 0; 738 739 740 return vaStatus; 741 } 742 743 vaPtr = (PsbXvVAPutSurfacePtr)xvImage->data; 744 vaPtr->flags = flags; 745 vaPtr->num_subpicture = obj_surface->subpic_count; 746 vaPtr->num_clipbox = number_cliprects; 747 for (j = 0; j < number_cliprects; j++) { 748 vaPtr->clipbox[j].x = cliprects[j].x; 749 vaPtr->clipbox[j].y = cliprects[j].y; 750 vaPtr->clipbox[j].width = cliprects[j].width; 751 vaPtr->clipbox[j].height = cliprects[j].height; 752 } 753 754 psb_surface_init(driver_data, &vaPtr->src_srf, VA_FOURCC_NV12, 2, 755 obj_surface->width, obj_surface->height, 756 psb_surface->stride, psb_surface->size, 757 psb_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory 758 * all surfaces share one BO but with different offset 759 * pass the offset as the "pre_add" 760 */ 761 psb_surface->buf.drm_buf, flags); 762 763 if ((driver_data->output_method == PSB_PUTSURFACE_OVERLAY) 764 && (driver_data->drawable_info & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270))) { 765 unsigned int rotate_width, rotate_height; 766 int fourcc; 767 if (output->sprite_enabled) 768 fourcc = VA_FOURCC_RGBA; 769 else 770 fourcc = VA_FOURCC_NV12; 771 if (driver_data->drawable_info & (XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) { 772 rotate_width = obj_surface->height; 773 rotate_height = obj_surface->width; 774 } else { 775 rotate_width = obj_surface->width; 776 rotate_height = obj_surface->height; 777 } 778 unsigned int protected = vaPtr->src_srf.pl_flags & 0; 779 780 vaStatus = psb_check_rotatesurface(ctx, rotate_width, rotate_height, protected, fourcc); 781 if (VA_STATUS_SUCCESS != vaStatus) 782 return vaStatus; 783 784 psb_surface_init(driver_data, &vaPtr->dst_srf, fourcc, 4, 785 rotate_width, rotate_height, 786 output->rotate_surface->stride, output->rotate_surface->size, 787 output->rotate_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory 788 * all surfaces share one BO but with different offset 789 * pass the offset as the "pre_add" 790 */ 791 output->rotate_surface->buf.drm_buf, 0); 792 } 793 subpic_surface = obj_surface->subpictures; 794 while (subpic_surface) { 795 PsbVASurfaceRec *tmp = &vaPtr->subpic_srf[i++]; 796 797 memcpy(tmp, subpic_surface, sizeof(*tmp)); 798 799 /* reload palette for paletted subpicture 800 * palete_ptr point to image palette 801 */ 802 if (subpic_surface->palette_ptr) 803 memcpy(&tmp->palette[0], subpic_surface->palette_ptr, 16 * sizeof(PsbAYUVSample8)); 804 805 subpic_surface = subpic_surface->next; 806 } 807 808 if (output->ignore_dpm == 0) 809 psb_force_dpms_on(ctx); 810 811 XvPutImage((Display *)ctx->native_dpy, portID, draw, output->gc, xvImage, 812 srcx, srcy, srcw, srch, destx, desty, destw, desth); 813 XFlush((Display *)ctx->native_dpy); 814 //XSync((Display *)ctx->native_dpy, False); 815 816 if (portID == output->overlay_portID) { 817 if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE) 818 driver_data->last_displaying_surface = driver_data->cur_displaying_surface; 819 obj_surface->display_timestamp = GetTickCount(); 820 driver_data->cur_displaying_surface = surface; 821 } else { 822 driver_data->cur_displaying_surface = VA_INVALID_SURFACE; 823 driver_data->last_displaying_surface = VA_INVALID_SURFACE; 824 obj_surface->display_timestamp = 0; 825 } 826 827 828 return vaStatus; 829 } 830 831