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 * Zhaohan Ren <zhaohan.ren (at) intel.com> 26 * Shengquan Yuan <shengquan.yuan (at) intel.com> 27 * Jiang Fei <jiang.fei (at) intel.com> 28 * Binglin Chen <binglin.chen (at) intel.com> 29 * 30 */ 31 #include <va/va_backend.h> 32 #include "psb_output.h" 33 #include "psb_surface.h" 34 #include "psb_buffer.h" 35 #include "psb_overlay.h" 36 #include "psb_texture.h" 37 #include <stdio.h> 38 #include <string.h> 39 #include <stdarg.h> 40 #include "psb_android_glue.h" 41 #include "psb_output_android.h" 42 #ifndef BAYTRAIL 43 #include "psb_HDMIExtMode.h" 44 #endif 45 #include "pnw_rotate.h" 46 #include "psb_drv_debug.h" 47 #include <wsbm/wsbm_manager.h> 48 #include <hardware.h> 49 50 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 51 #define INIT_OUTPUT_PRIV psb_android_output_p output = (psb_android_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv) 52 53 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 54 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id )) 55 #define IMAGE(id) ((object_image_p) object_heap_lookup( &driver_data->image_heap, id )) 56 #define SUBPIC(id) ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id )) 57 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 58 59 #define GET_SURFACE_INFO_rotate(psb_surface) ((int) psb_surface->extra_info[5]) 60 #define GET_SURFACE_INFO_protect(psb_surface) ((int) psb_surface->extra_info[6]) 61 #define MAX_OVERLAY_IDLE_FRAME 4 62 63 enum { 64 eWidiOff = 1, 65 eWidiClone = 2, 66 eWidiExtendedVideo = 3, 67 }; 68 extern unsigned int update_forced; 69 70 inline int va2hw_rotation(int va_rotate) 71 { 72 switch (va_rotate) { 73 case VA_ROTATION_90: 74 return HAL_TRANSFORM_ROT_270; 75 case VA_ROTATION_180: 76 return HAL_TRANSFORM_ROT_180; 77 case VA_ROTATION_270: 78 return HAL_TRANSFORM_ROT_90; 79 defaut: 80 return 0; 81 } 82 83 return 0; 84 } 85 86 unsigned char *psb_android_output_init(VADriverContextP ctx) 87 { 88 INIT_DRIVER_DATA; 89 char put_surface[1024]; 90 psb_android_output_p output = calloc(1, sizeof(psb_android_output_s)); 91 struct fb_var_screeninfo vinfo; 92 int fbfd = -1; 93 94 if (output == NULL) { 95 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't malloc memory\n"); 96 return NULL; 97 } 98 memset(output, 0, sizeof(psb_android_output_s)); 99 100 /* Guess the screen size */ 101 output->screen_width = 800; 102 output->screen_height = 480; 103 104 // Open the frame buffer for reading 105 memset(&vinfo, 0, sizeof(vinfo)); 106 fbfd = open("/dev/graphics/fb0", O_RDONLY); 107 if (fbfd) { 108 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) 109 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Error reading screen information.\n"); 110 } 111 close(fbfd); 112 output->screen_width = vinfo.xres; 113 output->screen_height = vinfo.yres; 114 115 /* TS by default */ 116 driver_data->output_method = PSB_PUTSURFACE_OVERLAY; 117 driver_data->color_key = 0x000001; /*light blue*/ 118 119 if (psb_parse_config("PSB_VIDEO_CTEXTURES", &put_surface[0]) == 0) { 120 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB_VIDEO_CTEXTURES is enabled for vaPutSurfaceBuf\n"); 121 driver_data->ctexture = 1; /* Init CTEXTURE for vaPutSurfaceBuf */ 122 } 123 124 if (psb_parse_config("PSB_VIDEO_COVERLAY", &put_surface[0]) == 0) { 125 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Putsurface use client overlay\n"); 126 driver_data->output_method = PSB_PUTSURFACE_FORCE_COVERLAY; 127 } 128 129 driver_data->coverlay = 1; 130 131 return (unsigned char *)output; 132 } 133 134 VAStatus psb_android_output_deinit(VADriverContextP ctx) 135 { 136 INIT_DRIVER_DATA; 137 INIT_OUTPUT_PRIV; 138 //psb_android_output_p output = GET_OUTPUT_DATA(ctx); 139 #ifdef TARGET_HAS_MULTIPLE_DISPLAY 140 if (output->mds != NULL) { 141 deinit_mds_listener(output); 142 } 143 #endif 144 return VA_STATUS_SUCCESS; 145 } 146 147 #ifndef BAYTRAIL 148 static VAStatus psb_putsurface_ctexture( 149 VADriverContextP ctx, 150 VASurfaceID surface, 151 unsigned char* data, 152 short srcx, 153 short srcy, 154 unsigned short srcw, 155 unsigned short srch, 156 short destx, 157 short desty, 158 unsigned short destw, 159 unsigned short desth, 160 unsigned int __maybe_unused flags /* de-interlacing flags */ 161 ) 162 { 163 INIT_DRIVER_DATA; 164 INIT_OUTPUT_PRIV; 165 object_surface_p obj_surface; 166 int offset = 0; 167 psb_surface_p psb_surface; 168 VAStatus vaStatus = VA_STATUS_SUCCESS; 169 170 obj_surface = SURFACE(surface); 171 CHECK_SURFACE(obj_surface); 172 psb_surface = obj_surface->psb_surface; 173 174 // psb_surface->buf.drm_buf; 175 // psb_surface->buf.pl_flags; 176 psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch, 177 destx, desty, destw, desth, 0, /* no subtitle */ 178 obj_surface->width, obj_surface->height, 179 psb_surface->stride, psb_surface->buf.drm_buf, 180 psb_surface->buf.pl_flags, 1 /* need wrap dst */); 181 182 psb_android_postBuffer(offset); 183 184 return VA_STATUS_SUCCESS; 185 } 186 #endif 187 188 #if 0 189 VAStatus psb_putsurface_coverlay( 190 VADriverContextP ctx, 191 VASurfaceID surface, 192 short srcx, 193 short srcy, 194 unsigned short srcw, 195 unsigned short srch, 196 short destx, /* screen cooridination */ 197 short desty, 198 unsigned short destw, 199 unsigned short desth, 200 unsigned int flags /* de-interlacing flags */ 201 ) 202 { 203 INIT_OUTPUT_PRIV; 204 VAStatus vaStatus = VA_STATUS_SUCCESS; 205 206 /* USE_FIT_SCR_SIZE */ 207 /* calculate fit screen size of frame */ 208 unsigned short _scr_x = output->screen_width; 209 unsigned short _scr_y = output->screen_height; 210 float _slope_xy = (float)srch / srcw; 211 unsigned short _destw = (short)(_scr_y / _slope_xy); 212 unsigned short _desth = (short)(_scr_x * _slope_xy); 213 short _pos_x, _pos_y; 214 215 if (_destw <= _scr_x) { 216 _desth = _scr_y; 217 _pos_x = (_scr_x - _destw) >> 1; 218 _pos_y = 0; 219 } else { 220 _destw = _scr_x; 221 _pos_x = 0; 222 _pos_y = (_scr_y - _desth) >> 1; 223 } 224 destx += _pos_x; 225 desty += _pos_y; 226 destw = _destw; 227 desth = _desth; 228 229 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_putsurface_overlay: src (%d, %d, %d, %d), destx (%d, %d, %d, %d).\n", 230 srcx, srcy, srcw, srch, destx, desty, destw, desth); 231 /* display by overlay */ 232 vaStatus = psb_putsurface_overlay( 233 ctx, surface, srcx, srcy, srcw, srch, 234 destx, desty, destw, desth, /* screen coordinate */ 235 flags, OVERLAY_A, PIPEA); 236 237 return vaStatus; 238 } 239 #endif 240 241 #if 0 242 static int psb_update_destbox( 243 VADriverContextP ctx 244 ) 245 { 246 INIT_DRIVER_DATA; 247 INIT_OUTPUT_PRIV; 248 short destx; 249 short desty; 250 unsigned short destw; 251 unsigned short desth; 252 VAStatus vaStatus = VA_STATUS_SUCCESS; 253 254 psb_android_get_destbox(&destx, &desty, &destw, &desth); 255 /*drv_debug_msg(VIDEO_DEBUG_GENERAL, "destbox = (%d,%d,%d,%d)\n", destx, desty, destw, desth);*/ 256 if ((destx >= 0) && (desty >= 0) && 257 ((destx + destw) <= output->screen_width) && 258 ((desty + desth) <= output->screen_height) && 259 (output->destx != destx || 260 output->desty != desty || 261 output->destw != destw || 262 output->desth != desth)) { 263 output->destx = destx; 264 output->desty = desty; 265 output->destw = destw; 266 output->desth = desth; 267 output->new_destbox = 1; 268 269 LOGD("==========New Destbox=============\n"); 270 LOGD("output->destbox = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth); 271 } 272 273 return vaStatus; 274 } 275 #endif 276 277 #if 0 278 static int psb_check_outputmethod( 279 VADriverContextP ctx, 280 VASurfaceID surface, 281 unsigned short srcw, 282 unsigned short srch, 283 void *android_isurface, 284 psb_hdmi_mode *hdmi_mode 285 ) 286 { 287 INIT_DRIVER_DATA; 288 INIT_OUTPUT_PRIV; 289 psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info; 290 object_surface_p obj_surface; 291 int rotation = 0, widi = 0; 292 int delta_rotation = 0; 293 int srf_rotate; /* primary surface rotation */ 294 psb_surface_p rotate_surface; /* rotate surface */ 295 int rotate_srf_rotate = -1; /* degree of the rotate surface */ 296 297 if ((srcw >= 2048) || (srch >= 2048)) { 298 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clip size extend overlay hw limit, use texstreaming\n"); 299 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING; 300 return 0; 301 } 302 303 /* use saved status to avoid per-frame checking */ 304 if ((driver_data->frame_count % driver_data->outputmethod_checkinterval) != 0) { 305 *hdmi_mode = psb_HDMIExt_get_mode(output); 306 return 0; 307 } 308 309 /* check the status at outputmethod_checkinterval frequency */ 310 /* at first check HDMI status */ 311 if (psb_HDMIExt_update(ctx, psb_HDMIExt_info)) { 312 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to update HDMIExt info.\n", __FUNCTION__); 313 return -1; 314 } 315 316 obj_surface = SURFACE(surface); 317 if (obj_surface == NULL) { 318 drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surface\n"); 319 return -1; 320 } 321 322 *hdmi_mode = psb_HDMIExt_get_mode(output); 323 if ((*hdmi_mode == EXTENDED_VIDEO) || (*hdmi_mode == CLONE)) { 324 unsigned short _destw, _desth; 325 short _pos_x, _pos_y; 326 unsigned short crtc_width = 0, crtc_height = 0; 327 float _slope_xy; 328 329 /* need to handle VA rotation, and set WM rotate to 0 330 * for Android, MIPI0/HDMI has the same WM rotation always 331 */ 332 if (driver_data->mipi0_rotation != 0 || driver_data->rotation_dirty != 0) { 333 driver_data->mipi0_rotation = 0; 334 driver_data->hdmi_rotation = 0; 335 driver_data->rotation_dirty = 0; 336 output->new_destbox = 1; 337 psb_RecalcRotate(ctx, CONTEXT(obj_surface->context_id)); 338 } 339 340 psb_HDMIExt_get_prop(output, &crtc_width, &crtc_height); 341 342 /*recalculate the render box to fit the ratio of height/width*/ 343 if ((driver_data->extend_rotation == VA_ROTATION_90) || 344 (driver_data->extend_rotation == VA_ROTATION_270)) 345 _slope_xy = (float)srcw / srch; 346 else 347 _slope_xy = (float)srch / srcw; 348 349 _destw = (short)(crtc_height / _slope_xy); 350 _desth = (short)(crtc_width * _slope_xy); 351 if (_destw <= crtc_width) { 352 _desth = crtc_height; 353 _pos_x = (crtc_width - _destw) >> 1; 354 _pos_y = 0; 355 } else { 356 _destw = crtc_width; 357 _pos_x = 0; 358 _pos_y = (crtc_height - _desth) >> 1; 359 } 360 driver_data->render_rect.x = _pos_x; 361 driver_data->render_rect.y = _pos_y; 362 driver_data->render_rect.width = _destw; 363 driver_data->render_rect.height = _desth; 364 drv_debug_msg(VIDEO_DEBUG_GENERAL, "HDMI mode is on (%d), Render Rect: (%d,%d,%d,%d)\n", 365 *hdmi_mode, 366 driver_data->render_rect.x, driver_data->render_rect.y, 367 driver_data->render_rect.width, driver_data->render_rect.height); 368 return 0; 369 } 370 371 /* HDMI is not enabled */ 372 psb_android_surfaceflinger_status(android_isurface, &output->sf_composition, &rotation, &widi); 373 /*Update output destbox using layerbuffer's visible region*/ 374 psb_update_destbox(ctx); 375 376 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_COVERLAY) 377 || (driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXSTREAMING)) 378 return 0; 379 380 /*If overlay can not get correct destbox, use texstreaming.*/ 381 if (output->destw == 0 || output->desth == 0 || 382 ((output->destw == srcw) && (output->desth == srch))) { 383 drv_debug_msg(VIDEO_DEBUG_GENERAL, "No proper destbox, use texstreaming (%dx%d+%d+%d)\n", 384 output->destw, output->desth, output->destx, output->desty); 385 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING; 386 return 0; 387 } 388 389 /* only care local rotation */ 390 delta_rotation = Rotation2Angle(driver_data->mipi0_rotation) - Rotation2Angle(rotation); 391 if ((((abs(delta_rotation) == 90) || (abs(delta_rotation) == 270)) && output->new_destbox) || 392 (abs(delta_rotation) == 180)) { 393 drv_debug_msg(VIDEO_DEBUG_GENERAL, "New rotation degree %d of MIPI0 WM, Need to recalc rotation\n", rotation); 394 driver_data->mipi0_rotation = rotation; 395 driver_data->hdmi_rotation = rotation; 396 driver_data->rotation_dirty |= PSB_NEW_WM_ROTATION; 397 } 398 output->new_destbox = 0; 399 400 if (driver_data->rotation_dirty != 0) { 401 psb_RecalcRotate(ctx, CONTEXT(obj_surface->context_id)); 402 driver_data->rotation_dirty = 0; 403 } 404 405 if (GET_SURFACE_INFO_protect(obj_surface->psb_surface)) { 406 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Protected surface, use overlay\n"); 407 driver_data->output_method = PSB_PUTSURFACE_COVERLAY; 408 409 return 0; 410 } 411 412 if (widi == eWidiClone) { 413 drv_debug_msg(VIDEO_DEBUG_GENERAL, "WIDI in clone mode, use texstreaming\n"); 414 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING; 415 driver_data->msvdx_rotate_want = 0;/* disable msvdx rotae */ 416 417 return 0; 418 } 419 if (widi == eWidiExtendedVideo) { 420 drv_debug_msg(VIDEO_DEBUG_GENERAL, "WIDI in extend video mode, disable local displaying\n"); 421 driver_data->output_method = PSB_PUTSURFACE_NONE; 422 driver_data->msvdx_rotate_want = 0;/* disable msvdx rotae */ 423 424 return 0; 425 } 426 427 if (output->sf_composition) { 428 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Composition is detected, use texstreaming\n"); 429 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING; 430 return 0; 431 } 432 433 srf_rotate = GET_SURFACE_INFO_rotate(obj_surface->psb_surface); 434 rotate_surface = obj_surface->out_loop_surface; 435 if (rotate_surface != NULL) 436 rotate_srf_rotate = GET_SURFACE_INFO_rotate(rotate_surface); 437 438 drv_debug_msg(VIDEO_DEBUG_GENERAL, "SF rotation %d, VA rotation %d, final MSVDX rotation %d\n", 439 rotation, driver_data->va_rotate, driver_data->local_rotation); 440 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Primary surface rotation %d, rotated surface rotation %d\n", 441 srf_rotate, rotate_srf_rotate); 442 443 /* The surface rotation is not same with the final rotation */ 444 if ((driver_data->local_rotation != 0) && 445 ((srf_rotate != driver_data->local_rotation) || (rotate_srf_rotate != driver_data->local_rotation))) { 446 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Use texstreaming due to different VA surface rotation and final rotaion\n", 447 srf_rotate, rotate_srf_rotate); 448 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING; 449 return 0; 450 } 451 452 driver_data->output_method = PSB_PUTSURFACE_COVERLAY; 453 454 return 0; 455 } 456 #endif 457 458 VAStatus psb_PutSurface( 459 VADriverContextP ctx, 460 VASurfaceID surface, 461 void __maybe_unused * android_isurface, 462 short srcx, 463 short srcy, 464 unsigned short srcw, 465 unsigned short srch, 466 short destx, 467 short desty, 468 unsigned short destw, 469 unsigned short desth, 470 VARectangle *cliprects, /* client supplied clip list */ 471 unsigned int number_cliprects, /* number of clip rects in the clip list */ 472 unsigned int flags /* de-interlacing flags */ 473 ) 474 { 475 INIT_DRIVER_DATA; 476 INIT_OUTPUT_PRIV; 477 object_surface_p obj_surface; 478 VAStatus vaStatus = VA_STATUS_SUCCESS; 479 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 480 int ret = 0; 481 482 #ifndef BAYTRAIL 483 484 obj_surface = SURFACE(surface); 485 486 // psb__dump_NV_buffers(obj_surface,srcx,srcy,srcw,srch); 487 CHECK_SURFACE(obj_surface); 488 CHECK_INVALID_PARAM((NULL == cliprects) && (0 != number_cliprects)); 489 490 if ((srcx < 0) || (srcx > obj_surface->width) || (srcw > (obj_surface->width - srcx)) || 491 (srcy < 0) || (srcy > obj_surface->height_origin) || (srch > (obj_surface->height_origin - srcy))) { 492 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: source rectangle passed from upper layer is not correct.\n"); 493 return VA_STATUS_ERROR_UNKNOWN; 494 } 495 if ((destx < 0) || (desty < 0)) { 496 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: dest rectangle passed from upper layer is not correct.\n"); 497 return VA_STATUS_ERROR_UNKNOWN; 498 } 499 500 if (driver_data->dummy_putsurface) { 501 drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: dummy mode, return directly\n"); 502 return VA_STATUS_SUCCESS; 503 } 504 505 /* init overlay */ 506 if (!driver_data->coverlay_init) { 507 ret = psb_coverlay_init(ctx); 508 if (ret != 0) { 509 drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: psb_coverlay_init failed. Fallback to texture streaming.\n"); 510 driver_data->coverlay_init = 0; 511 } else 512 driver_data->coverlay_init = 1; 513 } 514 515 /* set the current displaying video frame into kernel */ 516 psb_surface_set_displaying(driver_data, obj_surface->width, 517 obj_surface->height_origin, 518 obj_surface->psb_surface); 519 520 /* local video playback */ 521 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MIPI: Use overlay to display.\n"); 522 523 /*initialize output destbox using default destbox if it has not been initialized until here.*/ 524 if (output->destw == 0 || output->desth == 0) { 525 output->destx = (destx > 0) ? destx : 0; 526 output->desty = (desty > 0) ? desty : 0; 527 output->destw = ((output->destx + destw) > output->screen_width) ? (output->screen_width - output->destx) : destw; 528 output->desth = ((output->desty + desth) > output->screen_height) ? (output->screen_height - output->desty) : desth; 529 } 530 531 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overlay position = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth); 532 srcw = srcw <= 2047? srcw : 2047; 533 vaStatus = psb_putsurface_overlay(ctx, surface, 534 srcx, srcy, srcw, srch, 535 output->destx, output->desty, output->destw, output->desth, 536 flags, OVERLAY_A, PIPEA); 537 538 driver_data->frame_count++; 539 #endif 540 return vaStatus; 541 } 542