diff --git a/build/BUILD.gn b/build/BUILD.gn index 2a5bf2c45b85c8c9f22bb7cb98b26f1dec446f9b..86a380fa7ead15d89a33531d518234f3ad24a1c5 100755 --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -20,6 +20,6 @@ group("products_group") { } deps += [ - "//device/rockchip/common:common_group", + "//device/rockchip/hardware:hardware_group", ] } diff --git a/common/BUILD.gn b/hardware/BUILD.gn similarity index 94% rename from common/BUILD.gn rename to hardware/BUILD.gn index 0288373acc824dfe52e774a3f4877779b081f310..4388a2da9d5d52bfd16ecf22b4c372ab74bf0ba2 100755 --- a/common/BUILD.gn +++ b/hardware/BUILD.gn @@ -13,8 +13,7 @@ import("//build/ohos.gni") -print("common_group in") -group("common_group") { +group("hardware_group") { deps = [ "//device/rockchip/hardware/wifi:ap6xxx", "//device/rockchip/hardware/isp:isp", diff --git a/hardware/display/BUILD.gn b/hardware/display/BUILD.gn old mode 100755 new mode 100644 index 41fc1ddd76a1842f46b1f1224c80833950cfedb6..5b423bb2bd3712d019c4f59ce7ca6ca6bc4141a5 --- a/hardware/display/BUILD.gn +++ b/hardware/display/BUILD.gn @@ -12,62 +12,150 @@ # limitations under the License. import("//build/ohos.gni") -import("//build/ohos/ndk/ndk.gni") -ohos_prebuilt_shared_library("display_gralloc") { - if (target_cpu == "arm") { - source = "lib/libdisplay_gralloc.z.so" - } else if (target_cpu == "arm64") { - source = "lib64/libdisplay_gralloc.z.so" - } - subsystem_name = "hdf" - part_name = "hdf" - install_enable = true - # output_name = "display_gralloc.z" +group("display_group") { + deps = [ + ":display_device", + ":display_gralloc", + ":display_gfx", + ":higbm", + ] } -ohos_prebuilt_shared_library("display_gfx") { - if (target_cpu == "arm") { - source = "lib/libdisplay_gfx.z.so" - } else if (target_cpu == "arm64") { - source = "lib64/libdisplay_gfx.z.so" - } - subsystem_name = "hdf" - part_name = "hdf" - install_enable = true - # output_name = "display_gfx.z" +ohos_static_library("higbm") { + sources = [ "src/display_gralloc/hi_gbm.c" ] + include_dirs = [ + "include", + "//utils/native/base/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ] + output_name = "higbm" + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + deps = [ + "//third_party/libdrm:libdrm", + "//utils/native/base:utils", + ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] } -ohos_prebuilt_shared_library("display_device_drm") { - if (target_cpu == "arm") { - source = "lib/libdisplay_device_drm.z.so" - } else if (target_cpu == "arm64") { - source = "lib64/libdisplay_device_drm.z.so" - } +ohos_shared_library("display_gralloc") { + sources = [ + "src/display_gralloc/display_gralloc.c", + "src/display_gralloc/display_gralloc_gbm.c", + "src/display_gralloc/wayland_drm_auth_client.c", + ] + include_dirs = [ + "include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + "//drivers/framework/include/utils", + "//drivers/adapter/uhdf2/osal/include", + "//utils/native/base/include", + "//foundation/graphic/standard/utils/include", + "//foundation/graphic/standard/prebuilts/librarys/drm/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ] + output_name = "display_gralloc" + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + deps = [ + ":higbm", + "//third_party/libdrm:libdrm", + "//third_party/wayland_standard:libwayland_client", + "//third_party/weston:drm_auth_protocol", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + install_enable = true subsystem_name = "hdf" part_name = "hdf" - install_enable = true - # output_name = "display_device_drm.z" } -ohos_prebuilt_shared_library("display_device") { - if (target_cpu == "arm") { - source = "lib/libdisplay_device.z.so" - } else if (target_cpu == "arm64") { - source = "lib64/libdisplay_device.z.so" - } +ohos_shared_library("display_gfx") { + sources = [ "src/display_gfx/display_gfx.c" ] + include_dirs = [ + "include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + "//drivers/framework/include/utils", + "//drivers/adapter/uhdf2/adapter/osal/include/", + "//utils/native/base/include", + "//foundation/graphic/standard/utils/include", + "//device/rockchip/hardware/rga/include/", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ] + output_name = "display_gfx" + cflags = [ "-Wno-macro-redefined" ] + deps = [ + ":display_gralloc", + "//utils/native/base:utils", + "//device/rockchip/hardware/rga:librga", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + install_enable = true subsystem_name = "hdf" part_name = "hdf" - install_enable = true - # output_name = "display_device_drm.z" } -ohos_prebuilt_shared_library("display_layer") { - if (target_cpu == "arm") { - source = "lib/libdisplay_layer.z.so" - } +ohos_shared_library("display_device") { + sources = [ + "src/display_device/drm_connector.cpp", + "src/display_device/drm_crtc.cpp", + "src/display_device/drm_device.cpp", + "src/display_device/drm_display.cpp", + "src/display_device/drm_encoder.cpp", + "src/display_device/drm_plane.cpp", + "src/display_device/drm_vsync_worker.cpp", + "src/display_device/hdi_composer.cpp", + "src/display_device/hdi_device_interface.cpp", + "src/display_device/hdi_display.cpp", + "src/display_device/hdi_drm_composition.cpp", + "src/display_device/hdi_drm_layer.cpp", + "src/display_device/hdi_gfx_composition.cpp", + "src/display_device/hdi_layer.cpp", + "src/display_device/hdi_session.cpp", + ] + output_name = "display_device" + include_dirs = [ + "src/display_device", + "include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + "//drivers/framework/include/utils", + "//drivers/adapter/uhdf2/osal/include", + "//utils/native/base/include", + "//foundation/graphic/standard/utils/include", + "//foundation/graphic/standard/prebuilts/librarys/drm/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ] + deps = [ + ":display_gfx", + ":display_gralloc", + "//third_party/libdrm:libdrm", + "//utils/native/base:utils", + ] + cflags = [ "-Wno-unused-function" ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + install_enable = true subsystem_name = "hdf" part_name = "hdf" - install_enable = true - # output_name = "display_device_drm.z" +} + +group("display_layer") { + deps = [ + ":display_device", + ":display_gralloc", + ":display_gfx", + ":higbm", + ] } diff --git a/hardware/display/include/display_common.h b/hardware/display/include/display_common.h new file mode 100644 index 0000000000000000000000000000000000000000..316ce7e9325f4ca5c59c618916cf4e334731a262 --- /dev/null +++ b/hardware/display/include/display_common.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISP_COMMON_H +#define DISP_COMMON_H +#include +#include +#include "hilog/log.h" +#include "stdio.h" +#ifdef HDF_LOG_TAG +#undef HDF_LOG_TAG +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +#undef LOG_TAG +#undef LOG_DOMAIN +#define LOG_TAG "DISP" +#define LOG_DOMAIN 0xD001400 + +#ifndef DISPLAY_UNUSED +#define DISPLAY_UNUSED(x) (void)x +#endif + +#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__) + +#ifndef DISPLAY_LOGD +#define DISPLAY_LOGD(format, ...) \ + do { \ + HILOG_DEBUG(LOG_CORE, "[%{public}s@%{public}s:%{public}d] " format "\n", __FUNCTION__, __FILENAME__, __LINE__, \ + ##__VA_ARGS__); \ + } while (0) +#endif + +#ifndef DISPLAY_LOGI +#define DISPLAY_LOGI(format, ...) \ + do { \ + HILOG_INFO(LOG_CORE, "[%{public}s@%{public}s:%{public}d] " format "\n", __FUNCTION__, __FILENAME__, __LINE__, \ + ##__VA_ARGS__); \ + } while (0) +#endif + +#ifndef DISPLAY_LOGW +#define DISPLAY_LOGW(format, ...) \ + do { \ + HILOG_WARN(LOG_CORE, "[%{public}s@%{public}s:%{public}d] " format "\n", __FUNCTION__, __FILENAME__, __LINE__, \ + ##__VA_ARGS__); \ + } while (0) +#endif + +#ifndef DISPLAY_LOGE +#define DISPLAY_LOGE(format, ...) \ + do { \ + HILOG_ERROR(LOG_CORE, \ + "\033[0;32;31m" \ + "[%{public}s@%{public}s:%{public}d] " format "\033[m" \ + "\n", \ + __FUNCTION__, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + } while (0) +#endif + +#ifndef CHECK_NULLPOINTER_RETURN_VALUE +#define CHECK_NULLPOINTER_RETURN_VALUE(pointer, ret) \ + do { \ + if ((pointer) == NULL) { \ + DISPLAY_LOGE("pointer is null and return ret\n"); \ + return (ret); \ + } \ + } while (0) +#endif + +#ifndef CHECK_NULLPOINTER_RETURN +#define CHECK_NULLPOINTER_RETURN(pointer) \ + do { \ + if ((pointer) == NULL) { \ + DISPLAY_LOGE("pointer is null and return\n"); \ + return; \ + } \ + } while (0) +#endif + +#ifndef DISPLAY_CHK_RETURN +#define DISPLAY_CHK_RETURN(val, ret, ...) \ + do { \ + if (val) { \ + __VA_ARGS__; \ + return (ret); \ + } \ + } while (0) +#endif + +#ifndef DISPLAY_CHK_RETURN_NOT_VALUE +#define DISPLAY_CHK_RETURN_NOT_VALUE(val, ret, ...) \ + do { \ + if (val) { \ + __VA_ARGS__; \ + return; \ + } \ + } while (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* DISP_COMMON_H */ diff --git a/hardware/display/include/display_gralloc_private.h b/hardware/display/include/display_gralloc_private.h new file mode 100644 index 0000000000000000000000000000000000000000..e5ce9e0cefa946019050cd4a37de2c428dad1a50 --- /dev/null +++ b/hardware/display/include/display_gralloc_private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISPLAY_GRALLOC_INTERNAL_H +#define DISPLAY_GRALLOC_INTERNAL_H +#include "display_type.h" +#ifdef __cplusplus +extern "C" { +#endif +#define GRALLOC_NUM_FDS 1 +#define GRALLOC_NUM_INTS ((sizeof(struct PrivBufferHandle) - sizeof(BufferHandle)) / sizeof(int) - GRALLOC_NUM_FDS) + +#define INVALID_PIXEL_FMT 0 + +typedef struct { + BufferHandle hdl; +} PriBufferHandle; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/hardware/display/lib/libdisplay_device.z.so b/hardware/display/lib/libdisplay_device.z.so deleted file mode 100644 index 697f706903fe1616281aba4e61e43110046b61a6..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib/libdisplay_device.z.so and /dev/null differ diff --git a/hardware/display/lib/libdisplay_device_drm.z.so b/hardware/display/lib/libdisplay_device_drm.z.so deleted file mode 100644 index 3d9174f4843f936cae6711c1cf8515ba41b46506..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib/libdisplay_device_drm.z.so and /dev/null differ diff --git a/hardware/display/lib/libdisplay_gfx.z.so b/hardware/display/lib/libdisplay_gfx.z.so deleted file mode 100644 index 16d562d0d83c4ca8b7997be67410cfdfec9940f2..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib/libdisplay_gfx.z.so and /dev/null differ diff --git a/hardware/display/lib/libdisplay_gralloc.z.so b/hardware/display/lib/libdisplay_gralloc.z.so deleted file mode 100644 index ffe7315cd6e4f02813b23413712a4c9ca9323572..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib/libdisplay_gralloc.z.so and /dev/null differ diff --git a/hardware/display/lib/libdisplay_layer.z.so b/hardware/display/lib/libdisplay_layer.z.so deleted file mode 100644 index 53705e692dbf28533165d7d9ba61eb29863bca58..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib/libdisplay_layer.z.so and /dev/null differ diff --git a/hardware/display/lib64/libdisplay_device.z.so b/hardware/display/lib64/libdisplay_device.z.so deleted file mode 100644 index 86030b399877ca5a7cd69ab5476be2eacb8028d8..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib64/libdisplay_device.z.so and /dev/null differ diff --git a/hardware/display/lib64/libdisplay_device_drm.z.so b/hardware/display/lib64/libdisplay_device_drm.z.so deleted file mode 100644 index 44885cce8381d47ca25cb4288505542a4a954f2b..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib64/libdisplay_device_drm.z.so and /dev/null differ diff --git a/hardware/display/lib64/libdisplay_gfx.z.so b/hardware/display/lib64/libdisplay_gfx.z.so deleted file mode 100644 index 6c4fd345708ad6b4a60cb24ca98f517a5bb825ac..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib64/libdisplay_gfx.z.so and /dev/null differ diff --git a/hardware/display/lib64/libdisplay_gralloc.z.so b/hardware/display/lib64/libdisplay_gralloc.z.so deleted file mode 100644 index f2d029d30ecc8fa51673e7374b7abb6c2418ba1b..0000000000000000000000000000000000000000 Binary files a/hardware/display/lib64/libdisplay_gralloc.z.so and /dev/null differ diff --git a/hardware/display/src/display_device/drm_connector.cpp b/hardware/display/src/display_device/drm_connector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f75b27f852c3c1abcf5c42b3cfdd502adf32e6e2 --- /dev/null +++ b/hardware/display/src/display_device/drm_connector.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_connector.h" +#include +#include +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +void DrmMode::ConvertToHdiMode(DisplayModeInfo &hdiMode) +{ + hdiMode.height = mModeInfo.vdisplay; + hdiMode.width = mModeInfo.hdisplay; + hdiMode.freshRate = mModeInfo.vrefresh; + hdiMode.id = mId; +} + +DrmConnector::DrmConnector(drmModeConnector c, FdPtr &fd) + : mId(c.connector_id), + mPhyWidth(c.mmWidth), + mPhyHeight(c.mmHeight), + mEncoderId(c.encoder_id), + mConnectState(c.connection), + mDrmFdPtr(fd) +{ + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + DISPLAY_LOGD("the connect state is %{public}d", mConnectState); + + for (int i = 0; i < c.count_encoders; i++) { + mPossibleEncoders.push_back(c.encoders[i]); + DISPLAY_LOGD("add possible encoder id %{public}d", c.encoders[i]); + } + + ConvertToHdiType(c.connector_type, mType); + ConvertTypeToName(mType, mName); + InitModes(c); + DISPLAY_LOGD("name %{public}s", mName.c_str()); +} + +void DrmConnector::InitModes(drmModeConnector c) +{ + DISPLAY_LOGD("id %{public}d", mId); + mModes.clear(); + mPreferenceId = INVALID_MODE_ID; + for (int i = 0; i < c.count_modes; i++) { + drmModeModeInfoPtr mode = c.modes + i; + DISPLAY_LOGD("mode: hdisplay %{public}d, vdisplay %{public}d vrefresh %{public}d type %{public}d", + mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->type); + if ((mPreferenceId == INVALID_MODE_ID) && (mode->type & DRM_MODE_TYPE_PREFERRED)) { + DISPLAY_LOGD("set it to prefernce id %{public}d", i); + mPreferenceId = i; + } + mModes.emplace(i, DrmMode { *mode, i }); + } + DISPLAY_LOGD("mode count %{public}zd", mModes.size()); +} + +int32_t DrmConnector::Init(DrmDevice &drmDevice) +{ + int32_t ret; + DrmProperty prop; + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((mDrmFdPtr == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the mDrmFdPtr is NULL")); + DISPLAY_CHK_RETURN((mDrmFdPtr->GetFd() == -1), DISPLAY_FAILURE, DISPLAY_LOGE("the drm fd is -1")); + // find dpms prop + ret = drmDevice.GetConnectorProperty(*this, PROP_DPMS, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not get mode prop id")); + mPropDpmsId = prop.propId; + mDpmsState = prop.value; + DISPLAY_LOGD("dpms state : %{public}" PRIu64 "", mDpmsState); + // find the crtcid + ret = drmDevice.GetConnectorProperty(*this, PROP_CRTCID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get out fence prop id")); + mPropCrtcId = prop.propId; + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + DISPLAY_LOGD("mPropCrtcId %{public}d", mPropCrtcId); + // find the brightness + ret = drmDevice.GetConnectorProperty(*this, PROP_BRIGHTNESS, prop); + if (ret == DISPLAY_SUCCESS) { + mPropBrightnessId = prop.propId; + mBrightnessLevel = static_cast(prop.value); + DISPLAY_LOGD("prop brightness is %{public}d, level is %{public}d", mPropBrightnessId, mBrightnessLevel); + } else { + DISPLAY_LOGW("can not get the brightness prop, can not set the brightness"); + } + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::GetBrightness(uint32_t& level) { + if (mPropBrightnessId == DRM_INVALID_ID) { + DISPLAY_LOGE("the prop id of brightness is invalid"); + return DISPLAY_NOT_SUPPORT; + } + level = mBrightnessLevel; + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::SetBrightness(uint32_t level) +{ + DISPLAY_LOGD("set %{public}d", level); + if (mPropBrightnessId == DRM_INVALID_ID) { + DISPLAY_LOGE("the prop id of brightness is invalid"); + return DISPLAY_NOT_SUPPORT; + } + int ret = drmModeConnectorSetProperty(mDrmFdPtr->GetFd(), mId, mPropBrightnessId, level); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("can not set dpms")); + mBrightnessLevel = level; + return DISPLAY_SUCCESS; +} + +void DrmConnector::GetDisplayCap(DisplayCapability &cap) +{ + cap.phyHeight = mPhyHeight; + cap.phyWidth = mPhyWidth; + cap.type = mType; + memcpy_s(cap.name, sizeof(cap.name), mName.c_str(), mName.size()); + if (mName.size() >= sizeof(cap.name)) { + cap.name[sizeof(cap.name) - 1] = 0; + } else { + cap.name[mName.size()] = 0; + } +} + +void DrmConnector::ConvertTypeToName(uint32_t type, std::string &name) +{ + DISPLAY_LOGD("type %{public}d", type); + switch (type) { + case DISP_INTF_VGA: + name = "VGA"; + break; + case DISP_INTF_HDMI: + name = "HDMI"; + break; + case DISP_INTF_MIPI: + name = "MIPI"; + break; + default: + name = "Unknown"; + break; + } +} + +void DrmConnector::ConvertToHdiType(uint32_t type, InterfaceType &hdiType) +{ + switch (type) { + case DRM_MODE_CONNECTOR_VGA: + hdiType = DISP_INTF_VGA; + break; + case DRM_MODE_CONNECTOR_DSI: + hdiType = DISP_INTF_MIPI; + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + hdiType = DISP_INTF_HDMI; + break; + default: + hdiType = DISP_INTF_BUTT; + break; + } +} +int32_t DrmConnector::TryPickEncoder(IdMapPtr &encoders, uint32_t encoderId, IdMapPtr &crtcs, + uint32_t &crtcId) +{ + int ret; + auto encoderIter = encoders.find(encoderId); + if (encoderIter == encoders.end()) { + DISPLAY_LOGW("can not find encoder for id : %{public}d", encoderId); + return DISPLAY_FAILURE; + } + + auto &encoder = encoderIter->second; + DISPLAY_LOGD("connector : %{public}d encoder : %{public}d", mId, encoder->GetId()); + ret = encoder->PickIdleCrtcId(crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick encoder : %{public}d", mId, encoder->GetId())); + return DISPLAY_FAILURE; +} + +int32_t DrmConnector::PickIdleCrtcId(IdMapPtr &encoders, IdMapPtr &crtcs, uint32_t &crtcId) +{ + DISPLAY_LOGD(); + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + int ret = TryPickEncoder(encoders, mEncoderId, crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick endcoder : %{public}d crtcId : %{public}d", + mId, mEncoderId, crtcId)); + + for (auto encoder : mPossibleEncoders) { + ret = TryPickEncoder(encoders, encoder, crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick endcoder : %{public}d crtcId : %{public}d", mId, mEncoderId, + crtcId)); + } + + DISPLAY_LOGW("can not pick a crtc for connector"); + return DISPLAY_FAILURE; +} + +int32_t DrmConnector::UpdateModes() +{ + int drmFd = mDrmFdPtr->GetFd(); + drmModeConnectorPtr c = drmModeGetConnector(drmFd, mId); + DISPLAY_CHK_RETURN((c == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get connector")); + mConnectState = c->connection; + // init the modes + InitModes(*c); + drmModeFreeConnector(c); + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes) +{ + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + *num = static_cast(mModes.size()); + if (modes != nullptr) { + int i = 0; + for (const auto &modeMap : mModes) { + DrmMode mode = modeMap.second; + mode.ConvertToHdiMode(*(modes + i)); + i++; + } + } + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::SetDpmsState(uint64_t dmps) +{ + DISPLAY_LOGD("dmps %{public}" PRIu64 "", dmps); + int ret = drmModeConnectorSetProperty(mDrmFdPtr->GetFd(), mId, mPropDpmsId, dmps); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("can not set dpms")); + mDpmsState = dmps; + return DISPLAY_SUCCESS; +} + +bool DrmConnector::IsConnected() +{ + return (mConnectState == DRM_MODE_CONNECTED); +} + +int32_t DrmConnector::GetModeFromId(int32_t id, DrmMode &mode) +{ + DISPLAY_LOGD(); + auto iter = mModes.find(id); + if (iter == mModes.end()) { + return DISPLAY_FAILURE; + } + mode = mModes[id]; + return DISPLAY_SUCCESS; +} + +std::unique_ptr DrmConnector::GetModeBlockFromId(int32_t id) +{ + DISPLAY_LOGD("id %{public}d", id); + auto iter = mModes.find(id); + DISPLAY_CHK_RETURN((iter == mModes.end()), nullptr, DISPLAY_LOGE("can not the mode %{public}d", id)); + return std::make_unique(mModes[id]); +} + +DrmModeBlock::DrmModeBlock(DrmMode &mode) +{ + DISPLAY_LOGD(); + Init(mode); +} + +int32_t DrmModeBlock::Init(DrmMode &mode) +{ + int ret; + int drmFd; + drmFd = DrmDevice::GetDrmFd(); + DISPLAY_CHK_RETURN((drmFd < 0), DISPLAY_FAILURE, DISPLAY_LOGE("the drm fd is invalid")); + drmModeModeInfo modeInfo = *(mode.GetModeInfoPtr()); + ret = drmModeCreatePropertyBlob(drmFd, static_cast(&modeInfo), sizeof(modeInfo), &mBlockId); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("create property blob failed")); + DISPLAY_LOGD("mBlockId %{public}d", mBlockId); + return DISPLAY_SUCCESS; +} + +DrmModeBlock::~DrmModeBlock() +{ + DISPLAY_LOGD("mBlockId %{public}d", mBlockId); + int drmFd; + drmFd = DrmDevice::GetDrmFd(); + if ((mBlockId != DRM_INVALID_ID) && (drmFd >= 0)) { + int ret = drmModeDestroyPropertyBlob(drmFd, mBlockId); + if (ret != 0) { + DISPLAY_LOGE("destroy property blob failed errno %{public}d", errno); + } + } else { + DISPLAY_LOGE("can not destruct the block id %{public}d drmFd %{public}d", mBlockId, drmFd); + } +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_connector.h b/hardware/display/src/display_device/drm_connector.h new file mode 100644 index 0000000000000000000000000000000000000000..9d07db4f9a3312c401bf5c49beaf18776b88a89e --- /dev/null +++ b/hardware/display/src/display_device/drm_connector.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_CONNECTOR_H +#define DRM_CONNECTOR_H +#include +#include +#include +#include +#include +#include "display_type.h" +#include "drm_encoder.h" +#include "hdi_device_common.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const std::string PROP_DPMS = "DPMS"; +const std::string PROP_CRTCID = "CRTC_ID"; +const std::string PROP_BRIGHTNESS = "brightness"; +class DrmDevice; +class DrmModeBlock; + +class DrmMode { +public: + DrmMode() {}; + DrmMode(drmModeModeInfo &modeInfo, uint32_t id) : mModeInfo(modeInfo), mId(id) {} + virtual ~DrmMode() {}; + drmModeModeInfoPtr GetModeInfoPtr() + { + return &mModeInfo; + } + void ConvertToHdiMode(DisplayModeInfo &hdiMode); + +private: + drmModeModeInfo mModeInfo = { 0 }; + int32_t mId = -1; +}; + +class DrmModeBlock { +public: + explicit DrmModeBlock(DrmMode &mode); + virtual ~DrmModeBlock(); + int32_t Init(DrmMode &mode); + uint32_t GetBlockId() const + { + return mBlockId; + } + +private: + uint32_t mBlockId = DRM_INVALID_ID; +}; + +class DrmConnector { +public: + DrmConnector(drmModeConnector c, FdPtr &fd); + virtual ~DrmConnector() {}; + uint32_t GetId() const + { + return mId; + } + uint32_t GetEncoderId() const + { + return mEncoderId; + } + void GetDisplayCap(DisplayCapability &cap); + int32_t Init(DrmDevice &drmDevice); + int32_t PickIdleCrtcId(IdMapPtr &encoders, IdMapPtr &crtcs, uint32_t &crtcId); + int32_t GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes); + int32_t GetPreferenceId() const + { + return mPreferenceId; + } + uint32_t GetPropCrtcId() const + { + return mPropCrtcId; + } + int32_t TryPickEncoder(IdMapPtr &encoders, uint32_t encoderId, IdMapPtr &crtcs, + uint32_t &crtcId); + // update modes will reset the preference mode id and active mode id + int32_t UpdateModes(); + std::unique_ptr GetModeBlockFromId(int32_t id); + int32_t GetModeFromId(int32_t id, DrmMode &mode); + uint64_t GetDpmsState() const + { + return mDpmsState; + } + int32_t SetDpmsState(uint64_t dmps); + bool IsConnected(); + + int32_t GetBrightness(uint32_t& level); + int32_t SetBrightness(uint32_t level); + +private: + static void ConvertTypeToName(uint32_t type, std::string &name); + static void ConvertToHdiType(uint32_t type, InterfaceType &hdiType); + + void InitModes(drmModeConnector c); + uint32_t mId; + InterfaceType mType; + uint32_t mPhyWidth; + uint32_t mPhyHeight; + uint32_t mEncoderId; + std::vector mPossibleEncoders; + std::string mName; + drmModeConnection mConnectState; + uint32_t mPropDpmsId = DRM_INVALID_ID; + uint64_t mDpmsState = 0; + uint32_t mPropCrtcId = DRM_INVALID_ID; + uint32_t mPropBrightnessId = DRM_INVALID_ID; + uint32_t mBrightnessLevel = 0; + std::unordered_map mModes; + int32_t mPreferenceId = INVALID_MODE_ID; + + FdPtr mDrmFdPtr; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY +#endif // DRM_CONNECTOR_H diff --git a/hardware/display/src/display_device/drm_crtc.cpp b/hardware/display/src/display_device/drm_crtc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0fe8b22dc9584bb4ef13d225647dae0be388e2e --- /dev/null +++ b/hardware/display/src/display_device/drm_crtc.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_crtc.h" +#include "display_common.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmCrtc::DrmCrtc(drmModeCrtcPtr c, uint32_t pipe) : mId(c->crtc_id), mPipe(pipe) {} + +int32_t DrmCrtc::Init(DrmDevice &drmDevice) +{ + DISPLAY_LOGD(); + int32_t ret; + DrmProperty prop; + ret = drmDevice.GetCrtcProperty(*this, PROP_MODEID, prop); + mModePropId = prop.propId; + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not get mode prop id")); + + ret = drmDevice.GetCrtcProperty(*this, PROP_OUTFENCE, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get out fence prop id")); + mOutFencePropId = prop.propId; + + ret = drmDevice.GetCrtcProperty(*this, PROP_ACTIVE, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get out fence prop id")); + mActivePropId = prop.propId; + + return DISPLAY_SUCCESS; +} + +int32_t DrmCrtc::BindToDisplay(uint32_t id) +{ + DISPLAY_CHK_RETURN((mDisplayId != INVALIDE_DISPLAY_ID), DISPLAY_FAILURE, + DISPLAY_LOGE("the crtc has bind to %{public}d", mDisplayId)); + mDisplayId = id; + return DISPLAY_SUCCESS; +} + +void DrmCrtc::UnBindDisplay(uint32_t id) +{ + DISPLAY_LOGD(); + if (mDisplayId == id) { + mDisplayId = INVALIDE_DISPLAY_ID; + } else { + DISPLAY_LOGE("can not unbind"); + } +} + +bool DrmCrtc::CanBind() +{ + return (mDisplayId == INVALIDE_DISPLAY_ID); +} + +int32_t DrmCrtc::SetActivieMode(int32_t id) +{ + DISPLAY_LOGD("set activie modeid to %{public}d", id); + DISPLAY_CHK_RETURN((id > 0), DISPLAY_PARAM_ERR, DISPLAY_LOGE("id %{public}d is invalid ", id)); + if (mActiveModeId != id) { + mNeedModeSet = true; + } + mActiveModeId = id; + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_crtc.h b/hardware/display/src/display_device/drm_crtc.h new file mode 100644 index 0000000000000000000000000000000000000000..2d7d0b93a8c3c714a73f8f8827fed5e9b69be5e7 --- /dev/null +++ b/hardware/display/src/display_device/drm_crtc.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_CRTC_H +#define DRM_CRTC_H +#include +#include +#include +#include +#include "hdi_device_common.h" +#include "hdi_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const std::string PROP_ACTIVE = "ACTIVE"; +const std::string PROP_MODEID = "MODE_ID"; +const std::string PROP_OUTFENCE = "OUT_FENCE_PTR"; + +class DrmDevice; + +class DrmCrtc { +public: + DrmCrtc(drmModeCrtcPtr c, uint32_t pipe); + virtual ~DrmCrtc() {}; + int32_t BindToDisplay(uint32_t id); + void UnBindDisplay(uint32_t id); + bool CanBind(); + uint32_t GetId() const + { + return mId; + } + uint32_t GetModePropId() const + { + return mModePropId; + } + uint32_t GetOutFencePropId() const + { + return mOutFencePropId; + } + uint32_t GetActivePropId() const + { + return mActivePropId; + } + uint32_t GetPipe() const + { + return mPipe; + } + int32_t Init(DrmDevice &drmDevice); + int32_t SetActivieMode(int32_t id); + int32_t GetActiveModeId() const + { + return mActiveModeId; + } + bool NeedModeSet() + { + return mNeedModeSet; + } + +private: + uint32_t mId = 0; + uint32_t mModePropId = 0; + uint32_t mOutFencePropId = 0; + uint32_t mActivePropId = 0; + uint32_t mDisplayId = INVALIDE_DISPLAY_ID; + uint32_t mPipe = 0; + int32_t mActiveModeId = INVALID_MODE_ID; + bool mNeedModeSet = false; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_CRTC_H \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_device.cpp b/hardware/display/src/display_device/drm_device.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fdbedab6ffd478a75c201d8ae9faca129d35b533 --- /dev/null +++ b/hardware/display/src/display_device/drm_device.cpp @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_device.h" +#include +#include +#include +#include +#include +#include "display_common.h" +#include "drm_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +FdPtr DrmDevice::mDrmFd = nullptr; +std::shared_ptr DrmDevice::mInstance; + +std::shared_ptr DrmDevice::Create() +{ + DISPLAY_LOGD(); + if (mDrmFd == nullptr) { + const std::string name("rockchip"); + int drmFd = drmOpen(name.c_str(), nullptr); + if (drmFd < 0) { + DISPLAY_LOGE("drm file:%{public}s open failed %{public}s", name.c_str(), strerror(errno)); + return nullptr; + } + DISPLAY_LOGD("the drm fd is %{public}d", drmFd); + mDrmFd = std::make_shared(drmFd); + } + if (mInstance == nullptr) { + mInstance = std::make_shared(); + } + return mInstance; +} + +int DrmDevice::GetDrmFd() +{ + if (mDrmFd == nullptr) { + DISPLAY_LOGE("the drmfd is null not open"); + return -1; + } + return mDrmFd->GetFd(); +} + +using PixelFormatConvertTbl = struct PixFmtConvertTbl { + uint32_t drmFormat; + PixelFormat pixFormat; +}; + +uint32_t DrmDevice::ConvertToDrmFormat(PixelFormat fmtIn) +{ + static const PixelFormatConvertTbl convertTable[] = { + {DRM_FORMAT_XBGR8888, PIXEL_FMT_RGBX_8888}, {DRM_FORMAT_ABGR8888, PIXEL_FMT_RGBA_8888}, + {DRM_FORMAT_RGB888, PIXEL_FMT_RGB_888}, {DRM_FORMAT_RGB565, PIXEL_FMT_BGR_565}, + {DRM_FORMAT_BGRX4444, PIXEL_FMT_BGRX_4444}, {DRM_FORMAT_BGRA4444, PIXEL_FMT_BGRA_4444}, + {DRM_FORMAT_RGBA4444, PIXEL_FMT_RGBA_4444}, {DRM_FORMAT_RGBX4444, PIXEL_FMT_RGBX_4444}, + {DRM_FORMAT_BGRX5551, PIXEL_FMT_BGRX_5551}, {DRM_FORMAT_BGRA5551, PIXEL_FMT_BGRA_5551}, + {DRM_FORMAT_BGRX8888, PIXEL_FMT_BGRX_8888}, {DRM_FORMAT_ARGB8888, PIXEL_FMT_BGRA_8888}, + {DRM_FORMAT_NV12, PIXEL_FMT_YCBCR_420_SP}, {DRM_FORMAT_NV21, PIXEL_FMT_YCRCB_420_SP}, + {DRM_FORMAT_YUV420, PIXEL_FMT_YCBCR_420_P}, {DRM_FORMAT_YVU420, PIXEL_FMT_YCRCB_420_P}, + {DRM_FORMAT_NV16, PIXEL_FMT_YCBCR_422_SP}, {DRM_FORMAT_NV61, PIXEL_FMT_YCRCB_422_SP}, + {DRM_FORMAT_YUV422, PIXEL_FMT_YCBCR_422_P}, {DRM_FORMAT_YVU422, PIXEL_FMT_YCRCB_422_P}, + }; + uint32_t fmtOut = 0; + for (uint32_t i = 0; i < sizeof(convertTable) / sizeof(convertTable[0]); i++) { + if (convertTable[i].pixFormat == fmtIn) { + fmtOut = convertTable[i].drmFormat; + } + } + DISPLAY_LOGD("fmtIn %{public}d, outFmt %{public}d", fmtIn, fmtOut); + return fmtOut; +} + +DrmDevice::DrmDevice() {} + +int32_t DrmDevice::GetCrtcProperty(const DrmCrtc &crtc, const std::string &name, DrmProperty &prop) +{ + return GetProperty(crtc.GetId(), DRM_MODE_OBJECT_CRTC, name, prop); +} + +int32_t DrmDevice::GetConnectorProperty(const DrmConnector &connector, const std::string &name, DrmProperty &prop) +{ + return GetProperty(connector.GetId(), DRM_MODE_OBJECT_CONNECTOR, name, prop); +} + +int32_t DrmDevice::GetPlaneProperty(const DrmPlane &plane, const std::string &name, DrmProperty &prop) +{ + return GetProperty(plane.GetId(), DRM_MODE_OBJECT_PLANE, name, prop); +} + +int32_t DrmDevice::GetProperty(const uint32_t objId, uint32_t objType, const std::string &name, DrmProperty &prop) +{ + drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(GetDrmFd(), objId, objType); + DISPLAY_CHK_RETURN((!props), DISPLAY_FAILURE, DISPLAY_LOGE("can not get properties")); + bool found = false; + for (uint32_t i = 0; i < props->count_props; i++) { + drmModePropertyPtr p = drmModeGetProperty(GetDrmFd(), props->props[i]); + if (strcmp(p->name, name.c_str()) == 0) { + found = true; + prop.propId = p->prop_id; + prop.value = props->prop_values[i]; + } + drmModeFreeProperty(p); + } + drmModeFreeObjectProperties(props); + return found ? DISPLAY_SUCCESS : DISPLAY_NOT_SUPPORT; +} + +int32_t DrmDevice::Init() +{ + int ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, + DISPLAY_LOGE("DRM_CLIENT_CAP_UNIVERSAL_PLANES set failed %{public}s", strerror(errno))); + ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_ATOMIC, 1); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, + DISPLAY_LOGE("DRM_CLIENT_CAP_ATOMIC set failed %{public}s", strerror(errno))); + + ret = drmSetMaster(GetDrmFd()); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, DISPLAY_LOGE("can not set to master errno : %{public}d", errno)); + DISPLAY_LOGE("chenyf master"); + ret = drmIsMaster(GetDrmFd()); + DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("is not master : %{public}d", errno)); + + return DISPLAY_SUCCESS; +} + +void DrmDevice::DeInit() +{ + mDisplays.clear(); + mCrtcs.clear(); +} + +void DrmDevice::FindAllCrtc(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mCrtcs.clear(); + for (int i = 0; i < res->count_crtcs; i++) { + drmModeCrtcPtr crtc = drmModeGetCrtc(GetDrmFd(), res->crtcs[i]); + if (!crtc) { + DISPLAY_LOGE("can not get crtc %{public}d", i); + continue; + } + uint32_t crtc_id = crtc->crtc_id; + std::shared_ptr drmCrtc = std::make_shared(crtc, i); + int ret = drmCrtc->Init(*this); + drmModeFreeCrtc(crtc); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("crtc %{public}d init failed", i); + continue; + } + mCrtcs.emplace(crtc_id, std::move(drmCrtc)); + } +} + +void DrmDevice::FindAllEncoder(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mEncoders.clear(); + for (int i = 0; i < res->count_encoders; i++) { + drmModeEncoderPtr encoder = drmModeGetEncoder(GetDrmFd(), res->encoders[i]); + if (!encoder) { + DISPLAY_LOGE("can not get encoder %{public}d", i); + continue; + } + std::shared_ptr drmEncoder = std::make_shared(*encoder); + mEncoders.emplace(encoder->encoder_id, std::move(drmEncoder)); + drmModeFreeEncoder(encoder); + } + DISPLAY_LOGD("find encoder count %{public}zd", mEncoders.size()); +} + +void DrmDevice::FindAllConnector(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mConnectors.clear(); + int ret; + for (int i = 0; i < res->count_connectors; i++) { + drmModeConnectorPtr connector = drmModeGetConnector(GetDrmFd(), res->connectors[i]); + if (!connector) { + DISPLAY_LOGE("can not get connector mode %{public}d", i); + continue; + } + std::shared_ptr drmConnector = std::make_shared(*connector, mDrmFd); + ret = drmConnector->Init(*this); + drmModeFreeConnector(connector); + if (ret != DISPLAY_SUCCESS) { + continue; + } + int connectorId = drmConnector->GetId(); + mConnectors.emplace(connectorId, std::move(drmConnector)); + } + DISPLAY_LOGD("find connector count %{public}zd", mConnectors.size()); +} + +void DrmDevice::FindAllPlane() +{ + mPlanes.clear(); + int ret; + drmModePlaneResPtr planeRes = drmModeGetPlaneResources(GetDrmFd()); + DISPLAY_CHK_RETURN_NOT_VALUE((planeRes == nullptr), DISPLAY_LOGE("can not get plane resource")); + DISPLAY_LOGD("count_planes %{public}d", planeRes->count_planes); + for (uint32_t i = 0; i < planeRes->count_planes; i++) { + drmModePlanePtr p = drmModeGetPlane(GetDrmFd(), planeRes->planes[i]); + if (!p) { + DISPLAY_LOGE("can not get plane %{public}d", i); + continue; + } + std::shared_ptr drmPlane = std::make_shared(*p); + DISPLAY_LOGD(); + ret = drmPlane->Init(*this); + DISPLAY_LOGD(); + drmModeFreePlane(p); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("drm plane %{public}d init failed", i); + continue; + } + mPlanes.emplace_back(std::move(drmPlane)); + } + DISPLAY_LOGD("find plane count %{public}zd", mPlanes.size()); +} + +std::shared_ptr DrmDevice::GetDrmEncoderFromId(uint32_t id) +{ + /*int32_t ret = DISPLAY_FAILURE; + auto iter = mEncoders.find(id); + if (iter == mEncoders.end()) { + ret = DISPLAY_SUCCESS; + }*/ + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmConnectorFromId(uint32_t id) +{ + /*int32_t ret = DISPLAY_FAILURE; + auto iter = mConnectors.find(id); + if (iter == mConnectors.end()) { + ret = DISPLAY_SUCCESS; + }*/ + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmCrtcFromId(uint32_t id) +{ + /*int32_t ret = DISPLAY_FAILURE; + auto iter = mCrtcs.find(id); + if (iter == mCrtcs.end()) { + ret = DISPLAY_SUCCESS; + }*/ + return nullptr; +} + +std::vector> DrmDevice::GetDrmPlane(uint32_t pipe, uint32_t type) +{ + std::vector> planes; + for (const auto &plane : mPlanes) { + if (plane->IsIdle() && ((1 << pipe) & plane->GetPossibleCrtcs()) && (type == plane->GetType())) { + plane->BindToPipe(pipe); + planes.push_back(plane); + } + } + DISPLAY_LOGD("the planes count %{public}zd", planes.size()); + return planes; +} + + +std::unordered_map> DrmDevice::DiscoveryDisplay() +{ + mDisplays.clear(); + drmModeResPtr res = drmModeGetResources(GetDrmFd()); + DISPLAY_CHK_RETURN((res == nullptr), mDisplays, DISPLAY_LOGE("can not get drm resource")); + // discovery all drm resource + FindAllCrtc(res); + FindAllEncoder(res); + FindAllConnector(res); + FindAllPlane(); + DISPLAY_LOGD(); + // travel all connector + for (auto &connectorPair : mConnectors) { + auto connector = connectorPair.second; + uint32_t crtcId = 0; + int32_t ret = connector->PickIdleCrtcId(mEncoders, mCrtcs, crtcId); + if (ret != DISPLAY_SUCCESS) { + continue; + } + DISPLAY_LOGD(); + + auto crtcIter = mCrtcs.find(crtcId); + if (crtcIter == mCrtcs.end()) { + DISPLAY_LOGE("can not find crtc for the id %{public}d", connector->GetId()); + continue; + } + DISPLAY_LOGD(); + auto crtc = crtcIter->second; + DISPLAY_LOGD("crtc %{public}p", crtc.get()); + // create the display + std::shared_ptr display = std::make_shared(connector, crtc, mInstance); + DISPLAY_LOGD(); + display->Init(); + mDisplays.emplace(display->GetId(), std::move(display)); + } + DISPLAY_LOGD("find display size %{public}zd", mDisplays.size()); + return mDisplays; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_device.h b/hardware/display/src/display_device/drm_device.h new file mode 100644 index 0000000000000000000000000000000000000000..178db8b71a91aa26061241bb5b5ab384a43eab41 --- /dev/null +++ b/hardware/display/src/display_device/drm_device.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_DEVICE_H +#define DRM_DEVICE_H +#include +#include +#include +#include +#include "drm_connector.h" +#include "drm_crtc.h" +#include "drm_encoder.h" +#include "drm_plane.h" +#include "hdi_device_common.h" +#include "hdi_device_interface.h" +#include "hdi_display.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +struct DrmProperty { + uint32_t propId; + uint64_t value; +}; + +class DrmDevice : public HdiDeviceInterface, std::enable_shared_from_this { +public: + static std::shared_ptr Create(); + static uint32_t ConvertToDrmFormat(PixelFormat fmtIn); + static int GetDrmFd(); + DrmDevice(); + virtual ~DrmDevice() {} + + std::vector> GetDrmPlane(uint32_t pipe, uint32_t type); + + int32_t GetCrtcProperty(const DrmCrtc &crtc, const std::string &name, DrmProperty &prop); + int32_t GetConnectorProperty(const DrmConnector &connector, const std::string &name, DrmProperty &prop); + int32_t GetPlaneProperty(const DrmPlane &plane, const std::string &name, DrmProperty &prop); + + int32_t GetProperty(uint32_t objId, uint32_t objType, const std::string &name, DrmProperty &prop); + std::shared_ptr GetDrmEncoderFromId(uint32_t id); + std::shared_ptr GetDrmConnectorFromId(uint32_t id); + std::shared_ptr GetDrmCrtcFromId(uint32_t id); + void CreateCrtc(drmModeCrtcPtr c); + virtual std::unordered_map> DiscoveryDisplay(); + virtual int32_t Init(); + virtual void DeInit(); + +private: + static FdPtr mDrmFd; + static std::shared_ptr mInstance; + void FindAllCrtc(const drmModeResPtr &drmRes); + void FindAllEncoder(const drmModeResPtr &drmRes); + void FindAllConnector(const drmModeResPtr &drmRes); + void FindAllPlane(); + int InitNetLink(); + IdMapPtr mDisplays; + IdMapPtr mCrtcs; + IdMapPtr mEncoders; + IdMapPtr mConnectors; + std::vector> mPlanes; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_DEVICE_H \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_display.cpp b/hardware/display/src/display_device/drm_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9576e6a5da96b230c1094b2e8ad9fe0581c8c36 --- /dev/null +++ b/hardware/display/src/display_device/drm_display.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_display.h" +#include +#include +#include +#include +#include +#include "display_gralloc.h" +#include "display_common.h" +#include "drm_device.h" +#include "drm_vsync_worker.h" +#include "hdi_drm_composition.h" +#include "hdi_gfx_composition.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmDisplay::DrmDisplay(std::shared_ptr connector, std::shared_ptr crtc, + std::shared_ptr drmDevice) + : mDrmDevice(drmDevice), mConnector(connector), mCrtc(crtc) +{} + +DrmDisplay::~DrmDisplay() +{ + if (mCrtc != nullptr) { + mCrtc->UnBindDisplay(GetId()); + } +} + +int32_t DrmDisplay::Init() +{ + int ret; + DISPLAY_CHK_RETURN((mCrtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null")); + DISPLAY_CHK_RETURN((mConnector == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("connector is null")); + DISPLAY_CHK_RETURN((mDrmDevice == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("drmDevice is null")); + + ret = HdiDisplay::Init(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("init failed")); + auto preComp = std::make_unique(); + DISPLAY_CHK_RETURN((preComp == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("can not new HdiGfxComposition errno %{public}d", errno)); + ret = preComp->Init(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not init HdiGfxComposition")); + + auto postComp = std::make_unique(mConnector, mCrtc, mDrmDevice); + DISPLAY_CHK_RETURN((postComp == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("can not new HdiDrmComposition errno %{public}d", errno)); + ret = postComp->Init(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not init HdiDrmComposition")); + mComposer = std::make_unique(std::move(preComp), std::move(postComp)); + ret = mCrtc->BindToDisplay(GetId()); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("bind crtc failed")); + + ret = ChosePreferenceMode(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("choose preference mode fialed")); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::GetDisplayCapability(DisplayCapability *info) +{ + mConnector->GetDisplayCap(*info); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes) +{ + mConnector->GetDisplaySuppportedModes(num, modes); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::GetDisplayMode(uint32_t *modeId) +{ + DISPLAY_CHK_RETURN((modeId == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the in modeId is nullptr")); + *modeId = mCrtc->GetActiveModeId(); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::SetDisplayMode(uint32_t modeId) +{ + return mCrtc->SetActivieMode(modeId); +} + +int32_t DrmDisplay::GetDisplayPowerStatus(DispPowerStatus *status) +{ + DISPLAY_CHK_RETURN((status == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("status is nullptr")); + return ConvertToHdiPowerState(mConnector->GetDpmsState(), *status); +} + +int32_t DrmDisplay::SetDisplayPowerStatus(DispPowerStatus status) +{ + DISPLAY_LOGD("the status %{public}d ", status); + uint32_t drmPowerState = 0; + int ret = ConvertToDrmPowerState(status, drmPowerState); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_PARAM_ERR, + DISPLAY_LOGE("unknown power status %{public}d", status)); + mConnector->SetDpmsState(drmPowerState); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::ConvertToHdiPowerState(uint32_t drmPowerState, DispPowerStatus &hdiPowerState) +{ + int32_t ret = DISPLAY_SUCCESS; + switch (drmPowerState) { + case DRM_MODE_DPMS_OFF: + hdiPowerState = POWER_STATUS_OFF; + break; + case DRM_MODE_DPMS_ON: + hdiPowerState = POWER_STATUS_ON; + break; + case DRM_MODE_DPMS_STANDBY: + hdiPowerState = POWER_STATUS_STANDBY; + break; + case DRM_MODE_DPMS_SUSPEND: + hdiPowerState = POWER_STATUS_SUSPEND; + break; + default: + hdiPowerState = POWER_STATUS_BUTT; + ret = DISPLAY_FAILURE; + break; + } + DISPLAY_LOGD("hdi power state %{public}u", hdiPowerState); + return ret; +} + +int32_t DrmDisplay::ConvertToDrmPowerState(DispPowerStatus hdiPowerState, uint32_t &drmPowerState) +{ + int32_t ret = DISPLAY_SUCCESS; + switch (hdiPowerState) { + case POWER_STATUS_OFF: + drmPowerState = DRM_MODE_DPMS_OFF; + break; + case POWER_STATUS_ON: + drmPowerState = DRM_MODE_DPMS_ON; + break; + case POWER_STATUS_STANDBY: + drmPowerState = DRM_MODE_DPMS_STANDBY; + break; + case POWER_STATUS_SUSPEND: + drmPowerState = DRM_MODE_DPMS_SUSPEND; + break; + default: + ret = DISPLAY_FAILURE; + break; + } + return ret; +} + +std::unique_ptr DrmDisplay::CreateHdiLayer(LayerType type) +{ + DISPLAY_LOGD(); + return std::make_unique(type); +} + +int32_t DrmDisplay::WaitForVBlank(uint64_t *ns) +{ + int ret; + constexpr uint64_t nPerS = 1000000000; + constexpr uint64_t nPerUS = 1000; + drmVBlank vbl = { + .request.type = DRM_VBLANK_RELATIVE, + .request.sequence = 0, + .request.signal = 0, + }; + DISPLAY_CHK_RETURN((ns == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in ns is nullptr")); + ret = drmWaitVBlank(mDrmDevice->GetDrmFd(), &vbl); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("wait vblank failed errno %{public}d", errno)); + *ns = static_cast(vbl.reply.tval_sec * nPerS + vbl.reply.tval_usec * nPerUS); + return DISPLAY_SUCCESS; +} + +bool DrmDisplay::IsConnected() +{ + DISPLAY_LOGD("conneted %{public}d", mConnector->IsConnected()); + return mConnector->IsConnected(); +} + +int32_t DrmDisplay::PushFirstFrame() +{ + GrallocFuncs *grallocFucs = nullptr; + int ret = GrallocInitialize(&grallocFucs); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("Gralloc init failed")); + DrmMode mode; + ret = mConnector->GetModeFromId(mCrtc->GetActiveModeId(), mode); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("can not get the mode from id %{public}d", mCrtc->GetActiveModeId())); + AllocInfo info = { + .width = mode.GetModeInfoPtr()->hdisplay, + .height = mode.GetModeInfoPtr()->vdisplay, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRA_8888 + }; + + BufferHandle *buffer = nullptr; + ret = grallocFucs->AllocMem(&info, &buffer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not alloc memory")); + mClientLayer->SetLayerBuffer(buffer, -1); + + std::vector layers; + HdiDrmComposition *drmComp = static_cast(mComposer->GetPostCompostion()); + drmComp->SetLayers(layers, *mClientLayer); + drmComp->Apply(true); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::ChosePreferenceMode() +{ + int32_t ret; + int32_t modeId = mConnector->GetPreferenceId(); + if (modeId == INVALID_MODE_ID) { + int32_t num = 0; + ret = GetDisplaySuppportedModes(&num, nullptr); + DISPLAY_CHK_RETURN((num == 0) && (ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not get modes")); + modeId = 0; + } + ret = SetDisplayMode(modeId); + // Push first frame to the drm, for that the vblank must init all the componet. + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("set display mode failed")); + return PushFirstFrame(); +} + +int32_t DrmDisplay::RegDisplayVBlankCallback(VBlankCallback cb, void *data) +{ + DISPLAY_LOGD("the VBlankCallback %{public}p ", cb); + (void)data; + std::shared_ptr vsyncCb = std::make_shared(cb, nullptr); + DrmVsyncWorker::GetInstance().ReqesterVBlankCb(vsyncCb); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::SetDisplayVsyncEnabled(bool enabled) +{ + DISPLAY_LOGD("enable %{public}d", enabled); + DrmVsyncWorker::GetInstance().EnableVsync(enabled); + return DISPLAY_SUCCESS; +} + +int32_t DrmDisplay::GetDisplayBacklight(uint32_t *value) +{ + DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr")); + return mConnector->GetBrightness(*value); +} + +int32_t DrmDisplay::SetDisplayBacklight(uint32_t value) +{ + return mConnector->SetBrightness(value); +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_display.h b/hardware/display/src/display_device/drm_display.h new file mode 100644 index 0000000000000000000000000000000000000000..e4dfba6231a787f941bf0e9bfc6271eaba366df2 --- /dev/null +++ b/hardware/display/src/display_device/drm_display.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_DISPLAY_H +#define DRM_DISPLAY_H +#include +#include +#include "drm_connector.h" +#include "drm_crtc.h" +#include "drm_device.h" +#include "drm_plane.h" +#include "hdi_composer.h" +#include "hdi_drm_composition.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class DrmDisplay : public HdiDisplay { +public: + DrmDisplay(std::shared_ptr connector, std::shared_ptr crtc, + std::shared_ptr drmDevice); + + virtual ~DrmDisplay(); + + int32_t Init() override; + int32_t GetDisplayCapability(DisplayCapability *info) override; + int32_t GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes) override; + int32_t GetDisplayMode(uint32_t *modeId) override; + int32_t SetDisplayMode(uint32_t modeId) override; + int32_t GetDisplayPowerStatus(DispPowerStatus *status) override; + int32_t SetDisplayPowerStatus(DispPowerStatus status) override; + int32_t GetDisplayBacklight(uint32_t *value) override; + int32_t SetDisplayBacklight(uint32_t value) override; + int32_t ChosePreferenceMode(); + virtual int32_t RegDisplayVBlankCallback(VBlankCallback cb, void *data) override; + virtual int32_t WaitForVBlank(uint64_t *ns) override; + virtual bool IsConnected() override; + virtual int32_t SetDisplayVsyncEnabled(bool enabled) override; + HdiDrmComposition *GetDrmComposition(); + +protected: + std::unique_ptr CreateHdiLayer(LayerType type) override; + +private: + int32_t PushFirstFrame(); + int32_t ConvertToHdiPowerState(uint32_t drmPowerState, DispPowerStatus &hdiPowerState); + int32_t ConvertToDrmPowerState(DispPowerStatus hdiPowerState, uint32_t &drmPowerState); + std::shared_ptr mDrmDevice; + std::shared_ptr mConnector; + std::shared_ptr mCrtc; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DISPLAY_H \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_encoder.cpp b/hardware/display/src/display_device/drm_encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70ed87521cb2a8378b6cf956fdd2af8f381ffcd7 --- /dev/null +++ b/hardware/display/src/display_device/drm_encoder.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_encoder.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmEncoder::DrmEncoder(drmModeEncoder e) +{ + mEncoderId = e.encoder_id; + mCrtcId = e.crtc_id; + mPossibleCrtcs = e.possible_crtcs; +} + +int32_t DrmEncoder::PickIdleCrtcId(IdMapPtr &crtcs, uint32_t &crtcId) +{ + // find the crtc id; + DISPLAY_LOGD("crtcs szie %{public}zu", crtcs.size()); + std::shared_ptr crtc; + auto crtcIter = crtcs.find(mCrtcId); + if (crtcIter == crtcs.end()) { + DISPLAY_LOGW("can not find crtc for id %{public}d", mCrtcId); + crtcIter = crtcs.begin(); + } + DISPLAY_CHK_RETURN((crtcIter == crtcs.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("have no crtc %{public}zu ", crtcs.size())); + crtc = crtcIter->second; + DISPLAY_CHK_RETURN((crtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null")); + + if (!crtc->CanBind()) { + crtc = nullptr; + for (const auto &posCrtcPair : crtcs) { + auto &posCrts = posCrtcPair.second; + DISPLAY_LOGD("try crtc id : %{public}d", posCrts->GetId()); + if (posCrts->CanBind() && ((1 << posCrts->GetPipe()) & mPossibleCrtcs)) { + crtc = posCrts; + } + } + } + DISPLAY_CHK_RETURN((crtc == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("encoder %{public}d can not bind to idle crtc", mEncoderId)); + crtcId = crtc->GetId(); + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_encoder.h b/hardware/display/src/display_device/drm_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..4f35578a54ef9ac26439f1ebf19cf342307fa509 --- /dev/null +++ b/hardware/display/src/display_device/drm_encoder.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_ENCODER_H +#define DRM_ENCODER_H +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class DrmEncoder { +public: + explicit DrmEncoder(drmModeEncoder e); + virtual ~DrmEncoder() {} + uint32_t GetCrtcId() const + { + return mCrtcId; + } + void SetCrtcId(uint32_t id) + { + mCrtcId = id; + } + uint32_t GetPossibleCrtcs() const + { + return mPossibleCrtcs; + } + int32_t PickIdleCrtcId(IdMapPtr &crtcs, uint32_t &crtcId); + uint32_t GetId() const + { + return mEncoderId; + } + +private: + uint32_t mEncoderId; + uint32_t mCrtcId; + uint32_t mPossibleCrtcs; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_ENCODER_H \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_plane.cpp b/hardware/display/src/display_device/drm_plane.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a98887a8be2c54cb3d2bd2366db70b861036732 --- /dev/null +++ b/hardware/display/src/display_device/drm_plane.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_plane.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmPlane::DrmPlane(drmModePlane &p) + : mId(p.plane_id), mPossibleCrtcs(p.possible_crtcs), mFormats(p.formats, p.formats + p.count_formats) +{} + +DrmPlane::~DrmPlane() +{ + DISPLAY_LOGD(); +} + +int32_t DrmPlane::Init(DrmDevice &drmDevice) +{ + DISPLAY_LOGD(); + int32_t ret; + DrmProperty prop; + ret = drmDevice.GetPlaneProperty(*this, PROP_FBID, prop); + mPropFbId = prop.propId; + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not get plane fb id")); + ret = drmDevice.GetPlaneProperty(*this, PROP_IN_FENCE_FD, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get plane in fence prop id")); + mPropFenceInId = prop.propId; + ret = drmDevice.GetPlaneProperty(*this, PROP_CRTC_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc prop id")); + mPropCrtcId = prop.propId; + ret = drmDevice.GetPlaneProperty(*this, PROP_TYPE, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc prop id")); + switch (prop.value) { + case DRM_PLANE_TYPE_OVERLAY: + case DRM_PLANE_TYPE_PRIMARY: + case DRM_PLANE_TYPE_CURSOR: + mType = static_cast(prop.value); + break; + default: + DISPLAY_LOGE("unknown type value %{public}" PRIu64 "", prop.value); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/drm_plane.h b/hardware/display/src/display_device/drm_plane.h new file mode 100644 index 0000000000000000000000000000000000000000..05ee6cbe7cf4ce94b8a572d5374ce744b58a1405 --- /dev/null +++ b/hardware/display/src/display_device/drm_plane.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_PLANE_H +#define DRM_PLANE_H +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const std::string PROP_FBID = "FB_ID"; +const std::string PROP_IN_FENCE_FD = "IN_FENCE_FD"; +const std::string PROP_CRTC_ID = "CRTC_ID"; +const std::string PROP_TYPE = "type"; +class DrmDevice; + +class DrmPlane { +public: + explicit DrmPlane(drmModePlane &p); + virtual ~DrmPlane(); + int32_t Init(DrmDevice &drmDevice); + uint32_t GetId() const + { + return mId; + } + uint32_t GetPropFbId() const + { + return mPropFbId; + } + uint32_t GetPropFenceInId() const + { + return mPropFenceInId; + } + uint32_t GetPropCrtcId() const + { + return mPropCrtcId; + } + uint32_t GetPossibleCrtcs() const + { + return mPossibleCrtcs; + } + uint32_t GetType() const + { + return mType; + } + void BindToPipe(uint32_t pipe) + { + mPipe = pipe; + } + void UnBindPipe() + { + mPipe = 0; + } + bool IsIdle() const + { + return (mPipe == 0); + } + +private: + uint32_t mId = 0; + uint32_t mPossibleCrtcs = 0; + uint32_t mPropFbId = 0; + uint32_t mPropFenceInId = 0; + uint32_t mPropCrtcId = 0; + uint32_t mPipe = 0; + uint32_t mType = 0; + std::vector mFormats; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_PLANE_H \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_vsync_worker.cpp b/hardware/display/src/display_device/drm_vsync_worker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b150f957c7caad571a522e072badcab7ce37ab87 --- /dev/null +++ b/hardware/display/src/display_device/drm_vsync_worker.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_vsync_worker.h" +#include +#include "display_common.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmVsyncWorker::DrmVsyncWorker() {} + +int32_t DrmVsyncWorker::Init(int fd) +{ + DISPLAY_CHK_RETURN((fd < 0), DISPLAY_FAILURE, DISPLAY_LOGE("the fd is invalid")); + mDrmFd = fd; + DISPLAY_LOGD("the drm fd is %{public}d", fd); + mThread = std::make_unique([this]() { WorkThread(); }); + DISPLAY_CHK_RETURN((mThread == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create thread")); + mRunning = true; + return DISPLAY_SUCCESS; +} + +DrmVsyncWorker &DrmVsyncWorker::GetInstance() +{ + static DrmVsyncWorker instance; + static std::once_flag once; + std::call_once(once, [&]() { + int ret = instance.Init(DrmDevice::GetDrmFd()); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("Vsync Worker Init failed"); + } + }); + return instance; +} + +DrmVsyncWorker::~DrmVsyncWorker() +{ + DISPLAY_LOGD(); + { + std::lock_guard lg(mMutex); + mRunning = false; + } + DISPLAY_LOGD(); + mCondition.notify_one(); + if (mThread != nullptr) { + mThread->join(); + } + DISPLAY_LOGD(); +} + +bool DrmVsyncWorker::WaitSignalAndCheckRuning() +{ + std::unique_lock ul(mMutex); + mCondition.wait(ul, [this]() { return (mEnable || !mRunning); }); + return mRunning; +} + + +uint64_t DrmVsyncWorker::WaitNextVBlank(unsigned int &sq) +{ + constexpr uint64_t SEC_TO_NSEC = 1000 * 1000 * 1000; + constexpr uint64_t USEC_TO_NSEC = 1000; + drmVBlank vblank = { + .request = + drmVBlankReq { + .type = DRM_VBLANK_RELATIVE, + .sequence = 1, + .signal = 0, + } + }; + int ret = drmWaitVBlank(mDrmFd, &vblank); + DISPLAY_CHK_RETURN((ret < 0), 0, + DISPLAY_LOGE("wait vblank failed ret : %{public}d errno %{public}d", ret, errno)); + sq = vblank.reply.sequence; + return (uint64_t)(vblank.reply.tval_sec * SEC_TO_NSEC + vblank.reply.tval_usec * USEC_TO_NSEC); +} + + +void DrmVsyncWorker::EnableVsync(bool enable) +{ + DISPLAY_LOGD(); + { + std::lock_guard lg(mMutex); + mEnable = enable; + } + mCondition.notify_one(); +} + +void DrmVsyncWorker::WorkThread() +{ + DISPLAY_LOGD(); + unsigned int seq = 0; + while (WaitSignalAndCheckRuning()) { + // wait the vblank + uint64_t time = WaitNextVBlank(seq); + if (mCallBack != nullptr) { + mCallBack->Vsync(seq, time); + } else { + DISPLAY_LOGE("the callbac is nullptr"); + } + } +} + +void DrmVsyncWorker::ReqesterVBlankCb(std::shared_ptr &cb) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN_NOT_VALUE((cb == nullptr), DISPLAY_LOGE("the VBlankCallback is nullptr ")); + mCallBack = cb; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY \ No newline at end of file diff --git a/hardware/display/src/display_device/drm_vsync_worker.h b/hardware/display/src/display_device/drm_vsync_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..c578e91c49e9fc8722115ef711cfd097fe1a3737 --- /dev/null +++ b/hardware/display/src/display_device/drm_vsync_worker.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_VSYNC_WORKER_H +#define DRM_VSYNC_WORKER_H +#include +#include +#include +#include +#include "display_device.h" +#include "hdi_device_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class DrmVsyncWorker { +public: + DrmVsyncWorker(); + virtual ~DrmVsyncWorker(); + int32_t Init(int fd); + static DrmVsyncWorker &GetInstance(); + + void EnableVsync(bool enable); + void WorkThread(); + uint64_t WaitNextVBlank(unsigned int &sq); + bool WaitSignalAndCheckRuning(); + void ReqesterVBlankCb(std::shared_ptr &cb); + +private: + int mDrmFd = 0; + std::unique_ptr mThread; + bool mEnable = false; + std::mutex mMutex; + std::condition_variable mCondition; + std::shared_ptr mCallBack; + bool mRunning = false; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_VSYNC_WORKER_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_composer.cpp b/hardware/display/src/display_device/hdi_composer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04eefdbcf0fefbbd48ede43d5cd37c50150e6d5f --- /dev/null +++ b/hardware/display/src/display_device/hdi_composer.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_composer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiComposer::HdiComposer(std::unique_ptr pre, std::unique_ptr post) +{ + mPreComp = std::move(pre); + mPostComp = std::move(post); +} + +int32_t HdiComposer::Prepare(std::vector &layers, HdiLayer &clientLayer) +{ + int ret = mPreComp->SetLayers(layers, clientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("pre composition prepare failed")); + ret = mPostComp->SetLayers(layers, clientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("post composition prepare failed")); + return DISPLAY_SUCCESS; +} + +int32_t HdiComposer::Commit(bool modeSet) +{ + int ret = mPreComp->Apply(modeSet); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("pre composition apply failed")); + ret = mPostComp->Apply(modeSet); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("post composition apply failed")); + return DISPLAY_SUCCESS; +} +} // OHOS +} // HDI +} // DISPLAY diff --git a/hardware/display/src/display_device/hdi_composer.h b/hardware/display/src/display_device/hdi_composer.h new file mode 100644 index 0000000000000000000000000000000000000000..a3b69de50dd58f1af8317533bf1ce9ab4fb23e38 --- /dev/null +++ b/hardware/display/src/display_device/hdi_composer.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_COMPOSER_H +#define HDI_COMPOSER_H +#include +#include +#include "hdi_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiComposition { +public: + HdiComposition() {} + virtual int32_t Init() + { + return DISPLAY_SUCCESS; + }; + virtual int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer) + { + return DISPLAY_SUCCESS; + } + virtual int32_t Apply(bool modeSet) + { + return DISPLAY_SUCCESS; + } + virtual ~HdiComposition() {} + +protected: + std::vector mCompLayers; +}; + +class HdiComposer { +public: + HdiComposer(std::unique_ptr pre, std::unique_ptr post); + virtual ~HdiComposer() {}; + int32_t Prepare(std::vector &layers, HdiLayer &clientLayer); + int32_t Commit(bool modeSet); + HdiComposition *GetPreCompostion() + { + return mPreComp.get(); + } + HdiComposition *GetPostCompostion() + { + return mPostComp.get(); + } + +private: + std::unique_ptr mPreComp; + std::unique_ptr mPostComp; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_COMPOSER_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_device_common.h b/hardware/display/src/display_device/hdi_device_common.h new file mode 100644 index 0000000000000000000000000000000000000000..c5ceaf092a29ef909e045ffa8916668e69910c67 --- /dev/null +++ b/hardware/display/src/display_device/hdi_device_common.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DEVICE_COMMON_H +#define HDI_DEVICE_COMMON_H +#include +#include +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const int32_t INVALID_MODE_ID = -1; +const uint32_t DRM_INVALID_ID = 0xFFFFFFFF; +template using IdMapPtr = std::unordered_map>; +class DrmEncoder; +class DrmCrtc; +class DrmPlane; +class DrmDevice; +class DrmConnector; +class VsyncCallBack; +class DrmVsyncWorker; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DEVICE_COMMON_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_device_interface.cpp b/hardware/display/src/display_device/hdi_device_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96e5d2e4b9ca1fb9197e40d79ba6d846813ada2f --- /dev/null +++ b/hardware/display/src/display_device/hdi_device_interface.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_device_interface.h" +#include +#include "display_common.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +std::vector> HdiDeviceInterface::DiscoveryDevice() +{ + DISPLAY_LOGD(); + int ret; + std::vector> devices; + std::shared_ptr drmDevice = DrmDevice::Create(); + if (!drmDevice) { + DISPLAY_LOGE("can not create drm device"); + } + ret = drmDevice->Init(); + if (ret == DISPLAY_SUCCESS) { + DISPLAY_LOGD("drm device init success"); + devices.push_back(std::move(drmDevice)); + } else { + DISPLAY_LOGE("drm device init failed"); + } + return devices; +} +} +} +} \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_device_interface.h b/hardware/display/src/display_device/hdi_device_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..f5964ef98a85d3a62a63a716745bb4b9ee1c7778 --- /dev/null +++ b/hardware/display/src/display_device/hdi_device_interface.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DEVICE_INTERFACE_H +#define HDI_DEVICE_INTERFACE_H +#include +#include +#include +#include "hdi_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiDeviceInterface { +public: + static std::vector> DiscoveryDevice(); + virtual std::unordered_map> DiscoveryDisplay() = 0; + virtual int32_t Init() = 0; + virtual void DeInit() = 0; + virtual ~HdiDeviceInterface() {}; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DEVICE_INTERFACE_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_display.cpp b/hardware/display/src/display_device/hdi_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31f0fe86ae6bf45f5d3c77c26a367ba950768186 --- /dev/null +++ b/hardware/display/src/display_device/hdi_display.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_display.h" +#include +#include "display_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +uint32_t HdiDisplay::mIdleId = 0; +std::unordered_set HdiDisplay::mIdSets; + +uint32_t HdiDisplay::GetIdleId() +{ + const uint32_t oldIdleId = mIdleId; + uint32_t id = INVALIDE_DISPLAY_ID; + // ensure the mIdleId not INVALIDE_DISPLAY_ID + mIdleId = mIdleId % INVALIDE_DISPLAY_ID; + do { + auto iter = mIdSets.find(mIdleId); + if (iter == mIdSets.end()) { + id = mIdleId; + break; + } + mIdleId = (mIdleId + 1) % INVALIDE_DISPLAY_ID; + } while (oldIdleId != mIdleId); + mIdSets.emplace(id); + mIdleId++; + return id; +} + + +int32_t HdiDisplay::Init() +{ + DISPLAY_LOGD(); + uint32_t id = GetIdleId(); + DISPLAY_CHK_RETURN((id == INVALIDE_DISPLAY_ID), DISPLAY_FAILURE, DISPLAY_LOGE("have no id to used")); + mId = id; + auto layer = CreateHdiLayer(LAYER_TYPE_GRAPHIC); + DISPLAY_CHK_RETURN((layer.get() == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create hdi layer for client")); + mClientLayer = std::move(layer); + DISPLAY_LOGD("the id is %{public}d", id); + return DISPLAY_SUCCESS; +} + + +HdiDisplay::~HdiDisplay() +{ + mIdSets.erase(mId); +} + +int32_t HdiDisplay::SetLayerZorder(uint32_t layerId, uint32_t zorder) +{ + DISPLAY_LOGD("layerId : %{public}d", layerId); + auto iter = mLayersMap.find(layerId); + DISPLAY_CHK_RETURN((iter == mLayersMap.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find the layer %{public}d", layerId)); + auto layer = mLayersMap[layerId].get(); + if (layer->GetZorder() == zorder) { + DISPLAY_LOGD("zorder no change layerId %{public}d, zorder %{public}d", layerId, zorder); + return DISPLAY_SUCCESS; + } + // reset to sort + auto zRange = mLayers.equal_range(layer); + DISPLAY_LOGD("zorder range : zRange.first %{public}p zRange.second %{public}p", *zRange.first, *zRange.second); + for (auto c = zRange.first; c != zRange.second; c++) { + if (*c == layer) { + mLayers.erase(c); + break; + } + } + layer->SetLayerZorder(zorder); + mLayers.emplace(layer); + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::CreateLayer(const LayerInfo *layerInfo, uint32_t *layerId) +{ + DISPLAY_LOGD(); + int ret; + DISPLAY_CHK_RETURN((layerInfo == nullptr), DISPLAY_PARAM_ERR, DISPLAY_LOGE("LayerInfo is null")); + DISPLAY_CHK_RETURN((layerId == nullptr), DISPLAY_PARAM_ERR, DISPLAY_LOGE("layerId is null")); + auto layer = CreateHdiLayer(layerInfo->type); + DISPLAY_CHK_RETURN((layer.get() == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create hdi layer")); + ret = layer->Init(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("Layer Init failed")); + *layerId = layer->GetId(); + mLayers.insert(layer.get()); + mLayersMap.emplace(layer->GetId(), std::move(layer)); + DISPLAY_LOGD("mLayers size %{public}zu", mLayers.size()); + DISPLAY_LOGD("mLayerMap size %{public}zu", mLayersMap.size()); + return DISPLAY_SUCCESS; +} + +std::unique_ptr HdiDisplay::CreateHdiLayer(LayerType type) +{ + DISPLAY_LOGD(); + return std::make_unique(type); +} + + +int32_t HdiDisplay::CloseLayer(uint32_t layerId) +{ + DISPLAY_LOGD("layerId %{public}d", layerId); + auto iter = mLayersMap.find(layerId); + DISPLAY_CHK_RETURN((iter == mLayersMap.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find the layer id %{public}d", layerId)); + mLayers.erase(iter->second.get()); + mLayersMap.erase(layerId); + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::GetDisplayCompChange(uint32_t *num, uint32_t *layers, int32_t *type) +{ + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the num is nullptr")); + *num = mChangeLayers.size(); + if ((layers == nullptr) && (type == nullptr)) { + return DISPLAY_SUCCESS; + } + DISPLAY_LOGD("set the layers and type"); + for (uint32_t i = 0; i < mChangeLayers.size(); i++) { + HdiLayer *layer = mChangeLayers[i]; + if (layers != nullptr) { + *(layers + i) = layer->GetId(); + } + if (type != nullptr) { + *(type + i) = layer->GetCompositionType(); + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::GetDisplayReleaseFence(uint32_t *num, uint32_t *layers, int32_t *fences) +{ + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the num is nullptr")); + *num = mLayers.size(); + if ((layers == nullptr) && (fences == nullptr)) { + return DISPLAY_SUCCESS; + } + DISPLAY_LOGD("set the layer fences"); + int i = 0; + for (auto layer : mLayers) { + if (layers != nullptr) { + *(layers + i) = layer->GetId(); + } + if (fences != nullptr) { + *(fences + i) = layer->GetReleaseFenceFd(); + } + DISPLAY_LOGD("layer id %{public}d fencefd %{public}d", layer->GetId(), layer->GetReleaseFenceFd()); + i++; + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::PrepareDisplayLayers(bool *needFlushFb) +{ + DISPLAY_LOGD(); + mChangeLayers.clear(); + std::vector layers; + for (auto c : mLayers) { + layers.push_back(c); + } + DISPLAY_LOGD(" mLayers size %{public}zu layers size %{public}zu", mLayers.size(), layers.size()); + + mComposer->Prepare(layers, *mClientLayer); + // get the change layers + for (auto &layer : layers) { + if (layer->GetDeviceSelect() != layer->GetCompositionType()) { + DISPLAY_LOGD("layer change"); + layer->SetLayerCompositionType(layer->GetDeviceSelect()); + } + mChangeLayers.push_back(layer); + } + *needFlushFb = true; + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::Commit(int32_t *fence) +{ + DISPLAY_LOGD(); + mComposer->Commit(false); + *fence = mClientLayer->GetReleaseFenceFd(); + DISPLAY_LOGD("the release fence is %{public}d", *fence); + return DISPLAY_SUCCESS; +} + +int32_t HdiDisplay::SetDisplayClientBuffer(const BufferHandle *buffer, int32_t fence) +{ + mClientLayer->SetLayerBuffer(buffer, fence); + return DISPLAY_SUCCESS; +} + +HdiLayer *HdiDisplay::GetHdiLayer(uint32_t id) +{ + DISPLAY_LOGD("id : %{public}d", id); + auto iter = mLayersMap.find(id); + DISPLAY_CHK_RETURN((iter == mLayersMap.end()), nullptr, DISPLAY_LOGE("can not find the layer %{public}d", id)); + return iter->second.get(); +} + +VsyncCallBack::VsyncCallBack(VBlankCallback cb, void *data) : mVBlankCb(cb), mData(data) +{ + DISPLAY_LOGD("VsyncCallBack %{public}p", cb); +} + +void VsyncCallBack::Vsync(unsigned int sequence, uint64_t ns) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN_NOT_VALUE((mVBlankCb == nullptr), DISPLAY_LOGE("the callback is nullptr")); + mVBlankCb(sequence, ns, mData); +} +} +} +} \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_display.h b/hardware/display/src/display_device/hdi_display.h new file mode 100644 index 0000000000000000000000000000000000000000..57974c680e9a7222ebed2185dbd45a577a7fa3e7 --- /dev/null +++ b/hardware/display/src/display_device/hdi_display.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DISPLAY_H +#define HDI_DISPLAY_H +#include +#include +#include +#include +#include "display_device.h" +#include "hdi_composer.h" +#include "hdi_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const uint32_t INVALIDE_DISPLAY_ID = 0xffffffff; +const uint32_t DISPLAY_TYPE_DRM = (1 << 31); + +class VsyncCallBack { +public: + VsyncCallBack(VBlankCallback cb, void *data); + virtual void Vsync(unsigned int sequence, uint64_t ns); + virtual ~VsyncCallBack() {} + +private: + VBlankCallback mVBlankCb; + void *mData; +}; + + +class HdiDisplay { +public: + uint32_t GetId() const + { + return mId; + } + virtual int32_t Init(); + virtual void DeInit() {} + HdiDisplay() {} + virtual ~HdiDisplay(); + virtual int32_t GetDisplayCapability(DisplayCapability *info) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t GetDisplayMode(uint32_t *modeId) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t SetDisplayMode(uint32_t modeId) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t GetDisplayPowerStatus(DispPowerStatus *status) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t SetDisplayPowerStatus(DispPowerStatus status) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t GetDisplayBacklight(uint32_t *value) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t SetDisplayBacklight(uint32_t value) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t CreateLayer(const LayerInfo *layerInfo, uint32_t *layerId); + virtual int32_t CloseLayer(uint32_t layerId); + virtual int32_t PrepareDisplayLayers(bool *needFlushFb); + virtual int32_t Commit(int32_t *fence); + virtual int32_t GetDisplayCompChange(uint32_t *num, uint32_t *layers, int32_t *type); + virtual int32_t SetLayerZorder(uint32_t layerId, uint32_t zorder); + virtual bool IsConnected() + { + return false; + } + virtual int32_t RegDisplayVBlankCallback(VBlankCallback cb, void *data) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t SetDisplayVsyncEnabled(bool enabled) + { + return DISPLAY_NOT_SUPPORT; + } + virtual int32_t GetDisplayReleaseFence(uint32_t *num, uint32_t *layers, int32_t *fences); + virtual int32_t SetDisplayClientBuffer(const BufferHandle *buffer, int32_t fence); + virtual int32_t WaitForVBlank(uint64_t *ns) + { + return DISPLAY_NOT_SUPPORT; + } + HdiLayer *GetHdiLayer(uint32_t id); + +protected: + virtual std::unique_ptr CreateHdiLayer(LayerType type); + std::unique_ptr mComposer; + + static uint32_t GetIdleId(); + static uint32_t mIdleId; + static std::unordered_set mIdSets; + uint32_t mId = INVALIDE_DISPLAY_ID; + std::unordered_map> mLayersMap; + std::multiset mLayers; + std::unique_ptr mClientLayer; + std::vector mChangeLayers; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DISPLAY_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_drm_composition.cpp b/hardware/display/src/display_device/hdi_drm_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b09166310b999f97407d6c35e2cfa9333b99d2c1 --- /dev/null +++ b/hardware/display/src/display_device/hdi_drm_composition.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_drm_composition.h" +#include +#include "hdi_drm_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiDrmComposition::HdiDrmComposition(std::shared_ptr connector, std::shared_ptr crtc, + std::shared_ptr drmDevice) + : mDrmDevice(drmDevice), mConnector(connector), mCrtc(crtc) +{ + DISPLAY_LOGD(); +} + +int32_t HdiDrmComposition::Init() +{ + DISPLAY_LOGD(); + mPrimPlanes.clear(); + mOverlayPlanes.clear(); + mPlanes.clear(); + DISPLAY_CHK_RETURN((mCrtc == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("crtc is null")); + DISPLAY_CHK_RETURN((mConnector == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("connector is null")); + DISPLAY_CHK_RETURN((mDrmDevice == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("drmDevice is null")); + mPrimPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_PRIMARY); + mOverlayPlanes = mDrmDevice->GetDrmPlane(mCrtc->GetPipe(), DRM_PLANE_TYPE_OVERLAY); + DISPLAY_CHK_RETURN((mPrimPlanes.size() == 0), DISPLAY_FAILURE, DISPLAY_LOGE("has no primary plane")); + mPlanes.insert(mPlanes.end(), mPrimPlanes.begin(), mPrimPlanes.end()); + mPlanes.insert(mPlanes.end(), mOverlayPlanes.begin(), mOverlayPlanes.end()); + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::SetLayers(std::vector &layers, HdiLayer &clientLayer) +{ + // now we do not surpport present direct + DISPLAY_LOGD(); + mCompLayers.clear(); + mCompLayers.push_back(&clientLayer); + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer, DrmPlane &drmPlane, drmModeAtomicReqPtr pset) +{ + // set fence in + int ret; + int fenceFd = layer.GetAcquireFenceFd(); + int propId = drmPlane.GetPropFenceInId(); + DISPLAY_LOGD(); + if (propId != 0) { + DISPLAY_LOGD("set the fence in prop"); + if (fenceFd >= 0) { + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), propId, fenceFd); + DISPLAY_LOGD("set the IfenceProp plane id %{public}d, propId %{public}d, fenceFd %{public}d", + drmPlane.GetId(), propId, fenceFd); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set IN_FENCE_FD failed")); + } + } + + // set fb id + DrmGemBuffer *gemBuffer = layer.GetGemBuffer(); + DISPLAY_CHK_RETURN((gemBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("current gemBuffer is nullptr")); + DISPLAY_CHK_RETURN((!gemBuffer->IsValid()), DISPLAY_FAILURE, DISPLAY_LOGE("the DrmGemBuffer is invalid")); + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropFbId(), gemBuffer->GetFbId()); + DISPLAY_LOGD("set the fb planeid %{public}d, propId %{public}d, fbId %{public}d", drmPlane.GetId(), + drmPlane.GetPropFbId(), gemBuffer->GetFbId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set fb id fialed errno : %{public}d", errno)); + + // set crtc id + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_LOGD("set the crtc planeId %{public}d, propId %{public}d, crtcId %{public}d", drmPlane.GetId(), + drmPlane.GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set crtc id fialed errno : %{public}d", errno)); + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::UpdateMode(std::unique_ptr &modeBlock, drmModeAtomicReq &pset) +{ + // set the mode + DISPLAY_LOGD(); + if (mCrtc->NeedModeSet()) { + modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId()); + if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) { + // set to active + DISPLAY_LOGD("set crtc to active"); + int ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the active prop errno %{public}d", errno)); + + // set the mode id + DISPLAY_LOGD("set the mode"); + ret = drmModeAtomicAddProperty(&pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId()); + DISPLAY_LOGD("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d", mCrtc->GetId(), + mCrtc->GetModePropId(), modeBlock->GetBlockId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno)); + ret = drmModeAtomicAddProperty(&pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", mConnector->GetId(), + mConnector->GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::Apply(bool modeSet) +{ + uint64_t crtcOutFence = -1; + int ret; + std::unique_ptr modeBlock; + int drmFd = mDrmDevice->GetDrmFd(); + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough")); + drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); + DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR, + DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno)); + AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset); + + // set the outFence property + ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(), + (uint64_t)&crtcOutFence); + + DISPLAY_LOGD("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(), + mCrtc->GetOutFencePropId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed ")); + + // set the plane info. + DISPLAY_LOGD("mCompLayers size %{public}zd", mCompLayers.size()); + for (uint32_t i = 0; i < mCompLayers.size(); i++) { + HdiDrmLayer *layer = static_cast(mCompLayers[i]); + auto &drmPlane = mPlanes[i]; + ret = ApplyPlane(*layer, *drmPlane, atomicReqPtr.Get()); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("apply plane failed"); + break; + } + } + ret = UpdateMode(modeBlock, *(atomicReqPtr.Get())); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed")); + uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + + ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, + DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno)); + // set the release fence + for (auto layer : mCompLayers) { + layer->SetReleaseFence(static_cast(crtcOutFence)); + } + + return DISPLAY_SUCCESS; +} +} // OHOS +} // HDI +} // DISPLAY diff --git a/hardware/display/src/display_device/hdi_drm_composition.h b/hardware/display/src/display_device/hdi_drm_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..877897e3f7f9fe937f64c4ea12d189f781b5e7c0 --- /dev/null +++ b/hardware/display/src/display_device/hdi_drm_composition.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DRM_COMPOSITION_H +#define HDI_DRM_COMPOSITION_H +#include +#include +#include +#include +#include "drm_device.h" +#include "hdi_composer.h" +#include "hdi_device_common.h" +#include "hdi_drm_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class AtomicReqPtr { +public: + explicit AtomicReqPtr(drmModeAtomicReqPtr ptr) : mPtr(ptr) {} + virtual ~AtomicReqPtr() + { + if (mPtr != nullptr) + drmModeAtomicFree(mPtr); + } + drmModeAtomicReqPtr Get() const + { + return mPtr; + } + +private: + drmModeAtomicReqPtr mPtr; +}; + +class HdiDrmComposition : public HdiComposition { +public: + HdiDrmComposition(std::shared_ptr connector, std::shared_ptr crtc, + std::shared_ptr drmDevice); + virtual ~HdiDrmComposition() {} + int32_t Init(); + int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer); + int32_t Apply(bool modeSet); + int32_t UpdateMode(std::unique_ptr &modeBlock, drmModeAtomicReq &pset); + +private: + int32_t ApplyPlane(HdiDrmLayer &layer, DrmPlane &drmPlane, drmModeAtomicReqPtr pset); + std::shared_ptr mDrmDevice; + std::shared_ptr mConnector; + std::shared_ptr mCrtc; + std::vector> mPrimPlanes; + std::vector> mOverlayPlanes; + std::vector> mPlanes; +}; +} // OHOS +} // HDI +} // DISPLAY + +#endif // HDI_DRM_COMPOSITION_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_drm_layer.cpp b/hardware/display/src/display_device/hdi_drm_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97040c47385ae441493e09913ece2f48d8dca839 --- /dev/null +++ b/hardware/display/src/display_device/hdi_drm_layer.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_drm_layer.h" +#include +#include +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DrmGemBuffer::DrmGemBuffer(int drmfd, HdiLayerBuffer &hdl) : mDrmFd(drmfd) +{ + DISPLAY_LOGD(); + Init(mDrmFd, hdl); +} + +void DrmGemBuffer::Init(int drmFd, HdiLayerBuffer &hdl) +{ + int ret; + const int MAX_COUNT = 4; + uint32_t pitches[MAX_COUNT] = {0}; + uint32_t gemHandles[MAX_COUNT] = {0}; + uint32_t offsets[MAX_COUNT] = {0}; + DISPLAY_LOGD("hdl %{public}" PRIx64 "", hdl.GetPhysicalAddr()); + DISPLAY_CHK_RETURN_NOT_VALUE((drmFd < 0), DISPLAY_LOGE("can not init drmfd %{public}d", drmFd)); + mDrmFormat = DrmDevice::ConvertToDrmFormat(static_cast(hdl.GetFormat())); + ret = drmPrimeFDToHandle(drmFd, hdl.GetFb(), &mGemHandle); + DISPLAY_CHK_RETURN_NOT_VALUE((ret != 0), DISPLAY_LOGE("can not get handle errno %{public}d", errno)); + + pitches[0] = hdl.GetStride(); + gemHandles[0] = mGemHandle; + offsets[0] = 0; + ret = drmModeAddFB2(drmFd, hdl.GetWight(), hdl.GetHeight(), mDrmFormat, gemHandles, pitches, offsets, &mFdId, 0); + DISPLAY_LOGD("mGemHandle %{public}d mFdId %{public}d", mGemHandle, mFdId); + DISPLAY_LOGD("w: %{public}d h: %{public}d mDrmFormat : %{public}d gemHandles: %{public}d pitches: %{public}d " + "offsets: %{public}d", + hdl.GetWight(), hdl.GetHeight(), mDrmFormat, gemHandles[0], pitches[0], offsets[0]); + DISPLAY_CHK_RETURN_NOT_VALUE((ret != 0), DISPLAY_LOGE("can not add fb errno %{public}d", errno)); +} + +DrmGemBuffer::~DrmGemBuffer() +{ + DISPLAY_LOGD(); + if (mFdId) { + if (drmModeRmFB(mDrmFd, mFdId)) { + DISPLAY_LOGE("can not free fdid %{public}d errno %{public}d", mFdId, errno); + } + } + + if (mGemHandle) { + struct drm_gem_close gemClose = { 0 }; + gemClose.handle = mGemHandle; + if (drmIoctl(mDrmFd, DRM_IOCTL_GEM_CLOSE, &gemClose)) { + DISPLAY_LOGE("can not free gem handle %{public}d errno : %{public}d", mGemHandle, errno); + } + } +} + +bool DrmGemBuffer::IsValid() +{ + DISPLAY_LOGD(); + return (mGemHandle != INVALID_DRM_ID) && (mFdId != INVALID_DRM_ID); +} + +DrmGemBuffer *HdiDrmLayer::GetGemBuffer() +{ + DISPLAY_LOGD(); + std::unique_ptr ptr = std::make_unique(DrmDevice::GetDrmFd(), *GetCurrentBuffer()); + mLastBuffer = std::move(mCurrentBuffer); + mCurrentBuffer = std::move(ptr); + return mCurrentBuffer.get(); +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/hdi_drm_layer.h b/hardware/display/src/display_device/hdi_drm_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..97c3e985d1fc59a7a016c5aece7cf81d6ff88235 --- /dev/null +++ b/hardware/display/src/display_device/hdi_drm_layer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DRM_LAYER_H +#define HDI_DRM_LAYER_H +#include +#include +#include "buffer_handle.h" +#include "display_common.h" +#include "drm_fourcc.h" +#include "hdi_layer.h" +#include "hdi_device_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const int INVALID_DRM_ID = 0; +class DrmGemBuffer { +public: + DrmGemBuffer(int drmFd, HdiLayerBuffer &hdl); + virtual ~DrmGemBuffer(); + uint32_t GetFbId() const + { + return mFdId; + } + bool IsValid(); + +private: + void Init(int drmFd, HdiLayerBuffer &hdl); + uint32_t mGemHandle = 0; + uint32_t mFdId = 0; + int mDrmFd = -1; // the fd can not close. the other module will close it. + uint32_t mDrmFormat = DRM_FORMAT_INVALID; +}; + +class HdiDrmLayer : public HdiLayer { +public: + explicit HdiDrmLayer(LayerType type) : HdiLayer(type) {} + virtual ~HdiDrmLayer() {} + // Return value optimization + DrmGemBuffer *GetGemBuffer(); + +private: + std::unique_ptr mCurrentBuffer; + std::unique_ptr mLastBuffer; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DRM_LAYER_H diff --git a/hardware/display/src/display_device/hdi_gfx_composition.cpp b/hardware/display/src/display_device/hdi_gfx_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69feb169582933ab335b01dbdbbb5bb918889a46 --- /dev/null +++ b/hardware/display/src/display_device/hdi_gfx_composition.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_gfx_composition.h" +#include +#include +#include +#include "display_gfx.h" + +#define LIB_HDI_GFX_NAME "libdisplay_gfx.z.so" +#define LIB_GFX_FUNC_INIT "GfxInitialize" +#define LIB_GFX_FUNC_DEINIT "GfxUninitialize" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +int32_t HdiGfxComposition::Init(void) +{ + DISPLAY_LOGD(); + int32_t ret = GfxModuleInit(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS) || (mGfxFuncs == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("GfxModuleInit failed")); + ret = mGfxFuncs->InitGfx(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("gfx init failed")); + return DISPLAY_SUCCESS; +} + +int32_t HdiGfxComposition::GfxModuleInit(void) +{ + DISPLAY_LOGD(); + mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW | RTLD_NOLOAD); + if (mGfxModule != nullptr) { + DISPLAY_LOGI("Module '%{public}s' already loaded", LIB_HDI_GFX_NAME); + } else { + DISPLAY_LOGI("Loading module '%{public}s'", LIB_HDI_GFX_NAME); + mGfxModule = dlopen(LIB_HDI_GFX_NAME, RTLD_NOW); + if (mGfxModule == nullptr) { + DISPLAY_LOGE("Failed to load module: %{public}s", dlerror()); + return DISPLAY_FAILURE; + } + } + + using InitFunc = int32_t (*)(GfxFuncs **funcs); + InitFunc func = reinterpret_cast(dlsym(mGfxModule, LIB_GFX_FUNC_INIT)); + if (func == nullptr) { + DISPLAY_LOGE("Failed to lookup %{public}s function: %s", LIB_GFX_FUNC_INIT, dlerror()); + dlclose(mGfxModule); + return DISPLAY_FAILURE; + } + return func(&mGfxFuncs); +} + +int32_t HdiGfxComposition::GfxModuleDeinit(void) +{ + DISPLAY_LOGD(); + int32_t ret = DISPLAY_SUCCESS; + if (mGfxModule == nullptr) { + using DeinitFunc = int32_t (*)(GfxFuncs *funcs); + DeinitFunc func = reinterpret_cast(dlsym(mGfxModule, LIB_GFX_FUNC_DEINIT)); + if (func == nullptr) { + DISPLAY_LOGE("Failed to lookup %{public}s function: %s", LIB_GFX_FUNC_DEINIT, dlerror()); + } else { + ret = func(mGfxFuncs); + } + dlclose(mGfxModule); + } + return ret; +} + +bool HdiGfxComposition::CanHandle(HdiLayer &hdiLayer) +{ + DISPLAY_LOGD(); + (void)hdiLayer; + return true; +} + +int32_t HdiGfxComposition::SetLayers(std::vector &layers, HdiLayer &clientLayer) +{ + DISPLAY_LOGD("layers size %{public}zd", layers.size()); + mClientLayer = &clientLayer; + mCompLayers.clear(); + for (auto &layer : layers) { + if (CanHandle(*layer)) { + if ((layer->GetCompositionType() != COMPOSITION_VIDEO) && + (layer->GetCompositionType() != COMPOSITION_CURSOR)) { + layer->SetDeviceSelect(COMPOSITION_DEVICE); + } else { + layer->SetDeviceSelect(layer->GetCompositionType()); + } + mCompLayers.push_back(layer); + } + } + DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size()); + return DISPLAY_SUCCESS; +} + +void HdiGfxComposition::InitGfxSurface(ISurface &surface, HdiLayerBuffer &buffer) +{ + surface.width = buffer.GetWight(); + surface.height = buffer.GetHeight(); + surface.phyAddr = buffer.GetFb();//buffer.GetPhysicalAddr(); +// surface.fd = buffer.GetFb(); + surface.enColorFmt = (PixelFormat)buffer.GetFormat(); + surface.stride = buffer.GetStride(); + surface.bAlphaExt1555 = true; + surface.bAlphaMax255 = true; + surface.alpha0 = 0XFF; + surface.alpha1 = 0XFF; + DISPLAY_LOGD("surface fd %{public}d w:%{public}d h:%{public}d addr:0x%{public}" PRIx64 " fmt:%{public}d stride:%{public}d", + buffer.GetFb(), surface.width, surface.height, buffer.GetPhysicalAddr(), surface.enColorFmt, surface.stride); +} + +// now not handle the alpha of layer +int32_t HdiGfxComposition::BlitLayer(HdiLayer &src, HdiLayer &dst) +{ + ISurface srcSurface = { 0 }; + ISurface dstSurface = { 0 }; + GfxOpt opt = { 0 }; + DISPLAY_LOGD(); + HdiLayerBuffer *srcBuffer = src.GetCurrentBuffer(); + DISPLAY_CHK_RETURN((srcBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the srcbuffer is null")); + DISPLAY_LOGD("init the src surface"); + InitGfxSurface(srcSurface, *srcBuffer); + + HdiLayerBuffer *dstBuffer = dst.GetCurrentBuffer(); + DISPLAY_CHK_RETURN((dstBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get client layer buffer")); + DISPLAY_LOGD("init the dst surface"); + InitGfxSurface(dstSurface, *dstBuffer); + + opt.blendType = src.GetLayerBlenType(); + DISPLAY_LOGD("blendType %{public}d", opt.blendType); + opt.enPixelAlpha = true; + opt.enableScale = true; + + if (src.GetAlpha().enGlobalAlpha) { // is alpha is 0xff we not set it + opt.enGlobalAlpha = true; + srcSurface.alpha0 = src.GetAlpha().gAlpha; + DISPLAY_LOGD("src alpha %{public}x", src.GetAlpha().gAlpha); + } + opt.rotateType = src.GetTransFormType(); + DISPLAY_LOGD(" the roate type is %{public}d", opt.rotateType); + IRect crop = src.GetLayerCrop(); + IRect displayRect = src.GetLayerDisplayRect(); + DISPLAY_LOGD("crop x: %{public}d y : %{public}d w : %{public}d h: %{public}d", crop.x, crop.y, crop.w, crop.h); + DISPLAY_LOGD("displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", displayRect.x, displayRect.y, + displayRect.w, displayRect.h); + DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Blit: mGfxFuncs is null")); + return mGfxFuncs->Blit(&srcSurface, &crop, &dstSurface, &displayRect, &opt); +} + +int32_t HdiGfxComposition::ClearRect(HdiLayer &src, HdiLayer &dst) +{ + ISurface dstSurface = { 0 }; + GfxOpt opt = { 0 }; + DISPLAY_LOGD(); + HdiLayerBuffer *dstBuffer = dst.GetCurrentBuffer(); + DISPLAY_CHK_RETURN((dstBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get client layer buffer")); + InitGfxSurface(dstSurface, *dstBuffer); + IRect rect = src.GetLayerDisplayRect(); + DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Rect: mGfxFuncs is null")); + return mGfxFuncs->FillRect(&dstSurface, &rect, 0, &opt); +} + +int32_t HdiGfxComposition::Apply(bool modeSet) +{ + int32_t ret; + DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size()); + for (uint32_t i = 0; i < mCompLayers.size(); i++) { + HdiLayer *layer = mCompLayers[i]; + CompositionType compType = layer->GetCompositionType(); + switch (compType) { + case COMPOSITION_VIDEO: + ret = ClearRect(*layer, *mClientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("clear layer %{public}d failed", i)); + break; + case COMPOSITION_DEVICE: + ret = BlitLayer(*layer, *mClientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("blit layer %{public}d failed ", i)); + break; + default: + DISPLAY_LOGE("the gfx composition can not surpport the type %{public}d", compType); + break; + } + } + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/hdi_gfx_composition.h b/hardware/display/src/display_device/hdi_gfx_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..7d09be44c908204d3e54f85913325687e79f9d66 --- /dev/null +++ b/hardware/display/src/display_device/hdi_gfx_composition.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_GFX_COMPOSITION_H +#define HDI_GFX_COMPOSITION_H +#include "display_gfx.h" +#include "hdi_composer.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiGfxComposition : public HdiComposition { +public: + int32_t Init(void) override; + int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer) override; + int32_t Apply(bool modeSet) override; + virtual ~HdiGfxComposition() + { + (void)GfxModuleDeinit(); + } + +private: + bool CanHandle(HdiLayer &hdiLayer); + void InitGfxSurface(ISurface &surface, HdiLayerBuffer &buffer); + int32_t BlitLayer(HdiLayer &src, HdiLayer &dst); + int32_t ClearRect(HdiLayer &src, HdiLayer &dst); + int32_t GfxModuleInit(void); + int32_t GfxModuleDeinit(void); + void *mGfxModule = nullptr; + GfxFuncs *mGfxFuncs = nullptr; + HdiLayer *mClientLayer; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_GFX_COMPOSITION_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_layer.cpp b/hardware/display/src/display_device/hdi_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e862e5943b606643082094aa5ef3a83c172cf9b4 --- /dev/null +++ b/hardware/display/src/display_device/hdi_layer.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_layer.h" +#include +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +uint32_t HdiLayer::mIdleId = 0; +std::unordered_set HdiLayer::mIdSets; + +HdiLayerBuffer::HdiLayerBuffer(const BufferHandle &hdl) + : mPhyAddr(hdl.phyAddr), mHeight(hdl.height), mWidth(hdl.width), mStride(hdl.stride), mFormat(hdl.format) +{ + DISPLAY_LOGD(); + mFd = dup(hdl.fd); + mHandle = hdl; + if (mFd < 0) { + DISPLAY_LOGE("the fd : %{public}d dup failed errno %{public}d", hdl.fd, errno); + } +} + +HdiLayerBuffer::~HdiLayerBuffer() +{ + DISPLAY_LOGD(); + if (mFd >= 0) { + close(mFd); + } +} + +HdiLayerBuffer &HdiLayerBuffer::operator = (const BufferHandle &right) +{ + DISPLAY_LOGD(); + if (mFd >= 0) { + close(mFd); + } + mFd = right.fd; + mPhyAddr = right.phyAddr; + mWidth = right.width; + mHeight = right.height; + mStride = right.stride; + mFormat = right.format; + return *this; +} + +uint32_t HdiLayer::GetIdleId() +{ + const uint32_t oldIdleId = mIdleId; + uint32_t id = INVALIDE_LAYER_ID; + // ensure the mIdleId not INVALIDE_LAYER_ID + mIdleId = mIdleId % INVALIDE_LAYER_ID; + do { + auto iter = mIdSets.find(mIdleId); + if (iter == mIdSets.end()) { + id = mIdleId; + break; + } + mIdleId = (mIdleId + 1) % INVALIDE_LAYER_ID; + } while (oldIdleId != mIdleId); + mIdSets.emplace(id); + mIdleId++; + DISPLAY_LOGD("id %{public}d mIdleId %{public}d", id, mIdleId); + return id; +} + +int32_t HdiLayer::Init() +{ + DISPLAY_LOGD(); + uint32_t id = GetIdleId(); + DISPLAY_CHK_RETURN((id == INVALIDE_LAYER_ID), DISPLAY_FAILURE, DISPLAY_LOGE("have no id to used")); + mId = id; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerSize(IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr")); + DISPLAY_LOGD(" displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", rect->x, rect->y, rect->w, + rect->h); + mDisplayRect = *rect; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerCrop(IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr")); + DISPLAY_LOGD("id : %{public}d crop x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId, rect->x, + rect->y, rect->w, rect->h); + mCrop = *rect; + return DISPLAY_SUCCESS; +} + +void HdiLayer::SetLayerZorder(uint32_t zorder) +{ + DISPLAY_LOGD("id : %{public}d zorder : %{public}d ", mId, zorder); + mZorder = zorder; +} + +int32_t HdiLayer::SetLayerPreMulti(bool preMul) +{ + DISPLAY_LOGD(); + mPreMul = preMul; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerAlpha(LayerAlpha *alpha) +{ + DISPLAY_CHK_RETURN((alpha == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in alpha is nullptr")); + DISPLAY_LOGD("enable alpha %{public}d galpha 0x%{public}x", alpha->enGlobalAlpha, alpha->gAlpha); + mAlpha = *alpha; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetTransformMode(TransformType type) +{ + DISPLAY_LOGD("TransformType %{public}d", type); + mTransformType = type; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerDirtyRegion(IRect *region) +{ + DISPLAY_CHK_RETURN((region == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the in rect is null")); + DISPLAY_LOGD("id : %{public}d DirtyRegion x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId, + region->x, region->y, region->w, region->h); + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerVisibleRegion(uint32_t num, IRect *rect) +{ + DISPLAY_LOGD("id : %{public}d DirtyRegion x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId, rect->x, + rect->y, rect->w, rect->h); + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerBuffer(const BufferHandle *buffer, int32_t fence) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((buffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is nullptr")); + std::unique_ptr layerbuffer = std::make_unique(*buffer); + mHdiBuffer = std::move(layerbuffer); + mAcquireFence = fence; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerCompositionType(CompositionType type) +{ + DISPLAY_LOGD("CompositionType type %{public}d", type); + mCompositionType = type; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerBlendType(BlendType type) +{ + DISPLAY_LOGD("BlendType type %{public}d", type); + mBlendType = type; + return DISPLAY_SUCCESS; +} + +void HdiLayer::SetPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + const int32_t pixelBytes = 4; + DISPLAY_CHK_RETURN_NOT_VALUE((handle.format <= 0), + DISPLAY_LOGE("CheckPixel do not support format %{public}d", handle.format)); + DISPLAY_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), DISPLAY_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width), + DISPLAY_LOGE("CheckPixel invalid parameter x:%{public}d width:%{public}d", x, handle.width)); + DISPLAY_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height), + DISPLAY_LOGE("CheckPixel invalid parameter y:%{public}d height:%{public}d", y, handle.height)); + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + *pixel = color; +} + +void HdiLayer::ClearColor(uint32_t color) +{ + DISPLAY_LOGD(); + BufferHandle &handle = mHdiBuffer->mHandle; + for (int32_t x = 0; x < handle.width; x++) { + for (int32_t y = 0; y < handle.height; y++) { + SetPixel(handle, x, y, color); + } + } +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/hardware/display/src/display_device/hdi_layer.h b/hardware/display/src/display_device/hdi_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..b4042cbd3f7ce694cc1849f3125a6cc9e3c66d59 --- /dev/null +++ b/hardware/display/src/display_device/hdi_layer.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_LAYER_H +#define HDI_LAYER_H +#include +#include +#include "buffer_handle.h" +#include "display_common.h" +#include "hdi_device_common.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const uint32_t INVALIDE_LAYER_ID = 0xffffffff; +struct HdiLayerBuffer { +public: + explicit HdiLayerBuffer(const BufferHandle &hdl); + virtual ~HdiLayerBuffer(); + HdiLayerBuffer &operator = (const BufferHandle &right); + uint64_t GetPhysicalAddr() const + { + return mPhyAddr; + } + int32_t GetHeight() const + { + return mHeight; + } + int32_t GetWight() const + { + return mWidth; + } + int32_t GetStride() const + { + return mStride; + } + int32_t GetFormat() const + { + return mFormat; + } + int GetFb() const + { + return mFd; + } + BufferHandle mHandle; + +private: + uint64_t mPhyAddr = 0; + int32_t mHeight = 0; + int32_t mWidth = 0; + int32_t mStride = 0; + int32_t mFormat = 0; + int mFd = -1; +}; + +class HdiLayer { +public: + explicit HdiLayer(LayerType type) : mType(type) {} + int32_t Init(); + uint32_t GetId() const + { + return mId; + } + uint32_t GetZorder() const + { + return mZorder; + } + const IRect &GetLayerDisplayRect() const + { + return mDisplayRect; + } + const IRect &GetLayerCrop() const + { + return mCrop; + } + bool GetLayerPreMulti() const + { + return mPreMul; + } + const LayerAlpha &GetAlpha() const + { + return mAlpha; + } + LayerType GetType() const + { + return mType; + } + TransformType GetTransFormType() const + { + return mTransformType; + } + BlendType GetLayerBlenType() const + { + return mBlendType; + } + CompositionType GetCompositionType() const + { + return mCompositionType; + } + void SetDeviceSelect(CompositionType type) + { + DISPLAY_LOGD("%{public}d", type); + mDeviceSelect = type; + } + CompositionType GetDeviceSelect() const + { + return mDeviceSelect; + } + + int GetAcquireFenceFd() + { + return mAcquireFence.GetFd(); + } + int GetReleaseFenceFd() + { + return mReleaseFence.GetFd(); + } + void SetReleaseFence(int fd) + { + mReleaseFence = fd; + }; + void ClearColor(uint32_t color); + + void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color); + + virtual int32_t SetLayerSize(IRect *rect); + virtual int32_t SetLayerCrop(IRect *rect); + virtual void SetLayerZorder(uint32_t zorder); + virtual int32_t SetLayerPreMulti(bool preMul); + virtual int32_t SetLayerAlpha(LayerAlpha *alpha); + virtual int32_t SetTransformMode(TransformType type); + virtual int32_t SetLayerDirtyRegion(IRect *region); + virtual int32_t SetLayerVisibleRegion(uint32_t num, IRect *rect); + virtual int32_t SetLayerBuffer(const BufferHandle *buffer, int32_t fence); + virtual int32_t SetLayerCompositionType(CompositionType type); + virtual int32_t SetLayerBlendType(BlendType type); + virtual HdiLayerBuffer *GetCurrentBuffer() + { + return mHdiBuffer.get(); + } + virtual ~HdiLayer() {} + +private: + static uint32_t GetIdleId(); + static uint32_t mIdleId; + static std::unordered_set mIdSets; + + uint32_t mId = 0; + HdiFd mAcquireFence; + HdiFd mReleaseFence; + LayerType mType; + + IRect mDisplayRect; + IRect mCrop; + uint32_t mZorder = -1; + bool mPreMul = false; + LayerAlpha mAlpha; + TransformType mTransformType; + CompositionType mCompositionType = COMPOSITION_CLIENT; + CompositionType mDeviceSelect = COMPOSITION_CLIENT; + BlendType mBlendType; + std::unique_ptr mHdiBuffer; +}; + +struct SortLayersByZ { + bool operator () (const HdiLayer *lhs, const HdiLayer *rhs) const + { + if (lhs == nullptr || rhs == nullptr) { + return (lhs == nullptr) && (rhs == nullptr); + } + return lhs->GetZorder() < rhs->GetZorder(); + } +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_LAYER_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_netlink_monitor.cpp b/hardware/display/src/display_device/hdi_netlink_monitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a58290c2fd4e90e5976e1cc84e10ad6a22ea089 --- /dev/null +++ b/hardware/display/src/display_device/hdi_netlink_monitor.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_netlink_monitor.h" +#include +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiNetLinkMonitor::HdiNetLinkMonitor() +{ + DISPLAY_LOGD(); +} + +int HdiNetLinkMonitor::Init() +{ + DISPLAY_LOGD(); + int fd; + struct sockaddr_nl snl = { 0 }; + int ret; + const int32_t bufferSize = 1024; + DISPLAY_CHK_RETURN((mScoketFd < 0), DISPLAY_FAILURE, DISPLAY_LOGE("the socket has initial")); + fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + DISPLAY_CHK_RETURN((fd < 0), DISPLAY_FAILURE, DISPLAY_LOGE("scoket create failed")); + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); + ret = bind(fd, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl)); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("bind failed errno : %{public}d", errno)); + + mThread = std::make_unique([this]() { + mRunning = true; + MonitorThread(); + }); + mScoketFd = fd; + return DISPLAY_SUCCESS; +} + +HdiNetLinkMonitor::~HdiNetLinkMonitor() +{ + DISPLAY_LOGD(); + if (mScoketFd >= 0) { + close(mScoketFd); + } +} + +Void HdiNetLinkMonitor::MonitorThread() +{ + DISPLAY_LOGD(); + constexpr int BUFFER_SIZE = UEVENT_BUFFER_SIZE * 2; + while (mRunning) { + char buf[BUFFER_SIZE] = { 0 }; + recv(mScoketFd, &buf, sizeof(buf), 0); + } +} +} //DISPLAY +} //HDI +} //OHOS \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_netlink_monitor.h b/hardware/display/src/display_device/hdi_netlink_monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..f46af61b14c8389580f9ad9862d5146f7fbd546b --- /dev/null +++ b/hardware/display/src/display_device/hdi_netlink_monitor.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_NETLINK_NONITOR_H +#define HDI_NETLINK_NONITOR_H +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiNetLinkMonitor { +public: + HdiNetLinkMonitor(); + int Init(); + virtual ~HdiNetLinkMonitor(); + +private: + Void MonitorThread(); + volatile bool mRunning = false; + int mScoketFd = -1; + std::unique_ptr mThread; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_NETLINK_NONITOR_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_session.cpp b/hardware/display/src/display_device/hdi_session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cac2fb388a419541aaaa4ef94691c343e362c80f --- /dev/null +++ b/hardware/display/src/display_device/hdi_session.cpp @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "display_common.h" +#include "display_device.h" +#include "display_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiSession &HdiSession::GetInstance() +{ + static HdiSession instance; + static std::once_flag once; + std::call_once(once, [&]() { instance.Init(); }); + return instance; +} + +void HdiSession::Init() +{ + DISPLAY_LOGD(); + mHdiDevices = HdiDeviceInterface::DiscoveryDevice(); + DISPLAY_LOGD("devices size %{public}zd", mHdiDevices.size()); + mHdiDisplays.clear(); + for (auto device : mHdiDevices) { + auto displays = device->DiscoveryDisplay(); + mHdiDisplays.insert(displays.begin(), displays.end()); + } +} + +int32_t HdiSession::RegHotPlugCallback(HotPlugCallback callback, void *data) +{ + DISPLAY_CHK_RETURN((callback == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the callback is nullptr")); + mHotPlugCallBacks.emplace(callback, data); + for (auto displayMap : mHdiDisplays) { + auto display = displayMap.second; + if (display->IsConnected()) { + DoHotPlugCallback(display->GetId(), true); + } + } + return DISPLAY_SUCCESS; +} + +void HdiSession::DoHotPlugCallback(uint32_t devId, bool connect) +{ + DISPLAY_LOGD(); + for (const auto &callback : mHotPlugCallBacks) { + callback.first(devId, connect, callback.second); + } +} +} // OHOS +} // HDI +} // DISPLAY + +using namespace OHOS::HDI::DISPLAY; +static int32_t RegHotPlugCallback(HotPlugCallback callback, void *data) +{ + DISPLAY_LOGD(); + HdiSession::GetInstance().RegHotPlugCallback(callback, data); + return DISPLAY_SUCCESS; +} + +static int32_t GetDisplayCapability(uint32_t devId, DisplayCapability *info) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN(info == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("info is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCapability, info); +} + +static int32_t GetDisplaySuppportedModes(uint32_t devId, int *num, DisplayModeInfo *modes) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN(num == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplaySuppportedModes, num, modes); +} + +static int32_t GetDisplayMode(uint32_t devId, uint32_t *mode) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((mode == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("mode is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayMode, mode); +} + +static int32_t SetDisplayMode(uint32_t devId, uint32_t mode) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayMode, mode); +} + +static int32_t GetDisplayPowerStatus(uint32_t devId, DispPowerStatus *status) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((status == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("status is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayPowerStatus, status); +} + +static int32_t SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayPowerStatus, status); +} + +static int32_t GetDisplayBacklight(uint32_t devId, uint32_t *value) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayBacklight, value); +} + +static int32_t SetDisplayBacklight(uint32_t devId, uint32_t value) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayBacklight, value); +} + +static int32_t GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t *value) +{ + DISPLAY_LOGD(); + (void)id; + DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value) +{ + DISPLAY_LOGD(); + (void)id; + return DISPLAY_NOT_SUPPORT; +} + +static int32_t PrepareDisplayLayers(uint32_t devId, bool *needFlushFb) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((needFlushFb == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("needFlushFb is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::PrepareDisplayLayers, needFlushFb); +} + +static int32_t GetDisplayCompChange(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *type) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCompChange, num, layers, type); +} + +static int32_t SetDisplayClientCrop(uint32_t devId, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayClientDestRect(uint32_t devId, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayClientBuffer(uint32_t devId, const BufferHandle *buffer, int32_t fence) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayClientBuffer, buffer, fence); +} + +static int32_t SetDisplayClientDamage(uint32_t devId, uint32_t num, IRect *rect) +{ + DISPLAY_LOGD(); + (void)num; + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayVsyncEnabled(uint32_t devId, bool enabled) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayVsyncEnabled, enabled); +} + +static int32_t RegDisplayVBlankCallback(uint32_t devId, VBlankCallback callback, void *data) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::RegDisplayVBlankCallback, callback, data); +} + +static int32_t GetDisplayReleaseFence(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *fences) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayReleaseFence, num, layers, + fences); +// return DISPLAY_NOT_SUPPORT; +} + +static int32_t Commit(uint32_t devId, int32_t *fence) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((fence == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("fence is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::Commit, fence); +} + +static int32_t CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format, uint32_t *devId) +{ + DISPLAY_LOGD(); + return DISPLAY_NOT_SUPPORT; +} +static int32_t DestroyVirtualDisplay(uint32_t devId) +{ + DISPLAY_LOGD(); + return DISPLAY_NOT_SUPPORT; +} +static int32_t SetVirtualDisplayBuffer(uint32_t devId, BufferHandle *buffer, int32_t releaseFence) +{ + DISPLAY_LOGD(); + return DISPLAY_NOT_SUPPORT; +} + + +// Layer function +static int32_t CreateLayer(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((layerId == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("layerId is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CreateLayer, layerInfo, layerId); +} + +static int32_t CloseLayer(uint32_t devId, uint32_t layerId) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CloseLayer, layerId); +} + +static int32_t SetLayerSize(uint32_t devId, uint32_t layerId, IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerSize, rect); +} + +static int32_t SetLayerCrop(uint32_t devId, uint32_t layerId, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCrop, rect); +} + +static int32_t SetLayerZorder(uint32_t devId, uint32_t layerId, uint32_t zorder) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetLayerZorder, layerId, zorder); +} + +static int32_t SetLayerPreMulti(uint32_t devId, uint32_t layerId, bool preMul) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerPreMulti, preMul); +} + +static int32_t SetLayerAlpha(uint32_t devId, uint32_t layerId, LayerAlpha *alpha) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((alpha == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("alpha is nullptr")); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerAlpha, alpha); +} + +static int32_t SetTransformMode(uint32_t devId, uint32_t layerId, TransformType type) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetTransformMode, type); +} + +static int32_t SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, IRect *region) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((region == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("region is nullptr")); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerDirtyRegion, region); +} + +static int32_t SetLayerVisibleRegion(uint32_t devId, uint32_t layerId, uint32_t num, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerVisibleRegion, num, rect); +} + +static int32_t SetLayerBuffer(uint32_t devId, uint32_t layerId, const BufferHandle *buffer, int32_t fence) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBuffer, buffer, fence); +} + +static int32_t SetLayerCompositionType(uint32_t devId, uint32_t layerId, CompositionType type) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCompositionType, type); +} + +static int32_t SetLayerBlendType(uint32_t devId, uint32_t layerId, BlendType type) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBlendType, type); +} + + +extern "C" { +int32_t DeviceInitialize(DeviceFuncs **funcs) +{ + DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in funcs is null")); + DeviceFuncs *dFuncs = (DeviceFuncs *)calloc(1, sizeof(DeviceFuncs)); + DISPLAY_CHK_RETURN((dFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not calloc")); + + dFuncs->RegHotPlugCallback = RegHotPlugCallback; + dFuncs->GetDisplayCapability = GetDisplayCapability; + dFuncs->GetDisplaySuppportedModes = GetDisplaySuppportedModes; + dFuncs->GetDisplayMode = GetDisplayMode; + dFuncs->SetDisplayMode = SetDisplayMode; + dFuncs->GetDisplayPowerStatus = GetDisplayPowerStatus; + dFuncs->SetDisplayPowerStatus = SetDisplayPowerStatus; + dFuncs->PrepareDisplayLayers = PrepareDisplayLayers; + dFuncs->GetDisplayBacklight = GetDisplayBacklight; + dFuncs->SetDisplayBacklight = SetDisplayBacklight; + dFuncs->GetDisplayProperty = GetDisplayProperty; + dFuncs->GetDisplayCompChange = GetDisplayCompChange; + dFuncs->SetDisplayClientCrop = SetDisplayClientCrop; + dFuncs->SetDisplayClientDestRect = SetDisplayClientDestRect; + dFuncs->SetDisplayClientBuffer = SetDisplayClientBuffer; + dFuncs->SetDisplayClientDamage = SetDisplayClientDamage; + dFuncs->SetDisplayVsyncEnabled = SetDisplayVsyncEnabled; + dFuncs->RegDisplayVBlankCallback = RegDisplayVBlankCallback; + dFuncs->GetDisplayReleaseFence = GetDisplayReleaseFence; + dFuncs->CreateVirtualDisplay = CreateVirtualDisplay; + dFuncs->DestroyVirtualDisplay = DestroyVirtualDisplay; + dFuncs->SetVirtualDisplayBuffer = SetVirtualDisplayBuffer; + dFuncs->SetDisplayProperty = SetDisplayProperty; + dFuncs->Commit = Commit; + *funcs = dFuncs; + DISPLAY_LOGD("%{public}s: device initialize success", __func__); + HdiSession::GetInstance(); + return DISPLAY_SUCCESS; +} + +int32_t DeviceUninitialize(DeviceFuncs *funcs) +{ + DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in funcs is null")); + free(funcs); + return DISPLAY_SUCCESS; +} + + +int32_t LayerInitialize(LayerFuncs **funcs) +{ + DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the in funcs is nullptr")); + LayerFuncs *lFuncs = (LayerFuncs *)calloc(1, sizeof(LayerFuncs)); + DISPLAY_CHK_RETURN((lFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not calloc errno: %{public}d", errno)); + lFuncs->SetLayerAlpha = SetLayerAlpha; + lFuncs->CreateLayer = CreateLayer; + lFuncs->CloseLayer = CloseLayer; + lFuncs->SetLayerSize = SetLayerSize; + lFuncs->SetLayerCrop = SetLayerCrop; + lFuncs->SetLayerZorder = SetLayerZorder; + lFuncs->SetLayerPreMulti = SetLayerPreMulti; + lFuncs->SetTransformMode = SetTransformMode; + lFuncs->SetLayerDirtyRegion = SetLayerDirtyRegion; + lFuncs->SetLayerVisibleRegion = SetLayerVisibleRegion; + lFuncs->SetLayerBuffer = SetLayerBuffer; + lFuncs->SetLayerCompositionType = SetLayerCompositionType; + lFuncs->SetLayerBlendType = SetLayerBlendType; + + *funcs = lFuncs; + DISPLAY_LOGD("%{public}s: layer initialize success", __func__); + return DISPLAY_SUCCESS; +} + +int32_t LayerUninitialize(LayerFuncs *funcs) +{ + DISPLAY_CHK_RETURN((funcs == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the funcs is nullptr")); + free(funcs); + DISPLAY_LOGD("%{public}s: layer uninitialize success", __func__); + return DISPLAY_SUCCESS; +} +} \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_session.h b/hardware/display/src/display_device/hdi_session.h new file mode 100644 index 0000000000000000000000000000000000000000..bed5d63561d2ae8823701aa9e1df151426a421e4 --- /dev/null +++ b/hardware/display/src/display_device/hdi_session.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_SESSION_H +#define HDI_SESSION_H +#include +#include +#include +#include "display_device.h" +#include "hdi_device_interface.h" +#include "hdi_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiSession { +public: + void Init(); + static HdiSession &GetInstance(); + + template + int32_t CallDisplayFunction(uint32_t devId, int32_t (HdiDisplay::*member)(Args...), Args... args) + { + DISPLAY_LOGD("device Id : %{public}d", devId); + DISPLAY_CHK_RETURN((devId == INVALIDE_DISPLAY_ID), DISPLAY_FAILURE, DISPLAY_LOGE("invalide device id")); + auto iter = mHdiDisplays.find(devId); + DISPLAY_CHK_RETURN((iter == mHdiDisplays.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find display %{public}d", devId)); + auto display = iter->second.get(); + return (display->*member)(std::forward(args)...); + } + + template + int32_t CallLayerFunction(uint32_t devId, uint32_t layerId, int32_t (HdiLayer::*member)(Args...), Args... args) + { + DISPLAY_LOGD("device Id : %{public}d", devId); + DISPLAY_CHK_RETURN((devId == INVALIDE_DISPLAY_ID), DISPLAY_FAILURE, DISPLAY_LOGE("invalide device id")); + auto iter = mHdiDisplays.find(devId); + DISPLAY_CHK_RETURN((iter == mHdiDisplays.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find display %{public}d", devId)); + auto display = iter->second.get(); + auto layer = display->GetHdiLayer(layerId); + DISPLAY_CHK_RETURN((layer == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find the layer %{public}d", layerId)); + return (layer->*member)(std::forward(args)...); + } + + int32_t RegHotPlugCallback(HotPlugCallback callback, void *data); + void DoHotPlugCallback(uint32_t devId, bool connect); + +private: + std::unordered_map> mHdiDisplays; + std::vector> mHdiDevices; + std::unordered_map mHotPlugCallBacks; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_SESSION_H \ No newline at end of file diff --git a/hardware/display/src/display_device/hdi_shared_fd.h b/hardware/display/src/display_device/hdi_shared_fd.h new file mode 100644 index 0000000000000000000000000000000000000000..b31b5af4dc6483fa5d8f00b76c34e63ff445e578 --- /dev/null +++ b/hardware/display/src/display_device/hdi_shared_fd.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_SHARED_FD +#define HDI_SHARED_FD +#include +#include +#include "display_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiFd { +public: + HdiFd() + { + DISPLAY_LOGD(); + } + explicit HdiFd(int fd) : mFd(fd) + { + DISPLAY_LOGD("mFd %{public}d", mFd); + } + int GetFd() const + { + return mFd; + }; + + HdiFd &operator = (int fd) + { + if (mFd >= 0) { + close(mFd); + } + mFd = fd; + return *this; + } + + virtual ~HdiFd() + { + if (mFd >= 0) { + close(mFd); + } + } + +private: + int mFd = -1; +}; + +using FdPtr = std::shared_ptr; +} // OHOS +} // HDIO +} // DISPLAY + +#endif // HDI_SHARED_FD \ No newline at end of file diff --git a/hardware/display/src/display_gfx/display_gfx.c b/hardware/display/src/display_gfx/display_gfx.c new file mode 100644 index 0000000000000000000000000000000000000000..4bd6647153cf0d5a4884d8723c0baf0130ef0cb2 --- /dev/null +++ b/hardware/display/src/display_gfx/display_gfx.c @@ -0,0 +1,468 @@ +/* + * Copyright 2015 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "display_gfx.h" +#include "im2d.h" +#include "rga.h" +#include "display_common.h" +#include +#include +#include "display_gralloc.h" + +#define ALIGN_UP(x, a) ((((x) + ((a)-1)) / (a)) * (a)) +GrallocFuncs *grallocFucs = NULL; +int32_t rkInitGfx() +{ + DISPLAY_LOGE("%s\n", querystring(RGA_ALL)); + return DISPLAY_SUCCESS; +} + +int32_t rkDeinitGfx() +{ + return DISPLAY_SUCCESS; +} + +RgaSURF_FORMAT colorSpaceModeChange(PixelFormat color, uint8_t *isYuv) +{ + RgaSURF_FORMAT rkFormat; + switch(color) { + case PIXEL_FMT_RGB_565: /**< RGB565 format */ + rkFormat = RK_FORMAT_RGB_565; + *isYuv = 0; + break; + case PIXEL_FMT_RGBA_4444: /**< RGBA4444 format */ + rkFormat = RK_FORMAT_RGBA_4444; + *isYuv = 0; + break; + case PIXEL_FMT_RGBA_5551: /**< RGBA5551 format */ + rkFormat = RK_FORMAT_RGBA_5551; + *isYuv = 0; + break; + case PIXEL_FMT_RGBX_8888: /**< RGBX8888 format */ + rkFormat = RK_FORMAT_RGBX_8888; + *isYuv = 0; + break; + case PIXEL_FMT_RGBA_8888: /**< RGBA8888 format */ + rkFormat = RK_FORMAT_RGBA_8888; + *isYuv = 0; + break; + case PIXEL_FMT_RGB_888: /**< RGB888 format */ + rkFormat = RK_FORMAT_RGB_888; + *isYuv = 0; + break; + case PIXEL_FMT_BGR_565: /**< BGR565 format */ + rkFormat = RK_FORMAT_BGR_565; + *isYuv = 0; + break; + case PIXEL_FMT_BGRA_4444: /**< BGRA4444 format */ + rkFormat = RK_FORMAT_BGRA_4444; + *isYuv = 0; + break; + case PIXEL_FMT_BGRA_5551: /**< BGRA5551 format */ + rkFormat = RK_FORMAT_BGRA_5551; + *isYuv = 0; + break; + case PIXEL_FMT_BGRX_8888: /**< BGRX8888 format */ + rkFormat = RK_FORMAT_BGRX_8888; + *isYuv = 0; + break; + case PIXEL_FMT_BGRA_8888: /**< BGRA8888 format */ + rkFormat = RK_FORMAT_BGRA_8888; + *isYuv = 0; + break; + case PIXEL_FMT_YCBCR_422_SP: /**< YCBCR422 semi-planar format */ + rkFormat = RK_FORMAT_YCbCr_420_SP; + *isYuv = 1; + break; + case PIXEL_FMT_YCRCB_422_SP: /**< YCRCB422 semi-planar format */ + rkFormat = RK_FORMAT_YCrCb_422_SP; + *isYuv = 1; + break; + case PIXEL_FMT_YCBCR_420_SP: /**< YCBCR420 semi-planar format */ + rkFormat = RK_FORMAT_YCbCr_420_SP; + *isYuv = 1; + break; + case PIXEL_FMT_YCRCB_420_SP: /**< YCRCB420 semi-planar format */ + rkFormat = RK_FORMAT_YCrCb_420_SP; + *isYuv = 1; + break; + case PIXEL_FMT_YCBCR_422_P: /**< YCBCR422 planar format */ + rkFormat = RK_FORMAT_YCbCr_422_P; + *isYuv = 1; + break; + case PIXEL_FMT_YCRCB_422_P: /**< YCRCB422 planar format */ + rkFormat = RK_FORMAT_YCrCb_422_P; + *isYuv = 1; + break; + case PIXEL_FMT_YCBCR_420_P: /**< YCBCR420 planar format */ + rkFormat = RK_FORMAT_YCbCr_420_P; + *isYuv = 1; + break; + case PIXEL_FMT_YCRCB_420_P: /**< YCRCB420 planar format */ + rkFormat = RK_FORMAT_YCrCb_420_P; + *isYuv = 1; + break; + case PIXEL_FMT_YUYV_422_PKG: /**< YUYV422 packed format */ + rkFormat = RK_FORMAT_YUYV_422; + *isYuv = 1; + break; + case PIXEL_FMT_UYVY_422_PKG: /**< UYVY422 packed format */ + rkFormat = RK_FORMAT_UYVY_422; + *isYuv = 1; + break; + case PIXEL_FMT_YVYU_422_PKG: /**< YVYU422 packed format */ + rkFormat = RK_FORMAT_YUYV_422; + *isYuv = 1; + break; + case PIXEL_FMT_VYUY_422_PKG: /**< VYUY422 packed format */ + rkFormat = RK_FORMAT_VYUY_422; + *isYuv = 1; + break; + default: +// PIXEL_FMT_CLUT8: /**< CLUT8 format */ +// PIXEL_FMT_CLUT1, /**< CLUT1 format */ +// PIXEL_FMT_CLUT4, /**< CLUT4 format */ +// PIXEL_FMT_RGBA_5658, /**< RGBA5658 format */ +// PIXEL_FMT_RGBX_4444, /**< RGBX4444 format */ +// PIXEL_FMT_RGB_444, /**< RGB444 format */ +// PIXEL_FMT_RGBX_5551, /**< RGBX5551 format */ +// PIXEL_FMT_RGB_555, /**< RGB555 format */ +// PIXEL_FMT_BGRX_4444, /**< BGRX4444 format */ +// PIXEL_FMT_BGRX_5551, /**< BGRX5551 format */ +// PIXEL_FMT_YUV_422_I, /**< YUV422 interleaved format */ + rkFormat = RK_FORMAT_UNKNOWN; + break; + } + return rkFormat; +} + +int32_t rkFillRect(ISurface *surface, IRect *rect, uint32_t color, GfxOpt *opt) +{ + rga_buffer_t dst; + im_rect imRect; + IM_STATUS ret; + uint8_t isYuv; + + memset((void *)&imRect, 0, sizeof(imRect)); + imRect.x = rect->x; + imRect.y = rect->y; + imRect.width = rect->w; + imRect.height = rect->h; + + memset((void *)&dst, 0, sizeof(dst)); + dst.phy_addr = 0;//(void*)surface->phyAddr; + dst.vir_addr = 0;//surface->virAddr; + dst.fd = (int32_t)surface->phyAddr; + if ((int)dst.phy_addr == 0 && dst.fd == 0 && dst.vir_addr == NULL) { + DISPLAY_LOGE("source surface address error"); + return DISPLAY_PARAM_ERR; + } + DISPLAY_LOGE("gfx vir %{public}p phy 0x%{public}x fd %{public}d",dst.vir_addr, (int32_t)dst.phy_addr, dst.fd); + dst.width = surface->width; + dst.height = surface->height; + dst.wstride = ALIGN_UP(surface->width, 16); + dst.hstride = ALIGN_UP(surface->height, 16); + dst.format = colorSpaceModeChange(surface->enColorFmt, &isYuv); + dst.color_space_mode = IM_COLOR_SPACE_DEFAULT; + dst.color = color; + if (opt->enGlobalAlpha) + dst.global_alpha = opt->globalAlpha; + ret = imfill(dst, imRect, color); + + if (ret != IM_STATUS_SUCCESS) + return DISPLAY_FAILURE; + else + return DISPLAY_SUCCESS; +} + +int32_t blendTypeChange(BlendType blendType) +{ + int32_t rkBlendType; + switch(blendType) { + case BLEND_SRC: /**< SRC blending */ + rkBlendType = IM_ALPHA_BLEND_SRC; + break; + case BLEND_DST: /**< SRC blending */ + rkBlendType = IM_ALPHA_BLEND_DST; + break; + case BLEND_SRCOVER: /**< SRC_OVER blending */ + rkBlendType = IM_ALPHA_BLEND_SRC_OVER; + break; + case BLEND_DSTOVER: /**< DST_OVER blending */ + rkBlendType = IM_ALPHA_BLEND_DST_OVER; + break; + default: + /* Fix up later */ +// BLEND_NONE /**< No blending */ +// BLEND_CLEAR: /**< CLEAR blending */ +// BLEND_SRCIN: /**< SRC_IN blending */ +// BLEND_DSTIN: /**< DST_IN blending */ +// BLEND_SRCOUT: /**< SRC_OUT blending */ +// BLEND_DSTOUT: /**< DST_OUT blending */ +// BLEND_SRCATOP: /**< SRC_ATOP blending */ +// BLEND_DSTATOP: /**< DST_ATOP blending */ +// BLEND_ADD: /**< ADD blending */ +// BLEND_XOR: /**< XOR blending */ +// BLEND_DST: /**< DST blending */ +// BLEND_AKS: /**< AKS blending */ +// BLEND_AKD: /**< AKD blending */ +// BLEND_BUTT: /**< Null operation */ + rkBlendType = IM_STATUS_NOT_SUPPORTED; + break; + } + return rkBlendType; +} + +int32_t TransformTypeChange(TransformType type) +{ + int32_t rkRotateType; + switch(type) { + case ROTATE_90: /**< Rotation by 90 degrees */ + rkRotateType = IM_HAL_TRANSFORM_ROT_90; + break; + case ROTATE_180: /**< Rotation by 180 degrees */ + rkRotateType = IM_HAL_TRANSFORM_ROT_180; + break; + case ROTATE_270: /**< Rotation by 270 degrees */ + rkRotateType = IM_HAL_TRANSFORM_ROT_270; + break; + default: + rkRotateType = 0; /**< No rotation */ + break; + } + return rkRotateType; +} + +int32_t mirrorTypeChange(MirrorType type) +{ + int32_t rkMirrorType; + switch(type) { + case MIRROR_LR: /**< Left and right mirrors */ + rkMirrorType = IM_HAL_TRANSFORM_FLIP_H; + break; + case MIRROR_TB: /**< Top and bottom mirrors */ + rkMirrorType = IM_HAL_TRANSFORM_FLIP_V; + break; + default: + rkMirrorType = 0; + break; + } + return rkMirrorType; +} + +int32_t doFlit(ISurface *srcSurface, IRect *srcRect, ISurface *dstSurface, IRect *dstRect, GfxOpt *opt) +{ + int32_t usage = 0; + uint8_t isYuv = 0; + rga_buffer_t dstRgaBuffer, srcRgaBuffer, bRgbBuffer; + IM_STATUS ret = 0; + im_rect srect; + im_rect drect; + im_rect prect; + int32_t rkBlendType = 0; + int32_t rkRotateType = 0; + int32_t rkMirrorType = 0; + + memset(&dstRgaBuffer, 0, sizeof(dstRgaBuffer)); + memset(&srcRgaBuffer, 0, sizeof(srcRgaBuffer)); + memset(&bRgbBuffer, 0, sizeof(bRgbBuffer)); + memset(&srect, 0, sizeof(srect)); + memset(&drect, 0, sizeof(drect)); + memset(&prect, 0, sizeof(prect)); + if (opt->enGlobalAlpha) { + dstRgaBuffer.global_alpha = opt->globalAlpha; + srcRgaBuffer.global_alpha = opt->globalAlpha; + } + dstRgaBuffer.width = dstSurface->width; + dstRgaBuffer.height = dstSurface->height; + dstRgaBuffer.wstride = ALIGN_UP(dstSurface->width, 16); + dstRgaBuffer.hstride = ALIGN_UP(dstSurface->height, 16); + dstRgaBuffer.format = colorSpaceModeChange(dstSurface->enColorFmt, &isYuv); + dstRgaBuffer.phy_addr = 0;//(void *)dstSurface->phyAddr; + dstRgaBuffer.vir_addr = 0;//dstSurface->virAddr; + dstRgaBuffer.color_space_mode = IM_COLOR_SPACE_DEFAULT; + dstRgaBuffer.fd = (int32_t)dstSurface->phyAddr; + if (isYuv == 1) { + DISPLAY_LOGE("rk gfx do not support dst buffer is yuv format"); + return DISPLAY_PARAM_ERR; + } + + srcRgaBuffer.width = srcSurface->width; + srcRgaBuffer.height = srcSurface->height; + srcRgaBuffer.wstride = ALIGN_UP(srcSurface->width, 16); + srcRgaBuffer.hstride = ALIGN_UP(srcSurface->height, 16); + srcRgaBuffer.phy_addr = 0;//(void *)srcSurface->phyAddr; + srcRgaBuffer.vir_addr = 0;//srcSurface->virAddr; + srcRgaBuffer.format = colorSpaceModeChange(srcSurface->enColorFmt, &isYuv); + srcRgaBuffer.color_space_mode = IM_COLOR_SPACE_DEFAULT; + srcRgaBuffer.fd = (int32_t)srcSurface->phyAddr; + + if ((int)srcRgaBuffer.phy_addr == 0 && srcRgaBuffer.fd == 0 && srcRgaBuffer.vir_addr == NULL) { + DISPLAY_LOGE("source surface address error"); + return DISPLAY_PARAM_ERR; + } + + DISPLAY_LOGE("gfx src fd %{public}d, w %{public}d, h %{publuc}d, sw %{public}d sh %{public}d vir %{public}p",(int32_t)srcSurface->phyAddr, srcSurface->width, + srcSurface->height, ALIGN_UP(srcSurface->width, 16), ALIGN_UP(srcSurface->height, 16), srcRgaBuffer.vir_addr); + DISPLAY_LOGE("gfx dst fd %{public}d, w %{public}d, h %{public}d, sw %{public}d sh %{public}d vir %{public}p",(int32_t)dstSurface->phyAddr, dstSurface->width, + dstSurface->height, ALIGN_UP(dstSurface->width, 16), ALIGN_UP(dstSurface->height, 16), dstRgaBuffer.vir_addr); + + srect.x = srcRect->x; + srect.y = srcRect->y; + srect.height = srcRect->h; + srect.width = srcRect->w; + drect.x = dstRect->x; + drect.y = dstRect->y; + drect.height = dstRect->h; + drect.width = dstRect->w; + + if (opt->blendType) { + rkBlendType = blendTypeChange(opt->blendType); + if (rkBlendType > 0) { + usage |= rkBlendType; + if (rkBlendType == IM_ALPHA_BLEND_DST_OVER || rkBlendType == IM_ALPHA_BLEND_SRC_OVER) + usage |= IM_ALPHA_BLEND_PRE_MUL; + } else if (rkBlendType == IM_STATUS_NOT_SUPPORTED) { + return DISPLAY_NOT_SUPPORT; + } + } + if (opt->rotateType) { + rkRotateType = TransformTypeChange(opt->rotateType); + if (rkRotateType != 0) + usage |= rkRotateType; + } + if (opt->mirrorType == MIRROR_LR || opt->mirrorType == MIRROR_TB) { + rkMirrorType = mirrorTypeChange(opt->mirrorType); + if (rkMirrorType != 0) + usage |= rkMirrorType; + } + if (opt->enableScale) { + DISPLAY_LOGE("gfx scale from (%{puhblic}d, %{public}d) to (%{public}d, %{public}d)", srcRgaBuffer.width, srcRgaBuffer.height, dstRgaBuffer.width, + dstRgaBuffer.height); + } + usage |= IM_SYNC; + if (isYuv == 1) { + if (rkBlendType == IM_ALPHA_BLEND_SRC_OVER || rkBlendType == IM_ALPHA_BLEND_SRC) { + usage = 0; + if (opt->enableScale == 0) { + memset(&srect, 0, sizeof(srect)); + srect.width = srcRgaBuffer.width; + srect.height = srcRgaBuffer.height; + + memset(&drect, 0, sizeof(drect)); + drect.x = dstRgaBuffer.width - srcRgaBuffer.width; + drect.y = dstRgaBuffer.height - srcRgaBuffer.height; + drect.width = srcRgaBuffer.width; + drect.height = srcRgaBuffer.height; + } + usage = rkRotateType | rkMirrorType | IM_SYNC; + ret = improcess(srcRgaBuffer, dstRgaBuffer, bRgbBuffer, srect, drect, prect, usage); + if (ret != IM_STATUS_SUCCESS) { + DISPLAY_LOGE("gfx improcess %{public}s", imStrError(ret)); + } + } else if (rkBlendType == IM_ALPHA_BLEND_DST_OVER) { + if (grallocFucs == NULL) { + ret = GrallocInitialize(&grallocFucs); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("Gralloc init failed")); + } + AllocInfo info = { + .width = dstRgaBuffer.width, + .height = dstRgaBuffer.height, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBA_8888,//srcSurface->enColorFmt, + }; + BufferHandle *buffer = NULL; + + ret = grallocFucs->AllocMem(&info, &buffer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not alloc memory")); + + bRgbBuffer.width = dstRgaBuffer.width; + bRgbBuffer.height = dstRgaBuffer.height; + bRgbBuffer.wstride = dstRgaBuffer.wstride; + bRgbBuffer.hstride = dstRgaBuffer.hstride; + bRgbBuffer.format = RK_FORMAT_RGBA_8888;//srcRgaBuffer.format; + bRgbBuffer.phy_addr = 0;//(void *) buffer->phyAddr; + bRgbBuffer.vir_addr = 0;//buffer->virAddr; + bRgbBuffer.color_space_mode = dstRgaBuffer.color_space_mode; + bRgbBuffer.fd = (int32_t)buffer->phyAddr; + memcpy(&prect, &drect, sizeof(drect)); + + ret = improcess(srcRgaBuffer, bRgbBuffer, dstRgaBuffer, srect, prect, drect, usage); + if (ret != IM_STATUS_SUCCESS) { + DISPLAY_LOGE("gfx improcess %{public}s", imStrError(ret)); + } else { + ret = imcopy(bRgbBuffer, dstRgaBuffer); + if (ret != IM_STATUS_SUCCESS) { + DISPLAY_LOGE("gfx improcess %{public}s", imStrError(ret)); + } + } + grallocFucs->FreeMem(buffer); + } + } else { + ret = improcess(srcRgaBuffer, dstRgaBuffer, bRgbBuffer, srect, drect, prect, usage); + if (ret != IM_STATUS_SUCCESS) { + DISPLAY_LOGE("gfx improcess %{public}s", imStrError(ret)); + } + } + if (ret != IM_STATUS_SUCCESS) + return DISPLAY_FAILURE; + else + return DISPLAY_SUCCESS; +} + +int32_t rkBlit(ISurface *srcSurface, IRect *srcRect, ISurface *dstSurface, IRect *dstRect, GfxOpt *opt) +{ + CHECK_NULLPOINTER_RETURN_VALUE(srcSurface, DISPLAY_NULL_PTR); + CHECK_NULLPOINTER_RETURN_VALUE(srcRect, DISPLAY_NULL_PTR); + CHECK_NULLPOINTER_RETURN_VALUE(dstSurface, DISPLAY_NULL_PTR); + CHECK_NULLPOINTER_RETURN_VALUE(dstRect, DISPLAY_NULL_PTR); + CHECK_NULLPOINTER_RETURN_VALUE(opt, DISPLAY_NULL_PTR); + + if (doFlit(srcSurface, srcRect, dstSurface, dstRect, opt) < 0) + return DISPLAY_FAILURE; + else + return DISPLAY_SUCCESS; +} + +int32_t rkSync(int32_t timeOut) +{ + return DISPLAY_SUCCESS; +} + +int32_t GfxInitialize(GfxFuncs **funcs) +{ + DISPLAY_CHK_RETURN((funcs == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("info is null")); + GfxFuncs *gfxFuncs = (GfxFuncs *)malloc(sizeof(GfxFuncs)); + memset((void *)gfxFuncs, 0, sizeof(GfxFuncs)); + + gfxFuncs->InitGfx = rkInitGfx; + gfxFuncs->DeinitGfx = rkDeinitGfx; + gfxFuncs->FillRect = rkFillRect; + gfxFuncs->Blit = rkBlit; + gfxFuncs->Sync = rkSync; + *funcs = gfxFuncs; + + return DISPLAY_SUCCESS; +} + +int32_t GfxUninitialize(GfxFuncs *funcs) +{ + CHECK_NULLPOINTER_RETURN_VALUE(funcs, DISPLAY_NULL_PTR); + free(funcs); + DISPLAY_LOGI("%s: gfx uninitialize success", __func__); + return DISPLAY_SUCCESS; +} + diff --git a/hardware/display/src/display_gralloc/display_gralloc.c b/hardware/display/src/display_gralloc/display_gralloc.c new file mode 100644 index 0000000000000000000000000000000000000000..49835812be55201e2abb8770b541f341761448d2 --- /dev/null +++ b/hardware/display/src/display_gralloc/display_gralloc.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "display_gralloc.h" +#include +#include +#include "display_common.h" +#include "display_gralloc_gbm.h" + +int32_t AllocMem(const AllocInfo *info, BufferHandle **handle) +{ + DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("info is null")); + DISPLAY_CHK_RETURN((handle == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (info->usage & HBM_USE_MEM_DMA) { + return GbmAllocMem(info, handle); + } +#endif + DISPLAY_LOGE("the usage is not support 0x%{public}" PRIx64 "", info->usage); + return DISPLAY_NOT_SUPPORT; +} + +void FreeMem(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((handle == NULL), DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (handle->usage & HBM_USE_MEM_DMA) { + GbmFreeMem(handle); + return; + } +#endif +} + +void *Mmap(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN((handle == NULL), NULL, DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (handle->usage & HBM_USE_MEM_DMA) { + return GbmMmap(handle); + } +#endif + return NULL; +} + +int32_t Unmap(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN((handle == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (handle->usage & HBM_USE_MEM_DMA) { + return GbmUnmap(handle); + } +#endif + return DISPLAY_NOT_SUPPORT; +} + +int32_t FlushCache(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN((handle == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (handle->usage & HBM_USE_MEM_DMA) { + return GbmFlushCache(handle); + } +#endif + return DISPLAY_NOT_SUPPORT; +} + +int32_t InvalidateCache(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN((handle == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("handle is null")); +#ifdef GRALLOC_GBM_SUPPORT + if (handle->usage & HBM_USE_MEM_DMA) { + return GbmInvalidateCache(handle); + } +#endif + return DISPLAY_NOT_SUPPORT; +} + +int32_t GrallocUninitialize(GrallocFuncs *funcs) +{ + DISPLAY_CHK_RETURN(funcs == NULL, DISPLAY_PARAM_ERR, DISPLAY_LOGE("funcs is null")); + DISPLAY_LOGD(); +#ifdef GRALLOC_GBM_SUPPORT + if (GbmGrallocUninitialize() != DISPLAY_SUCCESS) { + DISPLAY_LOGE("gbm uninit failed"); + } +#endif + free(funcs); + return DISPLAY_SUCCESS; +} + +int32_t GrallocInitialize(GrallocFuncs **funcs) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((funcs == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("funcs is null")); + GrallocFuncs *grallocFuncs = (GrallocFuncs *)malloc(sizeof(GrallocFuncs)); + DISPLAY_CHK_RETURN((grallocFuncs == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("memset_s failed")); + errno_t eok = memset_s(grallocFuncs, sizeof(GrallocFuncs), 0, sizeof(GrallocFuncs)); + DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_FAILURE, DISPLAY_LOGE("memset_s failed")); + // initialize gbm gralloc +#ifdef GRALLOC_GBM_SUPPORT + int ret = GbmGrallocInitialize(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_LOGE("gbm initial"); free(grallocFuncs)); +#endif + grallocFuncs->AllocMem = AllocMem; + grallocFuncs->FreeMem = FreeMem; + grallocFuncs->Mmap = Mmap; + grallocFuncs->Unmap = Unmap; + grallocFuncs->InvalidateCache = InvalidateCache; + grallocFuncs->FlushCache = FlushCache; + *funcs = grallocFuncs; + return DISPLAY_SUCCESS; +} \ No newline at end of file diff --git a/hardware/display/src/display_gralloc/display_gralloc_gbm.c b/hardware/display/src/display_gralloc/display_gralloc_gbm.c new file mode 100644 index 0000000000000000000000000000000000000000..f1c93238269cc7b95132040d8401c6debf938be3 --- /dev/null +++ b/hardware/display/src/display_gralloc/display_gralloc_gbm.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "display_gralloc_gbm.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wayland_drm_auth_client.h" +#include "drm_fourcc.h" +#include "hisilicon_drm.h" +#include "hi_gbm.h" +#include "hdf_dlist.h" +#include "display_gralloc_private.h" +#include "display_common.h" + +const char *g_drmFileNode = "/dev/dri/renderD128"; +static GrallocManager *g_grallocManager = NULL; +static pthread_mutex_t g_lock; + +typedef struct { + uint32_t drmFormat; + PixelFormat pixFormat; +} PixelFormatConvertTbl; + +typedef struct { + uint32_t value; + const char *str; +} ValueStrMap; + +static GrallocManager *GetGrallocManager() +{ + if (g_grallocManager == NULL) { + g_grallocManager = (GrallocManager *)malloc(sizeof(GrallocManager)); + errno_t eok = memset_s(g_grallocManager, sizeof(GrallocManager), 0, sizeof(GrallocManager)); + if (eok != EOK) { + DISPLAY_LOGE("memset_s failed"); + } + if (g_grallocManager == NULL) { + DISPLAY_LOGE("gralloc manager malloc failed"); + } + } + return g_grallocManager; +} + +const char *GetPixelFmtStr(PixelFormat format) +{ + static const ValueStrMap pixelStrMaps[] = { + {PIXEL_FMT_CLUT8, "PIXEL_FMT_CLUT8"}, {PIXEL_FMT_CLUT1, "PIXEL_FMT_CLUT1"}, + {PIXEL_FMT_CLUT4, "PIXEL_FMT_CLUT4"}, {PIXEL_FMT_RGB_565, "PIXEL_FMT_RGB_565"}, + {PIXEL_FMT_RGBA_5658, "IXEL_FMT_RGBA_5658"}, {PIXEL_FMT_RGBX_4444, "PIXEL_FMT_RGBX_4444"}, + {PIXEL_FMT_RGBA_4444, "PIXEL_FMT_RGBA_4444"}, {PIXEL_FMT_RGB_444, "PIXEL_FMT_RGB_444"}, + {PIXEL_FMT_RGBX_5551, "PIXEL_FMT_RGBX_5551"}, {PIXEL_FMT_RGBA_5551, "PIXEL_FMT_RGBA_5551"}, + {PIXEL_FMT_RGB_555, "PIXEL_FMT_RGB_555"}, {PIXEL_FMT_RGBX_8888, "PIXEL_FMT_RGBX_8888"}, + {PIXEL_FMT_RGBA_8888, "PIXEL_FMT_RGBA_8888"}, {PIXEL_FMT_RGB_888, "PIXEL_FMT_RGB_888"}, + {PIXEL_FMT_BGR_565, "PIXEL_FMT_BGR_565"}, {PIXEL_FMT_BGRX_4444, "PIXEL_FMT_BGRX_4444"}, + {PIXEL_FMT_BGRA_4444, "PIXEL_FMT_BGRA_4444"}, {PIXEL_FMT_BGRX_5551, "PIXEL_FMT_BGRX_5551"}, + {PIXEL_FMT_BGRA_5551, "PIXEL_FMT_BGRA_5551"}, {PIXEL_FMT_BGRX_8888, "PIXEL_FMT_BGRX_8888"}, + {PIXEL_FMT_BGRA_8888, "PIXEL_FMT_BGRA_8888"}, {PIXEL_FMT_YUV_422_I, "PIXEL_FMT_YUV_422_I"}, + {PIXEL_FMT_YUV_422_I, "PIXEL_FMT_YUV_422_I"}, {PIXEL_FMT_YCBCR_422_SP, "PIXEL_FMT_YCBCR_422_SP"}, + {PIXEL_FMT_YCRCB_422_SP, "PIXEL_FMT_YCRCB_422_SP"}, {PIXEL_FMT_YCBCR_420_SP, "PIXEL_FMT_YCBCR_420_SP"}, + {PIXEL_FMT_YCRCB_420_SP, "PIXEL_FMT_YCRCB_420_SP"}, {PIXEL_FMT_YCBCR_422_P, "PIXEL_FMT_YCBCR_422_P"}, + {PIXEL_FMT_YCRCB_422_P, "PIXEL_FMT_YCRCB_422_P"}, {PIXEL_FMT_YCBCR_420_P, "PIXEL_FMT_YCBCR_420_P"}, + {PIXEL_FMT_YCRCB_420_P, "PIXEL_FMT_YCRCB_420_P"}, {PIXEL_FMT_YUYV_422_PKG, "PIXEL_FMT_YUYV_422_PKG"}, + {PIXEL_FMT_UYVY_422_PKG, "PIXEL_FMT_UYVY_422_PKG"}, {PIXEL_FMT_YVYU_422_PKG, "PIXEL_FMT_YVYU_422_PKG"}, + {PIXEL_FMT_VYUY_422_PKG, "PIXEL_FMT_VYUY_422_PKG"}, {PIXEL_FMT_BUTT, "PIXEL_FMT_BUTT"}, + }; + static const char *unknown = "unknown format"; + for (uint32_t i = 0; i < sizeof(pixelStrMaps) / sizeof(pixelStrMaps[0]); i++) { + if (pixelStrMaps[i].value == format) { + return pixelStrMaps[i].str; + } + } + DISPLAY_LOGE("GetPixelFmtStr unknown format %{public}d", format); + return unknown; +} + +const char *GetDrmFmtStr(uint32_t format) +{ + static const ValueStrMap formatStrMaps[] = { + {DRM_FORMAT_C8, "DRM_FORMAT_C8" }, {DRM_FORMAT_R8, "DRM_FORMAT_R8" }, + {DRM_FORMAT_R16, "DRM_FORMAT_R16"}, {DRM_FORMAT_RG88, "DRM_FORMAT_RG88"}, + {DRM_FORMAT_GR88, "DRM_FORMAT_GR88"}, {DRM_FORMAT_RG1616, "DRM_FORMAT_RG1616"}, + {DRM_FORMAT_GR1616, "DRM_FORMAT_GR1616"}, {DRM_FORMAT_RGB332, "DRM_FORMAT_RGB332"}, + {DRM_FORMAT_BGR233, "DRM_FORMAT_BGR233"}, {DRM_FORMAT_XRGB4444, "DRM_FORMAT_XRGB4444"}, + {DRM_FORMAT_XBGR4444, "DRM_FORMAT_XBGR4444"}, {DRM_FORMAT_RGBX4444, "DRM_FORMAT_RGBX4444"}, + {DRM_FORMAT_BGRX4444, "DRM_FORMAT_BGRX4444"}, {DRM_FORMAT_ARGB4444, "DRM_FORMAT_ARGB4444"}, + {DRM_FORMAT_ABGR4444, "DRM_FORMAT_ABGR4444"}, {DRM_FORMAT_RGBA4444, "DRM_FORMAT_RGBA4444"}, + {DRM_FORMAT_BGRA4444, "DRM_FORMAT_BGRA4444"}, {DRM_FORMAT_XRGB1555, "DRM_FORMAT_XRGB1555"}, + {DRM_FORMAT_XBGR1555, "DRM_FORMAT_XBGR1555"}, {DRM_FORMAT_RGBX5551, "DRM_FORMAT_RGBX5551"}, + {DRM_FORMAT_BGRX5551, "DRM_FORMAT_BGRX5551"}, {DRM_FORMAT_ARGB1555, "DRM_FORMAT_ARGB1555"}, + {DRM_FORMAT_ABGR1555, "DRM_FORMAT_ABGR1555"}, {DRM_FORMAT_RGBA5551, "DRM_FORMAT_RGBA5551"}, + {DRM_FORMAT_BGRA5551, "DRM_FORMAT_BGRA5551"}, {DRM_FORMAT_RGB565, "DRM_FORMAT_RGB565"}, + {DRM_FORMAT_BGR565, "DRM_FORMAT_BGR565"}, {DRM_FORMAT_RGB888, "DRM_FORMAT_RGB888"}, + {DRM_FORMAT_BGR888, "DRM_FORMAT_BGR888"}, {DRM_FORMAT_XRGB8888, "DRM_FORMAT_XRGB8888"}, + {DRM_FORMAT_XBGR8888, "DRM_FORMAT_XBGR8888"}, {DRM_FORMAT_RGBX8888, "DRM_FORMAT_RGBX8888"}, + {DRM_FORMAT_BGRX8888, "DRM_FORMAT_BGRX8888"}, {DRM_FORMAT_ARGB8888, "DRM_FORMAT_ARGB8888"}, + {DRM_FORMAT_ABGR8888, "DRM_FORMAT_ABGR8888"}, {DRM_FORMAT_RGBA8888, "DRM_FORMAT_RGBA8888"}, + {DRM_FORMAT_BGRA8888, "DRM_FORMAT_BGRA8888"}, {DRM_FORMAT_XRGB2101010, "DRM_FORMAT_XRGB2101010"}, + {DRM_FORMAT_BGRX1010102, "DRM_FORMAT_BGRX1010102"}, {DRM_FORMAT_ARGB2101010, "DRM_FORMAT_ARGB2101010"}, + {DRM_FORMAT_ABGR2101010, "DRM_FORMAT_ABGR2101010"}, {DRM_FORMAT_RGBA1010102, "DRM_FORMAT_RGBA1010102"}, + {DRM_FORMAT_YVYU, "DRM_FORMAT_YVYU"}, {DRM_FORMAT_UYVY, "DRM_FORMAT_UYVY"}, + {DRM_FORMAT_VYUY, "DRM_FORMAT_VYUY"}, {DRM_FORMAT_AYUV, "DRM_FORMAT_AYUV"}, + {DRM_FORMAT_NV12, "DRM_FORMAT_NV12"}, {DRM_FORMAT_NV21, "DRM_FORMAT_NV21"}, + {DRM_FORMAT_NV16, "DRM_FORMAT_NV16"}, {DRM_FORMAT_NV61, "DRM_FORMAT_NV61"}, + {DRM_FORMAT_NV24, "DRM_FORMAT_NV24"}, {DRM_FORMAT_NV42, "DRM_FORMAT_NV42"}, + {DRM_FORMAT_YUV410, "DRM_FORMAT_YUV410"}, {DRM_FORMAT_YVU410, "DRM_FORMAT_YVU410"}, + {DRM_FORMAT_YUV411, "DRM_FORMAT_YUV411"}, {DRM_FORMAT_YVU411, "DRM_FORMAT_YVU411"}, + {DRM_FORMAT_YUV420, "DRM_FORMAT_YUV420"}, {DRM_FORMAT_YVU420, "DRM_FORMAT_YVU420"}, + {DRM_FORMAT_YUV422, "DRM_FORMAT_YUV422"}, {DRM_FORMAT_YVU422, "DRM_FORMAT_YVU422"}, + {DRM_FORMAT_YUV444, "DRM_FORMAT_YUV444"}, {DRM_FORMAT_YVU444, "DRM_FORMAT_YVU444"}, + }; + + static const char *unknown = "unknown drm format"; + for (uint32_t i = 0; i < sizeof(formatStrMaps) / sizeof(formatStrMaps[0]); i++) { + if (formatStrMaps[i].value == format) { + return formatStrMaps[i].str; + } + } + DISPLAY_LOGE("GetDrmFmtStr unknown format %{public}d", format); + return unknown; +} + +static uint32_t ConvertFormatToDrm(PixelFormat fmtIn) +{ + static const PixelFormatConvertTbl convertTable[] = { + {DRM_FORMAT_RGBX8888, PIXEL_FMT_RGBX_8888}, {DRM_FORMAT_RGBA8888, PIXEL_FMT_RGBA_8888}, + {DRM_FORMAT_RGB888, PIXEL_FMT_RGB_888}, {DRM_FORMAT_RGB565, PIXEL_FMT_BGR_565}, + {DRM_FORMAT_BGRX4444, PIXEL_FMT_BGRX_4444}, {DRM_FORMAT_BGRA4444, PIXEL_FMT_BGRA_4444}, + {DRM_FORMAT_RGBA4444, PIXEL_FMT_RGBA_4444}, {DRM_FORMAT_RGBX4444, PIXEL_FMT_RGBX_4444}, + {DRM_FORMAT_BGRX5551, PIXEL_FMT_BGRX_5551}, {DRM_FORMAT_BGRA5551, PIXEL_FMT_BGRA_5551}, + {DRM_FORMAT_BGRX8888, PIXEL_FMT_BGRX_8888}, {DRM_FORMAT_BGRA8888, PIXEL_FMT_BGRA_8888}, + {DRM_FORMAT_NV12, PIXEL_FMT_YCBCR_420_SP}, {DRM_FORMAT_NV21, PIXEL_FMT_YCRCB_420_SP}, + {DRM_FORMAT_YUV420, PIXEL_FMT_YCBCR_420_P}, {DRM_FORMAT_YVU420, PIXEL_FMT_YCRCB_420_P}, + {DRM_FORMAT_NV16, PIXEL_FMT_YCBCR_422_SP}, {DRM_FORMAT_NV61, PIXEL_FMT_YCRCB_422_SP}, + {DRM_FORMAT_YUV422, PIXEL_FMT_YCBCR_422_P}, {DRM_FORMAT_YVU422, PIXEL_FMT_YCRCB_422_P}, + }; + uint32_t fmtOut = 0; + for (uint32_t i = 0; i < sizeof(convertTable) / sizeof(convertTable[0]); i++) { + if (convertTable[i].pixFormat == fmtIn) { + fmtOut = convertTable[i].drmFormat; + } + } + DISPLAY_LOGD("fmtIn %{public}d : %{public}s, outFmt %{public}d : %{public}s", fmtIn, GetPixelFmtStr(fmtIn), fmtOut, + GetDrmFmtStr(fmtOut)); + return fmtOut; +} + +static uint64_t ConvertUsageToGbm(uint64_t inUsage) +{ + uint64_t outUsage = GBM_BO_USE_TEXTURING; + if (inUsage & HBM_USE_CPU_READ) { + outUsage |= GBM_BO_USE_SW_READ_OFTEN; + } + if (inUsage & HBM_USE_CPU_WRITE) { + outUsage |= GBM_BO_USE_SW_WRITE_OFTEN; + } + DISPLAY_LOGD("outUsage 0x%{public}" PRIx64 "", outUsage); + return outUsage; +} + +static int32_t InitGbmDevice(const char *drmFile, GrallocManager *grallocManager) +{ + DISPLAY_LOGD(); + if (grallocManager->gbmDevice == NULL) { + char path[PATH_MAX] = {0}; + if (realpath(drmFile, path) == NULL) { + DISPLAY_LOGE(" drm File : %{public}s is not a realpath, errno: %{public}s", drmFile, strerror(errno)); + return DISPLAY_PARAM_ERR; + } + int drmFd = open(path, O_RDWR); + if (drmFd < 0) { + DISPLAY_LOGE("drm file:%{public}s open failed %{public}s", drmFile, strerror(errno)); + return DISPLAY_FD_ERR; + } + /* + if (WaylandDrmAuth(drmFd) != AUTH_SCUCCESS) { + DISPLAY_LOGE("drm authentication failed, may have no permission to allocate memory"); + } + */ + struct gbm_device *gbmDevice = hdi_gbm_create_device(drmFd); + grallocManager->drmFd = drmFd; + if (gbmDevice == NULL) { + close(drmFd); + grallocManager->drmFd = -1; + DISPLAY_LOGE("gbm device create failed"); + return DISPLAY_FAILURE; + } + grallocManager->gbmDevice = gbmDevice; + grallocManager->drmFd = drmFd; + DListHeadInit(&grallocManager->gbmBoHead); + } + return DISPLAY_SUCCESS; +} + +static void DeInitGbmDevice(GrallocManager *grallocManager) +{ + DISPLAY_LOGD(); + hdi_gbm_device_destroy(grallocManager->gbmDevice); + if (grallocManager->drmFd > 0) { + close(grallocManager->drmFd); + grallocManager->drmFd = -1; + } + grallocManager->gbmDevice = NULL; +} + +static int32_t DmaBufferSync(const BufferHandle *handle, bool start) +{ + DISPLAY_LOGD(); + struct dma_buf_sync syncPrm; + errno_t eok = memset_s(&syncPrm, sizeof(syncPrm), 0, sizeof(syncPrm)); + DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_PARAM_ERR, DISPLAY_LOGE("dma buffer sync memset_s failed")); + + if (handle->usage & HBM_USE_CPU_WRITE) { + syncPrm.flags |= DMA_BUF_SYNC_WRITE; + } + + if (handle->usage & HBM_USE_CPU_READ) { + syncPrm.flags |= DMA_BUF_SYNC_READ; + } + + if (start) { + syncPrm.flags |= DMA_BUF_SYNC_START; + } else { + syncPrm.flags |= DMA_BUF_SYNC_END; + } + int retry = 6; + int ret; + do { + ret = ioctl(handle->fd, DMA_BUF_IOCTL_SYNC, &syncPrm); + } while ((retry--) && (ret != -EAGAIN) && (ret != -EINTR)); + + if (ret < 0) { + DISPLAY_LOGE("sync failed"); + return DISPLAY_SYS_BUSY; + } + return DISPLAY_SUCCESS; +} + +static void InitBufferHandle(struct gbm_bo *bo, int fd, const AllocInfo *info, PriBufferHandle *buffer) +{ + BufferHandle *bufferHandle = &(buffer->hdl); + bufferHandle->fd = fd; + bufferHandle->reserveFds = 0; + bufferHandle->reserveInts = 0; + bufferHandle->stride = hdi_gbm_bo_get_stride(bo); + bufferHandle->width = hdi_gbm_bo_get_width(bo); + bufferHandle->height = hdi_gbm_bo_get_height(bo); + bufferHandle->usage = info->usage; + bufferHandle->format = info->format; + bufferHandle->virAddr = NULL; + bufferHandle->size = hdi_gbm_bo_get_stride(bo) * hdi_gbm_bo_get_height(bo); +} + +//static uint64_t GetPhysicalAddr(int fd, int primeFd) +//{ +// struct DrmHisiliconPhyaddr args; +// int ret; +// DISPLAY_LOGD(); +// errno_t eok = memset_s(&args, sizeof(args), 0, sizeof(args)); +// DISPLAY_CHK_RETURN((eok != EOK), 0, DISPLAY_LOGE("memset_s failed")); +// args.fd = primeFd; +// ret = ioctl(fd, DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR, &args); +// if (ret) { +// DISPLAY_LOGE("DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR return failed"); +// } +// DISPLAY_LOGD("DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR return %{public}d args.phyaddr %{public}llx", ret, +// args.phyaddr); +// return args.phyaddr; +//} + +int32_t GbmAllocMem(const AllocInfo *info, BufferHandle **buffer) +{ + DISPLAY_CHK_RETURN((info == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("info is null")); + DISPLAY_CHK_RETURN((buffer == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is null")); + PriBufferHandle *priBuffer = NULL; + uint32_t drmFmt = ConvertFormatToDrm(info->format); + DISPLAY_CHK_RETURN((drmFmt == INVALID_PIXEL_FMT), DISPLAY_NOT_SUPPORT, + DISPLAY_LOGE("format %{public}d can not support", info->format)); + DISPLAY_LOGD("requeset width %{public}d, heigt %{public}d, format %{public}d", info->width, info->height, drmFmt); + + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("gralloc manager failed"); + GRALLOC_UNLOCK()); + struct gbm_bo *bo = + hdi_gbm_bo_create(grallocManager->gbmDevice, info->width, info->height, drmFmt, ConvertUsageToGbm(info->usage)); + DISPLAY_CHK_RETURN((bo == NULL), DISPLAY_NOMEM, DISPLAY_LOGE("gbm create bo failed"); GRALLOC_UNLOCK()); + + int fd = hdi_gbm_bo_get_fd(bo); + DISPLAY_CHK_RETURN((fd < 0), DISPLAY_FD_ERR, DISPLAY_LOGE("gbm can not get fd"); hdi_gbm_bo_destroy(bo); + GRALLOC_UNLOCK()); + + priBuffer = (PriBufferHandle *)malloc(sizeof(PriBufferHandle)); + DISPLAY_CHK_RETURN((priBuffer == NULL), DISPLAY_NULL_PTR, DISPLAY_LOGE("bufferhandle malloc failed"); goto error); + errno_t eok = memset_s(priBuffer, sizeof(PriBufferHandle), 0, sizeof(PriBufferHandle)); + DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_PARAM_ERR, DISPLAY_LOGE("memset_s failed"); goto error); + + InitBufferHandle(bo, fd, info, priBuffer); +// priBuffer->hdl.phyAddr = GetPhysicalAddr(grallocManager->drmFd, fd); + *buffer = &priBuffer->hdl; + hdi_gbm_bo_destroy(bo); + GRALLOC_UNLOCK(); + return DISPLAY_SUCCESS; +error: + close(fd); + hdi_gbm_bo_destroy(bo); + if (priBuffer != NULL) { + free(priBuffer); + } + GRALLOC_UNLOCK(); + return DISPLAY_FAILURE; +} + +static void CloseBufferHandle(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((handle == NULL), DISPLAY_LOGE("buffer is null")); + if (handle->fd >= 0) { + close(handle->fd); + handle->fd = -1; + } + const uint32_t reserveFds = handle->reserveFds; + for (uint32_t i = 0; i < reserveFds; i++) { + if (handle->reserve[i] >= 0) { + close(handle->reserve[i]); + handle->reserve[i] = -1; + } + } +} + +void GbmFreeMem(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN_NOT_VALUE((buffer == NULL), DISPLAY_LOGE("buffer is null")); + if ((buffer->virAddr != NULL) && (GbmUnmap(buffer) != DISPLAY_SUCCESS)) { + DISPLAY_LOGE("freeMem unmap buffer failed"); + } + CloseBufferHandle(buffer); + free(buffer); +} + +void *GbmMmap(BufferHandle *buffer) +{ + void *virAddr = NULL; + DISPLAY_LOGD(); + if (buffer == NULL) { + DISPLAY_LOGE("gbmmap the buffer handle is NULL"); + return NULL; + } + if (buffer->virAddr != NULL) { + DISPLAY_LOGD("the buffer has virtual addr"); + return buffer->virAddr; + } + virAddr = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, buffer->fd, 0); + if (virAddr == MAP_FAILED) { + DISPLAY_LOGE("mmap failed errno %{public}s, fd : %{public}d", strerror(errno), buffer->fd); + } + buffer->virAddr = virAddr; + return virAddr; +} + +int32_t GbmUnmap(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + if (buffer == NULL) { + DISPLAY_LOGE("gbmumap the buffer handle is null"); + return DISPLAY_NULL_PTR; + } + + if (buffer->virAddr == NULL) { + DISPLAY_LOGE("virAddr is NULL , has not map the buffer"); + return DISPLAY_PARAM_ERR; + } + int ret = munmap(buffer->virAddr, buffer->size); + if (ret != 0) { + DISPLAY_LOGE("munmap failed err: %{public}s", strerror(errno)); + return DISPLAY_FAILURE; + } + buffer->virAddr = NULL; + return DISPLAY_SUCCESS; +} + +int32_t GbmInvalidateCache(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + return DmaBufferSync(buffer, true); +} + +int32_t GbmFlushCache(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + return DmaBufferSync(buffer, false); +} + +int32_t GbmGrallocUninitialize(void) +{ + DISPLAY_LOGD(); + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("gralloc manager failed"); + GRALLOC_UNLOCK()); + grallocManager->referCount--; + if (grallocManager->referCount < 0) { + DeInitGbmDevice(grallocManager); + free(g_grallocManager); + g_grallocManager = NULL; + } + GRALLOC_UNLOCK(); + return DISPLAY_SUCCESS; +} + +int32_t GbmGrallocInitialize(void) +{ + DISPLAY_LOGD(); + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("gralloc manager failed"); + GRALLOC_UNLOCK()); + int ret = InitGbmDevice(g_drmFileNode, grallocManager); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_LOGE("gralloc manager failed"); GRALLOC_UNLOCK()); + grallocManager->referCount++; + GRALLOC_UNLOCK(); + return DISPLAY_SUCCESS; +} diff --git a/hardware/display/src/display_gralloc/display_gralloc_gbm.h b/hardware/display/src/display_gralloc/display_gralloc_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..932056534b69b5718382bc48f791b21c821545f3 --- /dev/null +++ b/hardware/display/src/display_gralloc/display_gralloc_gbm.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISPLAY_GRALLOC_GBM_H +#define DISPLAY_GRALLOC_GBM_H +#include "display_type.h" +#include "hdf_dlist.h" +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + struct gbm_device *gbmDevice; + int drmFd; + struct DListHead gbmBoHead; + int32_t referCount; +} GrallocManager; + +typedef struct { + struct DListHead entry; + struct gbm_bo *bo; + int fd; +} GbmBoList; + +int32_t GbmAllocMem(const AllocInfo *info, BufferHandle **buffer); +void GbmFreeMem(BufferHandle *buffer); +void *GbmMmap(BufferHandle *buffer); +int32_t GbmUnmap(BufferHandle *buffer); +int32_t GbmInvalidateCache(BufferHandle *buffer); +int32_t GbmFlushCache(BufferHandle *buffer); +int32_t GbmGrallocUninitialize(); +int32_t GbmGrallocInitialize(); + +#ifdef GRALLOC_LOCK_DEBUG +#define GRALLOC_LOCK(format, ...) \ + do { \ + HDF_LOGD("[%{public}s@%{public}s:%{public}d]" format "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ + pthread_mutex_lock(&g_lock); \ + } while (0) + +#define GRALLOC_UNLOCK(format, ...) \ + do { \ + HDF_LOGD("[%{public}s@%{public}s:%{public}d]" format "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ + pthread_mutex_unlock(&g_lock); \ + } while (0) +#else +#define GRALLOC_LOCK(format, ...) \ + do { \ + pthread_mutex_lock(&g_lock); \ + } while (0) + +#define GRALLOC_UNLOCK(format, ...) \ + do { \ + pthread_mutex_unlock(&g_lock); \ + } while (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif // DISPLAY_GRALLOC_GBM_H \ No newline at end of file diff --git a/hardware/display/src/display_gralloc/hi_gbm.c b/hardware/display/src/display_gralloc/hi_gbm.c new file mode 100644 index 0000000000000000000000000000000000000000..8e698a414f32510cf80d0380739b116b385ade97 --- /dev/null +++ b/hardware/display/src/display_gralloc/hi_gbm.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hi_gbm.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "display_common.h" +#include "hi_gbm_internal.h" +#ifdef ROCKCHIP_CMA +#define ROCKCHIP_BO_CONTIG (1 << 0) +#endif + +typedef struct { + uint32_t numPlanes; + uint32_t radio[MAX_PLANES]; +} PlaneLayoutInfo; + +typedef struct { + uint32_t format; + uint32_t bitsPerPixel; // bits per pixel for first plane + const PlaneLayoutInfo *planes; +} FormatInfo; + +static const PlaneLayoutInfo g_yuv420SPLayout = { + .numPlanes = 2, + .radio = { 4, 2 }, +}; + +static const PlaneLayoutInfo g_yuv420PLayout = { + .numPlanes = 3, + .radio = { 4, 1, 1 }, +}; + +static const PlaneLayoutInfo g_yuv422SPLayout = { + .numPlanes = 2, + .radio = { 4, 4 }, +}; + +static const PlaneLayoutInfo g_yuv422PLayout = { + .numPlanes = 3, + .radio = { 4, 2, 2 }, +}; + +static const FormatInfo *GetFormatInfo(uint32_t format) +{ + static const FormatInfo fmtInfos[] = { + {DRM_FORMAT_RGBX8888, 32, NULL}, {DRM_FORMAT_RGBA8888, 32, NULL}, + {DRM_FORMAT_BGRX8888, 32, NULL}, {DRM_FORMAT_BGRA8888, 32, NULL}, + {DRM_FORMAT_RGB888, 24, NULL}, {DRM_FORMAT_RGB565, 16, NULL}, + {DRM_FORMAT_BGRX4444, 16, NULL}, {DRM_FORMAT_BGRA4444, 16, NULL}, + {DRM_FORMAT_RGBA4444, 16, NULL}, {DRM_FORMAT_RGBX4444, 16, NULL}, + {DRM_FORMAT_BGRX5551, 16, NULL}, {DRM_FORMAT_BGRA5551, 16, NULL}, + {DRM_FORMAT_NV12, 8, &g_yuv420SPLayout}, {DRM_FORMAT_NV21, 8, &g_yuv420SPLayout}, + {DRM_FORMAT_NV16, 8, &g_yuv422SPLayout}, {DRM_FORMAT_NV61, 8, &g_yuv422SPLayout}, + {DRM_FORMAT_YUV420, 8, &g_yuv420PLayout}, {DRM_FORMAT_YVU420, 8, &g_yuv420PLayout}, + {DRM_FORMAT_YUV422, 8, &g_yuv422PLayout}, {DRM_FORMAT_YVU422, 8, &g_yuv422PLayout}, + }; + + for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) { + if (fmtInfos[i].format == format) { + return &fmtInfos[i]; + } + } + DISPLAY_LOGE("the format can not support"); + return NULL; +} + +void InitGbmBo(struct gbm_bo *bo, const struct drm_mode_create_dumb *dumb) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((dumb == NULL), DISPLAY_LOGE("dumb is null")); + DISPLAY_CHK_RETURN_NOT_VALUE((bo == NULL), DISPLAY_LOGE("bo is null")); + bo->stride = dumb->pitch; + bo->size = dumb->size; + bo->handle = dumb->handle; +} + +static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t height) +{ + const FormatInfo *fmtInfo = GetFormatInfo(format); + if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) { + uint32_t sum = fmtInfo->planes->radio[0]; + for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) { + sum += fmtInfo->planes->radio[i]; + } + if (sum > 0) { + height = DIV_ROUND_UP((height * sum), fmtInfo->planes->radio[0]); + } + DISPLAY_LOGD("height adjust to : %{public}d", height); + } + return height; +} + +struct gbm_bo *hdi_gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, + uint32_t usage) +{ + DISPLAY_UNUSED(usage); + int ret; + struct gbm_bo *bo; + struct drm_mode_create_dumb dumb = { 0 }; + const FormatInfo *fmtInfo = GetFormatInfo(format); + DISPLAY_CHK_RETURN((fmtInfo == NULL), NULL, DISPLAY_LOGE("formt: 0x%{public}x can not get layout info", format)); + bo = (struct gbm_bo *)calloc(1, sizeof(struct gbm_bo)); + DISPLAY_CHK_RETURN((bo == NULL), NULL, DISPLAY_LOGE("gbm bo create fialed no memery")); + (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo)); + bo->width = width; + bo->height = height; + bo->gbm = gbm; + bo->format = format; + // init create_dumb + dumb.height = ALIGN_UP(height, HEIGHT_ALIGN); + dumb.width = ALIGN_UP(AdjustStrideFromFormat(format, width), WIDTH_ALIGN); + dumb.flags = 0; + dumb.bpp = fmtInfo->bitsPerPixel; + ret = drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb); + DISPLAY_LOGI("fmt 0x%{public}x create dumb width: %{public}d height: %{public}d bpp: %{public}u pitch %{public}d " + "size %{public}llu", + format, dumb.width, dumb.height, dumb.bpp, dumb.pitch, dumb.size); + DISPLAY_CHK_RETURN((ret != 0), NULL, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno)); + InitGbmBo(bo, &dumb); + DISPLAY_LOGI( + "fmt 0x%{public}x create dumb width: %{public}d height: %{public}d stride %{public}d size %{public}u", format, + bo->width, bo->height, bo->stride, bo->size); + return bo; +} + +struct gbm_device *hdi_gbm_create_device(int fd) +{ + struct gbm_device *gbm; + gbm = (struct gbm_device *)calloc(1, sizeof(struct gbm_device)); + DISPLAY_CHK_RETURN((gbm == NULL), NULL, DISPLAY_LOGE("memory calloc failed")); + gbm->fd = fd; + return gbm; +} + +void hdi_gbm_device_destroy(struct gbm_device *gbm) +{ + free(gbm); +} + +uint32_t hdi_gbm_bo_get_stride(struct gbm_bo *bo) +{ + DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null")); + return bo->stride; +} + +uint32_t hdi_gbm_bo_get_width(struct gbm_bo *bo) +{ + DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null")); + return bo->width; +} + +uint32_t hdi_gbm_bo_get_height(struct gbm_bo *bo) +{ + DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null")); + return bo->height; +} + +void hdi_gbm_bo_destroy(struct gbm_bo *bo) +{ + int ret; + DISPLAY_CHK_RETURN_NOT_VALUE((bo == NULL), DISPLAY_LOGE("the bo is null")); + struct drm_mode_destroy_dumb dumb = { 0 }; + dumb.handle = bo->handle; + ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dumb); + DISPLAY_CHK_RETURN_NOT_VALUE((ret), DISPLAY_LOGE("dumb buffer destroy failed errno %{public}d", errno)); + free(bo); +} + +int hdi_gbm_bo_get_fd(struct gbm_bo *bo) +{ + int fd, ret; + ret = drmPrimeHandleToFD(bo->gbm->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd); + DISPLAY_CHK_RETURN((ret), -1, + DISPLAY_LOGE("drmPrimeHandleToFD failed ret: %{public}d errno: %{public}d", ret, errno)); + return fd; +} \ No newline at end of file diff --git a/hardware/display/src/display_gralloc/hi_gbm.h b/hardware/display/src/display_gralloc/hi_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..259aa37e406181ab7d45e372a795e0c6599af16e --- /dev/null +++ b/hardware/display/src/display_gralloc/hi_gbm.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HI_GBM_H +#define HI_GBM_H +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +struct gbm_device; +struct gbm_bo; + +enum gbm_bo_flags { + /* * + * Buffer is going to be presented to the screen using an API such as KMS + */ + GBM_BO_USE_SCANOUT = (1 << 0), + /* * + * Buffer is going to be used as cursor + */ + GBM_BO_USE_CURSOR = (1 << 1), + /* * + * Deprecated + */ + GBM_BO_USE_CURSOR_64X64 = GBM_BO_USE_CURSOR, + /* * + * Buffer is to be used for rendering - for example it is going to be used + * as the storage for a color buffer + */ + GBM_BO_USE_RENDERING = (1 << 2), + /* * + * Deprecated + */ + GBM_BO_USE_WRITE = (1 << 3), + /* * + * Buffer is guaranteed to be laid out linearly in memory. That is, the + * buffer is laid out as an array with 'height' blocks, each block with + * length 'stride'. Each stride is in the same order as the rows of the + * buffer. This is intended to be used with buffers that will be accessed + * via dma-buf mmap(). + */ + GBM_BO_USE_LINEAR = (1 << 4), + /* * + * The buffer will be used as a texture that will be sampled from. + */ + GBM_BO_USE_TEXTURING = (1 << 5), + /* * + * The buffer will be written to by a camera subsystem. + */ + GBM_BO_USE_CAMERA_WRITE = (1 << 6), + /* * + * The buffer will be read from by a camera subsystem. + */ + GBM_BO_USE_CAMERA_READ = (1 << 7), + /* * + * Buffer inaccessible to unprivileged users. + */ + GBM_BO_USE_PROTECTED = (1 << 8), + /* * + * These flags specify the frequency of software access. These flags do not + * guarantee the buffer is linear, but do guarantee gbm_bo_map(..) will + * present a linear view. + */ + GBM_BO_USE_SW_READ_OFTEN = (1 << 9), + GBM_BO_USE_SW_READ_RARELY = (1 << 10), + GBM_BO_USE_SW_WRITE_OFTEN = (1 << 11), + GBM_BO_USE_SW_WRITE_RARELY = (1 << 12), + /* * + * The buffer will be written by a video decode accelerator. + */ + GBM_BO_USE_HW_VIDEO_DECODER = (1 << 13), +}; + +struct gbm_device *hdi_gbm_create_device(int fd); +void hdi_gbm_device_destroy(struct gbm_device *gbm); +struct gbm_bo *hdi_gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, uint32_t usage); +uint32_t hdi_gbm_bo_get_stride(struct gbm_bo *bo); +uint32_t hdi_gbm_bo_get_width(struct gbm_bo *bo); +uint32_t hdi_gbm_bo_get_height(struct gbm_bo *bo); +void hdi_gbm_bo_destroy(struct gbm_bo *bo); +int hdi_gbm_bo_get_fd(struct gbm_bo *bo); + +#if defined(__cplusplus) +} +#endif +#endif // HI_GBM_H \ No newline at end of file diff --git a/hardware/display/src/display_gralloc/hi_gbm_internal.h b/hardware/display/src/display_gralloc/hi_gbm_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..3155bb669334833f45da03be5db37f6b47d59653 --- /dev/null +++ b/hardware/display/src/display_gralloc/hi_gbm_internal.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HI_GBM_INTERNEL_H +#define HI_GBM_INTERNEL_H + +#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) +#define ALIGN_UP(x, a) ((((x) + ((a)-1)) / (a)) * (a)) +#define HEIGHT_ALIGN 2U +#define WIDTH_ALIGN 8U + +#define MAX_PLANES 3 + +struct gbm_device { + int fd; +}; + +struct gbm_bo { + struct gbm_device *gbm; + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t handle; + uint32_t stride; + uint32_t size; +}; + +#endif // HI_GBM_INTERNEL_H \ No newline at end of file diff --git a/hardware/display/src/display_gralloc/hisilicon_drm.h b/hardware/display/src/display_gralloc/hisilicon_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..eed389e88acc3154ba29a3d0010f3a463b18f7b1 --- /dev/null +++ b/hardware/display/src/display_gralloc/hisilicon_drm.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HISILICON_DRM_H +#define HISILICON_DRM_H + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif +#define DRM_HISILICON_GEM_FD_TO_PHYADDR 0x1 + +struct DrmHisiliconPhyaddr { + /* * return the physical address */ + __u64 phyaddr; + /* * dmabuf file descriptor */ + __s32 fd; +}; + +#define DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_HISILICON_GEM_FD_TO_PHYADDR, struct DrmHisiliconPhyaddr) + +#if defined(__cplusplus) +} +#endif + +#endif // HISILICON_DRM_H diff --git a/hardware/display/src/display_gralloc/wayland_drm_auth_client.c b/hardware/display/src/display_gralloc/wayland_drm_auth_client.c new file mode 100644 index 0000000000000000000000000000000000000000..4f30624511140b28e690ef79d25da98f697f5ecd --- /dev/null +++ b/hardware/display/src/display_gralloc/wayland_drm_auth_client.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wayland_drm_auth_client.h" +#include +#include +#include "xf86drm.h" +#include "wayland-client.h" +#include "drm-auth-client-protocol.h" +#include "display_common.h" + +typedef struct { + struct wl_display *display; + struct wl_registry *registry; + struct wl_drm_auth *drmAuth; + enum wl_drm_auth_status authStatus; +} WaylandDisplay; + +const char *AUTH_INTERFACE_NAME = "wl_drm_auth"; + +static void AuthenticationStatus(void *data, struct wl_drm_auth *wlDrmAuth, uint32_t status) +{ + (void)wlDrmAuth; + DISPLAY_LOGD("AuthenticationStatus the status %{public}d", status); + WaylandDisplay *display = data; + display->authStatus = status; +} + +static const struct wl_drm_auth_listener g_drmAuthListener = { AuthenticationStatus }; + +static void RegistryHandleGlobal(void *data, struct wl_registry *registry, uint32_t id, const char *interface, + uint32_t version) +{ + WaylandDisplay *display = data; + DISPLAY_LOGD("interface global : %{public}s", interface); + if (strcmp(interface, wl_drm_auth_interface.name) == 0) { + display->drmAuth = wl_registry_bind(registry, id, &wl_drm_auth_interface, 1); + wl_drm_auth_add_listener(display->drmAuth, &g_drmAuthListener, display); + } +} + +static void RegistryHandleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name) +{ + DISPLAY_LOGD("RegistryHandleGlobalRemove %{publuc}d name ", name); +} + +static const struct wl_registry_listener g_registrListener = { RegistryHandleGlobal, RegistryHandleGlobalRemove }; + +void DeInitWaylandClient(WaylandDisplay *display) +{ + DISPLAY_LOGD("DeInitWaylandClient"); + DISPLAY_CHK_RETURN_NOT_VALUE((display == NULL), DISPLAY_LOGD("display is NULL")); + if (display->registry != NULL) { + wl_registry_destroy(display->registry); + } + + if (display->display != NULL) { + wl_display_flush(display->display); + wl_display_disconnect(display->display); + } + free(display); +} + +WaylandDisplay *InitWaylandClient() +{ + WaylandDisplay *dsp; + int ret; + dsp = calloc(1, sizeof(WaylandDisplay)); + DISPLAY_CHK_RETURN((dsp == NULL), NULL, DISPLAY_LOGE("can not alloc memory errno : %{public}d", errno)); + dsp->display = wl_display_connect(NULL); + DISPLAY_CHK_RETURN((dsp->display == NULL), NULL, DISPLAY_LOGE("display connect failed, errno: %{public}d", errno); + DeInitWaylandClient(dsp)); + dsp->registry = wl_display_get_registry(dsp->display); + DISPLAY_CHK_RETURN((dsp->registry == NULL), NULL, DISPLAY_LOGE("can not get registry"); DeInitWaylandClient(dsp)); + ret = wl_registry_add_listener(dsp->registry, &g_registrListener, dsp); + DISPLAY_CHK_RETURN((ret < 0), NULL, DISPLAY_LOGE("add listener failed")); + wl_display_roundtrip(dsp->display); // for get registry + wl_display_roundtrip(dsp->display); // for the listener will bind the service + return dsp; +} + +int32_t WaylandDrmAuth(int drmFd) +{ + WaylandDisplay *dsp; + drm_magic_t magic; + int ret; + dsp = InitWaylandClient(); + DISPLAY_CHK_RETURN((dsp == NULL), AUTH_FAILED, DISPLAY_LOGE("init wayland client failed")); + ret = drmGetMagic(drmFd, &magic); + DISPLAY_CHK_RETURN((ret != 0), AUTH_FAILED, DISPLAY_LOGE("can not get magic")); + DISPLAY_CHK_RETURN((dsp->drmAuth == NULL), AUTH_FAILED, DISPLAY_LOGE("drm auth service no find")); + wl_drm_auth_authenticate(dsp->drmAuth, magic); + wl_display_roundtrip(dsp->display); // wait for authenticate status return + DISPLAY_LOGD("the status of authenticate is %{public}d", dsp->authStatus); + if (dsp->authStatus == WL_DRM_AUTH_STATUS_SUCCESS) { + ret = AUTH_SCUCCESS; + } + DeInitWaylandClient(dsp); + return ret; +} diff --git a/hardware/display/src/display_gralloc/wayland_drm_auth_client.h b/hardware/display/src/display_gralloc/wayland_drm_auth_client.h new file mode 100644 index 0000000000000000000000000000000000000000..69be0fa04193612989e7fb62f207faf385455bf6 --- /dev/null +++ b/hardware/display/src/display_gralloc/wayland_drm_auth_client.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WAYLAND_DRM_AUTH_CLIENT_H +#define WAYLAND_DRM_AUTH_CLIENT_H +#include + +typedef enum { + AUTH_SCUCCESS = 0, /* * authenticate sucess */ + AUTH_FAILED = 1 /* * authenticate failed */ +} AuthStatus; + +/* * + * @brief authenticate the drm fd + * + * it will connect to the wayland server, and will block to authenticate the drm fd, then disconnect the wayland + * + * @param display Indicates the pointer of wayland display + * + * @param drmFd Indicates the file descriptor of drm device + * + * @return Returns AUTH_SCUCCESS if the operation is successful else returns AUTH_FAILED + * otherwise. + * @since 1.0 + * @version 1.0 + */ +int32_t WaylandDrmAuth(int drmFd); + +#endif // WAYLAND_DRM_AUTH_CLIENT_H diff --git a/rk3568/build/rootfs/BUILD.gn b/rk3568/build/rootfs/BUILD.gn index 319a9301e39f78975a928f7a3553858c7e0fe02a..73ecdf579cfde964ac5230191a1cab87433a22be 100755 --- a/rk3568/build/rootfs/BUILD.gn +++ b/rk3568/build/rootfs/BUILD.gn @@ -20,6 +20,14 @@ ohos_prebuilt_etc("init.rk3568.cfg") { install_enable = true } +ohos_prebuilt_executable("weston.cfg") { + install_enable = true + source = "weston.cfg" + module_install_dir = "etc/init" + install_images = [ "system" ] + part_name = "rockchip_products" +} + ohos_prebuilt_etc("init.rk3568.usb.cfg") { source = "init.rk3568.usb.cfg" install_images = [ "system" ] @@ -51,6 +59,7 @@ ohos_prebuilt_executable("display-hotplug.sh") { group("init_configs") { deps = [ ":display-hotplug.sh", + ":weston.cfg", ":init.rk3568.cfg", ":init.rk3568.usb.cfg", ":init.cfg", diff --git a/rk3568/build/rootfs/weston.cfg b/rk3568/build/rootfs/weston.cfg new file mode 100755 index 0000000000000000000000000000000000000000..f01a769aec1f82548160162c67a0c617deb03e17 --- /dev/null +++ b/rk3568/build/rootfs/weston.cfg @@ -0,0 +1,42 @@ +{ + "jobs" : [{ + "name" : "post-fs", + "cmds" : [ + "start udevd_service", + "sleep 1", + "start mmi_uinput_service", + "sleep 2", + "export XDG_RUNTIME_DIR /data/weston", + "export XKB_CONFIG_ROOT /etc/xkb", + "export XKB_CONFIG_EXTRA_PATH /etc/xkb", + "mkdir /data/weston", + "chmod 777 /data/weston", + "start weston", + "trigger weston_start", + "sleep 2", + "exec /system/bin/udevadm trigger", + "exec /system/bin/udevadm settle --timeout=30" + ] + } + ], + "services" : [{ + "name" : "weston", + "path" : ["/system/bin/weston", "-c", "/system/etc/weston.ini", "-B", "drm-backend.so", "--tty=1"], + "disabled" : 1 + }, { + "name" : "hdi_weston", + "path" : ["/system/bin/weston", "-c", "/system/etc/weston.ini", "-B", "hdi-backend.so"], + "disabled" : 1 + }, { + "name" : "mmi_uinput_service", + "path" : ["/system/bin/uinput_inject"], + "uid" : "root", + "gid" : ["system", "shell", "uhid"] + }, { + "name" : "udevd_service", + "path" : ["/system/bin/udevd"], + "uid" : "root", + "gid" : ["system"] + } + ] +} diff --git a/rk3568/camera/BUILD.gn b/rk3568/camera/BUILD.gn index 50850a9f0bc1cc991be5cd9e69447cdefafae790..ce080cd2f6d83f0b92790f1ef831954fff841a86 100755 --- a/rk3568/camera/BUILD.gn +++ b/rk3568/camera/BUILD.gn @@ -13,17 +13,11 @@ import("//build/ohos.gni") import("//drivers/adapter/uhdf2/uhdf.gni") import("//drivers/peripheral/camera/hal/camera.gni") +import("$hdf_framework_path/tools/hc-gen/hc_gen.gni") -action("build_camera_host_config") { - script = "$hdf_framework_path/tools/hc-gen/build_hcs.py" +hc_gen("build_camera_host_config") { sources = [ rebase_path( "$camera_product_name_path/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs") ] - outputs = [ "$target_gen_dir/config/hdi_impl/camera_host_config.hcb" ] - args = [ - "-o", - rebase_path(outputs[0]), - sources[0], - ] } ohos_prebuilt_etc("camera_host_config.hcb") { @@ -35,48 +29,55 @@ ohos_prebuilt_etc("camera_host_config.hcb") { part_name = "hdf" } +hc_gen_c("generate_source") { + sources = [ + "$camera_product_name_path/hdf_config/uhdf/camera/pipeline_core/config.hcs", + "$camera_product_name_path/hdf_config/uhdf/camera/pipeline_core/params.hcs", + ] +} + +action("copy_source") { + script = "/usr/bin/env" + outputs = [ "$target_out_dir/tmp.c" ] # no use, just for gn complains + args = [ + "cp", + "-f", + ] + args += rebase_path(get_target_outputs(":generate_source")) + args += [ rebase_path( + "$camera_path/pipeline_core/pipeline_impl/src/strategy/config/") ] + deps = [ ":generate_source" ] +} + ohos_prebuilt_etc("config.c") { + deps = [ ":copy_source" ] source = "$camera_path/pipeline_core/pipeline_impl/src/strategy/config/config.c" exec_script( - "//drivers/framework/tools/hc-gen/build_hcs.py", + "/usr/bin/env", [ - "-o", + "touch", rebase_path( "$camera_path/pipeline_core/pipeline_impl/src/strategy/config/config.c"), - "-t", - rebase_path( - "$camera_product_name_path/hdf_config/uhdf/camera/pipeline_core/config.hcs"), - ], - "") + ]) } ohos_prebuilt_etc("params.c") { + deps = [ ":copy_source" ] source = "$camera_path/pipeline_core/pipeline_impl/src/strategy/config/params.c" exec_script( - "//drivers/framework/tools/hc-gen/build_hcs.py", + "/usr/bin/env", [ - "-o", + "touch", rebase_path( "$camera_path/pipeline_core/pipeline_impl/src/strategy/config/params.c"), - "-t", - rebase_path( - "$camera_product_name_path/hdf_config/uhdf/camera/pipeline_core/params.hcs"), - ], - "") + ]) } -action("build_ipp_algo_config") { - script = "$hdf_framework_path/tools/hc-gen/build_hcs.py" +hc_gen("build_ipp_algo_config") { sources = [ rebase_path( "$camera_product_name_path/hdf_config/uhdf/camera/pipeline_core/ipp_algo_config.hcs") ] - outputs = [ "$target_gen_dir/pipeline_core/ipp_algo_config.hcb" ] - args = [ - "-o", - rebase_path(outputs[0]), - sources[0], - ] } ohos_prebuilt_etc("ipp_algo_config.hcb") {