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.

1055 lines
44 KiB

/*
* 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 <cstring>
#include <securec.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <uapi_win.h>
#include <uapi_gfx2d.h>
#include <uapi_disp.h>
#ifdef EXT_HDMI_SUPPORT
#include <uapi_hdmitx.h>
#endif
#include <gfbg.h>
#include <soc_errno.h>
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<uapi_hdmitx_id>(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<td_u32>(hwcRect.right - hwcRect.left),
static_cast<td_u32>(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<int>(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<uapi_gfx2d_surface *>(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<uapi_gfx2d_surface *>(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<uapi_gfx2d_attr *>(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<const private_handle_t *>(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<td_u32>(layerSourceCrop.right - layerSourceCrop.left),
static_cast<td_u32>(layerSourceCrop.bottom - layerSourceCrop.top) };
srcSurface.out_rect = { layerDisplayFrame.left, layerDisplayFrame.top,
static_cast<td_u32>(layerDisplayFrame.right - layerDisplayFrame.left),
static_cast<td_u32>(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<const private_handle_t *>(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<const private_handle_t *>(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<const private_handle_t *>(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<bool>(ioctl(framebufferFd, GFBGIOGET_VBLANK, &blankInfo))) {
ALOGE(" GFBGIOGET_VBLANK error");
return HWC_INVALID_VSYNC_TIME;
}
freshRate = blankInfo.refresh_rate / HWC_REFRESH_RATIO;
return static_cast<int64_t>(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<int>(device.width);
int activeHeight = static_cast<int>(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<int>(RESOLUTIONS[i].width)) &&
(activeHeight == static_cast<int>(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