| /* |
| * Copyright (c) 2011 Intel Corporation. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| */ |
| |
| #include <sys/mman.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/ioctl.h> |
| #include <fcntl.h> |
| #include <malloc.h> |
| #ifdef ANDROID |
| #include <linux/ion.h> |
| #endif |
| #include <va/va_tpi.h> |
| #include "psb_drv_video.h" |
| #include "psb_drv_debug.h" |
| #include "psb_surface.h" |
| #include "psb_surface_attrib.h" |
| |
| |
| #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; |
| |
| #define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) |
| #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) |
| #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) |
| #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id )) |
| |
| |
| /* |
| * Create surface |
| */ |
| VAStatus psb_surface_create_from_ub( |
| psb_driver_data_p driver_data, |
| int width, int height, int fourcc, |
| VASurfaceAttributeTPI *graphic_buffers, |
| psb_surface_p psb_surface, /* out */ |
| void *vaddr, |
| int fd, |
| unsigned flags |
| ) |
| { |
| int ret = 0; |
| |
| if ((fourcc == VA_FOURCC_NV12) || (fourcc == VA_FOURCC_YV16) || (fourcc == VA_FOURCC_IYUV) || (fourcc == VA_FOURCC_RGBA)) { |
| if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| psb_surface->stride = graphic_buffers->luma_stride; |
| if (0) { |
| ; |
| } else if (512 == graphic_buffers->luma_stride) { |
| psb_surface->stride_mode = STRIDE_512; |
| } else if (1024 == graphic_buffers->luma_stride) { |
| psb_surface->stride_mode = STRIDE_1024; |
| } else if (1280 == graphic_buffers->luma_stride) { |
| psb_surface->stride_mode = STRIDE_1280; |
| } else if (2048 == graphic_buffers->luma_stride) { |
| psb_surface->stride_mode = STRIDE_2048; |
| } else if (4096 == graphic_buffers->luma_stride) { |
| psb_surface->stride_mode = STRIDE_4096; |
| } else { |
| psb_surface->stride_mode = STRIDE_NA; |
| } |
| if (psb_surface->stride != graphic_buffers->luma_stride) { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| psb_surface->luma_offset = 0; |
| psb_surface->chroma_offset = psb_surface->stride * height; |
| |
| if (VA_FOURCC_NV12 == fourcc) { |
| psb_surface->size = ((psb_surface->stride * height) * 3) / 2; |
| psb_surface->extra_info[4] = VA_FOURCC_NV12; |
| } |
| else if (VA_FOURCC_YV16 == fourcc) { |
| psb_surface->size = (psb_surface->stride * height) * 2; |
| psb_surface->extra_info[4] = VA_FOURCC_YV16; |
| } |
| else if (VA_FOURCC_IYUV == fourcc) { |
| psb_surface->size = ((psb_surface->stride * height) * 3) / 2; |
| psb_surface->extra_info[4] = VA_FOURCC_IYUV; |
| } |
| else if (VA_FOURCC_RGBA == fourcc) { |
| psb_surface->size = (psb_surface->stride * height) * 4; |
| psb_surface->extra_info[4] = VA_FOURCC_RGBA; |
| } |
| |
| psb_surface->extra_info[8] = psb_surface->extra_info[4]; |
| |
| } else { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| #ifdef PSBVIDEO_MSVDX_DEC_TILING |
| if (graphic_buffers->tiling) |
| ret = psb_buffer_create_from_ub(driver_data, psb_surface->size, |
| psb_bt_mmu_tiling, &psb_surface->buf, |
| vaddr, fd, 0); |
| else |
| #endif |
| ret = psb_buffer_create_from_ub(driver_data, psb_surface->size, |
| psb_bt_surface, &psb_surface->buf, |
| vaddr, fd, flags); |
| |
| return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS; |
| } |
| |
| #if 0 |
| VAStatus psb_CreateSurfaceFromV4L2Buf( |
| VADriverContextP ctx, |
| int v4l2_fd, /* file descriptor of V4L2 device */ |
| struct v4l2_format *v4l2_fmt, /* format of V4L2 */ |
| struct v4l2_buffer *v4l2_buf, /* V4L2 buffer */ |
| VASurfaceID *surface /* out */ |
| ) |
| { |
| INIT_DRIVER_DATA; |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| int surfaceID; |
| object_surface_p obj_surface; |
| psb_surface_p psb_surface; |
| int width, height, buf_stride, buf_offset, size; |
| unsigned long *user_ptr = NULL; |
| |
| if (IS_MRST(driver_data) == 0 && IS_MFLD(driver_data) == 0) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaceFromV4L2Buf isn't supported on non-MRST platform\n"); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| /* Todo: |
| * sanity check if the v4l2 device on MRST is supported |
| */ |
| if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) { |
| unsigned long tmp = (unsigned long)(v4l2_buf->m.userptr); |
| |
| if (tmp & 0xfff) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "The buffer address 0x%08x must be page aligned\n", tmp); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| } |
| |
| surfaceID = object_heap_allocate(&driver_data->surface_heap); |
| obj_surface = SURFACE(surfaceID); |
| CHECK_ALLOCATION(obj_surface); |
| |
| MEMSET_OBJECT(obj_surface, struct object_surface_s); |
| |
| width = v4l2_fmt->fmt.pix.width; |
| height = v4l2_fmt->fmt.pix.height; |
| |
| buf_stride = width; /* ? */ |
| buf_offset = v4l2_buf->m.offset; |
| size = v4l2_buf->length; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create Surface from V4L2 buffer: %dx%d, stride=%d, buffer offset=0x%08x, size=%d\n", |
| width, height, buf_stride, buf_offset, size); |
| |
| obj_surface->surface_id = surfaceID; |
| *surface = surfaceID; |
| obj_surface->context_id = -1; |
| obj_surface->width = width; |
| obj_surface->height = height; |
| obj_surface->subpictures = NULL; |
| obj_surface->subpic_count = 0; |
| obj_surface->derived_imgcnt = 0; |
| obj_surface->display_timestamp = 0; |
| |
| psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); |
| if (NULL == psb_surface) { |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| |
| DEBUG_FAILURE; |
| |
| return vaStatus; |
| } |
| |
| #if PSB_MFLD_DUMMY_CODE |
| /* current assume it is NV12 */ |
| if (IS_MRST(driver_data)) |
| vaStatus = psb_surface_create_camera(driver_data, width, height, buf_stride, size, psb_surface, 1, buf_offset); |
| else { |
| if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) |
| user_ptr = (unsigned long *)(v4l2_buf->m.userptr); |
| else { |
| user_ptr = mmap(NULL /* start anywhere */ , |
| v4l2_buf->length, |
| PROT_READ , |
| MAP_SHARED /* recommended */ , |
| v4l2_fd, v4l2_buf->m.offset); |
| } |
| |
| if (NULL != user_ptr && MAP_FAILED != user_ptr) |
| vaStatus = psb_surface_create_camera_from_ub(driver_data, width, height, |
| buf_stride, size, psb_surface, 1, buf_offset, user_ptr); |
| else { |
| DEBUG_FAILURE; |
| vaStatus = VA_STATUS_ERROR_UNKNOWN; |
| } |
| } |
| #else |
| vaStatus = VA_STATUS_ERROR_UNKNOWN; |
| #endif |
| |
| |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| free(psb_surface); |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| DEBUG_FAILURE; |
| |
| return vaStatus; |
| } |
| |
| memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); |
| psb_surface->extra_info[4] = VA_FOURCC_NV12; /* temp treat is as IYUV */ |
| |
| obj_surface->psb_surface = psb_surface; |
| |
| /* Error recovery */ |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| object_surface_p obj_surface = SURFACE(*surface); |
| psb__destroy_surface(driver_data, obj_surface); |
| *surface = VA_INVALID_SURFACE; |
| } |
| |
| return vaStatus; |
| } |
| #endif |
| |
| |
| VAStatus psb_CreateSurfacesForUserPtr( |
| VADriverContextP ctx, |
| int Width, |
| int Height, |
| int format, |
| int num_surfaces, |
| VASurfaceID *surface_list, /* out */ |
| unsigned size, /* total buffer size need to be allocated */ |
| unsigned int fourcc, /* expected fourcc */ |
| unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ |
| unsigned int chroma_u_stride, /* chroma stride */ |
| unsigned int chroma_v_stride, |
| unsigned int luma_offset, /* could be 0 */ |
| unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ |
| unsigned int chroma_v_offset, |
| unsigned int tiling |
| ) |
| { |
| INIT_DRIVER_DATA |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| int i, height_origin; |
| unsigned long buffer_stride; |
| |
| /* silient compiler warning */ |
| unsigned int width = (unsigned int)Width; |
| unsigned int height = (unsigned int)Height; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x" |
| "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x" |
| "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d" |
| "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n", |
| width, height, format, |
| num_surfaces, size, fourcc, |
| luma_stride, chroma_u_stride, chroma_v_stride, |
| luma_offset, chroma_u_offset, chroma_v_offset); |
| |
| CHECK_INVALID_PARAM(num_surfaces <= 0); |
| CHECK_SURFACE(surface_list); |
| |
| /* We only support one format */ |
| if ((VA_RT_FORMAT_YUV420 != format) && (VA_RT_FORMAT_RGB32 != format)) { |
| vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| |
| /* We only support NV12 */ |
| if ((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n"); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); |
| CHECK_VASTATUS(); |
| |
| if (VA_RT_FORMAT_YUV420 == format) { |
| CHECK_INVALID_PARAM((size < width * height * 1.5) || |
| (luma_stride < width) || |
| (chroma_u_stride * 2 < width) || |
| (chroma_v_stride * 2 < width) || |
| (chroma_u_offset < luma_offset + width * height) || |
| (chroma_v_offset < luma_offset + width * height)); |
| } else if (VA_RT_FORMAT_RGB32 == format) { |
| CHECK_INVALID_PARAM((size < width * height * 4) || |
| (luma_stride < width) || |
| (chroma_u_stride * 2 < width) || |
| (chroma_v_stride * 2 < width) || |
| (chroma_u_offset < luma_offset + width * height) || |
| (chroma_v_offset < luma_offset + width * height)); |
| } |
| |
| height_origin = height; |
| |
| for (i = 0; i < num_surfaces; i++) { |
| int surfaceID; |
| object_surface_p obj_surface; |
| psb_surface_p psb_surface; |
| |
| surfaceID = object_heap_allocate(&driver_data->surface_heap); |
| obj_surface = SURFACE(surfaceID); |
| if (NULL == obj_surface) { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| break; |
| } |
| MEMSET_OBJECT(obj_surface, struct object_surface_s); |
| |
| obj_surface->surface_id = surfaceID; |
| surface_list[i] = surfaceID; |
| obj_surface->context_id = -1; |
| obj_surface->width = width; |
| obj_surface->height = height; |
| obj_surface->width_r = width; |
| obj_surface->height_r = height; |
| obj_surface->height_origin = height_origin; |
| obj_surface->is_ref_surface = 0; |
| |
| psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); |
| if (NULL == psb_surface) { |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| |
| DEBUG_FAILURE; |
| break; |
| } |
| |
| |
| vaStatus = psb_surface_create_for_userptr(driver_data, width, height, |
| size, |
| fourcc, |
| luma_stride, |
| chroma_u_stride, |
| chroma_v_stride, |
| luma_offset, |
| chroma_u_offset, |
| chroma_v_offset, |
| psb_surface |
| ); |
| |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| free(psb_surface); |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| DEBUG_FAILURE; |
| break; |
| } |
| buffer_stride = psb_surface->stride; |
| /* by default, surface fourcc is NV12 */ |
| memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); |
| psb_surface->extra_info[4] = fourcc; |
| psb_surface->extra_info[8] = fourcc; |
| #ifdef PSBVIDEO_MSVDX_DEC_TILING |
| psb_surface->extra_info[7] = tiling; |
| #endif |
| obj_surface->psb_surface = psb_surface; |
| } |
| |
| /* Error recovery */ |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| /* surface_list[i-1] was the last successful allocation */ |
| for (; i--;) { |
| object_surface_p obj_surface = SURFACE(surface_list[i]); |
| psb__destroy_surface(driver_data, obj_surface); |
| surface_list[i] = VA_INVALID_SURFACE; |
| } |
| } |
| |
| |
| return vaStatus; |
| } |
| |
| VAStatus psb_CreateSurfaceFromKBuf( |
| VADriverContextP ctx, |
| int _width, |
| int _height, |
| int format, |
| VASurfaceID *surface, /* out */ |
| unsigned int kbuf_handle, /* kernel buffer handle*/ |
| unsigned size, /* kernel buffer size */ |
| unsigned int kBuf_fourcc, /* expected fourcc */ |
| unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ |
| unsigned int chroma_u_stride, /* chroma stride */ |
| unsigned int chroma_v_stride, |
| unsigned int luma_offset, /* could be 0 */ |
| unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ |
| unsigned int chroma_v_offset, |
| unsigned int tiling |
| ) |
| { |
| INIT_DRIVER_DATA |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| unsigned long buffer_stride; |
| |
| /* silient compiler warning */ |
| unsigned int width = (unsigned int)_width; |
| unsigned int height = (unsigned int)_height; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x" |
| "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x" |
| "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d" |
| "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n", |
| width, height, format, |
| size, kBuf_fourcc, |
| luma_stride, chroma_u_stride, chroma_v_stride, |
| luma_offset, chroma_u_offset, chroma_v_offset); |
| |
| CHECK_SURFACE(surface); |
| |
| /* We only support one format */ |
| if (VA_RT_FORMAT_YUV420 != format) { |
| vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| |
| /* We only support NV12/YV12 */ |
| |
| if ((VA_RT_FORMAT_YUV420 == format) && (kBuf_fourcc != VA_FOURCC_NV12)) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 format\n"); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| /* |
| vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); |
| CHECK_VASTATUS(); |
| */ |
| |
| CHECK_INVALID_PARAM((size < width * height * 1.5) || |
| (luma_stride < width) || |
| (chroma_u_stride * 2 < width) || |
| (chroma_v_stride * 2 < width) || |
| (chroma_u_offset < luma_offset + width * height) || |
| (chroma_v_offset < luma_offset + width * height)); |
| |
| int surfaceID; |
| object_surface_p obj_surface; |
| psb_surface_p psb_surface; |
| |
| surfaceID = object_heap_allocate(&driver_data->surface_heap); |
| obj_surface = SURFACE(surfaceID); |
| CHECK_ALLOCATION(obj_surface); |
| |
| MEMSET_OBJECT(obj_surface, struct object_surface_s); |
| |
| obj_surface->surface_id = surfaceID; |
| *surface = surfaceID; |
| obj_surface->context_id = -1; |
| obj_surface->width = width; |
| obj_surface->height = height; |
| obj_surface->width_r = width; |
| obj_surface->height_r = height; |
| obj_surface->height_origin = height; |
| obj_surface->is_ref_surface = 0; |
| |
| psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); |
| if (NULL == psb_surface) { |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| |
| vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, |
| size, |
| kBuf_fourcc, |
| kbuf_handle, |
| luma_stride, |
| chroma_u_stride, |
| chroma_v_stride, |
| luma_offset, |
| chroma_u_offset, |
| chroma_v_offset, |
| psb_surface); |
| |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| free(psb_surface); |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| buffer_stride = psb_surface->stride; |
| /* by default, surface fourcc is NV12 */ |
| memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); |
| psb_surface->extra_info[4] = kBuf_fourcc; |
| psb_surface->extra_info[8] = kBuf_fourcc; |
| #ifdef PSBVIDEO_MSVDX_DEC_TILING |
| psb_surface->extra_info[7] = tiling; |
| #endif |
| obj_surface->psb_surface = psb_surface; |
| |
| /* Error recovery */ |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| object_surface_p obj_surface = SURFACE(surfaceID); |
| psb__destroy_surface(driver_data, obj_surface); |
| *surface = VA_INVALID_SURFACE; |
| } |
| |
| return vaStatus; |
| } |
| |
| VAStatus psb_CreateSurfaceFromUserspace( |
| VADriverContextP ctx, |
| int width, |
| int height, |
| int format, |
| int num_surfaces, |
| VASurfaceID *surface_list, /* out */ |
| VASurfaceAttributeTPI *attribute_tpi |
| ) |
| { |
| INIT_DRIVER_DATA; |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| #ifdef ANDROID |
| unsigned int *vaddr; |
| unsigned long fourcc; |
| int surfaceID; |
| object_surface_p obj_surface; |
| psb_surface_p psb_surface; |
| int i; |
| |
| switch (format) { |
| case VA_RT_FORMAT_YUV422: |
| fourcc = VA_FOURCC_YV16; |
| break; |
| case VA_RT_FORMAT_YUV420: |
| default: |
| fourcc = VA_FOURCC_NV12; |
| break; |
| } |
| |
| for (i=0; i < num_surfaces; i++) { |
| vaddr = (unsigned int *)(attribute_tpi->buffers[i]); |
| surfaceID = object_heap_allocate(&driver_data->surface_heap); |
| obj_surface = SURFACE(surfaceID); |
| if (NULL == obj_surface) { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| break; |
| } |
| MEMSET_OBJECT(obj_surface, struct object_surface_s); |
| |
| obj_surface->surface_id = surfaceID; |
| surface_list[i] = surfaceID; |
| obj_surface->context_id = -1; |
| obj_surface->width = attribute_tpi->width; |
| obj_surface->height = attribute_tpi->height; |
| obj_surface->width_r = attribute_tpi->width; |
| obj_surface->height_r = attribute_tpi->height; |
| obj_surface->is_ref_surface = 0; |
| |
| psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); |
| if (NULL == psb_surface) { |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| break; |
| } |
| |
| if (attribute_tpi->type == VAExternalMemoryNoneCacheUserPointer) |
| vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, |
| attribute_tpi, psb_surface, vaddr, -1, PSB_USER_BUFFER_UNCACHED); |
| else { |
| vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, |
| attribute_tpi, psb_surface, vaddr, -1, 0); |
| psb_surface->buf.unfence_flag = 2; |
| } |
| obj_surface->psb_surface = psb_surface; |
| |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| free(psb_surface); |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| DEBUG_FAILURE; |
| break; |
| } |
| /* by default, surface fourcc is NV12 */ |
| memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); |
| psb_surface->extra_info[4] = fourcc; |
| psb_surface->extra_info[8] = fourcc; |
| obj_surface->psb_surface = psb_surface; |
| |
| /* Error recovery */ |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| object_surface_p obj_surface = SURFACE(surfaceID); |
| psb__destroy_surface(driver_data, obj_surface); |
| } |
| } |
| #endif |
| return vaStatus; |
| } |
| |
| VAStatus psb_CreateSurfaceFromION( |
| VADriverContextP ctx, |
| int width, |
| int height, |
| int format, |
| int num_surfaces, |
| VASurfaceID *surface_list, /* out */ |
| VASurfaceAttributeTPI *attribute_tpi |
| ) |
| { |
| INIT_DRIVER_DATA; |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| #ifdef ANDROID |
| unsigned int *vaddr = NULL; |
| unsigned long fourcc; |
| int surfaceID; |
| object_surface_p obj_surface; |
| psb_surface_p psb_surface; |
| int i; |
| unsigned int source_size = 0; |
| int ion_fd = 0; |
| int ion_ret = 0; |
| struct ion_fd_data ion_source_share; |
| |
| switch (format) { |
| case VA_RT_FORMAT_YUV422: |
| fourcc = VA_FOURCC_YV16; |
| break; |
| case VA_RT_FORMAT_YUV420: |
| default: |
| fourcc = VA_FOURCC_NV12; |
| break; |
| } |
| |
| ion_fd = open("/dev/ion", O_RDWR); |
| if (ion_fd < 0) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to open the ion device!\n", __FUNCTION__); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| for (i=0; i < num_surfaces; i++) { |
| ion_source_share.handle = 0; |
| ion_source_share.fd = (int)(attribute_tpi->buffers[i]); |
| ion_ret = ioctl(ion_fd, ION_IOC_IMPORT, &ion_source_share); |
| if ((ion_ret < 0) || (0 == ion_source_share.handle)) { |
| close(ion_fd); |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to import the ion fd!\n", __FUNCTION__); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| if (VA_FOURCC_NV12 == fourcc) |
| source_size = attribute_tpi->width * attribute_tpi->height * 1.5; |
| else |
| source_size = attribute_tpi->width * attribute_tpi->height * 2; |
| |
| vaddr = mmap(NULL, source_size, PROT_READ|PROT_WRITE, MAP_SHARED, ion_source_share.fd, 0); |
| if (MAP_FAILED == vaddr) { |
| close(ion_fd); |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to mmap the ion buffer!\n", __FUNCTION__); |
| return VA_STATUS_ERROR_UNKNOWN; |
| } |
| |
| surfaceID = object_heap_allocate(&driver_data->surface_heap); |
| obj_surface = SURFACE(surfaceID); |
| if (NULL == obj_surface) { |
| close(ion_fd); |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| break; |
| } |
| MEMSET_OBJECT(obj_surface, struct object_surface_s); |
| |
| obj_surface->surface_id = surfaceID; |
| surface_list[i] = surfaceID; |
| obj_surface->context_id = -1; |
| obj_surface->width = attribute_tpi->width; |
| obj_surface->height = attribute_tpi->height; |
| obj_surface->width_r = attribute_tpi->width; |
| obj_surface->height_r = attribute_tpi->height; |
| obj_surface->is_ref_surface = 0; |
| |
| psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); |
| if (NULL == psb_surface) { |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| close(ion_fd); |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| break; |
| } |
| |
| vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, |
| attribute_tpi, psb_surface, vaddr, ion_source_share.fd, 0); |
| obj_surface->psb_surface = psb_surface; |
| |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| free(psb_surface); |
| object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); |
| obj_surface->surface_id = VA_INVALID_SURFACE; |
| close(ion_fd); |
| DEBUG_FAILURE; |
| break; |
| } |
| /* by default, surface fourcc is NV12 */ |
| memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); |
| psb_surface->extra_info[4] = fourcc; |
| psb_surface->extra_info[8] = fourcc; |
| obj_surface->psb_surface = psb_surface; |
| |
| /* Error recovery */ |
| if (VA_STATUS_SUCCESS != vaStatus) { |
| object_surface_p obj_surface = SURFACE(surfaceID); |
| psb__destroy_surface(driver_data, obj_surface); |
| close(ion_fd); |
| } |
| |
| vaddr = NULL; |
| } |
| |
| close(ion_fd); |
| #endif |
| return vaStatus; |
| } |
| |
| VAStatus psb_CreateSurfacesWithAttribute( |
| VADriverContextP ctx, |
| int width, |
| int height, |
| int format, |
| int num_surfaces, |
| VASurfaceID *surface_list, /* out */ |
| VASurfaceAttributeTPI *attribute_tpi |
| ) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| int i; |
| int tiling; |
| |
| CHECK_INVALID_PARAM(attribute_tpi == NULL); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create %d surface(%dx%d) with type %d, tiling is %d\n", |
| num_surfaces, width, height, attribute_tpi->type, attribute_tpi->tiling); |
| |
| tiling = attribute_tpi->tiling; |
| switch (attribute_tpi->type) { |
| case VAExternalMemoryNULL: |
| vaStatus = psb_CreateSurfacesForUserPtr(ctx, width, height, format, num_surfaces, surface_list, |
| attribute_tpi->size, attribute_tpi->pixel_format, |
| attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride, |
| attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset, |
| attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset, |
| attribute_tpi->tiling); |
| return vaStatus; |
| #ifdef ANDROID |
| case VAExternalMemoryNoneCacheUserPointer: |
| #endif |
| case VAExternalMemoryUserPointer: |
| vaStatus = psb_CreateSurfaceFromUserspace(ctx, width, height, |
| format, num_surfaces, surface_list, |
| attribute_tpi); |
| return vaStatus; |
| case VAExternalMemoryKernelDRMBufffer: |
| for (i=0; i < num_surfaces; i++) { |
| vaStatus = psb_CreateSurfaceFromKBuf( |
| ctx, width, height, format, &surface_list[i], |
| attribute_tpi->buffers[i], |
| attribute_tpi->size, attribute_tpi->pixel_format, |
| attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride, |
| attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset, |
| attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset, tiling); |
| CHECK_VASTATUS(); |
| } |
| return vaStatus; |
| case VAExternalMemoryAndroidGrallocBuffer: |
| vaStatus = psb_CreateSurfacesFromGralloc(ctx, width, height, |
| format, num_surfaces, surface_list, |
| (PsbSurfaceAttributeTPI *)attribute_tpi); |
| return vaStatus; |
| #ifdef ANDROID |
| case VAExternalMemoryIONSharedFD: |
| vaStatus = psb_CreateSurfaceFromION(ctx, width, height, |
| format, num_surfaces, surface_list, |
| attribute_tpi); |
| return vaStatus; |
| #endif |
| default: |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |