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 78% rename from common/BUILD.gn rename to hardware/BUILD.gn index 0288373acc824dfe52e774a3f4877779b081f310..363e577468bbb16ac29aa8899475b23e455a4e98 100755 --- a/common/BUILD.gn +++ b/hardware/BUILD.gn @@ -13,11 +13,11 @@ import("//build/ohos.gni") -print("common_group in") -group("common_group") { +print("hardware_group in") +group("hardware_group") { deps = [ - "//device/rockchip/hardware/wifi:ap6xxx", - "//device/rockchip/hardware/isp:isp", - "//device/rockchip/hardware/mpp:mpp", + "wifi:ap6xxx", + "isp:isp", + "mpp:mpp", ] } diff --git a/hardware/display/BUILD.gn b/hardware/display/BUILD.gn old mode 100755 new mode 100644 index 41fc1ddd76a1842f46b1f1224c80833950cfedb6..e4f118db9c3c2f09b9946f399a8fe456447ca817 --- a/hardware/display/BUILD.gn +++ b/hardware/display/BUILD.gn @@ -12,62 +12,161 @@ # 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 = [ + "//device/rockchip/common/include", + "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("displaymoduletest") { + testonly = true + deps = [ + "test:devicetest", + "test:gfxtest", + "test:gralloctest", + ] +} + +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..2185b2c6bacd538e5794af0df71a57d366b93df4 --- /dev/null +++ b/hardware/display/src/display_device/drm_connector.cpp @@ -0,0 +1,309 @@ +/* + * 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()); + int i = 0; + if (modes != nullptr) { + 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; + int ret; + drmFd = DrmDevice::GetDrmFd(); + if ((mBlockId != DRM_INVALID_ID) && (drmFd >= 0)) { + 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..f75132d75be3813073bb9885344fda31de217b99 --- /dev/null +++ b/hardware/display/src/display_device/drm_device.cpp @@ -0,0 +1,327 @@ +/* + * 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) +{ +#if 0 + int32_t ret = DISPLAY_FAILURE; + auto iter = mEncoders.find(id); + if (iter == mEncoders.end()) { + ret = DISPLAY_SUCCESS; + } +#endif + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmConnectorFromId(uint32_t id) +{ +#if 0 + int32_t ret = DISPLAY_FAILURE; + auto iter = mConnectors.find(id); + if (iter == mConnectors.end()) { + ret = DISPLAY_SUCCESS; + } +#endif + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmCrtcFromId(uint32_t id) +{ +#if 0 + int32_t ret = DISPLAY_FAILURE; + auto iter = mCrtcs.find(id); + if (iter == mCrtcs.end()) { + ret = DISPLAY_SUCCESS; + } +#endif + 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() +{ + int32_t ret; + 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; + 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..173532b950edcaa0347b0845709541db35227518 --- /dev/null +++ b/hardware/display/src/display_device/drm_vsync_worker.cpp @@ -0,0 +1,127 @@ +/* + * 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; + uint64_t time = 0; + while (WaitSignalAndCheckRuning()) { + // wait the vblank + 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..ab6db44df60ad44cd657ad552564f48467d7f6dc --- /dev/null +++ b/hardware/display/src/display_device/hdi_drm_composition.cpp @@ -0,0 +1,169 @@ +/* + * 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 + int ret; + 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"); + 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..a82b950555fadea0df2a168b5001030149d6e80b --- /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.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 w:%{public}d h:%{public}d addr:0x%{public}" PRIx64 " fmt:%{public}d stride:%{public}d", + surface.width, surface.height, surface.phyAddr, 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..906b62b4d945af50b72d719d38cbc11649e540c2 --- /dev/null +++ b/hardware/display/src/display_device/hdi_layer.cpp @@ -0,0 +1,205 @@ +/* + * 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_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); + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr")); + 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; + const int32_t bpp = 32; + DISPLAY_CHK_RETURN_NOT_VALUE((bpp <= 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..5b8ffa476859952e39d4197d68ce46ea1ecb698c --- /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); + } +} + + +#endif // HDI_NETLINK_NONITOR_H \ 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..f9c12115253c792806c03a7c224db7b3f378f8e7 --- /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..ab9e778909b524312d81f0b5491f0a76529077d6 --- /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 = (void*)surface->phyAddr; + dst.vir_addr = surface->virAddr; + dst.fd = surface->fd; + 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, (int)surface->phyAddr, surface->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 = (void *)dstSurface->phyAddr; + dstRgaBuffer.vir_addr = dstSurface->virAddr; + dstRgaBuffer.color_space_mode = IM_COLOR_SPACE_DEFAULT; + dstRgaBuffer.fd = dstSurface->fd; + 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 = (void *)srcSurface->phyAddr; + srcRgaBuffer.vir_addr = srcSurface->virAddr; + srcRgaBuffer.format = colorSpaceModeChange(srcSurface->enColorFmt, &isYuv); + srcRgaBuffer.color_space_mode = IM_COLOR_SPACE_DEFAULT; + srcRgaBuffer.fd = srcSurface->fd; + + 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",srcSurface->fd, srcSurface->width, + srcSurface->height, ALIGN_UP(srcSurface->width, 16), ALIGN_UP(srcSurface->height, 16), srcSurface->virAddr); + DISPLAY_LOGE("gfx dst fd %{public}d, w %{public}d, h %{public}d, sw %{public}d sh %{public}d vir %{public}p",dstSurface->fd, dstSurface->width, + dstSurface->height, ALIGN_UP(dstSurface->width, 16), ALIGN_UP(dstSurface->height, 16), dstSurface->virAddr); + + 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 = (void *) buffer->phyAddr; + bRgbBuffer.vir_addr = buffer->virAddr; + bRgbBuffer.color_space_mode = dstRgaBuffer.color_space_mode; + bRgbBuffer.fd = buffer->fd; + 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..932d11bd9cb62861ec250e4933f144a926e29bb6 --- /dev/null +++ b/hardware/display/src/display_gralloc/display_gralloc.c @@ -0,0 +1,125 @@ +/* + * 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(); + int ret; + 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 + 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..8cefdc27150f4ec6c052c0683c8fa98670ad7a81 --- /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(); + char path[PATH_MAX] = {0}; + if (grallocManager->gbmDevice == NULL) { + 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/hardware/display/test/BUILD.gn b/hardware/display/test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..e30c58f2a1387686b7d18c6246c89059a46d9725 --- /dev/null +++ b/hardware/display/test/BUILD.gn @@ -0,0 +1,113 @@ +# Copyright (C) 2021 HiHope Open Source Organization . +# 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. + +import("//build/test.gni") +module_output_path = "device/display/hdi" + +config("module_private_config") { + visibility = [ ":*" ] +} + +ohos_static_library("test_common") { + sources = [ "common/display_test_utils.cpp" ] + include_dirs = [ + "include", + "//utils/native/base/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + ] + output_name = "test_common" + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + deps = [ "//utils/native/base:utils" ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_moduletest("gralloctest") { + module_out_path = module_output_path + sources = [ "display_gralloc/display_gralloc_test.cpp" ] + deps = [ + "../:display_gralloc", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + include_dirs = [ + "common", + "../src/display_gralloc", + "../include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/framework/include/utils", + "//utils/native/base/include", + "//drivers/peripheral/base", + "//drivers/peripheral/display/interfaces/include", + "//drivers/framework/include/utils", + "//foundation/graphic/standard/utils/include", + ] +} + +ohos_moduletest("gfxtest") { + module_out_path = module_output_path + sources = [ + "display_gfx/display_gfx_test.cpp", + "display_gfx/soft_blit.cpp", + ] + deps = [ + "../:display_gfx", + "../:display_gralloc", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + include_dirs = [ + "common", + "//foundation/graphic/standard/utils/include", + "//drivers/hdf/interfaces/display/include", + "//utils/native/base/include", + "//drivers/peripheral/display/interfaces/include", + "//drivers/framework/include/utils", + "//drivers/peripheral/base", + ] +} + +ohos_moduletest("devicetest") { + module_out_path = module_output_path + sources = [ + "display_device/hdi_composition_check.cpp", + "display_device/hdi_device_test.cpp", + "display_device/hdi_test_device.cpp", + "display_device/hdi_test_display.cpp", + "display_device/hdi_test_layer.cpp", + ] + deps = [ + ":test_common", + "../:display_device", + "../:display_gfx", + "../:display_gralloc", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + include_dirs = [ + "common", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + "//drivers/framework/include/utils", + "//drivers/adapter/uhdf2/osal/include", + "//utils/native/base/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ".", + ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + cflags = [ "-Wno-unused-function" ] +} diff --git a/hardware/display/test/common/display_test.h b/hardware/display/test/common/display_test.h new file mode 100644 index 0000000000000000000000000000000000000000..dc4983de1732506bd7fd524cb780f7bd53b46b49 --- /dev/null +++ b/hardware/display/test/common/display_test.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 DISPLAY_TEST_H +#define DISPLAY_TEST_H +#include +#include +#include "display_gfx.h" +#include "display_gralloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__) + +#ifndef DISPLAY_TEST_CHK_RETURN_NOT_VALUE +#define DISPLAY_TEST_CHK_RETURN_NOT_VALUE(val, ret, ...) \ + do { \ + if (val) { \ + __VA_ARGS__; \ + return; \ + } \ + } while (0) +#endif + +#ifndef DISPLAY_TEST_CHK_RETURN +#define DISPLAY_TEST_CHK_RETURN(val, ret, ...) \ + do { \ + if (val) { \ + __VA_ARGS__; \ + return (ret); \ + } \ + } while (0) +#endif + +#define DISPLAY_TEST_LOGD(format, ...) \ + do { \ + printf("[%s@%s:%d] " format "\n", __FUNCTION__, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +#define DISPLAY_TEST_LOGE(format, ...) \ + do { \ + printf("\033[0;32;31m" \ + "[%s@%s:%d] " format "\033[m" \ + "\n", \ + __FUNCTION__, __FILENAME__, __LINE__, ##__VA_ARGS__); \ + } while (0) + +#ifdef __cplusplus +} +#endif +#endif // DISPLAY_TEST_H diff --git a/hardware/display/test/common/display_test_utils.cpp b/hardware/display/test/common/display_test_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c30b6328b52006493bbbb1d09323b7b55e7fbb13 --- /dev/null +++ b/hardware/display/test/common/display_test_utils.cpp @@ -0,0 +1,211 @@ +/* + * 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 "display_test.h" +#include "display_type.h" +#include "buffer_handle.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +constexpr uint8_t BITS_PER_BYTE = 8; + +static uint32_t BGRAToRGBA(uint32_t bgra) +{ + uint32_t rgba = 0; + const int32_t twoByteOffset = 16; + + rgba |= (bgra & 0x0000ff00) << twoByteOffset; // get red then move to rgba + rgba |= (bgra & 0x00ff0000); // get green + rgba |= (bgra & 0xff000000) >> twoByteOffset; // get blue then move to rgba + rgba |= (bgra & 0x000000ff); // get alpha + return rgba; +} + +static int32_t GetPixelFormatBpp(PixelFormat format) +{ + const int32_t bppRgba8888 = 32; + switch (format) { + case PIXEL_FMT_RGBA_8888: + return bppRgba8888; + case PIXEL_FMT_BGRA_8888: + return bppRgba8888; + default: + return -1; + } +} + +void SaveFile(const char *fileName, uint8_t *data, int size) +{ + int fileFd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + int hasWriten = write(fileFd, data, size); + DISPLAY_TEST_LOGD("SaveFile hasWriten %d", hasWriten); +} + +static uint32_t ConverToRGBA(PixelFormat fmt, uint32_t color) +{ + switch (fmt) { + case PIXEL_FMT_BGRA_8888: + return BGRAToRGBA(color); + case PIXEL_FMT_RGBA_8888: + return color; + default: + DISPLAY_TEST_LOGE("the fmt can not covert %d", fmt); + } + return color; +} + +uint32_t GetPixelValue(const BufferHandle &handle, int x, int y) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), 0, + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + return *pixel; +} + +uint32_t GetUint32(uint32_t value) +{ + uint32_t dst; + uint8_t *data = reinterpret_cast(&dst); + for (uint8_t i = 0; i < sizeof(uint32_t); i++) { + *(data + i) = (value >> ((sizeof(uint32_t) - i - 1) * BITS_PER_BYTE)) & 0xff; + } + return dst; +} + +uint32_t CheckPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), 0, + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + uint32_t checkColor = ConverToRGBA(static_cast(handle.format), GetUint32(*pixel)); + if (checkColor != color) { + DISPLAY_TEST_LOGD("the pixel color not match vAddr:%p position:%d pixel:%08x color:%08x", handle.virAddr, + position, checkColor, color); + DISPLAY_TEST_LOGD("x:%d y:%d width:%d", x, y, handle.width); + SaveFile("/data/display_test_bitmap_", static_cast(handle.virAddr), handle.size); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} + +void SetUint32(uint32_t &dst, uint32_t value) +{ + constexpr uint8_t BITS_PER_BYTE = 8; + uint8_t *data = reinterpret_cast(&dst); + for (uint8_t i = 0; i < sizeof(uint32_t); i++) { + *(data + i) = (value >> ((sizeof(uint32_t) - i - 1) * BITS_PER_BYTE)) & 0xff; + } +} + +void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + constexpr int32_t pixelBytes = 4; + constexpr int32_t bpp = 32; + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((bpp <= 0), + DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + SetUint32(*pixel, color); +} + +void ClearColor(const BufferHandle &handle, uint32_t color) +{ + for (int32_t x = 0; x < handle.width; x++) { + for (int32_t y = 0; y < handle.height; y++) { + SetPixel(handle, x, y, color); + } + } +} + +void ClearColorRect(const BufferHandle &handle, uint32_t color, IRect &rect) +{ + DISPLAY_TEST_LOGD("x %d, y %d w %d h %d color %x ", rect.x, rect.y, rect.w, rect.h, color); + for (int32_t x = 0; x < rect.w; x++) { + for (int32_t y = 0; y < rect.h; y++) { + SetPixel(handle, x + rect.x, y + rect.y, color); + } + } +} + +std::vector SplitBuffer(const BufferHandle &handle, std::vector &colors) +{ + std::vector splitRects; + if (colors.empty()) { + DISPLAY_TEST_LOGD("the colors empty"); + } + const uint32_t rowNum = sqrt(colors.size()); + const uint32_t colNum = rowNum; + if (colNum == 0) { + DISPLAY_TEST_LOGD("rowNum and colNum are zero"); + return splitRects; + } + const uint32_t cellWidth = handle.width / rowNum; + const uint32_t cellHeight = handle.height / colNum; + IRect rect = { 0, 0, cellWidth, cellHeight }; + DISPLAY_TEST_LOGD("rowNum %d, colNum %d cellWidth %d cellHeight %d", rowNum, colNum, cellWidth, cellHeight); + uint32_t count = 0; + for (uint32_t x = 0; x < rowNum; x++) { + for (uint32_t y = 0; y < colNum; y++) { + rect.x = x * cellWidth; + rect.y = y * cellHeight; + ClearColorRect(handle, colors[count++], rect); + splitRects.push_back(rect); + } + } + SaveFile("/data/splitbuffer_data_", static_cast(handle.virAddr), handle.size); + return splitRects; +} +} // OHOS +} // HDI +} // DISPLAY +} // TEST diff --git a/hardware/display/test/common/display_test_utils.h b/hardware/display/test/common/display_test_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..ab42971d21955533bb9694993beb85d790c6008f --- /dev/null +++ b/hardware/display/test/common/display_test_utils.h @@ -0,0 +1,37 @@ +/* + * 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_TEST_UTILS_H +#define DISPLAY_TEST_UTILS_H +#include +#include "display_test.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +void SaveFile(const char *fileName, uint8_t *data, int size); +void SetUint32(uint32_t &dst, uint32_t value); +void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color); +void ClearColor(const BufferHandle &handle, uint32_t color); +uint32_t GetPixelValue(const BufferHandle &handle, int x, int y); +uint32_t CheckPixel(const BufferHandle &handle, int x, int y, uint32_t color); +std::vector SplitBuffer(const BufferHandle &handle, std::vector &colors); +} // OHOS +} // HDI +} // DISPLAY +} // TEST + + +#endif // HDI_TEST_RENDER_UTILS_H diff --git a/hardware/display/test/display_device/hdi_composition_check.cpp b/hardware/display/test/display_device/hdi_composition_check.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9ce468c0c6de95f0f1ea98fc7dee49640ce22eb --- /dev/null +++ b/hardware/display/test/display_device/hdi_composition_check.cpp @@ -0,0 +1,116 @@ +/* + * 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_composition_check.h" +#include "display_test.h" +#include "display_test_utils.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +void HdiCompostionCheck::GetCheckPoints(Point center, std::vector &points) +{ + constexpr uint32_t step = 3; + points.push_back(center); + points.push_back({ center.x + step, center.y }); + points.push_back({ center.x + step, center.y + step }); + points.push_back({ center.x + step, center.y - step }); + points.push_back({ center.x, center.y + step }); + points.push_back({ center.x - step, center.y }); + points.push_back({ center.x - step, center.y - step }); + points.push_back({ center.x - step, center.y + step }); + points.push_back({ center.x, center.y - step }); +} +// simple hande the alpha it may not compatible with all scenarios +void HdiCompostionCheck::SimpleHandleAlpha(const LayerSettings &layers, uint32_t &color) +{ + const float inv = 1.0f / 255.0f; + if (layers.alpha != -1) { + switch (layers.blendType) { + case BLEND_SRC: + color = (color & 0xffffff00) | (layers.alpha & 0xff); // get the alpha + break; + case BLEND_SRCOVER: + color = color * (layers.alpha * inv); + color = (color & 0xffffff00) | (layers.alpha & 0xff); // get the alpha + break; + default: + break; + } + } +} + +std::vector HdiCompostionCheck::GetCheckColors(std::vector &layers, std::vector &points) +{ + std::vector colors; + for (auto point : points) { + uint32_t color = 0; + for (uint32_t i = layers.size(); i > 0; i--) { + auto layer = layers[i - 1]; + IRect &rect = layer.displayRect; + // check wether the point is inside the rect + if ((point.x >= rect.x) && (point.x < (rect.x + rect.w)) && (point.y >= rect.y) && + (point.y < (rect.y + rect.h))) { + if (layer.compositionType != COMPOSITION_VIDEO) { + color = layer.color; + SimpleHandleAlpha(layer, color); + } + break; + } + } + colors.push_back(color); + } + return colors; +} + +int32_t HdiCompostionCheck::Check(std::vector &layers, BufferHandle &clientBuffer, uint32_t checkType) +{ + int ret = DISPLAY_SUCCESS; + const int midPos = 2; + // get the all check point + std::vector points; + for (auto layer : layers) { + IRect &rect = layer.displayRect; + if (checkType == CHECK_VERTEX) { + GetCheckPoints({ rect.x, rect.y }, points); + GetCheckPoints({ rect.x, rect.y + rect.h }, points); + GetCheckPoints({ rect.x + rect.w, rect.y }, points); + GetCheckPoints({ rect.x + rect.w, rect.y + rect.h }, points); + } else { + GetCheckPoints({ rect.x + rect.w / midPos, rect.y + rect.h / midPos }, points); // center point + } + } + + // get all the check color + std::vector colors = GetCheckColors(layers, points); + DISPLAY_TEST_CHK_RETURN((colors.size() != points.size()), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("Points and colors don't match")); + for (uint32_t i = 0; i < points.size(); i++) { + if ((points[i].x >= clientBuffer.width) || (points[i].x < 0) || (points[i].y < 0) || + (points[i].y >= clientBuffer.height)) { + continue; + } + ret = CheckPixel(clientBuffer, points[i].x, points[i].y, colors[i]); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("check failed"); + break; + } + } + return ret; +} +} // OHOS +} // HDI +} // DISPLAY +} // TEST \ No newline at end of file diff --git a/hardware/display/test/display_device/hdi_composition_check.h b/hardware/display/test/display_device/hdi_composition_check.h new file mode 100644 index 0000000000000000000000000000000000000000..a913f5c00fce0facd95eb1814f3eae1eacff28f0 --- /dev/null +++ b/hardware/display/test/display_device/hdi_composition_check.h @@ -0,0 +1,62 @@ +/* + * 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_COMPOSITION_CHECK_H +#define HDI_COMPOSITION_CHECK_H +#include "display_type.h" +#include "hdi_device_test.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +struct Point { + int32_t x = 0; + int32_t y = 0; +}; + +class HdiCompostionCheck { +public: + static HdiCompostionCheck &GetInstance() + { + static HdiCompostionCheck instace = HdiCompostionCheck(); + return instace; + } + void Init(uint32_t w, uint32_t h) + { + mDispW = w; + mDispH = h; + } + enum { + CHECK_CENTER, + CHECK_VERTEX + }; + int32_t Check(std::vector &layers, BufferHandle &clientBuffer, uint32_t type = CHECK_VERTEX); + +private: + void GetCheckPoints(Point center, std::vector &points); + void SimpleHandleAlpha(const LayerSettings &layers, uint32_t &color); + std::vector GetCheckColors(std::vector &layers, std::vector &points); + HdiCompostionCheck() {} + ~HdiCompostionCheck() {} + uint32_t mDispW = 0; + uint32_t mDispH = 0; +}; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + +#endif // HDI_COMPOSITION_CHECK_H \ No newline at end of file diff --git a/hardware/display/test/display_device/hdi_device_test.cpp b/hardware/display/test/display_device/hdi_device_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c73a07941c4b3db7b85cc68b640160e0b65da17f --- /dev/null +++ b/hardware/display/test/display_device/hdi_device_test.cpp @@ -0,0 +1,542 @@ +/* + * 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_test.h" +#include +#include +#include +#include "display_device.h" +#include "display_gralloc.h" +#include "display_layer.h" +#include "display_test.h" +#include "display_test_utils.h" +#include "hdi_composition_check.h" +#include "hdi_test_device.h" +#include "hdi_test_device_common.h" +#include "hdi_test_display.h" +#include "hdi_test_render_utils.h" + +using namespace OHOS::HDI::DISPLAY::TEST; +static std::shared_ptr g_testFreshLayer; + +static const std::vector> TEST_SINGLE_LAYER = { + // one layer display test + { + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = RED }, + }, + { + { + .rectRatio = { 0, 0.875f, 1.0f, 0.125f }, + .color = GREEN }, + }, + { + { + .rectRatio = { 0, 0.0, 1.0f, 1.0f }, + .color = YELLOW }, + }, +}; + +static const std::vector> TEST_MULTILAYER = { + + // three layer displayrect test + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = GREEN }, + { + .rectRatio = { 0, 0.875f, 1.0f, 0.125f }, + .color = YELLOW }, + } + +}; + +static const std::vector> TEST_SCALE = { + // scale layer test + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .bufferRatio = { 1.5, 1.5 } }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = GREEN, + .bufferSize = { 1, 1 } }, + }, + { + { + .rectRatio = { 0, 0.875f, 1.0f, 0.125f }, + .color = YELLOW, + .bufferRatio = { 0.25, 0.25 } }, + } +}; + +static const std::vector> TEST_VIDEO = { + // video layer test + { + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = GREEN, + .compositionType = COMPOSITION_VIDEO }, + }, + + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .compositionType = COMPOSITION_VIDEO }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = GREEN, + .compositionType = COMPOSITION_VIDEO }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + { + .rectRatio = { 0, 0.875f, 1.0f, 0.125f }, + .color = YELLOW, + .compositionType = COMPOSITION_VIDEO }, + } +}; + +static const std::vector> TEST_ALPHA = { + // alpha layer test + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .alpha = 0xFF }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .alpha = 0x55 }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .alpha = 0x00 }, + }, + // RED float will overide, must use green now + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = GREEN, + .alpha = 0xFF, + .blendType = BLEND_SRCOVER }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = GREEN, + .alpha = 0xA7, + .blendType = BLEND_SRCOVER }, + }, + { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = GREEN, + .alpha = 0x00, + .blendType = BLEND_SRCOVER }, + }, +}; + +const std::vector TEST_ROTATE = { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .rotate = ROTATE_NONE }, + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .rotate = ROTATE_90 }, + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .rotate = ROTATE_180 }, + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED, + .rotate = ROTATE_270 }, +}; + +inline std::shared_ptr GetFirstDisplay() +{ + return HdiTestDevice::GetInstance().GetFirstDisplay(); +} + +int32_t CheckComposition(std::vector &layers, BufferHandle *clientBuffer, + uint32_t checkType = HdiCompostionCheck::CHECK_VERTEX) +{ + DISPLAY_TEST_CHK_RETURN((clientBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_TEST_LOGE("client buffer is nullptr")); + return HdiCompostionCheck::GetInstance().Check(layers, *clientBuffer, checkType); +} + +std::shared_ptr CreateTestLayer(LayerSettings setting, uint32_t zorder) +{ + int ret; + HdiTestDevice::GetInstance(); + DISPLAY_TEST_LOGD("color 0x%x", setting.color); + std::shared_ptr display = HdiTestDevice::GetInstance().GetFirstDisplay(); + DISPLAY_TEST_CHK_RETURN((display == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get display")); + + std::shared_ptr layer = display->CreateHdiTestLayer(setting.bufferSize.w, setting.bufferSize.h); + DISPLAY_TEST_CHK_RETURN((layer == nullptr), nullptr, DISPLAY_TEST_LOGE("can not create hdi test layer")); + + layer->SetLayerSize(setting.displayRect); + + layer->SetCompType(setting.compositionType); + + if ((setting.alpha >= 0) && (setting.alpha <= 0xff)) { // alpha rang 0x00 ~ 0xff + LayerAlpha alpha = { 0 }; + alpha.gAlpha = setting.alpha; + alpha.enGlobalAlpha = true; + layer->SetAlpha(alpha); + } + HdiGrallocBuffer *handle = layer->GetFrontBuffer(); + DISPLAY_TEST_CHK_RETURN((handle == nullptr), nullptr, DISPLAY_TEST_LOGE("can not get front buffer")); + ClearColor(*(handle->Get()), setting.color); + ret = layer->SwapFrontToBackQ(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("SwapFrontToBackQ failed")); + layer->SetZorder(zorder); + layer->SetBlendType(setting.blendType); + layer->SetTransform(setting.rotate); + return layer; +} + +int PrepareAndPrensent() +{ + int ret; + DISPLAY_TEST_LOGD(); + std::shared_ptr display = HdiTestDevice::GetInstance().GetFirstDisplay(); + DISPLAY_TEST_CHK_RETURN((display == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get display")); + + ret = display->PrepareDisplayLayers(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("PrepareDisplayLayers failed")); + + ret = display->Commit(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Commit failed")); + return DISPLAY_SUCCESS; +} + +void TestVBlankCallback(unsigned int sequence, uint64_t ns, void *data) +{ + static uint64_t lastns; + DISPLAY_TEST_LOGD("seq %d ns %" PRId64 " duration %" PRId64 " ns", sequence, ns, (ns - lastns)); + lastns = ns; + VblankCtr::GetInstance().NotifyVblank(sequence, ns, data); +} + +int TestVblankEvent() +{ + DISPLAY_TEST_LOGD(); + std::shared_ptr display = HdiTestDevice::GetInstance().GetFirstDisplay(); + int ret = display->RegDisplayVBlankCallback(TestVBlankCallback, nullptr); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("RegDisplayVBlankCallback failed")); + ret = display->SetDisplayVsyncEnabled(true); + return ret; +} + +void AdjustLayerSettings(std::vector &settings, uint32_t w, uint32_t h) +{ + DISPLAY_TEST_LOGD(); + for (uint32_t i = 0; i < settings.size(); i++) { + LayerSettings &setting = settings[i]; + DISPLAY_TEST_LOGD(" ratio w: %f ratio h: %f", setting.rectRatio.w, setting.rectRatio.h); + if ((setting.rectRatio.w > 0.0f) && (setting.rectRatio.h > 0.0f)) { + setting.displayRect.h = static_cast(setting.rectRatio.h * h); + setting.displayRect.w = static_cast(setting.rectRatio.w * w); + setting.displayRect.x = static_cast(setting.rectRatio.x * w); + setting.displayRect.y = static_cast(setting.rectRatio.y * h); + DISPLAY_TEST_LOGD("display rect adust form %f %f %f %f to %d %d %d %d ", setting.rectRatio.x, + setting.rectRatio.y, setting.rectRatio.w, setting.rectRatio.h, setting.displayRect.x, + setting.displayRect.y, setting.displayRect.w, setting.displayRect.h); + } + + if ((setting.bufferRatio.h > 0.0f) || (setting.bufferRatio.w > 0.0f)) { + setting.bufferSize.h = static_cast(setting.bufferRatio.h * h); + setting.bufferSize.w = static_cast(setting.bufferRatio.w * w); + DISPLAY_TEST_LOGD("buffer szie adjust for %f %f to %d %d", setting.bufferRatio.w, setting.bufferRatio.h, + setting.bufferSize.w, setting.bufferSize.h); + } + + if ((setting.bufferSize.w == 0) || (setting.bufferSize.h == 0)) { + DISPLAY_TEST_LOGD("buffer szie adjust for %d %d to %d %d", setting.bufferSize.w, setting.bufferSize.h, + setting.displayRect.w, setting.displayRect.h); + + setting.bufferSize.w = setting.displayRect.w; + setting.bufferSize.h = setting.displayRect.h; + } + } +} + +std::vector> CreateLayers(std::vector &settings) +{ + DISPLAY_TEST_LOGD("settings %u", settings.size()); + std::vector> layers; + DisplayModeInfo mode = GetFirstDisplay()->GetCurrentMode(); + AdjustLayerSettings(settings, mode.width, mode.height); + for (uint32_t i = 0; i < settings.size(); i++) { + LayerSettings setting = settings[i]; + + auto layer = CreateTestLayer(setting, i); + layers.push_back(layer); + } + + return layers; +} + +inline void PresentAndCheck(std::vector &layerSettings, + uint32_t checkType = HdiCompostionCheck::CHECK_VERTEX) +{ + int ret; + ret = PrepareAndPrensent(); + ASSERT_TRUE((ret == DISPLAY_SUCCESS)); + HdiTestDevice::GetInstance().GetGrallocFuncs().InvalidateCache(GetFirstDisplay()->SnapShot()); + ret = CheckComposition(layerSettings, GetFirstDisplay()->SnapShot(), checkType); + ASSERT_TRUE((ret == DISPLAY_SUCCESS)); +} + +void LayerRotateTest::TearDown() +{ + DISPLAY_TEST_LOGD(); + HdiTestDevice::GetInstance().Clear(); +} + +void DeviceTest::TearDown() +{ + DISPLAY_TEST_LOGD(); + HdiTestDevice::GetInstance().Clear(); +} + +void DeviceLayerDisplay::TearDown() +{ + HdiTestDevice::GetInstance().Clear(); +} + +void VblankCtr::NotifyVblank(unsigned int sequence, uint64_t ns, void *data) +{ + DISPLAY_TEST_LOGD(); + std::unique_lock lg(mVblankMutex); + mHasVblank = true; + mVblankCondition.notify_one(); + DISPLAY_TEST_LOGD(); +} + +VblankCtr::~VblankCtr() {} + +int32_t VblankCtr::WaitVblank(uint32_t ms) +{ + bool ret; + DISPLAY_TEST_LOGD(); + std::unique_lock lck(mVblankMutex); + mHasVblank = false; // must wait next vblank + ret = mVblankCondition.wait_for(lck, std::chrono::milliseconds(ms), [=] { return mHasVblank; }); + DISPLAY_TEST_LOGD(); + if (!ret) { + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} + +void VblankTest::TearDown() +{ + auto display = HdiTestDevice::GetInstance().GetFirstDisplay(); + int32_t ret = display->SetDisplayVsyncEnabled(false); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("vsync disable failed"); + } + VblankCtr::GetInstance().WaitVblank(100); // wait for last vsync 100ms. + HdiTestDevice::GetInstance().Clear(); +} + +TEST_P(DeviceLayerDisplay, LayerDisplay) +{ + std::vector layerSettings = GetParam(); + CreateLayers(layerSettings); + PresentAndCheck(layerSettings); + if (TestParemeter::GetInstance().mTestSleep > 0) { + sleep(TestParemeter::GetInstance().mTestSleep); + } +} + +TEST_F(DeviceTest, zorder) +{ + std::vector settings = { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + { + .rectRatio = { 0, 0, 1.0f, 0.125f }, + .color = GREEN }, + { + .rectRatio = { 0, 0.875f, 1.0f, 0.125f }, + .color = YELLOW }, + }; + + std::vector> zorders = { + { 3, 2, 1 }, { 1, 3, 2 }, { 3, 1, 2 }, { 1, 2, 3 }, { 2, 1, 3 }, { 9, 100, 3 }, + }; + std::vector> layers = CreateLayers(settings); + + for (const auto &zorderList : zorders) { + // adjust the zorder + for (uint32_t i = 0; i < zorderList.size(); i++) { + settings[i].zorder = zorderList[i]; + layers[i]->SetZorder(zorderList[i]); + } + std::vector tempSettings = settings; + std::sort(tempSettings.begin(), tempSettings.end(), + [=](const auto &l, auto const & r) { return l.zorder < r.zorder; }); + // present and check + PresentAndCheck(tempSettings); + } + HdiTestDevice::GetInstance().Clear(); +} + +TEST_P(LayerRotateTest, SplitCheck) +{ + LayerSettings settings = GetParam(); + std::vector layersSetting = { settings }; + std::vector splitColors = { RED, GREEN, YELLOW, TRANSPARENT }; + std::vector> layers = CreateLayers(layersSetting); + ASSERT_TRUE((layers.size() > 0)); + // split the buffer + auto layer = layers[0]; + HdiGrallocBuffer *handle = layer->GetBackBuffer(); // the backbuffer has not present now + ASSERT_TRUE((handle != nullptr)); + auto splitRects = SplitBuffer(*(handle->Get()), splitColors); + ASSERT_TRUE(splitRects.size() == splitColors.size()); // ensure the splitRects size + PrepareAndPrensent(); + // chage the rect and color to clockwise. + std::swap(splitColors[2], splitColors[1]); + std::swap(splitColors[2], splitColors[3]); + std::swap(splitRects[2], splitRects[1]); + std::swap(splitRects[2], splitRects[3]); + + // rotation is clockwise,the color will change clockwise, we just change the color start index + uint32_t startIndex = 0; + switch (settings.rotate) { + case ROTATE_90: + startIndex = 3; // start form color index 3 + break; + case ROTATE_180: + startIndex = 2; // start form color index 2 + break; + case ROTATE_270: + startIndex = 1; // start form color index 1 + break; + default: + startIndex = 0; + break; + } + std::vector layersCheck; + for (uint32_t i = 0; i < splitRects.size(); i++) { + uint32_t color = splitColors[(i + startIndex) % sizeof(splitColors.size())]; + layersCheck.push_back({ + .displayRect = splitRects[i], + .color = color }); + } + ASSERT_TRUE((handle != nullptr)); + /* for rotation may scale the buffer , Near the edge of rect the color will Smooth gradient, + so we must use the center to check. + */ + PresentAndCheck(layersCheck, HdiCompostionCheck::CHECK_CENTER); +} + +TEST_F(DeviceTest, crop) +{ + std::vector settings = { + { + .rectRatio = { 0, 0, 1.0f, 1.0f }, + .color = RED }, + }; + std::vector splitColors = { { RED, GREEN, YELLOW, TRANSPARENT } }; + + std::vector> layers = CreateLayers(settings); + ASSERT_TRUE((layers.size() > 0)); + // split the buffer + auto layer = layers[0]; + HdiGrallocBuffer *handle = layer->GetBackBuffer(); // the backbuffer has not present now + ASSERT_TRUE((handle != nullptr)); + auto splitRects = SplitBuffer(*(handle->Get()), splitColors); + PrepareAndPrensent(); + for (uint32_t i = 0; i < splitRects.size(); i++) { + settings[0].color = splitColors[i]; + layer->SetLayerCrop(splitRects[i]); + PresentAndCheck(settings); + } +} + +TEST_F(VblankTest, CtrlTest) +{ + int ret; + DISPLAY_TEST_LOGD(); + std::shared_ptr display = HdiTestDevice::GetInstance().GetFirstDisplay(); + ret = display->RegDisplayVBlankCallback(TestVBlankCallback, nullptr); + ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "RegDisplayVBlankCallback failed"; + ret = display->SetDisplayVsyncEnabled(true); + ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed"; + ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms + ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "WaitVblank timeout"; + ret = display->SetDisplayVsyncEnabled(false); + ASSERT_TRUE(ret == DISPLAY_SUCCESS) << "SetDisplayVsyncEnabled failed"; + usleep(100 * 1000); // wait for 100ms avoid the last vsync. + ret = VblankCtr::GetInstance().WaitVblank(1000); // 1000ms + ASSERT_TRUE(ret != DISPLAY_SUCCESS) << "vblank do not disable"; +} + +INSTANTIATE_TEST_CASE_P(MultiLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_MULTILAYER)); +INSTANTIATE_TEST_CASE_P(SingleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SINGLE_LAYER)); +INSTANTIATE_TEST_CASE_P(ScaleLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_SCALE)); +INSTANTIATE_TEST_CASE_P(VideoLayer, DeviceLayerDisplay, ::testing::ValuesIn(TEST_VIDEO)); +INSTANTIATE_TEST_CASE_P(LayerAlpha, DeviceLayerDisplay, ::testing::ValuesIn(TEST_ALPHA)); +INSTANTIATE_TEST_CASE_P(Rotation, LayerRotateTest, ::testing::ValuesIn(TEST_ROTATE)); + +int main(int argc, char **argv) +{ + int ret; + ret = HdiTestDevice::GetInstance().InitDevice(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("Init Device Failed")); + ::testing::InitGoogleTest(&argc, argv); + ret = RUN_ALL_TESTS(); + auto display = HdiTestDevice::GetInstance().GetFirstDisplay(); + if (display != nullptr) { + // avoid vsync call back affer the destruction of VblankCtr + display->SetDisplayVsyncEnabled(false); + VblankCtr::GetInstance().WaitVblank(100); + } + return ret; +} diff --git a/hardware/display/test/display_device/hdi_device_test.h b/hardware/display/test/display_device/hdi_device_test.h new file mode 100644 index 0000000000000000000000000000000000000000..84fb82266784ab2b150bb06e2edd0f0628b8520e --- /dev/null +++ b/hardware/display/test/display_device/hdi_device_test.h @@ -0,0 +1,125 @@ +/* + * 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_TEST_H +#define HDI_DEVICE_TEST_H +#include +#include +#include +#include "gtest/gtest.h" +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +constexpr uint32_t DISPLAY_DEAULT_W = 480; +constexpr uint32_t DISPLAY_DEAULT_H = 960; + +constexpr uint32_t RED = 0xff0000ff; +constexpr uint32_t GREEN = 0x00ff00ff; +constexpr uint32_t BLUE = 0x0000ffff; +constexpr uint32_t TRANSPARENT = 0; +constexpr uint32_t YELLOW = 0xffff29ff; + +struct FRect { + float x = 0; + float y = 0; + float w = 0; // ratio + float h = 0; // ratio +}; + +struct BufferRatio { + float w; + float h; +}; + +struct Size { + uint32_t w; + uint32_t h; +}; + +struct LayerSettings { + IRect displayRect; + IRect displayCrop; + FRect rectRatio = { 0.0f }; + uint32_t color; + uint32_t zorder = 0; + Size bufferSize = { 0 }; + BufferRatio bufferRatio { 0 }; + int32_t alpha = -1; + CompositionType compositionType = COMPOSITION_DEVICE; + BlendType blendType = BLEND_SRC; + TransformType rotate = ROTATE_NONE; +}; + +struct TestParemeter { + static TestParemeter &GetInstance() + { + static TestParemeter instance; + return instance; + } + int32_t mTestSleep = 0; +}; + +using LayersSetting = std::vector; +class DeviceLayerDisplay : public ::testing::TestWithParam> { +protected: + void SetUp() {} + void TearDown(); +}; + +class DeviceTest : public ::testing::Test { +protected: + void TearDown(); +}; + +// only support single layer test +class LayerRotateTest : public ::testing::TestWithParam { +protected: + void TearDown(); +}; + +class VblankTest : public ::testing::Test { +protected: + void TearDown(); +}; + +class VblankCtr { +public: + static VblankCtr &GetInstance() + { + static VblankCtr instance; + return instance; + } + void NotifyVblank(unsigned int sequence, uint64_t ns, void *data); + int32_t WaitVblank(uint32_t ms); + +protected: + void TearDown(); + +private: + std::mutex mVblankMutex; + std::condition_variable mVblankCondition; + VblankCtr() {} + ~VblankCtr(); + bool mHasVblank = false; +}; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + +#endif // HDI_DEVICE_TEST_H \ No newline at end of file diff --git a/hardware/display/test/display_device/hdi_test_device.cpp b/hardware/display/test/display_device/hdi_test_device.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55a93213faa3bdba12f3f72e9187e2ee0bce7b35 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_device.cpp @@ -0,0 +1,95 @@ +/* + * 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_test_device.h" +#include +#include "hdi_test_device_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +HdiTestDevice &HdiTestDevice::GetInstance() +{ + static HdiTestDevice device; + return device; +} + +void HdiTestDevice::HotPlug(uint32_t outputId, bool connected, void *data) +{ + DISPLAY_TEST_LOGD("outputId %d connected %d", outputId, connected); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((data == nullptr), DISPLAY_TEST_LOGE("the data is null ptr")); + HdiTestDevice *device = static_cast(data); + if (connected) { + device->FindDisplayOrCreate(outputId); + } + DISPLAY_TEST_LOGD("end"); +} + +int32_t HdiTestDevice::InitDevice() +{ + int ret; + ret = DeviceInitialize(&mDeviceFuncs); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("DeviceInitialize Failed")); + DISPLAY_TEST_CHK_RETURN((mDeviceFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("device funcs is null")); + ret = LayerInitialize(&mLayerFuncs); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("LayerInitialize Failed")); + DISPLAY_TEST_CHK_RETURN((mLayerFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("layer funcs is null")); + ret = GrallocInitialize(&mGrallocFuncs); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("GrallocInitialize Failed")); + DISPLAY_TEST_CHK_RETURN((mGrallocFuncs == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("gralloc funcs is null")); + + mDeviceFuncs->RegHotPlugCallback(HotPlug, static_cast(this)); + return DISPLAY_SUCCESS; +} + +std::shared_ptr HdiTestDevice::GetDisplayFromId(uint32_t id) +{ + auto iter = mDisplays.find(id); + DISPLAY_TEST_CHK_RETURN((iter == mDisplays.end()), nullptr, DISPLAY_TEST_LOGD("can not find the display %d", id)); + return mDisplays[id]; +} + +std::shared_ptr HdiTestDevice::FindDisplayOrCreate(uint32_t id) +{ + int ret; + std::shared_ptr display = GetDisplayFromId(id); + if (display == nullptr) { + DISPLAY_TEST_LOGD("the display not find will creat a display"); + } + display = std::make_shared(id, *mDeviceFuncs); + ret = display->Init(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("can not init the display")); + mDisplays.emplace(id, display); + return display; +} + +std::shared_ptr HdiTestDevice::GetFirstDisplay() +{ + DISPLAY_TEST_CHK_RETURN((mDisplays.begin() == mDisplays.end()), nullptr, + DISPLAY_TEST_LOGE("the mDisplays is empty")); + return mDisplays.begin()->second; +} + +void HdiTestDevice::Clear() +{ + for (auto const & iter : mDisplays) { + iter.second->Clear(); + } +} +} // OHOS +} // HDI +} // DISPLAY +} // TEST diff --git a/hardware/display/test/display_device/hdi_test_device.h b/hardware/display/test/display_device/hdi_test_device.h new file mode 100644 index 0000000000000000000000000000000000000000..a3fd906d89ba58fd9a6dcc68868c9335adee7bb1 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_device.h @@ -0,0 +1,67 @@ +/* + * 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_TEST_DEVICE +#define HDI_TEST_DEVICE +#include +#include +#include "display_device.h" +#include "display_gralloc.h" +#include "display_layer.h" +#include "hdi_test_device_common.h" +#include "hdi_test_display.h" +#include "hdi_test_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +class HdiTestDevice { +public: + static HdiTestDevice &GetInstance(); + static void HotPlug(uint32_t outputId, bool connected, void *data); + int32_t InitDevice(); + + GrallocFuncs &GetGrallocFuncs() + { + return *mGrallocFuncs; + } + LayerFuncs &GetLayerFuncs() + { + return *mLayerFuncs; + } + DeviceFuncs &GetDeviceFuncs() + { + return *mDeviceFuncs; + } + + std::shared_ptr GetDisplayFromId(uint32_t id); + std::shared_ptr GetFirstDisplay(); + void Clear(); + +private: + std::shared_ptr FindDisplayOrCreate(uint32_t id); + + std::map> mDisplays; + DeviceFuncs *mDeviceFuncs = nullptr; + LayerFuncs *mLayerFuncs = nullptr; + GrallocFuncs *mGrallocFuncs = nullptr; +}; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + +#endif // HDI_TEST_DEVICE diff --git a/hardware/display/test/display_device/hdi_test_device_common.h b/hardware/display/test/display_device/hdi_test_device_common.h new file mode 100644 index 0000000000000000000000000000000000000000..0f3aaa65685adcc530b7a372e90121e4c5f12339 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_device_common.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 HDI_DEVICE_DEVICE_COMMON_H +#define HDI_DEVICE_DEVICE_COMMON_H +#include +#include +#include +#include +#include +#include +#include +#include +#include "display_test.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +class HdiTestDevice; +class HdiTestDisplay; +class HdiTestLayer; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + + +#endif // HDI_DEVICE_DEVICE_TEST_H \ No newline at end of file diff --git a/hardware/display/test/display_device/hdi_test_display.cpp b/hardware/display/test/display_device/hdi_test_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87f91a74e132adc6f07f738171a131393dc540a0 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_display.cpp @@ -0,0 +1,235 @@ +/* + * 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_test_display.h" +#include "display_test_utils.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +HdiTestDisplay::HdiTestDisplay(uint32_t id, DeviceFuncs &deviceFunc) : mId(id), mDeviceFunc(deviceFunc) {} + +int32_t HdiTestDisplay::Init() +{ + DISPLAY_TEST_LOGD(); + int ret; + ret = mDeviceFunc.GetDisplayCapability(mId, &mCap); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get cap")); + DISPLAY_TEST_LOGD("the capablility name %s type : %d phyWidth : %d phyHeight : %d", mCap.name, mCap.type, + mCap.phyWidth, mCap.phyHeight); + // get the modes + int num = 0; + ret = mDeviceFunc.GetDisplaySuppportedModes(mId, &num, nullptr); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get modes num")); + DISPLAY_TEST_CHK_RETURN((num <= 0), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("the mode num is %d", num)); + mModes.resize(num); + ret = mDeviceFunc.GetDisplaySuppportedModes(mId, &num, mModes.data()); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get modes")); + DISPLAY_TEST_LOGD("the modes size() %d", mModes.size()); + + ret = mDeviceFunc.GetDisplayMode(mId, &mActiveModeId); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("the mode id is : %d", mActiveModeId)); + + ret = GetModeInfoFromId(mActiveModeId, mCurrentMode); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("can not get the mode of id : %d", mActiveModeId)); + + LayerInfo layerinfo = { 0 }; + layerinfo.width = mCurrentMode.width; + layerinfo.height = mCurrentMode.height; + layerinfo.pixFormat = PIXEL_FMT_BGRA_8888; + const uint32_t clientLayerId = 0xffffffff; // invalid id + mClientLayer = std::make_unique(layerinfo, clientLayerId, mId); + ret = mClientLayer->Init(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("the client layer can not creat")); + return DISPLAY_SUCCESS; +} + +int32_t HdiTestDisplay::GetModeInfoFromId(int32_t id, DisplayModeInfo &modeInfo) +{ + DISPLAY_TEST_LOGD(); + for (const auto &mode : mModes) { + if (mode.id == id) { + modeInfo = mode; + DISPLAY_TEST_LOGD("the mode width: %d height : %d freshRate : %u id: %d", mode.width, mode.height, + mode.freshRate, mode.id); + return DISPLAY_SUCCESS; + } + } + DISPLAY_TEST_LOGE("can not find the modeinfo id : %d", id); + return DISPLAY_FAILURE; +} + +std::shared_ptr HdiTestDisplay::CreateHdiTestLayer(LayerInfo &info) +{ + DISPLAY_TEST_LOGD(); + uint32_t layerId = 0; + LayerFuncs &layerFuncs = HdiTestDevice::GetInstance().GetLayerFuncs(); + int ret; + ret = layerFuncs.CreateLayer(mId, &info, &layerId); + DISPLAY_TEST_LOGD(" layerId %d", layerId); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("layer creat failed")); + auto layer = std::make_shared(info, layerId, mId); + ret = layer->Init(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), nullptr, DISPLAY_TEST_LOGE("layer init failed")); + mLayerMaps.emplace(layerId, layer); + return layer; +} + +std::shared_ptr HdiTestDisplay::CreateHdiTestLayer(uint32_t w, uint32_t h) +{ + const int32_t bpp = 32; + + LayerInfo info = { w, h, LAYER_TYPE_GRAPHIC, bpp, PIXEL_FMT_RGBA_8888 }; + return CreateHdiTestLayer(info); +} + +int32_t HdiTestDisplay::RefreshLayersCompType() +{ + uint32_t num; + int ret; + std::vector layers; + std::vector types; + ret = GetDeviceFuncs().GetDisplayCompChange(mId, &num, nullptr, nullptr); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("GetDisplayCompChange get number failed")); + DISPLAY_TEST_LOGD("the change numbers %d", num); + layers.resize(num); + types.resize(num); + ret = GetDeviceFuncs().GetDisplayCompChange(mId, &num, layers.data(), types.data()); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("GetDisplayCompChange get layers and types failed")); + for (uint32_t i = 0; i < layers.size(); i++) { + DISPLAY_TEST_LOGD(" the layer id %d ", layers[i]); + std::shared_ptr layer = GetLayerFromId(layers[i]); + layer->SetCompType(static_cast(types[i])); + } + return DISPLAY_SUCCESS; +} + +int32_t HdiTestDisplay::GetLayersReleaseFence() +{ + uint32_t num; + int ret; + std::vector layers; + std::vector fences; + + ret = HdiTestDevice::GetInstance().GetDeviceFuncs().GetDisplayReleaseFence(mId, &num, nullptr, nullptr); + DISPLAY_TEST_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("GetDisplayReleaseFence failed")); + DISPLAY_TEST_CHK_RETURN((num == 0), DISPLAY_SUCCESS, DISPLAY_TEST_LOGE("has no layers fence data")); + layers.resize(num); + fences.resize(num); + ret = HdiTestDevice::GetInstance().GetDeviceFuncs().GetDisplayReleaseFence(mId, &num, layers.data(), fences.data()); + DISPLAY_TEST_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("GetDisplayReleaseFence get data failed")); + for (uint32_t i = 0; i < layers.size(); i++) { + DISPLAY_TEST_LOGD(" the layer id %d ", layers[i]); + std::shared_ptr layer = GetLayerFromId(layers[i]); + layer->SetReleaseFence(fences[i]); + } + return DISPLAY_SUCCESS; +} + +int32_t HdiTestDisplay::PrepareDisplayLayers() +{ + int ret; + mNeedFlushFb = false; + DISPLAY_TEST_LOGD("id : %d layer size %d", mId, mLayerMaps.size()); + for (const auto &layerMap : mLayerMaps) { + ret = layerMap.second->PreparePresent(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("layer %d Prepare failed", layerMap.first)); + } + ret = GetDeviceFuncs().PrepareDisplayLayers(mId, &mNeedFlushFb); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("PrepareDisplayLayers failed display id %d", mId)); + ret = RefreshLayersCompType(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("RefreshLayersCompType failed")); + return DISPLAY_SUCCESS; +} + +int32_t HdiTestDisplay::Commit() +{ + int32_t fenceFd; + int ret; + HdiGrallocBuffer *buffer = nullptr; + if (mNeedFlushFb) { + ret = mClientLayer->SwapFrontToBackQ(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("has no front buffer display id %d", mId)); + + buffer = mClientLayer->GetBackBuffer(); + DISPLAY_TEST_CHK_RETURN((buffer == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get back buffer")); + BufferHandle *handle = buffer->Get(); + DISPLAY_TEST_CHK_RETURN((handle == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("BufferHandle is null")); + ClearColor(*handle, 0); // need clear the fb first + ret = HdiTestDevice::GetInstance().GetDeviceFuncs().SetDisplayClientBuffer(mId, handle, -1); + mCurrentFb = handle; + DISPLAY_TEST_LOGD("client fb phyaddr %" PRIx64 " vritual addr %p", handle->phyAddr, handle->virAddr); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("set client buffer handle failed")); + } + + ret = HdiTestDevice::GetInstance().GetDeviceFuncs().Commit(mId, &fenceFd); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("commit failed display id %d", mId)); + ret = GetLayersReleaseFence(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("GetLayersReleaseFence failed %d", mId)); + buffer->SetReleaseFence(fenceFd); + if (mNeedFlushFb) { + ret = mClientLayer->SwapBackToFrontQ(); + } + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("has no back buffer display id %d", mId)); + return DISPLAY_SUCCESS; +} + +int32_t HdiTestDisplay::RegDisplayVBlankCallback(VBlankCallback cb, void *data) +{ + int ret = HdiTestDevice::GetInstance().GetDeviceFuncs().RegDisplayVBlankCallback(mId, cb, data); + return ret; +} + +int32_t HdiTestDisplay::SetDisplayVsyncEnabled(bool enabled) +{ + int ret = HdiTestDevice::GetInstance().GetDeviceFuncs().SetDisplayVsyncEnabled(mId, enabled); + return ret; +} + +std::shared_ptr HdiTestDisplay::GetLayerFromId(uint32_t id) +{ + auto layerMap = mLayerMaps.find(id); + DISPLAY_TEST_CHK_RETURN((layerMap == mLayerMaps.end()), nullptr, + DISPLAY_TEST_LOGE("can not find the layer id : %d", id)); + return layerMap->second; +} + +void HdiTestDisplay::Clear() +{ + DISPLAY_TEST_LOGD(); + for (auto const & iter : mLayerMaps) { + uint32_t layerId = iter.first; + HdiTestDevice::GetInstance().GetLayerFuncs().CloseLayer(mId, layerId); + } + mLayerMaps.clear(); + DISPLAY_TEST_LOGD("mLayerMaps size %u", mLayerMaps.size()); +} +} // OHOS +} // HDI +} // DISPLAY +} // TEST diff --git a/hardware/display/test/display_device/hdi_test_display.h b/hardware/display/test/display_device/hdi_test_display.h new file mode 100644 index 0000000000000000000000000000000000000000..e176f4b710a659e261812e3fe31b8556e3fdfed3 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_display.h @@ -0,0 +1,83 @@ +/* + * 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_TEST_DISPLAY_H +#define HDI_TEST_DISPLAY_H +#include +#include "display_device.h" +#include "display_gralloc.h" +#include "display_type.h" +#include "display_test.h" +#include "hdi_test_device.h" +#include "hdi_test_device_common.h" +#include "hdi_test_layer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +class HdiTestDisplay { +public: + HdiTestDisplay(uint32_t id, DeviceFuncs &deviceFunc); + virtual ~HdiTestDisplay() {}; + int32_t Init(); + int32_t GetModeInfoFromId(int32_t id, DisplayModeInfo &modeInfo); + std::shared_ptr CreateHdiTestLayer(LayerInfo &info); + std::shared_ptr CreateHdiTestLayer(uint32_t w, uint32_t h); + int32_t Commit(); + int32_t PrepareDisplayLayers(); + DisplayModeInfo GetCurrentMode() const + { + return mCurrentMode; + } + int32_t RegDisplayVBlankCallback(VBlankCallback cb, void *data); + int32_t SetDisplayVsyncEnabled(bool enabled); + std::shared_ptr GetLayerFromId(uint32_t id); + std::unordered_map> &GetLayers() + { + return mLayerMaps; + } + void Clear(); + BufferHandle *SnapShot() + { + DISPLAY_TEST_LOGD("client fb phyaddr %" PRIx64 " virtual addr %p", mCurrentFb->phyAddr, mCurrentFb->virAddr); + return mCurrentFb; + } + +private: + const DeviceFuncs &GetDeviceFuncs() const + { + return mDeviceFunc; + } + int32_t RefreshLayersCompType(); + int32_t GetLayersReleaseFence(); + uint32_t mActiveModeId = 0; + DisplayModeInfo mCurrentMode = { 0 }; + uint32_t mId; + DeviceFuncs mDeviceFunc = { 0 }; + + DisplayCapability mCap; + std::vector mModes; + std::unordered_map> mLayerMaps; + std::unique_ptr mClientLayer; + BufferHandle *mCurrentFb; + bool mNeedFlushFb = false; +}; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + +#endif // HDI_TEST_DISPLAY_H diff --git a/hardware/display/test/display_device/hdi_test_layer.cpp b/hardware/display/test/display_device/hdi_test_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f62ad127d5bc2afdeb9b9f2e0aa1926a2a7c4d00 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_layer.cpp @@ -0,0 +1,230 @@ +/* + * 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_test_layer.h" +#include "hdi_test_device.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +HdiGrallocBuffer::HdiGrallocBuffer(uint32_t w, uint32_t h, PixelFormat fmt) +{ + GrallocFuncs &gralloc = HdiTestDevice::GetInstance().GetGrallocFuncs(); + AllocInfo info = { 0 }; + info.width = w; + info.height = h; + info.usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE; + info.format = fmt; + + int ret = gralloc.AllocMem(&info, &mBufferHandle); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("can not alloc memory"); + } + void *vaddr = gralloc.Mmap(mBufferHandle); + if (vaddr == nullptr) { + DISPLAY_TEST_LOGE("mmap failed"); + } +} + +HdiGrallocBuffer::~HdiGrallocBuffer() +{ + int ret; + + if (mBufferHandle != nullptr) { + GrallocFuncs &gralloc = HdiTestDevice::GetInstance().GetGrallocFuncs(); + if (mBufferHandle->virAddr != nullptr) { + ret = gralloc.Unmap(mBufferHandle); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("can not ummap buffer handle"); + } + } + gralloc.FreeMem(mBufferHandle); + mBufferHandle = nullptr; + } + if (mReleaseFence != -1) { + close(mReleaseFence); + } +} + +void HdiGrallocBuffer::SetReleaseFence(int fd) +{ + DISPLAY_TEST_LOGD("the fd is %d", fd); + if (mReleaseFence != -1) { + close(mReleaseFence); + mReleaseFence = -1; + } + mReleaseFence = fd; +} + +void HdiGrallocBuffer::SetAcquirceFence(int fd) +{ + DISPLAY_TEST_LOGD("the fd is %d", fd); + mAcquireFence = fd; +} + +HdiGrallocBuffer *HdiTestLayer::AcquireBackBuffer() +{ + if (!mBackBuffers.empty()) { + if (mCurrentBuffer != nullptr) { + mFrontBuffers.emplace(std::move(mCurrentBuffer)); + } + mCurrentBuffer = std::move(mBackBuffers.front()); + mBackBuffers.pop(); + } + return mCurrentBuffer.get(); +} + +HdiGrallocBuffer *HdiTestLayer::GetFrontBuffer() +{ + HdiGrallocBuffer *buffer = nullptr; + if (!mFrontBuffers.empty()) { + buffer = mFrontBuffers.front().get(); + } + return buffer; +} + +HdiGrallocBuffer *HdiTestLayer::GetBackBuffer() +{ + HdiGrallocBuffer *buffer = nullptr; + if (!mBackBuffers.empty()) { + buffer = mBackBuffers.front().get(); + } + return buffer; +} + +HdiTestLayer::HdiTestLayer(LayerInfo &info, uint32_t id, uint32_t displayId) + : mId(id), mDisplayID(displayId), mLayerInfo(info) +{} + +int32_t HdiTestLayer::Init() +{ + // init the font queue + DISPLAY_TEST_LOGD(); + const int maxBufferCount = 3; + for (int i = 0; i < maxBufferCount; i++) { + std::unique_ptr buffer = + std::make_unique(mLayerInfo.width, mLayerInfo.height, mLayerInfo.pixFormat); + DISPLAY_TEST_CHK_RETURN((buffer->Get() == nullptr), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("buffer handle is null")); + mFrontBuffers.emplace(std::move(buffer)); + } + mDisplayRect.w = mLayerInfo.width; + mDisplayRect.h = mLayerInfo.height; + mCropRect = mDisplayRect; + return DISPLAY_SUCCESS; +} + + +int32_t HdiTestLayer::SwapFrontToBackQ() +{ + DISPLAY_TEST_CHK_RETURN((mFrontBuffers.empty()), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("the font buffer is empty")); + mBackBuffers.emplace(std::move(mFrontBuffers.front())); + mFrontBuffers.pop(); + return DISPLAY_SUCCESS; +} + +int32_t HdiTestLayer::SwapBackToFrontQ() +{ + DISPLAY_TEST_CHK_RETURN((mBackBuffers.empty()), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("the font buffer is empty")); + mFrontBuffers.emplace(std::move(mBackBuffers.front())); + mBackBuffers.pop(); + return DISPLAY_SUCCESS; +} + +void HdiTestLayer::SetLayerSize(IRect &rect) +{ + DISPLAY_TEST_LOGD("x : %d y : %d w : %d h : %d", rect.x, rect.y, rect.w, rect.h); + mDisplayRect = rect; +} + +void HdiTestLayer::SetLayerCrop(IRect &rect) +{ + DISPLAY_TEST_LOGD("x : %d y : %d w : %d h : %d", rect.x, rect.y, rect.w, rect.h); + mCropRect = rect; +} + +int32_t HdiTestLayer::PreparePresent() +{ + int ret; + DISPLAY_TEST_LOGD(); + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerSize(mDisplayID, mId, &mDisplayRect); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set display rect failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerCrop(mDisplayID, mId, &mCropRect); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set display crop failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerZorder(mDisplayID, mId, mZorder); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set display crop failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerCompositionType(mDisplayID, mId, mCompType); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("set display composition type failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetTransformMode(mDisplayID, mId, mTransform); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set transform mode failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerAlpha(mDisplayID, mId, &mAlpha); + HdiGrallocBuffer *buffer = AcquireBackBuffer(); + DISPLAY_TEST_CHK_RETURN((buffer == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("can not get back buffer")); + + BufferHandle *handle = buffer->Get(); + DISPLAY_TEST_CHK_RETURN((handle == nullptr), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("BufferHandle is null")); + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerBuffer(mDisplayID, mId, handle, -1); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set buffer handle failed")); + + ret = HdiTestDevice::GetInstance().GetLayerFuncs().SetLayerBlendType(mDisplayID, mId, mBlendType); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_TEST_LOGE("set blend type failed")); + return DISPLAY_SUCCESS; +} + +void HdiTestLayer::SetZorder(uint32_t zorder) +{ + DISPLAY_TEST_LOGD("the zorder is %d", zorder); + mZorder = zorder; +} + +void HdiTestLayer::SetCompType(CompositionType type) +{ + DISPLAY_TEST_LOGD("layer id %d ,the type is : %d", mId, type); + mCompType = type; +} + +void HdiTestLayer::SetTransform(TransformType transform) +{ + mTransform = transform; +} + +void HdiTestLayer::SetAlpha(LayerAlpha alpha) +{ + DISPLAY_TEST_LOGD(); + mAlpha = alpha; +} + +void HdiTestLayer::SetBlendType(BlendType type) +{ + DISPLAY_TEST_LOGD("type %d", type); + mBlendType = type; +} + +void HdiTestLayer::SetReleaseFence(int fd) +{ + DISPLAY_TEST_LOGD("layer id %d , fd %d", mId, fd); +} + +HdiTestLayer::~HdiTestLayer() {} +} // OHOS +} // HDI +} // DISPLAY +} // TEST diff --git a/hardware/display/test/display_device/hdi_test_layer.h b/hardware/display/test/display_device/hdi_test_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..918cb369753c2c26f17851792a130aee8ce6f660 --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_layer.h @@ -0,0 +1,105 @@ +/* + * 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_TEST_LAYER_H +#define HDI_TEST_LAYER_H +#include +#include "display_gralloc.h" +#include "display_layer.h" +#include "hdi_test_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +class HdiGrallocBuffer { +public: + HdiGrallocBuffer(uint32_t w, uint32_t h, PixelFormat fmt); + ~HdiGrallocBuffer(); + BufferHandle *Get() const + { + return mBufferHandle; + } + void SetReleaseFence(int fd); + void SetAcquirceFence(int fd); + int GetAcquireFence() const + { + return mAcquireFence; + } + int GetReleaseFence() const + { + return mReleaseFence; + } + +private: + BufferHandle *mBufferHandle = nullptr; + int mAcquireFence = -1; + int mReleaseFence = -1; +}; + +class HdiTestLayer { +public: + HdiTestLayer(LayerInfo &info, uint32_t id, uint32_t displayId); + virtual ~HdiTestLayer(); + int32_t Init(); + int32_t PreparePresent(); + + uint32_t GetId() const + { + return mId; + } + CompositionType GetCompType() const + { + return mCompType; + } + + HdiGrallocBuffer *GetFrontBuffer(); + HdiGrallocBuffer *GetBackBuffer(); + HdiGrallocBuffer *AcquireBackBuffer(); + + int32_t SwapFrontToBackQ(); + int32_t SwapBackToFrontQ(); + + void SetLayerSize(IRect &rect); + void SetLayerCrop(IRect &rect); + void SetZorder(uint32_t zorder); + void SetCompType(CompositionType type); + void SetReleaseFence(int fd); + void SetAlpha(LayerAlpha alpha); + void SetBlendType(BlendType type); + void SetTransform(TransformType transform); + +private: + uint32_t mId; + uint32_t mDisplayID; + std::queue> mFrontBuffers; + std::queue> mBackBuffers; + LayerInfo mLayerInfo = { 0 }; + + CompositionType mCompType = COMPOSITION_CLIENT; + IRect mDisplayRect = { 0 }; + IRect mCropRect = { 0 }; + uint32_t mZorder = 0; + LayerAlpha mAlpha = { 0 }; + BlendType mBlendType = BLEND_SRC; + std::unique_ptr mCurrentBuffer; + TransformType mTransform = ROTATE_NONE; +}; +} // OHOS +} // HDI +} // DISPLAY +} // TEST + +#endif // HDI_TEST_LAYER_H \ No newline at end of file diff --git a/hardware/display/test/display_device/hdi_test_render_utils.cpp b/hardware/display/test/display_device/hdi_test_render_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6c3281f5328434e23f0a1cf7aaa4c4a209259cb --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_render_utils.cpp @@ -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. + */ + +#include "display_test.h" +#include "buffer_handle.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +// constexpr uint8_t BITS_PER_BYTE = 8; +void SetUint32(uint32_t &dst, uint32_t value) +{ + uint8_t *data = reinterpret_cast(&dst); + for (uint8_t i = 0; i < sizeof(uint32_t); i++) { + *(data + i) = (value >> ((sizeof(uint32_t) - i - 1) * BITS_PER_BYTE)) & 0xff; + } +} + +void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + constexpr int32_t pixelBytes = 4; + constexpr int32_t bpp = 32; + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((bpp <= 0), + DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + SetUint32(*pixel, color); +} + +void ClearColor(const BufferHandle &handle, uint32_t color) +{ + for (int32_t x = 0; x < handle.width; x++) { + for (int32_t y = 0; y < handle.height; y++) { + SetPixel(handle, x, y, color); + } + } +} +} // OHOS +} // HDI +} // DISPLAY +} // TEST diff --git a/hardware/display/test/display_device/hdi_test_render_utils.h b/hardware/display/test/display_device/hdi_test_render_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..f08ee50d08784f2177b2b50fc535ab131784caab --- /dev/null +++ b/hardware/display/test/display_device/hdi_test_render_utils.h @@ -0,0 +1,33 @@ +/* + * 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_TEST_RENDER_UTILS_H +#define HDI_TEST_RENDER_UTILS_H +#include "display_test.h" +#include "hdi_test_device_common.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +namespace TEST { +void SetUint32(uint32_t &dst, uint32_t value); +void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color); +void ClearColor(const BufferHandle &handle, uint32_t color); +} // OHOS +} // HDI +} // DISPLAY +} // TEST + + +#endif // HDI_TEST_RENDER_UTILS_H diff --git a/hardware/display/test/display_gfx/display_gfx_test.cpp b/hardware/display/test/display_gfx/display_gfx_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8cdcf8ab9944c525bb6f6248e7f282ba063c53be --- /dev/null +++ b/hardware/display/test/display_gfx/display_gfx_test.cpp @@ -0,0 +1,499 @@ +/* + * 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_gfx_test.h" +#include +#include +#include "display_gfx.h" +#include "display_gralloc.h" +#include "display_test.h" +#include "soft_blit.h" + +namespace { +const uint32_t DEFAULT_COLOR = 0x11225588; +const uint32_t CHECK_COLOR = 0x22336699; +const uint32_t ROTATE_DEFULT_X = 200; +const uint32_t ROTATE_DEFULT_Y = 100; + +static void SourceSurfaceInit(ISurface &surface, const BufferHandle &buffer) +{ + surface.width = buffer.width; + surface.height = buffer.height; + surface.phyAddr = buffer.phyAddr; + surface.enColorFmt = (PixelFormat)buffer.format; + surface.stride = buffer.stride; + surface.bAlphaExt1555 = true; + surface.bAlphaMax255 = true; + surface.alpha0 = 0XFF; + surface.alpha1 = 0XFF; +} + +static int32_t GetPixelFormatBpp(PixelFormat format) +{ + const int32_t bppRgba8888 = 32; + switch (format) { + case PIXEL_FMT_RGBA_8888: + return bppRgba8888; + case PIXEL_FMT_BGRA_8888: + return bppRgba8888; + default: + return -1; + } +} + +static uint32_t GetPixelValue(const BufferHandle &handle, int x, int y) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), 0, + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + return *pixel; +} + +static uint32_t CheckPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + if (*pixel != color) { + DISPLAY_TEST_LOGD("the pixel color not match vAddr:%p position:%d pixel:%x color:%x", handle.virAddr, position, + *pixel, color); + DISPLAY_TEST_LOGD("x:%d y:%d width:%d", x, y, handle.width); + } + return *pixel; +} + +static void SetPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((bpp <= 0), + DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height), + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + *pixel = color; +} + +static void CalculRotateSize(TransformType angle, int &width, int &height) +{ + switch (angle) { + case ROTATE_NONE: + break; + case ROTATE_180: + break; + case ROTATE_90: + case ROTATE_270: + width = width ^ height; + height = width ^ height; + width = width ^ height; + break; + default: + break; + } +} + +static BufferHandle *AllocateTestMemory(const GrallocFuncs &grallocFuncs, const AllocInfo &info, uint32_t color) +{ + int32_t ret; + BufferHandle *buffer = nullptr; + ret = grallocFuncs.AllocMem(&info, &buffer); + if (ret != DISPLAY_SUCCESS) { + return nullptr; + } + + void *vAddr = grallocFuncs.Mmap(buffer); + if (vAddr == nullptr) { + return nullptr; + } + + DISPLAY_TEST_LOGD(" vAddr %p buffer->size %d", vAddr, buffer->size); + for (int x = 0; x < buffer->width; x++) { + for (int y = 0; y < buffer->height; y++) { + SetPixel(*buffer, x, y, color); + } + } + + ret = grallocFuncs.FlushCache(buffer); + if (ret != DISPLAY_SUCCESS) { + return nullptr; + } + return buffer; +} + +static BufferHandle *AllocateRotateTestMemory(const GrallocFuncs &grallocFuncs, const AllocInfo &info, int position_x, + int position_y) +{ + BufferHandle *buffer = nullptr; + int32_t ret = grallocFuncs.AllocMem(&info, &buffer); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("RotateTest allocMem failed!"); + return nullptr; + } + + void *vAddr = grallocFuncs.Mmap(buffer); + if (vAddr == nullptr) { + DISPLAY_TEST_LOGE("RotateTest mmap failed!"); + grallocFuncs.FreeMem(buffer); + return nullptr; + } + + DISPLAY_TEST_LOGD(" vAddr %p buffer->size %d", vAddr, buffer->size); + for (int x = 0; x < buffer->width; x++) { + for (int y = 0; y < buffer->height; y++) { + if (position_x == x && position_y == y) { + SetPixel(*buffer, x, y, CHECK_COLOR); + } else { + SetPixel(*buffer, x, y, DEFAULT_COLOR); + } + } + } + ret = grallocFuncs.FlushCache(buffer); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("RotateTest FlushCache failed!"); + grallocFuncs.Unmap(buffer); + grallocFuncs.FreeMem(buffer); + return nullptr; + } + return buffer; +} + +static void ReleaseTestMemory(const GrallocFuncs &grallocFuncs, BufferHandle &bufferHdl) +{ + grallocFuncs.Unmap((&bufferHdl)); + grallocFuncs.FreeMem(&bufferHdl); +} + +void GfxTestBase::TestSetUp() +{ + int32_t ret = GrallocInitialize(&mGrallocFuncs); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gralloc initialize failure"); + ASSERT_TRUE(0)); + ret = GfxInitialize(&mGfxFuncs); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gfx initialize failure"); + ASSERT_TRUE(0)); + ret = mGfxFuncs->InitGfx(); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gfx intgfx failure"); + ASSERT_TRUE(0)); + InitTestBuffer(); +} + +void GfxTestBase::TestTearDown() +{ + int32_t ret; + DeInitTestBuffer(); + ret = mGfxFuncs->DeinitGfx(); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gfx intgfx failure"); + ASSERT_TRUE(0)); + ret = GrallocUninitialize(mGrallocFuncs); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("gralloc uninitialize failure"); + ASSERT_TRUE(0); + } + ret = GfxUninitialize(mGfxFuncs); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("gfx uninitialize failure"); + ASSERT_TRUE(0); + } +} + +void GfxTestBase::InitTestBuffer() +{ + const int testWidth = 1080; + const int testHeight = 1920; + const uint32_t initSrcRgba = 0x555555ee; // RGBA + const uint32_t initDstRgba = 0xaaaaaa22; // RGBA + + mSrcRect = { 0, 0, testWidth, testHeight }; + mDstRect = { 0, 0, testWidth, testHeight }; + // allocate a 1080p memory. + AllocInfo allocInfo = { + .width = testWidth, // 1080p width memory + .height = testHeight, // 1080p height memory + .usage = (uint64_t)(HBM_USE_CPU_WRITE | HBM_USE_CPU_READ | HBM_USE_MEM_DMA), + .format = PIXEL_FMT_RGBA_8888 + }; + + mSrcBuffer = AllocateTestMemory(*mGrallocFuncs, allocInfo, initSrcRgba); + mDstBuffer = AllocateTestMemory(*mGrallocFuncs, allocInfo, initDstRgba); + mSoftBlendBuffer = AllocateTestMemory(*mGrallocFuncs, allocInfo, initDstRgba); + if ((mSrcBuffer == nullptr) || (mDstBuffer == nullptr) || (mSoftBlendBuffer == nullptr)) { + DISPLAY_TEST_LOGE("init memory failed"); + ASSERT_TRUE(0); + } +} + +void GfxTestBase::DeInitTestBuffer() +{ + if (mSrcBuffer != nullptr) { + ReleaseTestMemory(*mGrallocFuncs, *mSrcBuffer); + } + if (mDstBuffer != nullptr) { + ReleaseTestMemory(*mGrallocFuncs, *mDstBuffer); + } + if (mSoftBlendBuffer != nullptr) { + ReleaseTestMemory(*mGrallocFuncs, *mSoftBlendBuffer); + } +} + +void GfxBlendTypeTest::SetUp() +{ + TestSetUp(); +} + +void GfxBlendTypeTest::TearDown() +{ + TestTearDown(); +} + +int32_t GfxBlendTypeTest::GfxBlitBlendTypeTest(BlendType type) +{ + int ret; + GfxOpt opt = { 0 }; + opt.blendType = type; + opt.enPixelAlpha = true; + ret = GfxBlitTest(*mGfxFuncs, *mGrallocFuncs, opt); + return ret; +} + +int32_t GfxBlendTypeTest::GfxBlitTest(const GfxFuncs &gfxFuncs, const GrallocFuncs &grallocFuncs, GfxOpt &opt) +{ + int32_t ret; + ISurface dstSurface = { 0 }; + ISurface srcSurface = { 0 }; + + SourceSurfaceInit(srcSurface, *mSrcBuffer); + SourceSurfaceInit(dstSurface, *mDstBuffer); + SoftBlit softBlit(*mSrcBuffer, mSrcRect, *mSoftBlendBuffer, mDstRect, opt.blendType); + + auto blitBegin = std::chrono::steady_clock::now(); + ret = gfxFuncs.Blit(&srcSurface, &mSrcRect, &dstSurface, &mDstRect, &opt); + auto blitEnd = std::chrono::steady_clock::now(); + double durationBlit = std::chrono::duration(blitEnd - blitBegin).count(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("Blit failed ret:%d", ret)); + auto syncBegin = std::chrono::steady_clock::now(); + ret = grallocFuncs.InvalidateCache(mDstBuffer); + auto syncEnd = std::chrono::steady_clock::now(); + double durationSync = std::chrono::duration(syncEnd - syncBegin).count(); + DISPLAY_TEST_LOGD("gfx blit cost %lf ms, sync cost %lf ms", durationBlit, durationSync); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, + DISPLAY_TEST_LOGE("gralloc buffer flush cache failed ret:%d", ret)); + if (!softBlit.RunAndCheck(*mDstBuffer)) { + ret = DISPLAY_FAILURE; + } + return ret; +} + +void GfxFillTest ::SetUp() +{ + TestSetUp(); +} + +void GfxFillTest::TearDown() +{ + TestTearDown(); +} + +int32_t GfxFillTest::FillRectTest(uint32_t testColor) +{ + int32_t ret; + ISurface dstSurface = { 0 }; + GfxOpt opt = { 0 }; + SourceSurfaceInit(dstSurface, *mDstBuffer); + ret = mGfxFuncs->InitGfx(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("InitGfx failed ret:%d", ret)); + + ret = mGfxFuncs->FillRect(&dstSurface, &mDstRect, testColor, &opt); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("FillRect failed ret:%d", ret)); + + ret = mGfxFuncs->DeinitGfx(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("DeinitGfx failed ret:%d", ret)); + + ret = mGrallocFuncs->InvalidateCache(mDstBuffer); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, + DISPLAY_TEST_LOGE("gralloc buffer flush cache failed ret:%d", ret)); + // check the buffer + for (int x = 0; x < mDstBuffer->width; x++) { + for (int y = 0; y < mDstBuffer->height; y++) { + uint32_t pixel = CheckPixel(*mDstBuffer, x, y, testColor); + if (pixel != testColor) { + DISPLAY_TEST_LOGE("the color check failed pixel x: %d y:%d color: 0x%x", x, y, pixel); + return DISPLAY_FAILURE; + } + } + } + return ret; +} + +void GfxRotateTest::SetUp() +{ + int32_t ret = GrallocInitialize(&mGrallocFuncs); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gralloc initialize failure"); + ASSERT_TRUE(0)); + ret = GfxInitialize(&mGfxFuncs); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gfx initialize failure"); + ASSERT_TRUE(0)); + ret = mGfxFuncs->InitGfx(); + DISPLAY_TEST_CHK_RETURN_NOT_VALUE((ret != DISPLAY_SUCCESS), DISPLAY_TEST_LOGE("gfx intgfx failure"); + ASSERT_TRUE(0)); + const int width = 1920; + const int height = 1080; + + mSrcRect = { 0, 0, width, height }; + AllocInfo srcAllocInfo = { + .width = width, + .height = height, + .usage = (uint64_t)(HBM_USE_CPU_WRITE | HBM_USE_CPU_READ | HBM_USE_MEM_DMA), + .format = PIXEL_FMT_BGRA_8888 + }; + + mSrcBuffer = AllocateRotateTestMemory(*mGrallocFuncs, srcAllocInfo, ROTATE_DEFULT_X, ROTATE_DEFULT_Y); +} + +void GfxRotateTest::TearDown() +{ + TestTearDown(); +} + +int32_t GfxRotateTest::RotateTest(RotateParam param) +{ + int32_t ret; + ISurface dstSurface = { 0 }; + ISurface srcSurface = { 0 }; + GfxOpt opt = { 0 }; + opt.rotateType = param.transformType; + opt.blendType = param.blendType; + int width = 1920; + int height = 1080; + CalculRotateSize(param.transformType, width, height); + mDstRect = { 0, 0, width, height }; + AllocInfo dstAllocInfo = { + .width = width, + .height = height, + .usage = HBM_USE_CPU_WRITE | HBM_USE_CPU_READ | HBM_USE_MEM_DMA, + .format = PIXEL_FMT_BGRA_8888 + }; + mDstBuffer = AllocateRotateTestMemory(*mGrallocFuncs, dstAllocInfo, -1, -1); + + SourceSurfaceInit(srcSurface, *mSrcBuffer); + SourceSurfaceInit(dstSurface, *mDstBuffer); + ret = mGfxFuncs->InitGfx(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("InitGfx failed ret:%d", ret)); + ret = mGfxFuncs->Blit(&srcSurface, &mSrcRect, &dstSurface, &mDstRect, &opt); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("RotateTest failed ret:%d", ret)); + ret = mGfxFuncs->DeinitGfx(); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_TEST_LOGE("DeinitGfx failed ret:%d", ret)); + + ret = mGrallocFuncs->InvalidateCache(mDstBuffer); + DISPLAY_TEST_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, + DISPLAY_TEST_LOGE("gralloc buffer flush cache failed ret:%d", ret)); + // check the buffer + ret = DISPLAY_FAILURE; + for (int x = 0; x < mDstBuffer->width; x++) { + for (int y = 0; y < mDstBuffer->height; y++) { + uint32_t pixel = GetPixelValue(*mDstBuffer, x, y); + if ((pixel == CHECK_COLOR) && (x == param.expectX) && (y == param.expectY)) { + DISPLAY_TEST_LOGE("angle = %d, current position = %d,%d", param.transformType, x, y); + ret = DISPLAY_SUCCESS; + } + } + } + return ret; +} + +TEST_P(GfxBlendTypeTest, BlendType) +{ + BlendType type = GetParam(); + int ret = GfxBlitBlendTypeTest(type); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); +} +TEST_P(GfxFillTest, FillRect) +{ + uint32_t testColor = GetParam(); + int ret = FillRectTest(testColor); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); +} +TEST_P(GfxRotateTest, Blit) +{ + RotateParam rotateParams = GetParam(); + int ret = RotateTest(rotateParams); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); +} +// BLEND_AKD BLEND_AKS has no function to test it +const BlendType BLEND_TYPES[] = { + BLEND_NONE, + BLEND_CLEAR, /* < CLEAR blending {0, 0} */ + BLEND_SRC, /* < SRC blending {Sa, Sc} */ + BLEND_SRCOVER, /* < SRC_OVER blending {Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc} */ + BLEND_DSTOVER, /* < DST_OVER blending {Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc} */ + 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 */ +}; +const uint32_t FILL_COLORS[] = { + 0, + 0xffffffff, + 0xaaaaaaaa, +}; + +const RotateParam TEST_ROTATE_PARAMS[] = { + {ROTATE_NONE, BLEND_SRC, 200, 100}, + {ROTATE_90, BLEND_SRC, 979, 200}, + {ROTATE_180, BLEND_SRC, 1719, 979}, + {ROTATE_270, BLEND_SRC, 100, 1719}, +}; + +INSTANTIATE_TEST_CASE_P(GfxTest, GfxBlendTypeTest, ::testing::ValuesIn(BLEND_TYPES)); +INSTANTIATE_TEST_CASE_P(GfxTest, GfxFillTest, ::testing::ValuesIn(FILL_COLORS)); +INSTANTIATE_TEST_CASE_P(GfxTest, GfxRotateTest, ::testing::ValuesIn(TEST_ROTATE_PARAMS)); +} diff --git a/hardware/display/test/display_gfx/display_gfx_test.h b/hardware/display/test/display_gfx/display_gfx_test.h new file mode 100644 index 0000000000000000000000000000000000000000..20fbe992b74bfe0d84b1bf2e2ebc98f3adc8c716 --- /dev/null +++ b/hardware/display/test/display_gfx/display_gfx_test.h @@ -0,0 +1,73 @@ +/* + * 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_GFX_TEST_H +#define DISPLAY_GFX_TEST_H +#include "gtest/gtest.h" +#include "display_gfx.h" +#include "display_gralloc.h" +#include "display_type.h" +#include "display_test.h" + +namespace { +class GfxTestBase { +public: + virtual ~GfxTestBase() {}; + +protected: + void TestSetUp(); + void TestTearDown(); + void DeInitTestBuffer(); + void InitTestBuffer(); + IRect mSrcRect = { 0 }; + IRect mDstRect = { 0 }; + BufferHandle *mSrcBuffer = nullptr; + BufferHandle *mDstBuffer = nullptr; + BufferHandle *mSoftBlendBuffer = nullptr; + GrallocFuncs *mGrallocFuncs = nullptr; + GfxFuncs *mGfxFuncs = nullptr; +}; + +struct RotateParam { + TransformType transformType; + BlendType blendType; + int expectX; + int expectY; +}; + +class GfxFillTest : public ::testing::TestWithParam, public GfxTestBase { +protected: + void SetUp(); + void TearDown(); + int32_t FillRectTest(uint32_t testColor); +}; + +class GfxRotateTest : public ::testing::TestWithParam, public GfxTestBase { +protected: + void SetUp(); + void TearDown(); + int32_t RotateTest(RotateParam param); +}; + +class GfxBlendTypeTest : public ::testing::TestWithParam, public GfxTestBase { +protected: + void SetUp(); + void TearDown(); + int32_t GfxBlitBlendTypeTest(BlendType type); + int32_t GfxBlitTest(const GfxFuncs &gfxFuncs, const GrallocFuncs &grallocFuncs, GfxOpt &opt); +}; +} + +#endif // DISPLAY_GFX_TEST_H diff --git a/hardware/display/test/display_gfx/soft_blit.cpp b/hardware/display/test/display_gfx/soft_blit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2da1f190e92bf422c14b1979e350d9628e614187 --- /dev/null +++ b/hardware/display/test/display_gfx/soft_blit.cpp @@ -0,0 +1,331 @@ +/* + * 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 "soft_blit.h" +#include +#include +#include +#include "display_test.h" + +namespace { +const int MAX_FLOAT_TO_INT32 = 2147483520; +const int MIN_FLOAT_TO_INT32 = -2147483520; + +using BlendFunction = void (*)(ColorRGBAf &src, ColorRGBAf &dst); + +static inline uint32_t RgbaGetA(uint32_t color) +{ + return ((color >> 0) & 0xFF); +} + +static inline uint32_t RgbaGetR(uint32_t color) +{ + const uint32_t shift = 24; + const uint32_t mask = 0xFF; + return ((color >> shift) & mask); +} + +static inline uint32_t RgbaGetG(uint32_t color) +{ + const uint32_t shift = 16; + const uint32_t mask = 0xFF; + return ((color >> shift) & mask); +} + +static inline uint32_t RgbaGetB(uint32_t color) +{ + const uint32_t shift = 8; + const uint32_t mask = 0xFF; + return ((color >> shift) & mask); +} + +static constexpr inline uint32_t ColorSetARGB(uint8_t r, uint8_t g, uint8_t b, uint8_t a) +{ + const uint32_t shiftR = 24; + const uint32_t shiftG = 16; + const uint32_t shiftB = 8; + return (r << shiftR) | (g << shiftG) | (b << shiftB) | (a << 0); +} +// blend none +/* +fs: sa fd: 1.0-sa +pixel = (foreground x fs + background x fd) +*/ +static inline void BlendNone(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = src.mR * src.mA + dst.mR * (1 - src.mA); + dst.mG = src.mG * src.mA + dst.mG * (1 - src.mA); + dst.mB = src.mB * src.mA + dst.mB * (1 - src.mA); + dst.mA = src.mA * src.mA + dst.mA * (1 - src.mA); +} + +// blend clear +static inline void BlendClear(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mA = 0; + dst.mR = 0; + dst.mG = 0; + dst.mB = 0; +} + +// blend src +static inline void BlendSrc(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst = src; +} + +// blend src over +static inline void BlendSrcOver(ColorRGBAf &src, ColorRGBAf &dst) +{ + // the display_gfx has Premultiplied + src.mR *= src.mA; + src.mG *= src.mA; + src.mB *= src.mA; + + dst.mR = src.mR + (1 - src.mA) * dst.mR; + dst.mG = src.mG + (1 - src.mA) * dst.mG; + dst.mB = src.mB + (1 - src.mA) * dst.mB; + dst.mA = src.mA + (1 - src.mA) * dst.mA; +} + +// blend src in +static inline void BlendSrcIn(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = src.mR * dst.mA; + dst.mG = src.mG * dst.mA; + dst.mB = src.mB * dst.mA; + dst.mA = src.mA * dst.mA; +} + +// blend src out +static inline void BlendSrcOut(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = (1 - dst.mA) * src.mR; + dst.mG = (1 - dst.mA) * src.mG; + dst.mB = (1 - dst.mA) * src.mB; + dst.mA = (1 - dst.mA) * src.mA; +} + +// blend src Atop +static inline void BlendAtop(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = dst.mA * src.mR + (1 - src.mA) * dst.mR; + dst.mG = dst.mA * src.mG + (1 - src.mA) * dst.mG; + dst.mB = dst.mA * src.mB + (1 - src.mA) * dst.mB; + dst.mA = dst.mA; +} + +// blend dst +static inline void BlendDst(ColorRGBAf &src, ColorRGBAf &dst) {} + +// blend dst atop +static inline void BlendDstAtop(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = src.mA * dst.mR + (1 - dst.mA) * src.mR; + dst.mG = src.mA * dst.mG + (1 - dst.mA) * src.mG; + dst.mB = src.mA * dst.mB + (1 - dst.mA) * src.mB; + dst.mA = src.mA; +} + +// blend dst in +static inline void BlendDstIn(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = dst.mR * src.mA; + dst.mG = dst.mG * src.mA; + dst.mB = dst.mB * src.mA; + dst.mA = src.mA * dst.mA; +} + +// blend dst out +static inline void BlendDstOut(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = (1 - src.mA) * dst.mR; + dst.mG = (1 - src.mA) * dst.mG; + dst.mB = (1 - src.mA) * dst.mB; + dst.mA = (1 - src.mA) * dst.mA; +} + +// blend dst over +static inline void BlendDstOver(ColorRGBAf &src, ColorRGBAf &dst) +{ + // the display_gfx has Premultiplied + dst.mR *= dst.mA; + dst.mG *= dst.mA; + dst.mB *= dst.mA; + + dst.mR = dst.mR + (1 - dst.mA) * src.mR; + dst.mG = dst.mG + (1 - dst.mA) * src.mG; + dst.mB = dst.mB + (1 - dst.mA) * src.mB; + dst.mA = dst.mA + (1 - dst.mA) * src.mA; +} + +// blend xor +static inline void BlendXor(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = (1 - dst.mA) * src.mR + (1 - src.mA) * dst.mR; + dst.mG = (1 - dst.mA) * src.mG + (1 - src.mA) * dst.mG; + dst.mB = (1 - dst.mA) * src.mB + (1 - src.mA) * dst.mB; + dst.mA = (1 - dst.mA) * src.mA + (1 - src.mA) * dst.mA; +} + +// blend add +static inline void BlendAdd(ColorRGBAf &src, ColorRGBAf &dst) +{ + dst.mR = std::max(0.0f, std::min(src.mR + dst.mR, 1.0f)); + dst.mG = std::max(0.0f, std::min(src.mG + dst.mG, 1.0f)); + dst.mB = std::max(0.0f, std::min(src.mB + dst.mB, 1.0f)); + dst.mA = std::max(0.0f, std::min(src.mA + dst.mA, 1.0f)); +} + +static BlendFunction GetBlendFunc(BlendType type) +{ + std::unordered_map maps = { + { BLEND_CLEAR, BlendClear }, { BLEND_SRC, BlendSrc }, { BLEND_DST, BlendDst }, + { BLEND_SRCOVER, BlendSrcOver }, { BLEND_SRCIN, BlendSrcIn }, { BLEND_SRCOUT, BlendSrcOut }, + { BLEND_SRCATOP, BlendAtop }, { BLEND_DSTIN, BlendDstIn }, { BLEND_DSTOUT, BlendDstOut }, + { BLEND_DSTATOP, BlendDstAtop }, { BLEND_DSTOVER, BlendDstOver }, { BLEND_XOR, BlendXor }, + { BLEND_ADD, BlendAdd }, { BLEND_NONE, BlendNone }, + }; + if (maps.find(type) != maps.end()) { + return maps[type]; + } else { + DISPLAY_TEST_LOGE("has no function for blend type %d maps.size() %d", type, maps.size()); + return nullptr; + } +} + +static inline int32_t ConvertFloatToint(float f) +{ + if (f > MAX_FLOAT_TO_INT32) { + return MAX_FLOAT_TO_INT32; + } + if (f < MIN_FLOAT_TO_INT32) { + return MIN_FLOAT_TO_INT32; + } + return static_cast(f); +} + +static int32_t GetPixelFormatBpp(PixelFormat format) +{ + const int32_t bppRgba8888 = 32; + switch (format) { + case PIXEL_FMT_RGBA_8888: + return bppRgba8888; + default: + return -1; + } +} + +static uint32_t GetPixelRGBA32(const BufferHandle &handle, int x, int y) +{ + const int32_t pixelBytes = 4; + int32_t bpp = GetPixelFormatBpp((PixelFormat)handle.format); + DISPLAY_TEST_CHK_RETURN((bpp <= 0), 0, DISPLAY_TEST_LOGE("CheckPixel do not support format %d", handle.format)); + DISPLAY_TEST_CHK_RETURN((handle.virAddr == nullptr), 0, + DISPLAY_TEST_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_TEST_CHK_RETURN((x < 0 || x >= handle.width), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter x:%d width:%d", x, handle.width)); + DISPLAY_TEST_CHK_RETURN((y < 0 || y >= handle.height), 0, + DISPLAY_TEST_LOGE("CheckPixel invalid parameter y:%d height:%d", y, handle.height)); + + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_TEST_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + return *pixel; +} + +ColorRGBAf::ColorRGBAf(uint32_t r, uint32_t g, uint32_t b, uint32_t a) +{ + const float inv = 1.0f / 255.0f; + mA = a * inv; + mR = r * inv; + mG = g * inv; + mB = b * inv; +} + +bool ColorRGBA32::Compare(ColorRGBA32 &other) +{ + const int endure = 1; + if ((std::abs(other.mA - mA) > endure) || (std::abs(other.mR - mR) > endure) || + (std::abs(other.mG - mG) > endure) || (std::abs(other.mB - mB) > endure)) { + DISPLAY_TEST_LOGE("compare failed mC %x other.mC %x ", mC, other.mC); + return false; + } + return true; +} + +ColorRGBA32::ColorRGBA32(uint32_t pixel) +{ + mA = RgbaGetA(pixel); + mR = RgbaGetR(pixel); + mG = RgbaGetG(pixel); + mB = RgbaGetB(pixel); + mC = pixel; +} + +ColorRGBA32::ColorRGBA32(ColorRGBAf colorF) +{ + const uint8_t rgbMax = 255; + const float round = 0.5; + mA = static_cast(ConvertFloatToint(colorF.mA * rgbMax + round)); + mR = static_cast(ConvertFloatToint(colorF.mR * rgbMax + round)); + mG = static_cast(ConvertFloatToint(colorF.mG * rgbMax + round)); + mB = static_cast(ConvertFloatToint(colorF.mB * rgbMax + round)); + mC = ColorSetARGB(mR, mG, mB, mA); +} +} + +bool SoftBlit::RunAndCheck(const BufferHandle &exBuffer) +{ + BlendFunction blendFunc = GetBlendFunc(mType); + if (blendFunc == nullptr) { + return false; + } + DISPLAY_TEST_LOGE("blend RunAndCheck begin"); + for (int x = mSrcRect.x; x < mSrcRect.w; x++) { + for (int y = mSrcRect.y; y < mSrcRect.h; y++) { + uint32_t srcPixel = GetPixelRGBA32(mSrcBuffer, x, y); + uint32_t dstPixel = GetPixelRGBA32(mDstBuffer, x, y); + uint32_t exPixel = GetPixelRGBA32(exBuffer, x, y); + ColorRGBAf srcColorF = + ColorRGBAf(RgbaGetR(srcPixel), RgbaGetG(srcPixel), RgbaGetB(srcPixel), RgbaGetA(srcPixel)); + ColorRGBAf dstColorF = + ColorRGBAf(RgbaGetR(dstPixel), RgbaGetG(dstPixel), RgbaGetB(dstPixel), RgbaGetA(dstPixel)); + blendFunc(srcColorF, dstColorF); + ColorRGBA32 dstColrRGBA = ColorRGBA32(dstColorF); + ColorRGBA32 exRGBA = ColorRGBA32(exPixel); + if (!dstColrRGBA.Compare(exRGBA)) { + DISPLAY_TEST_LOGE( + "blend check failed x %d, y %d, srcPixel %x, dstPixel %x , exPixel %x, blendResult %x blendtype %d", + x, y, srcPixel, dstPixel, exPixel, dstColrRGBA.mC, mType); + return false; + } + } + } + DISPLAY_TEST_LOGE("blend RunAndCheck end"); + return true; +} + +SoftBlit::SoftBlit(const BufferHandle &srcBuffer, const IRect &srcRect, const BufferHandle &dstBuffer, + const IRect &dstRect, const BlendType type) +{ + mSrcRect = srcRect; + mDstRect = dstRect; + mSrcBuffer = srcBuffer; + mDstBuffer = dstBuffer; + mType = type; +} \ No newline at end of file diff --git a/hardware/display/test/display_gfx/soft_blit.h b/hardware/display/test/display_gfx/soft_blit.h new file mode 100644 index 0000000000000000000000000000000000000000..fac6c36c326b237aa2d985891026c9f823ed56ff --- /dev/null +++ b/hardware/display/test/display_gfx/soft_blit.h @@ -0,0 +1,62 @@ +/* + * 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 BLIT_CHECK_H +#define BLIT_CHECK_H +#include "display_type.h" + +namespace { +struct ColorRGBAf { + ColorRGBAf(uint32_t r, uint32_t g, uint32_t b, uint32_t a); + inline void Clear() + { + mR = 0; + mB = 0; + mG = 0; + mA = 0; + } + float mR = 0; + float mB = 0; + float mG = 0; + float mA = 0; +}; + +struct ColorRGBA32 { + explicit ColorRGBA32(ColorRGBAf colorFrom); + explicit ColorRGBA32(uint32_t pixel); + bool Compare(ColorRGBA32 &other); + uint32_t mC = 0; + uint8_t mR = 0; + uint8_t mB = 0; + uint8_t mG = 0; + uint8_t mA = 0; +}; +} +class SoftBlit { +public: + SoftBlit(const BufferHandle &srcBuffer, const IRect &srcRect, const BufferHandle &dstBuffer, const IRect &dstRect, + const BlendType type); + bool RunAndCheck(const BufferHandle &exBuffer); + ~SoftBlit() {}; + +private: + IRect mSrcRect = { 0 }; + IRect mDstRect = { 0 }; + BufferHandle mSrcBuffer = { 0 }; + BufferHandle mDstBuffer = { 0 }; + BlendType mType = BLEND_BUTT; +}; + +#endif // BLIT_CHECK_H diff --git a/hardware/display/test/display_gralloc/display_gralloc_test.cpp b/hardware/display/test/display_gralloc/display_gralloc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..751e52070b83560939eead7279a47be01aee762f --- /dev/null +++ b/hardware/display/test/display_gralloc/display_gralloc_test.cpp @@ -0,0 +1,372 @@ +/* + * 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_test.h" +#include +#include "gtest/gtest.h" +#include "display_gralloc.h" +#include "display_test.h" +#include "hi_gbm_internal.h" + +namespace { +const AllocTestPrms GRALLOC_TEST_SETS[] = { + { + .allocInfo = { + .width = 1920, + .height = 1080, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1920 * 4, + .expectSize = 1920 * 1080 * 4 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4 + }, + + { + .allocInfo = { + .width = 1280, + .height = 720, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1280 * 4, + .expectSize = 1280 * 720 * 4 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBA_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGB_888 + }, + .expectStride = 1080 * 3, + .expectSize = 1080 * 1920 * 3 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRA_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRX_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBA_4444 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = + { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBX_4444 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRA_4444 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRX_4444 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGR_565 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRA_5551 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_BGRX_5551 + }, + .expectStride = 1080 * 2, + .expectSize = 1080 * 1920 * 2 + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_YCBCR_420_SP + }, + .expectStride = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN), + .expectSize = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN) * 1920, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_YCRCB_420_SP + }, + .expectStride = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN), + .expectSize = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN) * 1920, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_YCBCR_420_P + }, + .expectStride = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN), + .expectSize = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN) * 1920, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_YCRCB_420_P + }, + .expectStride = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN), + .expectSize = ALIGN_UP(1080 * 3 / 2, WIDTH_ALIGN) * 1920, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_READ, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4, + }, + + { + .allocInfo = { + .width = 1080, + .height = 1920, + .usage = HBM_USE_MEM_DMA | HBM_USE_CPU_WRITE, + .format = PIXEL_FMT_RGBX_8888 + }, + .expectStride = 1080 * 4, + .expectSize = 1080 * 1920 * 4, + }, +}; + +static bool CheckBufferHandle(AllocTestPrms &info, BufferHandle &buffer) +{ + if (buffer.stride != (ALIGN_UP(info.expectStride, WIDTH_ALIGN))) { + DISPLAY_TEST_LOGE("stride check faild stride %d, expect stride %d ", buffer.stride, info.expectStride); + DISPLAY_TEST_LOGE("stride check faild format %d width %d, height %d ", info.allocInfo.format, + info.allocInfo.width, info.allocInfo.height); + return false; + } + + if (buffer.size != info.expectSize) { + DISPLAY_TEST_LOGE("size check faild size %d, expect size %d ", buffer.size, info.expectSize); + DISPLAY_TEST_LOGE("stride check faild format %d width %d, height %d ", info.allocInfo.format, + info.allocInfo.width, info.allocInfo.height); + return false; + } + return true; +} + +void GrallocAllocTest::SetUp() +{ + if (GrallocInitialize(&mGrallocFuncs) != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("DisplayInit failure\n"); + ASSERT_TRUE(0); + } +} + +void GrallocAllocTest::TearDown() +{ + if (GrallocUninitialize(mGrallocFuncs) != DISPLAY_SUCCESS) { + DISPLAY_TEST_LOGE("DisplayUninit failure\n"); + ASSERT_TRUE(0); + } +} + +int32_t GrallocAllocTest::AllocMemTest(AllocTestPrms &info) +{ + int ret; + BufferHandle *buffer = nullptr; + const int testCount = 1; // test 40 times + for (int i = 0; i < testCount; i++) { + ret = mGrallocFuncs->AllocMem(&info.allocInfo, &buffer); + if (ret != DISPLAY_SUCCESS) { + return ret; + } + void *vAddr = mGrallocFuncs->Mmap(buffer); + if (vAddr == nullptr) { + return DISPLAY_FAILURE; + } + + if (info.allocInfo.usage & (HBM_USE_CPU_READ | HBM_USE_CPU_WRITE)) { + ret = mGrallocFuncs->InvalidateCache(buffer); + if (ret != DISPLAY_SUCCESS) { + return ret; + } + } + if (memset_s(vAddr, buffer->size, 0, buffer->size) != EOK) { + return DISPLAY_NOMEM; + } + DISPLAY_TEST_CHK_RETURN(!CheckBufferHandle(info, *buffer), DISPLAY_FAILURE, + DISPLAY_TEST_LOGE("buffer check failed")); + if (info.allocInfo.usage & (HBM_USE_CPU_READ | HBM_USE_CPU_WRITE)) { + ret = mGrallocFuncs->FlushCache(buffer); + if (ret != DISPLAY_SUCCESS) { + return ret; + } + } + mGrallocFuncs->Unmap((buffer)); + mGrallocFuncs->FreeMem(buffer); + } + + return DISPLAY_SUCCESS; +} + +TEST(GrallocAllocTestm, NULLPTR) +{ + int ret; + ret = GrallocInitialize(nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + + GrallocFuncs *grallocFuncs; + AllocInfo allocInfo; + BufferHandle *hdl; + ret = GrallocInitialize(&grallocFuncs); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); + ret = grallocFuncs->AllocMem(nullptr, nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + ret = grallocFuncs->AllocMem(&allocInfo, nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + ret = grallocFuncs->AllocMem(nullptr, &hdl); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + ret = grallocFuncs->InvalidateCache(nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + ret = grallocFuncs->FlushCache(nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + grallocFuncs->FreeMem(nullptr); + void *vAddr = grallocFuncs->Mmap(nullptr); + ASSERT_TRUE(vAddr == nullptr); + ret = grallocFuncs->Unmap(nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + ret = GrallocUninitialize(nullptr); + ASSERT_TRUE(ret != DISPLAY_SUCCESS); + + ret = GrallocUninitialize(grallocFuncs); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); +} + +TEST_P(GrallocAllocTest, GrallocAlloc) +{ + AllocTestPrms params = GetParam(); + int ret = AllocMemTest(params); + ASSERT_TRUE(ret == DISPLAY_SUCCESS); +} + +INSTANTIATE_TEST_CASE_P(AllocTest, GrallocAllocTest, ::testing::ValuesIn(GRALLOC_TEST_SETS)); +} diff --git a/hardware/display/test/display_gralloc/display_gralloc_test.h b/hardware/display/test/display_gralloc/display_gralloc_test.h new file mode 100644 index 0000000000000000000000000000000000000000..8e3c718ac00f15ea53853191811236eb5ae53248 --- /dev/null +++ b/hardware/display/test/display_gralloc/display_gralloc_test.h @@ -0,0 +1,36 @@ +/* + * 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_TEST_H +#define DISPLAY_GRALLOC_TEST_H +#include "gtest/gtest.h" +#include "display_gralloc.h" + +namespace { +struct AllocTestPrms { + AllocInfo allocInfo; + int32_t expectStride; + int32_t expectSize; +}; + +class GrallocAllocTest : public ::testing::TestWithParam { +protected: + virtual void SetUp(); + virtual void TearDown(); + int32_t AllocMemTest(AllocTestPrms &info); + GrallocFuncs *mGrallocFuncs = nullptr; +}; +} +#endif // DISPLAY_GRALLOC_TEST_H \ No newline at end of file diff --git a/hardware/mpp/include/mpi_enc_utils.h b/hardware/mpp/include/mpi_enc_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..5ea51040dc65f42c11c30621d669e4200b1987ed --- /dev/null +++ b/hardware/mpp/include/mpi_enc_utils.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#ifndef __MPI_ENC_UTILS_H__ +#define __MPI_ENC_UTILS_H__ + +#include + +#include "rk_venc_cmd.h" + +typedef struct MpiEncTestArgs_t { + MppCodingType type; + MppFrameFormat format; + + RK_S32 width; + RK_S32 height; +} MpiEncTestArgs; + +typedef struct { + // global flow control flag + RK_U32 frm_eos; + RK_U32 pkt_eos; + RK_S32 frame_count; + RK_U64 stream_size; + + // base flow context + MppCtx ctx; + MppApi *mpi; + MppEncCfg cfg; + + // input / output + MppBufferGroup buf_grp; + MppBuffer pkt_buf; + MppEncSeiMode sei_mode; + MppEncHeaderMode header_mode; + + // paramter for resource malloc + RK_U32 width; + RK_U32 height; + RK_U32 hor_stride; + RK_U32 ver_stride; + MppFrameFormat fmt; + MppCodingType type; + RK_S32 num_frames; + + // resources + size_t frame_size; + + RK_U32 split_mode; + RK_U32 split_arg; + + // rate control runtime parameter + + RK_S32 fps_in_flex; + RK_S32 fps_in_den; + RK_S32 fps_in_num; + RK_S32 fps_out_flex; + RK_S32 fps_out_den; + RK_S32 fps_out_num; + RK_S32 bps; + RK_S32 bps_max; + RK_S32 bps_min; + RK_S32 rc_mode; + RK_S32 gop_mode; + RK_S32 gop_len; + RK_S32 vi_len; +} MpiEncTestData; + +int hal_mpp_get_sps(void *ctx, unsigned char *buf, size_t *buf_size); +int hal_mpp_encode(void *ctx, int dma_fd, unsigned char *buf, size_t *buf_size); + +void *hal_mpp_ctx_create(MpiEncTestArgs *args); +void hal_mpp_ctx_delete(void *ctx); + +#endif /*__MPI_ENC_UTILS_H__*/ diff --git a/hardware/mpp/src/mpi_enc_utils.c b/hardware/mpp/src/mpi_enc_utils.c new file mode 100644 index 0000000000000000000000000000000000000000..79331d227fe23ebcc8dc6b147ecca4b3dbf701be --- /dev/null +++ b/hardware/mpp/src/mpi_enc_utils.c @@ -0,0 +1,886 @@ +/* + * 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. + */ + +#define MODULE_TAG "mpi_enc_utils" + +#include + +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_buffer.h" + +#include "rk_mpi.h" +#include "mpp_common.h" +#include "mpi_enc_utils.h" + +#if 0 +RK_S32 mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt) +{ + RK_S32 stride = 0; + + switch (fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP : + case MPP_FMT_YUV420SP_VU : { + stride = MPP_ALIGN(width, 8); + } break; + case MPP_FMT_YUV420P : { + /* NOTE: 420P need to align to 16 so chroma can align to 8 */ + stride = MPP_ALIGN(width, 16); + } break; + case MPP_FMT_YUV422P: + case MPP_FMT_YUV422SP: + case MPP_FMT_YUV422SP_VU: { + /* NOTE: 422 need to align to 8 so chroma can align to 16 */ + stride = MPP_ALIGN(width, 8); + } break; + case MPP_FMT_RGB565: + case MPP_FMT_BGR565: + case MPP_FMT_RGB555: + case MPP_FMT_BGR555: + case MPP_FMT_RGB444: + case MPP_FMT_BGR444: + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_YVYU : + case MPP_FMT_YUV422_UYVY : + case MPP_FMT_YUV422_VYUY : { + /* NOTE: for vepu limitation */ + stride = MPP_ALIGN(width, 8) * 2; + } break; + case MPP_FMT_RGB888 : + case MPP_FMT_BGR888 : { + /* NOTE: for vepu limitation */ + stride = MPP_ALIGN(width, 8) * 3; + } break; + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : + case MPP_FMT_ARGB8888 : + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { + /* NOTE: for vepu limitation */ + stride = MPP_ALIGN(width, 8) * 4; + } break; + default : { + mpp_err_f("do not support type %d\n", fmt); + } break; + } + + return stride; +} +#endif + +static MPP_RET mpi_enc_gen_ref_cfg(MppEncRefCfg ref, RK_S32 gop_mode) +{ + MppEncRefLtFrmCfg lt_ref[4]; + MppEncRefStFrmCfg st_ref[16]; + RK_S32 lt_cnt = 0; + RK_S32 st_cnt = 0; + MPP_RET ret = 0; + + memset(<_ref, 0, sizeof(lt_ref)); + memset(&st_ref, 0, sizeof(st_ref)); + + switch (gop_mode) { + case 3 : { + // tsvc4 + // /-> P1 /-> P3 /-> P5 /-> P7 + // / / / / + // //--------> P2 //--------> P6 + // // // + // ///---------------------> P4 + // /// + // P0 ------------------------------------------------> P8 + lt_cnt = 1; + + /* set 8 frame lt-ref gap */ + lt_ref[0].lt_idx = 0; + lt_ref[0].temporal_id = 0; + lt_ref[0].ref_mode = REF_TO_PREV_LT_REF; + lt_ref[0].lt_gap = 8; + lt_ref[0].lt_delay = 0; + + st_cnt = 9; + /* set tsvc4 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 3 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 3; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 2 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 2; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + /* st 3 layer 3 - non-ref */ + st_ref[3].is_non_ref = 1; + st_ref[3].temporal_id = 3; + st_ref[3].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[3].ref_arg = 0; + st_ref[3].repeat = 0; + /* st 4 layer 1 - ref */ + st_ref[4].is_non_ref = 0; + st_ref[4].temporal_id = 1; + st_ref[4].ref_mode = REF_TO_PREV_LT_REF; + st_ref[4].ref_arg = 0; + st_ref[4].repeat = 0; + /* st 5 layer 3 - non-ref */ + st_ref[5].is_non_ref = 1; + st_ref[5].temporal_id = 3; + st_ref[5].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[5].ref_arg = 0; + st_ref[5].repeat = 0; + /* st 6 layer 2 - ref */ + st_ref[6].is_non_ref = 0; + st_ref[6].temporal_id = 2; + st_ref[6].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[6].ref_arg = 0; + st_ref[6].repeat = 0; + /* st 7 layer 3 - non-ref */ + st_ref[7].is_non_ref = 1; + st_ref[7].temporal_id = 3; + st_ref[7].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[7].ref_arg = 0; + st_ref[7].repeat = 0; + /* st 8 layer 0 - ref */ + st_ref[8].is_non_ref = 0; + st_ref[8].temporal_id = 0; + st_ref[8].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[8].ref_arg = 0; + st_ref[8].repeat = 0; + } break; + case 2 : { + // tsvc3 + // /-> P1 /-> P3 + // / / + // //--------> P2 + // // + // P0/---------------------> P4 + lt_cnt = 0; + + st_cnt = 5; + /* set tsvc4 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 2 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 2; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 1 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 1; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + /* st 3 layer 2 - non-ref */ + st_ref[3].is_non_ref = 1; + st_ref[3].temporal_id = 2; + st_ref[3].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[3].ref_arg = 0; + st_ref[3].repeat = 0; + /* st 4 layer 0 - ref */ + st_ref[4].is_non_ref = 0; + st_ref[4].temporal_id = 0; + st_ref[4].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[4].ref_arg = 0; + st_ref[4].repeat = 0; + } break; + case 1 : { + // tsvc2 + // /-> P1 + // / + // P0--------> P2 + lt_cnt = 0; + + st_cnt = 3; + /* set tsvc4 st-ref struct */ + /* st 0 layer 0 - ref */ + st_ref[0].is_non_ref = 0; + st_ref[0].temporal_id = 0; + st_ref[0].ref_mode = REF_TO_TEMPORAL_LAYER; + st_ref[0].ref_arg = 0; + st_ref[0].repeat = 0; + /* st 1 layer 2 - non-ref */ + st_ref[1].is_non_ref = 1; + st_ref[1].temporal_id = 1; + st_ref[1].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[1].ref_arg = 0; + st_ref[1].repeat = 0; + /* st 2 layer 1 - ref */ + st_ref[2].is_non_ref = 0; + st_ref[2].temporal_id = 0; + st_ref[2].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[2].ref_arg = 0; + st_ref[2].repeat = 0; + } break; + default : { + mpp_err_f("unsupport gop mode %d\n", gop_mode); + } break; + } + + if (lt_cnt || st_cnt) { + ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt); + + if (lt_cnt) + ret = mpp_enc_ref_cfg_add_lt_cfg(ref, lt_cnt, lt_ref); + + if (st_cnt) + ret = mpp_enc_ref_cfg_add_st_cfg(ref, st_cnt, st_ref); + + /* check and get dpb size */ + ret = mpp_enc_ref_cfg_check(ref); + } + + return ret; +} + +static MPP_RET mpi_enc_gen_smart_gop_ref_cfg(MppEncRefCfg ref, RK_S32 gop_len, RK_S32 vi_len) +{ + MppEncRefLtFrmCfg lt_ref[4]; + MppEncRefStFrmCfg st_ref[16]; + RK_S32 lt_cnt = 1; + RK_S32 st_cnt = 8; + RK_S32 pos = 0; + MPP_RET ret; + + memset(<_ref, 0, sizeof(lt_ref)); + memset(&st_ref, 0, sizeof(st_ref)); + + ret = mpp_enc_ref_cfg_set_cfg_cnt(ref, lt_cnt, st_cnt); + + /* set 8 frame lt-ref gap */ + lt_ref[0].lt_idx = 0; + lt_ref[0].temporal_id = 0; + lt_ref[0].ref_mode = REF_TO_PREV_LT_REF; + lt_ref[0].lt_gap = gop_len; + lt_ref[0].lt_delay = 0; + + ret = mpp_enc_ref_cfg_add_lt_cfg(ref, 1, lt_ref); + + /* st 0 layer 0 - ref */ + st_ref[pos].is_non_ref = 0; + st_ref[pos].temporal_id = 0; + st_ref[pos].ref_mode = REF_TO_PREV_INTRA; + st_ref[pos].ref_arg = 0; + st_ref[pos].repeat = 0; + pos++; + + /* st 1 layer 1 - non-ref */ + if (vi_len > 1) { + st_ref[pos].is_non_ref = 0; + st_ref[pos].temporal_id = 1; + st_ref[pos].ref_mode = REF_TO_PREV_REF_FRM; + st_ref[pos].ref_arg = 0; + st_ref[pos].repeat = vi_len - 2; + pos++; + } + + st_ref[pos].is_non_ref = 0; + st_ref[pos].temporal_id = 0; + st_ref[pos].ref_mode = REF_TO_PREV_INTRA; + st_ref[pos].ref_arg = 0; + st_ref[pos].repeat = 0; + pos++; + + ret = mpp_enc_ref_cfg_add_st_cfg(ref, pos, st_ref); + + /* check and get dpb size */ + ret = mpp_enc_ref_cfg_check(ref); + + return ret; +} + +/* ˱õһЩߣͼʽʽȣֱ֪0 + * test_mpp_enc_cfg_setupԶĬϵIJbps gopȲ + */ +static MPP_RET test_ctx_init(MpiEncTestData **data, MpiEncTestArgs *cmd) +{ + MpiEncTestData *p = NULL; + MPP_RET ret = 0; + + if (!data || !cmd) { + mpp_err_f("invalid input data %p cmd %p\n", data, cmd); + return MPP_ERR_NULL_PTR; + } + + p = mpp_calloc(MpiEncTestData, 1); + if (!p) { + mpp_err_f("create MpiEncTestData failed\n"); + ret = MPP_ERR_MALLOC; + goto RET; + } + + // get paramter from cmd + p->width = cmd->width; + p->height = cmd->height; + p->hor_stride = MPP_ALIGN(cmd->width, 16); + p->ver_stride = MPP_ALIGN(cmd->height, 16); + p->fmt = cmd->format; + p->type = cmd->type; + + // update resource parameter + switch (p->fmt & MPP_FRAME_FMT_MASK) { + case MPP_FMT_YUV420SP: + case MPP_FMT_YUV420P: { + p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 3 / 2; + } break; + + case MPP_FMT_YUV422_YUYV : + case MPP_FMT_YUV422_YVYU : + case MPP_FMT_YUV422_UYVY : + case MPP_FMT_YUV422_VYUY : + case MPP_FMT_YUV422P : + case MPP_FMT_YUV422SP : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : { + p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 2; + } break; + + default: { + p->frame_size = MPP_ALIGN(p->hor_stride, 64) * MPP_ALIGN(p->ver_stride, 64) * 4; + } break; + } + +RET: + *data = p; + return ret; +} + +static MPP_RET test_ctx_deinit(MpiEncTestData **data) +{ + MpiEncTestData *p = NULL; + + if (!data) { + mpp_err_f("invalid input data %p\n", data); + return MPP_ERR_NULL_PTR; + } + p = *data; + if (p) { + MPP_FREE(p); + *data = NULL; + } + return MPP_OK; +} + +static MPP_RET test_mpp_enc_cfg_setup(MpiEncTestData *p) +{ + MPP_RET ret; + MppApi *mpi; + MppCtx ctx; + MppEncCfg cfg; + + if (NULL == p) + return MPP_ERR_NULL_PTR; + + mpi = p->mpi; + ctx = p->ctx; + cfg = p->cfg; + + /* setup default parameter */ + if (p->fps_in_den == 0) + p->fps_in_den = 1; + if (p->fps_in_num == 0) + p->fps_in_num = 30; + if (p->fps_out_den == 0) + p->fps_out_den = 1; + if (p->fps_out_num == 0) + p->fps_out_num = 30; + + /* Ĭbps */ + if (!p->bps) + p->bps = p->width * p->height / 8 * (p->fps_out_num / p->fps_out_den); + + mpp_enc_cfg_set_s32(cfg, "prep:width", p->width); + mpp_enc_cfg_set_s32(cfg, "prep:height", p->height); + mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", p->hor_stride); + mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", p->ver_stride); + mpp_enc_cfg_set_s32(cfg, "prep:format", p->fmt); + + mpp_enc_cfg_set_s32(cfg, "rc:mode", p->rc_mode); + + /* fix input / output frame rate */ + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", p->fps_in_flex); + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", p->fps_in_num); + mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denorm", p->fps_in_den); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", p->fps_out_flex); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", p->fps_out_num); + mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denorm", p->fps_out_den); + mpp_enc_cfg_set_s32(cfg, "rc:gop", p->gop_len ? p->gop_len : p->fps_out_num * 2); + + /* drop frame or not when bitrate overflow */ + mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED); + mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */ + mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */ + + /* setup bitrate for different rc_mode */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_target", p->bps); + switch (p->rc_mode) { + case MPP_ENC_RC_MODE_FIXQP : { + /* do not setup bitrate on FIXQP mode */ + } break; + case MPP_ENC_RC_MODE_CBR : { + /* CBR mode has narrow bound */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); + mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); + } break; + case MPP_ENC_RC_MODE_VBR : + case MPP_ENC_RC_MODE_AVBR : { + /* VBR mode has wide bound */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); + mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 1 / 16); + } break; + default : { + /* default use CBR mode */ + mpp_enc_cfg_set_s32(cfg, "rc:bps_max", p->bps_max ? p->bps_max : p->bps * 17 / 16); + mpp_enc_cfg_set_s32(cfg, "rc:bps_min", p->bps_min ? p->bps_min : p->bps * 15 / 16); + } break; + } + + /* setup qp for different codec and rc_mode */ + switch (p->type) { + case MPP_VIDEO_CodingAVC : + case MPP_VIDEO_CodingHEVC : { + switch (p->rc_mode) { + case MPP_ENC_RC_MODE_FIXQP : { + mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 20); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 20); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 20); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 20); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 20); + mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2); + } break; + case MPP_ENC_RC_MODE_CBR : + case MPP_ENC_RC_MODE_VBR : + case MPP_ENC_RC_MODE_AVBR : { + mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 26); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 51); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 10); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 51); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 10); + mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 2); + } break; + default : { + mpp_err_f("unsupport encoder rc mode %d\n", p->rc_mode); + } break; + } + } break; + case MPP_VIDEO_CodingVP8 : { + /* vp8 only setup base qp range */ + mpp_enc_cfg_set_s32(cfg, "rc:qp_init", 40); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max", 127); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min", 0); + mpp_enc_cfg_set_s32(cfg, "rc:qp_max_i", 127); + mpp_enc_cfg_set_s32(cfg, "rc:qp_min_i", 0); + mpp_enc_cfg_set_s32(cfg, "rc:qp_ip", 6); + } break; + case MPP_VIDEO_CodingMJPEG : { + /* jpeg use special codec config to control qtable */ + mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80); + mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99); + mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1); + } break; + default : { + } break; + } + + /* setup codec */ + mpp_enc_cfg_set_s32(cfg, "codec:type", p->type); + switch (p->type) { + case MPP_VIDEO_CodingAVC : { + /* + * H.264 profile_idc parameter + * 66 - Baseline profile + * 77 - Main profile + * 100 - High profile + */ + mpp_enc_cfg_set_s32(cfg, "h264:profile", 100); + /* + * H.264 level_idc parameter + * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps + * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps + * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps + * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps + * 50 / 51 / 52 - 4K@30fps + */ + mpp_enc_cfg_set_s32(cfg, "h264:level", 40); + mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1); + mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0); + mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1); + } break; + case MPP_VIDEO_CodingHEVC : + case MPP_VIDEO_CodingMJPEG : + case MPP_VIDEO_CodingVP8 : { + } break; + default : { + mpp_err_f("unsupport encoder coding type %d\n", p->type); + } break; + } + + p->split_mode = 0; + p->split_arg = 0; + + mpp_env_get_u32("split_mode", &p->split_mode, MPP_ENC_SPLIT_NONE); + mpp_env_get_u32("split_arg", &p->split_arg, 0); + + if (p->split_mode) { + mpp_log("%p split_mode %d split_arg %d\n", ctx, p->split_mode, p->split_arg); + mpp_enc_cfg_set_s32(cfg, "split:mode", p->split_mode); + mpp_enc_cfg_set_s32(cfg, "split:arg", p->split_arg); + } + + ret = mpi->control(ctx, MPP_ENC_SET_CFG, cfg); + if (ret) { + mpp_err("mpi control enc set cfg failed ret %d\n", ret); + goto RET; + } + + /* optional */ + p->sei_mode = MPP_ENC_SEI_MODE_ONE_FRAME; + ret = mpi->control(ctx, MPP_ENC_SET_SEI_CFG, &p->sei_mode); + if (ret) { + mpp_err("mpi control enc set sei cfg failed ret %d\n", ret); + goto RET; + } + + if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { + p->header_mode = MPP_ENC_HEADER_MODE_EACH_IDR; + ret = mpi->control(ctx, MPP_ENC_SET_HEADER_MODE, &p->header_mode); + if (ret) { + mpp_err("mpi control enc set header mode failed ret %d\n", ret); + goto RET; + } + } + + RK_U32 gop_mode = p->gop_mode; + + mpp_env_get_u32("gop_mode", &gop_mode, gop_mode); + if (gop_mode) { + MppEncRefCfg ref; + + mpp_enc_ref_cfg_init(&ref); + + if (p->gop_mode < 4) + mpi_enc_gen_ref_cfg(ref, gop_mode); + else + mpi_enc_gen_smart_gop_ref_cfg(ref, p->gop_len, p->vi_len); + + ret = mpi->control(ctx, MPP_ENC_SET_REF_CFG, ref); + if (ret) { + mpp_err("mpi control enc set ref cfg failed ret %d\n", ret); + goto RET; + } + mpp_enc_ref_cfg_deinit(&ref); + } + +RET: + return ret; +} + +static void test_mpp_frame_set_param(MppFrame frame, MpiEncTestData *p) +{ + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, p->hor_stride); + mpp_frame_set_ver_stride(frame, p->ver_stride); + mpp_frame_set_fmt(frame, p->fmt); + mpp_frame_set_eos(frame, p->frm_eos); +} + +static void test_mpp_ctx_cleanup(MpiEncTestData *p) +{ + if (!p) + return; + + p->mpi->reset(p->ctx); + + if (p->ctx) { + mpp_destroy(p->ctx); + p->ctx = NULL; + } + + if (p->cfg) { + mpp_enc_cfg_deinit(p->cfg); + p->cfg = NULL; + } + + if (p->pkt_buf) { + mpp_buffer_put(p->pkt_buf); + p->pkt_buf = NULL; + } + + if (p->buf_grp) { + mpp_buffer_group_put(p->buf_grp); + p->buf_grp = NULL; + } + + test_ctx_deinit(&p); +} + +int hal_mpp_get_sps(void *ctx, unsigned char *buf, size_t *buf_size) +{ + int ret; + MppApi *mpi; + MppCtx mpp_ctx; + MppPacket packet = NULL; + MpiEncTestData *p = (MpiEncTestData *)ctx; + + mpi = p->mpi; + mpp_ctx = p->ctx; + + /* + * Can use packet with normal malloc buffer as input not pkt_buf. + * Please refer to vpu_api_legacy.cpp for normal buffer case. + * Using pkt_buf buffer here is just for simplifing demo. + */ + + mpp_packet_init_with_buffer(&packet, p->pkt_buf); + /* NOTE: It is important to clear output packet length!! */ + mpp_packet_set_length(packet, 0); + + // һH264H265רõһЩ + if (p->type == MPP_VIDEO_CodingAVC || p->type == MPP_VIDEO_CodingHEVC) { + ret = mpi->control(mpp_ctx, MPP_ENC_GET_HDR_SYNC, packet); + if (ret) { + mpp_err("mpi control enc get extra info failed\n"); + ret = MPP_NOK; + goto exit; + } + } + + void *ptr = mpp_packet_get_pos(packet); + size_t len = mpp_packet_get_length(packet); + + if (*buf_size < len) { + mpp_err("mpi buffer size too small\n"); + ret = MPP_NOK; + goto exit; + } + + memcpy(buf, ptr, len); + + *buf_size = len; + + ret = MPP_OK; + +exit: + mpp_packet_deinit(&packet); + + return MPP_OK; +} + +int hal_mpp_encode(void *ctx, int dma_fd, unsigned char *buf, size_t *buf_size) +{ + MPP_RET ret; + MppFrame frame = NULL; + MppMeta meta = NULL; + MppPacket packet = NULL; + MpiEncTestData *p = (MpiEncTestData *)ctx; + MppApi *mpi = p->mpi; + RK_U32 eoi = 1; + RK_U32 packet_num = 0; + MppBuffer cam_buf = NULL; + MppBufferInfo info; + + memset(&info, 0, sizeof(MppBufferInfo)); + info.type = MPP_BUFFER_TYPE_EXT_DMA; + info.fd = dma_fd; + info.size = p->frame_size & 0x07ffffff; + info.index = (p->frame_size & 0xf8000000) >> 27; + + ret = mpp_buffer_import(&cam_buf, &info); + if (ret != MPP_SUCCESS) { + mpp_err_f("mpp_buffer_import failed\n"); + return MPP_NOK; + } + + ret = mpp_frame_init(&frame); + if (ret) { + mpp_err_f("mpp_frame_init failed\n"); + return MPP_NOK; + } + + /* set frame size info */ + test_mpp_frame_set_param(frame, p); + + /* set frame data include fd */ + mpp_frame_set_buffer(frame, cam_buf); + + /* packet init */ + mpp_packet_init_with_buffer(&packet, p->pkt_buf); + /* NOTE: It is important to clear output packet length!! */ + mpp_packet_set_length(packet, 0); + + meta = mpp_frame_get_meta(frame); + mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); + + /* + * NOTE: in non-block mode the frame can be resent. + * The default input timeout mode is block. + * + * User should release the input frame to meet the requirements of + * resource creator must be the resource destroyer. + */ + ret = mpi->encode_put_frame(p->ctx, frame); + if (ret) { + mpp_err("mpp encode put frame failed\n"); + mpp_frame_deinit(&frame); + goto RET; + } + + mpp_frame_deinit(&frame); + + packet_num = 0; + + do { + ret = mpi->encode_get_packet(p->ctx, &packet); + if (ret) { + mpp_err("mpp encode get packet failed\n"); + goto RET; + } + + mpp_assert(packet); + + if (packet) { + /* for low delay partition encoding */ + if (mpp_packet_is_partition(packet)) { + eoi = mpp_packet_is_eoi(packet); + } + + p->frame_count += eoi; + packet_num++; + } + } while (!eoi); + + void *ptr = mpp_packet_get_pos(packet); + size_t len = mpp_packet_get_length(packet); + + if (packet_num != 1) { + mpp_err("packet_num %u != 1\n"); + ret = MPP_NOK; + goto RET; + } + + if (*buf_size < len) { + mpp_err("mpi buffer size too small\n"); + ret = MPP_NOK; + goto RET; + } + + memcpy(buf, ptr, len); + + *buf_size = len; + + ret = MPP_OK; +RET: + + if (cam_buf) + mpp_buffer_put(cam_buf); + + mpp_packet_deinit(&packet); + + return ret; +} + +void *hal_mpp_ctx_create(MpiEncTestArgs *args) +{ + MPP_RET ret; + MpiEncTestData *p = NULL; + MppPollType timeout = MPP_POLL_BLOCK; + + /* ʼһ³õIJãcmdñȽ϶ */ + ret = test_ctx_init(&p, args); + if (ret) { + mpp_err_f("test data init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpp_buffer_group_get_internal(&p->buf_grp, MPP_BUFFER_TYPE_DRM); + if (ret) { + mpp_err_f("failed to get mpp buffer group ret %d\n", ret); + goto MPP_TEST_OUT; + } + + /* pkt_bufԱҪǸpacketʹõbuffer */ + ret = mpp_buffer_get(p->buf_grp, &p->pkt_buf, p->frame_size); + if (ret) { + mpp_err_f("failed to get buffer for output packet ret %d\n", ret); + goto MPP_TEST_OUT; + } + + // encoder demo + ret = mpp_create(&p->ctx, &p->mpi); + if (ret) { + mpp_err("mpp_create failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + mpp_log("%p mpi_enc_test encoder test start w %d h %d type %d\n", + p->ctx, p->width, p->height, p->type); + + ret = p->mpi->control(p->ctx, MPP_SET_OUTPUT_TIMEOUT, &timeout); + if (MPP_OK != ret) { + mpp_err("mpi control set output timeout %d ret %d\n", timeout, ret); + goto MPP_TEST_OUT; + } + + ret = mpp_init(p->ctx, MPP_CTX_ENC, p->type); + if (ret) { + mpp_err("mpp_init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = mpp_enc_cfg_init(&p->cfg); + if (ret) { + mpp_err_f("mpp_enc_cfg_init failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + ret = test_mpp_enc_cfg_setup(p); + if (ret) { + mpp_err_f("test mpp setup failed ret %d\n", ret); + goto MPP_TEST_OUT; + } + + return p; + +MPP_TEST_OUT: + + mpp_err("%p mpi_enc_test failed ret %d\n", p->ctx, ret); + + return NULL; +} + +void hal_mpp_ctx_delete(void *ctx) +{ + test_mpp_ctx_cleanup(ctx); +} diff --git a/hardware/rga/include/GrallocOps.h b/hardware/rga/include/GrallocOps.h new file mode 100755 index 0000000000000000000000000000000000000000..97e92d427b37e01990fc6a5f33f15461147bf7ca --- /dev/null +++ b/hardware/rga/include/GrallocOps.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _rk_graphic_buffer_h_ +#define _rk_graphic_buffer_h_ + +#ifdef ANDROID + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "drmrga.h" +#include "rga.h" + +// ------------------------------------------------------------------------------- +int RkRgaGetHandleFd(buffer_handle_t handle, int *fd); +int RkRgaGetHandleAttributes(buffer_handle_t handle, + std::vector *attrs); +int RkRgaGetHandleMapAddress(buffer_handle_t handle, + void **buf); +#endif //Android + +#endif //_rk_graphic_buffer_h_ diff --git a/hardware/rga/include/RgaApi.h b/hardware/rga/include/RgaApi.h new file mode 100755 index 0000000000000000000000000000000000000000..b0049f72b71f2bbfea749f3e921db26dca388919 --- /dev/null +++ b/hardware/rga/include/RgaApi.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _rockchip_rga_c_h_ +#define _rockchip_rga_c_h_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drmrga.h" +#include "rga.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/* + * Compatible with the old version of C interface.The new + * version of the C interface no longer requires users to + * initialize rga, so RgaInit and RgaDeInit are just for + * compatibility with the old C interface, so please do + * not use ctx, because it is usually a NULL. + */ +#define RgaInit(ctx) ({ \ + int ret = 0; \ + ret = c_RkRgaInit(); \ + c_RkRgaGetContext(ctx); \ + ret;\ +}) +#define RgaDeInit(ctx) { \ + (void)ctx; /* unused */ \ + c_RkRgaDeInit(); \ +} +#define RgaBlit(...) c_RkRgaBlit(__VA_ARGS__) +#define RgaCollorFill(...) c_RkRgaColorFill(__VA_ARGS__) +#define RgaFlush() c_RkRgaFlush() + +int c_RkRgaInit(); +void c_RkRgaDeInit(); +void c_RkRgaGetContext(void **ctx); +int c_RkRgaBlit(rga_info_t *src, rga_info_t *dst, rga_info_t *src1); +int c_RkRgaColorFill(rga_info_t *dst); +int c_RkRgaFlush(); + +#ifndef ANDROID /* linux */ +int c_RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); +int c_RkRgaGetAllocBufferCache(bo_t *bo_info, int width, int height, int bpp); +int c_RkRgaGetMmap(bo_t *bo_info); +int c_RkRgaUnmap(bo_t *bo_info); +int c_RkRgaFree(bo_t *bo_info); +int c_RkRgaGetBufferFd(bo_t *bo_info, int *fd); +#endif /* #ifndef ANDROID */ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef _rockchip_rga_c_h_ */ diff --git a/hardware/rga/include/RgaMutex.h b/hardware/rga/include/RgaMutex.h new file mode 100755 index 0000000000000000000000000000000000000000..61909e2c809e3b33cda6054ebfc9b397c0cd88cb --- /dev/null +++ b/hardware/rga/include/RgaMutex.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2020 Rockchip Electronics Co., Ltd. + * Authors: + * PutinLee + * + * 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 _LIBS_RGA_MUTEX_H +#define _LIBS_RGA_MUTEX_H + +#ifndef ANDROID +#include +#include +#include + +#include + + +// Enable thread safety attributes only with clang. +// The attributes can be safely erased when compiling with other compilers. +#if defined(__clang__) && (!defined(SWIG)) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +class Condition; + +/* + * NOTE: This class is for code that builds on Win32. Its usage is + * deprecated for code which doesn't build for Win32. New code which + * doesn't build for Win32 should use std::mutex and std::lock_guard instead. + * + * Simple mutex class. The implementation is system-dependent. + * + * The mutex must be unlocked by the thread that locked it. They are not + * recursive, i.e. the same thread can't lock it multiple times. + */ +class CAPABILITY("mutex") Mutex { + public: + enum { + PRIVATE = 0, + SHARED = 1 + }; + + Mutex(); + explicit Mutex(const char* name); + explicit Mutex(int type, const char* name = nullptr); + ~Mutex(); + + // lock or unlock the mutex + int32_t lock() ACQUIRE(); + void unlock() RELEASE(); + + // lock if possible; returns 0 on success, error otherwise + int32_t tryLock() TRY_ACQUIRE(0); + + int32_t timedLock(int64_t timeoutNs) TRY_ACQUIRE(0); + + // Manages the mutex automatically. It'll be locked when Autolock is + // constructed and released when Autolock goes out of scope. + class SCOPED_CAPABILITY Autolock { + public: + inline explicit Autolock(Mutex& mutex) ACQUIRE(mutex) : mLock(mutex) { + mLock.lock(); + } + inline explicit Autolock(Mutex* mutex) ACQUIRE(mutex) : mLock(*mutex) { + mLock.lock(); + } + inline ~Autolock() RELEASE() { + mLock.unlock(); + } + + private: + Mutex& mLock; + // Cannot be copied or moved - declarations only + Autolock(const Autolock&); + Autolock& operator=(const Autolock&); + }; + + private: + friend class Condition; + + // A mutex cannot be copied + Mutex(const Mutex&); + Mutex& operator=(const Mutex&); + + pthread_mutex_t mMutex; +}; + +// --------------------------------------------------------------------------- +inline Mutex::Mutex() { + pthread_mutex_init(&mMutex, nullptr); +} +inline Mutex::Mutex(__attribute__((unused)) const char* name) { + pthread_mutex_init(&mMutex, nullptr); +} +inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) { + if (type == SHARED) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&mMutex, &attr); + pthread_mutexattr_destroy(&attr); + } else { + pthread_mutex_init(&mMutex, nullptr); + } +} +inline Mutex::~Mutex() { + pthread_mutex_destroy(&mMutex); +} +inline int32_t Mutex::lock() { + return -pthread_mutex_lock(&mMutex); +} +inline void Mutex::unlock() { + pthread_mutex_unlock(&mMutex); +} +inline int32_t Mutex::tryLock() { + return -pthread_mutex_trylock(&mMutex); +} +inline int32_t Mutex::timedLock(int64_t timeoutNs) { + timespec now; + clock_gettime(CLOCK_REALTIME, &now); + timeoutNs += now.tv_sec*1000000000 + now.tv_nsec; + const struct timespec ts = { + /* .tv_sec = */ static_cast(timeoutNs / 1000000000), + /* .tv_nsec = */ static_cast(timeoutNs % 1000000000), + }; + return -pthread_mutex_timedlock(&mMutex, &ts); +} + +// --------------------------------------------------------------------------- + +/* + * Automatic mutex. Declare one of these at the top of a function. + * When the function returns, it will go out of scope, and release the + * mutex. + */ + +typedef Mutex::Autolock AutoMutex; +#endif // __ANDROID_VNDK__ +#endif // _LIBS_RGA_MUTEX_H diff --git a/hardware/rga/include/RgaSingleton.h b/hardware/rga/include/RgaSingleton.h new file mode 100755 index 0000000000000000000000000000000000000000..e87cf1c385533d009360f66e95d3badba0a66be7 --- /dev/null +++ b/hardware/rga/include/RgaSingleton.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _LIBS_RGA_SINGLETON_H +#define _LIBS_RGA_SINGLETON_H + +#ifndef ANDROID +#include "RgaMutex.h" + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundefined-var-template" +#endif + +template +class Singleton { + public: + static TYPE& getInstance() { + Mutex::Autolock _l(sLock); + TYPE* instance = sInstance; + if (instance == nullptr) { + instance = new TYPE(); + sInstance = instance; + } + return *instance; + } + + static bool hasInstance() { + Mutex::Autolock _l(sLock); + return sInstance != nullptr; + } + + protected: + ~Singleton() { } + Singleton() { } + + private: + Singleton(const Singleton&); + Singleton& operator = (const Singleton&); + static Mutex sLock; + static TYPE* sInstance; +}; + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + +#define RGA_SINGLETON_STATIC_INSTANCE(TYPE) \ + template<> ::Mutex \ + (::Singleton< TYPE >::sLock)(::Mutex::PRIVATE); \ + template<> TYPE* ::Singleton< TYPE >::sInstance(nullptr); /* NOLINT */ \ + template class ::Singleton< TYPE >; + +#endif //ANDROID +#endif //_LIBS_RGA_SINGLETON_H diff --git a/hardware/rga/include/RgaUtils.h b/hardware/rga/include/RgaUtils.h new file mode 100755 index 0000000000000000000000000000000000000000..27f9394d8e0435a4dd852819e76f3237a850f0c4 --- /dev/null +++ b/hardware/rga/include/RgaUtils.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _rga_utils_h_ +#define _rga_utils_h_ + +// ------------------------------------------------------------------------------- +float get_bpp_from_format(int format); +int get_buf_from_file(void *buf, int f, int sw, int sh, int index); +int output_buf_data_to_file(void *buf, int f, int sw, int sh, int index); +const char *translate_format_str(int format); +#endif + diff --git a/hardware/rga/include/RockchipRga.h b/hardware/rga/include/RockchipRga.h new file mode 100755 index 0000000000000000000000000000000000000000..082f9e1e874d61d8063d971e276acca9e989a157 --- /dev/null +++ b/hardware/rga/include/RockchipRga.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _rockchip_rga_h_ +#define _rockchip_rga_h_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmrga.h" +#include "GrallocOps.h" +#include "RgaUtils.h" +#include "rga.h" + +////////////////////////////////////////////////////////////////////////////////// +#ifndef ANDROID +#include "RgaSingleton.h" +#endif + +#ifdef ANDROID +#include +#include +#include + +namespace android { +#endif + + class RockchipRga :public Singleton { + public: + + static inline RockchipRga& get() { + return getInstance(); + } + + int RkRgaInit(); + void RkRgaDeInit(); + void RkRgaGetContext(void **ctx); +#ifndef ANDROID /* LINUX */ + int RkRgaAllocBuffer(int drm_fd /* input */, bo_t *bo_info, + int width, int height, int bpp, int flags); + int RkRgaFreeBuffer(int drm_fd /* input */, bo_t *bo_info); + int RkRgaGetAllocBuffer(bo_t *bo_info, int width, int height, int bpp); + int RkRgaGetAllocBufferExt(bo_t *bo_info, int width, int height, int bpp, int flags); + int RkRgaGetAllocBufferCache(bo_t *bo_info, int width, int height, int bpp); + int RkRgaGetMmap(bo_t *bo_info); + int RkRgaUnmap(bo_t *bo_info); + int RkRgaFree(bo_t *bo_info); + int RkRgaGetBufferFd(bo_t *bo_info, int *fd); +#else + int RkRgaGetBufferFd(buffer_handle_t handle, int *fd); + int RkRgaGetHandleMapCpuAddress(buffer_handle_t handle, void **buf); +#endif + int RkRgaBlit(rga_info *src, rga_info *dst, rga_info *src1); + int RkRgaCollorFill(rga_info *dst); + int RkRgaCollorPalette(rga_info *src, rga_info *dst, rga_info *lut); + int RkRgaFlush(); + + + void RkRgaSetLogOnceFlag(int log) { + mLogOnce = log; + } + void RkRgaSetAlwaysLogFlag(bool log) { + mLogAlways = log; + } + void RkRgaLogOutRgaReq(struct rga_req rgaReg); + int RkRgaLogOutUserPara(rga_info *rgaInfo); + inline bool RkRgaIsReady() { + return mSupportRga; + } + + RockchipRga(); + ~RockchipRga(); + private: + bool mSupportRga; + int mLogOnce; + int mLogAlways; + void * mContext; + + friend class Singleton; + }; + +#ifdef ANDROID +}; // namespace android +#endif + +#endif + diff --git a/hardware/rga/include/drmrga.h b/hardware/rga/include/drmrga.h new file mode 100755 index 0000000000000000000000000000000000000000..c9e3ddec9b922a50bbf22db309872a49c43f3904 --- /dev/null +++ b/hardware/rga/include/drmrga.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _rk_drm_rga_ +#define _rk_drm_rga_ + +#include +//#include + +#ifdef ANDROID +#define DRMRGA_HARDWARE_MODULE_ID "librga" + +#include +#include +#include +#include +#endif + +#ifndef ANDROID /* LINUX */ +/* flip source image horizontally (around the vertical axis) */ +#define HAL_TRANSFORM_FLIP_H 0x01 +/* flip source image vertically (around the horizontal axis)*/ +#define HAL_TRANSFORM_FLIP_V 0x02 +/* rotate source image 90 degrees clockwise */ +#define HAL_TRANSFORM_ROT_90 0x04 +/* rotate source image 180 degrees */ +#define HAL_TRANSFORM_ROT_180 0x03 +/* rotate source image 270 degrees clockwise */ +#define HAL_TRANSFORM_ROT_270 0x07 +#endif + +#define HAL_TRANSFORM_FLIP_H_V 0x08 + +/*****************************************************************************/ + +/* for compatibility */ +#define DRM_RGA_MODULE_API_VERSION HWC_MODULE_API_VERSION_0_1 +#define DRM_RGA_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_1 +#define DRM_RGA_API_VERSION HWC_DEVICE_API_VERSION + +#define DRM_RGA_TRANSFORM_ROT_MASK 0x0000000F +#define DRM_RGA_TRANSFORM_ROT_0 0x00000000 +#define DRM_RGA_TRANSFORM_ROT_90 HAL_TRANSFORM_ROT_90 +#define DRM_RGA_TRANSFORM_ROT_180 HAL_TRANSFORM_ROT_180 +#define DRM_RGA_TRANSFORM_ROT_270 HAL_TRANSFORM_ROT_270 + +#define DRM_RGA_TRANSFORM_FLIP_MASK 0x00000003 +#define DRM_RGA_TRANSFORM_FLIP_H HAL_TRANSFORM_FLIP_H +#define DRM_RGA_TRANSFORM_FLIP_V HAL_TRANSFORM_FLIP_V + +enum { + AWIDTH = 0, + AHEIGHT, + ASTRIDE, + AFORMAT, + ASIZE, + ATYPE, +}; +/*****************************************************************************/ + +#ifndef ANDROID +/* memory type definitions. */ +enum drm_rockchip_gem_mem_type { + /* Physically Continuous memory and used as default. */ + ROCKCHIP_BO_CONTIG = 1 << 0, + /* cachable mapping. */ + ROCKCHIP_BO_CACHABLE = 1 << 1, + /* write-combine mapping. */ + ROCKCHIP_BO_WC = 1 << 2, + ROCKCHIP_BO_SECURE = 1 << 3, + ROCKCHIP_BO_MASK = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_CACHABLE | + ROCKCHIP_BO_WC | ROCKCHIP_BO_SECURE +}; + +typedef struct bo { + int fd; + void *ptr; + size_t size; + size_t offset; + size_t pitch; + unsigned handle; +} bo_t; +#endif + +/* + @value size: user not need care about.For avoid read/write out of memory + */ +typedef struct rga_rect { + int xoffset; + int yoffset; + int width; + int height; + int wstride; + int hstride; + int format; + int size; +} rga_rect_t; + +typedef struct rga_nn { + int nn_flag; + int scale_r; + int scale_g; + int scale_b; + int offset_r; + int offset_g; + int offset_b; +} rga_nn_t; + +typedef struct rga_dither { + int enable; + int mode; + int lut0_l; + int lut0_h; + int lut1_l; + int lut1_h; +} rga_dither_t; + +/* + @value fd: use fd to share memory, it can be ion shard fd,and dma fd. + @value virAddr:userspace address + @value phyAddr:use phy address + @value hnd: use buffer_handle_t + */ +typedef struct rga_info { + int fd; + void *virAddr; + void *phyAddr; +#ifndef ANDROID /* LINUX */ + unsigned hnd; +#else /* Android */ + buffer_handle_t hnd; +#endif + int format; + rga_rect_t rect; + unsigned int blend; + int bufferSize; + int rotation; + int color; + int testLog; + int mmuFlag; + int colorkey_en; + int colorkey_mode; + int colorkey_max; + int colorkey_min; + int scale_mode; + int color_space_mode; + int sync_mode; + rga_nn_t nn; + rga_dither_t dither; + int rop_code; + int reserve[127]; +} rga_info_t; + + +typedef struct drm_rga { + rga_rect_t src; + rga_rect_t dst; +} drm_rga_t; + +/* + @fun rga_set_rect:For use to set the rects esayly + + @param rect:The rect user want to set,like setting the src rect: + drm_rga_t rects; + rga_set_rect(rects.src,0,0,1920,1080,1920,NV12); + mean to set the src rect to the value. + */ +static inline int rga_set_rect(rga_rect_t *rect, + int x, int y, int w, int h, int sw, int sh, int f) { + if (!rect) + return -EINVAL; + + rect->xoffset = x; + rect->yoffset = y; + rect->width = w; + rect->height = h; + rect->wstride = sw; + rect->hstride = sh; + rect->format = f; + + return 0; +} + +#ifndef ANDROID /* LINUX */ +static inline void rga_set_rotation(rga_info_t *info, int angle) { + if (angle == 90) + info->rotation = HAL_TRANSFORM_ROT_90; + else if (angle == 180) + info->rotation = HAL_TRANSFORM_ROT_180; + else if (angle == 270) + info->rotation = HAL_TRANSFORM_ROT_270; +} +#endif +/*****************************************************************************/ + +#endif diff --git a/hardware/rga/include/im2d.h b/hardware/rga/include/im2d.h new file mode 100755 index 0000000000000000000000000000000000000000..da962600c8e12b9f38d7038526a0d9e8a84ad1ca --- /dev/null +++ b/hardware/rga/include/im2d.h @@ -0,0 +1,892 @@ +/* + * Copyright (C) 2020 Rockchip Electronics Co., Ltd. + * Authors: + * PutinLee + * Cerf Yu + * + * 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 _im2d_h_ +#define _im2d_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef IM_API +#define IM_API /* define API export as needed */ +#endif + +typedef enum { + /* Rotation */ + IM_HAL_TRANSFORM_ROT_90 = 1 << 0, + IM_HAL_TRANSFORM_ROT_180 = 1 << 1, + IM_HAL_TRANSFORM_ROT_270 = 1 << 2, + IM_HAL_TRANSFORM_FLIP_H = 1 << 3, + IM_HAL_TRANSFORM_FLIP_V = 1 << 4, + IM_HAL_TRANSFORM_FLIP_H_V = 1 << 5, + IM_HAL_TRANSFORM_MASK = 0x3f, + + /* + * Blend + * Additional blend usage, can be used with both source and target configs. + * If none of the below is set, the default "SRC over DST" is applied. + */ + IM_ALPHA_BLEND_SRC_OVER = 1 << 6, /* Default, Porter-Duff "SRC over DST" */ + IM_ALPHA_BLEND_SRC = 1 << 7, /* Porter-Duff "SRC" */ + IM_ALPHA_BLEND_DST = 1 << 8, /* Porter-Duff "DST" */ + IM_ALPHA_BLEND_SRC_IN = 1 << 9, /* Porter-Duff "SRC in DST" */ + IM_ALPHA_BLEND_DST_IN = 1 << 10, /* Porter-Duff "DST in SRC" */ + IM_ALPHA_BLEND_SRC_OUT = 1 << 11, /* Porter-Duff "SRC out DST" */ + IM_ALPHA_BLEND_DST_OUT = 1 << 12, /* Porter-Duff "DST out SRC" */ + IM_ALPHA_BLEND_DST_OVER = 1 << 13, /* Porter-Duff "DST over SRC" */ + IM_ALPHA_BLEND_SRC_ATOP = 1 << 14, /* Porter-Duff "SRC ATOP" */ + IM_ALPHA_BLEND_DST_ATOP = 1 << 15, /* Porter-Duff "DST ATOP" */ + IM_ALPHA_BLEND_XOR = 1 << 16, /* Xor */ + IM_ALPHA_BLEND_MASK = 0x1ffc0, + + IM_ALPHA_COLORKEY_NORMAL = 1 << 17, + IM_ALPHA_COLORKEY_INVERTED = 1 << 18, + IM_ALPHA_COLORKEY_MASK = 0x60000, + + IM_SYNC = 1 << 19, + IM_ASYNC = 1 << 26, + IM_CROP = 1 << 20, /* Unused */ + IM_COLOR_FILL = 1 << 21, + IM_COLOR_PALETTE = 1 << 22, + IM_NN_QUANTIZE = 1 << 23, + IM_ROP = 1 << 24, + IM_ALPHA_BLEND_PRE_MUL = 1 << 25, + +} IM_USAGE; + +typedef enum { + IM_ROP_AND = 0x88, + IM_ROP_OR = 0xee, + IM_ROP_NOT_DST = 0x55, + IM_ROP_NOT_SRC = 0x33, + IM_ROP_XOR = 0xf6, + IM_ROP_NOT_XOR = 0xf9, +} IM_ROP_CODE; + +typedef enum { + IM_RGA_SUPPORT_FORMAT_ERROR_INDEX = 0, + IM_RGA_SUPPORT_FORMAT_RGB_INDEX, + IM_RGA_SUPPORT_FORMAT_RGB_OTHER_INDEX, + IM_RGA_SUPPORT_FORMAT_BPP_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_8_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_10_INDEX, + IM_RGA_SUPPORT_FORMAT_YUYV_420_INDEX, + IM_RGA_SUPPORT_FORMAT_YUYV_422_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_400_INDEX, + IM_RGA_SUPPORT_FORMAT_Y4_INDEX, + IM_RGA_SUPPORT_FORMAT_MASK_INDEX, +} IM_RGA_SUPPORT_FORMAT_INDEX; + +typedef enum { + IM_RGA_SUPPORT_FORMAT_ERROR = 1 << IM_RGA_SUPPORT_FORMAT_ERROR_INDEX, + IM_RGA_SUPPORT_FORMAT_RGB = 1 << IM_RGA_SUPPORT_FORMAT_RGB_INDEX, + IM_RGA_SUPPORT_FORMAT_RGB_OTHER = 1 << IM_RGA_SUPPORT_FORMAT_RGB_OTHER_INDEX, + IM_RGA_SUPPORT_FORMAT_BPP = 1 << IM_RGA_SUPPORT_FORMAT_BPP_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_8 = 1 << IM_RGA_SUPPORT_FORMAT_YUV_8_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_10 = 1 << IM_RGA_SUPPORT_FORMAT_YUV_10_INDEX, + IM_RGA_SUPPORT_FORMAT_YUYV_420 = 1 << IM_RGA_SUPPORT_FORMAT_YUYV_420_INDEX, + IM_RGA_SUPPORT_FORMAT_YUYV_422 = 1 << IM_RGA_SUPPORT_FORMAT_YUYV_422_INDEX, + IM_RGA_SUPPORT_FORMAT_YUV_400 = 1 << IM_RGA_SUPPORT_FORMAT_YUV_400_INDEX, + IM_RGA_SUPPORT_FORMAT_Y4 = 1 << IM_RGA_SUPPORT_FORMAT_Y4_INDEX, + IM_RGA_SUPPORT_FORMAT_MASK = ~((~(unsigned int)0x0 << IM_RGA_SUPPORT_FORMAT_MASK_INDEX) | 1), +} IM_RGA_SUPPORT_FORMAT; + +typedef enum { + IM_RGA_SUPPORT_FEATURE_ERROR_INDEX = 0, + IM_RGA_SUPPORT_FEATURE_COLOR_FILL_INDEX, + IM_RGA_SUPPORT_FEATURE_COLOR_PALETTE_INDEX, + IM_RGA_SUPPORT_FEATURE_ROP_INDEX, + IM_RGA_SUPPORT_FEATURE_QUANTIZE_INDEX, + IM_RGA_SUPPORT_FEATURE_SRC1_R2Y_CSC_INDEX, + IM_RGA_SUPPORT_FEATURE_DST_FULL_CSC_INDEX, + IM_RGA_SUPPORT_FEATURE_MASK_INDEX, +} IM_RGA_SUPPORT_FEATURE_INDEX; + +typedef enum { + IM_RGA_SUPPORT_FEATURE_ERROR = 1 << IM_RGA_SUPPORT_FEATURE_ERROR_INDEX, + IM_RGA_SUPPORT_FEATURE_COLOR_FILL = 1 << IM_RGA_SUPPORT_FEATURE_COLOR_FILL_INDEX, + IM_RGA_SUPPORT_FEATURE_COLOR_PALETTE = 1 << IM_RGA_SUPPORT_FEATURE_COLOR_PALETTE_INDEX, + IM_RGA_SUPPORT_FEATURE_ROP = 1 << IM_RGA_SUPPORT_FEATURE_ROP_INDEX, + IM_RGA_SUPPORT_FEATURE_QUANTIZE = 1 << IM_RGA_SUPPORT_FEATURE_QUANTIZE_INDEX, + IM_RGA_SUPPORT_FEATURE_SRC1_R2Y_CSC = 1 << IM_RGA_SUPPORT_FEATURE_SRC1_R2Y_CSC_INDEX, + IM_RGA_SUPPORT_FEATURE_DST_FULL_CSC = 1 << IM_RGA_SUPPORT_FEATURE_DST_FULL_CSC_INDEX, + IM_RGA_SUPPORT_FEATURE_MASK = ~((~(unsigned int)0x0 << IM_RGA_SUPPORT_FEATURE_MASK_INDEX) | 1), +} IM_RGA_SUPPORT_FEATURE; + +/* Status codes, returned by any blit function */ +typedef enum { + IM_STATUS_NOERROR = 2, + IM_STATUS_SUCCESS = 1, + IM_STATUS_NOT_SUPPORTED = -1, + IM_STATUS_OUT_OF_MEMORY = -2, + IM_STATUS_INVALID_PARAM = -3, + IM_STATUS_ILLEGAL_PARAM = -4, + IM_STATUS_FAILED = 0, +} IM_STATUS; + +/* Status codes, returned by any blit function */ +typedef enum { + IM_YUV_TO_RGB_BT601_LIMIT = 1 << 0, + IM_YUV_TO_RGB_BT601_FULL = 2 << 0, + IM_YUV_TO_RGB_BT709_LIMIT = 3 << 0, + IM_YUV_TO_RGB_MASK = 3 << 0, + IM_RGB_TO_YUV_BT601_FULL = 1 << 2, + IM_RGB_TO_YUV_BT601_LIMIT = 2 << 2, + IM_RGB_TO_YUV_BT709_LIMIT = 3 << 2, + IM_RGB_TO_YUV_MASK = 3 << 2, + IM_RGB_TO_Y4 = 1 << 4, + IM_RGB_TO_Y4_DITHER = 2 << 4, + IM_RGB_TO_Y1_DITHER = 3 << 4, + IM_Y4_MASK = 3 << 4, + IM_RGB_FULL = 1 << 8, + IM_RGB_CLIP = 2 << 8, + IM_YUV_BT601_LIMIT_RANGE = 3 << 8, + IM_YUV_BT601_FULL_RANGE = 4 << 8, + IM_YUV_BT709_LIMIT_RANGE = 5 << 8, + IM_YUV_BT709_FULL_RANGE = 6 << 8, + IM_FULL_CSC_MASK = 0xf << 8, + IM_COLOR_SPACE_DEFAULT = 0, +} IM_COLOR_SPACE_MODE; + +typedef enum { + IM_UP_SCALE, + IM_DOWN_SCALE, +} IM_SCALE; + +typedef enum { + INTER_NEAREST, + INTER_LINEAR, + INTER_CUBIC, +} IM_SCALE_MODE; + +/* Get RGA basic information index */ +typedef enum { + RGA_VENDOR = 0, + RGA_VERSION, + RGA_MAX_INPUT, + RGA_MAX_OUTPUT, + RGA_SCALE_LIMIT, + RGA_INPUT_FORMAT, + RGA_OUTPUT_FORMAT, + RGA_FEATURE, + RGA_EXPECTED, + RGA_ALL, +} IM_INFORMATION; + +/*rga version index*/ +typedef enum { + RGA_V_ERR = 0x0, + RGA_1 = 0x1, + RGA_1_PLUS = 0x2, + RGA_2 = 0x3, + RGA_2_LITE0 = 0x4, + RGA_2_LITE1 = 0x5, + RGA_2_ENHANCE = 0x6, +} RGA_VERSION_NUM; + +//struct AHardwareBuffer AHardwareBuffer; + +typedef struct { + RGA_VERSION_NUM version; + unsigned int input_resolution; + unsigned int output_resolution; + unsigned int scale_limit; + unsigned int performance; + unsigned int input_format; + unsigned int output_format; + unsigned int feature; + char reserved[28]; +} rga_info_table_entry; + +/* Rectangle definition */ +typedef struct { + int x; /* upper-left x */ + int y; /* upper-left y */ + int width; /* width */ + int height; /* height */ +} im_rect; + +typedef struct { + int max; /* The Maximum value of the color key */ + int min; /* The minimum value of the color key */ +} im_colorkey_range; + + +typedef struct im_nn { + int scale_r; /* scaling factor on R channal */ + int scale_g; /* scaling factor on G channal */ + int scale_b; /* scaling factor on B channal */ + int offset_r; /* offset on R channal */ + int offset_g; /* offset on G channal */ + int offset_b; /* offset on B channal */ +} im_nn_t; + +/* im_info definition */ +typedef struct { + void* vir_addr; /* virtual address */ + void* phy_addr; /* physical address */ + int fd; /* shared fd */ + int width; /* width */ + int height; /* height */ + int wstride; /* wstride */ + int hstride; /* hstride */ + int format; /* format */ + int color_space_mode; /* color_space_mode */ + int color; /* color, used by color fill */ + int global_alpha; /* global_alpha */ + im_colorkey_range colorkey_range; /* range value of color key */ + im_nn_t nn; + int rop_code; +} rga_buffer_t; + +/* + * @return error message string + */ +#define imStrError(...) \ + ({ \ + const char* err; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + err = imStrError_t(IM_STATUS_INVALID_PARAM); \ + } else if (argc == 1){ \ + err = imStrError_t((IM_STATUS)args[0]); \ + } else { \ + err = ("Fatal error, imStrError() too many parameters\n"); \ + printf("Fatal error, imStrError() too many parameters\n"); \ + } \ + err; \ + }) +IM_API const char* imStrError_t(IM_STATUS status); + +/* + * @return rga_buffer_t + */ +#define wrapbuffer_virtualaddr(vir_addr, width, height, format, ...) \ + ({ \ + rga_buffer_t buffer; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + buffer = wrapbuffer_virtualaddr_t(vir_addr, width, height, width, height, format); \ + } else if (argc == 2){ \ + buffer = wrapbuffer_virtualaddr_t(vir_addr, width, height, args[0], args[1], format); \ + } else { \ + printf("invalid parameter\n"); \ + } \ + buffer; \ + }) + +#define wrapbuffer_physicaladdr(phy_addr, width, height, format, ...) \ + ({ \ + rga_buffer_t buffer; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + buffer = wrapbuffer_physicaladdr_t(phy_addr, width, height, width, height, format); \ + } else if (argc == 2){ \ + buffer = wrapbuffer_physicaladdr_t(phy_addr, width, height, args[0], args[1], format); \ + } else { \ + printf("invalid parameter\n"); \ + } \ + buffer; \ + }) + +#define wrapbuffer_fd(fd, width, height, format, ...) \ + ({ \ + rga_buffer_t buffer; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + buffer = wrapbuffer_fd_t(fd, width, height, width, height, format); \ + } else if (argc == 2){ \ + buffer = wrapbuffer_fd_t(fd, width, height, args[0], args[1], format); \ + } else { \ + printf("invalid parameter\n"); \ + } \ + buffer; \ + }) + +IM_API rga_buffer_t wrapbuffer_virtualaddr_t(void* vir_addr, int width, int height, int wstride, int hstride, int format); +IM_API rga_buffer_t wrapbuffer_physicaladdr_t(void* phy_addr, int width, int height, int wstride, int hstride, int format); +IM_API rga_buffer_t wrapbuffer_fd_t(int fd, int width, int height, int wstride, int hstride, int format); + +/* + * Get RGA basic information, supported resolution, supported format, etc. + * + * @param name + * RGA_VENDOR + * RGA_VERSION + * RGA_MAX_INPUT + * RGA_MAX_OUTPUT + * RGA_INPUT_FORMAT + * RGA_OUTPUT_FORMAT + * RGA_EXPECTED + * RGA_ALL + * + * @returns a usage describing properties of RGA. + */ +//IM_API int rga_get_info(rga_info_table_entry *); +IM_API IM_STATUS rga_get_info(rga_info_table_entry *return_table); + +/* + * Query RGA basic information, supported resolution, supported format, etc. + * + * @param name + * RGA_VENDOR + * RGA_VERSION + * RGA_MAX_INPUT + * RGA_MAX_OUTPUT + * RGA_INPUT_FORMAT + * RGA_OUTPUT_FORMAT + * RGA_EXPECTED + * RGA_ALL + * + * @returns a string describing properties of RGA. + */ +IM_API const char* querystring(int name); + +/* + * check RGA basic information, supported resolution, supported format, etc. + * + * @param src + * @param dst + * @param src_rect + * @param dst_rect + * @param mode_usage + * + * @returns no error or else negative error code. + */ +#define imcheck(src, dst, src_rect, dst_rect, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_NOERROR; \ + rga_buffer_t pat; \ + im_rect pat_rect; \ + memset(&pat, 0, sizeof(rga_buffer_t)); \ + memset(&pat_rect, 0, sizeof(im_rect)); \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcheck_t(src, dst, pat, src_rect, dst_rect, pat_rect, 0); \ + } else if (argc == 1){ \ + ret = imcheck_t(src, dst, pat, src_rect, dst_rect, pat_rect, args[0]); \ + } else { \ + ret = IM_STATUS_FAILED; \ + printf("check failed\n"); \ + } \ + ret; \ + }) +#define imcheck_composite(src, dst, pat, src_rect, dst_rect, pat_rect, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_NOERROR; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcheck_t(src, dst, pat, src_rect, dst_rect, pat_rect, 0); \ + } else if (argc == 1){ \ + ret = imcheck_t(src, dst, pat, src_rect, dst_rect, pat_rect, args[0]); \ + } else { \ + ret = IM_STATUS_FAILED; \ + printf("check failed\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imcheck_t(const rga_buffer_t src, const rga_buffer_t dst, const rga_buffer_t pat, + const im_rect src_rect, const im_rect dst_rect, const im_rect pat_rect, const int mdoe_usage); + +/* + * Resize + * + * @param src + * @param dst + * @param fx + * @param fy + * @param interpolation + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imresize(src, dst, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + double args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(double); \ + if (argc == 0) { \ + ret = imresize_t(src, dst, 0, 0, INTER_LINEAR, 1); \ + } else if (argc == 2){ \ + ret = imresize_t(src, dst, args[0], args[1], INTER_LINEAR, 1); \ + } else if (argc == 3){ \ + ret = imresize_t(src, dst, args[0], args[1], (int)args[2], 1); \ + } else if (argc == 4){ \ + ret = imresize_t(src, dst, args[0], args[1], (int)args[2], (int)args[3]); \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +#define impyramid(src, dst, direction) \ + imresize_t(src, \ + dst, \ + direction == IM_UP_SCALE ? 0.5 : 2, \ + direction == IM_UP_SCALE ? 0.5 : 2, \ + INTER_LINEAR, 1) + +IM_API IM_STATUS imresize_t(const rga_buffer_t src, rga_buffer_t dst, double fx, double fy, int interpolation, int sync); + +/* + * Crop + * + * @param src + * @param dst + * @param rect + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imcrop(src, dst, rect, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcrop_t(src, dst, rect, 1); \ + } else if (argc == 1){ \ + ret = imcrop_t(src, dst, rect, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imcrop_t(const rga_buffer_t src, rga_buffer_t dst, im_rect rect, int sync); + +/* + * rotation + * + * @param src + * @param dst + * @param rotation + * IM_HAL_TRANSFORM_ROT_90 + * IM_HAL_TRANSFORM_ROT_180 + * IM_HAL_TRANSFORM_ROT_270 + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imrotate(src, dst, rotation, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imrotate_t(src, dst, rotation, 1); \ + } else if (argc == 1){ \ + ret = imrotate_t(src, dst, rotation, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imrotate_t(const rga_buffer_t src, rga_buffer_t dst, int rotation, int sync); + +/* + * flip + * + * @param src + * @param dst + * @param mode + * IM_HAL_TRANSFORM_FLIP_H + * IM_HAL_TRANSFORM_FLIP_V + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imflip(src, dst, mode, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imflip_t(src, dst, mode, 1); \ + } else if (argc == 1){ \ + ret = imflip_t(src, dst, mode, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imflip_t (const rga_buffer_t src, rga_buffer_t dst, int mode, int sync); + +/* + * fill/reset/draw + * + * @param src + * @param dst + * @param rect + * @param color + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imfill(buf, rect, color, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imfill_t(buf, rect, color, 1); \ + } else if (argc == 1){ \ + ret = imfill_t(buf, rect, color, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +#define imreset(buf, rect, color, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imfill_t(buf, rect, color, 1); \ + } else if (argc == 1){ \ + ret = imfill_t(buf, rect, color, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +#define imdraw(buf, rect, color, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imfill_t(buf, rect, color, 1); \ + } else if (argc == 1){ \ + ret = imfill_t(buf, rect, color, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imfill_t(rga_buffer_t dst, im_rect rect, int color, int sync); + +/* + * palette + * + * @param src + * @param dst + * @param lut + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define impalette(src, dst, lut, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = impalette_t(src, dst, lut, 1); \ + } else if (argc == 1){ \ + ret = impalette_t(src, dst, lut, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS impalette_t(rga_buffer_t src, rga_buffer_t dst, rga_buffer_t lut, int sync); + +/* + * translate + * + * @param src + * @param dst + * @param x + * @param y + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imtranslate(src, dst, x, y, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imtranslate_t(src, dst, x, y, 1); \ + } else if (argc == 1){ \ + ret = imtranslate_t(src, dst, x, y, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imtranslate_t(const rga_buffer_t src, rga_buffer_t dst, int x, int y, int sync); + +/* + * copy + * + * @param src + * @param dst + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imcopy(src, dst, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcopy_t(src, dst, 1); \ + } else if (argc == 1){ \ + ret = imcopy_t(src, dst, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imcopy_t(const rga_buffer_t src, rga_buffer_t dst, int sync); + +/* + * blend (SRC + DST -> DST or SRCA + SRCB -> DST) + * + * @param srcA + * @param srcB can be NULL. + * @param dst + * @param mode + * IM_ALPHA_BLEND_MODE + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imblend(srcA, dst, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + rga_buffer_t srcB; \ + memset(&srcB, 0x00, sizeof(rga_buffer_t)); \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imblend_t(srcA, srcB, dst, IM_ALPHA_BLEND_SRC_OVER, 1); \ + } else if (argc == 1){ \ + ret = imblend_t(srcA, srcB, dst, args[0], 1); \ + } else if (argc == 2){ \ + ret = imblend_t(srcA, srcB, dst, args[0], args[1]); \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +#define imcomposite(srcA, srcB, dst, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imblend_t(srcA, srcB, dst, IM_ALPHA_BLEND_SRC_OVER, 1); \ + } else if (argc == 1){ \ + ret = imblend_t(srcA, srcB, dst, args[0], 1); \ + } else if (argc == 2){ \ + ret = imblend_t(srcA, srcB, dst, args[0], args[1]); \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imblend_t(const rga_buffer_t srcA, const rga_buffer_t srcB, rga_buffer_t dst, int mode, int sync); + +/* + * color key + * + * @param src + * @param dst + * @param colorkey_range + * max color + * min color + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imcolorkey(src, dst, range, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcolorkey_t(src, dst, range, IM_ALPHA_COLORKEY_NORMAL, 1); \ + } else if (argc == 1){ \ + ret = imcolorkey_t(src, dst, range, args[0], 1); \ + } else if (argc == 2){ \ + ret = imcolorkey_t(src, dst, range, args[0], args[1]); \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imcolorkey_t(const rga_buffer_t src, rga_buffer_t dst, im_colorkey_range range, int mode, int sync); + +/* + * format convert + * + * @param src + * @param dst + * @param sfmt + * @param dfmt + * @param mode + * color space mode: IM_COLOR_SPACE_MODE + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imcvtcolor(src, dst, sfmt, dfmt, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imcvtcolor_t(src, dst, sfmt, dfmt, IM_COLOR_SPACE_DEFAULT, 1); \ + } else if (argc == 1){ \ + ret = imcvtcolor_t(src, dst, sfmt, dfmt, args[0], 1); \ + } else if (argc == 2){ \ + ret = imcvtcolor_t(src, dst, sfmt, dfmt, args[0], args[1]); \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imcvtcolor_t(rga_buffer_t src, rga_buffer_t dst, int sfmt, int dfmt, int mode, int sync); + +/* + * nn quantize + * + * @param src + * @param dst + * @param nninfo + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imquantize(src, dst, nn_info, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imquantize_t(src, dst, nn_info, 1); \ + } else if (argc == 1){ \ + ret = imquantize_t(src, dst, nn_info, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) + +IM_API IM_STATUS imquantize_t(const rga_buffer_t src, rga_buffer_t dst, im_nn_t nn_info, int sync); + +/* + * ROP + * + * @param src + * @param dst + * @param rop_code + * @param sync + * wait until operation complete + * + * @returns success or else negative error code. + */ +#define imrop(src, dst, rop_code, ...) \ + ({ \ + IM_STATUS ret = IM_STATUS_SUCCESS; \ + int args[] = {__VA_ARGS__}; \ + int argc = sizeof(args)/sizeof(int); \ + if (argc == 0) { \ + ret = imrop_t(src, dst, rop_code, 1); \ + } else if (argc == 1){ \ + ret = imrop_t(src, dst, rop_code, args[0]);; \ + } else { \ + ret = IM_STATUS_INVALID_PARAM; \ + printf("invalid parameter\n"); \ + } \ + ret; \ + }) +IM_API IM_STATUS imrop_t(const rga_buffer_t src, rga_buffer_t dst, int rop_code, int sync); + +/* + * process + * + * @param src + * @param dst + * @param usage + * @param ... + * wait until operation complete + * + * @returns success or else negative error code. + */ +IM_API IM_STATUS improcess(rga_buffer_t src, rga_buffer_t dst, rga_buffer_t pat, im_rect srect, im_rect drect, im_rect prect, int usage); + +/* + * block until all execution is complete + * + * @returns success or else negative error code. + */ +IM_API IM_STATUS imsync(void); + +#ifdef __cplusplus +} +#endif +#endif /* _im2d_h_ */ + diff --git a/hardware/rga/include/platform_gralloc4.h b/hardware/rga/include/platform_gralloc4.h new file mode 100755 index 0000000000000000000000000000000000000000..989687c1cbd330545e694999c1735d45a1d6a960 --- /dev/null +++ b/hardware/rga/include/platform_gralloc4.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2017-2018 RockChip Limited. All rights reserved. + * + * 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. + */ + +/* -------------------------------------------------------------------------------------------------------- + * File: platform_gralloc4.h + * + * Desc: 声明对 buffer_handle_t 实例的 get metadata, import_buffer/free_buffer, lock_buffer/unlock_buffer 等接口. + * 这些接口都将基于 IMapper 4.0 (gralloc 4.0) 实现. + * + * ----------------------------------------------------------------------------------- + * < 习语 和 缩略语 > : + * + * ----------------------------------------------------------------------------------- + * Usage: + * + * Note: + * + * Author: ChenZhen + * + * Log: + * init. + ----Fri Aug 28 10:10:14 2020 + * + * -------------------------------------------------------------------------------------------------------- + */ + + +#ifndef __PLATFORM_GRALLOC4_H__ +#define __PLATFORM_GRALLOC4_H__ + + +/* --------------------------------------------------------------------------------------------------------- + * Include Files + * --------------------------------------------------------------------------------------------------------- + */ +// #include + +#include + +#include +#include + +#include + +/* --------------------------------------------------------------------------------------------------------- + * Macros Definition + * --------------------------------------------------------------------------------------------------------- + */ + + +namespace gralloc4 { +/* --------------------------------------------------------------------------------------------------------- + * Types and Structures Definition + * --------------------------------------------------------------------------------------------------------- + */ + + +/* --------------------------------------------------------------------------------------------------------- + * Global Functions' Prototype + * --------------------------------------------------------------------------------------------------------- + */ + +/* + * 获取 'handle' 引用的 graphic_buffer 的 internal_format. + */ +uint64_t get_internal_format(buffer_handle_t handle); + +int get_width(buffer_handle_t handle, uint64_t* width); + +int get_height(buffer_handle_t handle, uint64_t* height); + +int get_pixel_stride(buffer_handle_t handle, int* pixel_stride); + +int get_byte_stride(buffer_handle_t handle, int* byte_stride); + +int get_format_requested(buffer_handle_t handle, int* format_requested); + +int get_usage(buffer_handle_t handle, uint64_t* usage); + +int get_allocation_size(buffer_handle_t handle, uint64_t* usage); + +int get_share_fd(buffer_handle_t handle, int* share_fd); + +using android::status_t; + +status_t importBuffer(buffer_handle_t rawHandle, buffer_handle_t* outHandle); + +void freeBuffer(buffer_handle_t handle); + +status_t lock(buffer_handle_t bufferHandle, + uint64_t usage, + int x, + int y, + int w, + int h, + void** outData); + +void unlock(buffer_handle_t bufferHandle); + +/* --------------------------------------------------------------------------------------------------------- + * Inline Functions Implementation + * --------------------------------------------------------------------------------------------------------- + */ + +} + +#endif /* __PLATFORM_GRALLOC4_H__ */ + diff --git a/hardware/rga/include/rga.h b/hardware/rga/include/rga.h new file mode 100755 index 0000000000000000000000000000000000000000..e251d8f86a2e6bcf9b7e1dfe8d03e2a0909dada6 --- /dev/null +++ b/hardware/rga/include/rga.h @@ -0,0 +1,795 @@ +/* + * Copyright (C) 2016 Rockchip Electronics Co., Ltd. + * Authors: + * Zhiqin Wei + * + * 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 _RGA_DRIVER_H_ +#define _RGA_DRIVER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#define RGA_BLIT_SYNC 0x5017 +#define RGA_BLIT_ASYNC 0x5018 +#define RGA_FLUSH 0x5019 +#define RGA_GET_RESULT 0x501a +#define RGA_GET_VERSION 0x501b + +#define RGA2_BLIT_SYNC 0x6017 +#define RGA2_BLIT_ASYNC 0x6018 +#define RGA2_FLUSH 0x6019 +#define RGA2_GET_RESULT 0x601a +#define RGA2_GET_VERSION 0x601b +#define RGA2_GET_VERSION 0x601b + +#define RGA_REG_CTRL_LEN 0x8 /* 8 */ +#define RGA_REG_CMD_LEN 0x1c /* 28 */ +#define RGA_CMD_BUF_SIZE 0x700 /* 16*28*4 */ + + + +#ifndef ENABLE +#define ENABLE 1 +#endif + + +#ifndef DISABLE +#define DISABLE 0 +#endif + + + +/* RGA process mode enum */ +enum { + bitblt_mode = 0x0, + color_palette_mode = 0x1, + color_fill_mode = 0x2, + line_point_drawing_mode = 0x3, + blur_sharp_filter_mode = 0x4, + pre_scaling_mode = 0x5, + update_palette_table_mode = 0x6, + update_patten_buff_mode = 0x7, +}; + + +enum { + rop_enable_mask = 0x2, + dither_enable_mask = 0x8, + fading_enable_mask = 0x10, + PD_enbale_mask = 0x20, +}; + +enum { + yuv2rgb_mode0 = 0x0, /* BT.601 MPEG */ + yuv2rgb_mode1 = 0x1, /* BT.601 JPEG */ + yuv2rgb_mode2 = 0x2, /* BT.709 */ + + rgb2yuv_601_full = 0x1 << 8, + rgb2yuv_709_full = 0x2 << 8, + yuv2yuv_601_limit_2_709_limit = 0x3 << 8, + yuv2yuv_601_limit_2_709_full = 0x4 << 8, + yuv2yuv_709_limit_2_601_limit = 0x5 << 8, + yuv2yuv_709_limit_2_601_full = 0x6 << 8, //not support + yuv2yuv_601_full_2_709_limit = 0x7 << 8, + yuv2yuv_601_full_2_709_full = 0x8 << 8, //not support + yuv2yuv_709_full_2_601_limit = 0x9 << 8, //not support + yuv2yuv_709_full_2_601_full = 0xa << 8, //not support + full_csc_mask = 0xf00, +}; + +/* RGA rotate mode */ +enum { + rotate_mode0 = 0x0, /* no rotate */ + rotate_mode1 = 0x1, /* rotate */ + rotate_mode2 = 0x2, /* x_mirror */ + rotate_mode3 = 0x3, /* y_mirror */ +}; + +enum { + color_palette_mode0 = 0x0, /* 1K */ + color_palette_mode1 = 0x1, /* 2K */ + color_palette_mode2 = 0x2, /* 4K */ + color_palette_mode3 = 0x3, /* 8K */ +}; + +enum { + BB_BYPASS = 0x0, /* no rotate */ + BB_ROTATE = 0x1, /* rotate */ + BB_X_MIRROR = 0x2, /* x_mirror */ + BB_Y_MIRROR = 0x3 /* y_mirror */ +}; + +enum { + nearby = 0x0, /* no rotate */ + bilinear = 0x1, /* rotate */ + bicubic = 0x2, /* x_mirror */ +}; + + + + + +/* +// Alpha Red Green Blue +{ 4, 32, {{32,24, 8, 0, 16, 8, 24,16 }}, GGL_RGBA }, // RK_FORMAT_RGBA_8888 +{ 4, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGBX_8888 +{ 3, 24, {{ 0, 0, 8, 0, 16, 8, 24,16 }}, GGL_RGB }, // RK_FORMAT_RGB_888 +{ 4, 32, {{32,24, 24,16, 16, 8, 8, 0 }}, GGL_BGRA }, // RK_FORMAT_BGRA_8888 +{ 2, 16, {{ 0, 0, 16,11, 11, 5, 5, 0 }}, GGL_RGB }, // RK_FORMAT_RGB_565 +{ 2, 16, {{ 1, 0, 16,11, 11, 6, 6, 1 }}, GGL_RGBA }, // RK_FORMAT_RGBA_5551 +{ 2, 16, {{ 4, 0, 16,12, 12, 8, 8, 4 }}, GGL_RGBA }, // RK_FORMAT_RGBA_4444 +{ 3, 24, {{ 0, 0, 24,16, 16, 8, 8, 0 }}, GGL_BGR }, // RK_FORMAT_BGB_888 + +*/ +/* In order to be compatible with RK_FORMAT_XX and HAL_PIXEL_FORMAT_XX, + * RK_FORMAT_XX is shifted to the left by 8 bits to distinguish. */ +typedef enum _Rga_SURF_FORMAT { + RK_FORMAT_RGBA_8888 = 0x0 << 8, + RK_FORMAT_RGBX_8888 = 0x1 << 8, + RK_FORMAT_RGB_888 = 0x2 << 8, + RK_FORMAT_BGRA_8888 = 0x3 << 8, + RK_FORMAT_RGB_565 = 0x4 << 8, + RK_FORMAT_RGBA_5551 = 0x5 << 8, + RK_FORMAT_RGBA_4444 = 0x6 << 8, + RK_FORMAT_BGR_888 = 0x7 << 8, + + RK_FORMAT_YCbCr_422_SP = 0x8 << 8, + RK_FORMAT_YCbCr_422_P = 0x9 << 8, + RK_FORMAT_YCbCr_420_SP = 0xa << 8, + RK_FORMAT_YCbCr_420_P = 0xb << 8, + + RK_FORMAT_YCrCb_422_SP = 0xc << 8, + RK_FORMAT_YCrCb_422_P = 0xd << 8, + RK_FORMAT_YCrCb_420_SP = 0xe << 8, + RK_FORMAT_YCrCb_420_P = 0xf << 8, + + RK_FORMAT_BPP1 = 0x10 << 8, + RK_FORMAT_BPP2 = 0x11 << 8, + RK_FORMAT_BPP4 = 0x12 << 8, + RK_FORMAT_BPP8 = 0x13 << 8, + + RK_FORMAT_Y4 = 0x14 << 8, + RK_FORMAT_YCbCr_400 = 0x15 << 8, + + RK_FORMAT_BGRX_8888 = 0x16 << 8, + + RK_FORMAT_YVYU_422 = 0x18 << 8, + RK_FORMAT_YVYU_420 = 0x19 << 8, + RK_FORMAT_VYUY_422 = 0x1a << 8, + RK_FORMAT_VYUY_420 = 0x1b << 8, + RK_FORMAT_YUYV_422 = 0x1c << 8, + RK_FORMAT_YUYV_420 = 0x1d << 8, + RK_FORMAT_UYVY_422 = 0x1e << 8, + RK_FORMAT_UYVY_420 = 0x1f << 8, + + RK_FORMAT_YCbCr_420_SP_10B = 0x20 << 8, + RK_FORMAT_YCrCb_420_SP_10B = 0x21 << 8, + RK_FORMAT_YCbCr_422_10b_SP = 0x22 << 8, + RK_FORMAT_YCrCb_422_10b_SP = 0x23 << 8, + + RK_FORMAT_BGR_565 = 0x24 << 8, + RK_FORMAT_BGRA_5551 = 0x25 << 8, + RK_FORMAT_BGRA_4444 = 0x26 << 8, + RK_FORMAT_UNKNOWN = 0x100 << 8, +} RgaSURF_FORMAT; + + +typedef struct rga_img_info_t { +#if defined(__arm64__) || defined(__aarch64__) + unsigned long yrgb_addr; /* yrgb mem addr */ + unsigned long uv_addr; /* cb/cr mem addr */ + unsigned long v_addr; /* cr mem addr */ +#else + unsigned int yrgb_addr; /* yrgb mem addr */ + unsigned int uv_addr; /* cb/cr mem addr */ + unsigned int v_addr; /* cr mem addr */ +#endif + unsigned int format; //definition by RK_FORMAT + unsigned short act_w; + unsigned short act_h; + unsigned short x_offset; + unsigned short y_offset; + + unsigned short vir_w; + unsigned short vir_h; + + unsigned short endian_mode; //for BPP + unsigned short alpha_swap; +} +rga_img_info_t; + + +typedef struct mdp_img_act { + unsigned short w; // width + unsigned short h; // height + short x_off; // x offset for the vir + short y_off; // y offset for the vir +} +mdp_img_act; + + + +typedef struct RANGE { + unsigned short min; + unsigned short max; +} +RANGE; + +typedef struct POINT { + unsigned short x; + unsigned short y; +} +POINT; + +typedef struct RECT { + unsigned short xmin; + unsigned short xmax; // width - 1 + unsigned short ymin; + unsigned short ymax; // height - 1 +} RECT; + +typedef struct RGB { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char res; +}RGB; + + +typedef struct MMU { + unsigned char mmu_en; +#if defined(__arm64__) || defined(__aarch64__) + unsigned long base_addr; +#else + unsigned int base_addr; +#endif + unsigned int mmu_flag; /* [0] mmu enable [1] src_flush [2] dst_flush [3] CMD_flush [4~5] page size*/ +} MMU; + + + + +typedef struct COLOR_FILL { + short gr_x_a; + short gr_y_a; + short gr_x_b; + short gr_y_b; + short gr_x_g; + short gr_y_g; + short gr_x_r; + short gr_y_r; + + //u8 cp_gr_saturation; +} +COLOR_FILL; + +typedef struct FADING { + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char res; +} +FADING; + + +typedef struct line_draw_t { + POINT start_point; /* LineDraw_start_point */ + POINT end_point; /* LineDraw_end_point */ + unsigned int color; /* LineDraw_color */ + unsigned int flag; /* (enum) LineDrawing mode sel */ + unsigned int line_width; /* range 1~16 */ +} +line_draw_t; + +/* color space convert coefficient. */ +typedef struct csc_coe_t { + int16_t r_v; + int16_t g_y; + int16_t b_u; + int32_t off; +} csc_coe_t; + +typedef struct full_csc_t { + unsigned char flag; + csc_coe_t coe_y; + csc_coe_t coe_u; + csc_coe_t coe_v; +} full_csc_t; + +struct rga_req { + unsigned char render_mode; /* (enum) process mode sel */ + + rga_img_info_t src; /* src image info */ + rga_img_info_t dst; /* dst image info */ + rga_img_info_t pat; /* patten image info */ + +#if defined(__arm64__) || defined(__aarch64__) + unsigned long rop_mask_addr; /* rop4 mask addr */ + unsigned long LUT_addr; /* LUT addr */ +#else + unsigned int rop_mask_addr; /* rop4 mask addr */ + unsigned int LUT_addr; /* LUT addr */ +#endif + + RECT clip; /* dst clip window default value is dst_vir */ + /* value from [0, w-1] / [0, h-1]*/ + + int sina; /* dst angle default value 0 16.16 scan from table */ + int cosa; /* dst angle default value 0 16.16 scan from table */ + + unsigned short alpha_rop_flag; /* alpha rop process flag */ + /* ([0] = 1 alpha_rop_enable) */ + /* ([1] = 1 rop enable) */ + /* ([2] = 1 fading_enable) */ + /* ([3] = 1 PD_enable) */ + /* ([4] = 1 alpha cal_mode_sel) */ + /* ([5] = 1 dither_enable) */ + /* ([6] = 1 gradient fill mode sel) */ + /* ([7] = 1 AA_enable) */ + /* ([8] = 1 nn_quantize) */ + /* ([9] = 1 Real color mode) */ + + unsigned char scale_mode; /* 0 nearst / 1 bilnear / 2 bicubic */ + + unsigned int color_key_max; /* color key max */ + unsigned int color_key_min; /* color key min */ + + unsigned int fg_color; /* foreground color */ + unsigned int bg_color; /* background color */ + + COLOR_FILL gr_color; /* color fill use gradient */ + + line_draw_t line_draw_info; + + FADING fading; + + unsigned char PD_mode; /* porter duff alpha mode sel */ + + unsigned char alpha_global_value; /* global alpha value */ + + unsigned short rop_code; /* rop2/3/4 code scan from rop code table*/ + + unsigned char bsfilter_flag; /* [2] 0 blur 1 sharp / [1:0] filter_type*/ + + unsigned char palette_mode; /* (enum) color palatte 0/1bpp, 1/2bpp 2/4bpp 3/8bpp*/ + + unsigned char yuv2rgb_mode; /* (enum) BT.601 MPEG / BT.601 JPEG / BT.709 */ + + unsigned char endian_mode; /* 0/big endian 1/little endian*/ + + unsigned char rotate_mode; /* (enum) rotate mode */ + /* 0x0, no rotate */ + /* 0x1, rotate */ + /* 0x2, x_mirror */ + /* 0x3, y_mirror */ + + unsigned char color_fill_mode; /* 0 solid color / 1 patten color */ + + MMU mmu_info; /* mmu information */ + + unsigned char alpha_rop_mode; /* ([0~1] alpha mode) */ + /* ([2~3] rop mode) */ + /* ([4] zero mode en) */ + /* ([5] dst alpha mode) (RGA1) */ + + unsigned char src_trans_mode; + + unsigned char dither_mode; + + full_csc_t full_csc; /* full color space convert */ + + unsigned char CMD_fin_int_enable; + + /* completion is reported through a callback */ + void (*complete)(int retval); +}; + +#if 0 +typedef struct TILE_INFO { + int64_t matrix[4]; + + uint16_t tile_x_num; /* x axis tile num / tile size is 8x8 pixel */ + uint16_t tile_y_num; /* y axis tile num */ + + int16_t dst_x_tmp; /* dst pos x = (xstart - xoff) default value 0 */ + int16_t dst_y_tmp; /* dst pos y = (ystart - yoff) default value 0 */ + + uint16_t tile_w; + uint16_t tile_h; + int16_t tile_start_x_coor; + int16_t tile_start_y_coor; + int32_t tile_xoff; + int32_t tile_yoff; + + int32_t tile_temp_xstart; + int32_t tile_temp_ystart; + + /* src tile incr */ + int32_t x_dx; + int32_t x_dy; + int32_t y_dx; + int32_t y_dy; + + mdp_img_act dst_ctrl; + +} +TILE_INFO; +#endif + +#if 0 + +#define RGA_BASE 0x10114000 + +//General Registers +#define RGA_SYS_CTRL 0x000 +#define RGA_CMD_CTRL 0x004 +#define RGA_CMD_ADDR 0x008 +#define RGA_STATUS 0x00c +#define RGA_INT 0x010 +#define RGA_AXI_ID 0x014 +#define RGA_MMU_STA_CTRL 0x018 +#define RGA_MMU_STA 0x01c + +//Command code start +#define RGA_MODE_CTRL 0x100 + +//Source Image Registers +#define RGA_SRC_Y_MST 0x104 +#define RGA_SRC_CB_MST 0x108 +#define RGA_MASK_READ_MST 0x108 //repeat +#define RGA_SRC_CR_MST 0x10c +#define RGA_SRC_VIR_INFO 0x110 +#define RGA_SRC_ACT_INFO 0x114 +#define RGA_SRC_X_PARA 0x118 +#define RGA_SRC_Y_PARA 0x11c +#define RGA_SRC_TILE_XINFO 0x120 +#define RGA_SRC_TILE_YINFO 0x124 +#define RGA_SRC_TILE_H_INCR 0x128 +#define RGA_SRC_TILE_V_INCR 0x12c +#define RGA_SRC_TILE_OFFSETX 0x130 +#define RGA_SRC_TILE_OFFSETY 0x134 +#define RGA_SRC_BG_COLOR 0x138 +#define RGA_SRC_FG_COLOR 0x13c +#define RGA_LINE_DRAWING_COLOR 0x13c //repeat +#define RGA_SRC_TR_COLOR0 0x140 +#define RGA_CP_GR_A 0x140 //repeat +#define RGA_SRC_TR_COLOR1 0x144 +#define RGA_CP_GR_B 0x144 //repeat + +#define RGA_LINE_DRAW 0x148 +#define RGA_PAT_START_POINT 0x148 //repeat + +//Destination Image Registers +#define RGA_DST_MST 0x14c +#define RGA_LUT_MST 0x14c //repeat +#define RGA_PAT_MST 0x14c //repeat +#define RGA_LINE_DRAWING_MST 0x14c //repeat + +#define RGA_DST_VIR_INFO 0x150 + +#define RGA_DST_CTR_INFO 0x154 +#define RGA_LINE_DRAW_XY_INFO 0x154 //repeat + +//Alpha/ROP Registers +#define RGA_ALPHA_CON 0x158 + +#define RGA_PAT_CON 0x15c +#define RGA_DST_VIR_WIDTH_PIX 0x15c //repeat + +#define RGA_ROP_CON0 0x160 +#define RGA_CP_GR_G 0x160 //repeat +#define RGA_PRESCL_CB_MST 0x160 //repeat + +#define RGA_ROP_CON1 0x164 +#define RGA_CP_GR_R 0x164 //repeat +#define RGA_PRESCL_CR_MST 0x164 //repeat + +//MMU Register +#define RGA_FADING_CON 0x168 +#define RGA_MMU_CTRL 0x168 //repeat + +#define RGA_MMU_TBL 0x16c //repeat + + +#define RGA_BLIT_COMPLETE_EVENT 1 + +#endif + +int +RGA_set_src_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ +); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ +); +#else +int +RGA_set_src_vir_info( + struct rga_req *req, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + unsigned char format, /* format */ + unsigned char a_swap_en /* only for 32bit RGB888 format */ +); +#endif + +int +RGA_set_dst_act_info( + struct rga_req *req, + unsigned int width, /* act width */ + unsigned int height, /* act height */ + unsigned int x_off, /* x_off */ + unsigned int y_off /* y_off */ +); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned long yrgb_addr, /* yrgb_addr */ + unsigned long uv_addr, /* uv_addr */ + unsigned long v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en +); +#else +int +RGA_set_dst_vir_info( + struct rga_req *msg, + unsigned int yrgb_addr, /* yrgb_addr */ + unsigned int uv_addr, /* uv_addr */ + unsigned int v_addr, /* v_addr */ + unsigned int vir_w, /* vir width */ + unsigned int vir_h, /* vir height */ + RECT *clip, /* clip window */ + unsigned char format, /* format */ + unsigned char a_swap_en +); +#endif + +int +RGA_set_pat_info( + struct rga_req *msg, + unsigned int width, + unsigned int height, + unsigned int x_off, + unsigned int y_off, + unsigned int pat_format +); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned long rop_mask_addr, + unsigned int rop_mask_endian_mode +); +#else +int +RGA_set_rop_mask_info( + struct rga_req *msg, + unsigned int rop_mask_addr, + unsigned int rop_mask_endian_mode +); +#endif + +int RGA_set_alpha_en_info( + struct rga_req *msg, + unsigned int alpha_cal_mode, /* 0:alpha' = alpha + (alpha>>7) | alpha' = alpha */ + unsigned int alpha_mode, /* 0 global alpha / 1 per pixel alpha / 2 mix mode */ + unsigned int global_a_value, + unsigned int PD_en, /* porter duff alpha mode en */ + unsigned int PD_mode, + unsigned int dst_alpha_en ); /* use dst alpha */ + +int +RGA_set_rop_en_info( + struct rga_req *msg, + unsigned int ROP_mode, + unsigned int ROP_code, + unsigned int color_mode, + unsigned int solid_color +); + + +int +RGA_set_fading_en_info( + struct rga_req *msg, + unsigned char r, + unsigned char g, + unsigned char b +); + +int +RGA_set_src_trans_mode_info( + struct rga_req *msg, + unsigned char trans_mode, + unsigned char a_en, + unsigned char b_en, + unsigned char g_en, + unsigned char r_en, + unsigned char color_key_min, + unsigned char color_key_max, + unsigned char zero_mode_en +); + + +int +RGA_set_bitblt_mode( + struct rga_req *msg, + unsigned char scale_mode, // 0/near 1/bilnear 2/bicubic + unsigned char rotate_mode, // 0/copy 1/rotate_scale 2/x_mirror 3/y_mirror + unsigned int angle, // rotate angle + unsigned int dither_en, // dither en flag + unsigned int AA_en, // AA flag + unsigned int yuv2rgb_mode +); + + +int +RGA_set_color_palette_mode( + struct rga_req *msg, + unsigned char palette_mode, /* 1bpp/2bpp/4bpp/8bpp */ + unsigned char endian_mode, /* src endian mode sel */ + unsigned int bpp1_0_color, /* BPP1 = 0 */ + unsigned int bpp1_1_color /* BPP1 = 1 */ +); + + +int +RGA_set_color_fill_mode( + struct rga_req *msg, + COLOR_FILL *gr_color, /* gradient color part */ + unsigned char gr_satur_mode, /* saturation mode */ + unsigned char cf_mode, /* patten fill or solid fill */ + unsigned int color, /* solid color */ + unsigned short pat_width, /* pattern width */ + unsigned short pat_height, /* pattern height */ + unsigned char pat_x_off, /* pattern x offset */ + unsigned char pat_y_off, /* pattern y offset */ + unsigned char aa_en /* alpha en */ +); + + +int +RGA_set_line_point_drawing_mode( + struct rga_req *msg, + POINT sp, /* start point */ + POINT ep, /* end point */ + unsigned int color, /* line point drawing color */ + unsigned int line_width, /* line width */ + unsigned char AA_en, /* AA en */ + unsigned char last_point_en /* last point en */ +); + + +int +RGA_set_blur_sharp_filter_mode( + struct rga_req *msg, + unsigned char filter_mode, /* blur/sharpness */ + unsigned char filter_type, /* filter intensity */ + unsigned char dither_en /* dither_en flag */ +); + +int +RGA_set_pre_scaling_mode( + struct rga_req *msg, + unsigned char dither_en +); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned long LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ +); +#else +int +RGA_update_palette_table_mode( + struct rga_req *msg, + unsigned int LUT_addr, /* LUT table addr */ + unsigned int palette_mode /* 1bpp/2bpp/4bpp/8bpp */ +); +#endif + +int +RGA_set_update_patten_buff_mode( + struct rga_req *msg, + unsigned int pat_addr, /* patten addr */ + unsigned int w, /* patten width */ + unsigned int h, /* patten height */ + unsigned int format /* patten format */ +); + +#if defined(__arm64__) || defined(__aarch64__) +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned long base_addr, + unsigned char page_size +); +#else +int +RGA_set_mmu_info( + struct rga_req *msg, + unsigned char mmu_en, + unsigned char src_flush, + unsigned char dst_flush, + unsigned char cmd_flush, + unsigned int base_addr, + unsigned char page_size +); +#endif + +void rga_set_fds_offsets( + struct rga_req *rga_request, + unsigned short src_fd, + unsigned short dst_fd, + unsigned int src_offset, + unsigned int dst_offset); + +int +RGA_set_src_fence_flag( + struct rga_req *msg, + int acq_fence, + int src_flag +); + + +int +RGA_set_dst_fence_flag( + struct rga_req *msg, + int dst_flag +); + +int +RGA_get_dst_fence( + struct rga_req *msg +); +#ifdef __cplusplus +} +#endif + +#endif /*_RK29_IPP_DRIVER_H_*/ diff --git a/rk3568/camera/src/pipeline_core/BUILD.gn b/rk3568/camera/src/pipeline_core/BUILD.gn index 8eb4bea3400ee2e16ac532cde5ab12d65e785a24..8e1f1f91d27b6ded3c6f2df980ccd42fdcdce8df 100755 --- a/rk3568/camera/src/pipeline_core/BUILD.gn +++ b/rk3568/camera/src/pipeline_core/BUILD.gn @@ -47,6 +47,7 @@ ohos_shared_library("camera_pipeline_core") { sources = [ "$camera_path/adapter/platform/v4l2/src/pipeline_core/nodes/uvc_node/uvc_node.cpp", "$camera_path/adapter/platform/v4l2/src/pipeline_core/nodes/v4l2_source_node/v4l2_source_node.cpp", + "$camera_device_name_path/camera/src/pipeline_core/node/rk_codec_node.cpp", "$camera_path/pipeline_core/host_stream/src/host_stream_impl.cpp", "$camera_path/pipeline_core/host_stream/src/host_stream_mgr_impl.cpp", "$camera_path/pipeline_core/ipp/src/algo_plugin.cpp", @@ -70,6 +71,7 @@ ohos_shared_library("camera_pipeline_core") { "$camera_path/pipeline_core/pipeline_impl/src/strategy/stream_pipeline_strategy.cpp", "$camera_path/pipeline_core/pipeline_impl/src/stream_pipeline_core.cpp", "$camera_path/pipeline_core/src/pipeline_core.cpp", + "//device/rockchip/hardware/mpp/src/mpi_enc_utils.c", ] include_dirs = [ "//utils/native/base/include", @@ -114,7 +116,10 @@ ohos_shared_library("camera_pipeline_core") { "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", "//utils/native/base/include", "//foundation/multimedia/camera_standard/frameworks/innerkitsimpl/metadata/include", - "$camera_device_name_path/camera/rk", + "$camera_device_name_path/camera/src/pipeline_core/node", + "//device/rockchip/hardware/rga/include", + "//device/rockchip/hardware/mpp/include", + "//third_party/libjpeg", # hcs parser "//drivers/framework/include/osal", @@ -123,12 +128,15 @@ ohos_shared_library("camera_pipeline_core") { "//system/core/include/cutils", "//drivers/framework/utils/include", "//drivers/adapter/uhdf2/osal/include", - ] + ] deps = [ "$camera_path/buffer_manager:camera_buffer_manager", "$camera_path/device_manager:camera_device_manager", "//foundation/multimedia/camera_standard/frameworks/innerkitsimpl/metadata:metadata", + "//device/rockchip/hardware/rga:librga", + "//device/rockchip/hardware/mpp:libmpp", + "//third_party/libjpeg:libjpeg_static", # hcs parser "$hdf_uhdf_path/utils:libhdf_utils", diff --git a/rk3568/camera/src/pipeline_core/node/rk_codec_node.cpp b/rk3568/camera/src/pipeline_core/node/rk_codec_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd77d86e7384dfbf981a33aabd44054a501bc87c --- /dev/null +++ b/rk3568/camera/src/pipeline_core/node/rk_codec_node.cpp @@ -0,0 +1,348 @@ +/* + * 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 "rk_codec_node.h" +#include "securec.h" + +namespace OHOS::Camera { +uint32_t RKCodecNode::previewWidth_ = 0; +uint32_t RKCodecNode::previewHeight_ = 0; + +RKCodecNode::RKCodecNode(const std::string& name, const std::string& type) : NodeBase(name, type) +{ + CAMERA_LOGV("%{public}s enter, type(%{public}s)\n", name_.c_str(), type_.c_str()); +} + +RKCodecNode::~RKCodecNode() +{ + CAMERA_LOGI("~RKCodecNode Node exit."); +} + +RetCode RKCodecNode::Start(const int32_t streamId) +{ + CAMERA_LOGI("RKCodecNode::Start streamId = %{public}d\n", streamId); + return RC_OK; +} + +RetCode RKCodecNode::Stop(const int32_t streamId) +{ + CAMERA_LOGI("RKCodecNode::Stop streamId = %{public}d\n", streamId); + + if (halCtx_ != nullptr) { + hal_mpp_ctx_delete(halCtx_); + halCtx_ = nullptr; + mppStatus_ = 0; + } + + return RC_OK; +} + +RetCode RKCodecNode::Flush(const int32_t streamId) +{ + CAMERA_LOGI("RKCodecNode::Flush streamId = %{public}d\n", streamId); + return RC_OK; +} + +void RKCodecNode::encodeJpegToMemory(unsigned char* image, int width, int height, + const char* comment, size_t* jpegSize, unsigned char** jpegBuf) +{ + struct jpeg_compress_struct cInfo; + struct jpeg_error_mgr jErr; + JSAMPROW row_pointer[1]; + int row_stride = 0; + constexpr uint32_t colorMap = 3; + constexpr uint32_t compressionRatio = 100; + constexpr uint32_t pixelsThick = 3; + + cInfo.err = jpeg_std_error(&jErr); + + jpeg_create_compress(&cInfo); + cInfo.image_width = width; + cInfo.image_height = height; + cInfo.input_components = colorMap; + cInfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&cInfo); + jpeg_set_quality(&cInfo, compressionRatio, TRUE); + jpeg_mem_dest(&cInfo, jpegBuf, jpegSize); + jpeg_start_compress(&cInfo, TRUE); + + if (comment) { + jpeg_write_marker(&cInfo, JPEG_COM, (const JOCTET*)comment, strlen(comment)); + } + + row_stride = width; + while (cInfo.next_scanline < cInfo.image_height) { + row_pointer[0] = &image[cInfo.next_scanline * row_stride * pixelsThick]; + jpeg_write_scanlines(&cInfo, row_pointer, 1); + } + + jpeg_finish_compress(&cInfo); + jpeg_destroy_compress(&cInfo); +} + +int RKCodecNode::findStartCode(unsigned char *data, size_t dataSz) +{ + constexpr uint32_t dataSize = 4; + constexpr uint32_t dataBit2 = 2; + constexpr uint32_t dataBit3 = 3; + + if (data == nullptr) { + CAMERA_LOGI("RKCodecNode::findStartCode paramater == nullptr"); + return -1; + } + + if ((dataSz > dataSize) && (data[0] == 0) && (data[1] == 0) && \ + (data[dataBit2] == 0) && (data[dataBit3] == 1)) { + return 4; + } + + return -1; +} + +static constexpr uint32_t nalBit = 0x1F; +#define NAL_TYPE(value) ((value) & nalBit) +void RKCodecNode::SerchIFps(unsigned char* buf, size_t bufSize, std::shared_ptr& buffer) +{ + size_t nalType = 0; + size_t idx = 0; + size_t size = bufSize; + constexpr uint32_t nalTypeValue = 0x05; + + if (buffer == nullptr || buf == nullptr) { + CAMERA_LOGI("RKCodecNode::SerchIFps paramater == nullptr"); + return; + } + + int ret = 0; + for (int i = 0; i < bufSize; i++) { + ret = findStartCode(buf + idx, size); + if (ret == -1) { + idx += 1; + size -= 1; + } else { + nalType = NAL_TYPE(buf[idx + ret]); + CAMERA_LOGI("ForkNode::ForkBuffers nalu == 0x%{public}x buf == 0x%{public}x \n", nalType, buf[idx + ret]); + if (nalType == nalTypeValue) { + buffer->SetEsKeyFrame(1); + CAMERA_LOGI("ForkNode::ForkBuffers SetEsKeyFrame == 1 nalu == 0x%{public}x\n", nalType); + break; + } else { + idx += ret; + size -= ret; + } + } + + if (idx >= bufSize) { + break; + } + } + + if (idx >= bufSize) { + buffer->SetEsKeyFrame(0); + CAMERA_LOGI("ForkNode::ForkBuffers SetEsKeyFrame == 0 nalu == 0x%{public}x idx = %{public}d\n", + nalType, idx); + } + +} + +void RKCodecNode::Yuv420ToRGBA8888(std::shared_ptr& buffer) +{ + if (buffer == nullptr) { + CAMERA_LOGI("RKCodecNode::Yuv420ToRGBA8888 buffer == nullptr"); + return; + } + + int dma_fd = buffer->GetFileDescriptor(); + void* temp = malloc(buffer->GetSize()); + if (temp == nullptr) { + CAMERA_LOGI("RKCodecNode::Yuv420ToRGBA8888 malloc buffer == nullptr"); + return; + } + + previewWidth_ = buffer->GetWidth(); + previewHeight_ = buffer->GetHeight(); + memcpy(temp, (const void *)buffer->GetVirAddress(), buffer->GetSize()); + RockchipRga rkRga; + + rga_info_t src = {}; + rga_info_t dst = {}; + + src.fd = -1; + src.mmuFlag = 1; + src.rotation = 0; + src.virAddr = (void *)temp; + + dst.fd = dma_fd; + dst.mmuFlag = 1; + dst.virAddr = 0; + + rga_set_rect(&src.rect, 0, 0, buffer->GetWidth(), buffer->GetHeight(), + buffer->GetWidth(), buffer->GetHeight(), + RK_FORMAT_YCbCr_420_P); + rga_set_rect(&dst.rect, 0, 0, buffer->GetWidth(), buffer->GetHeight(), + buffer->GetWidth(), buffer->GetHeight(), + RK_FORMAT_RGBA_8888); + + rkRga.RkRgaBlit(&src, &dst, NULL); + rkRga.RkRgaFlush(); + free(temp); +} + +void RKCodecNode::Yuv420ToJpeg(std::shared_ptr& buffer) +{ + constexpr uint32_t RGB24Width = 3; + + if (buffer == nullptr) { + CAMERA_LOGI("RKCodecNode::Yuv420ToJpeg buffer == nullptr"); + return; + } + + int dma_fd = buffer->GetFileDescriptor(); + unsigned char* jBuf = nullptr; + size_t jpegSize = 0; + uint32_t tempSize = (previewWidth_ * previewHeight_ * RGB24Width); + + void* temp = malloc(tempSize); + if (temp == nullptr) { + CAMERA_LOGI("RKCodecNode::Yuv420ToJpeg malloc buffer == nullptr"); + return; + } + + RockchipRga rkRga; + rga_info_t src = {}; + rga_info_t dst = {}; + + src.mmuFlag = 1; + src.rotation = 0; + src.virAddr = 0; + src.fd = dma_fd; + + dst.fd = -1; + dst.mmuFlag = 1; + dst.virAddr = temp; + + rga_set_rect(&src.rect, 0, 0, previewWidth_, previewHeight_, + previewWidth_, previewHeight_, + RK_FORMAT_YCbCr_420_P); + rga_set_rect(&dst.rect, 0, 0, previewWidth_, previewHeight_, + previewWidth_, previewHeight_, + RK_FORMAT_RGB_888); + + rkRga.RkRgaBlit(&src, &dst, NULL); + rkRga.RkRgaFlush(); + encodeJpegToMemory((unsigned char *)temp, previewWidth_, previewHeight_, NULL, &jpegSize, &jBuf); + memcpy((unsigned char*)buffer->GetVirAddress(), jBuf, jpegSize); + buffer->SetEsFrameSize(jpegSize); + free(jBuf); + free(temp); + + CAMERA_LOGE("RKCodecNode::Yuv420ToJpeg jpegSize = %{public}d\n", jpegSize); +} + +void RKCodecNode::Yuv420ToH264(std::shared_ptr& buffer) +{ + if (buffer == nullptr) { + CAMERA_LOGI("RKCodecNode::Yuv420ToH264 buffer == nullptr"); + return; + } + + int ret = 0; + size_t buf_size = 0; + struct timespec ts = {}; + int64_t timestamp = 0; + int dma_fd = buffer->GetFileDescriptor(); + + if (mppStatus_ == 0) { + MpiEncTestArgs args = {}; + args.width = previewWidth_; + args.height = previewHeight_; + args.format = MPP_FMT_YUV420P; + args.type = MPP_VIDEO_CodingAVC; + halCtx_ = hal_mpp_ctx_create(&args); + mppStatus_ = 1; + buf_size = ((MpiEncTestData *)halCtx_)->frame_size; + + ret = hal_mpp_encode(halCtx_, dma_fd, (unsigned char *)buffer->GetVirAddress(), &buf_size); + SerchIFps((unsigned char *)buffer->GetVirAddress(), buf_size, buffer); + + buffer->SetEsFrameSize(buf_size); + clock_gettime(CLOCK_REALTIME, &ts); + timestamp = ts.tv_sec & 0xFFFFFF; + timestamp *= 1000000000; + timestamp += ts.tv_nsec; + buffer->SetEsTimestamp(timestamp); + CAMERA_LOGI("RKCodecNode::Yuv420ToH264 video capture on\n"); + } else { + buf_size = ((MpiEncTestData *)halCtx_)->frame_size; + ret = hal_mpp_encode(halCtx_, dma_fd, (unsigned char *)buffer->GetVirAddress(), &buf_size); + SerchIFps((unsigned char *)buffer->GetVirAddress(), buf_size, buffer); + buffer->SetEsFrameSize(buf_size); + clock_gettime(CLOCK_REALTIME, &ts); + timestamp = ts.tv_sec & 0xFFFFFF; + timestamp *= 1000000000; + timestamp += ts.tv_nsec; + buffer->SetEsTimestamp(timestamp); + } + + CAMERA_LOGI("ForkNode::ForkBuffers H264 size = %{public}d ret = %{public}d timestamp = %{public}lld\n", + buf_size, ret, timestamp); +} + +void RKCodecNode::DeliverBuffer(std::shared_ptr& buffer) +{ + if (buffer == nullptr) { + CAMERA_LOGE("RKCodecNode::DeliverBuffer frameSpec is null"); + return; + } + + int32_t id = buffer->GetStreamId(); + CAMERA_LOGE("RKCodecNode::DeliverBuffer StreamId %{public}d", id); + if (buffer->GetEncodeType() == ENCODE_TYPE_JPEG) { + Yuv420ToJpeg(buffer); + } else if (buffer->GetEncodeType() == ENCODE_TYPE_H264) { + Yuv420ToH264(buffer); + } else { + Yuv420ToRGBA8888(buffer); + } + + outPutPorts_ = GetOutPorts(); + for (auto& it : outPutPorts_) { + if (it->format_.streamId_ == id) { + it->DeliverBuffer(buffer); + CAMERA_LOGI("RKCodecNode deliver buffer streamid = %{public}d", it->format_.streamId_); + return; + } + } +} + +RetCode RKCodecNode::Capture(const int32_t streamId, const int32_t captureId) +{ + CAMERA_LOGV("RKCodecNode::Capture"); + return RC_OK; +} + +RetCode RKCodecNode::CancelCapture(const int32_t streamId) +{ + CAMERA_LOGI("RKCodecNode::CancelCapture streamid = %{public}d", streamId); + if (halCtx_ != nullptr) { + hal_mpp_ctx_delete(halCtx_); + halCtx_ = nullptr; + mppStatus_ = 0; + } + + return RC_OK; +} + +REGISTERNODE(RKCodecNode, {"RKCodec"}) +} // namespace OHOS::Camera diff --git a/rk3568/camera/src/pipeline_core/node/rk_codec_node.h b/rk3568/camera/src/pipeline_core/node/rk_codec_node.h new file mode 100644 index 0000000000000000000000000000000000000000..dc44ccd56b412a69079ecf3f3eeb8f95959dd1d7 --- /dev/null +++ b/rk3568/camera/src/pipeline_core/node/rk_codec_node.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 HOS_CAMERA_RKCODEC_NODE_H +#define HOS_CAMERA_RKCODEC_NODE_H + +#include +#include +#include +#include +#include "device_manager_adapter.h" +#include "utils.h" +#include "camera.h" +#include "source_node.h" +#include "RockchipRga.h" +#include "RgaUtils.h" +#include "RgaApi.h" +#include "rk_mpi.h" +#include "mpp_env.h" +#include "mpp_mem.h" +#include "mpp_log.h" +#include "mpp_common.h" +extern "C" { +#include "mpi_enc_utils.h" +} + + +namespace OHOS::Camera { +class RKCodecNode : public NodeBase { +public: + RKCodecNode(const std::string& name, const std::string& type); + ~RKCodecNode() override; + RetCode Start(const int32_t streamId) override; + RetCode Stop(const int32_t streamId) override; + void DeliverBuffer(std::shared_ptr& buffer) override; + virtual RetCode Capture(const int32_t streamId, const int32_t captureId) override; + RetCode CancelCapture(const int32_t streamId) override; + RetCode Flush(const int32_t streamId); +private: + void encodeJpegToMemory(unsigned char* image, int width, int height, + const char* comment, size_t* jpegSize, unsigned char** jpegBuf); + int findStartCode(unsigned char *data, size_t dataSz); + void SerchIFps(unsigned char* buf, size_t bufSize, std::shared_ptr& buffer); + void Yuv420ToRGBA8888(std::shared_ptr& buffer); + void Yuv420ToJpeg(std::shared_ptr& buffer); + void Yuv420ToH264(std::shared_ptr& buffer); + + static uint32_t previewWidth_; + static uint32_t previewHeight_; + std::vector> outPutPorts_; + void* halCtx_ = nullptr; + int mppStatus_ = 0; +}; +}// namespace OHOS::Camera +#endif diff --git a/rk3568/loader/boot_linux.img b/rk3568/loader/boot_linux.img index 550f91bee05cbe31ea7c268b4f07b25c1e66526e..b04906b2fe245b61013e599e66e088eaef34c03d 100644 Binary files a/rk3568/loader/boot_linux.img and b/rk3568/loader/boot_linux.img differ