/* * 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 #include #include #include #include #include #include #include #include #include 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 (ptCapPicture.decode_width); captureInfo.captureRect.bottom = static_cast (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(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(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( (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( (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; } }