/* * Copyright (c) 2011 Intel Corporation. All Rights Reserved. * 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 * "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. * * Authors: * Waldo Bastian <waldo.bastian@intel.com> * */ #include <va/va_backend.h> #include <va/va_backend_tpi.h> #include <va/va_backend_egl.h> #ifdef PSBVIDEO_MRFL_VPP #include <va/va_backend_vpp.h> #endif #ifdef PSBVIDEO_MFLD #include <va/va_backend_vpp.h> #endif #include <va/va_drmcommon.h> #include <va/va_android.h> #include <va/va_tpi.h> #include "psb_drv_video.h" #include "psb_texture.h" #include "psb_cmdbuf.h" #ifndef BAYTRAIL #include "pnw_cmdbuf.h" #include "tng_cmdbuf.h" #endif #ifdef PSBVIDEO_MRFL_VPP #include "vsp_cmdbuf.h" #endif #include "psb_surface.h" #include "pnw_MPEG2.h" #include "pnw_MPEG4.h" #include "pnw_H264.h" #include "pnw_VC1.h" #include "tng_jpegdec.h" #include "tng_VP8.h" #include "tng_yuv_processor.h" #ifdef PSBVIDEO_MFLD #include "pnw_MPEG4ES.h" #include "pnw_H264ES.h" #include "pnw_H263ES.h" #include "pnw_jpeg.h" #endif #ifdef PSBVIDEO_MRFL #include "tng_H264ES.h" #include "tng_H263ES.h" #include "tng_MPEG4ES.h" #include "tng_jpegES.h" #endif #ifdef PSBVIDEO_MRFL_VPP #include "vsp_VPP.h" #include "vsp_vp8.h" #endif #include "psb_output.h" #include <stdio.h> #include <string.h> #include <stdarg.h> #include <time.h> #include <unistd.h> #include <wsbm/wsbm_pool.h> #include <wsbm/wsbm_manager.h> #include <wsbm/wsbm_util.h> #include <wsbm/wsbm_fencemgr.h> #include <linux/videodev2.h> #include <errno.h> #include "psb_def.h" #include "psb_drv_debug.h" #ifndef BAYTRAIL #include "psb_ws_driver.h" #endif #include "pnw_rotate.h" #include "psb_surface_attrib.h" #include "android/psb_gralloc.h" #ifndef PSB_PACKAGE_VERSION #define PSB_PACKAGE_VERSION "Undefined" #endif #define PSB_DRV_VERSION PSB_PACKAGE_VERSION #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 #define PSB_STR_VENDOR_MRFL "Intel GMA500-MRFL-" PSB_DRV_VERSION " " PSB_CHG_REVISION #define PSB_STR_VENDOR_BAYTRAIL "Intel GMA500-BAYTRAIL-" PSB_DRV_VERSION " " PSB_CHG_REVISION #define PSB_STR_VENDOR_LEXINGTON "Intel GMA500-LEXINGTON-" PSB_DRV_VERSION " " PSB_CHG_REVISION #define MAX_UNUSED_BUFFERS 16 #define PSB_SURFACE_UNAVAILABLE 0x40000000 #define PSB_MAX_FLIP_DELAY (1000/30/10) #define PSB_SURFACE_UNAVAILABLE 0x40000000 #include <signal.h> #define EXPORT __attribute__ ((visibility("default"))) #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; #ifdef PSBVIDEO_MRFL_VPP #define INIT_FORMAT_VTABLE format_vtable_p format_vtable = ((profile < PSB_MAX_PROFILES) && (entrypoint < PSB_MAX_ENTRYPOINTS)) ? (profile == VAProfileNone? driver_data->vpp_profile : driver_data->profile2Format[profile][entrypoint]) : NULL; #endif #ifdef PSBVIDEO_MFLD #define INIT_FORMAT_VTABLE format_vtable_p format_vtable = ((profile < PSB_MAX_PROFILES) && (entrypoint < PSB_MAX_ENTRYPOINTS)) ? (profile == VAProfileNone? driver_data->vpp_profile : driver_data->profile2Format[profile][entrypoint]) : NULL; #endif #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 )) #define CONFIG_ID_OFFSET 0x01000000 #define CONTEXT_ID_OFFSET 0x02000000 #define SURFACE_ID_OFFSET 0x03000000 #define BUFFER_ID_OFFSET 0x04000000 #define IMAGE_ID_OFFSET 0x05000000 #define SUBPIC_ID_OFFSET 0x06000000 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); VAStatus psb_QueryConfigProfiles( VADriverContextP ctx, VAProfile *profile_list, /* out */ int *num_profiles /* out */ ) { DEBUG_FUNC_ENTER (void) ctx; /* unused */ int i = 0; VAStatus vaStatus = VA_STATUS_SUCCESS; INIT_DRIVER_DATA CHECK_INVALID_PARAM(profile_list == NULL); CHECK_INVALID_PARAM(num_profiles == NULL); #ifdef PSBVIDEO_MRFL_VPP profile_list[i++] = VAProfileNone; #endif // profile_list[i++] = VAProfileMPEG2Simple; profile_list[i++] = VAProfileMPEG2Main; profile_list[i++] = VAProfileMPEG4Simple; profile_list[i++] = VAProfileMPEG4AdvancedSimple; // profile_list[i++] = VAProfileMPEG4Main; profile_list[i++] = VAProfileH264Baseline; profile_list[i++] = VAProfileH264Main; profile_list[i++] = VAProfileH264High; profile_list[i++] = VAProfileH264StereoHigh; profile_list[i++] = VAProfileVC1Simple; profile_list[i++] = VAProfileVC1Main; profile_list[i++] = VAProfileVC1Advanced; if (IS_MRFL(driver_data) || IS_BAYTRAIL(driver_data)) { profile_list[i++] = VAProfileH263Baseline; profile_list[i++] = VAProfileJPEGBaseline; profile_list[i++] = VAProfileVP8Version0_3; } else if (IS_MFLD(driver_data)) { profile_list[i++] = VAProfileH263Baseline; profile_list[i++] = VAProfileJPEGBaseline; } profile_list[i++] = VAProfileH264ConstrainedBaseline; /* If the assert fails then PSB_MAX_PROFILES needs to be bigger */ ASSERT(i <= PSB_MAX_PROFILES); *num_profiles = i; DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } VAStatus psb_QueryConfigEntrypoints( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, /* out */ int *num_entrypoints /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; int entrypoints = 0; int i; CHECK_INVALID_PARAM(entrypoint_list == NULL); CHECK_INVALID_PARAM((num_entrypoints == NULL) || (profile >= PSB_MAX_PROFILES)); for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) { #ifndef BAYTRAIL #ifdef PSBVIDEO_MRFL_VPP if (profile == VAProfileNone && driver_data->vpp_profile && i == VAEntrypointVideoProc) { entrypoints++; *entrypoint_list++ = i; } else #endif #endif if (profile != VAProfileNone && driver_data->profile2Format[profile][i]) { entrypoints++; *entrypoint_list++ = i; } } /* If the assert fails then PSB_MAX_ENTRYPOINTS needs to be bigger */ ASSERT(entrypoints <= PSB_MAX_ENTRYPOINTS); if (0 == entrypoints) { return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } *num_entrypoints = entrypoints; DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } /* * Figure out if we should return VA_STATUS_ERROR_UNSUPPORTED_PROFILE * or VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT */ static VAStatus psb__error_unsupported_profile_entrypoint(psb_driver_data_p driver_data, VAProfile profile, VAEntrypoint __maybe_unused entrypoint) { /* Does the driver support _any_ entrypoint for this profile? */ if (profile < PSB_MAX_PROFILES) { int i; /* Do the parameter check for MFLD and MRFLD */ if (profile == VAProfileNone) return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) { if (driver_data->profile2Format[profile][i]) { /* There is an entrypoint, so the profile is supported */ return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT; } } } return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; } VAStatus psb_GetConfigAttributes( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, /* in/out */ int num_attribs ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA #if defined(BAYTRAIL) format_vtable_p format_vtable = driver_data->profile2Format[profile][entrypoint]; #elif defined(PSBVIDEO_MRFL_VPP) INIT_FORMAT_VTABLE #else format_vtable_p format_vtable = driver_data->profile2Format[profile][entrypoint]; #endif int i; VAStatus vaStatus = VA_STATUS_SUCCESS; if (NULL == format_vtable) { return psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint); } CHECK_INVALID_PARAM(attrib_list == NULL); CHECK_INVALID_PARAM(num_attribs <= 0); /* Generic attributes */ for (i = 0; i < num_attribs; i++) { switch (attrib_list[i].type) { case VAConfigAttribRTFormat: attrib_list[i].value = VA_RT_FORMAT_YUV420; if (entrypoint == VAEntrypointEncPicture) attrib_list[i].value |= VA_RT_FORMAT_YUV422; if ((profile == VAProfileJPEGBaseline) && (entrypoint == VAEntrypointVLD)) attrib_list[i].value |= VA_RT_FORMAT_YUV444; break; default: attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED; break; } } /* format specific attributes */ format_vtable->queryConfigAttributes(profile, entrypoint, attrib_list, num_attribs); DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } static VAStatus psb__update_attribute(object_config_p obj_config, VAConfigAttrib *attrib) { int i; /* Check existing attributes */ for (i = 0; i < obj_config->attrib_count; i++) { if (obj_config->attrib_list[i].type == attrib->type) { /* Update existing attribute */ obj_config->attrib_list[i].value = attrib->value; return VA_STATUS_SUCCESS; } } if (obj_config->attrib_count < PSB_MAX_CONFIG_ATTRIBUTES) { i = obj_config->attrib_count; obj_config->attrib_list[i].type = attrib->type; obj_config->attrib_list[i].value = attrib->value; obj_config->attrib_count++; return VA_STATUS_SUCCESS; } return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; } static VAStatus psb__validate_config(object_config_p obj_config) { int i; /* Check all attributes */ for (i = 0; i < obj_config->attrib_count; i++) { switch (obj_config->attrib_list[i].type) { case VAConfigAttribRTFormat: if (!(obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV420 || (obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV422 && obj_config->entrypoint == VAEntrypointEncPicture) || (obj_config->attrib_list[i].value == (VA_RT_FORMAT_YUV444 | VA_RT_FORMAT_YUV420 )))) { return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; } break; default: /* * Ignore unknown attributes here, it * may be format specific. */ break; } } 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) { drv_debug_msg(VIDEO_DEBUG_ERROR, "%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) { drv_debug_msg(VIDEO_DEBUG_ERROR, "%s drmCommandWriteRead fails %d.\n", __FUNCTION__, ret); return -1; } return count; } VAStatus psb_CreateConfig( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA #if defined(BAYTRAIL) format_vtable_p format_vtable = driver_data->profile2Format[profile][entrypoint]; #elif defined(PSBVIDEO_MRFL_VPP) INIT_FORMAT_VTABLE #else format_vtable_p format_vtable = driver_data->profile2Format[profile][entrypoint]; #endif VAStatus vaStatus = VA_STATUS_SUCCESS; int configID; object_config_p obj_config; int i; drv_debug_msg(VIDEO_DEBUG_INIT, "CreateConfig profile:%d, entrypoint:%d, num_attribs:%d.\n", profile, entrypoint, num_attribs); /*echo 8 > /sys/module/pvrsrvkm/parameters/no_ec will disable error concealment*/ if ((profile == VAProfileH264ConstrainedBaseline) && (VAEntrypointVLD == entrypoint)) { char ec_disable[2]; FILE *ec_fp = fopen("/sys/module/pvrsrvkm/parameters/no_ec", "r"); if (ec_fp) { if (fgets(ec_disable, 2, ec_fp) != NULL) { /* force profile to VAProfileH264High */ if (strcmp(ec_disable, "8") == 0) { drv_debug_msg(VIDEO_DEBUG_INIT, "disabled error concealment by setting profile to VAProfileH264High\n"); profile = VAProfileH264High; } } fclose(ec_fp); } } CHECK_INVALID_PARAM(config_id == NULL); CHECK_INVALID_PARAM(num_attribs < 0); CHECK_INVALID_PARAM(attrib_list == NULL); if (NULL == format_vtable) { vaStatus = psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint); } CHECK_VASTATUS(); if ((IS_MFLD(driver_data)) && ((VAEntrypointEncPicture == entrypoint) || (VAEntrypointEncSlice == entrypoint))) { int active_slc, active_pic; /* Only allow one encoding entrypoint at the sametime. * But if video encoding request comes when process JPEG encoding, * it will wait until current JPEG picture encoding finish. * Further JPEG encoding should fall back to software path.*/ active_slc = psb_get_active_entrypoint_number(ctx, VAEntrypointEncSlice); active_pic = psb_get_active_entrypoint_number(ctx, VAEntrypointEncPicture); if (active_slc > 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "There already is a active video encoding entrypoint." "Entrypoint %d isn't available.\n", entrypoint); return VA_STATUS_ERROR_HW_BUSY; } else if (active_pic > 0 && VAEntrypointEncPicture == entrypoint) { drv_debug_msg(VIDEO_DEBUG_ERROR, "There already is a active picture encoding entrypoint." "Entrypoint %d isn't available.\n", entrypoint); return VA_STATUS_ERROR_HW_BUSY; } } configID = object_heap_allocate(&driver_data->config_heap); obj_config = CONFIG(configID); CHECK_ALLOCATION(obj_config); MEMSET_OBJECT(obj_config, struct object_config_s); obj_config->profile = profile; obj_config->format_vtable = format_vtable; obj_config->entrypoint = entrypoint; obj_config->attrib_list[0].type = VAConfigAttribRTFormat; obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420; obj_config->attrib_count = 1; for (i = 0; i < num_attribs; i++) { if (attrib_list[i].type > VAConfigAttribTypeMax) return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; vaStatus = psb__update_attribute(obj_config, &(attrib_list[i])); if (VA_STATUS_SUCCESS != vaStatus) { break; } } if (VA_STATUS_SUCCESS == vaStatus) { vaStatus = psb__validate_config(obj_config); } if (VA_STATUS_SUCCESS == vaStatus) { vaStatus = format_vtable->validateConfig(obj_config); } /* Error recovery */ if (VA_STATUS_SUCCESS != vaStatus) { object_heap_free(&driver_data->config_heap, (object_base_p) obj_config); } else { *config_id = configID; } #ifdef PSBVIDEO_MSVDX_EC if((getenv("PSB_VIDEO_NOEC") == NULL) && (profile == VAProfileH264ConstrainedBaseline)) { drv_debug_msg(VIDEO_DEBUG_INIT, "profile is VAProfileH264ConstrainedBaseline, error concealment is enabled. \n"); driver_data->ec_enabled = 1; } else { driver_data->ec_enabled = 0; } if (profile == VAProfileVP8Version0_3 || profile == VAProfileH264Baseline || profile == VAProfileH264Main || profile == VAProfileH264High || profile == VAProfileH264ConstrainedBaseline) driver_data->ec_enabled = 1; if (!IS_MRFL(driver_data)) { if (profile == VAProfileMPEG4Simple || profile == VAProfileMPEG4AdvancedSimple || profile == VAProfileMPEG4Main) driver_data->ec_enabled = 1; } #else driver_data->ec_enabled = 0; #endif DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_DestroyConfig( VADriverContextP ctx, VAConfigID config_id ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_config_p obj_config; obj_config = CONFIG(config_id); CHECK_CONFIG(obj_config); object_heap_free(&driver_data->config_heap, (object_base_p) obj_config); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_QueryConfigAttributes( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, /* out */ VAEntrypoint *entrypoint, /* out */ VAConfigAttrib *attrib_list, /* out */ int *num_attribs /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_config_p obj_config; int i; CHECK_INVALID_PARAM(profile == NULL); CHECK_INVALID_PARAM(entrypoint == NULL); CHECK_INVALID_PARAM(attrib_list == NULL); CHECK_INVALID_PARAM(num_attribs == NULL); obj_config = CONFIG(config_id); CHECK_CONFIG(obj_config); *profile = obj_config->profile; *entrypoint = obj_config->entrypoint; *num_attribs = obj_config->attrib_count; for (i = 0; i < obj_config->attrib_count; i++) { attrib_list[i] = obj_config->attrib_list[i]; } DEBUG_FUNC_EXIT return vaStatus; } void psb__destroy_surface(psb_driver_data_p driver_data, object_surface_p obj_surface) { if (NULL != obj_surface) { /* delete subpicture association */ psb_SurfaceDeassociateSubpict(driver_data, obj_surface); obj_surface->is_ref_surface = 0; psb_surface_sync(obj_surface->psb_surface); psb_surface_destroy(obj_surface->psb_surface); if (obj_surface->out_loop_surface) { psb_surface_destroy(obj_surface->out_loop_surface); } if (obj_surface->scaling_surface) { psb_surface_destroy(obj_surface->scaling_surface); } free(obj_surface->psb_surface); object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); } } VAStatus psb__checkSurfaceDimensions(psb_driver_data_p driver_data, int width, int height) { if (driver_data->video_sd_disabled) { return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; } if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) { return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; } if (driver_data->video_hd_disabled) { if ((width > 1024) || (height > 576)) { return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; } } return VA_STATUS_SUCCESS; } VAStatus psb_GetSurfaceAttributes( VADriverContextP __maybe_unused ctx, VAConfigID __maybe_unused config, VASurfaceAttrib *attrib_list, unsigned int num_attribs ) { DEBUG_FUNC_ENTER uint32_t i; VAStatus vaStatus = VA_STATUS_SUCCESS; CHECK_INVALID_PARAM(attrib_list == NULL); CHECK_INVALID_PARAM(num_attribs <= 0); /* Generic attributes */ for (i = 0; i < num_attribs; i++) { switch (attrib_list[i].type) { case VASurfaceAttribMemoryType: attrib_list[i].flags = VA_SURFACE_ATTRIB_SETTABLE | VA_SURFACE_ATTRIB_GETTABLE; attrib_list[i].value.type = VAGenericValueTypeInteger; attrib_list[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR | VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION; break; case VASurfaceAttribExternalBufferDescriptor: attrib_list[i].flags = VA_SURFACE_ATTRIB_SETTABLE; attrib_list[i].value.type = VAGenericValueTypePointer; break; default: attrib_list[i].flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED; break; } } DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } #ifdef PSBVIDEO_MSVDX_DEC_TILING unsigned long psb__tile_stride_log2_256(int w) { int stride_mode = 0; if (512 >= w) stride_mode = 1; else if (1024 >= w) stride_mode = 2; else if (2048 >= w) stride_mode = 3; else if (4096 >= w) stride_mode = 4; return stride_mode; } unsigned long psb__tile_stride_log2_512(int w) { int stride_mode = 0; if (512 >= w) stride_mode = 0; else if (1024 >= w) stride_mode = 1; else if (2048 >= w) stride_mode = 2; else if (4096 >= w) stride_mode = 3; return stride_mode; } #endif VAStatus psb_CreateSurfaces( VADriverContextP __maybe_unused ctx, int __maybe_unused width, int __maybe_unused height, int __maybe_unused format, int __maybe_unused num_surfaces, VASurfaceID __maybe_unused * surface_list /* out */ ) { return VA_STATUS_ERROR_UNIMPLEMENTED; } VAStatus psb_CreateSurfaces2( VADriverContextP ctx, unsigned int format, unsigned int width, unsigned int height, VASurfaceID *surface_list, /* out */ unsigned int num_surfaces, VASurfaceAttrib *attrib_list, unsigned int num_attribs ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; unsigned int i; int height_origin, buffer_stride = 0; driver_data->protected = (VA_RT_FORMAT_PROTECTED & format); unsigned long fourcc; unsigned int flags = 0; int memory_type = -1; unsigned int initalized_info_flag = 1; VASurfaceAttribExternalBuffers *pExternalBufDesc = NULL; PsbSurfaceAttributeTPI attribute_tpi; attribute_tpi.buffers = NULL; bool attribute_tpi_buffersAlloced = false; CHECK_INVALID_PARAM(num_surfaces <= 0); CHECK_SURFACE(surface_list); if ((attrib_list != NULL) && (num_attribs > 0)) { for (i = 0; i < num_attribs; i++, attrib_list++) { if (!attrib_list) { if(attribute_tpi.buffers != NULL) free(attribute_tpi.buffers); return VA_STATUS_ERROR_INVALID_PARAMETER; } switch (attrib_list->type) { case VASurfaceAttribExternalBufferDescriptor: { pExternalBufDesc = (VASurfaceAttribExternalBuffers *)attrib_list->value.value.p; if (pExternalBufDesc == NULL) { if(attribute_tpi.buffers != NULL) free(attribute_tpi.buffers); drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid VASurfaceAttribExternalBuffers.\n"); return VA_STATUS_ERROR_INVALID_PARAMETER; } attribute_tpi.type = memory_type; if (attribute_tpi_buffersAlloced == true && attribute_tpi.buffers != NULL) { free(attribute_tpi.buffers); attribute_tpi.buffers = NULL; } attribute_tpi.buffers = malloc(sizeof(long) * pExternalBufDesc->num_buffers); attribute_tpi_buffersAlloced = true; attribute_tpi.width = pExternalBufDesc->width; attribute_tpi.height = pExternalBufDesc->height; attribute_tpi.count = pExternalBufDesc->num_buffers; memcpy((void*)attribute_tpi.buffers, (void*)pExternalBufDesc->buffers, sizeof(pExternalBufDesc->buffers[0]) * pExternalBufDesc->num_buffers); attribute_tpi.pixel_format = pExternalBufDesc->pixel_format; attribute_tpi.size = pExternalBufDesc->data_size; attribute_tpi.luma_stride = pExternalBufDesc->pitches[0]; attribute_tpi.chroma_u_stride = pExternalBufDesc->pitches[1]; attribute_tpi.chroma_v_stride = pExternalBufDesc->pitches[2]; attribute_tpi.luma_offset = pExternalBufDesc->offsets[0]; attribute_tpi.chroma_u_offset = pExternalBufDesc->offsets[1]; attribute_tpi.chroma_v_offset = pExternalBufDesc->offsets[2]; attribute_tpi.reserved[0] = (unsigned long) pExternalBufDesc->private_data; if (pExternalBufDesc->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING) attribute_tpi.tiling = 1; else attribute_tpi.tiling = 0; } break; case VASurfaceAttribMemoryType: { switch (attrib_list->value.value.i) { case VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR: memory_type = VAExternalMemoryUserPointer; break; case VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM: memory_type = VAExternalMemoryKernelDRMBufffer; break; case VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC: memory_type = VAExternalMemoryAndroidGrallocBuffer; break; case VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION: memory_type = VAExternalMemoryIONSharedFD; break; case VA_SURFACE_ATTRIB_MEM_TYPE_VA: memory_type = VAExternalMemoryNULL; break; default: if (attribute_tpi.buffers != NULL) free(attribute_tpi.buffers); drv_debug_msg(VIDEO_DEBUG_ERROR, "Unsupported memory type.\n"); return VA_STATUS_ERROR_INVALID_PARAMETER; } } break; case VASurfaceAttribUsageHint: { /* Share info is to be initialized when created sufaces by default (for the data producer) * VPP Read indicate we do not NOT touch share info (for data consumer, which share buffer with data * producer, such as of VPP). */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "VASurfaceAttribUsageHint.\n"); if ((attrib_list->value.value.i & VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ)!= 0){ initalized_info_flag = 0; drv_debug_msg(VIDEO_DEBUG_GENERAL, "explicat not initialized share info.\n"); } } break; default: if (attribute_tpi.buffers != NULL) free(attribute_tpi.buffers); drv_debug_msg(VIDEO_DEBUG_ERROR, "Unsupported attribute.\n"); return VA_STATUS_ERROR_INVALID_PARAMETER; } } } if ((memory_type == -1 && pExternalBufDesc != NULL) || (memory_type != -1 && pExternalBufDesc == NULL)) { return VA_STATUS_ERROR_INVALID_PARAMETER; } else if(memory_type !=-1 && pExternalBufDesc != NULL) { attribute_tpi.type = memory_type; //set initialized share info in reserverd 1, by default we will initialized share_info attribute_tpi.reserved[2] = (unsigned int)initalized_info_flag; vaStatus = psb_CreateSurfacesWithAttribute(ctx, width, height, format, num_surfaces, surface_list, (VASurfaceAttributeTPI *)&attribute_tpi); pExternalBufDesc->private_data = (void *)(attribute_tpi.reserved[1]); if (attribute_tpi.buffers) free(attribute_tpi.buffers); return vaStatus; } format = format & (~VA_RT_FORMAT_PROTECTED); /* We only support one format */ if ((VA_RT_FORMAT_YUV420 != format) && (VA_RT_FORMAT_YUV422 != format) && (VA_RT_FORMAT_YUV444 != format)) { vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; DEBUG_FAILURE; return vaStatus; } vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); CHECK_VASTATUS(); /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */ height_origin = height; height = (height + 0x1f) & ~0x1f; 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->share_info = NULL; 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; } switch (format) { case VA_RT_FORMAT_YUV444: fourcc = VA_FOURCC_YV32; /* allocate 4 planar */ break; case VA_RT_FORMAT_YUV422: fourcc = VA_FOURCC_YV16; break; case VA_RT_FORMAT_YUV420: default: fourcc = VA_FOURCC_NV12; break; } flags |= driver_data->protected ? IS_PROTECTED : 0; vaStatus = psb_surface_create(driver_data, width, height, fourcc, flags, 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 */ 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) { /* 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; } drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n"); return vaStatus; } DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_DestroySurfaces( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ) { INIT_DRIVER_DATA int i, j; object_context_p obj_context = NULL; VAStatus vaStatus = VA_STATUS_SUCCESS; if (num_surfaces <= 0) { return VA_STATUS_ERROR_INVALID_PARAMETER; } CHECK_SURFACE(surface_list); #if 0 /* Free PVR2D buffer wrapped from the surfaces */ psb_free_surface_pvr2dbuf(driver_data); #endif /* Make validation happy */ for (i = 0; i < num_surfaces; i++) { object_surface_p obj_surface = SURFACE(surface_list[i]); if (obj_surface == NULL) { return VA_STATUS_ERROR_INVALID_SURFACE; } if (obj_surface->derived_imgcnt > 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Some surface is deriving by images\n"); return VA_STATUS_ERROR_OPERATION_FAILED; } } for (i = 0; i < num_surfaces; i++) { object_surface_p obj_surface = SURFACE(surface_list[i]); if (obj_surface == NULL) return VA_STATUS_ERROR_INVALID_SURFACE; if (driver_data->cur_displaying_surface == surface_list[i]) { /* Surface is being displaying. Need to stop overlay here */ psb_coverlay_stop(ctx); } obj_context = CONTEXT(obj_surface->context_id); if (obj_context != NULL) { for (j = 0; j < obj_context->num_render_targets; j++) { if (obj_context->render_targets[j] == obj_surface->surface_id) { obj_context->render_targets[j] = VA_INVALID_SURFACE; break; } } } drv_debug_msg(VIDEO_DEBUG_INIT, "%s : obj_surface->surface_id = 0x%x\n",__FUNCTION__, obj_surface->surface_id); if (obj_surface->share_info) { psb_DestroySurfaceGralloc(obj_surface); } psb__destroy_surface(driver_data, obj_surface); surface_list[i] = VA_INVALID_SURFACE; } DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } int psb_new_context(psb_driver_data_p driver_data, uint64_t ctx_type) { struct drm_lnc_video_getparam_arg arg; int ret = 0; arg.key = IMG_VIDEO_NEW_CONTEXT; arg.value = (uint64_t)((unsigned long) & ctx_type); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret != 0) drv_debug_msg(VIDEO_DEBUG_ERROR, "Set context %d failed\n", ctx_type); return ret; } #ifdef PSBVIDEO_MSVDX_DEC_TILING int psb_update_context(psb_driver_data_p driver_data, unsigned long ctx_type) { struct drm_lnc_video_getparam_arg arg; int ret = 0; arg.key = IMG_VIDEO_UPDATE_CONTEXT; arg.value = (uint64_t)((unsigned long) & ctx_type); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret != 0) drv_debug_msg(VIDEO_DEBUG_ERROR, "Update context %d failed\n", ctx_type); return ret; } #endif int psb_rm_context(psb_driver_data_p driver_data) { struct drm_lnc_video_getparam_arg arg; int tmp; int ret = 0; arg.key = IMG_VIDEO_RM_CONTEXT; arg.value = (uint64_t)((unsigned long) & tmp); /* value is ignored */ ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret != 0) drv_debug_msg(VIDEO_DEBUG_ERROR, "Remove context failed\n"); return ret; } VAStatus psb_CreateContext( VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_config_p obj_config; int cmdbuf_num, encode = 0, proc = 0; int i; drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateContext config_id:%d, pic_w:%d, pic_h:%d, flag:%d, num_render_targets:%d, render_targets: %p.\n", config_id, picture_width, picture_height, flag, num_render_targets, render_targets); CHECK_INVALID_PARAM(num_render_targets < 0); //CHECK_SURFACE(render_targets); CHECK_CONTEXT(context); vaStatus = psb__checkSurfaceDimensions(driver_data, picture_width, picture_height); CHECK_VASTATUS(); obj_config = CONFIG(config_id); CHECK_CONFIG(obj_config); int contextID = object_heap_allocate(&driver_data->context_heap); object_context_p obj_context = CONTEXT(contextID); CHECK_ALLOCATION(obj_context); *context = contextID; MEMSET_OBJECT(obj_context, struct object_context_s); obj_context->driver_data = driver_data; obj_context->current_render_target = NULL; obj_context->ec_target = NULL; obj_context->ec_candidate = NULL; obj_context->is_oold = driver_data->is_oold; obj_context->context_id = contextID; obj_context->config_id = config_id; obj_context->picture_width = picture_width; obj_context->picture_height = picture_height; obj_context->num_render_targets = num_render_targets; obj_context->msvdx_scaling = 0; #ifdef SLICE_HEADER_PARSING obj_context->msvdx_frame_end = 0; for (i = 0; i < obj_config->attrib_count; i++) { if ((obj_config->attrib_list[i].type == VAConfigAttribDecSliceMode) && (obj_config->attrib_list[i].value == VA_DEC_SLICE_MODE_SUBSAMPLE)) { obj_context->modular_drm = 1; break; } } #endif obj_context->scaling_width = 0; obj_context->scaling_height = 0; if (num_render_targets > 0) { obj_context->render_targets = (VASurfaceID *) calloc(1, num_render_targets * sizeof(VASurfaceID)); if (obj_context->render_targets == NULL) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; object_heap_free(&driver_data->context_heap, (object_base_p) obj_context); return vaStatus; } } /* allocate buffer points for vaRenderPicture */ obj_context->num_buffers = 10; obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * obj_context->num_buffers); if (obj_context->buffer_list == NULL) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; if (NULL != obj_context->render_targets) free(obj_context->render_targets); object_heap_free(&driver_data->context_heap, (object_base_p) obj_context); return vaStatus; } memset(obj_context->buffers_unused, 0, sizeof(obj_context->buffers_unused)); memset(obj_context->buffers_unused_count, 0, sizeof(obj_context->buffers_unused_count)); memset(obj_context->buffers_unused_tail, 0, sizeof(obj_context->buffers_unused_tail)); memset(obj_context->buffers_active, 0, sizeof(obj_context->buffers_active)); if (obj_config->entrypoint == VAEntrypointEncSlice || obj_config->entrypoint == VAEntrypointEncPicture) { encode = 1; } #ifdef PSBVIDEO_MRFL_VPP if (obj_config->entrypoint == VAEntrypointVideoProc) proc = 1; //todo: fixme if (obj_config->entrypoint == VAEntrypointEncSlice && obj_config->profile == VAProfileVP8Version0_3){ proc = 1; encode = 0; } #endif if (encode) cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE; else if (proc) cmdbuf_num = VSP_MAX_CMDBUFS; else cmdbuf_num = PSB_MAX_CMDBUFS; if (num_render_targets > 0 && (render_targets != NULL)) { for (i = 0; i < num_render_targets; i++) { object_surface_p obj_surface = SURFACE(render_targets[i]); psb_surface_p psb_surface; if (NULL == obj_surface) { vaStatus = VA_STATUS_ERROR_INVALID_SURFACE; DEBUG_FAILURE; break; } if (!driver_data->protected && obj_surface->share_info) obj_surface->share_info->force_output_method = 0; psb_surface = obj_surface->psb_surface; /* Clear format specific surface info */ obj_context->render_targets[i] = render_targets[i]; obj_surface->context_id = contextID; /* Claim ownership of surface */ #ifdef PSBVIDEO_MSVDX_DEC_TILING if (GET_SURFACE_INFO_tiling(psb_surface)) { #ifdef BAYTRAIL obj_context->msvdx_tile = psb__tile_stride_log2_512(obj_surface->width); #else if (obj_config->entrypoint == VAEntrypointVideoProc && obj_config->profile == VAProfileNone) // It's for two pass rotation case // Need the source surface width for tile stride setting obj_context->msvdx_tile = psb__tile_stride_log2_256(obj_context->picture_width); else obj_context->msvdx_tile = psb__tile_stride_log2_256(obj_surface->width); #endif } #endif #if 0 /* for decode, move the surface into |TT */ if ((encode == 0) && /* decode */ ((psb_surface->buf.pl_flags & DRM_PSB_FLAG_MEM_RAR) == 0)) /* surface not in RAR */ psb_buffer_setstatus(&obj_surface->psb_surface->buf, WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED, DRM_PSB_FLAG_MEM_MMU); #endif } } else if (num_render_targets > 0) { for (i = 0; i < num_render_targets; i++) { obj_context->render_targets[i] = VA_INVALID_SURFACE; } } obj_context->va_flags = flag; obj_context->format_vtable = obj_config->format_vtable; obj_context->format_data = NULL; if (VA_STATUS_SUCCESS == vaStatus) { vaStatus = obj_context->format_vtable->createContext(obj_context, obj_config); } /* Error recovery */ if (VA_STATUS_SUCCESS != vaStatus) { obj_context->context_id = -1; obj_context->config_id = -1; obj_context->picture_width = 0; obj_context->picture_height = 0; if (NULL != obj_context->render_targets) free(obj_context->render_targets); free(obj_context->buffer_list); obj_context->num_buffers = 0; obj_context->render_targets = NULL; obj_context->num_render_targets = 0; obj_context->va_flags = 0; object_heap_free(&driver_data->context_heap, (object_base_p) obj_context); return vaStatus; } /* initialize cmdbuf */ for (i = 0; i < PNW_MAX_CMDBUFS_ENCODE; i++) { obj_context->pnw_cmdbuf_list[i] = NULL; } #ifdef PSBVIDEO_MRFL for (i = 0; i < TNG_MAX_CMDBUFS_ENCODE; i++) { obj_context->tng_cmdbuf_list[i] = NULL; } #endif #ifdef PSBVIDEO_MRFL_VPP for (i = 0; i < VSP_MAX_CMDBUFS; i++) { obj_context->vsp_cmdbuf_list[i] = NULL; } #endif for (i = 0; i < PSB_MAX_CMDBUFS; i++) { obj_context->cmdbuf_list[i] = NULL; } for (i = 0; i < cmdbuf_num; i++) { #ifndef BAYTRAIL if (encode) { /* Topaz encode context */ #ifdef PSBVIDEO_MRFL if (IS_MRFL(obj_context->driver_data)) { obj_context->tng_cmdbuf_list[i] = calloc(1, sizeof(struct tng_cmdbuf_s)); if (NULL == obj_context->tng_cmdbuf_list[i]) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; break; } } #endif #ifdef PSBVIDEO_MFLD if (IS_MFLD(obj_context->driver_data)) { obj_context->pnw_cmdbuf_list[i] = calloc(1, sizeof(struct pnw_cmdbuf_s)); if (NULL == obj_context->pnw_cmdbuf_list[i]) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; break; } } #endif } else if (proc) { /* VSP VPP context */ /* VED two pass rotation under VPP API */ if (driver_data->ved_vpp) { obj_context->cmdbuf_list[i] = calloc(1, sizeof(struct psb_cmdbuf_s)); if (NULL == obj_context->cmdbuf_list[i]) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; break; } } #ifdef PSBVIDEO_MRFL_VPP else if (IS_MRFL(obj_context->driver_data)) { obj_context->vsp_cmdbuf_list[i] = calloc(1, sizeof(struct vsp_cmdbuf_s)); if (NULL == obj_context->vsp_cmdbuf_list[i]) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; break; } } #endif } else /* MSVDX decode context */ { #endif obj_context->cmdbuf_list[i] = calloc(1, sizeof(struct psb_cmdbuf_s)); if (NULL == obj_context->cmdbuf_list[i]) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; break; } } #ifndef BAYTRAIL if (encode) { /* Topaz encode context */ #ifdef PSBVIDEO_MRFL if (IS_MRFL(obj_context->driver_data)) { vaStatus = tng_cmdbuf_create(obj_context, driver_data, (tng_cmdbuf_p)obj_context->tng_cmdbuf_list[i]); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_context->tng_cmdbuf_list[i]); DEBUG_FAILURE; break; } } #endif #ifdef PSBVIDEO_MFLD if (IS_MFLD(obj_context->driver_data)) { vaStatus = pnw_cmdbuf_create(obj_context, driver_data, (pnw_cmdbuf_p)obj_context->pnw_cmdbuf_list[i]); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_context->pnw_cmdbuf_list[i]); DEBUG_FAILURE; break; } } #endif } else if (proc) { /* VSP VPP context */ if (driver_data->ved_vpp) { vaStatus = psb_cmdbuf_create(obj_context, driver_data, (psb_cmdbuf_p)obj_context->cmdbuf_list[i]); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_context->cmdbuf_list[i]); DEBUG_FAILURE; break; } } #ifdef PSBVIDEO_MRFL_VPP else if (IS_MRFL(obj_context->driver_data)) { vaStatus = vsp_cmdbuf_create(obj_context, driver_data, (vsp_cmdbuf_p)obj_context->vsp_cmdbuf_list[i]); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_context->vsp_cmdbuf_list[i]); DEBUG_FAILURE; break; } } #endif } else /* MSVDX decode context */ { #endif vaStatus = psb_cmdbuf_create(obj_context, driver_data, (psb_cmdbuf_p)obj_context->cmdbuf_list[i]); if (VA_STATUS_SUCCESS != vaStatus) { free(obj_context->cmdbuf_list[i]); DEBUG_FAILURE; break; } } #ifndef BAYTRAIL if (encode) { /* Topaz encode context */ if (i >= LNC_MAX_CMDBUFS_ENCODE) { #ifdef PSBVIDEO_MRFL tng_cmdbuf_destroy((tng_cmdbuf_p)obj_context->tng_cmdbuf_list[i]); free(obj_context->tng_cmdbuf_list[i]); #endif #ifdef PSBVIDEO_MFLD pnw_cmdbuf_destroy((pnw_cmdbuf_p)obj_context->pnw_cmdbuf_list[i]); free(obj_context->pnw_cmdbuf_list[i]); #endif DEBUG_FAILURE; break; } } #endif } obj_context->cmdbuf_current = -1; obj_context->cmdbuf = NULL; obj_context->pnw_cmdbuf = NULL; obj_context->tng_cmdbuf = NULL; #ifdef PSBVIDEO_MRFL_VPP obj_context->vsp_cmdbuf = NULL; #endif obj_context->frame_count = 0; obj_context->slice_count = 0; obj_context->msvdx_context = ((driver_data->msvdx_context_base & 0xff0000) >> 16) | ((contextID & 0xff000000) >> 16); #ifdef ANDROID obj_context->msvdx_context = ((driver_data->drm_fd & 0xf) << 4) | ((unsigned int)gettid() & 0xf); #endif obj_context->profile = obj_config->profile; obj_context->entry_point = obj_config->entrypoint; /* Error recovery */ if (VA_STATUS_SUCCESS != vaStatus) { if (cmdbuf_num > LNC_MAX_CMDBUFS_ENCODE) cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE; for (i = 0; i < cmdbuf_num; i++) { #ifndef BAYTRAIL 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; } #endif #ifdef PSBVIDEO_MRFL if (obj_context->tng_cmdbuf_list[i]) { tng_cmdbuf_destroy(obj_context->tng_cmdbuf_list[i]); free(obj_context->tng_cmdbuf_list[i]); obj_context->tng_cmdbuf_list[i] = NULL; } #endif if (obj_context->cmdbuf_list[i]) { psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]); free(obj_context->cmdbuf_list[i]); obj_context->cmdbuf_list[i] = NULL; } #ifdef PSBVIDEO_MRFL_VPP if (obj_context->vsp_cmdbuf_list[i]) { vsp_cmdbuf_destroy(obj_context->vsp_cmdbuf_list[i]); free(obj_context->vsp_cmdbuf_list[i]); obj_context->vsp_cmdbuf_list[i] = NULL; } #endif } obj_context->cmdbuf = NULL; #ifdef PSBVIDEO_MRFL_VPP obj_context->vsp_cmdbuf = NULL; #endif obj_context->context_id = -1; obj_context->config_id = -1; obj_context->picture_width = 0; obj_context->picture_height = 0; if (NULL != obj_context->render_targets) free(obj_context->render_targets); free(obj_context->buffer_list); obj_context->num_buffers = 0; obj_context->render_targets = NULL; obj_context->num_render_targets = 0; obj_context->va_flags = 0; object_heap_free(&driver_data->context_heap, (object_base_p) obj_context); } obj_context->ctp_type = (((obj_config->profile << 8) | obj_config->entrypoint | driver_data->protected) & 0xffff); /* VSP's PM rely on VPP ctx, so ved vpp use diferent profile/level for ctx */ if (driver_data->ved_vpp) obj_context->ctp_type = (((obj_config->profile << 8) | VAEntrypointVLD | driver_data->protected) & 0xffff); if (!encode) { obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16); } if (obj_context->ctp_type & VAEntrypointVLD) { if (render_targets == NULL) { obj_context->ctp_type |= PSB_SURFACE_UNAVAILABLE; } } if (obj_context->ctp_type & VAEntrypointVLD) { if (render_targets == NULL) { obj_context->ctp_type |= PSB_SURFACE_UNAVAILABLE; } } if (obj_config->profile == VAProfileVC1Simple || obj_config->profile == VAProfileVC1Main || obj_config->profile == VAProfileVC1Advanced || obj_config->profile == VAProfileH264Baseline || obj_config->profile == VAProfileH264Main || obj_config->profile == VAProfileH264High || obj_config->profile == VAProfileVP8Version0_3) { uint64_t width_in_mb = ((driver_data->render_rect.x + driver_data->render_rect.width + 15) / 16); uint64_t height_in_mb = ((driver_data->render_rect.y + driver_data->render_rect.height + 15) / 16); obj_context->ctp_type |= (width_in_mb << 32); obj_context->ctp_type |= (height_in_mb << 48); } /* add ctx_num to save vp8 enc context num to support dual vp8 encoding */ int ret = psb_new_context(driver_data, obj_context->ctp_type | driver_data->protected); if (ret) vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FUNC_EXIT return vaStatus; } static VAStatus psb__allocate_malloc_buffer(object_buffer_p obj_buffer, int size) { VAStatus vaStatus = VA_STATUS_SUCCESS; obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size); CHECK_ALLOCATION(obj_buffer->buffer_data); return vaStatus; } static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer); static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_context_p __maybe_unused obj_context, object_buffer_p obj_buffer, int size, unsigned char *data, VABufferType type) { VAStatus vaStatus = VA_STATUS_SUCCESS; ASSERT(NULL == obj_buffer->buffer_data); if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Abandoning BO for buffer %08x type %s\n", obj_buffer->base.id, buffer_type_to_string(obj_buffer->type)); /* need to set psb_buffer aside and get another one */ obj_buffer->psb_buffer->status = psb_bs_abandoned; obj_buffer->psb_buffer = NULL; obj_buffer->size = 0; obj_buffer->alloc_size = 0; } if (type == VAProtectedSliceDataBufferType) { if (obj_buffer->psb_buffer) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: old RAR slice buffer with RAR handle 0%08x, current RAR handle 0x%08x\n", obj_buffer->psb_buffer->rar_handle, (uint32_t)data); drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: force old RAR buffer destroy and new buffer re-allocation by set size=0\n"); obj_buffer->alloc_size = 0; } } if (obj_buffer->alloc_size < (unsigned int)size) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Buffer size mismatch: Need %d, currently have %d\n", size, obj_buffer->alloc_size); if (obj_buffer->psb_buffer) { if (obj_buffer->buffer_data) { psb__unmap_buffer(obj_buffer); } psb_buffer_destroy(obj_buffer->psb_buffer); obj_buffer->alloc_size = 0; } else { obj_buffer->psb_buffer = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s)); if (NULL == obj_buffer->psb_buffer) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; } } if (VA_STATUS_SUCCESS == vaStatus) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate new GPU buffers for vaCreateBuffer:type=%s,size=%d.\n", buffer_type_to_string(obj_buffer->type), size); size = (size + 0x7fff) & ~0x7fff; /* Round up */ if (obj_buffer->type == VAImageBufferType) /* Xserver side PutSurface, Image/subpicture buffer * should be shared between two process */ vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu_shared, obj_buffer->psb_buffer); #ifndef BAYTRAIL else if (obj_buffer->type == VAProtectedSliceDataBufferType) { vaStatus = psb_buffer_reference_imr(driver_data, (uint32_t)data, obj_buffer->psb_buffer); } #endif else if (obj_buffer->type == VAEncCodedBufferType) vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, 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); obj_buffer->psb_buffer = NULL; DEBUG_FAILURE; } else { obj_buffer->alloc_size = size; } } } return vaStatus; } static VAStatus psb__map_buffer(object_buffer_p obj_buffer) { if (obj_buffer->psb_buffer) { return psb_buffer_map(obj_buffer->psb_buffer, &obj_buffer->buffer_data); } return VA_STATUS_SUCCESS; } static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer) { if (obj_buffer->psb_buffer) { obj_buffer->buffer_data = NULL; return psb_buffer_unmap(obj_buffer->psb_buffer); } return VA_STATUS_SUCCESS; } static void psb__destroy_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer) { if (obj_buffer->psb_buffer) { if (obj_buffer->buffer_data) { psb__unmap_buffer(obj_buffer); } psb_buffer_destroy(obj_buffer->psb_buffer); free(obj_buffer->psb_buffer); obj_buffer->psb_buffer = NULL; } if (NULL != obj_buffer->buffer_data) { free(obj_buffer->buffer_data); obj_buffer->buffer_data = NULL; obj_buffer->size = 0; } object_heap_free(&driver_data->buffer_heap, (object_base_p) obj_buffer); } void psb__suspend_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer) { if (obj_buffer->context) { VABufferType type = obj_buffer->type; object_context_p obj_context = obj_buffer->context; if (type >= PSB_MAX_BUFFERTYPES) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid buffer type %d\n", type); return; } /* Remove buffer from active list */ *obj_buffer->pptr_prev_next = obj_buffer->ptr_next; /* Add buffer to tail of unused list */ obj_buffer->ptr_next = NULL; obj_buffer->last_used = obj_context->frame_count; if (obj_context->buffers_unused_tail[type]) { obj_buffer->pptr_prev_next = &(obj_context->buffers_unused_tail[type]->ptr_next); } else { obj_buffer->pptr_prev_next = &(obj_context->buffers_unused[type]); } *obj_buffer->pptr_prev_next = obj_buffer; obj_context->buffers_unused_tail[type] = obj_buffer; obj_context->buffers_unused_count[type]++; drv_debug_msg(VIDEO_DEBUG_GENERAL, "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; } if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) { /* need to set psb_buffer aside */ obj_buffer->psb_buffer->status = psb_bs_abandoned; obj_buffer->psb_buffer = NULL; } psb__destroy_buffer(driver_data, obj_buffer); } static void psb__destroy_context(psb_driver_data_p driver_data, object_context_p obj_context) { int encode, i; if (obj_context->entry_point == VAEntrypointEncSlice) encode = 1; else encode = 0; obj_context->format_vtable->destroyContext(obj_context); for (i = 0; i < PSB_MAX_BUFFERTYPES; i++) { object_buffer_p obj_buffer; obj_buffer = obj_context->buffers_active[i]; for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) { drv_debug_msg(VIDEO_DEBUG_INIT, "%s: destroying active buffer %08x\n", __FUNCTION__, obj_buffer->base.id); psb__destroy_buffer(driver_data, obj_buffer); } obj_buffer = obj_context->buffers_unused[i]; for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) { drv_debug_msg(VIDEO_DEBUG_INIT, "%s: destroying unused buffer %08x\n", __FUNCTION__, obj_buffer->base.id); psb__destroy_buffer(driver_data, obj_buffer); } obj_context->buffers_unused_count[i] = 0; } #ifndef BAYTRAIL 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; } } #endif #ifdef PSBVIDEO_MRFL for (i = 0; i < TNG_MAX_CMDBUFS_ENCODE; i++) { if (obj_context->tng_cmdbuf_list[i]) { tng_cmdbuf_destroy(obj_context->tng_cmdbuf_list[i]); free(obj_context->tng_cmdbuf_list[i]); obj_context->tng_cmdbuf_list[i] = NULL; } } #endif #ifdef PSBVIDEO_MRFL_VPP for (i = 0; i < VSP_MAX_CMDBUFS; i++) { if (obj_context->vsp_cmdbuf_list[i]) { vsp_cmdbuf_destroy(obj_context->vsp_cmdbuf_list[i]); free(obj_context->vsp_cmdbuf_list[i]); obj_context->vsp_cmdbuf_list[i] = NULL; } } #endif for (i = 0; i < PSB_MAX_CMDBUFS; i++) { if (obj_context->cmdbuf_list[i]) { psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]); free(obj_context->cmdbuf_list[i]); obj_context->cmdbuf_list[i] = NULL; } } obj_context->cmdbuf = NULL; #ifdef PSBVIDEO_MRFL_VPP obj_context->vsp_cmdbuf = NULL; #endif obj_context->context_id = -1; obj_context->config_id = -1; obj_context->picture_width = 0; obj_context->picture_height = 0; if (obj_context->render_targets) free(obj_context->render_targets); obj_context->render_targets = NULL; obj_context->num_render_targets = 0; obj_context->va_flags = 0; obj_context->current_render_target = NULL; obj_context->ec_target = NULL; obj_context->ec_candidate = NULL; if (obj_context->buffer_list) free(obj_context->buffer_list); obj_context->num_buffers = 0; object_heap_free(&driver_data->context_heap, (object_base_p) obj_context); psb_rm_context(driver_data); } VAStatus psb_DestroyContext( VADriverContextP ctx, VAContextID context ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_context_p obj_context = CONTEXT(context); CHECK_CONTEXT(obj_context); psb__destroy_context(driver_data, obj_context); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb__CreateBuffer( psb_driver_data_p driver_data, object_context_p obj_context, /* in */ VABufferType type, /* in */ unsigned int size, /* in */ unsigned int num_elements, /* in */ unsigned char *data, /* in */ VABufferID *buf_desc /* out */ ) { DEBUG_FUNC_ENTER VAStatus vaStatus = VA_STATUS_SUCCESS; int bufferID; object_buffer_p obj_buffer; int unused_count; /*PSB_MAX_BUFFERTYPES is the size of array buffers_unused*/ if (type >= PSB_MAX_BUFFERTYPES) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid buffer type %d\n", type); return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; } obj_buffer = obj_context ? obj_context->buffers_unused[type] : NULL; unused_count = obj_context ? obj_context->buffers_unused_count[type] : 0; /* * Buffer Management * For each buffer type, maintain * - a LRU sorted list of unused buffers * - a list of active buffers * We only create a new buffer when * - no unused buffers are available * - the last unused buffer is still queued * - the last unused buffer was used very recently and may still be fenced * - used recently is defined as within the current frame_count (subject to tweaks) * * The buffer that is returned will be moved to the list of active buffers * - vaDestroyBuffer and vaRenderPicture will move the active buffer back to the list of unused buffers */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "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)) { drv_debug_msg(VIDEO_DEBUG_ERROR, "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) { /* Buffer is still queued, allocate new buffer instead */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "Skipping idle buffer %08x, still queued\n", obj_buffer->base.id); obj_buffer = NULL; } else if ((obj_buffer->last_used == obj_context->frame_count) && (unused_count < MAX_UNUSED_BUFFERS)) { /* Buffer was used for this frame, allocate new buffer instead */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "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 */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "Skipping idle buffer %08x used by frame %d. Unused = %d\n", obj_buffer->base.id, obj_buffer->last_used, unused_count); obj_buffer = NULL; } } if (obj_buffer) { bufferID = obj_buffer->base.id; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Reusing buffer %08x type %s from unused list. Unused = %d\n", bufferID, buffer_type_to_string(type), unused_count); /* Remove from unused list */ obj_context->buffers_unused[type] = obj_buffer->ptr_next; if (obj_context->buffers_unused[type]) { obj_context->buffers_unused[type]->pptr_prev_next = &(obj_context->buffers_unused[type]); ASSERT(obj_context->buffers_unused_tail[type] != obj_buffer); } else { ASSERT(obj_context->buffers_unused_tail[type] == obj_buffer); obj_context->buffers_unused_tail[type] = 0; } obj_context->buffers_unused_count[type]--; object_heap_suspend_object((object_base_p)obj_buffer, 0); /* Make BufferID valid again */ ASSERT(type == obj_buffer->type); ASSERT(obj_context == obj_buffer->context); } else { bufferID = object_heap_allocate(&driver_data->buffer_heap); obj_buffer = BUFFER(bufferID); CHECK_ALLOCATION(obj_buffer); MEMSET_OBJECT(obj_buffer, struct object_buffer_s); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocating new buffer %08x type %s.\n", bufferID, buffer_type_to_string(type)); obj_buffer->type = type; obj_buffer->buffer_data = NULL; obj_buffer->psb_buffer = NULL; obj_buffer->size = 0; obj_buffer->max_num_elements = 0; obj_buffer->alloc_size = 0; obj_buffer->context = obj_context; } if (obj_context) { /* Add to front of active list */ obj_buffer->ptr_next = obj_context->buffers_active[type]; if (obj_buffer->ptr_next) { obj_buffer->ptr_next->pptr_prev_next = &(obj_buffer->ptr_next); } obj_buffer->pptr_prev_next = &(obj_context->buffers_active[type]); *obj_buffer->pptr_prev_next = obj_buffer; } switch (obj_buffer->type) { case VABitPlaneBufferType: case VASliceDataBufferType: case VAResidualDataBufferType: case VAImageBufferType: case VASliceGroupMapBufferType: case VAEncCodedBufferType: case VAProtectedSliceDataBufferType: #ifdef SLICE_HEADER_PARSING case VAParseSliceHeaderGroupBufferType: #endif vaStatus = psb__allocate_BO_buffer(driver_data, obj_context,obj_buffer, size * num_elements, data, obj_buffer->type); DEBUG_FAILURE; break; case VAPictureParameterBufferType: case VAIQMatrixBufferType: case VASliceParameterBufferType: case VAMacroblockParameterBufferType: case VADeblockingParameterBufferType: case VAEncPackedHeaderParameterBufferType: case VAEncPackedHeaderDataBufferType: case VAEncSequenceParameterBufferType: case VAEncPictureParameterBufferType: case VAEncSliceParameterBufferType: case VAQMatrixBufferType: case VAEncMiscParameterBufferType: case VAProbabilityBufferType: case VAHuffmanTableBufferType: case VAProcPipelineParameterBufferType: case VAProcFilterParameterBufferType: #ifdef SLICE_HEADER_PARSING case VAParsePictureParameterBufferType: #endif drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate new malloc buffers for vaCreateBuffer:type=%s,size=%d, buffer_data=%p.\n", buffer_type_to_string(type), size, obj_buffer->buffer_data); vaStatus = psb__allocate_malloc_buffer(obj_buffer, size * num_elements); DEBUG_FAILURE; break; default: vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; DEBUG_FAILURE; break;; } if (VA_STATUS_SUCCESS == vaStatus) { obj_buffer->size = size; obj_buffer->max_num_elements = num_elements; obj_buffer->num_elements = num_elements; if (data && (obj_buffer->type != VAProtectedSliceDataBufferType)) { vaStatus = psb__map_buffer(obj_buffer); if (VA_STATUS_SUCCESS == vaStatus) { memcpy(obj_buffer->buffer_data, data, size * num_elements); psb__unmap_buffer(obj_buffer); } } } if (VA_STATUS_SUCCESS == vaStatus) { *buf_desc = bufferID; } else { psb__destroy_buffer(driver_data, obj_buffer); } DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_CreateBuffer( VADriverContextP ctx, VAContextID context, /* in */ VABufferType type, /* in */ unsigned int size, /* in */ unsigned int num_elements, /* in */ void *data, /* in */ VABufferID *buf_desc /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; CHECK_INVALID_PARAM(num_elements <= 0); switch (type) { case VABitPlaneBufferType: case VASliceDataBufferType: case VAProtectedSliceDataBufferType: case VAResidualDataBufferType: case VASliceGroupMapBufferType: case VAPictureParameterBufferType: case VAIQMatrixBufferType: case VASliceParameterBufferType: case VAMacroblockParameterBufferType: case VADeblockingParameterBufferType: case VAEncCodedBufferType: case VAEncSequenceParameterBufferType: case VAEncPictureParameterBufferType: case VAEncSliceParameterBufferType: case VAEncPackedHeaderParameterBufferType: case VAEncPackedHeaderDataBufferType: case VAQMatrixBufferType: case VAEncMiscParameterBufferType: case VAProbabilityBufferType: case VAHuffmanTableBufferType: case VAProcPipelineParameterBufferType: case VAProcFilterParameterBufferType: #ifdef SLICE_HEADER_PARSING case VAParsePictureParameterBufferType: case VAParseSliceHeaderGroupBufferType: #endif break; default: vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; DEBUG_FAILURE; return vaStatus; } object_context_p obj_context = CONTEXT(context); CHECK_CONTEXT(obj_context); CHECK_INVALID_PARAM(buf_desc == NULL); vaStatus = psb__CreateBuffer(driver_data, obj_context, type, size, num_elements, data, buf_desc); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_BufferInfo( VADriverContextP ctx, VABufferID buf_id, /* in */ VABufferType *type, /* out */ unsigned int *size, /* out */ unsigned int *num_elements /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_buffer_p obj_buffer = BUFFER(buf_id); CHECK_BUFFER(obj_buffer); *type = obj_buffer->type; *size = obj_buffer->size; *num_elements = obj_buffer->num_elements; DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } VAStatus psb_BufferSetNumElements( VADriverContextP ctx, VABufferID buf_id, /* in */ unsigned int num_elements /* in */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_buffer_p obj_buffer = BUFFER(buf_id); CHECK_BUFFER(obj_buffer); if ((num_elements <= 0) || (num_elements > obj_buffer->max_num_elements)) { vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; } if (VA_STATUS_SUCCESS == vaStatus) { obj_buffer->num_elements = num_elements; } DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_MapBuffer( VADriverContextP ctx, VABufferID buf_id, /* in */ void **pbuf /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_buffer_p obj_buffer = BUFFER(buf_id); CHECK_BUFFER(obj_buffer); CHECK_INVALID_PARAM(pbuf == NULL); vaStatus = psb__map_buffer(obj_buffer); CHECK_VASTATUS(); if (NULL != obj_buffer->buffer_data) { *pbuf = obj_buffer->buffer_data; /* specifically for Topaz encode * write validate coded data offset in CodedBuffer */ if (obj_buffer->type == VAEncCodedBufferType) psb_codedbuf_map_mangle(ctx, obj_buffer, pbuf); /* *(IMG_UINT32 *)((unsigned char *)obj_buffer->buffer_data + 4) = 16; */ } else { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; } DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_UnmapBuffer( VADriverContextP ctx, VABufferID buf_id /* in */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_buffer_p obj_buffer = BUFFER(buf_id); CHECK_BUFFER(obj_buffer); vaStatus = psb__unmap_buffer(obj_buffer); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_DestroyBuffer( VADriverContextP ctx, VABufferID buffer_id ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_buffer_p obj_buffer = BUFFER(buffer_id); if (NULL == obj_buffer) { return vaStatus; } psb__suspend_buffer(driver_data, obj_buffer); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_BeginPicture( VADriverContextP ctx, VAContextID context, VASurfaceID render_target ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_context_p obj_context; object_surface_p obj_surface; object_config_p obj_config; unsigned int i = 0, j = VA_INVALID_ID; obj_context = CONTEXT(context); CHECK_CONTEXT(obj_context); /* Must not be within BeginPicture / EndPicture already */ ASSERT(obj_context->current_render_target == NULL); obj_surface = SURFACE(render_target); CHECK_SURFACE(obj_surface); obj_context->current_render_surface_id = render_target; obj_context->current_render_target = obj_surface; obj_context->slice_count = 0; obj_config = CONFIG(obj_context->config_id); if (obj_config == NULL) return VA_STATUS_ERROR_INVALID_CONFIG; for (i = 0; i < (unsigned int)obj_context->num_render_targets; i++) { if (obj_context->render_targets[i] == obj_surface->surface_id) { break; } else if (SURFACE(obj_context->render_targets[i]) == NULL) { j = (i < j) ? i : j; } } if (i >= (unsigned int)obj_context->num_render_targets) { if (j < (unsigned int)obj_context->num_render_targets) { obj_context->render_targets[j] = obj_surface->surface_id; obj_surface->context_id = obj_context->context_id; #ifdef PSBVIDEO_MSVDX_DEC_TILING if (GET_SURFACE_INFO_tiling(obj_surface->psb_surface)) { #ifdef BAYTRAIL obj_context->msvdx_tile = psb__tile_stride_log2_512(obj_surface->width); #else if ( (obj_config != NULL) && (obj_config->entrypoint == VAEntrypointVideoProc) && (obj_config->profile == VAProfileNone)) { obj_context->msvdx_tile = psb__tile_stride_log2_256(obj_context->picture_width); } else { obj_context->msvdx_tile = psb__tile_stride_log2_256(obj_surface->width); } #endif } obj_context->msvdx_tile &= 0xf; /* clear rotate tile */ obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */ obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16); obj_context->ctp_type &= (~PSB_SURFACE_UNAVAILABLE); psb_update_context(driver_data, obj_context->ctp_type | driver_data->protected); #endif } } if ((driver_data->protected & VA_RT_FORMAT_PROTECTED) && !(obj_context->ctp_type & VA_RT_FORMAT_PROTECTED)) { obj_context->ctp_type |= VA_RT_FORMAT_PROTECTED; psb_update_context(driver_data, obj_context->ctp_type); } /* if the surface is decode render target, and in displaying */ if (obj_config && (obj_config->entrypoint != VAEntrypointEncSlice) && (driver_data->cur_displaying_surface == render_target)) drv_debug_msg(VIDEO_DEBUG_ERROR, "WARNING: rendering a displaying surface, may see tearing\n"); if (VA_STATUS_SUCCESS == vaStatus) { vaStatus = obj_context->format_vtable->beginPicture(obj_context); } #ifdef ANDROID /* want msvdx to do rotate * but check per-context stream type: interlace or not */ if ((obj_config->entrypoint != VAEntrypointEncSlice) && (obj_config->entrypoint != VAEntrypointEncPicture)) { psb_RecalcAlternativeOutput(obj_context); } #endif #ifdef PSBVIDEO_MRFL_VPP_ROTATE if (driver_data->vpp_on && GET_SURFACE_INFO_tiling(obj_surface->psb_surface)) driver_data->disable_msvdx_rotate = 0; #endif if (obj_context->interlaced_stream || driver_data->disable_msvdx_rotate) { int i = 0; obj_context->msvdx_rotate = 0; if (obj_context->num_render_targets > 0) { for (i = 0; i < obj_context->num_render_targets; i++) { object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]); /*we invalidate all surfaces's rotate buffer share info here.*/ if (obj_surface && obj_surface->share_info) { obj_surface->share_info->surface_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->out_loop_surface may not be updated */ SET_SURFACE_INFO_rotate(obj_surface->psb_surface, obj_context->msvdx_rotate); if (CONTEXT_SCALING(obj_context) && obj_config->entrypoint != VAEntrypointEncSlice) if(VA_STATUS_SUCCESS != psb_CreateScalingSurface(obj_context, obj_surface)) { obj_context->msvdx_scaling = 0; ALOGE("%s: fail to allocate scaling surface", __func__); } if (CONTEXT_ROTATE(obj_context)) { #ifdef PSBVIDEO_MRFL_VPP_ROTATE /* The VSP rotation is just for 1080P with tilling */ if (driver_data->vpp_on && GET_SURFACE_INFO_tiling(obj_surface->psb_surface)) { if (obj_config->entrypoint == VAEntrypointVideoProc) vaStatus = psb_CreateRotateSurface(obj_context, obj_surface, obj_context->msvdx_rotate); else { SET_SURFACE_INFO_rotate(obj_surface->psb_surface, 0); obj_context->msvdx_rotate = 0; vaStatus = psb_DestroyRotateBuffer(obj_context, obj_surface); } } else #endif vaStatus = psb_CreateRotateSurface(obj_context, obj_surface, obj_context->msvdx_rotate); if (VA_STATUS_SUCCESS !=vaStatus) ALOGE("%s: fail to allocate out loop surface", __func__); } else { if (obj_surface && obj_surface->share_info) { obj_surface->share_info->metadata_rotate = VAROTATION2HAL(driver_data->va_rotate); obj_surface->share_info->surface_rotate = VAROTATION2HAL(obj_context->msvdx_rotate); } } if (obj_surface && obj_surface->share_info && obj_config->entrypoint == VAEntrypointVLD) { obj_surface->share_info->crop_width = driver_data->render_rect.width; obj_surface->share_info->crop_height = driver_data->render_rect.height; } if (driver_data->is_oold && !obj_surface->psb_surface->in_loop_buf) { psb_surface_p psb_surface = obj_surface->psb_surface; psb_surface->in_loop_buf = calloc(1, sizeof(struct psb_buffer_s)); CHECK_ALLOCATION(psb_surface->in_loop_buf); /* FIXME: For RAR surface, need allocate RAR buffer */ vaStatus = psb_buffer_create(obj_context->driver_data, psb_surface->size, psb_bt_surface, psb_surface->in_loop_buf); } else if (!driver_data->is_oold && obj_surface->psb_surface->in_loop_buf) { psb_surface_p psb_surface = obj_surface->psb_surface; psb_buffer_destroy(psb_surface->in_loop_buf); free(psb_surface->in_loop_buf); psb_surface->in_loop_buf = NULL; } obj_context->is_oold = driver_data->is_oold; drv_debug_msg(VIDEO_DEBUG_GENERAL, "---BeginPicture 0x%08x for frame %d --\n", render_target, obj_context->frame_count); psb__trace_message("------Trace frame %d------\n", obj_context->frame_count); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_RenderPicture( VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_context_p obj_context; object_buffer_p *buffer_list; int i; obj_context = CONTEXT(context); CHECK_CONTEXT(obj_context); CHECK_INVALID_PARAM(num_buffers <= 0); /* Don't crash on NULL pointers */ CHECK_BUFFER(buffers); /* Must be within BeginPicture / EndPicture */ ASSERT(obj_context->current_render_target != NULL); if (num_buffers > obj_context->num_buffers) { free(obj_context->buffer_list); obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * num_buffers); if (obj_context->buffer_list == NULL) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; obj_context->num_buffers = 0; } obj_context->num_buffers = num_buffers; } buffer_list = obj_context->buffer_list; if (VA_STATUS_SUCCESS == vaStatus) { /* Lookup buffer references */ for (i = 0; i < num_buffers; i++) { object_buffer_p obj_buffer = BUFFER(buffers[i]); CHECK_BUFFER(obj_buffer); buffer_list[i] = obj_buffer; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Render buffer %08x type %s\n", obj_buffer->base.id, buffer_type_to_string(obj_buffer->type)); } } if (VA_STATUS_SUCCESS == vaStatus) { vaStatus = obj_context->format_vtable->renderPicture(obj_context, buffer_list, num_buffers); } if (buffer_list) { /* Release buffers */ for (i = 0; i < num_buffers; i++) { if (buffer_list[i]) { psb__suspend_buffer(driver_data, buffer_list[i]); } } } DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_EndPicture( VADriverContextP ctx, VAContextID context ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus; object_context_p obj_context; obj_context = CONTEXT(context); CHECK_CONTEXT(obj_context); vaStatus = obj_context->format_vtable->endPicture(obj_context); drv_debug_msg(VIDEO_DEBUG_GENERAL, "---EndPicture for frame %d --\n", obj_context->frame_count); obj_context->current_render_target = NULL; obj_context->frame_count++; psb__trace_message("FrameCount = %03d\n", obj_context->frame_count); drv_debug_msg(VIDEO_DEBUG_GENERAL, "FrameCount = %03d\n", obj_context->frame_count); psb__trace_message(NULL); //psb_SyncSurface(ctx, obj_context->current_render_surface_id); DEBUG_FUNC_EXIT return vaStatus; } static void psb__surface_usage( psb_driver_data_p driver_data, object_surface_p obj_surface, int *decode, int *encode, int *rc_enable, int *proc ) { object_context_p obj_context; object_config_p obj_config; VAEntrypoint tmp; unsigned int eRCmode; int i; *decode = 0; *encode = 0; *rc_enable = 0; *proc = 0; obj_context = CONTEXT(obj_surface->context_id); if (NULL == obj_context) /* not associate with a context */ return; obj_config = CONFIG(obj_context->config_id); if (NULL == obj_config) /* not have a validate context */ return; tmp = obj_config->entrypoint; *encode = (tmp == VAEntrypointEncSlice) || (tmp == VAEntrypointEncPicture); *decode = (VAEntrypointVLD <= tmp) && (tmp <= VAEntrypointDeblocking); #ifdef PSBVIDEO_MRFL_VPP *proc = (VAEntrypointVideoProc == tmp); #endif if (*encode) { for (i = 0; i < obj_config->attrib_count; i++) { if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) break; } if (i >= obj_config->attrib_count) eRCmode = VA_RC_NONE; else eRCmode = obj_config->attrib_list[i].value; if (eRCmode == VA_RC_NONE) *rc_enable = 0; else *rc_enable = 1; } } VAStatus psb_SyncSurface( VADriverContextP ctx, VASurfaceID render_target ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface; int decode = 0, encode = 0, rc_enable = 0, proc = 0; object_context_p obj_context = NULL; object_config_p obj_config = NULL; drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_SyncSurface: 0x%08x\n", render_target); obj_surface = SURFACE(render_target); CHECK_SURFACE(obj_surface); obj_context = CONTEXT(obj_surface->context_id); if (obj_context) { obj_config = CONFIG(obj_context->config_id); } /* The cur_displaying_surface indicates the surface being displayed by overlay. * The diaplay_timestamp records the time point of put surface, which would * be set to zero while using texture blit.*/ /* don't use mutex here for performance concern... */ //pthread_mutex_lock(&output->output_mutex); if (render_target == driver_data->cur_displaying_surface) vaStatus = VA_STATUS_ERROR_SURFACE_IN_DISPLAYING; else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface) /* use overlay */ && (render_target == driver_data->last_displaying_surface)) { /* It's the last displaying surface*/ object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface); /* The flip operation on current displaying surface could be delayed to * next VBlank and hadn't been finished yet. Then, the last displaying * surface shouldn't be freed, because the hardware may not * complete loading data of it. Any change of the last surface could * have a impect on the scrren.*/ if (NULL != cur_obj_surface) { while ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY) usleep(PSB_MAX_FLIP_DELAY * 1000); } } //pthread_mutex_unlock(&output->output_mutex); if (vaStatus != VA_STATUS_ERROR_SURFACE_IN_DISPLAYING) { #ifdef PSBVIDEO_MRFL_VPP_ROTATE /* For VPP buffer, will sync the rotated buffer */ if (obj_config && obj_config->entrypoint == VAEntrypointVideoProc) { if (GET_SURFACE_INFO_tiling(obj_surface->psb_surface) && (obj_context->msvdx_rotate == VA_ROTATION_90 || obj_context->msvdx_rotate == VA_ROTATION_270) && obj_surface->out_loop_surface) vaStatus = psb_surface_sync(obj_surface->out_loop_surface); else vaStatus = psb_surface_sync(obj_surface->psb_surface); } else #endif vaStatus = psb_surface_sync(obj_surface->psb_surface); } /* report any error of decode for Android */ psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable, &proc); #if 0 if (decode && IS_MRST(driver_data)) { struct drm_lnc_video_getparam_arg arg; uint32_t ret, handle, fw_status = 0; handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf)); arg.key = IMG_VIDEO_DECODE_STATUS; arg.arg = (uint64_t)((unsigned long) & handle); arg.value = (uint64_t)((unsigned long) & fw_status); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret == 0) { if (fw_status != 0) vaStatus = VA_STATUS_ERROR_DECODING_ERROR; } else { drv_debug_msg(VIDEO_DEBUG_GENERAL, "IMG_VIDEO_DECODE_STATUS ioctl return failed.\n"); vaStatus = VA_STATUS_ERROR_UNKNOWN; } } else if (proc && IS_MRFL(driver_data)) { /* FIXME: does it need a new surface sync mechanism for FRC? */ } #endif if (proc && IS_MRFL(driver_data)) { /* FIXME: does it need a new surface sync mechanism for FRC? */ } //psb__dump_NV_buffers(obj_surface->psb_surface, 0, 0, obj_surface->width, obj_surface->height); //psb__dump_NV_buffers(obj_surface->psb_surface_rotate, 0, 0, obj_surface->height, ((obj_surface->width + 0x1f) & (~0x1f))); if (obj_surface->scaling_surface) psb__dump_NV12_buffers(obj_surface->scaling_surface, 0, 0, obj_surface->width_s, obj_surface->height_s); DEBUG_FAILURE; DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_QuerySurfaceStatus( VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status /* out */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface; VASurfaceStatus surface_status; int frame_skip = 0, encode = 0, decode = 0, rc_enable = 0, proc = 0; object_context_p obj_context = NULL; obj_surface = SURFACE(render_target); CHECK_SURFACE(obj_surface); CHECK_INVALID_PARAM(status == NULL); psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable, &proc); #ifdef PSBVIDEO_MRFL_VPP_ROTATE /* For VPP 1080P, will query the rotated buffer */ if (proc) { obj_context = CONTEXT(obj_surface->context_id); CHECK_CONTEXT(obj_context); if (GET_SURFACE_INFO_tiling(obj_surface->psb_surface) && (obj_context->msvdx_rotate == VA_ROTATION_90 || obj_context->msvdx_rotate == VA_ROTATION_270) && obj_surface->out_loop_surface) vaStatus = psb_surface_query_status(obj_surface->out_loop_surface, &surface_status); else vaStatus = psb_surface_query_status(obj_surface->psb_surface, &surface_status); } else #endif vaStatus = psb_surface_query_status(obj_surface->psb_surface, &surface_status); /* The cur_displaying_surface indicates the surface being displayed by overlay. * The diaplay_timestamp records the time point of put surface, which would * be set to zero while using texture blit.*/ pthread_mutex_lock(&driver_data->output_mutex); if (render_target == driver_data->cur_displaying_surface) surface_status = VASurfaceDisplaying; else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface) /* use overlay */ && (render_target == driver_data->last_displaying_surface)) { /* It's the last displaying surface*/ object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface); /*The flip operation on current displaying surface could be delayed to * next VBlank and hadn't been finished yet. Then, the last displaying * surface shouldn't be freed, because the hardware may not * complete loading data of it. Any change of the last surface could * have a impect on the scrren.*/ if ((NULL != cur_obj_surface) && ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY)) { surface_status = VASurfaceDisplaying; } } pthread_mutex_unlock(&driver_data->output_mutex); /* try to get frameskip flag for encode */ #ifndef BAYTRAIL if (!decode) { /* The rendering surface may not be associated with any context. So driver should check the frame skip flag even variable encode is 0 */ #ifdef PSBVIDEO_MRFL if (IS_MRFL(driver_data)) tng_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip); else #endif pnw_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip); if (frame_skip == 1) { surface_status = surface_status | VASurfaceSkipped; drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s next frame of 0x%08x is skipped", __FUNCTION__, render_target); } } else #endif if (decode) { #ifdef ANDROID if (obj_surface->psb_surface->buf.handle) { buffer_handle_t handle = obj_surface->psb_surface->buf.handle; int display_status; int err; err = gralloc_getdisplaystatus(handle, &display_status); if (!err) { if (display_status) surface_status = VASurfaceDisplaying; else surface_status = VASurfaceReady; } else { surface_status = VASurfaceReady; } /* if not used by display, then check whether surface used by widi */ if (surface_status == VASurfaceReady && obj_surface->share_info) { if (obj_surface->share_info->renderStatus == 1) { surface_status = VASurfaceDisplaying; } } } #endif } else if (proc) { /* FIXME: does it need a new surface sync mechanism for FRC? */ } *status = surface_status; DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_QuerySurfaceError( VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info /*out*/ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface; uint32_t i; obj_surface = SURFACE(render_target); CHECK_SURFACE(obj_surface); #ifdef PSBVIDEO_MSVDX_EC if (driver_data->ec_enabled == 0) { #else { #endif drv_debug_msg(VIDEO_DEBUG_GENERAL, "error concealment is not supported for this profile.\n"); error_info = NULL; return VA_STATUS_ERROR_UNKNOWN; } if (error_status == VA_STATUS_ERROR_DECODING_ERROR) { drm_psb_msvdx_decode_status_t *decode_status = driver_data->msvdx_decode_status; struct drm_lnc_video_getparam_arg arg; uint32_t ret, handle; handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf)); arg.key = IMG_VIDEO_MB_ERROR; arg.arg = (uint64_t)((unsigned long) & handle); arg.value = (uint64_t)((unsigned long)decode_status); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret != 0) { drv_debug_msg(VIDEO_DEBUG_GENERAL,"return value is %d drmCommandWriteRead\n",ret); return VA_STATUS_ERROR_UNKNOWN; } #ifndef _FOR_FPGA_ if (decode_status->num_region > MAX_MB_ERRORS) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "too much mb errors are reported.\n"); return VA_STATUS_ERROR_UNKNOWN; } i = 0; for (i = 0; i < decode_status->num_region; ++i) { driver_data->surface_mb_error[i].status = 1; driver_data->surface_mb_error[i].start_mb = decode_status->mb_regions[i].start; driver_data->surface_mb_error[i].end_mb = decode_status->mb_regions[i].end; //driver_data->surface_mb_error[i].start_mb = decode_status->start_error_mb_list[i]; //driver_data->surface_mb_error[i].end_mb = decode_status->end_error_mb_list[i]; //driver_data->surface_mb_error[i].decode_error_type = decode_status->slice_missing_or_error[i]; } #endif driver_data->surface_mb_error[i].status = -1; *error_info = driver_data->surface_mb_error; } else { error_info = NULL; return VA_STATUS_ERROR_UNKNOWN; } DEBUG_FUNC_EXIT return vaStatus; } #define PSB_MAX_SURFACE_ATTRIBUTES 16 VAStatus psb_QuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list, unsigned int *num_attribs) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_config_p obj_config; unsigned int i = 0; CHECK_INVALID_PARAM(num_attribs == NULL); if (attrib_list == NULL) { *num_attribs = PSB_MAX_SURFACE_ATTRIBUTES; return VA_STATUS_SUCCESS; } obj_config = CONFIG(config); CHECK_CONFIG(obj_config); VASurfaceAttrib *attribs = NULL; attribs = malloc(PSB_MAX_SURFACE_ATTRIBUTES *sizeof(VASurfaceAttrib)); if (attribs == NULL) return VA_STATUS_ERROR_ALLOCATION_FAILED; attribs[i].type = VASurfaceAttribPixelFormat; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.i = VA_FOURCC('N', 'V', '1', '2'); i++; attribs[i].type = VASurfaceAttribMemoryType; attribs[i].value.type = VAGenericValueTypeInteger; attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; if (obj_config->entrypoint == VAEntrypointEncSlice && obj_config->profile == VAProfileVP8Version0_3) { attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION; } else { attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM | VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC | VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_ION; } i++; attribs[i].type = VASurfaceAttribExternalBufferDescriptor; attribs[i].value.type = VAGenericValueTypePointer; attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; attribs[i].value.value.p = NULL; i++; //modules have speical formats to support if (obj_config->entrypoint == VAEntrypointVLD) { /* decode */ } else if (obj_config->entrypoint == VAEntrypointEncSlice || /* encode */ obj_config->entrypoint == VAEntrypointEncPicture) { #ifdef PSBVIDEO_MFLD if (IS_MFLD(driver_data)) {} #endif #ifdef PSBVIDEO_MRFL if (IS_MRFL(driver_data)) {} #endif #ifdef BAYTRAIL if (IS_BAYTRAIL(driver_data)) {} #endif } else if (obj_config->entrypoint == VAEntrypointVideoProc) { /* vpp */ } if (i > *num_attribs) { *num_attribs = i; if (attribs != NULL) free(attribs); return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; } *num_attribs = i; memcpy(attrib_list, attribs, i * sizeof(*attribs)); free(attribs); DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_LockSurface( VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, /* following are output argument */ unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, unsigned int *buffer_name, void **buffer ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; unsigned char *surface_data; int ret; object_surface_p obj_surface = SURFACE(surface); psb_surface_p psb_surface; CHECK_SURFACE(obj_surface); psb_surface = obj_surface->psb_surface; 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; ret = psb_buffer_map(&psb_surface->buf, &surface_data); if (ret) { *buffer = NULL; vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FAILURE; return vaStatus; } srf_buf_ofs = psb_surface->buf.buffer_ofs; *buffer = surface_data + srf_buf_ofs; } *fourcc = VA_FOURCC_NV12; *luma_stride = psb_surface->stride; *chroma_u_stride = psb_surface->stride; *chroma_v_stride = psb_surface->stride; *luma_offset = 0; *chroma_u_offset = obj_surface->height * psb_surface->stride; *chroma_v_offset = obj_surface->height * psb_surface->stride + 1; DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_UnlockSurface( VADriverContextP ctx, VASurfaceID surface ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface = SURFACE(surface); CHECK_SURFACE(obj_surface); psb_surface_p psb_surface = obj_surface->psb_surface; psb_buffer_unmap(&psb_surface->buf); DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } VAStatus psb_GetEGLClientBufferFromSurface( VADriverContextP ctx, VASurfaceID surface, void **buffer ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface = SURFACE(surface); CHECK_SURFACE(obj_surface); psb_surface_p psb_surface = obj_surface->psb_surface; *buffer = (unsigned char *)psb_surface->bc_buffer; DEBUG_FUNC_EXIT return vaStatus; } VAStatus psb_PutSurfaceBuf( VADriverContextP ctx, VASurfaceID surface, unsigned char __maybe_unused * data, int __maybe_unused * data_len, short __maybe_unused srcx, short __maybe_unused srcy, unsigned short __maybe_unused srcw, unsigned short __maybe_unused srch, short __maybe_unused destx, short __maybe_unused desty, unsigned short __maybe_unused destw, unsigned short __maybe_unused desth, VARectangle __maybe_unused * cliprects, /* client supplied clip list */ unsigned int __maybe_unused number_cliprects, /* number of clip rects in the clip list */ unsigned int __maybe_unused flags /* de-interlacing flags */ ) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA; object_surface_p obj_surface = SURFACE(surface); psb_surface_p psb_surface; obj_surface = SURFACE(surface); if (obj_surface == NULL) return VA_STATUS_ERROR_INVALID_SURFACE; psb_surface = obj_surface->psb_surface; #if 0 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 */); #endif DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } VAStatus psb_SetTimestampForSurface( VADriverContextP ctx, VASurfaceID surface, long long timestamp ) { INIT_DRIVER_DATA; VAStatus vaStatus = VA_STATUS_SUCCESS; object_surface_p obj_surface = SURFACE(surface); obj_surface = SURFACE(surface); CHECK_SURFACE(obj_surface); if (obj_surface->share_info) { obj_surface->share_info->timestamp = timestamp; return VA_STATUS_SUCCESS; } else { return VA_STATUS_ERROR_UNKNOWN; } } int LOCK_HARDWARE(psb_driver_data_p driver_data) { char ret = 0; if (driver_data->dri2 || driver_data->dri_dummy) return 0; pthread_mutex_lock(&driver_data->drm_mutex); DRM_CAS(driver_data->drm_lock, driver_data->drm_context, (DRM_LOCK_HELD | driver_data->drm_context), ret); if (ret) { ret = drmGetLock(driver_data->drm_fd, driver_data->drm_context, 0); /* driver_data->contended_lock=1; */ } return ret; } int UNLOCK_HARDWARE(psb_driver_data_p driver_data) { /* driver_data->contended_lock=0; */ if (driver_data->dri2 || driver_data->dri_dummy) return 0; DRM_UNLOCK(driver_data->drm_fd, driver_data->drm_lock, driver_data->drm_context); pthread_mutex_unlock(&driver_data->drm_mutex); return 0; } static void psb__deinitDRM(VADriverContextP ctx) { INIT_DRIVER_DATA if (driver_data->main_pool) { driver_data->main_pool->takeDown(driver_data->main_pool); driver_data->main_pool = NULL; } if (driver_data->fence_mgr) { wsbmFenceMgrTTMTakedown(driver_data->fence_mgr); driver_data->fence_mgr = NULL; } if (wsbmIsInitialized()) wsbmTakedown(); driver_data->drm_fd = -1; } static VAStatus psb__initDRI(VADriverContextP ctx) { INIT_DRIVER_DATA struct drm_state *drm_state = (struct drm_state *)ctx->drm_state; assert(dri_state); #ifdef _FOR_FPGA_ dri_state->driConnectedFlag = VA_DUMMY; /* ON FPGA machine, psb may co-exist with gfx's drm driver */ dri_state->fd = open("/dev/dri/card1", O_RDWR); if (dri_state->fd < 0) dri_state->fd = open("/dev/dri/card0", O_RDWR); assert(dri_state->fd >= 0); #endif assert(dri_state->driConnectedFlag == VA_DRI2 || dri_state->driConnectedFlag == VA_DUMMY); driver_data->drm_fd = drm_state->fd; driver_data->dri_dummy = 1; driver_data->dri2 = 0; driver_data->ws_priv = NULL; driver_data->bus_id = NULL; return VA_STATUS_SUCCESS; } static VAStatus psb__initTTM(VADriverContextP ctx) { INIT_DRIVER_DATA const char drm_ext[] = "psb_ttm_placement_alphadrop"; union drm_psb_extension_arg arg; struct _WsbmBufferPool *pool; int ret; const char exec_ext[] = "psb_ttm_execbuf_alphadrop"; union drm_psb_extension_arg exec_arg; const char lncvideo_getparam_ext[] = "lnc_video_getparam"; union drm_psb_extension_arg lncvideo_getparam_arg; /* init wsbm * WSBM node is not used in driver, thus can pass NULL Node callback */ ret = wsbmInit(wsbmNullThreadFuncs(), NULL/*psbVNodeFuncs()*/); if (ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed initializing libwsbm.\n"); return VA_STATUS_ERROR_UNKNOWN; } strncpy(arg.extension, drm_ext, sizeof(arg.extension)); /* FIXME: should check dri enabled? * it seems not init dri here at all */ ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &arg, sizeof(arg)); if (ret != 0 || !arg.rep.exists) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\", fd=%d\n", drm_ext, driver_data->drm_fd); drv_debug_msg(VIDEO_DEBUG_ERROR, "found error %s (ret=%d), arg.rep.exists=%d", strerror(errno), ret, arg.rep.exists); driver_data->main_pool = NULL; return VA_STATUS_ERROR_UNKNOWN; } else { pool = wsbmTTMPoolInit(driver_data->drm_fd, arg.rep.driver_ioctl_offset); if (pool == NULL) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get ttm pool\n"); return VA_STATUS_ERROR_UNKNOWN; } driver_data->main_pool = pool; } strncpy(exec_arg.extension, exec_ext, sizeof(exec_arg.extension)); ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &exec_arg, sizeof(exec_arg)); if (ret != 0 || !exec_arg.rep.exists) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\".\n", exec_ext); return FALSE; } driver_data->execIoctlOffset = exec_arg.rep.driver_ioctl_offset; strncpy(lncvideo_getparam_arg.extension, lncvideo_getparam_ext, sizeof(lncvideo_getparam_arg.extension)); ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &lncvideo_getparam_arg, sizeof(lncvideo_getparam_arg)); if (ret != 0 || !lncvideo_getparam_arg.rep.exists) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\".\n", lncvideo_getparam_ext); /* return FALSE; */ /* not reture FALSE, so it still can run */ } driver_data->getParamIoctlOffset = lncvideo_getparam_arg.rep.driver_ioctl_offset; return VA_STATUS_SUCCESS; } static VAStatus psb__initDRM(VADriverContextP ctx) { VAStatus vaStatus; vaStatus = psb__initDRI(ctx); if (vaStatus == VA_STATUS_SUCCESS) return psb__initTTM(ctx); else return vaStatus; } VAStatus psb_Terminate(VADriverContextP ctx) { DEBUG_FUNC_ENTER INIT_DRIVER_DATA object_subpic_p obj_subpic; object_image_p obj_image; object_buffer_p obj_buffer; object_surface_p obj_surface; object_context_p obj_context; object_config_p obj_config; object_heap_iterator iter; drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: begin to tear down\n"); /* Clean up left over contexts */ obj_context = (object_context_p) object_heap_first(&driver_data->context_heap, &iter); while (obj_context) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: contextID %08x still allocated, destroying\n", obj_context->base.id); psb__destroy_context(driver_data, obj_context); obj_context = (object_context_p) object_heap_next(&driver_data->context_heap, &iter); } object_heap_destroy(&driver_data->context_heap); /* Clean up SubpicIDs */ obj_subpic = (object_subpic_p) object_heap_first(&driver_data->subpic_heap, &iter); while (obj_subpic) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: subpictureID %08x still allocated, destroying\n", obj_subpic->base.id); psb__destroy_subpicture(driver_data, obj_subpic); obj_subpic = (object_subpic_p) object_heap_next(&driver_data->subpic_heap, &iter); } object_heap_destroy(&driver_data->subpic_heap); /* Clean up ImageIDs */ obj_image = (object_image_p) object_heap_first(&driver_data->image_heap, &iter); while (obj_image) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: imageID %08x still allocated, destroying\n", obj_image->base.id); psb__destroy_image(driver_data, obj_image); obj_image = (object_image_p) object_heap_next(&driver_data->image_heap, &iter); } object_heap_destroy(&driver_data->image_heap); /* Clean up left over buffers */ obj_buffer = (object_buffer_p) object_heap_first(&driver_data->buffer_heap, &iter); while (obj_buffer) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id); psb__destroy_buffer(driver_data, obj_buffer); obj_buffer = (object_buffer_p) object_heap_next(&driver_data->buffer_heap, &iter); } object_heap_destroy(&driver_data->buffer_heap); /* Clean up left over surfaces */ #if 0 /* Free PVR2D buffer wrapped from the surfaces */ psb_free_surface_pvr2dbuf(driver_data); #endif obj_surface = (object_surface_p) object_heap_first(&driver_data->surface_heap, &iter); while (obj_surface) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: surfaceID %08x still allocated, destroying\n", obj_surface->base.id); psb__destroy_surface(driver_data, obj_surface); obj_surface = (object_surface_p) object_heap_next(&driver_data->surface_heap, &iter); } object_heap_destroy(&driver_data->surface_heap); /* Clean up configIDs */ obj_config = (object_config_p) object_heap_first(&driver_data->config_heap, &iter); while (obj_config) { object_heap_free(&driver_data->config_heap, (object_base_p) obj_config); obj_config = (object_config_p) object_heap_next(&driver_data->config_heap, &iter); } object_heap_destroy(&driver_data->config_heap); if (driver_data->camera_bo) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: clearup camera global BO\n"); psb_buffer_destroy((psb_buffer_p)driver_data->camera_bo); free(driver_data->camera_bo); driver_data->camera_bo = NULL; } if (driver_data->rar_bo) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: clearup RAR global BO\n"); psb_buffer_destroy((psb_buffer_p)driver_data->rar_bo); free(driver_data->rar_bo); driver_data->rar_bo = NULL; } if (driver_data->ws_priv) { drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: tear down output portion\n"); psb_deinitOutput(ctx); driver_data->ws_priv = NULL; } drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: de-initialized DRM\n"); psb__deinitDRM(ctx); if (driver_data->msvdx_decode_status) free(driver_data->msvdx_decode_status); if (driver_data->surface_mb_error) free(driver_data->surface_mb_error); pthread_mutex_destroy(&driver_data->drm_mutex); free(ctx->pDriverData); free(ctx->vtable_egl); free(ctx->vtable_tpi); ctx->pDriverData = NULL; drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: goodbye\n\n"); psb__close_log(); DEBUG_FUNC_EXIT return VA_STATUS_SUCCESS; } EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx) { psb_driver_data_p driver_data; struct VADriverVTableTPI *tpi; struct VADriverVTableEGL *va_egl; int result; if (psb_video_trace_fp) { /* make gdb always stop here */ signal(SIGUSR1, SIG_IGN); kill(getpid(), SIGUSR1); } psb__open_log(); drv_debug_msg(VIDEO_DEBUG_INIT, "vaInitilize: start the journey\n"); ctx->version_major = 0; ctx->version_minor = 31; ctx->max_profiles = PSB_MAX_PROFILES; ctx->max_entrypoints = PSB_MAX_ENTRYPOINTS; ctx->max_attributes = PSB_MAX_CONFIG_ATTRIBUTES; ctx->max_image_formats = PSB_MAX_IMAGE_FORMATS; ctx->max_subpic_formats = PSB_MAX_SUBPIC_FORMATS; ctx->max_display_attributes = PSB_MAX_DISPLAY_ATTRIBUTES; ctx->vtable->vaTerminate = psb_Terminate; ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints; ctx->vtable->vaTerminate = psb_Terminate; ctx->vtable->vaQueryConfigProfiles = psb_QueryConfigProfiles; ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints; ctx->vtable->vaQueryConfigAttributes = psb_QueryConfigAttributes; ctx->vtable->vaCreateConfig = psb_CreateConfig; ctx->vtable->vaDestroyConfig = psb_DestroyConfig; ctx->vtable->vaGetConfigAttributes = psb_GetConfigAttributes; ctx->vtable->vaCreateSurfaces2 = psb_CreateSurfaces2; ctx->vtable->vaCreateSurfaces = psb_CreateSurfaces; ctx->vtable->vaGetSurfaceAttributes = psb_GetSurfaceAttributes; ctx->vtable->vaDestroySurfaces = psb_DestroySurfaces; ctx->vtable->vaCreateContext = psb_CreateContext; ctx->vtable->vaDestroyContext = psb_DestroyContext; ctx->vtable->vaCreateBuffer = psb_CreateBuffer; ctx->vtable->vaBufferSetNumElements = psb_BufferSetNumElements; ctx->vtable->vaMapBuffer = psb_MapBuffer; ctx->vtable->vaUnmapBuffer = psb_UnmapBuffer; ctx->vtable->vaDestroyBuffer = psb_DestroyBuffer; ctx->vtable->vaBeginPicture = psb_BeginPicture; ctx->vtable->vaRenderPicture = psb_RenderPicture; ctx->vtable->vaEndPicture = psb_EndPicture; ctx->vtable->vaSyncSurface = psb_SyncSurface; ctx->vtable->vaQuerySurfaceStatus = psb_QuerySurfaceStatus; ctx->vtable->vaQuerySurfaceError = psb_QuerySurfaceError; ctx->vtable->vaPutSurface = psb_PutSurface; ctx->vtable->vaQueryImageFormats = psb_QueryImageFormats; ctx->vtable->vaCreateImage = psb_CreateImage; ctx->vtable->vaDeriveImage = psb_DeriveImage; ctx->vtable->vaDestroyImage = psb_DestroyImage; ctx->vtable->vaSetImagePalette = psb_SetImagePalette; ctx->vtable->vaGetImage = psb_GetImage; ctx->vtable->vaPutImage = psb_PutImage; ctx->vtable->vaQuerySubpictureFormats = psb_QuerySubpictureFormats; ctx->vtable->vaCreateSubpicture = psb_CreateSubpicture; ctx->vtable->vaDestroySubpicture = psb_DestroySubpicture; ctx->vtable->vaSetSubpictureImage = psb_SetSubpictureImage; ctx->vtable->vaSetSubpictureChromakey = psb_SetSubpictureChromakey; ctx->vtable->vaSetSubpictureGlobalAlpha = psb_SetSubpictureGlobalAlpha; ctx->vtable->vaAssociateSubpicture = psb_AssociateSubpicture; ctx->vtable->vaDeassociateSubpicture = psb_DeassociateSubpicture; ctx->vtable->vaQueryDisplayAttributes = psb_QueryDisplayAttributes; ctx->vtable->vaGetDisplayAttributes = psb_GetDisplayAttributes; ctx->vtable->vaSetDisplayAttributes = psb_SetDisplayAttributes; ctx->vtable->vaQuerySurfaceAttributes = psb_QuerySurfaceAttributes; ctx->vtable->vaBufferInfo = psb_BufferInfo; ctx->vtable->vaLockSurface = psb_LockSurface; ctx->vtable->vaUnlockSurface = psb_UnlockSurface; #ifdef PSBVIDEO_MRFL_VPP ctx->vtable_vpp->vaQueryVideoProcFilters = vsp_QueryVideoProcFilters; ctx->vtable_vpp->vaQueryVideoProcFilterCaps = vsp_QueryVideoProcFilterCaps; ctx->vtable_vpp->vaQueryVideoProcPipelineCaps = vsp_QueryVideoProcPipelineCaps; #endif #ifdef PSBVIDEO_MFLD ctx->vtable_vpp->vaQueryVideoProcFilters = ved_QueryVideoProcFilters; ctx->vtable_vpp->vaQueryVideoProcFilterCaps = ved_QueryVideoProcFilterCaps; ctx->vtable_vpp->vaQueryVideoProcPipelineCaps = ved_QueryVideoProcPipelineCaps; #endif ctx->vtable_tpi = calloc(1, sizeof(struct VADriverVTableTPI)); if (NULL == ctx->vtable_tpi) return VA_STATUS_ERROR_ALLOCATION_FAILED; tpi = (struct VADriverVTableTPI *)ctx->vtable_tpi; tpi->vaCreateSurfacesWithAttribute = psb_CreateSurfacesWithAttribute; tpi->vaPutSurfaceBuf = psb_PutSurfaceBuf; tpi->vaSetTimestampForSurface = psb_SetTimestampForSurface; ctx->vtable_egl = calloc(1, sizeof(struct VADriverVTableEGL)); if (NULL == ctx->vtable_egl) return VA_STATUS_ERROR_ALLOCATION_FAILED; va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl; va_egl->vaGetEGLClientBufferFromSurface = psb_GetEGLClientBufferFromSurface; driver_data = (psb_driver_data_p) calloc(1, sizeof(*driver_data)); ctx->pDriverData = (unsigned char *) driver_data; if (NULL == driver_data) { if (ctx->vtable_tpi) free(ctx->vtable_tpi); if (ctx->vtable_egl) free(ctx->vtable_egl); return VA_STATUS_ERROR_ALLOCATION_FAILED; } if (VA_STATUS_SUCCESS != psb__initDRM(ctx)) { free(ctx->pDriverData); ctx->pDriverData = NULL; return VA_STATUS_ERROR_UNKNOWN; } pthread_mutex_init(&driver_data->drm_mutex, NULL); /* * To read PBO.MSR.CCF Mode and Status Register C-Spec -p112 */ #define PCI_PORT5_REG80_VIDEO_SD_DISABLE 0x0008 #define PCI_PORT5_REG80_VIDEO_HD_DISABLE 0x0010 #if 0 struct drm_psb_hw_info hw_info; do { result = drmCommandRead(driver_data->drm_fd, DRM_PSB_HW_INFO, &hw_info, sizeof(hw_info)); } while (result == EAGAIN); if (result != 0) { psb__deinitDRM(ctx); free(ctx->pDriverData); ctx->pDriverData = NULL; return VA_STATUS_ERROR_UNKNOWN; } driver_data->video_sd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_SD_DISABLE); driver_data->video_hd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_HD_DISABLE); drv_debug_msg(VIDEO_DEBUG_GENERAL, "hw_info: rev_id = %08x capabilities = %08x\n", hw_info.rev_id, hw_info.caps); drv_debug_msg(VIDEO_DEBUG_GENERAL, "hw_info: video_sd_disable=%d,video_hd_disable=%d\n", driver_data->video_sd_disabled, driver_data->video_hd_disabled); if (driver_data->video_sd_disabled != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "MRST: hw_info shows video_sd_disable is true,fix it manually\n"); driver_data->video_sd_disabled = 0; } if (driver_data->video_hd_disabled != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "MRST: hw_info shows video_hd_disable is true,fix it manually\n"); driver_data->video_hd_disabled = 0; } #endif if (0 != psb_get_device_info(ctx)) { drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: failed to get video device info\n"); driver_data->encode_supported = 1; driver_data->decode_supported = 1; driver_data->hd_encode_supported = 1; driver_data->hd_decode_supported = 1; } #if 0 psb_init_surface_pvr2dbuf(driver_data); #endif if (VA_STATUS_SUCCESS != psb_initOutput(ctx)) { pthread_mutex_destroy(&driver_data->drm_mutex); psb__deinitDRM(ctx); free(ctx->pDriverData); ctx->pDriverData = NULL; return VA_STATUS_ERROR_UNKNOWN; } driver_data->msvdx_context_base = (((unsigned int) getpid()) & 0xffff) << 16; #ifdef PSBVIDEO_MRFL if (IS_MRFL(driver_data)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield topazhp encoder\n"); driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &tng_H264ES_vtable; driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &tng_H264ES_vtable; driver_data->profile2Format[VAProfileH264High][VAEntrypointEncSlice] = &tng_H264ES_vtable; driver_data->profile2Format[VAProfileH264StereoHigh][VAEntrypointEncSlice] = &tng_H264ES_vtable; driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &tng_H263ES_vtable; driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointEncPicture] = &tng_JPEGES_vtable; driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &tng_MPEG4ES_vtable; driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &tng_MPEG4ES_vtable; driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointEncSlice] = &tng_H264ES_vtable; } #endif #ifdef PSBVIDEO_MRFL_VPP if (IS_MRFL(driver_data)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield vsp vpp\n"); driver_data->vpp_profile = &vsp_VPP_vtable; driver_data->profile2Format[VAProfileVP8Version0_3][VAEntrypointEncSlice] = &vsp_VP8_vtable; } #endif #ifdef PSBVIDEO_VXD392 if (IS_MRFL(driver_data) || IS_BAYTRAIL(driver_data)) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield VXD392 decoder\n"); driver_data->profile2Format[VAProfileVP8Version0_3][VAEntrypointVLD] = &tng_VP8_vtable; driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointVLD] = &tng_JPEG_vtable; driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileMPEG2Simple][VAEntrypointVLD] = &pnw_MPEG2_vtable; driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &pnw_MPEG2_vtable; driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &pnw_H264_vtable; } #endif #ifdef PSBVIDEO_MRFL_VPP if (IS_MRFL(driver_data)) { if (*((unsigned int *)ctx->native_dpy) == 0x56454450 /* VEDP */) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield ved vpp\n"); driver_data->vpp_profile = &tng_yuv_processor_vtable; ctx->vtable_vpp->vaQueryVideoProcFilters = ved_QueryVideoProcFilters; ctx->vtable_vpp->vaQueryVideoProcFilterCaps = ved_QueryVideoProcFilterCaps; ctx->vtable_vpp->vaQueryVideoProcPipelineCaps = ved_QueryVideoProcPipelineCaps; driver_data->ved_vpp = 1; } } #endif #ifdef PSBVIDEO_MFLD if (IS_MFLD(driver_data)) { driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &pnw_H263ES_vtable; driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &pnw_H264ES_vtable; driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &pnw_H264ES_vtable; driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable; driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable; driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointEncPicture] = &pnw_JPEG_vtable; driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &pnw_MPEG2_vtable; driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileMPEG2Simple][VAEntrypointVLD] = &pnw_MPEG2_vtable; driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &pnw_MPEG2_vtable; driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointVLD] = &pnw_MPEG4_vtable; driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &pnw_VC1_vtable; driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &pnw_H264_vtable; driver_data->vpp_profile = &tng_yuv_processor_vtable; driver_data->ved_vpp = 1; } #endif result = object_heap_init(&driver_data->config_heap, sizeof(struct object_config_s), CONFIG_ID_OFFSET); ASSERT(result == 0); result = object_heap_init(&driver_data->context_heap, sizeof(struct object_context_s), CONTEXT_ID_OFFSET); ASSERT(result == 0); result = object_heap_init(&driver_data->surface_heap, sizeof(struct object_surface_s), SURFACE_ID_OFFSET); ASSERT(result == 0); result = object_heap_init(&driver_data->buffer_heap, sizeof(struct object_buffer_s), BUFFER_ID_OFFSET); ASSERT(result == 0); result = object_heap_init(&driver_data->image_heap, sizeof(struct object_image_s), IMAGE_ID_OFFSET); ASSERT(result == 0); result = object_heap_init(&driver_data->subpic_heap, sizeof(struct object_subpic_s), SUBPIC_ID_OFFSET); ASSERT(result == 0); driver_data->cur_displaying_surface = VA_INVALID_SURFACE; driver_data->last_displaying_surface = VA_INVALID_SURFACE; driver_data->clear_color = 0; driver_data->blend_color = 0; driver_data->blend_mode = 0; driver_data->overlay_auto_paint_color_key = 0; if (IS_BAYTRAIL(driver_data)) ctx->str_vendor = PSB_STR_VENDOR_BAYTRAIL; if (IS_MRFL(driver_data)) ctx->str_vendor = PSB_STR_VENDOR_MRFL; else if (IS_MFLD(driver_data)) { if (IS_LEXINGTON(driver_data)) ctx->str_vendor = PSB_STR_VENDOR_LEXINGTON; else ctx->str_vendor = PSB_STR_VENDOR_MFLD; } else ctx->str_vendor = PSB_STR_VENDOR_MRST; driver_data->msvdx_decode_status = calloc(1, sizeof(drm_psb_msvdx_decode_status_t)); if (NULL == driver_data->msvdx_decode_status) { pthread_mutex_destroy(&driver_data->drm_mutex); return VA_STATUS_ERROR_ALLOCATION_FAILED; } driver_data->surface_mb_error = calloc(MAX_MB_ERRORS, sizeof(VASurfaceDecodeMBErrors)); if (NULL == driver_data->surface_mb_error) { pthread_mutex_destroy(&driver_data->drm_mutex); return VA_STATUS_ERROR_ALLOCATION_FAILED; } drv_debug_msg(VIDEO_DEBUG_INIT, "vaInitilize: succeeded!\n\n"); #ifdef ANDROID #ifndef PSBVIDEO_VXD392 gralloc_init(); #endif #endif return VA_STATUS_SUCCESS; } EXPORT VAStatus __vaDriverInit_0_32(VADriverContextP ctx) { return __vaDriverInit_0_31(ctx); } static int psb_get_device_info(VADriverContextP ctx) { INIT_DRIVER_DATA; struct drm_lnc_video_getparam_arg arg; unsigned long device_info; int ret = 0; unsigned long video_capability; unsigned long pci_device; driver_data->dev_id = 0x4100; /* by default MRST */ arg.key = LNC_VIDEO_DEVICE_INFO; arg.value = (uint64_t)((unsigned long) & device_info); ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, &arg, sizeof(arg)); if (ret != 0) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get video device info\n"); return ret; } pci_device = (device_info >> 16) & 0xffff; video_capability = device_info & 0xffff; driver_data->dev_id = pci_device; drv_debug_msg(VIDEO_DEBUG_INIT, "Retrieve Device ID 0x%08x\n", driver_data->dev_id); if (IS_MFLD(driver_data) || IS_MRFL(driver_data)) driver_data->encode_supported = 1; else /* 0x4101 or other device hasn't encode support */ driver_data->encode_supported = 0; driver_data->decode_supported = 1; driver_data->hd_decode_supported = 1; driver_data->hd_encode_supported = 1; return ret; }