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 * Zeng Li <zeng.li@intel.com> 26 * Jason Hu <jason.hu@intel.com> 27 * Shengquan Yuan <shengquan.yuan@intel.com> 28 */ 29 30#include <va/va.h> 31#include <va/va_backend.h> 32#include <va/va_backend_tpi.h> 33#include <va/va_backend_egl.h> 34#include <va/va_drmcommon.h> 35#include "psb_drv_video.h" 36#include "psb_output.h" 37#include "android/psb_android_glue.h" 38#include "psb_drv_debug.h" 39#include "vc1_defs.h" 40#include "pnw_rotate.h" 41#include <stdio.h> 42#include <string.h> 43#include <stdarg.h> 44#include <time.h> 45#include <unistd.h> 46#include <wsbm/wsbm_pool.h> 47#include <wsbm/wsbm_manager.h> 48#include <wsbm/wsbm_util.h> 49#include <wsbm/wsbm_fencemgr.h> 50 51#ifdef ANROID 52#include <system/graphics.h> 53#endif 54 55#define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData 56#define INIT_OUTPUT_PRIV unsigned char* output = ((psb_driver_data_p)ctx->pDriverData)->ws_priv 57#define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 58#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 59#define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) 60 61#define CHECK_SURFACE_REALLOC(psb_surface, msvdx_rotate, need) \ 62do { \ 63 int old_rotate = GET_SURFACE_INFO_rotate(psb_surface); \ 64 switch (msvdx_rotate) { \ 65 case 2: /* 180 */ \ 66 if (old_rotate == 2) \ 67 need = 0; \ 68 else \ 69 need = 1; \ 70 break; \ 71 case 1: /* 90 */ \ 72 case 3: /* 270 */ \ 73 if (old_rotate == 1 || old_rotate == 3) \ 74 need = 0; \ 75 else \ 76 need = 1; \ 77 break; \ 78 } \ 79} while (0) 80 81static int get_surface_stride(int width, int tiling) 82{ 83 int stride = 0; 84 85 if (0) { 86 ; 87 } else if (512 >= width) { 88 stride = 512; 89 } else if (1024 >= width) { 90 stride = 1024; 91 } else if (1280 >= width) { 92 stride = 1280; 93#ifdef PSBVIDEO_MSVDX_DEC_TILING 94 if (tiling) { 95 stride = 2048; 96 } 97#endif 98 } else if (2048 >= width) { 99 stride = 2048; 100 } else if (4096 >= width) { 101 stride = 4096; 102 } else { 103 stride = (width + 0x3f) & ~0x3f; 104 } 105 106 return stride; 107} 108//#define OVERLAY_ENABLE_MIRROR 109 110#ifdef PSBVIDEO_MRFL_VPP 111 112static int isVppOn(void __maybe_unused *output) { 113#ifdef TARGET_HAS_MULTIPLE_DISPLAY 114 return psb_android_get_mds_vpp_state(output); 115#else 116 return psb_android_get_vpp_state(); 117#endif 118} 119#endif 120 121void psb_InitOutLoop(VADriverContextP ctx) 122{ 123 char env_value[64]; 124 INIT_DRIVER_DATA; 125 126 /* VA rotate from APP */ 127 driver_data->va_rotate = VA_ROTATION_NONE; 128 129 /* window manager rotation from OS */ 130 driver_data->mipi0_rotation = VA_ROTATION_NONE; 131 driver_data->mipi1_rotation = VA_ROTATION_NONE; 132 driver_data->hdmi_rotation = VA_ROTATION_NONE; 133 134 /* final rotation of VA rotate+WM rotate */ 135 driver_data->local_rotation = VA_ROTATION_NONE; 136 driver_data->extend_rotation = VA_ROTATION_NONE; 137 138 /* MSVDX rotate */ 139 driver_data->msvdx_rotate_want = ROTATE_VA2MSVDX(VA_ROTATION_NONE); 140 141 if (psb_parse_config("PSB_VIDEO_NOROTATE", &env_value[0]) == 0) { 142 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSVDX: disable MSVDX rotation\n"); 143 driver_data->disable_msvdx_rotate = 1; 144 } 145 /* FIXME: Disable rotation when VPP enabled, just a workround here*/ 146#ifdef PSBVIDEO_MRFL_VPP 147 if (isVppOn((void*)driver_data->ws_priv)) { 148 drv_debug_msg(VIDEO_DEBUG_GENERAL, "For VPP: disable MSVDX rotation\n"); 149 driver_data->disable_msvdx_rotate = 1; 150 driver_data->vpp_on = 1; 151 } 152#endif 153 154#ifdef BAYTRAIL 155 driver_data->disable_msvdx_rotate = 1; 156#endif 157 158 driver_data->disable_msvdx_rotate_backup = driver_data->disable_msvdx_rotate; 159} 160 161void psb_RecalcAlternativeOutput(object_context_p obj_context) 162{ 163 psb_driver_data_p driver_data = obj_context->driver_data; 164 object_surface_p obj_surface = obj_context->current_render_target; 165 int angle, new_rotate, i; 166 int old_rotate = driver_data->msvdx_rotate_want; 167 int mode = INIT_VALUE; 168#ifdef TARGET_HAS_MULTIPLE_DISPLAY 169 mode = psb_android_get_mds_mode((void*)driver_data->ws_priv); 170#endif 171 172 if (mode != INIT_VALUE) { 173 // clear device rotation info 174 if (driver_data->mipi0_rotation != VA_ROTATION_NONE) { 175 driver_data->mipi0_rotation = VA_ROTATION_NONE; 176 driver_data->hdmi_rotation = VA_ROTATION_NONE; 177 } 178 // Disable msvdx rotation if 179 // WIDI video is play and meta data rotation angle is 0 180 if (mode == WIDI_VIDEO_ISPLAYING) { 181 if (driver_data->va_rotate == VA_ROTATION_NONE) 182 driver_data->disable_msvdx_rotate = 1; 183 else { 184 driver_data->mipi0_rotation = 0; 185 driver_data->hdmi_rotation = 0; 186 driver_data->disable_msvdx_rotate = 0; 187 } 188 } else { 189 if (IS_MOFD(driver_data)) 190 driver_data->disable_msvdx_rotate = 1; 191 else 192 driver_data->disable_msvdx_rotate = driver_data->disable_msvdx_rotate_backup; 193 } 194 } else if (IS_MOFD(driver_data)) { 195 /* Moorefield has overlay rotaion, so decoder doesn't generate rotation 196 * output according to windows manager. It is controlled by payload info 197 * in which HWC signal decoder to generate rotation output 198 */ 199 long long hwc_timestamp = 0; 200 int index = -1; 201 202 for (i = 0; i < obj_context->num_render_targets; i++) { 203 object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]); 204 /* traverse all surfaces' share info to find out the latest transform info */ 205 if (obj_surface && obj_surface->share_info) { 206 if (obj_surface->share_info->hwc_timestamp > hwc_timestamp) { 207 hwc_timestamp = obj_surface->share_info->hwc_timestamp; 208 index = i; 209 } 210 } 211 } 212 if (index >= 0) { 213 object_surface_p obj_surface = SURFACE(obj_context->render_targets[index]); 214 if (obj_surface && obj_surface->share_info) { 215 int transform = obj_surface->share_info->layer_transform; 216 driver_data->mipi0_rotation = HAL2VAROTATION(transform); 217 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Signal from HWC to rotate %d\n", driver_data->mipi0_rotation); 218 } 219 } 220 } else if (driver_data->native_window) { 221 int display_rotate = 0; 222 psb_android_surfaceflinger_rotate(driver_data->native_window, &display_rotate); 223 drv_debug_msg(VIDEO_DEBUG_GENERAL, "NativeWindow(0x%x), get surface flinger rotate %d\n", driver_data->native_window, display_rotate); 224 225 if (driver_data->mipi0_rotation != display_rotate) { 226 driver_data->mipi0_rotation = display_rotate; 227 } 228 } else { 229 long long hwc_timestamp = 0; 230 int index = -1; 231 232 for (i = 0; i < obj_context->num_render_targets; i++) { 233 object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]); 234 /* traverse all surfaces' share info to find out the latest transform info */ 235 if (obj_surface && obj_surface->share_info) { 236 if (obj_surface->share_info->hwc_timestamp > hwc_timestamp) { 237 hwc_timestamp = obj_surface->share_info->hwc_timestamp; 238 index = i; 239 } 240 } 241 } 242 if (index >= 0) { 243 object_surface_p obj_surface = SURFACE(obj_context->render_targets[index]); 244 if (obj_surface && obj_surface->share_info) { 245 int transform = obj_surface->share_info->layer_transform; 246 driver_data->mipi0_rotation = HAL2VAROTATION(transform); 247 } 248 } 249 } 250 251#ifdef PSBVIDEO_MRFL 252 if ((mode == HDMI_VIDEO_ISPLAYING) && driver_data->native_window) { 253 int display_rotate = 0; 254 psb_android_surfaceflinger_rotate(driver_data->native_window, &display_rotate); 255 drv_debug_msg(VIDEO_DEBUG_GENERAL, "NativeWindow(0x%x), get surface flinger rotate %d\n", driver_data->native_window, display_rotate); 256 257 if (driver_data->mipi0_rotation != display_rotate && !IS_MOFD(driver_data)) { 258 driver_data->mipi0_rotation = display_rotate; 259 } 260 } 261#endif 262 263 /* calc VA rotation and WM rotation, and assign to the final rotation degree */ 264 angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->mipi0_rotation); 265 driver_data->local_rotation = Angle2Rotation(angle); 266 angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->hdmi_rotation); 267 driver_data->extend_rotation = Angle2Rotation(angle); 268 269 /* On MOFD, no need to use meta rotation, just use rotation angle signal from HWC */ 270 if (IS_MOFD(driver_data)) { 271 driver_data->local_rotation = driver_data->mipi0_rotation; 272 driver_data->extend_rotation = Rotation2Angle(driver_data->hdmi_rotation); 273 } 274 275 /* for any case that local and extened rotation are not same, fallback to GPU */ 276 if ((driver_data->mipi1_rotation != VA_ROTATION_NONE) || 277 ((driver_data->local_rotation != VA_ROTATION_NONE) && 278 (driver_data->extend_rotation != VA_ROTATION_NONE) && 279 (driver_data->local_rotation != driver_data->extend_rotation))) { 280 new_rotate = ROTATE_VA2MSVDX(driver_data->local_rotation); 281 if (driver_data->is_android == 0) /*fallback to texblit path*/ 282 driver_data->output_method = PSB_PUTSURFACE_CTEXTURE; 283 } else { 284 if (driver_data->local_rotation == VA_ROTATION_NONE) 285 new_rotate = driver_data->extend_rotation; 286 else 287 new_rotate = driver_data->local_rotation; 288 289 if (driver_data->is_android == 0) { 290 if (driver_data->output_method != PSB_PUTSURFACE_FORCE_CTEXTURE) 291 driver_data->output_method = PSB_PUTSURFACE_COVERLAY; 292 } 293 } 294 295 if (old_rotate != new_rotate) { 296 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSVDX: new rotation %d desired\n", new_rotate); 297 driver_data->msvdx_rotate_want = new_rotate; 298 } 299 300#ifdef TARGET_HAS_MULTIPLE_DISPLAY 301 int scaling_buffer_width = 1920, scaling_buffer_height = 1080 ; 302 int scaling_width = 0, scaling_height = 0; 303 int scaling_offset_x = 0, scaling_offset_y = 0; 304 int old_bufw = 0, old_bufh = 0, old_x = 0, old_y = 0, old_w = 0, old_h = 0; 305 int bScaleChanged = 0, size = 0; 306 unsigned char * surface_data; 307 308 int ret = psb_android_get_mds_decoder_output_resolution( 309 (void*)driver_data->ws_priv, 310 &scaling_width, &scaling_height, 311 &scaling_offset_x, &scaling_offset_y, 312 &scaling_buffer_width, &scaling_buffer_height); 313 314 if ((old_bufw != scaling_buffer_width) || (old_bufh != scaling_buffer_height) || 315 (old_x != scaling_offset_x) || (old_y != scaling_offset_y) || 316 (old_w != scaling_width) || (old_h != scaling_height)) { 317 bScaleChanged = 1; 318 } 319 320 old_x = scaling_offset_x; 321 old_y = scaling_offset_y; 322 old_w = scaling_width; 323 old_h = scaling_height; 324 old_bufw = scaling_buffer_width; 325 old_bufh = scaling_buffer_height; 326 327 /* turn off ved downscaling if width and height are 0. 328 * Besides, scaling_width and scaling_height must be a multiple of 2. 329 */ 330 if (!ret || (!scaling_width || !scaling_height) || 331 (scaling_width & 1) || (scaling_height & 1)) { 332 obj_context->msvdx_scaling = 0; 333 obj_context->scaling_width = 0; 334 obj_context->scaling_height = 0; 335 obj_context->scaling_offset_x= 0; 336 obj_context->scaling_offset_y = 0; 337 obj_context->scaling_buffer_width = 0; 338 obj_context->scaling_buffer_height = 0; 339 } else { 340 obj_context->msvdx_scaling = 1; 341 obj_context->scaling_width = scaling_width; 342 obj_context->scaling_height = scaling_height; 343 obj_context->scaling_offset_x= scaling_offset_x; 344 obj_context->scaling_offset_y = scaling_offset_y; 345 obj_context->scaling_buffer_width = scaling_buffer_width; 346 obj_context->scaling_buffer_height = scaling_buffer_height; 347 } 348 if (bScaleChanged) { 349 if ((obj_surface != NULL) && 350 (obj_surface->out_loop_surface != NULL)) { 351 if (psb_buffer_map(&obj_surface->out_loop_surface->buf, &surface_data)) { 352 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to map rotation buffer before clear it"); 353 } 354 else { 355 size = obj_surface->out_loop_surface->chroma_offset; 356 memset(surface_data, 0, size); 357 memset(surface_data + size, 0x80, obj_surface->out_loop_surface->size - size); 358 psb_buffer_unmap(&obj_context->current_render_target->out_loop_surface->buf); 359 } 360 } 361 } 362#endif 363} 364 365 366void psb_CheckInterlaceRotate(object_context_p obj_context, unsigned char *pic_param_tmp) 367{ 368 object_surface_p obj_surface = obj_context->current_render_target; 369 370 switch (obj_context->profile) { 371 case VAProfileMPEG2Simple: 372 case VAProfileMPEG2Main: 373 break; 374 case VAProfileMPEG4Simple: 375 case VAProfileMPEG4AdvancedSimple: 376 case VAProfileMPEG4Main: 377 case VAProfileH263Baseline: { 378 VAPictureParameterBufferMPEG4 *pic_params = (VAPictureParameterBufferMPEG4 *)pic_param_tmp; 379 380 if (pic_params->vol_fields.bits.interlaced) 381 obj_context->interlaced_stream = 1; /* is it the right way to check? */ 382 break; 383 } 384 case VAProfileH264Baseline: 385 case VAProfileH264Main: 386 case VAProfileH264High: 387 case VAProfileH264ConstrainedBaseline: { 388 VAPictureParameterBufferH264 *pic_params = (VAPictureParameterBufferH264 *)pic_param_tmp; 389 /* is it the right way to check? */ 390 if (pic_params->pic_fields.bits.field_pic_flag || pic_params->seq_fields.bits.mb_adaptive_frame_field_flag) 391 obj_context->interlaced_stream = 1; 392 393 break; 394 } 395 case VAProfileVC1Simple: 396 case VAProfileVC1Main: 397 case VAProfileVC1Advanced: { 398 VAPictureParameterBufferVC1 *pic_params = (VAPictureParameterBufferVC1 *)pic_param_tmp; 399 400 /* is it the right way to check? */ 401 if (pic_params->sequence_fields.bits.interlace) 402 obj_context->interlaced_stream = 1; 403 404 break; 405 } 406 default: 407 break; 408 } 409 410 if (obj_surface->share_info) { 411 psb_surface_share_info_p share_info = obj_surface->share_info; 412 if (obj_context->interlaced_stream) { 413 SET_SURFACE_INFO_rotate(obj_surface->psb_surface, 0); 414 obj_context->msvdx_rotate = 0; 415 share_info->bob_deinterlace = 1; 416 } else { 417 share_info->bob_deinterlace = 0; 418 } 419 } 420} 421#if 0 422/* 423 * Detach a surface from obj_surface 424 */ 425VAStatus psb_DestroyRotateSurface( 426 VADriverContextP ctx, 427 object_surface_p obj_surface, 428 int rotate 429) 430{ 431 INIT_DRIVER_DATA; 432 psb_surface_p psb_surface = obj_surface->out_loop_surface; 433 VAStatus vaStatus = VA_STATUS_SUCCESS; 434 435 /* Allocate alternative output surface */ 436 if (psb_surface) { 437 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Try to allocate surface for alternative rotate output\n"); 438 psb_surface_destroy(obj_surface->out_loop_surface); 439 free(psb_surface); 440 441 obj_surface->out_loop_surface = NULL; 442 obj_surface->width_r = obj_surface->width; 443 obj_surface->height_r = obj_surface->height; 444 } 445 446 return vaStatus; 447} 448#endif 449#ifdef TARGET_HAS_MULTIPLE_DISPLAY 450/* 451 * Create and attach a downscaling surface to obj_surface 452 */ 453static void clearScalingInfo(psb_surface_share_info_p share_info) { 454 if (share_info == NULL) 455 return; 456 share_info->width_s = 0; 457 share_info->height_s = 0; 458 share_info->scaling_khandle = 0; 459 460 share_info->scaling_luma_stride = 0; 461 share_info->scaling_chroma_u_stride = 0; 462 share_info->scaling_chroma_v_stride = 0; 463 return; 464} 465 466VAStatus psb_CreateScalingSurface( 467 object_context_p obj_context, 468 object_surface_p obj_surface 469) 470{ 471 psb_surface_p psb_surface; 472 VAStatus vaStatus = VA_STATUS_SUCCESS; 473 psb_surface_share_info_p share_info = obj_surface->share_info; 474 unsigned int set_flags, clear_flags; 475 int ret = 0; 476 477 if (obj_context->driver_data->render_rect.width <= obj_context->scaling_width || obj_context->driver_data->render_rect.height <= obj_context->scaling_height) { 478 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Either downscaling is not required or upscaling is needed for the target resolution\n"); 479 obj_context->msvdx_scaling = 0; /* Disable downscaling */ 480 clearScalingInfo(share_info); 481 return VA_STATUS_ERROR_OPERATION_FAILED; 482 } 483 484 psb_surface = obj_surface->scaling_surface; 485 /* Check if downscaling resolution has been changed */ 486 if (psb_surface) { 487 if (obj_surface->width_s != obj_context->scaling_width || obj_surface->height_s != obj_context->scaling_height) { 488 psb_surface_destroy(psb_surface); 489 free(psb_surface); 490 psb_surface = NULL; 491 492 drv_debug_msg(VIDEO_DEBUG_GENERAL, "downscaling buffer realloc: %d x %d -> %d x %d\n", 493 obj_surface->width_s, obj_surface->height_s, obj_context->scaling_width, obj_context->scaling_height); 494 clearScalingInfo(share_info); 495 } 496 } 497 498 if (!psb_surface) { 499 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Try to allocate surface for alternative scaling output: %dx%d\n", 500 obj_context->scaling_width, obj_context->scaling_height); 501 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 502 CHECK_ALLOCATION(psb_surface); 503 504 vaStatus = psb_surface_create(obj_context->driver_data, obj_context->scaling_width, 505 (obj_context->scaling_height + 0x1f) & ~0x1f, VA_FOURCC_NV12, 506 0, psb_surface); 507 508 //set_flags = WSBM_PL_FLAG_CACHED | DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED; 509 //clear_flags = WSBM_PL_FLAG_UNCACHED | WSBM_PL_FLAG_WC; 510 //ret = psb_buffer_setstatus(&psb_surface->buf, set_flags, clear_flags); 511 512 if (VA_STATUS_SUCCESS != vaStatus || ret) { 513 drv_debug_msg(VIDEO_DEBUG_GENERAL, "allocate scaling buffer fail\n"); 514 free(psb_surface); 515 obj_surface->scaling_surface = NULL; 516 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 517 DEBUG_FAILURE; 518 return vaStatus; 519 } 520 521 obj_surface->width_s = obj_context->scaling_width; 522 obj_surface->height_s = obj_context->scaling_height; 523 obj_surface->buffer_width_s = obj_context->scaling_width; 524 obj_surface->buffer_height_s = obj_context->scaling_height; 525 obj_surface->offset_x_s= obj_context->scaling_offset_x; 526 obj_surface->offset_y_s= obj_context->scaling_offset_y; 527 obj_context->scaling_update = 1; 528 } 529 obj_surface->scaling_surface = psb_surface; 530 531 /* derive the protected flag from the primay surface */ 532 SET_SURFACE_INFO_protect(psb_surface, 533 GET_SURFACE_INFO_protect(obj_surface->psb_surface)); 534 535 /*notify hwc that rotated buffer is ready to use. 536 * TODO: Do these in psb_SyncSurface() 537 */ 538 if (share_info != NULL) { 539 share_info->width_s = obj_surface->width_s; 540 share_info->height_s = obj_surface->height_s; 541 share_info->scaling_khandle = 542 (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf))); 543 544 share_info->scaling_luma_stride = psb_surface->stride; 545 share_info->scaling_chroma_u_stride = psb_surface->stride; 546 share_info->scaling_chroma_v_stride = psb_surface->stride; 547 } 548 return vaStatus; 549} 550#else 551VAStatus psb_CreateScalingSurface( 552 object_context_p __maybe_unused obj_context, 553 object_surface_p __maybe_unused obj_surface 554) 555{ 556 return VA_STATUS_ERROR_OPERATION_FAILED; 557} 558#endif 559 560/* 561 * Create and attach a rotate surface to obj_surface 562 */ 563VAStatus psb_CreateRotateSurface( 564 object_context_p obj_context, 565 object_surface_p obj_surface, 566 int msvdx_rotate 567) 568{ 569 int width, height; 570 psb_surface_p rotate_surface; 571 VAStatus vaStatus = VA_STATUS_SUCCESS; 572 int need_realloc = 0; 573 unsigned int flags = 0; 574 psb_surface_share_info_p share_info = obj_surface->share_info; 575 psb_driver_data_p driver_data = obj_context->driver_data; 576 int rotate_stride = 0, rotate_tiling = 0; 577 object_config_p obj_config = CONFIG(obj_context->config_id); 578 unsigned char * surface_data; 579 580 CHECK_CONFIG(obj_config); 581 582 rotate_surface = obj_surface->out_loop_surface; 583 584 if (msvdx_rotate == 0 585#ifdef OVERLAY_ENABLE_MIRROR 586 /*Bypass 180 degree rotate when overlay enabling mirror*/ 587 || msvdx_rotate == VA_ROTATION_180 588#endif 589 ) 590 return vaStatus; 591 592 if (rotate_surface) { 593 CHECK_SURFACE_REALLOC(rotate_surface, msvdx_rotate, need_realloc); 594 if (need_realloc == 0) { 595 goto exit; 596 } else { /* free the old rotate surface */ 597 /*FIX ME: it is not safe to do that because surfaces may be in use for rendering.*/ 598 psb_surface_destroy(obj_surface->out_loop_surface); 599 memset(rotate_surface, 0, sizeof(*rotate_surface)); 600 } 601 } else { 602 rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 603 CHECK_ALLOCATION(rotate_surface); 604 } 605 606#ifdef PSBVIDEO_MSVDX_DEC_TILING 607 SET_SURFACE_INFO_tiling(rotate_surface, GET_SURFACE_INFO_tiling(obj_surface->psb_surface)); 608#endif 609#ifdef PSBVIDEO_MRFL_VPP_ROTATE 610 SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate); 611#endif 612 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Try to allocate surface for alternative rotate output\n"); 613 614 flags = IS_ROTATED; 615 616 if (msvdx_rotate == 2 /* VA_ROTATION_180 */) { 617 width = obj_surface->width; 618 height = obj_surface->height; 619 620#ifdef PSBVIDEO_MRFL_VPP_ROTATE 621 if (obj_config->entrypoint == VAEntrypointVideoProc && 622 share_info && share_info->out_loop_khandle) { 623 vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, 624 obj_surface->psb_surface->size, VA_FOURCC_NV12, 625 share_info->out_loop_khandle, 626 obj_surface->psb_surface->stride, 627 obj_surface->psb_surface->stride, 628 obj_surface->psb_surface->stride, 629 0, 0, 0, rotate_surface); 630 } else 631#endif 632 vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, 633 flags, rotate_surface); 634 } else { 635 width = obj_surface->height_origin; 636 height = (obj_surface->width + 0x1f) & ~0x1f; 637 638#ifdef PSBVIDEO_MRFL_VPP_ROTATE 639 if (obj_config->entrypoint == VAEntrypointVideoProc && 640 share_info && share_info->out_loop_khandle != 0) { 641 drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create the surface from kbuf out_loop_khandle=%x!\n", share_info->out_loop_khandle); 642 rotate_tiling = GET_SURFACE_INFO_tiling(rotate_surface); 643 rotate_stride = get_surface_stride(width, rotate_tiling); 644 vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, 645 (rotate_stride * height * 3) / 2, VA_FOURCC_NV12, 646 share_info->out_loop_khandle, 647 rotate_stride, rotate_stride, rotate_stride, 648 0, rotate_stride * height, rotate_stride * height, 649 rotate_surface); 650 } else 651#endif 652 { 653 drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create rotated buffer. width=%d, height=%d\n", width, height); 654 if (CONTEXT_SCALING(obj_context)) { 655 width = obj_context->scaling_buffer_height; 656 height = (obj_context->scaling_buffer_width+ 0x1f) & ~0x1f; 657 } 658 vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, 659 flags, rotate_surface); 660 } 661 } 662 if (VA_STATUS_SUCCESS != vaStatus) { 663 free(rotate_surface); 664 obj_surface->out_loop_surface = NULL; 665 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 666 DEBUG_FAILURE; 667 return vaStatus; 668 } 669 670 //clear rotation surface 671 if (CONTEXT_SCALING(obj_context)) { 672 if (psb_buffer_map(&rotate_surface->buf, &surface_data)) { 673 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to map rotation buffer before clear it"); 674 } 675 else { 676 memset(surface_data, 0, rotate_surface->chroma_offset); 677 memset(surface_data + rotate_surface->chroma_offset, 0x80, 678 rotate_surface->size - rotate_surface->chroma_offset); 679 psb_buffer_unmap(&rotate_surface->buf); 680 } 681 } 682 obj_surface->width_r = width; 683 obj_surface->height_r = height; 684 685#ifdef PSBVIDEO_MSVDX_DEC_TILING 686 drv_debug_msg(VIDEO_DEBUG_GENERAL, "attempt to update tile context\n"); 687 if (GET_SURFACE_INFO_tiling(rotate_surface) && obj_config->entrypoint != VAEntrypointVideoProc) { 688 drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context\n"); 689 object_context_p obj_context = CONTEXT(obj_surface->context_id); 690 if (NULL == obj_context) { 691 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 692 DEBUG_FAILURE; 693 return vaStatus; 694 } 695 unsigned long msvdx_tile = psb__tile_stride_log2_256(obj_surface->width_r); 696 obj_context->msvdx_tile &= 0xf; /* clear rotate tile */ 697 obj_context->msvdx_tile |= (msvdx_tile << 4); 698 obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */ 699 obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16); 700 psb_update_context(driver_data, obj_context->ctp_type); 701 } 702#endif 703 704exit: 705 obj_surface->out_loop_surface = rotate_surface; 706 SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate); 707 /* derive the protected flag from the primay surface */ 708 SET_SURFACE_INFO_protect(rotate_surface, 709 GET_SURFACE_INFO_protect(obj_surface->psb_surface)); 710 711 /*notify hwc that rotated buffer is ready to use. 712 * TODO: Do these in psb_SyncSurface() 713 */ 714 if (share_info != NULL) { 715 share_info->width_r = rotate_surface->stride; 716 share_info->height_r = obj_surface->height_r; 717 share_info->out_loop_khandle = 718 (uint32_t)(wsbmKBufHandle(wsbmKBuf(rotate_surface->buf.drm_buf))); 719 share_info->metadata_rotate = VAROTATION2HAL(driver_data->va_rotate); 720 share_info->surface_rotate = VAROTATION2HAL(msvdx_rotate); 721 722 share_info->out_loop_luma_stride = rotate_surface->stride; 723 share_info->out_loop_chroma_u_stride = rotate_surface->stride; 724 share_info->out_loop_chroma_v_stride = rotate_surface->stride; 725 } 726 727 return vaStatus; 728} 729 730VAStatus psb_DestroyRotateBuffer( 731 object_context_p obj_context, 732 object_surface_p obj_surface) 733{ 734 VAStatus vaStatus = VA_STATUS_SUCCESS; 735 psb_surface_share_info_p share_info = obj_surface->share_info; 736 psb_driver_data_p driver_data = obj_context->driver_data; 737 psb_surface_p rotate_surface = obj_surface->out_loop_surface; 738 struct psb_buffer_s psb_buf; 739 740 if (share_info && share_info->out_loop_khandle) { 741 drv_debug_msg(VIDEO_DEBUG_GENERAL,"psb_DestroyRotateBuffer out_loop_khandle=%x\n", share_info->out_loop_khandle); 742 vaStatus = psb_kbuffer_reference(driver_data, &psb_buf, share_info->out_loop_khandle); 743 if (vaStatus != VA_STATUS_SUCCESS) 744 return vaStatus; 745 psb_buffer_destroy(&psb_buf); 746 share_info->out_loop_khandle = 0; 747 } 748 749 if (rotate_surface) 750 free(rotate_surface); 751 752 return vaStatus; 753} 754 755