diff options
Diffstat (limited to 'src/psb_drv_video.c')
-rwxr-xr-x[-rw-r--r--] | src/psb_drv_video.c | 669 |
1 files changed, 417 insertions, 252 deletions
diff --git a/src/psb_drv_video.c b/src/psb_drv_video.c index 5ea21e2..e275201 100644..100755 --- a/src/psb_drv_video.c +++ b/src/psb_drv_video.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011 Intel Corporation. All Rights Reserved. - * Copyright (c) Imagination Technologies Limited, UK + * Copyright (c) Imagination Technologies Limited, UK * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -9,11 +9,11 @@ * 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. @@ -33,6 +33,7 @@ #include <va/va_dricommon.h> #include "psb_drv_video.h" +#include "psb_texture.h" #include "psb_cmdbuf.h" #include "lnc_cmdbuf.h" #include "pnw_cmdbuf.h" @@ -66,17 +67,19 @@ #include <wsbm/wsbm_fencemgr.h> #include <linux/videodev2.h> #include <sys/mman.h> +#include <errno.h> #include "psb_def.h" #include "psb_ws_driver.h" #include "ci_va.h" +#include "pnw_rotate.h" #ifndef PSB_PACKAGE_VERSION #define PSB_PACKAGE_VERSION "Undefined" #endif #define PSB_DRV_VERSION PSB_PACKAGE_VERSION -#define PSB_CHG_REVISION "(0X0000005E)" +#define PSB_CHG_REVISION "(0X00000071)" #define PSB_STR_VENDOR_MRST "Intel GMA500-MRST-" PSB_DRV_VERSION " " PSB_CHG_REVISION #define PSB_STR_VENDOR_MFLD "Intel GMA500-MFLD-" PSB_DRV_VERSION " " PSB_CHG_REVISION @@ -106,8 +109,18 @@ #define IMAGE_ID_OFFSET 0x05000000 #define SUBPIC_ID_OFFSET 0x06000000 +#define SET_SURFACE_INFO_rotate(psb_surface, rotate) psb_surface->extra_info[5] = (uint32_t) rotate; +#define GET_SURFACE_INFO_rotate(psb_surface) ((int) psb_surface->extra_info[5]) + static int psb_get_device_info(VADriverContextP ctx); + +void psb_init_surface_pvr2dbuf(psb_driver_data_p driver_data); +void psb_free_surface_pvr2dbuf(psb_driver_data_p driver_data); + +static FILE *psb_video_debug_fp = NULL; +static int debug_fp_count = 0; + /* * read a config "env" for libva.conf or from environment setting * liva.conf has higher priority @@ -121,7 +134,7 @@ int psb_parse_config(char *env, char *env_value) FILE *fp = NULL; char *env_ptr; - if (env_value == NULL) + if (env == NULL) return 1; fp = fopen("/etc/psbvideo.conf", "r"); @@ -157,30 +170,13 @@ int psb_parse_config(char *env, char *env_value) return 1; } -static FILE *psb_video_debug_fp = NULL; - -static void psb__open_log(void) -{ - char log_fn[1024]; - - if (psb_parse_config("PSB_VIDEO_DEBUG", &log_fn[0]) == 0) { - unsigned int suffix = 0xffff & ((unsigned int)time(NULL)); - if (strcmp(log_fn, "/dev/stdout") != 0) - sprintf(log_fn + strlen(log_fn), ".%d", suffix); - psb_video_debug_fp = fopen(log_fn, "w"); - } -} - -static void psb__close_log(void) -{ - if (psb_video_debug_fp != NULL) - fclose(psb_video_debug_fp); -} - void psb__error_message(const char *msg, ...) { va_list args; FILE *fp; + char tag[128]; + + (void)tag; if (psb_video_debug_fp == NULL) /* not set the debug */ fp = stderr; @@ -191,6 +187,10 @@ void psb__error_message(const char *msg, ...) GetTickCount(), getpid(), pthread_self()); va_start(args, msg); vfprintf(fp, msg, args); +#ifdef ANDROID + sprintf(tag, "pvr_drv_video[%d:0x%08lx]", getpid(), pthread_self()); + __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, args); +#endif va_end(args); fflush(fp); @@ -201,50 +201,66 @@ void psb__information_message(const char *msg, ...) { if (psb_video_debug_fp) { va_list args; + char tag[128]; + + (void)tag; fprintf(psb_video_debug_fp, "[0x%08lx]psb_drv_video(%d:0x%08lx) ", GetTickCount(), getpid(), pthread_self()); va_start(args, msg); vfprintf(psb_video_debug_fp, msg, args); +#ifdef ANDROID + sprintf(tag, "pvr_drv_video[%d:0x%08lx]", getpid(), pthread_self()); + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, args); +#endif va_end(args); fflush(psb_video_debug_fp); fsync(fileno(psb_video_debug_fp)); } } -static int Angle2Rotation(int angle) + +static void psb__open_log(void) { - angle %= 360; - switch (angle) { - case 0: - return VA_ROTATION_NONE; - case 90: - return VA_ROTATION_90; - case 180: - return VA_ROTATION_180; - case 270: - return VA_ROTATION_270; - default: - return -1; + char log_fn[1024]; + unsigned int suffix; + + if ((psb_video_debug_fp != NULL) && (psb_video_debug_fp != stderr)) { + debug_fp_count++; + return; + } + + if (psb_parse_config("PSB_VIDEO_DEBUG", &log_fn[0]) != 0) + return; + + suffix = 0xffff & ((unsigned int)time(NULL)); + snprintf(log_fn + strnlen(log_fn, 1024), + (1024 - 8 - strnlen(log_fn, 1024)), + ".%d.%d", getpid(), suffix); + psb_video_debug_fp = fopen(log_fn, "w"); + if (psb_video_debug_fp == 0) { + psb__error_message("Log file %s open failed, reason %s, fall back to stderr\n", + log_fn, strerror(errno)); + psb_video_debug_fp = stderr; + } else { + psb__information_message("Log file %s open successfully\n", log_fn); + debug_fp_count++; } } -static int Rotation2Angle(int rotation) +static void psb__close_log(void) { - switch (rotation) { - case VA_ROTATION_NONE: - return 0; - case VA_ROTATION_90: - return 90; - case VA_ROTATION_180: - return 180; - case VA_ROTATION_270: - return 270; - default: - return -1; + if ((psb_video_debug_fp != NULL) & (psb_video_debug_fp != stderr)) { + debug_fp_count--; + if (debug_fp_count == 0) + fclose(psb_video_debug_fp); } + + return; + } + #ifdef DEBUG_TRACE void psb__trace_message(const char *msg, ...) { @@ -258,9 +274,6 @@ void psb__trace_message(const char *msg, ...) if (psb_parse_config("PSB_VIDEO_TRACE", &trace_fn[0]) == 0) trace_file = trace_fn; - if (getenv("PSB_VIDEO_TRACE")) - trace_file = getenv("PSB_VIDEO_TRACE"); - if (trace_file) { trace = fopen(trace_file, "w"); if (trace) { @@ -491,6 +504,36 @@ static VAStatus psb__validate_config(object_config_p obj_config) return VA_STATUS_SUCCESS; } +static int psb_get_active_entrypoint_number( + VADriverContextP ctx, + unsigned int entrypoint) +{ + INIT_DRIVER_DATA; + struct drm_lnc_video_getparam_arg arg; + int count = 0; + int ret; + + if (VAEntrypointVLD > entrypoint || + entrypoint > VAEntrypointEncPicture) { + psb__error_message("%s :Invalid entrypoint %d.\n", + __FUNCTION__, entrypoint); + return -1; + } + + arg.key = PNW_VIDEO_QUERY_ENTRY; + arg.value = (uint64_t)((unsigned long) &count); + arg.arg = (uint64_t)((unsigned int)&entrypoint); + ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, + &arg, sizeof(arg)); + if (ret) { + psb__error_message("%s drmCommandWriteRead fails %d.\n", + __FUNCTION__, ret); + return -1; + } + + return count; +} + VAStatus psb_CreateConfig( VADriverContextP ctx, VAProfile profile, @@ -523,10 +566,20 @@ VAStatus psb_CreateConfig( } } + if (NULL == config_id) { + vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; + return vaStatus; + } + if (num_attribs < 0) { vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; } + if (NULL == attrib_list) { + vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; + return vaStatus; + } + if (NULL == format_vtable) { vaStatus = psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint); } @@ -535,12 +588,25 @@ VAStatus psb_CreateConfig( return vaStatus; } + if ((IS_MFLD(driver_data)) && + (VAEntrypointEncPicture == entrypoint)) { + /*Only allow one encoding entrypoint at the sametime.*/ + if (psb_get_active_entrypoint_number(ctx, VAEntrypointEncSlice) > 0 || + psb_get_active_entrypoint_number(ctx, VAEntrypointEncPicture)) { + psb__error_message("There already is a active encoding entrypoint %d.\n", + entrypoint); + return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; + } + } + configID = object_heap_allocate(&driver_data->config_heap); obj_config = CONFIG(configID); if (NULL == obj_config) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; return vaStatus; } + + MEMSET_OBJECT(obj_config, struct object_config_s); obj_config->profile = profile; @@ -551,7 +617,7 @@ VAStatus psb_CreateConfig( obj_config->attrib_count = 1; for (i = 0; i < num_attribs; i++) { - if (attrib_list[i].type < VAConfigAttribRTFormat || attrib_list[i].type > VAConfigAttribRateControl) + if (attrib_list[i].type > VAConfigAttribRateControl) return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; vaStatus = psb__update_attribute(obj_config, &(attrib_list[i])); @@ -576,7 +642,9 @@ VAStatus psb_CreateConfig( } /* only VAProfileH264ConstrainedBaseline profile enable error concealment*/ - if ((getenv("PSB_VIDEO_NOEC") == NULL) && (profile == VAProfileH264ConstrainedBaseline)) { + if (IS_MRST(driver_data) && + (getenv("PSB_VIDEO_NOEC") == NULL) + && (profile == VAProfileH264ConstrainedBaseline)) { psb__information_message("profile is VAProfileH264ConstrainedBaseline, error concealment is enabled. \n"); driver_data->ec_enabled = 1; } else { @@ -704,8 +772,10 @@ VAStatus psb_CreateSurfaces( INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; int i, height_origin, buffer_stride = 0; + int protected = (VA_RT_FORMAT_PROTECTED & format); unsigned long fourcc; + format = format & (~VA_RT_FORMAT_PROTECTED); if (num_surfaces <= 0) { vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; DEBUG_FAILURE; @@ -780,9 +850,7 @@ VAStatus psb_CreateSurfaces( } vaStatus = psb_surface_create(driver_data, width, height, fourcc, - (VA_RT_FORMAT_PROTECTED & format), psb_surface - ); - + protected, psb_surface); if (VA_STATUS_SUCCESS != vaStatus) { free(psb_surface); object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); @@ -797,48 +865,6 @@ VAStatus psb_CreateSurfaces( psb_surface->extra_info[4] = fourcc; obj_surface->psb_surface = psb_surface; - - /* Allocate alternative output surface */ - if (driver_data->rotate != VA_ROTATION_NONE) { - psb__information_message("Try to allocate surface for alternative rotate output\n"); - psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); - if (NULL == psb_surface) { - psb_surface_destroy(obj_surface->psb_surface); - obj_surface->surface_id = VA_INVALID_SURFACE; - /* object_heap_free( &driver_data->surface_heap, (object_base_p) obj_surface); */ - - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - - DEBUG_FAILURE; - break; - } - - if (driver_data->rotate == VA_ROTATION_180) - vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, - (VA_RT_FORMAT_PROTECTED & format), psb_surface); - else { - vaStatus = psb_surface_create(driver_data, height_origin, ((width + 0x1f) & ~0x1f), VA_FOURCC_NV12, - (VA_RT_FORMAT_PROTECTED & format), psb_surface - ); - obj_surface->width_r = height_origin; - obj_surface->height_r = ((width + 0x1f) & ~0x1f); - } - 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; - psb_surface_destroy(obj_surface->psb_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] = VA_FOURCC_NV12; - psb_surface->extra_info[5] = driver_data->rotate; - - obj_surface->psb_surface_rotate = psb_surface; - } } /* Error recovery */ @@ -849,9 +875,13 @@ VAStatus psb_CreateSurfaces( psb__destroy_surface(driver_data, obj_surface); surface_list[i] = VA_INVALID_SURFACE; } + psb__error_message("CreateSurfaces failed\n"); + return vaStatus; } - vaStatus = psb_register_video_bcd(ctx, width, height, buffer_stride, num_surfaces, surface_list); + if (fourcc == VA_FOURCC_NV12) + psb_add_video_bcd(ctx, width, height, buffer_stride, + num_surfaces, surface_list); return vaStatus; } @@ -985,6 +1015,17 @@ VAStatus psb_DestroySurfaces( } if (NULL == surface_list) { + /* This is a workaround for bug 3419. If libva surfaces and context are pre-allocated, + * mix call the function with NULL & 0 parameters to notify video driver when decoder is destroyed. + */ +#ifdef ANDROID +#include "android/psb_android_glue.h" + if (driver_data->ts_source_created) { + psb__information_message("In psb_release_video_bcd, call psb_android_texture_streaming_destroy to destroy texture streaming source.\n"); + psb_android_texture_streaming_destroy(); + driver_data->ts_source_created = 0; + } +#endif return VA_STATUS_ERROR_INVALID_SURFACE; } @@ -992,10 +1033,8 @@ VAStatus psb_DestroySurfaces( if (VA_STATUS_SUCCESS != psb_release_video_bcd(ctx)) return VA_STATUS_ERROR_UNKNOWN; - /* This is work around. - Add sufficient delay for gfx to release surface pages, - Avoid page leak message in TTM */ - usleep(1000*100); + /* Free PVR2D buffer wrapped from the surfaces */ + psb_free_surface_pvr2dbuf(driver_data); /* Make validation happy */ for (i = 0; i < num_surfaces; i++) { @@ -1014,6 +1053,7 @@ VAStatus psb_DestroySurfaces( if (driver_data->cur_displaying_surface == surface_list[i]) { /* Surface is being displaying. Need to stop overlay here */ + psb_coverlay_stop(ctx); } psb__destroy_surface(driver_data, obj_surface); @@ -1116,8 +1156,6 @@ VAStatus psb_CreateContext( obj_context->driver_data = driver_data; obj_context->current_render_target = NULL; obj_context->is_oold = driver_data->is_oold; - obj_context->rotate = driver_data->rotate; - obj_context->context_id = contextID; obj_context->config_id = config_id; obj_context->picture_width = picture_width; @@ -1161,8 +1199,6 @@ VAStatus psb_CreateContext( for (i = 0; i < num_render_targets; i++) { object_surface_p obj_surface = SURFACE(render_targets[i]); psb_surface_p psb_surface; - unsigned char *p; - int ret; if (NULL == obj_surface) { vaStatus = VA_STATUS_ERROR_INVALID_SURFACE; @@ -1268,7 +1304,7 @@ VAStatus psb_CreateContext( obj_context->slice_count = 0; obj_context->msvdx_context = ((driver_data->msvdx_context_base & 0xff0000) >> 16) | ((contextID & 0xff000000) >> 16); - + obj_context->profile = obj_config->profile; obj_context->entry_point = obj_config->entrypoint; /* Error recovery */ @@ -1329,7 +1365,7 @@ static VAStatus psb__allocate_malloc_buffer(object_buffer_p obj_buffer, int size static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer); -static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer, int size, void *data, VABufferType type) +static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer, int size, unsigned char *data, VABufferType type) { VAStatus vaStatus = VA_STATUS_SUCCESS; @@ -1354,7 +1390,7 @@ static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_bu } } - if (obj_buffer->alloc_size < size) { + if (obj_buffer->alloc_size < (unsigned int)size) { psb__information_message("Buffer size mismatch: Need %d, currently have %d\n", size, obj_buffer->alloc_size); if (obj_buffer->psb_buffer) { if (obj_buffer->buffer_data) { @@ -1378,9 +1414,10 @@ static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_bu * should be shared between two process */ vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu_shared, obj_buffer->psb_buffer); - else if (obj_buffer->type == VAProtectedSliceDataBufferType) - vaStatus = psb_buffer_reference_rar(driver_data, (uint32_t)data, obj_buffer->psb_buffer); - else + else if (obj_buffer->type == VAProtectedSliceDataBufferType) { + if (IS_MFLD(driver_data)) + vaStatus = psb_buffer_reference_imr(driver_data, (uint32_t)data, obj_buffer->psb_buffer); + } else vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, obj_buffer->psb_buffer); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_buffer->psb_buffer); @@ -1454,7 +1491,6 @@ void psb__suspend_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buff psb__information_message("Adding buffer %08x type %s to unused list. unused count = %d\n", obj_buffer->base.id, buffer_type_to_string(obj_buffer->type), obj_context->buffers_unused_count[type]); - object_heap_suspend_object((object_base_p) obj_buffer, 1); /* suspend */ return; } @@ -1504,6 +1540,14 @@ static void psb__destroy_context(psb_driver_data_p driver_data, object_context_p } } + for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) { + if (obj_context->pnw_cmdbuf_list[i]) { + pnw_cmdbuf_destroy(obj_context->pnw_cmdbuf_list[i]); + free(obj_context->pnw_cmdbuf_list[i]); + obj_context->pnw_cmdbuf_list[i] = NULL; + } + } + for (i = 0; i < PSB_MAX_CMDBUFS; i++) { if (obj_context->cmdbuf_list[i]) { psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]); @@ -1559,7 +1603,7 @@ VAStatus psb__CreateBuffer( VABufferType type, /* in */ unsigned int size, /* in */ unsigned int num_elements, /* in */ - void *data, /* in */ + unsigned char *data, /* in */ VABufferID *buf_desc /* out */ ) { @@ -1586,10 +1630,13 @@ VAStatus psb__CreateBuffer( psb__information_message("Requesting buffer creation, size=%d,elements=%d,type=%s\n", size, num_elements, buffer_type_to_string(type)); + /* on MFLD, data is IMR offset, and could be 0 */ + /* if ((type == VAProtectedSliceDataBufferType) && (data == NULL)) { psb__error_message("RAR: Create protected slice buffer, but RAR handle is NULL\n"); return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE ; } + */ if (obj_buffer && obj_buffer->psb_buffer) { if (psb_bs_queued == obj_buffer->psb_buffer->status) { @@ -1600,6 +1647,10 @@ VAStatus psb__CreateBuffer( /* Buffer was used for this frame, allocate new buffer instead */ psb__information_message("Skipping idle buffer %08x, recently used. Unused = %d\n", obj_buffer->base.id, unused_count); obj_buffer = NULL; + } else if (obj_context->frame_count - obj_buffer->last_used < 5) { + /* Buffer was used for previous frame, allocate new buffer instead */ + psb__information_message("Skipping idle buffer %08x used by frame %d. Unused = %d\n", obj_buffer->base.id, obj_buffer->last_used, unused_count); + obj_buffer = NULL; } } @@ -1769,7 +1820,6 @@ VAStatus psb_CreateBuffer( VAStatus psb_BufferInfo( VADriverContextP ctx, - VAContextID context, /* in */ VABufferID buf_id, /* in */ VABufferType *type, /* out */ unsigned int *size, /* out */ @@ -1854,7 +1904,7 @@ VAStatus psb_MapBuffer( */ if (obj_buffer->type == VAEncCodedBufferType) psb_codedbuf_map_mangle(ctx, obj_buffer, pbuf); - /* *(IMG_UINT32 *)((void *)obj_buffer->buffer_data + 4) = 16; */ + /* *(IMG_UINT32 *)((unsigned char *)obj_buffer->buffer_data + 4) = 16; */ } else { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; } @@ -1900,50 +1950,6 @@ VAStatus psb_DestroyBuffer( return vaStatus; } -static VAStatus psb__create_surface_rotation(VADriverContextP ctx, object_surface_p obj_surface, int protected) -{ - INIT_DRIVER_DATA - int width, height; - psb_surface_p psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); - VAStatus vaStatus = VA_STATUS_SUCCESS; - - psb__information_message("Try to allocate surface for alternative rotate output\n"); - - if (NULL == psb_surface) { - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - DEBUG_FAILURE; - return vaStatus; - } - - width = obj_surface->width; - height = obj_surface->height; - - if (driver_data->rotate == VA_ROTATION_180) { - vaStatus = psb_surface_create(driver_data, width, height, VA_FOURCC_NV12, - protected, psb_surface); - obj_surface->width_r = width; - obj_surface->height_r = height; - } else { - vaStatus = psb_surface_create(driver_data, obj_surface->height_origin, ((width + 0x1f) & ~0x1f), VA_FOURCC_NV12, - protected, psb_surface - ); - obj_surface->width_r = obj_surface->height_origin; - obj_surface->height_r = ((width + 0x1f) & ~0x1f); - } - if (VA_STATUS_SUCCESS != vaStatus) { - free(psb_surface); - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - DEBUG_FAILURE; - return vaStatus; - } - /* by default, surface fourcc is NV12 */ - memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); - psb_surface->extra_info[4] = VA_FOURCC_NV12; - psb_surface->extra_info[5] = driver_data->rotate; - - obj_surface->psb_surface_rotate = psb_surface; - return vaStatus; -} VAStatus psb_BeginPicture( VADriverContextP ctx, @@ -1989,50 +1995,21 @@ VAStatus psb_BeginPicture( vaStatus = obj_context->format_vtable->beginPicture(obj_context); } - if (driver_data->xrandr_dirty & PSB_NEW_ROTATION) { - int angle; - angle = Rotation2Angle(driver_data->video_rotate) + Rotation2Angle(driver_data->mipi0_rotation); - driver_data->local_rotation = Angle2Rotation(angle); - angle = Rotation2Angle(driver_data->video_rotate) + Rotation2Angle(driver_data->hdmi_rotation); - driver_data->extend_rotation = Angle2Rotation(angle); -#ifndef ANDROID - if ((driver_data->mipi1_rotation != VA_ROTATION_NONE) || - ((driver_data->local_rotation != VA_ROTATION_NONE) && - (driver_data->extend_rotation != VA_ROTATION_NONE) && - (driver_data->local_rotation != driver_data->extend_rotation))) { - driver_data->rotate = driver_data->video_rotate; - /*fallback to texblit path*/ - driver_data->output_method = PSB_PUTSURFACE_CTEXTURE; - } else { - if (driver_data->output_method != PSB_PUTSURFACE_FORCE_CTEXTURE) { - driver_data->output_method = PSB_PUTSURFACE_COVERLAY; - driver_data->rotate = (driver_data->local_rotation == 0) ? driver_data->extend_rotation : driver_data->local_rotation; - } - } -#endif - if (driver_data->rotate == VA_ROTATION_270) - driver_data->rotate = 3; /* Match with hw definition */ - - driver_data->xrandr_dirty &= ~PSB_NEW_ROTATION; - } - /* Create surface for rotation if needed */ - if (driver_data->rotate == VA_ROTATION_NONE && obj_surface->psb_surface_rotate) { - psb_surface_destroy(obj_surface->psb_surface_rotate); - obj_surface->psb_surface_rotate = NULL; - obj_surface->width_r = obj_surface->width; - obj_surface->height_r = obj_surface->height; - obj_context->rotate = driver_data->rotate; - } else if (driver_data->rotate != VA_ROTATION_NONE && - (!obj_surface->psb_surface_rotate ? 1 : (obj_surface->psb_surface_rotate->extra_info[5] != driver_data->rotate))) { - if (!obj_surface->psb_surface_rotate) { - psb__create_surface_rotation(ctx, obj_surface, obj_surface->psb_surface->buf.type == psb_bt_rar_surface); - } else { - psb_surface_destroy(obj_surface->psb_surface_rotate); - free(obj_surface->psb_surface_rotate); - psb__create_surface_rotation(ctx, obj_surface, obj_surface->psb_surface->buf.type == psb_bt_rar_surface); - } - obj_context->rotate = driver_data->rotate; - } + /* want msvdx to do rotate + * but check per-context stream type: interlace or not + */ + if (obj_context->interlaced_stream || driver_data->disable_msvdx_rotate) + obj_context->msvdx_rotate = 0; + else + obj_context->msvdx_rotate = driver_data->msvdx_rotate_want; + + /* the main surface track current rotate information + * try to reuse the allocated rotate surfaces and don't destroy them + * thus the rotation info in obj_surface->psb_surface_rotate may not be updated + */ + SET_SURFACE_INFO_rotate(obj_surface->psb_surface, obj_context->msvdx_rotate); + if (IS_MFLD(driver_data) && CONTEXT_ROTATE(obj_context)) + psb_CreateRotateSurface(ctx, obj_surface, obj_context->msvdx_rotate); if (driver_data->is_oold && !obj_surface->psb_surface->in_loop_buf) { psb_surface_p psb_surface = obj_surface->psb_surface; @@ -2125,6 +2102,8 @@ VAStatus psb_RenderPicture( return vaStatus; } buffer_list[i] = obj_buffer; + psb__information_message("Render buffer %08x type %s\n", obj_buffer->base.id, + buffer_type_to_string(obj_buffer->type)); } } @@ -2234,6 +2213,8 @@ VAStatus psb_SyncSurface( object_surface_p obj_surface; int decode = 0, encode = 0, rc_enable = 0; + psb__information_message("psb_SyncSurface: 0x%08x\n", render_target); + obj_surface = SURFACE(render_target); if (NULL == obj_surface) { vaStatus = VA_STATUS_ERROR_INVALID_SURFACE; @@ -2389,7 +2370,7 @@ VAStatus psb_QuerySurfaceError( arg.key = IMG_VIDEO_MB_ERROR; arg.arg = (uint64_t)((unsigned long) & handle); - arg.value = (uint64_t)decode_status; + arg.value = (uint64_t)((unsigned long)decode_status); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); @@ -2430,7 +2411,7 @@ VAStatus psb_LockSurface( { INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; - void *surface_data; + unsigned char *surface_data; int ret; object_surface_p obj_surface = SURFACE(surface); @@ -2442,9 +2423,8 @@ VAStatus psb_LockSurface( } psb_surface = obj_surface->psb_surface; - if (buffer_name) { - /* todo */ - } + if (buffer_name) + *buffer_name = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf))); if (buffer) { /* map the surface buffer */ uint32_t srf_buf_ofs = 0; @@ -2510,7 +2490,7 @@ VAStatus psb_GetEGLClientBufferFromSurface( } psb_surface_p psb_surface = obj_surface->psb_surface; - *buffer = (void *)psb_surface->bc_buffer; + *buffer = (unsigned char *)psb_surface->bc_buffer; return vaStatus; } @@ -2640,8 +2620,8 @@ VAStatus psb_CreateSurfaceFromV4L2Buf( VAStatus psb_CreateSurfacesForUserPtr( VADriverContextP ctx, - int width, - int height, + int Width, + int Height, int format, int num_surfaces, VASurfaceID *surface_list, /* out */ @@ -2660,6 +2640,10 @@ VAStatus psb_CreateSurfacesForUserPtr( int i, height_origin; unsigned long buffer_stride; + /* silient compiler warning */ + unsigned int width = (unsigned int)Width; + unsigned int height = (unsigned int)Height; + psb__information_message("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" @@ -2689,6 +2673,13 @@ VAStatus psb_CreateSurfacesForUserPtr( return vaStatus; } + /* We only support NV12/YV12 */ + if (((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) || + ((VA_RT_FORMAT_YUV422 == format) && (fourcc != VA_FOURCC_YV16))) { + psb__error_message("Only support NV12/YV16 format\n"); + return VA_STATUS_ERROR_UNKNOWN; + } + vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); if (VA_STATUS_SUCCESS != vaStatus) { DEBUG_FAILURE; @@ -2795,6 +2786,180 @@ VAStatus psb_CreateSurfacesForUserPtr( 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 +) +{ + INIT_DRIVER_DATA + VAStatus vaStatus = VA_STATUS_SUCCESS; + int i ; + unsigned long buffer_stride; + + /* silient compiler warning */ + unsigned int width = (unsigned int)_width; + unsigned int height = (unsigned int)_height; + + psb__information_message("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); + + if (NULL == surface) { + vaStatus = VA_STATUS_ERROR_INVALID_SURFACE; + DEBUG_FAILURE; + return vaStatus; + } + + /* We only support one format */ + if ((VA_RT_FORMAT_YUV420 != format) + && (VA_RT_FORMAT_YUV422 != 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)) || + ((VA_RT_FORMAT_YUV422 == format) && (kBuf_fourcc != VA_FOURCC_YV16))) { + psb__error_message("Only support NV12/YV16 format\n"); + return VA_STATUS_ERROR_UNKNOWN; + } + + vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); + if (VA_STATUS_SUCCESS != vaStatus) { + DEBUG_FAILURE; + return vaStatus; + } + + if ((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)) { + + vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; + DEBUG_FAILURE; + return vaStatus; + } + + 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; + } + 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; + + 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; + } + + 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; + } + 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; + 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_PutSurfaceBuf( + VADriverContextP ctx, + VASurfaceID surface, + unsigned char* data, + int* data_len, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, /* client supplied clip list */ + unsigned int number_cliprects, /* number of clip rects in the clip list */ + unsigned int flags /* de-interlacing flags */ +) +{ + INIT_DRIVER_DATA; + object_surface_p obj_surface = SURFACE(surface); + psb_surface_p psb_surface; + + obj_surface = SURFACE(surface); + psb_surface = obj_surface->psb_surface; + + psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch, destx, desty, destw, desth, 1, /* check subpicture */ + obj_surface->width, obj_surface->height, + psb_surface->stride, psb_surface->buf.drm_buf, + psb_surface->buf.pl_flags, 1 /* wrap dst */); + + return VA_STATUS_SUCCESS; +} int LOCK_HARDWARE(psb_driver_data_p driver_data) @@ -2831,6 +2996,7 @@ int UNLOCK_HARDWARE(psb_driver_data_p driver_data) static void psb__deinitDRM(VADriverContextP ctx) { INIT_DRIVER_DATA + struct dri_state *dri_state = (struct dri_state *)ctx->dri_state; if (driver_data->main_pool) { driver_data->main_pool->takeDown(driver_data->main_pool); @@ -2845,7 +3011,7 @@ static void psb__deinitDRM(VADriverContextP ctx) wsbmTakedown(); close(driver_data->drm_fd); - driver_data->drm_fd = -1; + driver_data->drm_fd = dri_state->fd = -1; } @@ -2997,6 +3163,9 @@ VAStatus psb_Terminate(VADriverContextP ctx) object_heap_destroy(&driver_data->buffer_heap); /* Clean up left over surfaces */ + + /* Free PVR2D buffer wrapped from the surfaces */ + psb_free_surface_pvr2dbuf(driver_data); obj_surface = (object_surface_p) object_heap_first(&driver_data->surface_heap, &iter); while (obj_surface) { psb__information_message("vaTerminate: surfaceID %08x still allocated, destroying\n", obj_surface->base.id); @@ -3030,16 +3199,6 @@ VAStatus psb_Terminate(VADriverContextP ctx) driver_data->rar_bo = NULL; } - if (driver_data->rar_rd) { - RAR_desc_t *rar_rd = driver_data->rar_rd; - - psb__information_message("vaTerminate: tear down RAR device\n"); - - RAR_fini(rar_rd); - free(driver_data->rar_rd); - driver_data->rar_rd = NULL; - } - if (driver_data->ws_priv) { psb__information_message("vaTerminate: tear down output portion\n"); @@ -3057,9 +3216,15 @@ VAStatus psb_Terminate(VADriverContextP ctx) if (driver_data->surface_mb_error) free(driver_data->surface_mb_error); + if (driver_data->bcd_buffer_surfaces) + free(driver_data->bcd_buffer_surfaces); + free(ctx->pDriverData); + free(ctx->vtable_egl); + free(ctx->vtable_tpi); + ctx->pDriverData = NULL; - psb__information_message("vaTerminate: cleanup successfully, goodbye\n\n"); + psb__information_message("vaTerminate: goodbye\n\n"); psb__close_log(); @@ -3147,10 +3312,8 @@ EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) tpi->vaCreateSurfaceFromCIFrame = psb_CreateSurfaceFromCIFrame; tpi->vaCreateSurfaceFromV4L2Buf = psb_CreateSurfaceFromV4L2Buf; tpi->vaCreateSurfacesForUserPtr = psb_CreateSurfacesForUserPtr; - -#ifdef ANDROID + tpi->vaCreateSurfaceFromKBuf = psb_CreateSurfaceFromKbuf; tpi->vaPutSurfaceBuf = psb_PutSurfaceBuf; -#endif ctx->vtable_egl = calloc(1, sizeof(struct VADriverVTableEGL)); if (NULL == ctx->vtable_egl) @@ -3160,7 +3323,7 @@ EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) va_egl->vaGetEGLClientBufferFromSurface = psb_GetEGLClientBufferFromSurface; driver_data = (psb_driver_data_p) calloc(1, sizeof(*driver_data)); - ctx->pDriverData = (void *) driver_data; + ctx->pDriverData = (unsigned char *) driver_data; if (NULL == driver_data) { if (ctx->vtable_tpi) free(ctx->vtable_tpi); @@ -3219,12 +3382,8 @@ EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) driver_data->hd_decode_supported = 1; } - driver_data->use_xrandr_thread = 0; - driver_data->xrandr_thread_id = 0; - driver_data->rotate = VA_ROTATION_NONE; - driver_data->video_rotate = VA_ROTATION_NONE; - driver_data->xrandr_dirty = 0; - driver_data->xrandr_update = 0; + psb_init_surface_pvr2dbuf(driver_data); + struct dri_state *dri_state = (struct dri_state *)ctx->dri_state; if (dri_state->driConnectedFlag == VA_DRI1 || dri_state->driConnectedFlag == VA_DRI2 || @@ -3317,7 +3476,6 @@ EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) else ctx->str_vendor = PSB_STR_VENDOR_MRST; - psb__information_message("vaInitilize: succeeded!\n\n"); driver_data->msvdx_decode_status = calloc(1, sizeof(drm_psb_msvdx_decode_status_t)); if (NULL == driver_data->msvdx_decode_status) { @@ -3328,6 +3486,8 @@ EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) return VA_STATUS_ERROR_ALLOCATION_FAILED; } + psb__information_message("vaInitilize: succeeded!\n\n"); + return VA_STATUS_SUCCESS; } @@ -3354,19 +3514,24 @@ static int psb_get_device_info(VADriverContextP ctx) arg.value = (uint64_t)((unsigned long) & device_info); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); - if (ret == 0) { - pci_device = (device_info >> 16) & 0xffff; - video_capability = device_info & 0xffff; + if (ret != 0) { + psb__information_message("failed to get video device info\n"); + return ret; + } - driver_data->dev_id = pci_device; - psb__information_message("Retrieve Device ID 0x%04x\n", driver_data->dev_id); + pci_device = (device_info >> 16) & 0xffff; + video_capability = device_info & 0xffff; - if ((IS_MRST(driver_data) && (pci_device != 0x4101)) || - IS_MFLD(driver_data)) - driver_data->encode_supported = 1; - else /* 0x4101 or other device hasn't encode support */ - driver_data->encode_supported = 0; + driver_data->dev_id = pci_device; + psb__information_message("Retrieve Device ID 0x%04x\n", driver_data->dev_id); + if ((IS_MRST(driver_data) && (pci_device != 0x4101)) || + IS_MFLD(driver_data)) + driver_data->encode_supported = 1; + else /* 0x4101 or other device hasn't encode support */ + driver_data->encode_supported = 0; + + if (IS_MRST(driver_data)) { driver_data->decode_supported = !(video_capability & 0x2); driver_data->hd_decode_supported = !(video_capability & 0x3); driver_data->hd_encode_supported = !(video_capability & 0x4); @@ -3379,11 +3544,11 @@ static int psb_get_device_info(VADriverContextP ctx) driver_data->encode_supported ? "support" : "not support", driver_data->hd_encode_supported ? "support" : "not support"); - - return ret; + } else { + driver_data->decode_supported = 1; + driver_data->hd_decode_supported = 1; + driver_data->hd_encode_supported = 1; } - psb__information_message("failed to get video device info\n"); - return ret; } |