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