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