/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2019. All rights reserved. * Description: On behalf of a display device, hwcomposer is called for composition and sent for display * Author: Hisilicon * Created: 2019.12.02 */ #include "dft/HWCDft.h" #include "HWCIapiComImpl.h" #include #include #include #include #include #include #include #include #ifdef EXT_HDMI_SUPPORT #include #endif #include #include namespace android { using namespace dft; struct SupportResolution { uint32_t width; uint32_t height; }; const SupportResolution RESOLUTIONS[] = { { 3840, 2160 }, { 1920, 1080 }, { 1280, 720 } }; const float SUPPORTFPS[] = {20.00, 30.00, 60.00, 120}; static uapi_gfx2d_color_fmt GetGFX2DFormat(const int androidFormat) { struct { int androidFormat; uapi_gfx2d_color_fmt socGFX2DFormat; } getFormatMap[] = { { HAL_PIXEL_FORMAT_BGRA_8888, UAPI_GFX2D_FMT_ARGB8888 }, { HAL_PIXEL_FORMAT_RGBA_8888, UAPI_GFX2D_FMT_ABGR8888 }, { HAL_PIXEL_FORMAT_RGBX_8888, UAPI_GFX2D_FMT_XBGR8888 }, { HAL_PIXEL_FORMAT_RGB_888, UAPI_GFX2D_FMT_RGB888 }, { HAL_PIXEL_FORMAT_RGB_565, UAPI_GFX2D_FMT_RGB565 }, { HAL_PIXEL_FORMAT_RGBA_1010102, UAPI_GFX2D_FMT_ARGB2101010}, { HAL_PIXEL_FORMAT_YCrCb_420_SP, UAPI_GFX2D_FMT_SEMIPLANAR420UV }, { HAL_PIXEL_FORMAT_YV12, UAPI_GFX2D_FMT_PLANAR420 }, }; for (unsigned int i = 0; i < sizeof(getFormatMap) / sizeof(getFormatMap[0]); i++) { if (androidFormat == getFormatMap[i].androidFormat) { return getFormatMap[i].socGFX2DFormat; } } return UAPI_GFX2D_FMT_RGB565; } #ifdef EXT_HDMI_SUPPORT static void HandleHdmiCallback(uapi_hdmitx_id id, uapi_hdmitx_event_type event, td_void *privateData) { int displayId = 0; bool isSwitched = HWCIapiAdapter::GetInstance().IsDisplaySwitched(); if (id == UAPI_HDMITX_ID_0) { displayId = isSwitched ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY; } else if (id == UAPI_HDMITX_ID_1) { displayId = isSwitched ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL; } else { ALOGE("GetHdrInfo: invalid hdmitx id:%d", id); return; } UNUSED(privateData); if (HWCIapiComImpl::m_callback == nullptr) { ALOGE("Error: HandleHdmiCallback HWCIapiComImpl::m_callback is nullptr"); } switch (event) { case UAPI_HDMITX_EVENT_HOTPLUG_IN: case UAPI_HDMITX_EVENT_RSEN_CONNECT: HWCIapiComImpl::m_callback(displayId, HWC2::Connection::Connected); break; case UAPI_HDMITX_EVENT_HOTPLUG_OUT: case UAPI_HDMITX_EVENT_RSEN_DISCONNECT: HWCIapiComImpl::m_callback(displayId, HWC2::Connection::Disconnected); break; default: ALOGI("hwcHdmiEventProc enter other event:%d for display %d", event, id); break; } } #endif static bool Intersect(hwc_rect_t &with, hwc_rect_t &result) { result.left = result.left > with.left ? result.left : with.left; result.top = result.top > with.top ? result.top : with.top; result.right = result.right < with.right ? result.right : with.right; result.bottom = result.bottom < with.bottom ? result.bottom : with.bottom; return !(result.left >= result.right || result.top >= result.bottom); } #ifdef EXT_HDMI_SUPPORT static uapi_hdmitx_callback hdmiCallBack = { HandleHdmiCallback, nullptr }; #endif HWCHdmiCallback HWCIapiComImpl::m_callback = nullptr; HWCIapiComImpl::HWCIapiComImpl() : m_gfx2dList({0, nullptr, nullptr, UAPI_GFX2D_OPS_NONE}), m_enabledDisplayCount(1), m_switchDisplay(false), m_capabilityInfo({}) { } bool HWCIapiComImpl::IsDisplayConnected(const int displayId) { bool result = false; #ifdef EXT_HDMI_SUPPORT uapi_disp iapiDisplayId; if (displayId == HWC_DISPLAY_PRIMARY) { iapiDisplayId = m_switchDisplay ? UAPI_DISPLAY1 : UAPI_DISPLAY0; } else if (displayId == HWC_DISPLAY_EXTERNAL) { iapiDisplayId = m_switchDisplay ? UAPI_DISPLAY0 : UAPI_DISPLAY1; } else { ALOGE("UpdateVirtualScreen with bad displayId: %d", displayId); return result; } uapi_disp_intf_group intfStatus; int ret = uapi_disp_get_intf_status(iapiDisplayId, &intfStatus); if (ret != TD_SUCCESS) { ALOGI("Can not get the interface status for iapidisplay:%d display:%d", iapiDisplayId, displayId); return result; } for (td_u32 i = 0; i < intfStatus.number && !result; i++) { switch (intfStatus.intf[i].intf_type) { case UAPI_DISP_INTF_TYPE_HDMITX: uapi_hdmitx_status hdmiStatus; ret = uapi_hdmitx_get_status((uapi_hdmitx_id)intfStatus.intf[i].intf.hdmitx, &hdmiStatus); if ((ret == TD_SUCCESS) && (hdmiStatus.hotplug == UAPI_HDMITX_HOTPLUG_IN)) { result = true; ALOGI("HDMI Plug iapidisplay:%d display:%d", iapiDisplayId, displayId); } else { ALOGI("detect No HDMI Plug iapidisplay:%d display:%d", iapiDisplayId, displayId); } break; case UAPI_DISP_INTF_TYPE_PANEL: ALOGI("MIPI Interface iapidisplay:%d display:%d", iapiDisplayId, displayId); result = true; break; case UAPI_DISP_INTF_TYPE_CVBS: ALOGI("CVBS Interface iapidisplay:%d display:%d", iapiDisplayId, displayId); result = true; break; default: ALOGI("Invalid interface type:%d iapidisplay:%d display:%d", intfStatus.intf[i].intf_type, iapiDisplayId, displayId); } } #else result = true; ALOGD("force set disp type UAPI_DISP_INTF_TYPE_PANEL, displayID = %d ", displayId); #endif return result; } #ifdef EXT_HDMI_SUPPORT int HWCIapiComImpl::GetHdmiMaxPara(const int displayId, float &maxWidth, float &maxHeight) { uapi_hdmitx_id hdmiId; if (displayId == HWC_DISPLAY_PRIMARY) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_1 : UAPI_HDMITX_ID_0; } else if (displayId == HWC_DISPLAY_EXTERNAL) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_0 : UAPI_HDMITX_ID_1; } else { ALOGE("GetHdmiMaxPara: invalid display id:%d", displayId); return HWC_FAILURE; } uapi_hdmitx_sink_info sinkInfo; errno_t eok = memset_s(&sinkInfo, sizeof(uapi_hdmitx_sink_info), 0, sizeof(uapi_hdmitx_sink_info)); HWC_CHK_RETURN((eok != EOK), HWC_FAILURE, ALOGE("GetHdmiMaxPara sinkInfo winAttr memset_s failed")); td_s32 ret = uapi_hdmitx_get_sink_info(hdmiId, &sinkInfo); if (ret == TD_SUCCESS) { maxWidth = sinkInfo.disp_para.max_image_width; maxHeight = sinkInfo.disp_para.max_image_height; return HWC_SUCCESS; } return HWC_FAILURE; } int HWCIapiComImpl::RegisterHdmiCallback(const int displayId, HWCHdmiCallback callback) { if (callback == nullptr) { ALOGE("Error: RegisterHdmiCallback with null callback"); } uapi_hdmitx_id hdmiId; if (displayId == HWC_DISPLAY_PRIMARY) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_1 : UAPI_HDMITX_ID_0; } else if (displayId == HWC_DISPLAY_EXTERNAL) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_0 : UAPI_HDMITX_ID_1; } else { ALOGE("invalid display id:%d", displayId); return HWC_FAILURE; } m_callback = callback; uapi_hdmitx_register_callback(hdmiId, &hdmiCallBack); return HWC_SUCCESS; } int HWCIapiComImpl::UnregisterHdmiCallback(const int displayId) { uapi_hdmitx_unregister_callback(static_cast(displayId), &hdmiCallBack); m_callback = nullptr; return HWC_SUCCESS; } #endif int HWCIapiComImpl::InitIapiModules() { bool initResult = HWC_SUCCESS; // init display module int ret = uapi_disp_init(); if (ret != TD_SUCCESS) { initResult = HWC_FAILURE; ALOGE("uapi_disp_init fail(ret=0x%X)!", ret); } #ifdef EXT_HDMI_SUPPORT // init the hdmi tx module ret = uapi_hdmitx_init(); if (ret != TD_SUCCESS) { initResult = HWC_FAILURE; ALOGE("uapi_hdmitx_init fail(ret=0x%X)!", ret); } #endif // init vo module ret = uapi_win_init(); if (ret != TD_SUCCESS) { initResult = HWC_FAILURE; ALOGE("uapi_win_init fail(ret=0x%X).", ret); } // update enabled display count and primary display config int32_t iapiMasterDisplay = property_get_int32("persist.vendor.display.master", UAPI_DISPLAY0); m_enabledDisplayCount = property_get_int32("vendor.display.count", UAPI_DISPLAY0); m_switchDisplay = (iapiMasterDisplay != UAPI_DISPLAY0); ALOGI("InitIapiModules with %d enabled display, master is %d", m_enabledDisplayCount, iapiMasterDisplay); errno_t eok = memset_s(&m_capabilityInfo, sizeof(uapi_gfx2d_capability), 0, sizeof(uapi_gfx2d_capability)); if (eok != EOK) { ALOGE("memset capabilityInfo failed!"); initResult = HWC_FAILURE; } return initResult; } int HWCIapiComImpl::DeInitIapiModules() { bool deInitResult = HWC_SUCCESS; /* Deinit vo module */ int ret = uapi_win_deinit(); if (ret != TD_SUCCESS) { deInitResult = HWC_FAILURE; ALOGE("uapi_win_deinit fail(ret=0x%X)!", ret); } #ifdef EXT_HDMI_SUPPORT // Deinit hdmi tx module ret = uapi_hdmitx_deinit(); if (ret != TD_SUCCESS) { deInitResult = HWC_FAILURE; ALOGE("uapi_hdmitx_deinit fail(ret=0x%X)!", ret); } #endif // Deinit display module ret = uapi_disp_deinit(); if (ret != TD_SUCCESS) { deInitResult = HWC_FAILURE; ALOGE("uapi_disp_deinit fail(ret=0x%X)!", ret); } return deInitResult; } int HWCIapiComImpl::GetExternalDisplayStatus(uapi_disp_state *state) { return uapi_disp_get_state(UAPI_DISPLAY1, state); } bool HWCIapiComImpl::IsDisplaySwitched() { return m_switchDisplay; } int HWCIapiComImpl::GetFbDevId(const hwc2_display_t displayId) const { int externalId = property_get_int32("persist.vendor.disp1.attach.fb", FB_EXTERNAL_ID); externalId = externalId == FB_EXTERNAL_ID ? FB_EXTERNAL_ID : FB_EXTERNAL_CURSOR_ID; if (displayId == HWC_DISPLAY_PRIMARY) { return m_switchDisplay ? externalId : FB_PRIMARY_ID; } else if (displayId == HWC_DISPLAY_EXTERNAL) { return m_switchDisplay ? FB_PRIMARY_ID : externalId; } else { ALOGE("GetFbDevId with wrong displayId %" PRIu64, displayId); return m_switchDisplay ? externalId : FB_PRIMARY_ID; } } void HWCIapiComImpl::UpdateVirtualScreen(const uint64_t displayId, const unsigned int width, const unsigned int height) const { uapi_disp iapiDisplayId; if (displayId == HWC_DISPLAY_PRIMARY) { iapiDisplayId = m_switchDisplay ? UAPI_DISPLAY1 : UAPI_DISPLAY0; } else if (displayId == HWC_DISPLAY_EXTERNAL) { iapiDisplayId = m_switchDisplay ? UAPI_DISPLAY0 : UAPI_DISPLAY1; } else { ALOGE("UpdateVirtualScreen with bad displayId: %" PRIu64 "", displayId); return; } unsigned int curVirtualW = 0; unsigned int curVirtualH = 0; int ret = uapi_disp_get_virtual_screen(iapiDisplayId, &curVirtualW, &curVirtualH); if (ret != TD_SUCCESS) { ALOGE("UAPI_DISP_GetVirtualScreen failed(ret=0x%X)!", ret); } else { ALOGI("virtual screen current:(%d x %d) target:(%d x %d)", curVirtualW, curVirtualH, width, height); if ((curVirtualW != width) || (curVirtualH != height)) { ret = uapi_disp_set_virtual_screen(iapiDisplayId, width, height); if (ret != TD_SUCCESS) { ALOGE("UAPI_DISP_SetVirtualScreen(%d x %d) Failed(ret=0x%X)!", width, height, ret); } } } } inline void EnableVoWinIfNeccessary(int magicNum, td_handle window) { td_bool enable = TD_FALSE; uapi_win_get_enable(window, &enable); if (((magicNum == SIDEBAND_PLAY_MAGIC_NUM) || (magicNum == SIDEBAND_PLAY_MAGIC_NUM_BLACK)) && (enable == TD_FALSE)) { uapi_win_set_enable(window, TD_TRUE); } } void HWCIapiComImpl::DisableVoWindow(const native_handle_t &sideband) const { td_handle hWindow = sideband.data[0]; HWC_CHK_RETURN_NOT_VALUE((hWindow == 0), ALOGE("HWC sideband disable window, window handle null")); uapi_win_set_abs_zorder(hWindow, -1); ALOGI("layer destory sideband set absZorder -1, hWindow handle = 0x%x ", hWindow); return; } void HWCIapiComImpl::SetVoWindowPosition(const native_handle_t &sideband, const hwc_rect_t &hwcRect, int zorder, int absZorder) const { UNUSED(zorder); uapi_win_attr winAttr; uapi_video_rect rect = { hwcRect.left, hwcRect.top, static_cast(hwcRect.right - hwcRect.left), static_cast(hwcRect.bottom - hwcRect.top) }; td_handle hWindow = sideband.data[0]; HWC_CHK_RETURN_NOT_VALUE((hWindow == 0), ALOGE("HWC sideband set window position, window handle null")); int magicNum = 0; const int sidebandMaxNum = 2; // number of ints at &data[numFds] if (sideband.numInts >= sidebandMaxNum) { magicNum = sideband.data[1]; } errno_t eok = memset_s(&winAttr, sizeof(winAttr), 0, sizeof(winAttr)); HWC_CHK_RETURN_NOT_VALUE((eok != EOK), ALOGE("HWC sideband winAttr memset_s failed")); td_s32 ret = uapi_win_get_attr(hWindow, &winAttr); HWC_CHK_RETURN_NOT_VALUE((ret != TD_SUCCESS), ALOGE("sideband get window 0x%x attr failed, ret:%#x", hWindow, ret)); if ((rect.x != winAttr.output_rect.x) || (rect.y != winAttr.output_rect.y) || (rect.width != winAttr.output_rect.width) || (rect.height != winAttr.output_rect.height)) { ALOGI("HWC sideband position changed from(%d,%d,%d,%d) to(%d,%d,%d,%d) handle=0x%x", winAttr.output_rect.x, winAttr.output_rect.y, winAttr.output_rect.width, winAttr.output_rect.height, rect.x, rect.y, rect.width, rect.height, hWindow); td_handle handleArray[] = { hWindow }; uapi_video_rect outrect[] = { rect }; // set window outrect ret = uapi_win_set_outrect(handleArray, outrect, 1); HWC_CHK_RETURN_NOT_VALUE((ret != TD_SUCCESS), ALOGE("HWC uapi_win_set_outrect failed:%#x.", ret)); } ret = uapi_win_set_abs_zorder(hWindow, absZorder); FaultInfo mFaultInfo = {"uapi_win_set_abs_zorder", "handle", static_cast(hWindow), "absZorder", absZorder}; HWCDft::GetInstance()->ReportFaultIfNecessary( ret != TD_SUCCESS && ret != SOC_ERR_VO_WIN_NOT_EXIST, SIDEBANDPLAY_FAIL, mFaultInfo); ALOGI("set winodw zorder: %d, window handle: 0x%x ret:0x%x", absZorder, hWindow, ret); EnableVoWinIfNeccessary(magicNum, hWindow); return; } int HWCIapiComImpl::OpenGfx2dAndInitCapability() { int ret = uapi_gfx2d_open(UAPI_GFX2D_DEV_ID_0); HWC_CHK_RETURN(ret != HWC_SUCCESS, ret, ALOGE("Open gfx2d failed")); ret = uapi_gfx2d_get_capability(&m_capabilityInfo); HWC_CHK_PRINTF((ret != HWC_SUCCESS), ALOGE("get gfx2d capabilityInfo failed! %d", ret)); return ret; } int HWCIapiComImpl::CloseGfx2d() { return uapi_gfx2d_close(UAPI_GFX2D_DEV_ID_0); } int HwcFree(uapi_gfx2d_surface *gfx2dSrcSurface, uapi_gfx2d_surface *gfx2dDestSurface) { if (gfx2dDestSurface != nullptr) { free(gfx2dDestSurface); gfx2dDestSurface = nullptr; } if (gfx2dSrcSurface != nullptr) { free(gfx2dSrcSurface); gfx2dSrcSurface = nullptr; } return HWC_FAILURE; } int HWCIapiComImpl::PrepareGfx2dBasicArg(const int layerNumber) { int ret = memset_s(&m_gfx2dList, sizeof(uapi_gfx2d_list), 0, sizeof(uapi_gfx2d_list)); HWC_CHK_RETURN((ret != EOK), HWC_FAILURE, ALOGE("PrepareGfx2dBasicArg memset_s m_gfx2dList failed")); m_gfx2dList.src_surface_cnt = layerNumber; uint32_t gfx2dSurfaceSize = sizeof(uapi_gfx2d_surface) * layerNumber; uapi_gfx2d_surface *gfx2dSrcSurface = static_cast(malloc(gfx2dSurfaceSize)); HWC_CHK_RETURN((gfx2dSrcSurface == nullptr), HWC_FAILURE, ALOGE("PrepareGfx2dBasicArg: gfx2DCompose malloc failed")); ret = memset_s(gfx2dSrcSurface, gfx2dSurfaceSize, 0, gfx2dSurfaceSize); uapi_gfx2d_surface *gfx2dDestSurface = nullptr; if (ret != EOK) { ALOGE("PrepareGfx2dBasicArg memset_s gfx2DCompose failed"); return HwcFree(gfx2dSrcSurface, gfx2dDestSurface); } gfx2dDestSurface = static_cast(malloc(sizeof(uapi_gfx2d_surface))); if (gfx2dDestSurface == nullptr) { ALOGE("PrepareGfx2dBasicArg: gfx2dDestSurface malloc failed"); return HwcFree(gfx2dSrcSurface, gfx2dDestSurface); } ret = memset_s(gfx2dDestSurface, sizeof(uapi_gfx2d_surface), 0, sizeof(uapi_gfx2d_surface)); if (ret != EOK) { ALOGE("PrepareGfx2dBasicArg memset_s gfx2DCompose failed"); return HwcFree(gfx2dSrcSurface, gfx2dDestSurface); } m_gfx2dList.src_surfaces = gfx2dSrcSurface; m_gfx2dList.dst_surface = gfx2dDestSurface; return HWC_SUCCESS; } int HWCIapiComImpl::PrepareGfx2dBasicArgForLayer(uapi_gfx2d_surface& srcSurface, const HWCLayer& layer) const { srcSurface.attr = static_cast(malloc(sizeof(uapi_gfx2d_attr))); HWC_CHK_RETURN((srcSurface.attr == nullptr), HWC_FAILURE, ALOGE("PrepareGfx2dLayerArg: srcSurface.attr malloc failed")); int ret = memset_s(srcSurface.attr, sizeof(uapi_gfx2d_attr), 0, sizeof(uapi_gfx2d_attr)); HWC_CHK_RETURN((ret != EOK), HWC_FAILURE, ALOGE("PrepareGfx2dLayerArg memset_s srcSurface.attr failed")); srcSurface.attr->blend_attr.cov_blend = TD_FALSE; srcSurface.attr->blend_attr.global_alpha_en = TD_FALSE; srcSurface.attr->blend_attr.pixel_alpha_en = TD_FALSE; srcSurface.attr->blend_attr.global_alpha = layer.GetPlaneAlpha(); srcSurface.premulti_en = TD_FALSE; if (layer.GetBlendMode() == HWC2::BlendMode::Premultiplied) { srcSurface.attr->blend_attr.global_alpha_en = TD_TRUE; srcSurface.attr->blend_attr.pixel_alpha_en = TD_TRUE; srcSurface.premulti_en = TD_FALSE; } else if (layer.GetBlendMode() == HWC2::BlendMode::Coverage) { srcSurface.attr->blend_attr.global_alpha_en = TD_TRUE; srcSurface.attr->blend_attr.pixel_alpha_en = TD_TRUE; srcSurface.premulti_en = TD_TRUE; } else { srcSurface.attr->blend_attr.cov_blend = TD_TRUE; } srcSurface.attr->clip_attr.clip_mode = UAPI_GFX2D_CLIP_NONE; srcSurface.attr->colorkey_attr.colorkey_enable = TD_FALSE; srcSurface.attr->rop_attr.rop_enable = TD_FALSE; srcSurface.attr->resize_attr.resize_enable = TD_FALSE; srcSurface.attr->filter_attr.filter_mode = UAPI_GFX2D_FILTER_BOTH; if ((srcSurface.in_rect.width != srcSurface.out_rect.width) || (srcSurface.in_rect.height != srcSurface.out_rect.height)) { srcSurface.attr->resize_attr.resize_enable = TD_TRUE; } srcSurface.acquire_fence_fd = HWC_INVALID_FENCE_ID; srcSurface.release_fence_fd = HWC_INVALID_FENCE_ID; return HWC_SUCCESS; } void HWCIapiComImpl::PrepareGfx2dHandleRelatedArgForLayer(uapi_gfx2d_surface& srcSurface, const HWCLayer& layer, const bool isAsync) const { // handle is not nullptr const private_handle_t *handle = static_cast(layer.GetLayerBuffer().buffer); if (handle == nullptr) { ALOGE("In PrepareGfx2dHandleRelatedArgForLayer, layer's buffer is nullptr, ignore this layer!!"); return; } srcSurface.acquire_fence_fd = isAsync ? layer.GetLayerBuffer().fenceId : HWC_INVALID_FENCE_ID; srcSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_MEM; srcSurface.mem_handle[0].mem_handle = handle->fd; srcSurface.mem_handle[0].addr_offset = 0; srcSurface.format = GetGFX2DFormat(handle->format); int32_t val; int ret = gralloc_buffer_attr_read(handle, GRALLOC_BUFFER_ATTR_COMPRESSION, &val); if (ret != GRALLOC_SUCCESS) { ALOGE("gralloc_buffer_attr_read failed :%d", ret); } if (val == COMPRESSION_FLAG_AFBC) { srcSurface.compress_mode = UAPI_GFX2D_COMPRESS_AFBC; } else { srcSurface.compress_mode = UAPI_GFX2D_COMPRESS_NONE; } // videoLayer if ((handle->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) || (handle->format == HAL_PIXEL_FORMAT_YV12)) { srcSurface.height = handle->height; srcSurface.width = handle->width; srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = handle->bytes_stride; srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_1] = handle->bytes_stride; srcSurface.mem_handle[1].mem_handle = handle->fd; srcSurface.mem_handle[1].addr_offset = srcSurface.height * handle->bytes_stride; if (handle->format == HAL_PIXEL_FORMAT_YV12) { srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = handle->bytes_stride; const uint32_t bytesStrideNum = 2; unsigned int bytesStride = (unsigned int)handle->bytes_stride / bytesStrideNum; const uint32_t yuv12LayerAlign = 16; srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_1] = ALIGN(bytesStride, yuv12LayerAlign); srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_2] = ALIGN(bytesStride, yuv12LayerAlign); // y -- y -- y -- y // u -- u // v -- v // cb srcSurface.mem_handle[CB_INDEX].addr_offset = (srcSurface.height * srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0]) + ((srcSurface.height / bytesStrideNum) * srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_1]); // cr srcSurface.mem_handle[CR_INDEX].mem_handle = handle->fd; srcSurface.mem_handle[CR_INDEX].addr_offset = srcSurface.height * srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0]; } } else { // graphic layer srcSurface.height = handle->height; srcSurface.width = handle->width; srcSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = handle->bytes_stride; } } int HWCIapiComImpl::PrepareGfx2dLayerArg(const HWCLayer& layer, const unsigned int i, const int fbWidth, const int fbHeight, const bool isAsync) { HWC_CHK_RETURN((i >= m_gfx2dList.src_surface_cnt), HWC_FAILURE, ALOGE("PrepareGfx2dLayerArg has wrong parameter i:%d", i)); HWC_CHK_RETURN((m_gfx2dList.src_surfaces == nullptr), HWC_FAILURE, ALOGE("PrepareGfx2dLayerArg: src_surfaces[%d] is not initialized", i)); uapi_gfx2d_surface &srcSurface = m_gfx2dList.src_surfaces[i]; hwc_rect_t layerSourceCrop = layer.GetLayerSourceCrop(); hwc_rect_t layerDisplayFrame = layer.GetDisplayFrame(); hwc_rect_t fbRect = { 0, 0, fbWidth, fbHeight }; // crop display frame, but don't crop source crop by frame buffer size if (!Intersect(fbRect, layerDisplayFrame)) { ALOGE("DisplayFrame out of screen layer:%" PRIu64, layer.GetId()); } srcSurface.in_rect = { layerSourceCrop.left, layerSourceCrop.top, static_cast(layerSourceCrop.right - layerSourceCrop.left), static_cast(layerSourceCrop.bottom - layerSourceCrop.top) }; srcSurface.out_rect = { layerDisplayFrame.left, layerDisplayFrame.top, static_cast(layerDisplayFrame.right - layerDisplayFrame.left), static_cast(layerDisplayFrame.bottom - layerDisplayFrame.top) }; if (PrepareGfx2dBasicArgForLayer(srcSurface, layer) == HWC_FAILURE) { ALOGE("prepare basicarg for layer return Failure"); return HWC_FAILURE; } if (layer.GetDeviceSelected() == HWC2::Composition::Sideband) { srcSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_COLOR; srcSurface.background_color = 0; srcSurface.in_rect = srcSurface.out_rect; srcSurface.attr->resize_attr.resize_enable = TD_FALSE; srcSurface.attr->blend_attr.cov_blend = TD_TRUE; return HWC_SUCCESS; } // handle is nullptr if (layer.IsDimLayer()) { srcSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_COLOR; // GFBG_FMT_ABGR8888 A in 4th place const uint32_t alphaPosition = 24; srcSurface.background_color = layer.GetPlaneAlpha() << alphaPosition; srcSurface.in_rect = srcSurface.out_rect; srcSurface.attr->resize_attr.resize_enable = TD_FALSE; srcSurface.attr->blend_attr.cov_blend = TD_FALSE; srcSurface.attr->blend_attr.global_alpha_en = TD_FALSE; return HWC_SUCCESS; } PrepareGfx2dHandleRelatedArgForLayer(srcSurface, layer, isAsync); return HWC_SUCCESS; } int HWCIapiComImpl::PrepareGfx2dDestArg(const int framebufferFd, const HWCBuffer &fbBuffer, const bool hwcCompress) { const private_handle_t *fbHandle = static_cast(fbBuffer.buffer); HWC_CHK_RETURN(fbHandle == nullptr, HWC_FAILURE, ALOGE("PrepareGfx2dDestArg fbHandle is nullptr")); uapi_gfx2d_surface &dstSurface = m_gfx2dList.dst_surface[0]; // Number of bytes occupied by different formats dstSurface.mem_handle[0].mem_handle = fbHandle->fd; dstSurface.mem_handle[0].addr_offset = fbHandle->offset; dstSurface.format = UAPI_GFX2D_FMT_ARGB8888; dstSurface.width = fbHandle->width; dstSurface.height = fbHandle->height; dstSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = fbHandle->bytes_stride; dstSurface.surface_type = UAPI_GFX2D_SURFACE_TYPE_MEM; dstSurface.acquire_fence_fd = fbBuffer.fenceId; dstSurface.release_fence_fd = HWC_INVALID_FENCE_ID; gfbg_layerinfo fbLayerInfoGetStride; fbLayerInfoGetStride.surface.fmt = GFBG_COLOR_FMT_ARGB8888; if (ioctl(framebufferFd, GFBGIOGET_LAYERINFO, &fbLayerInfoGetStride) != 0) { ALOGE(" FBIO_HWC_GETLAYERINFO Error!"); return HWC_FAILURE; } if (hwcCompress) { dstSurface.compress_mode = UAPI_GFX2D_COMPRESS_HFBC; dstSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = fbLayerInfoGetStride.surface.cmp_stride; } else { dstSurface.stride[GFX2D_SURFACE_STRIDE_INDEX_0] = fbLayerInfoGetStride.surface.stride; } return HWC_SUCCESS; } void HWCIapiComImpl::DumpGfx2dComposeInfo() const { unsigned int count = m_gfx2dList.src_surface_cnt; if (GFX2D_SURFACE_STRIDE_INDEX_0 >= UAPI_GFX2D_COMPONENT || GFX2D_SURFACE_STRIDE_INDEX_1 >= UAPI_GFX2D_COMPONENT || GFX2D_SURFACE_STRIDE_INDEX_2 >= UAPI_GFX2D_COMPONENT) { ALOGE("DumpGfx2dComposeInfo failed:out of array range"); return; } ALOGD("=================DumpGfx2dComposeInfo Begin================="); for (unsigned int i = 0; i < count; i++) { ALOGD("srcSurface[%d]: fd=%lld offset=%llu acquireFence=%d", i, m_gfx2dList.src_surfaces[i].mem_handle[0].mem_handle, m_gfx2dList.src_surfaces[i].mem_handle[0].addr_offset, m_gfx2dList.src_surfaces[i].acquire_fence_fd); ALOGD(" InRect=[%d, %d, w:%d, h:%d] OutRect=[%d, %d, w:%d, w:%d] PreMulti=%d Type=%d BackgroundColor=0x%x", m_gfx2dList.src_surfaces[i].in_rect.x, m_gfx2dList.src_surfaces[i].in_rect.y, m_gfx2dList.src_surfaces[i].in_rect.width, m_gfx2dList.src_surfaces[i].in_rect.height, m_gfx2dList.src_surfaces[i].out_rect.x, m_gfx2dList.src_surfaces[i].out_rect.y, m_gfx2dList.src_surfaces[i].out_rect.width, m_gfx2dList.src_surfaces[i].out_rect.height, m_gfx2dList.src_surfaces[i].premulti_en, m_gfx2dList.src_surfaces[i].surface_type, m_gfx2dList.src_surfaces[i].background_color); ALOGD(" CompressMode=%d Width=%d Height=%d Stride={%d %d %d} Format=%d alpExt={%d %d %d}", m_gfx2dList.src_surfaces[i].compress_mode, m_gfx2dList.src_surfaces[i].width, m_gfx2dList.src_surfaces[i].height, m_gfx2dList.src_surfaces[i].stride[GFX2D_SURFACE_STRIDE_INDEX_0], m_gfx2dList.src_surfaces[i].stride[GFX2D_SURFACE_STRIDE_INDEX_1], m_gfx2dList.src_surfaces[i].stride[GFX2D_SURFACE_STRIDE_INDEX_2], m_gfx2dList.src_surfaces[i].format, m_gfx2dList.src_surfaces[i].alpha_ext.alpha_ext_enable, m_gfx2dList.src_surfaces[i].alpha_ext.alpha0, m_gfx2dList.src_surfaces[i].alpha_ext.alpha1); ALOGD(" GloAlp=%d PixAlpEn=%d GloAlpEn=%d CovBlend=%d keyEn=%d rezEn=%d clipMod=%d filMod=%d ropEn=%d", m_gfx2dList.src_surfaces[i].attr->blend_attr.global_alpha, m_gfx2dList.src_surfaces[i].attr->blend_attr.pixel_alpha_en, m_gfx2dList.src_surfaces[i].attr->blend_attr.global_alpha_en, m_gfx2dList.src_surfaces[i].attr->blend_attr.cov_blend, m_gfx2dList.src_surfaces[i].attr->colorkey_attr.colorkey_enable, m_gfx2dList.src_surfaces[i].attr->resize_attr.resize_enable, m_gfx2dList.src_surfaces[i].attr->clip_attr.clip_mode, m_gfx2dList.src_surfaces[i].attr->filter_attr.filter_mode, m_gfx2dList.src_surfaces[i].attr->rop_attr.rop_enable); } ALOGD("destSurface: fd=%lld offset=%llu acquireFence=%d", m_gfx2dList.dst_surface[0].mem_handle[0].mem_handle, m_gfx2dList.dst_surface[0].mem_handle[0].addr_offset, m_gfx2dList.dst_surface[0].acquire_fence_fd); ALOGD(" CompressMode=%d Width=%d Height=%d Stride=%d Format=%d", m_gfx2dList.dst_surface[0].compress_mode, m_gfx2dList.dst_surface[0].width, m_gfx2dList.dst_surface[0].height, m_gfx2dList.dst_surface[0].stride[0], m_gfx2dList.dst_surface[0].format); ALOGD("=================DumpGfx2dComposeInfo End================="); } int HWCIapiComImpl::Gfx2dCompose(int layerReleaseFence[], const int layerNumber, int &fbRealeaseFence, const bool isAsync) { td_bool syncCompose = isAsync ? TD_FALSE : TD_TRUE; // mem_handle valid value need >= 1, addr_offset valid value need >= 0 (that's alaways false) if (m_gfx2dList.dst_surface[0].mem_handle[0].mem_handle < 1) { ALOGE("Gfx2dCompose failed with invalid mem_handle"); DumpGfx2dComposeInfo(); return HWC_FAILURE; } int ret = uapi_gfx2d_compose(0, &m_gfx2dList, syncCompose); if (ret != TD_SUCCESS) { ALOGE("uapi_gfx2d_compose failed with return value:%d", ret); DumpGfx2dComposeInfo(); return HWC_FAILURE; } if (isAsync && m_gfx2dList.dst_surface[0].release_fence_fd != HWC_INVALID_FENCE_ID) { fbRealeaseFence = dup(m_gfx2dList.dst_surface[0].release_fence_fd); close(m_gfx2dList.dst_surface[0].release_fence_fd); } else { fbRealeaseFence = HWC_INVALID_FENCE_ID; } if (layerReleaseFence == nullptr) { ALOGE("Gfx2dCompose failed with layerReleaseFence is null"); return HWC_FAILURE; } for (int i = 0; i < layerNumber; i++) { // no need to dup because it have already been dupped in GFX2d API if (isAsync) { layerReleaseFence[i] = m_gfx2dList.src_surfaces[i].release_fence_fd; } else { layerReleaseFence[i] = HWC_INVALID_FENCE_ID; } } return HWC_SUCCESS; } void HWCIapiComImpl::PostGfx2dCompose() { if (property_get_bool("vendor.gfx.hwc.debug.compose", false)) { DumpGfx2dComposeInfo(); } for (unsigned int i = 0; i < m_gfx2dList.src_surface_cnt; i++) { if (m_gfx2dList.src_surfaces[i].attr != nullptr) { free(m_gfx2dList.src_surfaces[i].attr); m_gfx2dList.src_surfaces[i].attr = nullptr; } } if (m_gfx2dList.src_surfaces != nullptr) { free(m_gfx2dList.src_surfaces); m_gfx2dList.src_surfaces = nullptr; } if (m_gfx2dList.dst_surface != nullptr) { free(m_gfx2dList.dst_surface); m_gfx2dList.dst_surface = nullptr; } } static bool CheckFbAbilityAndBufferFlag(const int framebufferFd, const private_handle_t *handle) { gfbg_capability_info fbCapabilityInfo; ioctl(framebufferFd, GFBGIOGET_CAPABILITY, &fbCapabilityInfo); if (!fbCapabilityInfo.compression.is_support_afbc) { return false; } int bufferCompressionFlag = 0; gralloc_buffer_attr_read(handle, GRALLOC_BUFFER_ATTR_COMPRESSION, &bufferCompressionFlag); return bufferCompressionFlag != 0; } int HWCIapiComImpl::FreshDirect(const int framebufferFd, HWCBuffer &layerBuffer) const { const private_handle_t *handle = static_cast(layerBuffer.buffer); HWC_CHK_RETURN((handle == nullptr), HWC_FAILURE, ALOGE("HwcFbFreshfbHandle is null")); gfbg_layerinfo fbLayerInfo; errno_t eok = memset_s(&fbLayerInfo, sizeof(gfbg_layerinfo), 0, sizeof(gfbg_layerinfo)); HWC_CHK_RETURN((eok != EOK), HWC_FAILURE, ALOGE("hwcFbFresh stfbLayerInfo memset_s failed")); fbLayerInfo.acquire_fd = layerBuffer.fenceId; fbLayerInfo.release_fd = HWC_INVALID_FENCE_ID; fbLayerInfo.is_premulti = TD_TRUE; fbLayerInfo.alpha_sum = 0xFF; fbLayerInfo.surface.width = handle->width; fbLayerInfo.surface.height = handle->height; fbLayerInfo.surface.stride = handle->bytes_stride; fbLayerInfo.surface.mem_handle.mem_handle = handle->fd; fbLayerInfo.surface.mem_handle.addr_offset = handle->offset; fbLayerInfo.surface.fmt = GFBG_COLOR_FMT_ABGR8888; // equivalent to HAL_PIXEL_FORMAT_RGBA_8888 // afbc compress was not supported currently bool afbcCompress = property_get_bool("persist.vendor_im.gfx.afbc_compress", false); fbLayerInfo.compress_mode = afbcCompress && CheckFbAbilityAndBufferFlag(framebufferFd, handle) ? GFBG_CMP_AFBC : GFBG_CMP_NONE; if (ioctl(framebufferFd, GFBGIOPUT_LAYERINFO, &fbLayerInfo) < 0) { ALOGE("FreshDirect GFBGIOPUT_LAYERINFO failed!"); return HWC_FAILURE; } layerBuffer.releaseFenceFd = fbLayerInfo.release_fd; if (property_get_bool("vendor.gfx.hwc.debug", false)) { ALOGD("fresh fb fd=%d fence=%d releaseFence=%d, composeType=DirectFresh u32Stride=%d", handle->fd, fbLayerInfo.acquire_fd, fbLayerInfo.release_fd, fbLayerInfo.surface.stride); } return HWC_SUCCESS; } int HWCIapiComImpl::FreshFb(const int framebufferFd, HWCBuffer &fbBuffer, const int composeType, const bool hwcCompress, const bool discardFrame) const { gfbg_layerinfo fbLayerInfo; errno_t eok = memset_s(&fbLayerInfo, sizeof(gfbg_layerinfo), 0, sizeof(gfbg_layerinfo)); HWC_CHK_RETURN((eok != EOK), HWC_FAILURE, ALOGE("hwcFbFresh stfbLayerInfo memset_s failed")); const private_handle_t *fbHandle = static_cast(fbBuffer.buffer); HWC_CHK_RETURN((fbHandle == nullptr), HWC_FAILURE, ALOGE("HwcFbFreshfbHandle is null")); HWC_CHK_RETURN((framebufferFd < 0), HWC_FAILURE, ALOGE("framebufferFd is less than 0")); fbLayerInfo.acquire_fd = fbBuffer.fenceId; fbLayerInfo.release_fd = HWC_INVALID_FENCE_ID; fbLayerInfo.is_premulti = TD_TRUE; fbLayerInfo.alpha_sum = 0xFF; fbLayerInfo.surface.width = fbHandle->width; fbLayerInfo.surface.height = fbHandle->height; fbLayerInfo.surface.stride = fbHandle->bytes_stride; fbLayerInfo.surface.mem_handle.mem_handle = fbHandle->fd; fbLayerInfo.surface.mem_handle.addr_offset = fbHandle->offset; fbLayerInfo.surface.fmt = GFBG_COLOR_FMT_ARGB8888; fbLayerInfo.is_discard_frame = discardFrame ? TD_TRUE : TD_FALSE; gfbg_layerinfo fbLayerInfoGetStride; fbLayerInfoGetStride.surface.fmt = fbLayerInfo.surface.fmt; if (ioctl(framebufferFd, GFBGIOGET_LAYERINFO, &fbLayerInfoGetStride) != 0) { ALOGE(" FBIO_HWC_GETLAYERINFO Error!"); return HWC_FAILURE; } if (composeType == (int)HWC_COMPOSE::HWC_GPU_COMPOSE) { bool afbcCompress = property_get_bool("persist.vendor_im.gfx.afbc_compress", false); fbLayerInfo.compress_mode = afbcCompress && CheckFbAbilityAndBufferFlag(framebufferFd, fbHandle) ? GFBG_CMP_AFBC : GFBG_CMP_NONE; } else { fbLayerInfo.compress_mode = hwcCompress ? GFBG_CMP_HFBC : GFBG_CMP_NONE; if (hwcCompress) { fbLayerInfo.surface.stride = fbLayerInfoGetStride.surface.cmp_stride; } else { fbLayerInfo.surface.stride = fbLayerInfoGetStride.surface.stride; } } if (ioctl(framebufferFd, GFBGIOPUT_LAYERINFO, &fbLayerInfo) != 0) { ALOGE("GFBGIOPUT_LAYERINFO Error!"); } fbBuffer.releaseFenceFd = fbLayerInfo.release_fd; if (property_get_bool("vendor.gfx.hwc.debug", false)) { ALOGD("fresh fb addr=0x%x fence=%d releaseFence=%d composeType=%s compressMode=%d u32Stride=%d discard=%d", fbHandle->addr, fbLayerInfo.acquire_fd, fbBuffer.releaseFenceFd, (composeType == (int)HWC_COMPOSE::HWC_GFX2D_COMPOSE) ? "gfx2d" : "gpu", fbLayerInfo.compress_mode, fbLayerInfo.surface.stride, fbLayerInfo.is_discard_frame); } return HWC_SUCCESS; } int HWCIapiComImpl::GetHdrInfo(const hwc2_display_t display, HdrCap &hdrCap) const { #ifdef EXT_HDMI_SUPPORT uapi_hdmitx_id hdmiId; uapi_hdmitx_sink_info sinkCap; errno_t eok = memset_s(&sinkCap, sizeof(uapi_hdmitx_sink_info), 0, sizeof(uapi_hdmitx_sink_info)); HWC_CHK_RETURN(eok != EOK, HWC_FAILURE, ALOGE("GetHdrInfo sinkCap memset_s failed")); if (display == HWC_DISPLAY_PRIMARY) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_1 : UAPI_HDMITX_ID_0; } else if (display == HWC_DISPLAY_EXTERNAL) { hdmiId = m_switchDisplay ? UAPI_HDMITX_ID_0 : UAPI_HDMITX_ID_1; } else { ALOGE("GetHdrInfo: invalid display id:%" PRIu64, display); return HWC_FAILURE; } int ret = uapi_hdmitx_get_sink_info(hdmiId, &sinkCap); if (ret == HWC_FAILURE) { ALOGE("uapi_hdmitx_get_sink_info failed with ret:%d", ret); return ret; } unsigned int dolbySupport = 0; if ((sinkCap.dolby.support_v0 == TD_TRUE) || (sinkCap.dolby.support_v2 == TD_TRUE) || (sinkCap.dolby.support_v1 == TD_TRUE)) { dolbySupport = 1; } hdrCap.num = dolbySupport + (sinkCap.hdr.eotf.hdr10 ? 1 : 0) + (sinkCap.hdr.eotf.hlg ? 1 : 0); hdrCap.dolby = dolbySupport == 1 ? true : false; hdrCap.hdr10 = (sinkCap.hdr.eotf.hdr10 == TD_TRUE); hdrCap.hlg = (sinkCap.hdr.eotf.hlg == TD_TRUE); hdrCap.maxLuminance = sinkCap.hdr.static_metadata.max_lum_cv; hdrCap.maxAverageLuminance = sinkCap.hdr.static_metadata.aver_lum_cv; hdrCap.minLuminance = sinkCap.hdr.static_metadata.min_lum_cv; #else ALOGD("don't support hdmitx display: %d, hdr: %d", display == HWC_DISPLAY_PRIMARY, hdrCap.num); #endif return HWC_SUCCESS; } int64_t HWCIapiComImpl::GetVsyncTime(const int framebufferFd, unsigned int &freshRate) const { gfbg_vblank_info blankInfo; errno_t eok = memset_s(&blankInfo, sizeof(gfbg_vblank_info), 0, sizeof(gfbg_vblank_info)); HWC_CHK_RETURN(eok != EOK, HWC_FAILURE, ALOGE("GetVsyncTime blankInfo memset_s failed")); if (static_cast(ioctl(framebufferFd, GFBGIOGET_VBLANK, &blankInfo))) { ALOGE(" GFBGIOGET_VBLANK error"); return HWC_INVALID_VSYNC_TIME; } freshRate = blankInfo.refresh_rate / HWC_REFRESH_RATIO; return static_cast(blankInfo.time_val.tv_nsec); } bool HWCIapiComImpl::SupportModesCorrection(DisplayConfigs &configs, uint32_t config) const { ALOGI("add extension configModes on configs"); DisplayConfigs extensions; for (unsigned int i = 0; i < sizeof(SUPPORTFPS) / sizeof(SUPPORTFPS[0]); i++) { // copy the original modes, and change the fps. for (auto [key, value] : configs) { value.fps = SUPPORTFPS[i]; extensions.emplace(config++, value); } } configs.insert(extensions.cbegin(), extensions.cend()); return true; } int HWCIapiComImpl::InitDisplayConfigs(const hwc2_display_t display, DisplayConfigs &configs, const framebuffer_device_t &device, unsigned int &active) const { active = 0; configs.clear(); DisplayConfigInfo displayConfig = {device.width, device.height, device.xdpi, device.ydpi, device.fps}; configs.emplace(0, displayConfig); if (display == HWC_DISPLAY_EXTERNAL) { return HWC_SUCCESS; } int activeWidth = static_cast(device.width); int activeHeight = static_cast(device.height); char activeValue[PROPERTY_VALUE_MAX]; char *strPtr = nullptr; property_get("persist.vendor.display.mode", activeValue, ""); if (strlen(activeValue) != 0) { activeWidth = std::stoi(strtok_r(activeValue, "x", &strPtr)); char *ret = strtok_r(nullptr, "x", &strPtr); if (ret != nullptr) { activeHeight = std::stoi(ret); } else { ALOGE("strtok_r is null"); } } unsigned int config = 1; for (unsigned int i = 0; i < sizeof(RESOLUTIONS) / sizeof(RESOLUTIONS[0]); i++) { if ((device.width == RESOLUTIONS[i].width) && (device.height == RESOLUTIONS[i].height)) { // already added continue; } // the size of display config should not be larger than frame buffer size if ((device.width >= RESOLUTIONS[i].width) && (device.height >= RESOLUTIONS[i].height)) { DisplayConfigInfo displayConfigCandidate = { RESOLUTIONS[i].width, RESOLUTIONS[i].height, device.xdpi, device.ydpi, device.fps, }; configs.emplace(config, displayConfigCandidate); if ((activeWidth == static_cast(RESOLUTIONS[i].width)) && (activeHeight == static_cast(RESOLUTIONS[i].height))) { active = config; } config++; } } SupportModesCorrection(configs, config); ALOGI("InitDisplayConfigs with active config:%d for display:%" PRIu64, active, display); return HWC_SUCCESS; } bool HWCIapiComImpl::IsSupportGfx2dCompose() { if (m_capabilityInfo.total_layer_num <= GFX2D_COMPOSE_MIN_LAYER_COUNT) { ALOGI("gfx2d not support compose!"); return false; } return true; } bool HWCIapiComImpl::CheckLayerNum(const size_t layerSize) const { return layerSize > m_capabilityInfo.total_layer_num || layerSize <= 0; } bool HWCIapiComImpl::CheckLayerSize(const unsigned int cropWidth, const unsigned int cropHeight, const unsigned int dispWidth, const unsigned int dispHeight) const { if ((cropWidth == 0) || (cropHeight == 0) || (dispWidth == 0) || (dispHeight == 0) || cropHeight >= (dispHeight * m_capabilityInfo.max_horizontal_zme_ratio) || cropWidth >= (dispWidth * m_capabilityInfo.max_vertical_zme_ratio) || (cropWidth <= m_capabilityInfo.min_video_layer_width) || (cropHeight <= m_capabilityInfo.min_video_layer_height) || (dispWidth <= m_capabilityInfo.min_width) || (dispHeight <= m_capabilityInfo.min_height) || (dispWidth > m_capabilityInfo.max_width) || (dispHeight > m_capabilityInfo.max_height)) { return true; } return false; } bool HWCIapiComImpl::CheckResizeNum(const int layerNum, const int videoLayerNum) const { if (videoLayerNum == 0) { if (layerNum > m_capabilityInfo.graphic_layer_zme_num + m_capabilityInfo.video_layer_zme_num) { return true; } return false; } return layerNum > m_capabilityInfo.graphic_layer_zme_num || videoLayerNum > m_capabilityInfo.video_layer_zme_num; } void HWCIapiComImpl::SetDispPowerState(const int displayId, const HWC2::PowerMode mode) const { uapi_disp_power_state powerState; uapi_disp uapiDisplay; if (displayId == HWC_DISPLAY_PRIMARY) { uapiDisplay = m_switchDisplay ? UAPI_DISPLAY1 : UAPI_DISPLAY0; } else if (displayId == HWC_DISPLAY_EXTERNAL) { uapiDisplay = m_switchDisplay ? UAPI_DISPLAY0 : UAPI_DISPLAY1; } else { ALOGE("SetDispPowerState with bad displayId: %d", displayId); return; } if (mode == HWC2::PowerMode::Off || mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend) { powerState = UAPI_DISP_POWER_OFF; } if (mode == HWC2::PowerMode::On) { powerState = UAPI_DISP_POWER_ON; } int ret = uapi_disp_set_power_state(uapiDisplay, powerState); if (ret != TD_SUCCESS) { ALOGE("uapi_disp_set_power_state failed with return value %d", ret); } } } // namespace android