/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2016-2019. All rights reserved. * Description: Initialize hardware devices and implement some interfaces of hal * Author: Hisilicon * Created: 2016.08.12 */ #include "HWCDevice.h" #include #include #include #include #include #include #include #include #ifdef XCOLLIE_SUPPORT #include #endif #include "HWCIapiAdapter.h" #include "uapi_system.h" #include "uapi_disp.h" struct HwcModule { /* * Common methods of the hardware composer module. This *must* be the first member of * HwcModule as users of this structure will cast a hw_module_t to HwcModule pointer * in contexts where it's known the hw_module_t references a HwcModule. */ struct hw_module_t common; }; using HwcModuleT = HwcModule; static android::HWCDevice::HWCModuleMethods g_hwcModuleMethods; HwcModuleT HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .version_major = HwcCommon::HWCDEVICE_VERSION_MAJOR, .version_minor = HwcCommon::HWCDEVICE_VERSION_MINOR, .id = HWC_HARDWARE_MODULE_ID, .name = "hwcomposer", .author = "Hisilicon", .methods = &g_hwcModuleMethods, .dso = nullptr, .reserved = { 0 }, } }; namespace android { using std::string; #ifdef EXT_HDMI_SUPPORT static HWCDevice *g_hwcDevice = nullptr; static void HWCProcessHdmiEvent(hwc2_display_t displayId, HWC2::Connection state) { switch (state) { case HWC2::Connection::Connected: if (displayId == HWC_DISPLAY_EXTERNAL) { ALOGI("handle hdmi hotplug in for external display"); g_hwcDevice->SignalHotplug(displayId, HWC2::Connection::Connected); } else if (displayId == HWC_DISPLAY_PRIMARY) { ALOGI("ignore hdmi hotplug in for primary display"); } else { ALOGE("receive hdmi hotplug in from invalid display %" PRIu64, displayId); } break; case HWC2::Connection::Disconnected: if (displayId == HWC_DISPLAY_EXTERNAL) { ALOGI("handle hdmi hotplug out for external display"); g_hwcDevice->SignalHotplug(displayId, HWC2::Connection::Disconnected); } else if (displayId == HWC_DISPLAY_PRIMARY) { ALOGI("ignore hdmi hotplug out for primary display"); } else { ALOGE("ignore hotplug out from invalid display %" PRIu64, displayId); } break; default: break; } return; } #endif template static hwc2_function_pointer_t AsFP(T function) { static_assert(std::is_same::value, "Incompatible function pointer"); return reinterpret_cast(function); } // HWC2 functions returned in GetFunction Defined in the same order as in the HWC2 header static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges); } static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t *outLayerId) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, outLayerId); } static int32_t DestroyLayer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer); } static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display, hwc2_config_t *outConfig) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, outConfig); } static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumElements, hwc2_layer_t *outLayers, int32_t *outTypes) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes, outNumElements, outLayers, outTypes); } static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width, uint32_t height, int32_t format, int32_t dataSpace) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport, width, height, format, dataSpace); } static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumModes, int32_t *intOutModes) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, outNumModes, intOutModes); } static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display, hwc2_config_t config, int32_t intAttribute, int32_t *outValue) { auto attribute = static_cast(intAttribute); return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config, attribute, outValue); } static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumConfigs, hwc2_config_t *outConfigs) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs, outNumConfigs, outConfigs); } static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *outSize, char *outName) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, outSize, outName); } static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display, int32_t *outDisplayRequests, uint32_t *outNumElements, hwc2_layer_t *outLayers, int32_t *outLayerRequests) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests, outDisplayRequests, outNumElements, outLayers, outLayerRequests); } static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *outType) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, outType); } static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *outSupport) { HWC_CHK_RETURN((device == nullptr), HWC2_ERROR_NONE, ALOGE("getDozeSupport get null input")); if (display == HWC_DISPLAY_PRIMARY) { *outSupport = 1; } else { *outSupport = 0; } return HWC2_ERROR_NONE; } static int32_t GetHdrCapabilities(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumTypes, int32_t *outTypes, float *outMaxLuminance, float *outMaxAverageLuminance, float *outMinLuminance) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities, outNumTypes, outTypes, outMaxLuminance, outMaxAverageLuminance, outMinLuminance); } static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) { if (device == nullptr) { ALOGE("getMaxVirtualDisplayCount get null input"); } return MAX_VIRTUAL_DISP_COUNT; } static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumElements, hwc2_layer_t *outLayers, int32_t *outFences) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences, outNumElements, outLayers, outFences); } static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, uint32_t z) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z); } static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display, buffer_handle_t buffer, int32_t releaseFence) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetOutputBuffer, buffer, releaseFence); } static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t intMode) { auto mode = static_cast(intMode); return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode); } static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t intEnabled) { auto enabled = static_cast(intEnabled); return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled); } static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display, uint32_t *outNumTypes, uint32_t *outNumRequests) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::ValidateDisplay, outNumTypes, outNumRequests); } static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display, int32_t *outRetireFence) { #ifdef XCOLLIE_SUPPORT xcollie_t id = xcollie_start(HWC_XCOLLIE_TIME_OUT, NULL, NULL); #endif int32_t ret = HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::PresentDisplay, outRetireFence); #ifdef XCOLLIE_SUPPORT xcollie_end(id); #endif return ret; } static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display, hwc2_config_t config) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config); } static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display, buffer_handle_t target, int32_t acquireFence, int32_t dataSpace, hwc_region_t damage) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target, acquireFence, dataSpace, damage); } static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display, int32_t intMode) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, intMode); } static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display, const float *matrix, int32_t hint) { android_color_transform_t transformHint = static_cast(hint); return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix, transformHint); } static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, int32_t x, int32_t y) { return HWCDevice::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition, layer, x, y); } static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) { auto mode = static_cast(intMode); return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode); } static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, buffer_handle_t buffer, int32_t acquireFence) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer, acquireFence); } static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color); } static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, int32_t intType) { auto type = static_cast(intType); return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType, type); } static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, int32_t intdataSpace) { auto dataSpace = static_cast(intdataSpace); return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace, dataSpace); } static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, hwc_rect_t frame) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame, frame); } static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, float alpha) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha, alpha); } static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, hwc_frect_t crop) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop); } static int32_t SetLayerSidebandStream(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer, const native_handle_t* stream) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSidebandStream, stream); } static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, hwc_region_t damage) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage, damage); } static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) { auto transform = static_cast(intTransform); return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform, transform); } static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, hwc_region_t visible) { return HWCDevice::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion, visible); } static int LoadFbHalModule(const int fbDevNum, framebuffer_device_t **ppfbDevice) { HWC_CHK_RETURN((ppfbDevice == nullptr), TD_FAILURE, ALOGE("LoadFbHalModule the fb_device is null")); hw_module_t *module = nullptr; int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, const_cast(&module)); HWC_CHK_RETURN((err != 0), err, ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID)); module->reserved[0] = fbDevNum; int ret = framebuffer_open(module, ppfbDevice); if (ret == HWC_SUCCESS) { private_module_t *pModule = reinterpret_cast((*ppfbDevice)->common.module); ALOGI("LoadFbHalModule fb%d buffer num =%d width = %d, height = %d", fbDevNum, pModule->numBuffers[fbDevNum], (*ppfbDevice)->width, (*ppfbDevice)->height); } return ret; } HWCDevice::HWCDevice(const hw_module_t *module) { HWC_CHK_PRINTF((module == nullptr), ALOGE("HWC:HWCDevice get null input")); hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG; hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0; hwc2_device_t::common.module = const_cast(module); hwc2_device_t::common.close = Close; hwc2_device_t::getCapabilities = GetCapabilities; hwc2_device_t::getFunction = GetFunction; } HWCDevice::~HWCDevice() { for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) { delete m_hwcDisplay[i]; m_hwcDisplay[i] = nullptr; } } hwc2_function_pointer_t HWCDevice::GetFunction(struct hwc2_device *device, int32_t intDescriptor) { HWC_CHK_RETURN((device == nullptr), nullptr, ALOGE("HWC:GetFunction get null input")); auto descriptor = static_cast(intDescriptor); switch (descriptor) { case HWC2::FunctionDescriptor::AcceptDisplayChanges: return AsFP(AcceptDisplayChanges); case HWC2::FunctionDescriptor::CreateLayer: return AsFP(CreateLayer); case HWC2::FunctionDescriptor::DestroyLayer: return AsFP(DestroyLayer); case HWC2::FunctionDescriptor::GetActiveConfig: return AsFP(GetActiveConfig); case HWC2::FunctionDescriptor::GetChangedCompositionTypes: return AsFP(GetChangedCompositionTypes); case HWC2::FunctionDescriptor::GetClientTargetSupport: return AsFP(GetClientTargetSupport); case HWC2::FunctionDescriptor::GetColorModes: return AsFP(GetColorModes); case HWC2::FunctionDescriptor::GetDisplayAttribute: return AsFP(GetDisplayAttribute); case HWC2::FunctionDescriptor::GetDisplayConfigs: return AsFP(GetDisplayConfigs); case HWC2::FunctionDescriptor::GetDisplayName: return AsFP(GetDisplayName); case HWC2::FunctionDescriptor::GetDisplayRequests: return AsFP(GetDisplayRequests); case HWC2::FunctionDescriptor::GetDisplayType: return AsFP(GetDisplayType); case HWC2::FunctionDescriptor::GetHdrCapabilities: return AsFP(GetHdrCapabilities); case HWC2::FunctionDescriptor::GetDozeSupport: return AsFP(GetDozeSupport); case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount: return AsFP(GetMaxVirtualDisplayCount); case HWC2::FunctionDescriptor::GetReleaseFences: return AsFP(GetReleaseFences); case HWC2::FunctionDescriptor::PresentDisplay: return AsFP(PresentDisplay); case HWC2::FunctionDescriptor::SetActiveConfig: return AsFP(SetActiveConfig); case HWC2::FunctionDescriptor::SetClientTarget: return AsFP(SetClientTarget); case HWC2::FunctionDescriptor::SetColorMode: return AsFP(SetColorMode); case HWC2::FunctionDescriptor::SetColorTransform: return AsFP(SetColorTransform); case HWC2::FunctionDescriptor::SetCursorPosition: return AsFP(SetCursorPosition); case HWC2::FunctionDescriptor::SetLayerBlendMode: return AsFP(SetLayerBlendMode); case HWC2::FunctionDescriptor::SetLayerBuffer: return AsFP(SetLayerBuffer); case HWC2::FunctionDescriptor::SetLayerColor: return AsFP(SetLayerColor); case HWC2::FunctionDescriptor::SetLayerCompositionType: return AsFP(SetLayerCompositionType); case HWC2::FunctionDescriptor::SetLayerDataspace: return AsFP(SetLayerDataspace); case HWC2::FunctionDescriptor::SetLayerDisplayFrame: return AsFP(SetLayerDisplayFrame); case HWC2::FunctionDescriptor::SetLayerPlaneAlpha: return AsFP(SetLayerPlaneAlpha); case HWC2::FunctionDescriptor::SetLayerSidebandStream: return AsFP(SetLayerSidebandStream); case HWC2::FunctionDescriptor::SetLayerSourceCrop: return AsFP(SetLayerSourceCrop); case HWC2::FunctionDescriptor::SetLayerSurfaceDamage: return AsFP(SetLayerSurfaceDamage); case HWC2::FunctionDescriptor::SetLayerTransform: return AsFP(SetLayerTransform); case HWC2::FunctionDescriptor::SetLayerVisibleRegion: return AsFP(SetLayerVisibleRegion); case HWC2::FunctionDescriptor::SetLayerZOrder: return AsFP(SetLayerZOrder); case HWC2::FunctionDescriptor::SetOutputBuffer: return AsFP(SetOutputBuffer); case HWC2::FunctionDescriptor::SetPowerMode: return AsFP(SetPowerMode); case HWC2::FunctionDescriptor::SetVsyncEnabled: return AsFP(SetVsyncEnabled); case HWC2::FunctionDescriptor::ValidateDisplay: return AsFP(ValidateDisplay); case HWC2::FunctionDescriptor::DestroyVirtualDisplay: return AsFP(HWCDevice::DestroyVirtualDisplay); case HWC2::FunctionDescriptor::CreateVirtualDisplay: return AsFP(HWCDevice::CreateVirtualDisplay); case HWC2::FunctionDescriptor::Dump: return AsFP(HWCDevice::Dump); case HWC2::FunctionDescriptor::RegisterCallback: return AsFP(HWCDevice::RegisterCallback); default: ALOGD("Unknown/Unimplemented function descriptor: %d (%s)", intDescriptor, to_string(descriptor).c_str()); return nullptr; } return nullptr; } void HWCDevice::GetCapabilities(struct hwc2_device *device, uint32_t *outCount, int32_t *outCapabilities) { HWC_CHK_RETURN_NOT_VALUE(device == nullptr || outCount == nullptr); if (outCapabilities != nullptr && *outCount >= 1) { outCapabilities[0] = HWC2_CAPABILITY_SIDEBAND_STREAM; } *outCount = 1; } int32_t HWCDevice::RegisterCallback(hwc2_device_t *device, int32_t descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { HWC_CHK_RETURN((device == nullptr), HWC2_ERROR_BAD_DISPLAY, ALOGE("HWC RegisterCallback device is null")); HWCDevice *hwcDevice = static_cast(device); auto desc = static_cast(descriptor); auto error = hwcDevice->Register(desc, callbackData, pointer); if (descriptor == HWC2_CALLBACK_HOTPLUG) { hwcDevice->SignalHotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected); #ifdef EXT_DOUBLE_DISPLAY_SUPPORT if (hwcDevice->m_externalDisplayEnabled && hwcDevice->m_fbDevices[HWC_DISPLAY_EXTERNAL] != nullptr && HWCIapiAdapter::GetInstance().IsDisplayConnected(HWC_DISPLAY_EXTERNAL)) { hwcDevice->SignalHotplug(HWC_DISPLAY_EXTERNAL, HWC2::Connection::Connected); } #endif } return int32_t(error); } int32_t HWCDevice::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height, int32_t *format, hwc2_display_t *outDisplayDid) { HWC_CHK_RETURN((device == nullptr), HWC2_ERROR_BAD_PARAMETER, ALOGE("CreateVirtualDisplay devices is null")); HWC_CHK_RETURN((outDisplayDid == nullptr), HWC2_ERROR_BAD_PARAMETER, ALOGE("CreateVirtualDisplay outDisplayDid is nullptr")); HWCDevice *hwcDevice = static_cast(device); auto status = hwcDevice->CreateVirtualDisplayObject(width, height, format); if (status == HWC2::Error::None) { *outDisplayDid = HWC_DISPLAY_VIRTUAL; ALOGI("Created virtual display id:%" PRIu64 " with res: %dx%d", *outDisplayDid, width, height); } else { ALOGE("Failed to create virtual display: %s", to_string(status).c_str()); } return int32_t(status); } HWC2::Error HWCDevice::CreateVirtualDisplayObject(uint32_t width, uint32_t height, const int32_t *format) { UNUSED(format); HWC_CHK_RETURN(m_hwcDisplay[HWC_DISPLAY_VIRTUAL] != nullptr, HWC2::Error::NoResources); DisplayConfigInfo displayConfigInfo; displayConfigInfo.width = width; displayConfigInfo.height = height; displayConfigInfo.xDpi = m_fbDevices[HWC_DISPLAY_PRIMARY]->xdpi; displayConfigInfo.yDpi = m_fbDevices[HWC_DISPLAY_PRIMARY]->ydpi; displayConfigInfo.fps = m_fbDevices[HWC_DISPLAY_PRIMARY]->fps; m_hwcDisplay[HWC_DISPLAY_VIRTUAL] = new HWCDisplay(DisplayType::DISPLAY_VIRTUAL, HWC_DISPLAY_VIRTUAL, displayConfigInfo); m_hwcDisplay[HWC_DISPLAY_VIRTUAL]->Init(); return HWC2::Error::None; } int32_t HWCDevice::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) { HWC_CHK_RETURN((device == nullptr), HWC2_ERROR_BAD_DISPLAY, ALOGE("DestroyVirtualDisplay device is null")); ALOGI("Destroying virtual display id:%" PRIu64, display); auto *hwcDevice = static_cast(device); HWC_CHK_RETURN((hwcDevice->m_hwcDisplay[display] == nullptr), HWC2_ERROR_BAD_DISPLAY, ALOGE("DestroyVirtualDisplay hwcDevice->m_hwcDisplay is null")); delete hwcDevice->m_hwcDisplay[display]; hwcDevice->m_hwcDisplay[display] = nullptr; return HWC2_ERROR_NONE; } void HWCDevice::Dump(hwc2_device_t *device, uint32_t *outSize, char *outBuffer) { HWC_CHK_RETURN_NOT_VALUE(device == nullptr || outSize == nullptr); auto *hwcDevice = static_cast(device); if (outBuffer == nullptr) { *outSize = HWC_DUMP_SIZE; } else { std::string s(""); for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) { if (hwcDevice->m_hwcDisplay[id]) { s += hwcDevice->m_hwcDisplay[id]->Dump(); } } errno_t ret = strncpy_s(outBuffer, HWC_DUMP_SIZE + 1, s.c_str(), s.size()); HWC_CHK_RETURN_NOT_VALUE((ret != EOK), ALOGE("ERR :%s LINE %d | Dump strncpy_s ret(%x)", __FUNCTION__, __LINE__, ret)); *outSize = (s.size() > HWC_DUMP_SIZE) ? HWC_DUMP_SIZE : s.size(); } return; } int HWCDevice::Init() { ALOGI("HWC enter Init"); td_s32 sysInit = uapi_sys_init(); if (sysInit != TD_SUCCESS) { ALOGE("Init uapi_sys_init failed"); return HWC_FAILURE; } else { uapi_sys_deinit(); } int ret = HWCIapiAdapter::GetInstance().InitIapiModules(); HWC_CHK_PRINTF((ret != HWC_SUCCESS), ALOGE("HWCDevice InitIapiModules failed %d", ret)); // create primary hwc display const int primFbDevId = HWCIapiAdapter::GetInstance().GetFbDevId(HWC_DISPLAY_PRIMARY); int fberr = LoadFbHalModule(primFbDevId, &m_fbDevices[HWC_DISPLAY_PRIMARY]); HWC_CHK_RETURN((fberr != HWC_SUCCESS), HWC_FAILURE, ALOGE("primary failed to open fb%d", primFbDevId)); bool gfx2dEnabled = HWCIapiAdapter::GetInstance().OpenGfx2dAndInitCapability() == HWC_SUCCESS && HWCIapiAdapter::GetInstance().IsSupportGfx2dCompose(); bool gfx2dCompose = gfx2dEnabled && property_get_bool("ro.vendor.gfx.gfx2d.compose", true); m_hwcDisplay[HWC_DISPLAY_PRIMARY] = new HWCDisplay(DisplayType::DISPLAY_PRIMARY, HWC_DISPLAY_PRIMARY, m_fbDevices[HWC_DISPLAY_PRIMARY], gfx2dCompose, &m_hwcCallbacks); m_hwcDisplay[HWC_DISPLAY_PRIMARY]->Init(); #ifdef EXT_DOUBLE_DISPLAY_SUPPORT // create external hwc display bool isExtDisplayEnable = false; uapi_disp_state dispStatus = {}; ret = HWCIapiAdapter::GetInstance().GetExternalDisplayStatus(&dispStatus); if (ret != HWC_SUCCESS) { ALOGE("uapi_disp_get_state fail(ret=0x%X)!", ret); } else { isExtDisplayEnable = dispStatus.is_open; // is_slave is false mean different display ALOGI("support external display? :%d , is different?%d", dispStatus.is_open, dispStatus.is_slave); } if (isExtDisplayEnable && static_cast(property_get_bool("ro.vendor.gfx.hwc.support.ext", true))) { int extFbDevId = HWCIapiAdapter::GetInstance().GetFbDevId(HWC_DISPLAY_EXTERNAL); fberr = LoadFbHalModule(extFbDevId, &m_fbDevices[HWC_DISPLAY_EXTERNAL]); ALOGI("get ext fb device id:%d", extFbDevId); HWC_CHK_RETURN((fberr != HWC_SUCCESS), HWC_FAILURE, ALOGE("ext failed to open fb%d", extFbDevId)); bool gfx2dComposeExt = gfx2dEnabled && property_get_bool("ro.vendor.gfx.gfx2d.compose.ext", true); m_hwcDisplay[HWC_DISPLAY_EXTERNAL] = new HWCDisplay(DisplayType::DISPLAY_EXTERNAL, HWC_DISPLAY_EXTERNAL, m_fbDevices[HWC_DISPLAY_EXTERNAL], gfx2dComposeExt, &m_hwcCallbacks); m_hwcDisplay[HWC_DISPLAY_EXTERNAL]->Init(); m_externalDisplayEnabled = true; } else { ALOGI("external display was not enabled"); } #endif #ifdef XCOLLIE_SUPPORT xcollie_init(); #endif return HWC_SUCCESS; } int HWCDevice::Open(const struct hw_module_t *module, const char *name, struct hw_device_t **device) { ALOGI("enter hwc module"); td_s32 sysInit = uapi_sys_init(); if (sysInit != TD_SUCCESS) { ALOGE("Open uapi_sys_init failed"); return HWC_FAILURE; } else { uapi_sys_deinit(); } HWC_CHK_RETURN(module == nullptr || name == nullptr || device == nullptr, HWC_FAILURE, ALOGE("Open Invalid parameters.")); string composerName = HWC_HARDWARE_COMPOSER; if (strncmp(name, composerName.c_str(), composerName.length()) == 0) { HWCDevice *hwcDevice = new HWCDevice(module); HWC_CHK_RETURN((hwcDevice == nullptr), HWC_FAILURE, ALOGE("device open failed, hwcdevice is null")); int status = hwcDevice->Init(); if (status != 0) { delete hwcDevice; hwcDevice = nullptr; return status; } #ifdef EXT_HDMI_SUPPORT g_hwcDevice = hwcDevice; // pure android should not response to hdmi plug event int ret = HWCIapiAdapter::GetInstance().RegisterHdmiCallback(HWC_DISPLAY_PRIMARY, HWCProcessHdmiEvent); if (ret != HWC_SUCCESS) { ALOGE("hdmi reg hdmi0 failed:%#x", ret); } #ifdef EXT_DOUBLE_DISPLAY_SUPPORT if (hwcDevice->m_externalDisplayEnabled) { ret = HWCIapiAdapter::GetInstance().RegisterHdmiCallback(HWC_DISPLAY_EXTERNAL, HWCProcessHdmiEvent); if (ret != HWC_SUCCESS) { ALOGE("hdmi reg hdmi1 failed:%#x", ret); } } #endif #endif *device = &(hwcDevice->common); } return HWC_SUCCESS; } int HWCDevice::Close(struct hw_device_t *dev) { ALOGI("HWC enter Close"); HWC_CHK_RETURN(dev == nullptr, -EINVAL); auto *hwcDevice = reinterpret_cast(dev); for (int i = 0; i < HWC_NUM_PHYSICAL_DISPLAY_TYPES; i++) { if (hwcDevice->m_fbDevices[i] != nullptr) { framebuffer_close(hwcDevice->m_fbDevices[i]); free(hwcDevice->m_fbDevices); hwcDevice->m_fbDevices[i] = nullptr; } } #ifdef EXT_GFX2D_SUPPORT if (HWCIapiAdapter::GetInstance().CloseGfx2d() != HWC_SUCCESS) { ALOGE("close gfx2d failed!"); } #endif #ifdef EXT_HDMI_SUPPORT g_hwcDevice = nullptr; if (HWCIapiAdapter::GetInstance().UnregisterHdmiCallback(HWC_DISPLAY_PRIMARY) != HWC_SUCCESS) { ALOGE("primary display unregister hdmi callback failed!"); } #ifdef EXT_DOUBLE_DISPLAY_SUPPORT if (hwcDevice->m_externalDisplayEnabled) { if (HWCIapiAdapter::GetInstance().UnregisterHdmiCallback(HWC_DISPLAY_EXTERNAL) != HWC_SUCCESS) { ALOGE("external display unregister hdmi callback failed!"); } } #endif #endif int ret = HWCIapiAdapter::GetInstance().DeInitIapiModules(); HWC_CHK_PRINTF((ret != HWC_SUCCESS), ALOGE("HWC UAPI_VO_DeInit failed")); if (hwcDevice != nullptr) { delete hwcDevice; hwcDevice = nullptr; } return TD_SUCCESS; } void HWCDevice::SignalHotplug(hwc2_display_t display, HWC2::Connection state) { m_hwcCallbacks.Hotplug(display, state); } void HWCDevice::SignalRefresh(hwc2_display_t display) { m_hwcCallbacks.Refresh(display); } void HWCDevice::SignalVsync(hwc2_display_t display, int64_t timestamp) { m_hwcCallbacks.Vsync(display, timestamp); } HWC2::Error HWCDevice::Register(HWC2::Callback desc, hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { return m_hwcCallbacks.Register(desc, callbackData, pointer); } } // namespace android