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