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  */
     25 
     26 #include <sys/mman.h>
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 #include <sys/ioctl.h>
     30 #include <fcntl.h>
     31 #include <malloc.h>
     32 #ifdef ANDROID
     33 #include <linux/ion.h>
     34 #endif
     35 #include <va/va_tpi.h>
     36 #include "psb_drv_video.h"
     37 #include "psb_drv_debug.h"
     38 #include "psb_surface.h"
     39 #include "psb_surface_attrib.h"
     40 
     41 
     42 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
     43 
     44 #define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
     45 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
     46 #define SURFACE(id)    ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
     47 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
     48 
     49 
     50 /*
     51  * Create surface
     52  */
     53 VAStatus psb_surface_create_from_ub(
     54     psb_driver_data_p driver_data,
     55     int width, int height, int fourcc,
     56     VASurfaceAttributeTPI *graphic_buffers,
     57     psb_surface_p psb_surface, /* out */
     58     void *vaddr,
     59     int fd,
     60     unsigned flags
     61 )
     62 {
     63     int ret = 0;
     64 
     65     if ((fourcc == VA_FOURCC_NV12) || (fourcc == VA_FOURCC_YV16) || (fourcc == VA_FOURCC_IYUV) || (fourcc == VA_FOURCC_RGBA)) {
     66         if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
     67             return VA_STATUS_ERROR_ALLOCATION_FAILED;
     68         }
     69 
     70         psb_surface->stride = graphic_buffers->luma_stride;
     71         if (0) {
     72             ;
     73         } else if (512 == graphic_buffers->luma_stride) {
     74             psb_surface->stride_mode = STRIDE_512;
     75         } else if (1024 == graphic_buffers->luma_stride) {
     76             psb_surface->stride_mode = STRIDE_1024;
     77         } else if (1280 == graphic_buffers->luma_stride) {
     78             psb_surface->stride_mode = STRIDE_1280;
     79         } else if (2048 == graphic_buffers->luma_stride) {
     80             psb_surface->stride_mode = STRIDE_2048;
     81         } else if (4096 == graphic_buffers->luma_stride) {
     82             psb_surface->stride_mode = STRIDE_4096;
     83         } else {
     84             psb_surface->stride_mode = STRIDE_NA;
     85         }
     86         if (psb_surface->stride != graphic_buffers->luma_stride) {
     87             return VA_STATUS_ERROR_ALLOCATION_FAILED;
     88         }
     89 
     90         psb_surface->luma_offset = 0;
     91         psb_surface->chroma_offset = psb_surface->stride * height;
     92 
     93         if (VA_FOURCC_NV12 == fourcc) {
     94             psb_surface->size = ((psb_surface->stride * height) * 3) / 2;
     95             psb_surface->extra_info[4] = VA_FOURCC_NV12;
     96         }
     97         else if (VA_FOURCC_YV16 == fourcc) {
     98             psb_surface->size = (psb_surface->stride * height) * 2;
     99             psb_surface->extra_info[4] = VA_FOURCC_YV16;
    100         }
    101         else if (VA_FOURCC_IYUV == fourcc) {
    102             psb_surface->size = ((psb_surface->stride * height) * 3) / 2;
    103             psb_surface->extra_info[4] = VA_FOURCC_IYUV;
    104         }
    105 	else if (VA_FOURCC_RGBA == fourcc) {
    106             psb_surface->size = (psb_surface->stride * height) * 4;
    107             psb_surface->extra_info[4] = VA_FOURCC_RGBA;
    108         }
    109 
    110         psb_surface->extra_info[8] = psb_surface->extra_info[4];
    111 
    112     } else {
    113         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    114     }
    115 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    116     if (graphic_buffers->tiling)
    117         ret = psb_buffer_create_from_ub(driver_data, psb_surface->size,
    118                 psb_bt_mmu_tiling, &psb_surface->buf,
    119                 vaddr, fd, 0);
    120     else
    121 #endif
    122         ret = psb_buffer_create_from_ub(driver_data, psb_surface->size,
    123                 psb_bt_surface, &psb_surface->buf,
    124                 vaddr, fd, flags);
    125 
    126     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    127 }
    128 
    129 #if 0
    130 VAStatus psb_CreateSurfaceFromV4L2Buf(
    131     VADriverContextP ctx,
    132     int v4l2_fd,         /* file descriptor of V4L2 device */
    133     struct v4l2_format *v4l2_fmt,       /* format of V4L2 */
    134     struct v4l2_buffer *v4l2_buf,       /* V4L2 buffer */
    135     VASurfaceID *surface        /* out */
    136 )
    137 {
    138     INIT_DRIVER_DATA;
    139     VAStatus vaStatus = VA_STATUS_SUCCESS;
    140     int surfaceID;
    141     object_surface_p obj_surface;
    142     psb_surface_p psb_surface;
    143     int width, height, buf_stride, buf_offset, size;
    144     unsigned long *user_ptr = NULL;
    145 
    146     if (IS_MRST(driver_data) == 0 && IS_MFLD(driver_data) == 0) {
    147         drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaceFromV4L2Buf isn't supported on non-MRST platform\n");
    148         return VA_STATUS_ERROR_UNKNOWN;
    149     }
    150 
    151     /* Todo:
    152      * sanity check if the v4l2 device on MRST is supported
    153      */
    154     if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) {
    155         unsigned long tmp = (unsigned long)(v4l2_buf->m.userptr);
    156 
    157         if (tmp & 0xfff) {
    158             drv_debug_msg(VIDEO_DEBUG_ERROR, "The buffer address 0x%08x must be page aligned\n", tmp);
    159             return VA_STATUS_ERROR_UNKNOWN;
    160         }
    161     }
    162 
    163     surfaceID = object_heap_allocate(&driver_data->surface_heap);
    164     obj_surface = SURFACE(surfaceID);
    165     CHECK_ALLOCATION(obj_surface);
    166 
    167     MEMSET_OBJECT(obj_surface, struct object_surface_s);
    168 
    169     width = v4l2_fmt->fmt.pix.width;
    170     height = v4l2_fmt->fmt.pix.height;
    171 
    172     buf_stride = width; /* ? */
    173     buf_offset = v4l2_buf->m.offset;
    174     size = v4l2_buf->length;
    175 
    176     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create Surface from V4L2 buffer: %dx%d, stride=%d, buffer offset=0x%08x, size=%d\n",
    177                              width, height, buf_stride, buf_offset, size);
    178 
    179     obj_surface->surface_id = surfaceID;
    180     *surface = surfaceID;
    181     obj_surface->context_id = -1;
    182     obj_surface->width = width;
    183     obj_surface->height = height;
    184     obj_surface->subpictures = NULL;
    185     obj_surface->subpic_count = 0;
    186     obj_surface->derived_imgcnt = 0;
    187     obj_surface->display_timestamp = 0;
    188 
    189     psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    190     if (NULL == psb_surface) {
    191         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    192         obj_surface->surface_id = VA_INVALID_SURFACE;
    193 
    194         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    195 
    196         DEBUG_FAILURE;
    197 
    198         return vaStatus;
    199     }
    200 
    201 #if PSB_MFLD_DUMMY_CODE
    202     /* current assume it is NV12 */
    203     if (IS_MRST(driver_data))
    204         vaStatus = psb_surface_create_camera(driver_data, width, height, buf_stride, size, psb_surface, 1, buf_offset);
    205     else {
    206         if (V4L2_MEMORY_USERPTR == v4l2_buf->memory)
    207             user_ptr = (unsigned long *)(v4l2_buf->m.userptr);
    208         else {
    209             user_ptr = mmap(NULL /* start anywhere */ ,
    210                             v4l2_buf->length,
    211                             PROT_READ ,
    212                             MAP_SHARED /* recommended */ ,
    213                             v4l2_fd, v4l2_buf->m.offset);
    214         }
    215 
    216         if (NULL != user_ptr && MAP_FAILED != user_ptr)
    217             vaStatus = psb_surface_create_camera_from_ub(driver_data, width, height,
    218                        buf_stride, size, psb_surface, 1, buf_offset, user_ptr);
    219         else {
    220             DEBUG_FAILURE;
    221             vaStatus = VA_STATUS_ERROR_UNKNOWN;
    222         }
    223     }
    224 #else
    225         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    226 #endif
    227 
    228 
    229     if (VA_STATUS_SUCCESS != vaStatus) {
    230         free(psb_surface);
    231         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    232         obj_surface->surface_id = VA_INVALID_SURFACE;
    233 
    234         DEBUG_FAILURE;
    235 
    236         return vaStatus;
    237     }
    238 
    239     memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
    240     psb_surface->extra_info[4] = VA_FOURCC_NV12; /* temp treat is as IYUV */
    241 
    242     obj_surface->psb_surface = psb_surface;
    243 
    244     /* Error recovery */
    245     if (VA_STATUS_SUCCESS != vaStatus) {
    246         object_surface_p obj_surface = SURFACE(*surface);
    247         psb__destroy_surface(driver_data, obj_surface);
    248         *surface = VA_INVALID_SURFACE;
    249     }
    250 
    251     return vaStatus;
    252 }
    253 #endif
    254 
    255 
    256 VAStatus psb_CreateSurfacesForUserPtr(
    257     VADriverContextP ctx,
    258     int Width,
    259     int Height,
    260     int format,
    261     int num_surfaces,
    262     VASurfaceID *surface_list,       /* out */
    263     unsigned size, /* total buffer size need to be allocated */
    264     unsigned int fourcc, /* expected fourcc */
    265     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
    266     unsigned int chroma_u_stride, /* chroma stride */
    267     unsigned int chroma_v_stride,
    268     unsigned int luma_offset, /* could be 0 */
    269     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
    270     unsigned int chroma_v_offset,
    271     unsigned int tiling
    272 )
    273 {
    274     INIT_DRIVER_DATA
    275     VAStatus vaStatus = VA_STATUS_SUCCESS;
    276     int i, height_origin;
    277     unsigned long buffer_stride;
    278 
    279     /* silient compiler warning */
    280     unsigned int width = (unsigned int)Width;
    281     unsigned int height = (unsigned int)Height;
    282 
    283     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x"
    284                              "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
    285                              "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
    286                              "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
    287                              width, height, format,
    288                              num_surfaces, size, fourcc,
    289                              luma_stride, chroma_u_stride, chroma_v_stride,
    290                              luma_offset, chroma_u_offset, chroma_v_offset);
    291 
    292     CHECK_INVALID_PARAM(num_surfaces <= 0);
    293     CHECK_SURFACE(surface_list);
    294 
    295     /* We only support one format */
    296     if ((VA_RT_FORMAT_YUV420 != format) && (VA_RT_FORMAT_RGB32 != format)) {
    297         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
    298         DEBUG_FAILURE;
    299         return vaStatus;
    300     }
    301 
    302     /* We only support NV12 */
    303     if ((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) {
    304         drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n");
    305         return VA_STATUS_ERROR_UNKNOWN;
    306     }
    307 
    308     vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
    309     CHECK_VASTATUS();
    310 
    311     if (VA_RT_FORMAT_YUV420 == format) {
    312     CHECK_INVALID_PARAM((size < width * height * 1.5) ||
    313         (luma_stride < width) ||
    314         (chroma_u_stride * 2 < width) ||
    315         (chroma_v_stride * 2 < width) ||
    316         (chroma_u_offset < luma_offset + width * height) ||
    317         (chroma_v_offset < luma_offset + width * height));
    318     } else if (VA_RT_FORMAT_RGB32 == format) {
    319     CHECK_INVALID_PARAM((size < width * height * 4) ||
    320         (luma_stride < width) ||
    321         (chroma_u_stride * 2 < width) ||
    322         (chroma_v_stride * 2 < width) ||
    323         (chroma_u_offset < luma_offset + width * height) ||
    324         (chroma_v_offset < luma_offset + width * height));
    325     }
    326 
    327     height_origin = height;
    328 
    329     for (i = 0; i < num_surfaces; i++) {
    330         int surfaceID;
    331         object_surface_p obj_surface;
    332         psb_surface_p psb_surface;
    333 
    334         surfaceID = object_heap_allocate(&driver_data->surface_heap);
    335         obj_surface = SURFACE(surfaceID);
    336         if (NULL == obj_surface) {
    337             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    338             DEBUG_FAILURE;
    339             break;
    340         }
    341         MEMSET_OBJECT(obj_surface, struct object_surface_s);
    342 
    343         obj_surface->surface_id = surfaceID;
    344         surface_list[i] = surfaceID;
    345         obj_surface->context_id = -1;
    346         obj_surface->width = width;
    347         obj_surface->height = height;
    348         obj_surface->width_r = width;
    349         obj_surface->height_r = height;
    350         obj_surface->height_origin = height_origin;
    351 	obj_surface->is_ref_surface = 0;
    352 
    353         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    354         if (NULL == psb_surface) {
    355             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    356             obj_surface->surface_id = VA_INVALID_SURFACE;
    357 
    358             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    359 
    360             DEBUG_FAILURE;
    361             break;
    362         }
    363 
    364 
    365         vaStatus = psb_surface_create_for_userptr(driver_data, width, height,
    366                    size,
    367                    fourcc,
    368                    luma_stride,
    369                    chroma_u_stride,
    370                    chroma_v_stride,
    371                    luma_offset,
    372                    chroma_u_offset,
    373                    chroma_v_offset,
    374                    psb_surface
    375                                                  );
    376 
    377         if (VA_STATUS_SUCCESS != vaStatus) {
    378             free(psb_surface);
    379             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    380             obj_surface->surface_id = VA_INVALID_SURFACE;
    381 
    382             DEBUG_FAILURE;
    383             break;
    384         }
    385         buffer_stride = psb_surface->stride;
    386         /* by default, surface fourcc is NV12 */
    387         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
    388         psb_surface->extra_info[4] = fourcc;
    389         psb_surface->extra_info[8] = fourcc;
    390 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    391 	psb_surface->extra_info[7] = tiling;
    392 #endif
    393         obj_surface->psb_surface = psb_surface;
    394     }
    395 
    396     /* Error recovery */
    397     if (VA_STATUS_SUCCESS != vaStatus) {
    398         /* surface_list[i-1] was the last successful allocation */
    399         for (; i--;) {
    400             object_surface_p obj_surface = SURFACE(surface_list[i]);
    401             psb__destroy_surface(driver_data, obj_surface);
    402             surface_list[i] = VA_INVALID_SURFACE;
    403         }
    404     }
    405 
    406 
    407     return vaStatus;
    408 }
    409 
    410 VAStatus  psb_CreateSurfaceFromKBuf(
    411     VADriverContextP ctx,
    412     int _width,
    413     int _height,
    414     int format,
    415     VASurfaceID *surface,       /* out */
    416     unsigned int kbuf_handle, /* kernel buffer handle*/
    417     unsigned size, /* kernel buffer size */
    418     unsigned int kBuf_fourcc, /* expected fourcc */
    419     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
    420     unsigned int chroma_u_stride, /* chroma stride */
    421     unsigned int chroma_v_stride,
    422     unsigned int luma_offset, /* could be 0 */
    423     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
    424     unsigned int chroma_v_offset,
    425     unsigned int tiling
    426 )
    427 {
    428     INIT_DRIVER_DATA
    429     VAStatus vaStatus = VA_STATUS_SUCCESS;
    430     unsigned long buffer_stride;
    431 
    432     /* silient compiler warning */
    433     unsigned int width = (unsigned int)_width;
    434     unsigned int height = (unsigned int)_height;
    435 
    436     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x"
    437                              "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x"
    438                              "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d"
    439                              "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n",
    440                              width, height, format,
    441                              size, kBuf_fourcc,
    442                              luma_stride, chroma_u_stride, chroma_v_stride,
    443                              luma_offset, chroma_u_offset, chroma_v_offset);
    444 
    445     CHECK_SURFACE(surface);
    446 
    447     /* We only support one format */
    448     if (VA_RT_FORMAT_YUV420 != format) {
    449         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
    450         DEBUG_FAILURE;
    451         return vaStatus;
    452     }
    453 
    454     /* We only support NV12/YV12 */
    455 
    456     if ((VA_RT_FORMAT_YUV420 == format) && (kBuf_fourcc != VA_FOURCC_NV12)) {
    457         drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n");
    458         return VA_STATUS_ERROR_UNKNOWN;
    459     }
    460     /*
    461     vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
    462     CHECK_VASTATUS();
    463     */
    464 
    465     CHECK_INVALID_PARAM((size < width * height * 1.5) ||
    466         (luma_stride < width) ||
    467         (chroma_u_stride * 2 < width) ||
    468         (chroma_v_stride * 2 < width) ||
    469         (chroma_u_offset < luma_offset + width * height) ||
    470         (chroma_v_offset < luma_offset + width * height));
    471 
    472     int surfaceID;
    473     object_surface_p obj_surface;
    474     psb_surface_p psb_surface;
    475 
    476     surfaceID = object_heap_allocate(&driver_data->surface_heap);
    477     obj_surface = SURFACE(surfaceID);
    478     CHECK_ALLOCATION(obj_surface);
    479 
    480     MEMSET_OBJECT(obj_surface, struct object_surface_s);
    481 
    482     obj_surface->surface_id = surfaceID;
    483     *surface = surfaceID;
    484     obj_surface->context_id = -1;
    485     obj_surface->width = width;
    486     obj_surface->height = height;
    487     obj_surface->width_r = width;
    488     obj_surface->height_r = height;
    489     obj_surface->height_origin = height;
    490     obj_surface->is_ref_surface = 0;
    491 
    492     psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    493     if (NULL == psb_surface) {
    494         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    495         obj_surface->surface_id = VA_INVALID_SURFACE;
    496 
    497         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    498 
    499         DEBUG_FAILURE;
    500         return vaStatus;
    501     }
    502 
    503     vaStatus = psb_surface_create_from_kbuf(driver_data, width, height,
    504                                             size,
    505                                             kBuf_fourcc,
    506                                             kbuf_handle,
    507                                             luma_stride,
    508                                             chroma_u_stride,
    509                                             chroma_v_stride,
    510                                             luma_offset,
    511                                             chroma_u_offset,
    512                                             chroma_v_offset,
    513                                             psb_surface);
    514 
    515     if (VA_STATUS_SUCCESS != vaStatus) {
    516         free(psb_surface);
    517         object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    518         obj_surface->surface_id = VA_INVALID_SURFACE;
    519 
    520         DEBUG_FAILURE;
    521         return vaStatus;
    522     }
    523     buffer_stride = psb_surface->stride;
    524     /* by default, surface fourcc is NV12 */
    525     memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
    526     psb_surface->extra_info[4] = kBuf_fourcc;
    527     psb_surface->extra_info[8] = kBuf_fourcc;
    528 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    529     psb_surface->extra_info[7] = tiling;
    530 #endif
    531     obj_surface->psb_surface = psb_surface;
    532 
    533     /* Error recovery */
    534     if (VA_STATUS_SUCCESS != vaStatus) {
    535         object_surface_p obj_surface = SURFACE(surfaceID);
    536         psb__destroy_surface(driver_data, obj_surface);
    537         *surface = VA_INVALID_SURFACE;
    538     }
    539 
    540     return vaStatus;
    541 }
    542 
    543 VAStatus  psb_CreateSurfaceFromUserspace(
    544         VADriverContextP ctx,
    545         int width,
    546         int height,
    547         int format,
    548         int num_surfaces,
    549         VASurfaceID *surface_list,        /* out */
    550         VASurfaceAttributeTPI *attribute_tpi
    551 )
    552 {
    553     INIT_DRIVER_DATA;
    554     VAStatus vaStatus = VA_STATUS_SUCCESS;
    555 #ifdef ANDROID
    556     unsigned int *vaddr;
    557     unsigned long fourcc;
    558     int surfaceID;
    559     object_surface_p obj_surface;
    560     psb_surface_p psb_surface;
    561     int i;
    562 
    563     switch (format) {
    564     case VA_RT_FORMAT_YUV422:
    565         fourcc = VA_FOURCC_YV16;
    566         break;
    567     case VA_RT_FORMAT_YUV420:
    568     default:
    569         fourcc = VA_FOURCC_NV12;
    570         break;
    571     }
    572 
    573     for (i=0; i < num_surfaces; i++) {
    574         vaddr = (unsigned int *)(attribute_tpi->buffers[i]);
    575         surfaceID = object_heap_allocate(&driver_data->surface_heap);
    576         obj_surface = SURFACE(surfaceID);
    577         if (NULL == obj_surface) {
    578             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    579             DEBUG_FAILURE;
    580             break;
    581         }
    582         MEMSET_OBJECT(obj_surface, struct object_surface_s);
    583 
    584         obj_surface->surface_id = surfaceID;
    585         surface_list[i] = surfaceID;
    586         obj_surface->context_id = -1;
    587         obj_surface->width = attribute_tpi->width;
    588         obj_surface->height = attribute_tpi->height;
    589         obj_surface->width_r = attribute_tpi->width;
    590         obj_surface->height_r = attribute_tpi->height;
    591 	obj_surface->is_ref_surface = 0;
    592 
    593         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    594         if (NULL == psb_surface) {
    595             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    596             obj_surface->surface_id = VA_INVALID_SURFACE;
    597             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    598             DEBUG_FAILURE;
    599             break;
    600         }
    601 
    602         if (attribute_tpi->type == VAExternalMemoryNoneCacheUserPointer)
    603             vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
    604                     attribute_tpi, psb_surface, vaddr, -1, PSB_USER_BUFFER_UNCACHED);
    605         else {
    606             vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
    607                     attribute_tpi, psb_surface, vaddr, -1,  0);
    608             psb_surface->buf.unfence_flag = 2;
    609         }
    610         obj_surface->psb_surface = psb_surface;
    611 
    612         if (VA_STATUS_SUCCESS != vaStatus) {
    613             free(psb_surface);
    614             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    615             obj_surface->surface_id = VA_INVALID_SURFACE;
    616             DEBUG_FAILURE;
    617             break;
    618         }
    619         /* by default, surface fourcc is NV12 */
    620         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
    621         psb_surface->extra_info[4] = fourcc;
    622         psb_surface->extra_info[8] = fourcc;
    623         obj_surface->psb_surface = psb_surface;
    624 
    625         /* Error recovery */
    626         if (VA_STATUS_SUCCESS != vaStatus) {
    627             object_surface_p obj_surface = SURFACE(surfaceID);
    628             psb__destroy_surface(driver_data, obj_surface);
    629         }
    630     }
    631 #endif
    632     return vaStatus;
    633 }
    634 
    635 VAStatus  psb_CreateSurfaceFromION(
    636         VADriverContextP ctx,
    637         int width,
    638         int height,
    639         int format,
    640         int num_surfaces,
    641         VASurfaceID *surface_list,        /* out */
    642         VASurfaceAttributeTPI *attribute_tpi
    643 )
    644 {
    645     INIT_DRIVER_DATA;
    646     VAStatus vaStatus = VA_STATUS_SUCCESS;
    647 #ifdef ANDROID
    648     unsigned int *vaddr = NULL;
    649     unsigned long fourcc;
    650     int surfaceID;
    651     object_surface_p obj_surface;
    652     psb_surface_p psb_surface;
    653     int i;
    654     unsigned int source_size = 0;
    655     int ion_fd = 0;
    656     int ion_ret = 0;
    657     struct ion_fd_data ion_source_share;
    658 
    659     switch (format) {
    660     case VA_RT_FORMAT_YUV422:
    661         fourcc = VA_FOURCC_YV16;
    662         break;
    663     case VA_RT_FORMAT_YUV420:
    664     default:
    665         fourcc = VA_FOURCC_NV12;
    666         break;
    667     }
    668 
    669     ion_fd = open("/dev/ion", O_RDWR);
    670     if (ion_fd < 0) {
    671         drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to open the ion device!\n", __FUNCTION__);
    672         return VA_STATUS_ERROR_UNKNOWN;
    673     }
    674 
    675     for (i=0; i < num_surfaces; i++) {
    676         ion_source_share.handle = 0;
    677         ion_source_share.fd = (int)(attribute_tpi->buffers[i]);
    678         ion_ret = ioctl(ion_fd, ION_IOC_IMPORT, &ion_source_share);
    679             if ((ion_ret < 0) || (0 == ion_source_share.handle)) {
    680             close(ion_fd);
    681             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to import the ion fd!\n", __FUNCTION__);
    682             return VA_STATUS_ERROR_UNKNOWN;
    683         }
    684 
    685         if (VA_FOURCC_NV12 == fourcc)
    686             source_size = attribute_tpi->width * attribute_tpi->height * 1.5;
    687         else
    688             source_size = attribute_tpi->width * attribute_tpi->height * 2;
    689 
    690         vaddr = mmap(NULL, source_size, PROT_READ|PROT_WRITE, MAP_SHARED, ion_source_share.fd, 0);
    691         if (MAP_FAILED == vaddr) {
    692             close(ion_fd);
    693             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to mmap the ion buffer!\n", __FUNCTION__);
    694             return VA_STATUS_ERROR_UNKNOWN;
    695         }
    696 
    697         surfaceID = object_heap_allocate(&driver_data->surface_heap);
    698         obj_surface = SURFACE(surfaceID);
    699         if (NULL == obj_surface) {
    700             close(ion_fd);
    701             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    702             DEBUG_FAILURE;
    703             break;
    704         }
    705         MEMSET_OBJECT(obj_surface, struct object_surface_s);
    706 
    707         obj_surface->surface_id = surfaceID;
    708         surface_list[i] = surfaceID;
    709         obj_surface->context_id = -1;
    710         obj_surface->width = attribute_tpi->width;
    711         obj_surface->height = attribute_tpi->height;
    712         obj_surface->width_r = attribute_tpi->width;
    713         obj_surface->height_r = attribute_tpi->height;
    714 	obj_surface->is_ref_surface = 0;
    715 
    716         psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
    717         if (NULL == psb_surface) {
    718             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    719             obj_surface->surface_id = VA_INVALID_SURFACE;
    720             close(ion_fd);
    721             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    722             DEBUG_FAILURE;
    723             break;
    724         }
    725 
    726         vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc,
    727                 attribute_tpi, psb_surface, vaddr, ion_source_share.fd, 0);
    728         obj_surface->psb_surface = psb_surface;
    729 
    730         if (VA_STATUS_SUCCESS != vaStatus) {
    731             free(psb_surface);
    732             object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
    733             obj_surface->surface_id = VA_INVALID_SURFACE;
    734             close(ion_fd);
    735             DEBUG_FAILURE;
    736             break;
    737         }
    738         /* by default, surface fourcc is NV12 */
    739         memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info));
    740         psb_surface->extra_info[4] = fourcc;
    741         psb_surface->extra_info[8] = fourcc;
    742         obj_surface->psb_surface = psb_surface;
    743 
    744         /* Error recovery */
    745         if (VA_STATUS_SUCCESS != vaStatus) {
    746             object_surface_p obj_surface = SURFACE(surfaceID);
    747             psb__destroy_surface(driver_data, obj_surface);
    748             close(ion_fd);
    749         }
    750 
    751         vaddr = NULL;
    752     }
    753 
    754     close(ion_fd);
    755 #endif
    756     return vaStatus;
    757 }
    758 
    759 VAStatus psb_CreateSurfacesWithAttribute(
    760     VADriverContextP ctx,
    761     int width,
    762     int height,
    763     int format,
    764     int num_surfaces,
    765     VASurfaceID *surface_list,        /* out */
    766     VASurfaceAttributeTPI *attribute_tpi
    767 )
    768 {
    769     VAStatus vaStatus = VA_STATUS_SUCCESS;
    770     int i;
    771     int tiling;
    772 
    773     CHECK_INVALID_PARAM(attribute_tpi == NULL);
    774 
    775     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create %d surface(%dx%d) with type %d, tiling is %d\n",
    776             num_surfaces, width, height, attribute_tpi->type, attribute_tpi->tiling);
    777 
    778     tiling = attribute_tpi->tiling;
    779     switch (attribute_tpi->type) {
    780     case VAExternalMemoryNULL:
    781         vaStatus = psb_CreateSurfacesForUserPtr(ctx, width, height, format, num_surfaces, surface_list,
    782                                      attribute_tpi->size, attribute_tpi->pixel_format,
    783                                      attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride,
    784                                      attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset,
    785                                      attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset,
    786                                      attribute_tpi->tiling);
    787         return vaStatus;
    788 #ifdef ANDROID
    789     case VAExternalMemoryNoneCacheUserPointer:
    790 #endif
    791     case VAExternalMemoryUserPointer:
    792         vaStatus = psb_CreateSurfaceFromUserspace(ctx, width, height,
    793                                                  format, num_surfaces, surface_list,
    794                                                  attribute_tpi);
    795         return vaStatus;
    796     case VAExternalMemoryKernelDRMBufffer:
    797         for (i=0; i < num_surfaces; i++) {
    798             vaStatus = psb_CreateSurfaceFromKBuf(
    799                 ctx, width, height, format, &surface_list[i],
    800                 attribute_tpi->buffers[i],
    801                 attribute_tpi->size, attribute_tpi->pixel_format,
    802                 attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride,
    803                 attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset,
    804                 attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset, tiling);
    805             CHECK_VASTATUS();
    806         }
    807         return vaStatus;
    808     case VAExternalMemoryAndroidGrallocBuffer:
    809         vaStatus = psb_CreateSurfacesFromGralloc(ctx, width, height,
    810                                                  format, num_surfaces, surface_list,
    811                                                  (PsbSurfaceAttributeTPI *)attribute_tpi);
    812         return vaStatus;
    813 #ifdef ANDROID
    814     case VAExternalMemoryIONSharedFD:
    815         vaStatus = psb_CreateSurfaceFromION(ctx, width, height,
    816                                                  format, num_surfaces, surface_list,
    817                                                  attribute_tpi);
    818         return vaStatus;
    819 #endif
    820     default:
    821         return VA_STATUS_ERROR_INVALID_PARAMETER;
    822     }
    823 
    824     return VA_STATUS_ERROR_INVALID_PARAMETER;
    825 }
    826