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.

752 lines
31 KiB

/*
* 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 <cerrno>
#include <cstdlib>
#include <fcntl.h>
#include <hardware/hardware.h>
#include <log/log.h>
#include <utils/Errors.h>
#include <securec.h>
#include <cutils/properties.h>
#ifdef XCOLLIE_SUPPORT
#include <xcollie.h>
#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<typename PFN, typename T>
static hwc2_function_pointer_t AsFP(T function)
{
static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
return reinterpret_cast<hwc2_function_pointer_t>(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<HWC2::Attribute>(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<HWC2::PowerMode>(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<HWC2::Vsync>(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<android_color_transform_t>(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<HWC2::BlendMode>(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<HWC2::Composition>(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<android_dataspace_t>(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<HWC2::Transform>(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<const hw_module_t **>(&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<private_module_t *>((*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<hw_module_t *>(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<HWC2::FunctionDescriptor>(intDescriptor);
switch (descriptor) {
case HWC2::FunctionDescriptor::AcceptDisplayChanges:
return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(AcceptDisplayChanges);
case HWC2::FunctionDescriptor::CreateLayer:
return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
case HWC2::FunctionDescriptor::DestroyLayer:
return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
case HWC2::FunctionDescriptor::GetActiveConfig:
return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
case HWC2::FunctionDescriptor::GetClientTargetSupport:
return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
case HWC2::FunctionDescriptor::GetColorModes:
return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
case HWC2::FunctionDescriptor::GetDisplayAttribute:
return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
case HWC2::FunctionDescriptor::GetDisplayConfigs:
return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
case HWC2::FunctionDescriptor::GetDisplayName:
return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
case HWC2::FunctionDescriptor::GetDisplayRequests:
return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
case HWC2::FunctionDescriptor::GetDisplayType:
return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
case HWC2::FunctionDescriptor::GetHdrCapabilities:
return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
case HWC2::FunctionDescriptor::GetDozeSupport:
return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount);
case HWC2::FunctionDescriptor::GetReleaseFences:
return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
case HWC2::FunctionDescriptor::PresentDisplay:
return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
case HWC2::FunctionDescriptor::SetActiveConfig:
return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
case HWC2::FunctionDescriptor::SetClientTarget:
return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
case HWC2::FunctionDescriptor::SetColorMode:
return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
case HWC2::FunctionDescriptor::SetColorTransform:
return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
case HWC2::FunctionDescriptor::SetCursorPosition:
return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
case HWC2::FunctionDescriptor::SetLayerBlendMode:
return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
case HWC2::FunctionDescriptor::SetLayerBuffer:
return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
case HWC2::FunctionDescriptor::SetLayerColor:
return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
case HWC2::FunctionDescriptor::SetLayerCompositionType:
return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
case HWC2::FunctionDescriptor::SetLayerDataspace:
return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
case HWC2::FunctionDescriptor::SetLayerSidebandStream:
return AsFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(SetLayerSidebandStream);
case HWC2::FunctionDescriptor::SetLayerSourceCrop:
return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
case HWC2::FunctionDescriptor::SetLayerTransform:
return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
case HWC2::FunctionDescriptor::SetLayerZOrder:
return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
case HWC2::FunctionDescriptor::SetOutputBuffer:
return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
case HWC2::FunctionDescriptor::SetPowerMode:
return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
case HWC2::FunctionDescriptor::SetVsyncEnabled:
return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
case HWC2::FunctionDescriptor::ValidateDisplay:
return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(ValidateDisplay);
case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCDevice::DestroyVirtualDisplay);
case HWC2::FunctionDescriptor::CreateVirtualDisplay:
return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCDevice::CreateVirtualDisplay);
case HWC2::FunctionDescriptor::Dump:
return AsFP<HWC2_PFN_DUMP>(HWCDevice::Dump);
case HWC2::FunctionDescriptor::RegisterCallback:
return AsFP<HWC2_PFN_REGISTER_CALLBACK>(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<HWCDevice *>(device);
auto desc = static_cast<HWC2::Callback>(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<HWCDevice *>(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<HWCDevice *>(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<HWCDevice *>(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<bool>(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<HWCDevice *>(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