/* * 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; }