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