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