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