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 /*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 = NULL;
    585     bool rotate_surfaceAlloc = false;
    586     VAStatus vaStatus = VA_STATUS_SUCCESS;
    587     int need_realloc = 0;
    588     unsigned int flags = 0;
    589     psb_surface_share_info_p share_info = obj_surface->share_info;
    590     psb_driver_data_p driver_data = obj_context->driver_data;
    591     int rotate_stride = 0, rotate_tiling = 0;
    592     object_config_p obj_config = CONFIG(obj_context->config_id);
    593     unsigned char * surface_data;
    594 
    595     CHECK_CONFIG(obj_config);
    596 
    597     rotate_surface = obj_surface->out_loop_surface;
    598 
    599     if (msvdx_rotate == 0
    600 #ifdef OVERLAY_ENABLE_MIRROR
    601         /*Bypass 180 degree rotate when overlay enabling mirror*/
    602         || msvdx_rotate == VA_ROTATION_180
    603 #endif
    604         )
    605         return vaStatus;
    606 
    607     if (rotate_surface) {
    608         CHECK_SURFACE_REALLOC(rotate_surface, msvdx_rotate, need_realloc);
    609         if (need_realloc == 0) {
    610             goto exit;
    611         } else { /* free the old rotate surface */
    612             /*FIX ME: it is not safe to do that because surfaces may be in use for rendering.*/
    613             psb_surface_destroy(obj_surface->out_loop_surface);
    614             memset(rotate_surface, 0, sizeof(*rotate_surface));
    615         }
    616     } else {
    617         rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    618         CHECK_ALLOCATION(rotate_surface);
    619         rotate_surfaceAlloc = true;
    620     }
    621 
    622 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    623     SET_SURFACE_INFO_tiling(rotate_surface, GET_SURFACE_INFO_tiling(obj_surface->psb_surface));
    624 #endif
    625 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
    626     SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate);
    627 #endif
    628     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Try to allocate surface for alternative rotate output\n");
    629 
    630     flags = IS_ROTATED;
    631 
    632     if (msvdx_rotate == 2 /* VA_ROTATION_180 */) {
    633         width = obj_surface->width;
    634         height = obj_surface->height;
    635 
    636 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
    637     if (obj_config->entrypoint == VAEntrypointVideoProc &&
    638             share_info && share_info->out_loop_khandle) {
    639             vaStatus = psb_surface_create_from_kbuf(driver_data, width, height,
    640                                   obj_surface->psb_surface->size, VA_FOURCC_NV12,
    641                                   share_info->out_loop_khandle,
    642                                   obj_surface->psb_surface->stride,
    643                                   obj_surface->psb_surface->stride,
    644                                   obj_surface->psb_surface->stride,
    645                                   0, 0, 0, rotate_surface);
    646     } else
    647 #endif
    648             vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12,
    649                                       flags, rotate_surface);
    650     } else {
    651         width = obj_surface->height_origin;
    652         height = (obj_surface->width + 0x1f) & ~0x1f;
    653 
    654 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
    655         if (obj_config->entrypoint == VAEntrypointVideoProc &&
    656                 share_info && share_info->out_loop_khandle != 0) {
    657                 drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create the surface from kbuf out_loop_khandle=%x!\n", share_info->out_loop_khandle);
    658                 rotate_tiling = GET_SURFACE_INFO_tiling(rotate_surface);
    659                 rotate_stride = get_surface_stride(width, rotate_tiling);
    660                 vaStatus = psb_surface_create_from_kbuf(driver_data, width, height,
    661                                   (rotate_stride * height * 3) / 2, VA_FOURCC_NV12,
    662                                   share_info->out_loop_khandle,
    663                                   rotate_stride, rotate_stride, rotate_stride,
    664                                   0, rotate_stride * height, rotate_stride * height,
    665                                   rotate_surface);
    666         } else
    667 #endif
    668         {
    669             drv_debug_msg(VIDEO_DEBUG_GENERAL,"Create rotated buffer. width=%d, height=%d\n", width, height);
    670             if (CONTEXT_SCALING(obj_context)) {
    671                 width = obj_context->scaling_buffer_height;
    672                 height = (obj_context->scaling_buffer_width+ 0x1f) & ~0x1f;
    673             }
    674             vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12,
    675                                       flags, rotate_surface);
    676         }
    677     }
    678     if (VA_STATUS_SUCCESS != vaStatus) {
    679         free(rotate_surface);
    680         obj_surface->out_loop_surface = NULL;
    681         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    682         DEBUG_FAILURE;
    683         return vaStatus;
    684     }
    685 
    686     //clear rotation surface
    687      if (CONTEXT_SCALING(obj_context)) {
    688         if (psb_buffer_map(&rotate_surface->buf, &surface_data)) {
    689             drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to map rotation buffer before clear it");
    690         }
    691         else {
    692             memset(surface_data, 0, rotate_surface->chroma_offset);
    693             memset(surface_data + rotate_surface->chroma_offset, 0x80,
    694                        rotate_surface->size - rotate_surface->chroma_offset);
    695             psb_buffer_unmap(&rotate_surface->buf);
    696         }
    697     }
    698     obj_surface->width_r = width;
    699     obj_surface->height_r = height;
    700 
    701 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    702     drv_debug_msg(VIDEO_DEBUG_GENERAL, "attempt to update tile context\n");
    703     if (GET_SURFACE_INFO_tiling(rotate_surface) && obj_config->entrypoint != VAEntrypointVideoProc) {
    704         drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context\n");
    705         object_context_p obj_context = CONTEXT(obj_surface->context_id);
    706         if (NULL == obj_context) {
    707             vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
    708             DEBUG_FAILURE;
    709             if (rotate_surface != NULL && rotate_surfaceAlloc) {
    710                 free(rotate_surface);
    711                 rotate_surface = NULL;
    712             }
    713             return vaStatus;
    714         }
    715         unsigned long msvdx_tile = psb__tile_stride_log2_256(obj_surface->width_r);
    716         obj_context->msvdx_tile &= 0xf; /* clear rotate tile */
    717         obj_context->msvdx_tile |= (msvdx_tile << 4);
    718         obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */
    719         obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
    720         psb_update_context(driver_data, obj_context->ctp_type);
    721     }
    722 #endif
    723 
    724 exit:
    725     obj_surface->out_loop_surface = rotate_surface;
    726     SET_SURFACE_INFO_rotate(rotate_surface, msvdx_rotate);
    727     /* derive the protected flag from the primay surface */
    728     SET_SURFACE_INFO_protect(rotate_surface,
    729                              GET_SURFACE_INFO_protect(obj_surface->psb_surface));
    730 
    731     /*notify hwc that rotated buffer is ready to use.
    732     * TODO: Do these in psb_SyncSurface()
    733     */
    734     if (share_info != NULL) {
    735 	share_info->width_r = rotate_surface->stride;
    736         share_info->height_r = obj_surface->height_r;
    737         share_info->out_loop_khandle =
    738             (uint32_t)(wsbmKBufHandle(wsbmKBuf(rotate_surface->buf.drm_buf)));
    739         share_info->metadata_rotate = VAROTATION2HAL(driver_data->va_rotate);
    740         share_info->surface_rotate = VAROTATION2HAL(msvdx_rotate);
    741 
    742         share_info->out_loop_luma_stride = rotate_surface->stride;
    743         share_info->out_loop_chroma_u_stride = rotate_surface->stride;
    744         share_info->out_loop_chroma_v_stride = rotate_surface->stride;
    745     }
    746 
    747     return vaStatus;
    748 }
    749 
    750 VAStatus psb_DestroyRotateBuffer(
    751     object_context_p obj_context,
    752     object_surface_p obj_surface)
    753 {
    754     VAStatus vaStatus = VA_STATUS_SUCCESS;
    755     psb_surface_share_info_p share_info = obj_surface->share_info;
    756     psb_driver_data_p driver_data = obj_context->driver_data;
    757     psb_surface_p rotate_surface = obj_surface->out_loop_surface;
    758     struct psb_buffer_s psb_buf;
    759 
    760     if (share_info && share_info->out_loop_khandle) {
    761         drv_debug_msg(VIDEO_DEBUG_GENERAL,"psb_DestroyRotateBuffer out_loop_khandle=%x\n", share_info->out_loop_khandle);
    762         vaStatus = psb_kbuffer_reference(driver_data, &psb_buf, share_info->out_loop_khandle);
    763         if (vaStatus != VA_STATUS_SUCCESS)
    764             return vaStatus;
    765         psb_buffer_destroy(&psb_buf);
    766         share_info->out_loop_khandle = 0;
    767     }
    768 
    769     if (rotate_surface)
    770         free(rotate_surface);
    771 
    772     return vaStatus;
    773 }
    774 
    775