Home | History | Annotate | Download | only in src
      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 #define CHECK_SURFACE_REALLOC(psb_surface, msvdx_rotate, need)  \
     62 do {                                                            \
     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 
     81 static 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 
    112 static 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 
    121 void 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 
    161 void 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 
    366 void 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  */
    425 VAStatus 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  */
    453 static 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 
    466 VAStatus 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
    551 VAStatus 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  */
    563 VAStatus 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 
    704 exit:
    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 
    730 VAStatus 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