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