You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
28 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2020. All rights reserved.
* Description: Support private hwgraphics hidl interface
* Author: Hisilicon
* Created: 2016.11.29
*/
#define LOG_TAG "HwGraphicsIapiComImpl"
#include "dft/HwgraphicsDft.h"
#include "HwGraphicsIapiComImpl.h"
#include <cinttypes>
#include <sync/sync.h>
#include <utils/Log.h>
#include <utils/Timers.h>
#include <cutils/properties.h>
#include <securec.h>
#include <vendor/huanglong/hardware/hwgraphics/1.0/types.h>
#include <uapi_win.h>
#include <uapi_pdm.h>
#include <mpi_memory_ext.h>
namespace android {
using namespace dft;
HwGraphicsIapiComImpl::HwGraphicsIapiComImpl()
: m_debugCapture(false),
m_debugCast(false),
m_enableTdeCopy(true),
tdeFormat(UAPI_GFX2D_FMT_ABGR8888)
{
}
HwGraphicsIapiComImpl::~HwGraphicsIapiComImpl()
{
}
int HwGraphicsIapiComImpl::InitVoModule()
{
td_s32 ret = uapi_win_init();
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("UAPI_VO_Init err: %#x", ret));
return ret;
}
int HwGraphicsIapiComImpl::CloseVoWindow(uint32_t window)
{
td_s32 ret = 0;
uapi_win_source_info srcInfo;
ret = uapi_win_get_source(window, &srcInfo);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("uapi_win_get_source err: %#x", ret));
bool isDetach = (srcInfo.src == TD_INVALID_HANDLE);
if (isDetach) {
ret = uapi_win_set_enable(window, TD_FALSE);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("uapi_win_set_enable err: %#x", ret));
ret = uapi_win_destroy(window);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("uapi_win_destroy err: %#x", ret));
} else {
ALOGD("window is not detached srcInfo.src:%#x", srcInfo.src);
}
return ret;
}
int HwGraphicsIapiComImpl::DeinitVoModule()
{
td_s32 ret = uapi_win_deinit();
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("uapi_win_deinit err: %#x", ret));
return ret;
}
int HwGraphicsIapiComImpl::AcquireSnapshot(CaptureInfoData captureInfo, uapi_disp_snap_attr &ptSnapAttr,
uapi_video_frame_info &ptCapPicture)
{
td_s32 ret = uapi_disp_get_virtual_screen(UAPI_DISPLAY0, &ptSnapAttr.width, &ptSnapAttr.height);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("call uapi_disp_get_virtual_screen failed, ret=%#x", ret));
ret = uapi_disp_set_snapshot_attr(UAPI_DISPLAY0, &ptSnapAttr);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("uapi_disp_set_snapshot_attr fail %d", ret));
ret = uapi_disp_acquire_snapshot(UAPI_DISPLAY0, &ptCapPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("call uapi_disp_acquire_snapshot failed, ret=%#x", ret));
if (ptCapPicture.secure_frame) {
ALOGE("current frame is secure, tde not support");
ret = uapi_disp_release_snapshot(UAPI_DISPLAY0, &ptCapPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("snapshot_release failed ret = %#x", ret));
return ret;
}
ret = ConvertSnapShotByTDE(captureInfo, ptCapPicture);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("call hwcSetTdeConvert failed ret = %#x", ret));
ret = uapi_disp_release_snapshot(UAPI_DISPLAY0, &ptCapPicture);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("snapshot_release failed ret = %#x", ret));
return ret;
}
int HwGraphicsIapiComImpl::CaptureWinPicture(CaptureInfoData captureInfo, uapi_video_frame_info &ptCapPicture)
{
// If there are multiple windows, the main window is captured by default for display0.
// Only the video is captured.
uapi_win_handle_info winInfo = {};
td_s32 ret = uapi_win_get_handle_info(UAPI_DISPLAY0, &winInfo);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("call uapi_win_get_handle_info failed ret = 0x%x", ret));
ret = uapi_win_capture_picture(winInfo.main_handle, &ptCapPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("call uapi_win_capture_picture failed, ensure that the current window exists, ret = %#x", ret));
if (ptCapPicture.secure_frame) {
ALOGE("current frame is secure, tde not support");
ret = uapi_win_capture_picture_release(winInfo.main_handle, &ptCapPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("capture_picture_release failed ret = %#x", ret));
return ret;
}
captureInfo.captureRect.right = static_cast<int32_t> (ptCapPicture.decode_width);
captureInfo.captureRect.bottom = static_cast<int32_t> (ptCapPicture.decode_height);
ret = ConvertSnapShotByTDE(captureInfo, ptCapPicture);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("call hwcSetTdeConvert failed ret = %#x", ret));
ret = uapi_win_capture_picture_release(winInfo.main_handle, &ptCapPicture);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("capture_picture_release failed ret = %#x", ret));
return ret;
}
int HwGraphicsIapiComImpl::InitTdeData(uapi_gfx2d_list &surfaceList, uapi_gfx2d_surface &srcSurface,
uapi_gfx2d_surface &dstSurface, uapi_gfx2d_attr &attr) const
{
errno_t eok = memset_s(&surfaceList, sizeof(uapi_gfx2d_list), 0x0, sizeof(uapi_gfx2d_list));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("InitTdeData surfaceList memset failed"));
eok = memset_s(&dstSurface, sizeof(uapi_gfx2d_surface), 0x0, sizeof(uapi_gfx2d_surface));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("InitTdeData dstSurface memset failed"));
eok = memset_s(&srcSurface, sizeof(uapi_gfx2d_surface), 0x0, sizeof(uapi_gfx2d_surface));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("InitTdeData srcSurface memset failed"));
eok = memset_s(&attr, sizeof(attr), 0x0, sizeof(uapi_gfx2d_attr));
HWGRAPHIC_CHK_RETURN(eok != EOK, TD_FAILURE, ALOGE("InitTdeData attr memset failed"));
return TD_SUCCESS;
}
void HwGraphicsIapiComImpl::ConvertFormatToTDE(int andrFormat, uapi_gfx2d_color_fmt &gfx2dFormat) const
{
switch (andrFormat) {
case HAL_PIXEL_FORMAT_RGBA_8888:
gfx2dFormat = UAPI_GFX2D_FMT_ABGR8888;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
gfx2dFormat = UAPI_GFX2D_FMT_ABGR8888;
break;
case HAL_PIXEL_FORMAT_RGB_888:
gfx2dFormat = UAPI_GFX2D_FMT_BGR888;
break;
case HAL_PIXEL_FORMAT_RGB_565:
gfx2dFormat = UAPI_GFX2D_FMT_BGR565;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
gfx2dFormat = UAPI_GFX2D_FMT_ABGR8888;
break;
default:
ALOGE("AndrFormatToTDEFormat unsupport format:%d", andrFormat);
gfx2dFormat = UAPI_GFX2D_FMT_MAX;
}
}
void HwGraphicsIapiComImpl::ConvertFormatFromVideoToTDE(uapi_gfx2d_color_fmt &srcSurfaceFormat,
const uapi_video_pixel_format &captureFormat) const
{
switch (captureFormat) {
case UAPI_FORMAT_YUV_SEMIPLANAR_420_VU:
srcSurfaceFormat = UAPI_GFX2D_FMT_SEMIPLANAR420UV;
break;
case UAPI_FORMAT_RGB888:
srcSurfaceFormat = UAPI_GFX2D_FMT_BGR888;
break;
default:
srcSurfaceFormat = UAPI_GFX2D_FMT_MAX;
ALOGE("ConvertFormatFromVideoToTDE unsupport format:%d", srcSurfaceFormat);
break;
}
}
void HwGraphicsIapiComImpl::PrepareTdeDstSurfaceData(uapi_gfx2d_surface &dstSurface, const CaptureInfoData &data)
{
if (data.captureHandle == nullptr) {
ALOGE("captureHandle is null");
return;
}
ConvertFormatToTDE(data.captureHandle->format, dstSurface.format);
// four bytes per pixle
if (data.captureHandle->bytes_stride > max16KMul4 || data.captureHandle->height > max16K) {
ALOGI("CaptureInfoData data out of range");
return;
}
dstSurface.width = data.captureHandle->width;
dstSurface.height = data.captureHandle->height;
dstSurface.stride[0] = data.captureHandle->bytes_stride;
dstSurface.mem_handle[0].mem_handle = data.captureHandle->fd;
dstSurface.mem_handle[0].addr_offset = data.captureHandle->offset;
dstSurface.out_rect.x = 0;
dstSurface.out_rect.y = 0;
dstSurface.out_rect.width = data.captureHandle->width;
dstSurface.out_rect.height = data.captureHandle->height;
dstSurface.size[0] = data.captureHandle->bytes_stride * data.captureHandle->height;
dstSurface.alpha_ext.alpha0 = 0;
dstSurface.alpha_ext.alpha1 = 0xff;
dstSurface.is_alpha_ext_1555 = TD_TRUE;
dstSurface.is_alpha_max_255 = TD_TRUE;
}
void HwGraphicsIapiComImpl::PrepareTdeSourceSurfaceData(uapi_gfx2d_surface &srcSurface,
const uapi_video_frame_info &capPicture, HwRect rect)
{
ConvertFormatFromVideoToTDE(srcSurface.format, capPicture.video_format);
srcSurface.width = capPicture.decode_width;
srcSurface.height = capPicture.decode_height;
srcSurface.stride[0] = capPicture.frame_addr[UAPI_MULTI_VIEW_0].stride_y;
srcSurface.stride[1] = capPicture.frame_addr[UAPI_MULTI_VIEW_0].stride_c;
if (srcSurface.height > uMax16K || srcSurface.stride[0] > uMax16KMul4 ||
srcSurface.stride[1] > uMax16KMul4) {
ALOGI("Surface data out of range");
return;
}
srcSurface.size[0] = srcSurface.stride[0] * srcSurface.height;
srcSurface.size[1] = srcSurface.stride[1] * srcSurface.height;
srcSurface.alpha_ext.alpha0 = 0;
srcSurface.alpha_ext.alpha1 = 0xff;
srcSurface.is_alpha_ext_1555 = TD_TRUE;
srcSurface.is_alpha_max_255 = TD_TRUE;
if (rect.right < rect.left || rect.bottom < rect.top) {
ALOGI("HwRect data error");
return;
}
srcSurface.in_rect.x = rect.left;
srcSurface.in_rect.y = rect.top;
srcSurface.in_rect.width = (unsigned int)(rect.right - rect.left);
srcSurface.in_rect.height = (unsigned int)(rect.bottom - rect.top);
srcSurface.mem_handle[0].mem_handle = capPicture.frame_addr[UAPI_MULTI_VIEW_0].start_addr;
srcSurface.mem_handle[1].mem_handle = capPicture.frame_addr[UAPI_MULTI_VIEW_0].start_addr;
srcSurface.mem_handle[0].addr_offset = capPicture.frame_addr[UAPI_MULTI_VIEW_0].y_offset;
srcSurface.mem_handle[1].addr_offset = capPicture.frame_addr[UAPI_MULTI_VIEW_0].c_offset;
}
void CloseHandler(td_handle handle)
{
if (handle >= 0) {
uapi_gfx2d_destroy(handle);
}
uapi_gfx2d_close(UAPI_GFX2D_DEV_ID_0);
}
int HwGraphicsIapiComImpl::ConvertSnapShotByTDE(const CaptureInfoData &outCaptureInfo,
const uapi_video_frame_info &pstCapPicture)
{
uapi_gfx2d_list surfaceList;
td_s32 timeOut = 50;
uapi_gfx2d_surface dstSurface;
uapi_gfx2d_surface srcSurface;
uapi_gfx2d_attr attr;
int initOk = InitTdeData(surfaceList, srcSurface, dstSurface, attr);
HWGRAPHIC_CHK_RETURN((initOk == TD_FAILURE), TD_FAILURE);
PrepareTdeDstSurfaceData(dstSurface, outCaptureInfo);
HWGRAPHIC_CHK_RETURN((dstSurface.format == UAPI_GFX2D_FMT_MAX), TD_FAILURE);
PrepareTdeSourceSurfaceData(srcSurface, pstCapPicture, outCaptureInfo.captureRect);
HWGRAPHIC_CHK_RETURN((srcSurface.format == UAPI_GFX2D_FMT_MAX), TD_FAILURE);
attr.resize_attr.resize_enable = TD_TRUE;
dstSurface.attr = &attr;
surfaceList.src_surfaces = &srcSurface;
surfaceList.dst_surface = &dstSurface;
surfaceList.src_surface_cnt = 1;
surfaceList.ops_mode = UAPI_GFX2D_OPS_BIT_BLIT;
surfaceList.src_surfaces[0].attr = &attr;
td_s32 ret = uapi_gfx2d_open(UAPI_GFX2D_DEV_ID_0);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), ret, ALOGD("setTdeConvert uapi_gfx2d_open :ret = %#x ", ret));
td_handle handle = uapi_gfx2d_create(UAPI_GFX2D_DEV_ID_0);
if (handle < 0) {
ALOGE("uapi_gfx2d_create failed");
CloseHandler(handle);
return ret;
}
ret = uapi_gfx2d_bitblit(handle, &surfaceList);
FaultInfo mFaultInfo = {"uapi_gfx2d_bitblit"};
HwgraphicsDft::GetInstance()->ReportFaultIfNecessary(ret != TD_SUCCESS, SCREENCAP_FAIL, mFaultInfo);
if (ret != TD_SUCCESS) {
ALOGE("uapi_gfx2d_bitblit failed, ret = 0x%x", ret);
CloseHandler(handle);
return ret;
}
ret = uapi_gfx2d_submit(handle, TD_TRUE, timeOut);
mFaultInfo.funName = "uapi_gfx2d_submit";
HwgraphicsDft::GetInstance()->ReportFaultIfNecessary(ret != TD_SUCCESS, SCREENCAP_FAIL, mFaultInfo);
if (ret != TD_SUCCESS) {
ALOGE("uapi_gfx2d_submit failed, ret = 0x%x", ret);
CloseHandler(handle);
return ret;
}
return ret;
}
int HwGraphicsIapiComImpl::CaptureScreenByVDP(CaptureInfoData captureInfo)
{
uapi_video_frame_info capPicture;
uapi_disp_snap_attr snapAttr;
struct timeval start;
struct timeval end;
errno_t eok = memset_s(&start, sizeof(timeval), 0x0, sizeof(timeval));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("screencapVideo start time memset failed"));
eok = memset_s(&end, sizeof(timeval), 0x0, sizeof(timeval));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("screencapVideo end time memset failed"));
m_debugCapture = property_get_bool("vendor.gfx.debug.capture", false);
if (m_debugCapture) {
gettimeofday(&start, nullptr);
}
eok = memset_s(&capPicture, sizeof(uapi_video_frame_info), 0x0, sizeof(uapi_video_frame_info));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("capPicture memset failed"));
eok = memset_s(&snapAttr, sizeof(uapi_disp_snap_attr), 0x0, sizeof(uapi_disp_snap_attr));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("snapAttr memset failed"));
if (m_debugCapture) {
ALOGD("captureInfoRect [Width x Height = %d x %d]", captureInfo.captureHandle->width,
captureInfo.captureHandle->height);
}
td_s32 ret = uapi_disp_init();
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("call uapi_disp_init failed, ret=%#x", ret));
if (captureInfo.captureType == CaptureType::CAPTURE_TYPE_VIDEO_GRAPHIC) {
snapAttr.snap_type = UAPI_DISP_SNAP_TYPE_VIDEOGFX;
ret = AcquireSnapshot(captureInfo, snapAttr, capPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("AcquireSnapshot failed, ret = %#x", ret));
} else if (captureInfo.captureType == CaptureType::CAPTURE_TYPE_VIDEO) {
snapAttr.snap_type = UAPI_DISP_SNAP_TYPE_VIDEO;
ret = CaptureWinPicture(captureInfo, capPicture);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE,
ALOGE("CaptureWinPicture failed, ret = %#x", ret));
} else {
ALOGE("capture mode unsupported, type = %d", captureInfo.captureType);
return TD_FAILURE;
}
// uapi_disp_deinit will close all disp, when recording don't deinit
if (!m_isRecord) {
ret = uapi_disp_deinit();
}
if (m_debugCapture) {
gettimeofday(&end, nullptr);
time_t sec = end.tv_sec - start.tv_sec;
suseconds_t usec = end.tv_usec - start.tv_usec;
ALOGD("the cost time of capture_screen is %lds %ldus ", sec, usec);
}
return TD_SUCCESS;
}
int HwGraphicsIapiComImpl::InitCast(uint64_t display, uint32_t format, uint32_t width, uint32_t height)
{
ALOGI("InitCast");
(void)display;
td_s32 ret = uapi_disp_init();
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_INVALID_HANDLE, ALOGE("InitCast failed, ret=%#x", ret));
uapi_disp_cast_attr castAttr;
errno_t eok = memset_s(&castAttr, sizeof(uapi_disp_cast_attr), 0x0, sizeof(uapi_disp_cast_attr));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_INVALID_HANDLE, ALOGE("InitCast castAttr memset failed"));
castAttr.format = UAPI_FORMAT_YUV_SEMIPLANAR_420_UV;
castAttr.low_delay = TD_FALSE;
castAttr.cast_type = UAPI_DISP_CAST_TYPE_VIDEOGFX;
castAttr.width = width;
castAttr.height = height;
m_frameWidth = width;
m_frameHeight = height;
if (format == HAL_PIXEL_FORMAT_RGBA_8888) {
tdeFormat = UAPI_GFX2D_FMT_ABGR8888;
} else {
tdeFormat = UAPI_GFX2D_FMT_SEMIPLANAR420UV;
}
ALOGI("dstSurface Format:%d", tdeFormat);
td_handle castHandle = TD_INVALID_HANDLE;
uapi_disp dispId = UAPI_DISPLAY0;
if (IsSimultaneousDisplay()) {
ret = uapi_disp_create_cast(UAPI_DISPLAY1, &castAttr, &castHandle);
dispId = UAPI_DISPLAY1;
} else {
ret = uapi_disp_create_cast(UAPI_DISPLAY0, &castAttr, &castHandle);
dispId = UAPI_DISPLAY0;
}
ALOGI("InitCast with display: %d", dispId);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_INVALID_HANDLE, ALOGE("CreateCast failed, ret=%#x", ret));
ret = uapi_disp_set_cast_enable(castHandle, TD_TRUE);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_INVALID_HANDLE, ALOGE("SetCastEnable failed, ret=%#x", ret));
uapi_disp_timing timing = {};
ret = uapi_disp_get_custom_timing(dispId, &timing);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_INVALID_HANDLE, ALOGE("disp get custom timing failed, ret=%#x", ret));
timingFrameRate = timing.vert_freq / rateMulToMills;
setFrameRate = static_cast<uint32_t>(property_get_int32("config.virtualdisplay.frame_rate", defaultFrameRate));
if (setFrameRate <= 0 || setFrameRate >= timingFrameRate) {
setFrameRate = timingFrameRate;
}
ALOGI("timingFrameRate:%d setFrameRate:%d", timingFrameRate, setFrameRate);
m_isRecord = true;
m_debugCast = property_get_bool("vendor.gfx.debug.cast", false);
m_enableTdeCopy = property_get_bool("vendor.gfx.enable.tde.copy", true);
return static_cast<int32_t>(castHandle);
}
bool HwGraphicsIapiComImpl::IsSimultaneousDisplay() const
{
bool isSameDisplay = false;
uapi_disp_state state = {};
td_s32 ret = uapi_disp_get_state(UAPI_DISPLAY1, &state);
if (ret != TD_SUCCESS) {
ALOGE("get display state failed, ret=%#x", ret);
return false;
}
if (state.is_slave == TD_TRUE) {
isSameDisplay = true;
}
return isSameDisplay;
}
void HwGraphicsIapiComImpl::PrepareDstSurface(uapi_gfx2d_surface &dstSurface, const private_handle_t &dstHandle) const
{
dstSurface.format = tdeFormat;
dstSurface.width = dstHandle.width;
dstSurface.height = dstHandle.height;
dstSurface.stride[0] = dstHandle.bytes_stride;
dstSurface.stride[1] = dstHandle.bytes_stride;
dstSurface.mem_handle[0].mem_handle = dstHandle.fd;
dstSurface.mem_handle[1].mem_handle = dstHandle.fd;
dstSurface.mem_handle[0].addr_offset = dstHandle.offset;
dstSurface.mem_handle[1].addr_offset = dstHandle.offset + dstSurface.stride[0] * dstSurface.height;
dstSurface.out_rect.x = 0;
dstSurface.out_rect.y = 0;
dstSurface.out_rect.width = dstHandle.width;
dstSurface.out_rect.height = dstHandle.height;
if (dstHandle.bytes_stride > max16KMul4 || dstHandle.height > max16K) {
ALOGI("private_handle_t data out of range");
return;
}
dstSurface.size[0] = dstHandle.bytes_stride * dstHandle.height;
dstSurface.size[1] = dstHandle.bytes_stride * dstHandle.height;
dstSurface.alpha_ext.alpha0 = 0;
dstSurface.alpha_ext.alpha1 = 0xff;
dstSurface.is_alpha_ext_1555 = TD_TRUE;
dstSurface.is_alpha_max_255 = TD_TRUE;
}
void HwGraphicsIapiComImpl::PrepareSrcSurface(uapi_gfx2d_surface &srcSurface,
const uapi_video_frame_info &frameInfo) const
{
srcSurface.format = UAPI_GFX2D_FMT_SEMIPLANAR420UV;
srcSurface.width = frameInfo.decode_width;
srcSurface.height = frameInfo.decode_height;
srcSurface.stride[0] = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].stride_y;
srcSurface.stride[1] = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].stride_c;
if (srcSurface.height > uMax16K || srcSurface.stride[0] > uMax16KMul4 ||
srcSurface.stride[1] > uMax16K) {
ALOGI("Surface data out of range");
return;
}
srcSurface.size[0] = srcSurface.stride[0] * srcSurface.height;
srcSurface.size[1] = srcSurface.stride[1] * srcSurface.height;
srcSurface.alpha_ext.alpha0 = 0;
srcSurface.alpha_ext.alpha1 = 0xff;
srcSurface.is_alpha_ext_1555 = TD_TRUE;
srcSurface.is_alpha_max_255 = TD_TRUE;
srcSurface.in_rect.x = 0;
srcSurface.in_rect.y = 0;
srcSurface.in_rect.width = frameInfo.decode_width;
srcSurface.in_rect.height = frameInfo.decode_height;
srcSurface.mem_handle[0].mem_handle = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].start_addr;
srcSurface.mem_handle[1].mem_handle = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].start_addr;
srcSurface.mem_handle[0].addr_offset = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].y_offset;
srcSurface.mem_handle[1].addr_offset = frameInfo.frame_addr[UAPI_MULTI_VIEW_0].c_offset;
}
int HwGraphicsIapiComImpl::CopyBufferByTDE(const uapi_video_frame_info &frameInfo, const private_handle_t &dstHandle)
{
uapi_gfx2d_surface src, dst;
uapi_gfx2d_attr attr;
uapi_gfx2d_list surfaceList;
td_s32 timeOut = 50;
td_s32 ret = TD_FAILURE;
errno_t eok = memset_s(&src, sizeof(uapi_gfx2d_surface), 0x0, sizeof(uapi_gfx2d_surface));
HWGRAPHIC_CHK_RETURN(eok != EOK, TD_FAILURE, ALOGE("CopyBufferByTDE stSrc memset_s failed"));
eok = memset_s(&dst, sizeof(uapi_gfx2d_surface), 0x0, sizeof(uapi_gfx2d_surface));
HWGRAPHIC_CHK_RETURN(eok != EOK, TD_FAILURE, ALOGE("CopyBufferByTDE stDst memset_s failed"));
eok = memset_s(&attr, sizeof(uapi_gfx2d_attr), 0x0, sizeof(uapi_gfx2d_attr));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("uapi_gfx2d_attr memset failed"));
PrepareSrcSurface(src, frameInfo);
PrepareDstSurface(dst, dstHandle);
ret = uapi_gfx2d_open(UAPI_GFX2D_DEV_ID_0);
if (ret != TD_SUCCESS) {
ALOGE("uapi_gfx2d_open failed, ret = 0x%x", ret);
return ret;
}
td_handle handle = uapi_gfx2d_create(UAPI_GFX2D_DEV_ID_0);
if (handle < 0) {
ALOGE("uapi_gfx2d_create failed");
CloseHandler(handle);
return ret;
}
surfaceList.src_surfaces = &src;
surfaceList.dst_surface = &dst;
surfaceList.src_surface_cnt = 1;
surfaceList.ops_mode = UAPI_GFX2D_OPS_BIT_BLIT;
attr.resize_attr.resize_enable = TD_TRUE;
surfaceList.src_surfaces[0].attr = &attr;
ret = uapi_gfx2d_bitblit(handle, &surfaceList);
FaultInfo mFaultInfo = {"uapi_gfx2d_bitblit"};
HwgraphicsDft::GetInstance()->ReportFaultIfNecessary(ret != TD_SUCCESS, SCREENRECORD_FAIL, mFaultInfo);
if (ret != TD_SUCCESS) {
ALOGE("uapi_gfx2d_bitblit failed, ret = 0x%x", ret);
CloseHandler(handle);
return ret;
}
ret = uapi_gfx2d_submit(handle, TD_TRUE, timeOut);
mFaultInfo.funName = "uapi_gfx2d_submit";
HwgraphicsDft::GetInstance()->ReportFaultIfNecessary(ret != TD_SUCCESS, SCREENRECORD_FAIL, mFaultInfo);
if (ret != TD_SUCCESS) {
ALOGE("uapi_gfx2d_submit failed, ret = 0x%x", ret);
CloseHandler(handle);
return ret;
}
return ret;
}
void HwGraphicsIapiComImpl::SetBlackCastFrame(const bool isBlack)
{
// when change page, isBlack value will unsteady
if (isBlack) {
m_needSetBlackFrame = true;
}
if (!isBlack && !m_lastBlackFrame) {
m_needSetBlackFrame = false;
}
// App switching is too fast and the life cycle is disordered.
// Therefore, a delay black frame needs to be added
// when a secure layer is switched to an insecure layer.
if (m_lastNeedBlackFrame && !m_needSetBlackFrame) {
m_needBlackFrameCount = delayBlackFrame;
}
m_lastNeedBlackFrame = m_needSetBlackFrame;
m_lastBlackFrame = isBlack;
}
int HwGraphicsIapiComImpl::fillFrame(uapi_video_frame_info& frameInfo, const private_handle_t &handle)
{
errno_t eok = EOK;
int ret = TD_SUCCESS;
// TDE do't support secureFrame copy, so set to black frame.
if (m_needSetBlackFrame || m_needBlackFrameCount > 0 || frameInfo.secure_frame) {
// set the YUV to black, Y(0x20) U(0x80) V(0x80) means black
if (m_frameWidth <= uMax16K || m_frameHeight <= uMax16K) {
eok = memset_s((uint8_t *)handle.base,
m_frameWidth * m_frameHeight,
0x20,
m_frameWidth * m_frameHeight);
HWGRAPHIC_CHK_RETURN(eok != EOK, TD_FAILURE, ALOGE("handle memset_s failed"));
eok = memset_s((uint8_t *)handle.base + m_frameWidth * m_frameHeight,
m_frameWidth * m_frameHeight / half,
0x80,
m_frameWidth * m_frameHeight / half);
HWGRAPHIC_CHK_RETURN(eok != EOK, TD_FAILURE, ALOGE("handle memset_s failed"));
if (m_needBlackFrameCount > 0) {
m_needBlackFrameCount--;
}
ret = TD_SUCCESS;
}
} else {
// copy buffer
if (!m_enableTdeCopy) {
td_mem_size_t bufSize = static_cast<unsigned long long>(
(frameInfo.display_height) * (frameInfo.frame_addr[0].stride_y) * (1 + RATIO_OF_UV_TO_Y_FOR_YUV420));
void* virAddr = ext_mpi_mmz_map(frameInfo.frame_addr[0].start_addr, bufSize);
HWGRAPHIC_CHK_RETURN((virAddr == nullptr), TD_FAILURE, ALOGE("castFrame ext_mpi_mmz_map failed"));
size_t count = static_cast<uint32_t>(
(frameInfo.display_height) * (frameInfo.frame_addr[0].stride_y) * (1 + RATIO_OF_UV_TO_Y_FOR_YUV420));
ret = memcpy_s(handle.base, handle.size, virAddr, count);
ext_mpi_mmz_unmap(virAddr, bufSize);
HWGRAPHIC_CHK_RETURN((ret != TD_SUCCESS), TD_FAILURE, ALOGE("castFrame memcpy_s failed %d", ret));
} else {
ret = CopyBufferByTDE(frameInfo, handle);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("CopyBufferByTDE failed %d", ret));
}
}
return ret;
}
int HwGraphicsIapiComImpl::CastFrame(int32_t castHandle, const private_handle_t &handle, int fence, int &acquireFence)
{
uapi_video_frame_info frameInfo;
errno_t eok;
int ret;
int64_t acquireCastEnd;
if (fence >= 0) {
ret = sync_wait(fence, CAST_SYNC_TIMEOUT);
HWGRAPHIC_CHK_PRINTF((ret != 0), ALOGE("castFrame sync_wait failed %d", ret));
}
bool controlFrameRate = true;
do {
eok = memset_s(&frameInfo, sizeof(uapi_video_frame_info), 0x0, sizeof(uapi_video_frame_info));
HWGRAPHIC_CHK_RETURN((eok != EOK), TD_FAILURE, ALOGE("capPicture memset failed"));
ret = uapi_disp_acquire_cast_frame(castHandle, &frameInfo, ACQUIRE_FRAME_TIMEOUT);
acquireCastEnd = ns2us(systemTime(SYSTEM_TIME_MONOTONIC));
if (ret == TD_SUCCESS) {
if (IsDiscardFrame(timingFrameRate, setFrameRate, allFrameCount)) {
ret = uapi_disp_release_cast_frame(castHandle, &frameInfo);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("release cast frame failed %d", ret));
} else {
controlFrameRate = false;
}
allFrameCount++;
}
} while (controlFrameRate);
ret = fillFrame(frameInfo, handle);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("Fill frame failed! ret: %d", ret));
int64_t copyEnd = ns2us(systemTime(SYSTEM_TIME_MONOTONIC));
uapi_disp_release_cast_frame(castHandle, &frameInfo);
int64_t releaseCastEnd = ns2us(systemTime(SYSTEM_TIME_MONOTONIC));
if (m_debugCast) {
ALOGE("castFrame cost time:{Acquire:%" PRId64 ", Copy:%" PRId64 ", Release:%" PRId64 "}",
acquireCastEnd - castFrameStart, copyEnd - acquireCastEnd, releaseCastEnd - copyEnd);
}
acquireFence = -1;
return ret;
}
bool HwGraphicsIapiComImpl::IsDiscardFrame(int32_t systemFrameRate, int32_t needFrameRate, int32_t frameRateCount) const
{
if (systemFrameRate <= needFrameRate) {
return false;
}
if (((systemFrameRate - needFrameRate) * frameRateCount) % systemFrameRate < needFrameRate) {
return false;
} else {
return true;
}
}
int HwGraphicsIapiComImpl::CloseCast(int32_t castHandle)
{
ALOGI("close cast %d", castHandle);
td_s32 ret = uapi_disp_destroy_cast(castHandle);
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("call uapi_disp_destroy_cast failed %d", ret));
ret = uapi_disp_deinit();
HWGRAPHIC_CHK_PRINTF((ret != TD_SUCCESS), ALOGE("call uapi_disp_deinit failed %d", ret));
m_needSetBlackFrame = false;
m_isRecord = false;
return ret;
}
}