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