diff --git a/display/hal/default_standard/BUILD.gn b/display/hal/default_standard/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..713bf1f44ca5beb85f9e4530be07548db821da06 --- /dev/null +++ b/display/hal/default_standard/BUILD.gn @@ -0,0 +1,123 @@ +# 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. + +import("//build/ohos.gni") + +group("display_group") { + deps = [ + ":display_device_drm", + ":displaygralloc", + ":higbm", + ] +} + +ohos_static_library("higbm") { + sources = [ "src/display_gralloc/hi_gbm.c" ] + include_dirs = [ + "include", + "//utils/native/base/include", + "//base/hiviewdfx/interfaces/innerkits/libhilog/include", + ] + output_name = "higbm" + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + deps = [ + "//third_party/libdrm:libdrm", + "//utils/native/base:utils", + ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_shared_library("displaygralloc") { + 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" +} + +ohos_shared_library("display_device_drm") { + 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_drm" + 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 = [ + ":displaygralloc", + "//drivers/peripheral/display/hal:hdi_display_gfx", + "//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" +} diff --git a/display/hal/default_standard/include/display_common.h b/display/hal/default_standard/include/display_common.h new file mode 100644 index 0000000000000000000000000000000000000000..316ce7e9325f4ca5c59c618916cf4e334731a262 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/include/display_gralloc_private.h b/display/hal/default_standard/include/display_gralloc_private.h new file mode 100644 index 0000000000000000000000000000000000000000..e5ce9e0cefa946019050cd4a37de2c428dad1a50 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/drm_connector.cpp b/display/hal/default_standard/src/display_device/drm_connector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..636d992d2943389a5d00d16a70ce98dbd247940e --- /dev/null +++ b/display/hal/default_standard/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 + +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}d", 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("the prop of brightness is %d , the level is %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; + 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}llu", 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/display/hal/default_standard/src/display_device/drm_connector.h b/display/hal/default_standard/src/display_device/drm_connector.h new file mode 100644 index 0000000000000000000000000000000000000000..42cc27aa644371166d2e20d1c960852c2aeafc69 --- /dev/null +++ b/display/hal/default_standard/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 "hdi_shared_fd.h" +#include "drm_device.h" +#include "drm_encoder.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/display/hal/default_standard/src/display_device/drm_crtc.cpp b/display/hal/default_standard/src/display_device/drm_crtc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0fe8b22dc9584bb4ef13d225647dae0be388e2e --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/drm_crtc.h b/display/hal/default_standard/src/display_device/drm_crtc.h new file mode 100644 index 0000000000000000000000000000000000000000..23eb31fbd2c5093121d20d759666a56b159c447e --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_crtc.h @@ -0,0 +1,85 @@ +/* + * 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 "hdi_display.h" +#include "drm_device.h" +#include "hdi_device_common.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/display/hal/default_standard/src/display_device/drm_device.cpp b/display/hal/default_standard/src/display_device/drm_device.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f85950573ac44faa7de98fb694d3c8f9aaaf1e6 --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_device.cpp @@ -0,0 +1,328 @@ +/* + * 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 +#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("hisilicon"); + 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(); +} + +typedef struct { + uint32_t drmFormat; + PixelFormat pixFormat; +} PixelFormatConvertTbl; + +uint32_t DrmDevice::ConvertToDrmFormat(PixelFormat fmtIn) +{ + /* + 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 + now gbm can not support YUV 422 + */ + 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 }, + + }; + 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; + 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)); + + 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}d", 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}d", 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}d", mPlanes.size()); +} + +std::shared_ptr DrmDevice::GetDrmEncoderFromId(uint32_t id) +{ + int32_t ret = DISPLAY_FAILURE; + auto iter = mEncoders.find(id); + if (iter == mEncoders.end()) { + ret = DISPLAY_SUCCESS; + } + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmConnectorFromId(uint32_t id) +{ + int32_t ret = DISPLAY_FAILURE; + auto iter = mConnectors.find(id); + if (iter == mConnectors.end()) { + ret = DISPLAY_SUCCESS; + } + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmCrtcFromId(uint32_t id) +{ + int32_t ret = DISPLAY_FAILURE; + auto iter = mCrtcs.find(id); + if (iter == mCrtcs.end()) { + ret = DISPLAY_SUCCESS; + } + return nullptr; +} + +std::vector> DrmDevice::GetDrmPlane(uint32_t pipe, uint32_t type) +{ + std::vector> planes; + for (const auto &plane : mPlanes) { + if (plane->IsIdle() && ((1 << pipe) & plane->GetPossibleCrtcs()) && (type == plane->GetType())) { + plane->BindToPipe(pipe); + planes.push_back(plane); + } + } + DISPLAY_LOGD("the planes count %{public}d", 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}d", mDisplays.size()); + return mDisplays; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/hal/default_standard/src/display_device/drm_device.h b/display/hal/default_standard/src/display_device/drm_device.h new file mode 100644 index 0000000000000000000000000000000000000000..3b0b28112259b92ad36205a43114d4b1346c87e2 --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_device.h @@ -0,0 +1,81 @@ +/* + * 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 "hdi_device_common.h" +#include "hdi_device_interface.h" +#include "hdi_display.h" +#include "drm_crtc.h" +#include "drm_connector.h" +#include "drm_encoder.h" +#include "drm_plane.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/display/hal/default_standard/src/display_device/drm_display.cpp b/display/hal/default_standard/src/display_device/drm_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05cb5bf8db536fd188cc64992cfbaad86515ee19 --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_display.cpp @@ -0,0 +1,264 @@ +/* + * 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; + ret = ConvertToDrmPowerState(status, drmPowerState); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_PARAM_ERR, + DISPLAY_LOGE("unkown 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 %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); + 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/display/hal/default_standard/src/display_device/drm_display.h b/display/hal/default_standard/src/display_device/drm_display.h new file mode 100644 index 0000000000000000000000000000000000000000..3cdf41171f3999fef6f1b083f35d569c6b3e6919 --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_display.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 DRM_DISPLAY_H +#define DRM_DISPLAY_H +#include +#include +#include "drm_crtc.h" +#include "drm_connector.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(); + int32_t GetDisplayCapability(DisplayCapability *info); + int32_t GetDisplaySuppportedModes(int *num, DisplayModeInfo *modes); + int32_t GetDisplayMode(uint32_t *modeId); + int32_t SetDisplayMode(uint32_t modeId); + int32_t GetDisplayPowerStatus(DispPowerStatus *status); + int32_t SetDisplayPowerStatus(DispPowerStatus status); + int32_t GetDisplayBacklight(uint32_t *value); + int32_t SetDisplayBacklight(uint32_t value); + int32_t ChosePreferenceMode(); + virtual int32_t RegDisplayVBlankCallback(VBlankCallback cb, void *data); + virtual int32_t WaitForVBlank(uint64_t *ns); + virtual bool IsConnected(); + virtual int32_t SetDisplayVsyncEnabled(bool enabled); + + HdiDrmComposition *GetDrmComposition(); + +protected: + std::unique_ptr CreateHdiLayer(LayerType type); + +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/display/hal/default_standard/src/display_device/drm_encoder.cpp b/display/hal/default_standard/src/display_device/drm_encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..048d0fae6150f1bb8e4a67d2337b4ad52f6d31da --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_encoder.cpp @@ -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. + */ + +#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/display/hal/default_standard/src/display_device/drm_encoder.h b/display/hal/default_standard/src/display_device/drm_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..4f35578a54ef9ac26439f1ebf19cf342307fa509 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/drm_plane.cpp b/display/hal/default_standard/src/display_device/drm_plane.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8574c72847a6e9869ef68a744d0a11e0280904c --- /dev/null +++ b/display/hal/default_standard/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_device.h" +#include "drm_plane.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("unkown type value %{public}llu ", prop.value); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/hal/default_standard/src/display_device/drm_plane.h b/display/hal/default_standard/src/display_device/drm_plane.h new file mode 100644 index 0000000000000000000000000000000000000000..0391810977dc80b40e78f81fe851cd5f4a66a40e --- /dev/null +++ b/display/hal/default_standard/src/display_device/drm_plane.h @@ -0,0 +1,84 @@ +/* + * 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 "drm_device.h" + +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 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/display/hal/default_standard/src/display_device/drm_vsync_worker.cpp b/display/hal/default_standard/src/display_device/drm_vsync_worker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..173532b950edcaa0347b0845709541db35227518 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/drm_vsync_worker.h b/display/hal/default_standard/src/display_device/drm_vsync_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..c578e91c49e9fc8722115ef711cfd097fe1a3737 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_composer.cpp b/display/hal/default_standard/src/display_device/hdi_composer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72ac266c24ce8b3ac4662dd7c6626b840a2c50f9 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_composer.cpp @@ -0,0 +1,47 @@ +/* + * 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; + 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; + 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/display/hal/default_standard/src/display_device/hdi_composer.h b/display/hal/default_standard/src/display_device/hdi_composer.h new file mode 100644 index 0000000000000000000000000000000000000000..a3b69de50dd58f1af8317533bf1ce9ab4fb23e38 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_device_common.h b/display/hal/default_standard/src/display_device/hdi_device_common.h new file mode 100644 index 0000000000000000000000000000000000000000..30841561f572cedb1b2dea8ff7d223ee5a42b37d --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_device_common.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_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 \ No newline at end of file diff --git a/display/hal/default_standard/src/display_device/hdi_device_interface.cpp b/display/hal/default_standard/src/display_device/hdi_device_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96e5d2e4b9ca1fb9197e40d79ba6d846813ada2f --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_device_interface.h b/display/hal/default_standard/src/display_device/hdi_device_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..f5964ef98a85d3a62a63a716745bb4b9ee1c7778 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_display.cpp b/display/hal/default_standard/src/display_device/hdi_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75c3c8d92438ba9186df91c8373ba6f66bb6d798 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_display.cpp @@ -0,0 +1,226 @@ +/* + * 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 %d zorder %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/display/hal/default_standard/src/display_device/hdi_display.h b/display/hal/default_standard/src/display_device/hdi_display.h new file mode 100644 index 0000000000000000000000000000000000000000..3b8884c50d7449950d246a6f93651716d5967e9c --- /dev/null +++ b/display/hal/default_standard/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_layer.h" +#include "hdi_composer.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/display/hal/default_standard/src/display_device/hdi_drm_composition.cpp b/display/hal/default_standard/src/display_device/hdi_drm_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29712f666a64d682c8ec6fd2d1a40f1417763834 --- /dev/null +++ b/display/hal/default_standard/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}d", 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/display/hal/default_standard/src/display_device/hdi_drm_composition.h b/display/hal/default_standard/src/display_device/hdi_drm_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..d8bdc7e9c529fbdfae79eb1da056221ef39e26f0 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_drm_composition.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_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/display/hal/default_standard/src/display_device/hdi_drm_layer.cpp b/display/hal/default_standard/src/display_device/hdi_drm_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ceeb8d131dc38d5370683e73187a1691b426ad76 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_drm_layer.cpp @@ -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. + */ + +#include "hdi_drm_layer.h" +#include +#include +#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()); + mCurrentBuffer = std::move(ptr); + return mCurrentBuffer.get(); +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/hal/default_standard/src/display_device/hdi_drm_layer.h b/display/hal/default_standard/src/display_device/hdi_drm_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..3963703632a5986c95143edb07a08151804194af --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_drm_layer.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_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; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DRM_LAYER_H diff --git a/display/hal/default_standard/src/display_device/hdi_gfx_composition.cpp b/display/hal/default_standard/src/display_device/hdi_gfx_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..689cbb14fd59dc9f20571eb3fe0e200ce249ea53 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_gfx_composition.cpp @@ -0,0 +1,153 @@ +/* + * 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 "display_gfx.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +int32_t HdiGfxComposition::Init() +{ + int ret; + DISPLAY_LOGD(); + ret = GfxInitialize(&mGfxFuncs); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS) || (mGfxFuncs == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("gfx GfxInitialize failed")); + ret = mGfxFuncs->InitGfx(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS) || (mGfxFuncs == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("gfx init failed")); + return DISPLAY_SUCCESS; +} + +bool HdiGfxComposition::CanHandle(HdiLayer &hdiLayer) +{ + DISPLAY_LOGD(); + return true; +} + +int32_t HdiGfxComposition::SetLayers(std::vector &layers, HdiLayer &clientLayer) +{ + DISPLAY_LOGD("layers size %{public}d", 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}d", 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.enColorFmt = (PixelFormat)buffer.GetFormat(); + surface.stride = buffer.GetStride(); + surface.bAlphaExt1555 = true; + surface.bAlphaMax255 = true; + surface.alpha0 = 0XFF; + surface.alpha1 = 0XFF; + DISPLAY_LOGD("surface info w: %{public}d h: %{public}d addr: %{public}llx 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); + 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(); + return mGfxFuncs->FillRect(&dstSurface, &rect, 0, &opt); +} + +int32_t HdiGfxComposition::Apply(bool modeSet) +{ + int32_t ret; + DISPLAY_LOGD("composer layers size %{public}d", 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/display/hal/default_standard/src/display_device/hdi_gfx_composition.h b/display/hal/default_standard/src/display_device/hdi_gfx_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..472983ad585b36ede5b1d005d0f9912120b82d6d --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_gfx_composition.h @@ -0,0 +1,42 @@ +/* + * 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(); + int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer); + int32_t Apply(bool modeSet); + virtual ~HdiGfxComposition() {} + +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); + GfxFuncs *mGfxFuncs = nullptr; + HdiLayer *mClientLayer; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif \ No newline at end of file diff --git a/display/hal/default_standard/src/display_device/hdi_layer.cpp b/display/hal/default_standard/src/display_device/hdi_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..906b62b4d945af50b72d719d38cbc11649e540c2 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_layer.h b/display/hal/default_standard/src/display_device/hdi_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..b4042cbd3f7ce694cc1849f3125a6cc9e3c66d59 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_netlink_monitor.cpp b/display/hal/default_standard/src/display_device/hdi_netlink_monitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b8ffa476859952e39d4197d68ce46ea1ecb698c --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_netlink_monitor.h b/display/hal/default_standard/src/display_device/hdi_netlink_monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..f46af61b14c8389580f9ad9862d5146f7fbd546b --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_session.cpp b/display/hal/default_standard/src/display_device/hdi_session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e30cb7fb7e99db3aabd61c9997d4ba14efef888 --- /dev/null +++ b/display/hal/default_standard/src/display_device/hdi_session.cpp @@ -0,0 +1,393 @@ +/* + * 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() +{ + // find all device + DISPLAY_LOGD(); + mHdiDevices = HdiDeviceInterface::DiscoveryDevice(); + DISPLAY_LOGD("devices size %{public}d", mHdiDevices.size()); + // find all display + 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); + // find all display + 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(); + 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(); + 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(); + 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/display/hal/default_standard/src/display_device/hdi_session.h b/display/hal/default_standard/src/display_device/hdi_session.h new file mode 100644 index 0000000000000000000000000000000000000000..bed5d63561d2ae8823701aa9e1df151426a421e4 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_device/hdi_shared_fd.h b/display/hal/default_standard/src/display_device/hdi_shared_fd.h new file mode 100644 index 0000000000000000000000000000000000000000..e79c3f17a932cba292064aeefea3928584cf82cc --- /dev/null +++ b/display/hal/default_standard/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 \ No newline at end of file diff --git a/display/hal/default_standard/src/display_gralloc/display_gralloc.c b/display/hal/default_standard/src/display_gralloc/display_gralloc.c new file mode 100644 index 0000000000000000000000000000000000000000..9807360c5564382a1a8611ef2ed0c1cab9a99415 --- /dev/null +++ b/display/hal/default_standard/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_PARAM_ERR, DISPLAY_LOGE("memset_s failed")); + errno_t eok = memset_s(grallocFuncs, sizeof(GrallocFuncs), 0, sizeof(GrallocFuncs)); + DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_PARAM_ERR, 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/display/hal/default_standard/src/display_gralloc/display_gralloc_gbm.c b/display/hal/default_standard/src/display_gralloc/display_gralloc_gbm.c new file mode 100644 index 0000000000000000000000000000000000000000..afbf25a05eca3c9ed5d4b06fb3c68180cb918a7a --- /dev/null +++ b/display/hal/default_standard/src/display_gralloc/display_gralloc_gbm.c @@ -0,0 +1,449 @@ +/* + * 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/card0"; +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 = "unkown 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 unkown 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 = "unkown 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 unkown format %{public}d", format); + return unknown; +} + +static uint32_t ConvertFormatToDrm(PixelFormat fmtIn) +{ + /* + 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 + now gbm can not support YUV 422 + */ + 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 }, + + }; + 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; // retry 6 times + 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() +{ + 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() +{ + DISPLAY_LOGD(); + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == NULL), DISPLAY_PARAM_ERR, DISPLAY_LOGE("gralloc manager failed"); + GRALLOC_UNLOCK()); + // TOD: need lock + 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/display/hal/default_standard/src/display_gralloc/display_gralloc_gbm.h b/display/hal/default_standard/src/display_gralloc/display_gralloc_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..a1ec8272b1b06c1ee25907f0c14ad9177a94499d --- /dev/null +++ b/display/hal/default_standard/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("[%s@%s:%d] GrallocLock " format "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ + pthread_mutex_lock(&g_lock); \ + } while (0) + +#define GRALLOC_UNLOCK(format, ...) \ + do { \ + HDF_LOGD("[%s@%s:%d] GrallocUnLock " 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 \ No newline at end of file diff --git a/display/hal/default_standard/src/display_gralloc/hi_gbm.c b/display/hal/default_standard/src/display_gralloc/hi_gbm.c new file mode 100644 index 0000000000000000000000000000000000000000..678a0c0fbad85a6ea5a33dc2d17becda38e37b67 --- /dev/null +++ b/display/hal/default_standard/src/display_gralloc/hi_gbm.c @@ -0,0 +1,190 @@ +/* + * 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" + +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 = NULL; + 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)); + (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo)); + DISPLAY_CHK_RETURN((bo == NULL), NULL, DISPLAY_LOGE("gbm bo create fialed no memery")); + 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/display/hal/default_standard/src/display_gralloc/hi_gbm.h b/display/hal/default_standard/src/display_gralloc/hi_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..259aa37e406181ab7d45e372a795e0c6599af16e --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_gralloc/hi_gbm_internal.h b/display/hal/default_standard/src/display_gralloc/hi_gbm_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..2dbba7c83da49cebd9ead695bf650a26ba6d6afd --- /dev/null +++ b/display/hal/default_standard/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 \ No newline at end of file diff --git a/display/hal/default_standard/src/display_gralloc/hisilicon_drm.h b/display/hal/default_standard/src/display_gralloc/hisilicon_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..b3c09405946fd3f6ef4ea931760fdf9ec17e6468 --- /dev/null +++ b/display/hal/default_standard/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/display/hal/default_standard/src/display_gralloc/wayland_drm_auth_client.c b/display/hal/default_standard/src/display_gralloc/wayland_drm_auth_client.c new file mode 100644 index 0000000000000000000000000000000000000000..cf0607481f8c31a62b6d5fa757b5b09a02c88af2 --- /dev/null +++ b/display/hal/default_standard/src/display_gralloc/wayland_drm_auth_client.c @@ -0,0 +1,111 @@ +/* + * 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) +{ + 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: %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/display/hal/default_standard/src/display_gralloc/wayland_drm_auth_client.h b/display/hal/default_standard/src/display_gralloc/wayland_drm_auth_client.h new file mode 100644 index 0000000000000000000000000000000000000000..69be0fa04193612989e7fb62f207faf385455bf6 --- /dev/null +++ b/display/hal/default_standard/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/display/hdi_service/gralloc/client/BUILD.gn b/display/hdi_service/gralloc/client/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..792c6970e8c6effe097d88d5dd32bd6ecbfd70ec --- /dev/null +++ b/display/hdi_service/gralloc/client/BUILD.gn @@ -0,0 +1,111 @@ +# 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. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +config("gralloc_client_public_config") { + include_dirs = [ + "//drivers/peripheral/base", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hdi_service/gralloc/include", + + # "//drivers/adapter/uhdf2/include/hdi", + # "//third_party/bounds_checking_function/include", + ] +} + +group("hdi_gralloc_client") { + deps = [ + ":libhdi_display_gralloc_client", + ":libhdi_display_gralloc_proxy", + ":libhdi_mapper_adapter", + ] + public_configs = [ ":gralloc_client_public_config" ] +} + +ohos_shared_library("libhdi_display_gralloc_client") { + include_dirs = [ + "//drivers/peripheral/base", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hdi_service/gralloc/include", + ] + sources = [ "display_gralloc_client.cpp" ] + deps = [ + ":libhdi_display_gralloc_proxy", + ":libhdi_mapper_adapter", + "$hdf_uhdf_path/hdi:libhdi", + "$hdf_uhdf_path/host:libhdf_host", + "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", + "$hdf_uhdf_path/osal:libhdf_utils", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core", + "//utils/native/base:utils", + ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "hdf" + part_name = "hdf" +} + +ohos_shared_library("libhdi_display_gralloc_proxy") { + include_dirs = [ + "//drivers/peripheral/base", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hdi_service/gralloc/include", + ] + sources = [ "allocator_proxy.cpp" ] + deps = [ + "$hdf_uhdf_path/hdi:libhdi", + "$hdf_uhdf_path/host:libhdf_host", + "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", + "$hdf_uhdf_path/osal:libhdf_utils", + "//foundation/graphic/standard/utils:buffer_handle", + "//utils/native/base:utils", + ] + + if (is_standard_system) { + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "hdf" + part_name = "hdf" +} + +ohos_shared_library("libhdi_mapper_adapter") { + include_dirs = [ + "//drivers/peripheral/base", + "//drivers/peripheral/display/interfaces/include", + ] + + sources = [ "mapper_adapter.cpp" ] + deps = [ + "$hdf_uhdf_path/osal:libhdf_utils", + "//drivers/peripheral/display/hal:hdi_display_gralloc", + ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "hdf" + part_name = "hdf" +} diff --git a/display/hdi_service/gralloc/client/allocator_proxy.cpp b/display/hdi_service/gralloc/client/allocator_proxy.cpp new file mode 100755 index 0000000000000000000000000000000000000000..913b8e8783f589dc787061bd9dabfed772d4c09b --- /dev/null +++ b/display/hdi_service/gralloc/client/allocator_proxy.cpp @@ -0,0 +1,90 @@ +/* + * 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 "allocator_proxy.h" +#include +#include "buffer_handle_parcel.h" +#include "iservmgr_hdi.h" +#include "parcel_utils.h" + +#define HDF_LOG_TAG HDI_DISP_PROXY + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +sptr IDisplayAllocator::Get(const char *serviceName) +{ + do { + using namespace OHOS::HDI::ServiceManager::V1_0; + static sptr servMgr = IServiceManager::Get(); + if (servMgr == nullptr) { + HDF_LOGE("%{public}s: IServiceManager failed", __func__); + break; + } + auto remote = servMgr->GetService(serviceName); + if (remote != nullptr) { + sptr hostSptr = iface_cast(remote); + if (hostSptr == nullptr) { + HDF_LOGE("%{public}s: IServiceManager GetService null ptr", __func__); + return nullptr; + } + HDF_LOGE("%{public}s: GetService %{public}s ok", __func__, serviceName); + return hostSptr; + } + HDF_LOGE("%{public}s: IServiceManager GetService %{public}s failed", __func__, serviceName); + } while(false); + + return nullptr; +} + +int32_t AllocatorProxy::AllocMem(const AllocInfo &info, BufferHandle *&handle) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + auto ret = ParcelUtils::PackAllocInfo(data, &info); + if (ret != DISPLAY_SUCCESS) { + return ret; + } + int32_t retCode = Remote()->SendRequest(CMD_REMOTE_ALLOCATOR_ALLOCMEM, data, reply, option); + if (retCode != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}x", __func__, retCode); + return retCode; + } + + retCode = reply.ReadInt32(); + if (retCode != HDF_SUCCESS) { + HDF_LOGE("%{public}s: Read retrun code failed, error code is %{public}x", __func__, retCode); + return retCode; + } + + auto retHandle = ReadBufferHandle(reply); + if (retHandle != nullptr) { + handle = retHandle; + retCode = DISPLAY_SUCCESS; + } else { + retCode = DISPLAY_NULL_PTR; + } + HDF_LOGE("%{public}s: %{public}s(%{public}d) end", __FILE__, __func__, __LINE__); + return retCode; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS diff --git a/display/hdi_service/gralloc/client/allocator_proxy.h b/display/hdi_service/gralloc/client/allocator_proxy.h new file mode 100755 index 0000000000000000000000000000000000000000..1471b9432117401a30cb643aea1368d5d46c5d36 --- /dev/null +++ b/display/hdi_service/gralloc/client/allocator_proxy.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_ALLOCATOR_PROXY_V1_0_H +#define HDI_ALLOCATOR_PROXY_V1_0_H + +#include "idisplay_allocator.h" +#include "iremote_proxy.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class AllocatorProxy : public IRemoteProxy { +public: + explicit AllocatorProxy(const sptr& impl) : IRemoteProxy(impl) {} + virtual ~AllocatorProxy() = default; + virtual int32_t AllocMem(const AllocInfo &info, BufferHandle *&handle) override; + +private: + static inline BrokerDelegator delegator_; + static constexpr int CMD_REMOTE_ALLOCATOR_ALLOCMEM = 0; + // static constexpr int CMD_REMOTE_ALLOCATOR_FREE = 1; + // static constexpr int CMD_REMOTE_ALLOCATOR_MMAP = 2; + // static constexpr int CMD_REMOTE_ALLOCATOR_UNMAP = 3; + // static constexpr int CMD_REMOTE_ALLOCATOR_INVALIDDATE = 4; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_ALLOCATOR_PROXY_V1_0_H + diff --git a/display/hdi_service/gralloc/client/display_gralloc_client.cpp b/display/hdi_service/gralloc/client/display_gralloc_client.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9fb93baa6be79a8b5816763468f70d3247d83549 --- /dev/null +++ b/display/hdi_service/gralloc/client/display_gralloc_client.cpp @@ -0,0 +1,115 @@ +/* + * 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_client.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG HDI_DISP_CLIENT + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +IDisplayGralloc *IDisplayGralloc::Get() +{ + IDisplayGralloc *instance = nullptr; + instance = new DisplayGrallocClient(); + if (instance == nullptr) { + HDF_LOGE("%{public}s: Can't new a DisplayGrallocClient instance", __func__); + } + HDF_LOGI("%{public}s: Get display gralloc client handle succ", __func__); + return instance; +} + +DisplayGrallocClient::DisplayGrallocClient() +{ + mapperAdapter_ = std::make_shared(); + if (mapperAdapter_ == nullptr) return; + + allocatorProxy_ = IDisplayAllocator::Get("hdi_display_gralloc_service"); + if (allocatorProxy_ == nullptr) return; + HDF_LOGI("%{public}s instance ok", __func__); +} + +int32_t DisplayGrallocClient::AllocMem(const AllocInfo &info, BufferHandle *&handle) const +{ + if (allocatorProxy_ == nullptr) { + HDF_LOGE("%{public}s: allocatorProxy_ is null", __func__); + } + auto ret = allocatorProxy_->AllocMem(info, handle); + return ret; +} + +void DisplayGrallocClient::FreeMem(const BufferHandle &handle) const +{ + mapperAdapter_->FreeBuffer(handle); +} + +void* DisplayGrallocClient::Mmap(const BufferHandle &handle) const +{ + void* data = nullptr; + int32_t ret = mapperAdapter_->MapBuffer(handle, data); + if (ret != DISPLAY_SUCCESS) { + FreeMem(handle); + HDF_LOGE("%{public}s: DisplayGrallocClient::Mmap, mapBuffer failed", __func__); + return nullptr; + } + return data; +} + +int32_t DisplayGrallocClient::Unmap(const BufferHandle &handle) const +{ + auto ret = mapperAdapter_->UnmapBuffer(handle); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed, ret %d", __func__, ret); + } + return ret; +} + +int32_t DisplayGrallocClient::FlushCache(const BufferHandle &handle) const +{ + auto ret = mapperAdapter_->FlushCache(handle); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed, ret %d", __func__, ret); + } + return ret; +} + +int32_t DisplayGrallocClient::InvalidateCache(const BufferHandle &handle) const +{ + auto ret = mapperAdapter_->InvalidateCache(handle); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGI("%{public}s: failed, ret %d", __func__, ret); + } + return ret; +} + +void* DisplayGrallocClient::MmapCache(const BufferHandle &handle) const +{ + (void)handle; + return nullptr; +} + +int32_t DisplayGrallocClient::FlushMCache(const BufferHandle &handle) const +{ + (void)handle; + return DISPLAY_NOT_SUPPORT; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS diff --git a/display/hdi_service/gralloc/client/display_gralloc_client.h b/display/hdi_service/gralloc/client/display_gralloc_client.h new file mode 100755 index 0000000000000000000000000000000000000000..57611d2e602efa8271fe457d435ee88f7ff2353e --- /dev/null +++ b/display/hdi_service/gralloc/client/display_gralloc_client.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 HDI_DISPLAY_GRALLOC_CLIENT_V1_0_H +#define HDI_DISPLAY_GRALLOC_CLIENT_V1_0_H + +#include "iservmgr_hdi.h" +#include "buffer_handle.h" +#include "display_type.h" +#include "idisplay_gralloc.h" +#include "allocator_proxy.h" +#include "mapper_adapter.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class DisplayGrallocClient : public IDisplayGralloc { +public: + DisplayGrallocClient(); + virtual ~DisplayGrallocClient() {} + virtual int32_t AllocMem(const AllocInfo& info, BufferHandle*& handle) const override; + virtual void FreeMem(const BufferHandle& handle) const override; + virtual void *Mmap(const BufferHandle& handle) const override; + virtual void *MmapCache(const BufferHandle &buffer) const override; + virtual int32_t Unmap(const BufferHandle& handle) const override; + virtual int32_t FlushCache(const BufferHandle &buffer) const override; + virtual int32_t FlushMCache(const BufferHandle &buffer) const override; + virtual int32_t InvalidateCache(const BufferHandle& handle) const override; + +private: + std::shared_ptr mapperAdapter_; + sptr allocatorProxy_; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_DISPLAY_GRALLOC_CLIENT_V1_0_H diff --git a/display/hdi_service/gralloc/client/idisplay_allocator.h b/display/hdi_service/gralloc/client/idisplay_allocator.h new file mode 100755 index 0000000000000000000000000000000000000000..06d2a8695cda89ac17617a02b4834879b9fddf95 --- /dev/null +++ b/display/hdi_service/gralloc/client/idisplay_allocator.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_IDISPLAY_ALLOCATOR_V1_0_H +#define HDI_IDISPLAY_ALLOCATOR_V1_0_H + +#include "iservmgr_hdi.h" +#include "hdf_log.h" +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class IDisplayAllocator: public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Display.Gralloc.IAllocator.V1_0"); + virtual ~IDisplayAllocator() {} + virtual int32_t AllocMem(const AllocInfo &info, BufferHandle *&handle) = 0; + static sptr Get(const char *serviceName); +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_IDISPLAY_ALLOCATOR_V1_0_H diff --git a/display/hdi_service/gralloc/client/mapper_adapter.cpp b/display/hdi_service/gralloc/client/mapper_adapter.cpp new file mode 100755 index 0000000000000000000000000000000000000000..91da5aeab07b84bac74723525f1c5bc244a90721 --- /dev/null +++ b/display/hdi_service/gralloc/client/mapper_adapter.cpp @@ -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. + */ + +#include "mapper_adapter.h" +#include "hdf_base.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG HDI_DISP_MAPPER + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +MapperAdapter::MapperAdapter() +{ + if (GrallocInitialize(&mapperFuncs_) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: mapperFuncs_ init failed", __func__); + } +} + +MapperAdapter::~MapperAdapter() +{ + if (GrallocUninitialize(mapperFuncs_) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: mapperFuncs_ uninit failed", __func__); + } +} + +bool MapperAdapter::IsReady() +{ + HDF_LOGI("%{public}s(%d): entry.", __func__, __LINE__); + return mapperFuncs_ != nullptr; +} + +int32_t MapperAdapter::MapBuffer(const BufferHandle& handle, void*& outData) const +{ + int32_t ret = 0; + outData = mapperFuncs_->Mmap(const_cast(&handle)); + return ret; +} + +int32_t MapperAdapter::UnmapBuffer(const BufferHandle& handle) const +{ + int32_t ret = 0; + ret = mapperFuncs_->Unmap(const_cast(&handle)); + return ret; +} + +int32_t MapperAdapter::InvalidateCache(const BufferHandle& handle) const +{ + int32_t ret = 0; + ret = mapperFuncs_->InvalidateCache(const_cast(&handle)); + return ret; +} + +int32_t MapperAdapter::FlushCache(const BufferHandle& handle) const +{ + int32_t ret = 0; + ret = mapperFuncs_->FlushCache(const_cast(&handle)); + return ret; +} + +void MapperAdapter::FreeBuffer(const BufferHandle& handle) const +{ + mapperFuncs_->FreeMem(const_cast(&handle)); +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/display/hdi_service/gralloc/client/mapper_adapter.h b/display/hdi_service/gralloc/client/mapper_adapter.h new file mode 100755 index 0000000000000000000000000000000000000000..21b70c2bbdfca1c9dc34ab33f776dae15d1352d8 --- /dev/null +++ b/display/hdi_service/gralloc/client/mapper_adapter.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_MAPPER_ADAPTER_V1_0_H +#define HDI_MAPPER_ADAPTER_V1_0_H + +#include "buffer_handle.h" +#include "display_gralloc.h" +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class MapperAdapter { +public: + MapperAdapter(); + virtual ~MapperAdapter(); + bool IsReady(); + int32_t MapBuffer(const BufferHandle& handle, void*& outData) const; + int32_t UnmapBuffer(const BufferHandle& handle) const; + int32_t InvalidateCache(const BufferHandle& handle) const; + int32_t FlushCache(const BufferHandle& handle) const; + void FreeBuffer(const BufferHandle& handle) const; + +private: + GrallocFuncs *mapperFuncs_ = nullptr; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_MAPPER_ADAPTER_V1_0_H diff --git a/display/hdi_service/gralloc/include/idisplay_gralloc.h b/display/hdi_service/gralloc/include/idisplay_gralloc.h new file mode 100755 index 0000000000000000000000000000000000000000..db0cb9da706a0ffe9c14c60ab6cee3311903d43f --- /dev/null +++ b/display/hdi_service/gralloc/include/idisplay_gralloc.h @@ -0,0 +1,141 @@ +/* + * 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_IDISPLAY_GRALLOC_V1_0_H +#define HDI_IDISPLAY_GRALLOC_V1_0_H + +#include "display_type.h" +#include "buffer_handle.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class IDisplayGralloc { +public: + virtual ~IDisplayGralloc() = default; + + /** + * @brief Get all interfaces of display gralloc. + * + * @return Returns IDisplayGralloc* if the operation is successful; returns an Null point otherwise. + * @since 1.0 + * @version 1.0 + */ + // static sptr Get(); + static IDisplayGralloc* Get(); + + /** + * @brief Allocates memory based on the parameters passed by the GUI. + * + * @param info Indicates the reference to the description info of the memory to allocate. + * + * @param handle Indicates the reference of pointer to the buffer of the memory to allocate. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual int32_t AllocMem(const AllocInfo &info, BufferHandle *&handle) const = 0; + + /** + * @brief Releases memory. + * + * @param handle Indicates the reference to the buffer of the memory to release. + * + * @since 1.0 + * @version 1.0 + */ + virtual void FreeMem(const BufferHandle &handle) const = 0; + + /** + * @brief Maps memory to memory without cache in the process's address space. + * + * @param handle Indicates the reference to the buffer of the memory to map. + * + * @return Returns the pointer to a valid address if the operation is successful; returns NULL otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual void *Mmap(const BufferHandle &handle) const = 0; + + /** + * @brief Maps memory to memory with cache in the process's address space. + * + * @param handle Indicates the reference to the buffer of the memory to map. + * + * @return Returns the pointer to a valid address if the operation is successful; returns NULL otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual void *MmapCache(const BufferHandle &buffer) const = 0; + + /** + * @brief Unmaps memory, that is, removes any mappings in the process's address space. + * + * @param handle Indicates the reference to the buffer of the memory to unmap. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual int32_t Unmap(const BufferHandle &handle) const = 0; + + /** + * @brief Flushes data from the cache to memory and invalidates the data in the cache. + * + * @param handle Indicates the reference to the buffer of the cache to flush. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual int32_t FlushCache(const BufferHandle &handle) const = 0; + + /** + * @brief Flushes data from the cache mapped via {@link Mmap} to memory and invalidates the data in the cache. + * + * @param handle Indicates the reference to the buffer of the cache to flush. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual int32_t FlushMCache(const BufferHandle &buffer) const = 0; + + /** + * @brief Invalidate the Cache, it will update the cache from memory. + * + * @param handle Indicates the reference to the buffer of the cache which will been invalidated + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual int32_t InvalidateCache(const BufferHandle &handle) const = 0; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif //HDI_IDISPLAY_GRALLOC_V1_0_H diff --git a/display/hdi_service/gralloc/include/parcel_utils.h b/display/hdi_service/gralloc/include/parcel_utils.h new file mode 100755 index 0000000000000000000000000000000000000000..abc2b9bbb4685281fde70ac22a3e0c53a09115e5 --- /dev/null +++ b/display/hdi_service/gralloc/include/parcel_utils.h @@ -0,0 +1,78 @@ +/* + * 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_PARCEL_UTILS_V1_0_H +#define HDI_PARCEL_UTILS_V1_0_H + +#include +#include "hdf_sbuf_ipc.h" +#include "display_type.h" +#include "hdf_log.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class ParcelUtils { +public: + static int32_t UnpackAllocInfo(MessageParcel &data, AllocInfo *pAllocInfo) + { + if (pAllocInfo == nullptr) { + return DISPLAY_NULL_PTR; + } + pAllocInfo->width = data.ReadUint32(); + pAllocInfo->height = data.ReadUint32(); + pAllocInfo->usage = data.ReadUint64(); + pAllocInfo->format = static_cast(data.ReadUint32()); + pAllocInfo->expectedSize = data.ReadUint32(); + return DISPLAY_SUCCESS; + } + + static int32_t PackAllocInfo(MessageParcel &data, const AllocInfo *pAllocInfo) + { + if (pAllocInfo == nullptr) { + return DISPLAY_NULL_PTR; + } + if (!data.WriteUint32(pAllocInfo->width)) { + HDF_LOGE("%{public}s: write AllocInfo width failed", __func__); + return DISPLAY_PARAM_ERR; + } + if (!data.WriteUint32(pAllocInfo->height)) { + HDF_LOGE("%{public}s: write AllocInfo height failed", __func__); + return DISPLAY_PARAM_ERR; + } + if (!data.WriteUint64(pAllocInfo->usage)) { + HDF_LOGE("%{public}s: write AllocInfo usage failed", __func__); + return DISPLAY_PARAM_ERR; + } + if (!data.WriteUint32(pAllocInfo->format)) {// enum type + HDF_LOGE("%{public}s: write AllocInfo format failed", __func__); + return DISPLAY_PARAM_ERR; + } + if (!data.WriteUint32(pAllocInfo->expectedSize)) {// enum type + HDF_LOGE("%{public}s: write AllocInfo type failed", __func__); + return DISPLAY_PARAM_ERR; + } + return DISPLAY_SUCCESS; + } +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_PARCEL_UTILS_V1_0_H diff --git a/display/hdi_service/gralloc/server/BUILD.gn b/display/hdi_service/gralloc/server/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..86858dbc4f405c02fe57e33069bb5de1b146ea3e --- /dev/null +++ b/display/hdi_service/gralloc/server/BUILD.gn @@ -0,0 +1,55 @@ +# 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. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +group("hdi_gralloc_stub") { + deps = [ ":libhdi_display_gralloc_stub" ] +} + +ohos_shared_library("libhdi_display_gralloc_stub") { + include_dirs = [ + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hdi_service/gralloc/include", + "//drivers/peripheral/base", + ] + + sources = [ + "allocator_host.cpp", + "allocator_service_stub.cpp", + ] + + deps = [ + "$hdf_uhdf_path/hdi:libhdi", + "$hdf_uhdf_path/host:libhdf_host", + "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", + "$hdf_uhdf_path/osal:libhdf_utils", + "//drivers/peripheral/display/hal:hdi_display_gralloc", + "//foundation/graphic/standard/utils:buffer_handle", + ] + + if (is_standard_system) { + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + + # install_images = [ "system" ] + # install_enable = true + subsystem_name = "hdf" + part_name = "hdf" +} diff --git a/display/hdi_service/gralloc/server/allocator_host.cpp b/display/hdi_service/gralloc/server/allocator_host.cpp new file mode 100755 index 0000000000000000000000000000000000000000..538f9a170d0e1bff084b6fa674d0359fa894b39e --- /dev/null +++ b/display/hdi_service/gralloc/server/allocator_host.cpp @@ -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. + */ + +#include "allocator_service_stub.h" +#include "hdf_base.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "osal_mem.h" + +using HdfAllocatorService = struct HdfAllocatorService_ { + struct IDeviceIoService ioservice; + void *instance; +}; + +static int32_t AllocatorServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, + struct HdfSBuf *data, struct HdfSBuf *reply) +{ + HdfAllocatorService *allocatorService = CONTAINER_OF( + client->device->service, HdfAllocatorService, ioservice); + return AllocatorServiceOnRemoteRequest(allocatorService->instance, cmdId, *data, *reply); +} + +int HdfAllocatorDriverInit(struct HdfDeviceObject *deviceObject) +{ + (void)deviceObject; + return HDF_SUCCESS; +} + +int HdfAllocatorDriverBind(struct HdfDeviceObject *deviceObject) +{ + HdfAllocatorService *allocatorService = + (HdfAllocatorService *)OsalMemAlloc(sizeof(HdfAllocatorService)); + if (allocatorService == nullptr) { + HDF_LOGE("%{public}s: OsalMemAlloc failed", __func__); + return HDF_FAILURE; + } + + allocatorService->ioservice.Dispatch = AllocatorServiceDispatch; + allocatorService->ioservice.Open = NULL; + allocatorService->ioservice.Release = NULL; + allocatorService->instance = AllocatorServiceStubInstance(); + + deviceObject->service = &allocatorService->ioservice; + HDF_LOGI("%{public}s: exit succ", __func__); + return HDF_SUCCESS; +} + +void HdfAllocatorDriverRelease(struct HdfDeviceObject *deviceObject) +{ + HdfAllocatorService *allocatorService = CONTAINER_OF(deviceObject->service, HdfAllocatorService, ioservice); + AllocatorServiceStubRelease(allocatorService->instance); + OsalMemFree(allocatorService); +} + +struct HdfDriverEntry g_AllocatorDriverEntry = { + .moduleVersion = 1, + .moduleName = "allocator_service", + .Bind = HdfAllocatorDriverBind, + .Init = HdfAllocatorDriverInit, + .Release = HdfAllocatorDriverRelease, +}; + +#ifndef __cplusplus +extern "C" { +#endif + +HDF_INIT(g_AllocatorDriverEntry); + +#ifndef __cplusplus +} +#endif diff --git a/display/hdi_service/gralloc/server/allocator_service_stub.cpp b/display/hdi_service/gralloc/server/allocator_service_stub.cpp new file mode 100755 index 0000000000000000000000000000000000000000..7442535bba2950d6d411c96a928798366b459952 --- /dev/null +++ b/display/hdi_service/gralloc/server/allocator_service_stub.cpp @@ -0,0 +1,130 @@ +/* + * 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 "allocator_service_stub.h" +#include "buffer_handle_parcel.h" +#include "buffer_handle_utils.h" +#include "hdf_base.h" +#include "hdf_log.h" +#include "hdf_sbuf_ipc.h" +#include "parcel_utils.h" + +#define HDF_LOG_TAG HDI_DISP_STUB + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +AllocatorServiceStub::AllocatorServiceStub() +{ + if (GrallocInitialize(&grallocFuncs_) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: gralloc init failed", __func__); + } +} + +AllocatorServiceStub::~AllocatorServiceStub() +{ + if (GrallocUninitialize(grallocFuncs_) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: gralloc uninit failed", __func__); + } +} + +int32_t AllocatorServiceStub::AllocMem(MessageParcel &data, + MessageParcel &reply, MessageOption &option) const +{ + AllocInfo info; + if (ParcelUtils::UnpackAllocInfo(data, &info) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: UnpackAllocInfo failed", __func__); + return HDF_ERR_INVALID_PARAM; + } + BufferHandle *buffer = nullptr; + int32_t errCode = grallocFuncs_->AllocMem(&info, &buffer); + + if (!reply.WriteInt32(errCode)) { + HDF_LOGE("AllocMem: write reply failed!"); + return HDF_FAILURE; + } + + if (errCode != HDF_SUCCESS) { + HDF_LOGE("%{public}s: call failed", __func__); + return errCode; + } + + if (WriteBufferHandle(reply, *buffer) != true) { + HDF_LOGE("%{public}s: WriteBufferHandle failed", __func__); + return HDF_ERR_INVALID_PARAM; + } + + FreeBufferHandle(buffer); + return HDF_SUCCESS; +} + +int32_t AllocatorServiceStub::OnRemoteRequest(int cmdId, + MessageParcel &data, MessageParcel &reply, MessageOption &option) const +{ + switch (cmdId) { + case CMD_ALLOCATOR_ALLOCMEM: + return AllocMem(data, reply, option); + default: { + HDF_LOGE("%{public}s: not support cmd", __func__); + return HDF_ERR_INVALID_PARAM; + } + } + return HDF_SUCCESS; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +using namespace OHOS::HDI::Display::V1_0; + +void *AllocatorServiceStubInstance() +{ + return reinterpret_cast(new AllocatorServiceStub()); +} + +void AllocatorServiceStubRelease(void *stubObj) +{ + delete reinterpret_cast(stubObj); + stubObj = nullptr; +} + +int32_t AllocatorServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf &data, struct HdfSBuf &reply) +{ + if (stub == nullptr) { + HDF_LOGE("%{public}s: stub is nullptr", __func__); + return HDF_FAILURE; + } + + AllocatorServiceStub *AllocatorStub = reinterpret_cast(stub); + OHOS::MessageParcel *dataParcel = nullptr; + OHOS::MessageParcel *replyParcel = nullptr; + + if (SbufToParcel(&reply, &replyParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (SbufToParcel(&data, &dataParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + OHOS::MessageOption option; + return AllocatorStub->OnRemoteRequest(cmdId, *dataParcel, *replyParcel, option); +} diff --git a/display/hdi_service/gralloc/server/allocator_service_stub.h b/display/hdi_service/gralloc/server/allocator_service_stub.h new file mode 100755 index 0000000000000000000000000000000000000000..1e31e512f9e2259412ee0b70a4fc711e5a9274e1 --- /dev/null +++ b/display/hdi_service/gralloc/server/allocator_service_stub.h @@ -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. + */ + +#ifndef HDI_ALLOCATOR_SERVICE_STUB_V1_0_H +#define HDI_ALLOCATOR_SERVICE_STUB_V1_0_H + +#include +#include +#include +#include "display_gralloc.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +enum { + CMD_ALLOCATOR_ALLOCMEM = 0, + CMD_ALLOCATOR_FREE, + CMD_ALLOCATOR_MMAP, + CMD_ALLOCATOR_UNMAP, + CMD_ALLOCATOR_INVALIDDATE, +}; + +class AllocatorServiceStub { +public: + AllocatorServiceStub(); + virtual ~AllocatorServiceStub(); + int32_t AllocMem(MessageParcel &data, MessageParcel &reply, MessageOption &option) const; + + int32_t OnRemoteRequest(int cmdId, MessageParcel &data, MessageParcel &reply, MessageOption &option) const; + +private: + GrallocFuncs *grallocFuncs_; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +void *AllocatorServiceStubInstance(); + +void AllocatorServiceStubRelease(void *obj); + +int32_t AllocatorServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf &data, struct HdfSBuf &reply); + +#endif // HDI_ALLOCATOR_SERVICE_STUB_V1_0_H diff --git a/display/hdi_service/media_layer/client/BUILD.gn b/display/hdi_service/media_layer/client/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..d8f18287784f6284e20c8e0857f7deda2df9d876 --- /dev/null +++ b/display/hdi_service/media_layer/client/BUILD.gn @@ -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. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +config("media_layer_public_config") { + include_dirs = [ + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hdi_service/media_layer/client", + "//drivers/adapter/uhdf2/include/hdi", + ] +} + +group("media_layer_client") { + if (is_standard_system) { + deps = [ ":libhdi_media_layer_client" ] + public_configs = [ ":media_layer_public_config" ] + } +} + +if (is_standard_system) { + ohos_shared_library("libhdi_media_layer_client") { + include_dirs = [ + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + ] + + sources = [ "display_layer_proxy.cpp" ] + + deps = [ + "$hdf_uhdf_path/hdi:libhdi", + "$hdf_uhdf_path/host:libhdf_host", + "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", + "$hdf_uhdf_path/osal:libhdf_utils", + "//foundation/graphic/standard/utils:buffer_handle", + ] + + if (is_standard_system) { + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + + # install_images = [ "vendor" ] + subsystem_name = "hdf" + part_name = "hdf" + } +} diff --git a/display/hdi_service/media_layer/client/display_layer_proxy.cpp b/display/hdi_service/media_layer/client/display_layer_proxy.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f5f68115ca85d358c60d1e0042b787ac74eb6653 --- /dev/null +++ b/display/hdi_service/media_layer/client/display_layer_proxy.cpp @@ -0,0 +1,433 @@ +/* + * 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_layer_proxy.h" +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +sptr IDisplayLayer::Get(const char *serviceName) +{ + do { + using namespace OHOS::HDI::ServiceManager::V1_0; + auto servMgr = IServiceManager::Get(); + if (servMgr == nullptr) { + HDF_LOGE("%{public}s: IServiceManager failed", __func__); + break; + } + + auto remote = servMgr->GetService(serviceName); + if (remote != nullptr) { + sptr layerSptr = iface_cast(remote); + return layerSptr; + } + HDF_LOGE("%{public}s: GetService failed! serviceName = %{public}s", __func__, serviceName); + } while (false); + + return nullptr; +} + +DispErrCode DisplayLayerProxy::InitDisplay(unsigned int devId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId)) { + HDF_LOGE("%{public}s: write devId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_INIT_DISPLAY, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::DeinitDisplay(unsigned int devId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId)) { + HDF_LOGE("%{public}s: write devId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_DEINIT_DISPLAY, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId)) { + HDF_LOGE("%{public}s: write devId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_GET_DISPLAY_INFO, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + return retCode; + } + + dispInfo = std::make_shared(); + if (dispInfo == nullptr) { + HDF_LOGE("%{public}s: dispInfo is nullptr", __func__); + return DISPLAY_FAILURE; + } + dispInfo->width = reply.ReadUint32(); + dispInfo->height = reply.ReadUint32(); + dispInfo->rotAngle = reply.ReadInt32(); + + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerProxy::CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId)) { + HDF_LOGE("%{public}s: write devId failed", __func__); + return DISPLAY_FAILURE; + } + + bool flag = data.WriteInt32(layerInfo.width); + flag |= data.WriteInt32(layerInfo.height); + flag |= data.WriteInt32(static_cast(layerInfo.type)); + flag |= data.WriteInt32(layerInfo.bpp); + flag |= data.WriteInt32(static_cast(layerInfo.pixFormat)); + if (!flag) { + HDF_LOGE("%s: write layer info failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_CREATE_LAYER, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + return retCode; + } + + layerId = reply.ReadUint32(); + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerProxy::CloseLayer(unsigned int devId, unsigned int layerId) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_CLOSE_LAYER, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + if (!data.WriteBool(visible)) { + HDF_LOGE("%{public}s: write visible failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_VISIBLE, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_VISIBLE_STATE, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + return retCode; + } + + visible = reply.ReadBool(); + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerProxy::SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + bool flag = data.WriteInt32(rect.x); + flag |= data.WriteInt32(rect.y); + flag |= data.WriteInt32(rect.w); + flag |= data.WriteInt32(rect.h); + if (!flag) { + HDF_LOGE("%s: write rect failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_RECT, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_RECT, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + return retCode; + } + + rect = std::make_shared(); + if (rect == nullptr) { + HDF_LOGE("%{public}s: rect is nullptr", __func__); + return DISPLAY_FAILURE; + } + rect->x = reply.ReadInt32(); + rect->y = reply.ReadInt32(); + rect->w = reply.ReadInt32(); + rect->h = reply.ReadInt32(); + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerProxy::SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + if (!data.WriteUint32(zorder)) { + HDF_LOGE("%{public}s: write zorder failed!", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_ZORDER, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_ZORDER, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + return retCode; + } + zorder = reply.ReadUint32(); + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerProxy::SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + if (!data.WriteUint32(static_cast(type))) { + HDF_LOGE("%{public}s: write transmode failed!", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_SET_TRANSFORM_MODE, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +DispErrCode DisplayLayerProxy::SetLayerBuffer(unsigned int devId, unsigned int layerId, + const BufferHandle &buffer, int fence) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteUint32(devId) || !data.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write devId or layerId failed", __func__); + return DISPLAY_FAILURE; + } + + if (!OHOS::WriteBufferHandle(data, buffer)) { + HDF_LOGE("%{public}s: write bufferHandle failed", __func__); + return DISPLAY_FAILURE; + } + + int32_t ret = Remote()->SendRequest(CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_BUFFER, data, reply, option); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); + return DISPLAY_FAILURE; + } + + DispErrCode retCode = static_cast(reply.ReadInt32()); + if (retCode != DISPLAY_SUCCESS) { + HDF_LOGE("%{public}s: failed retCode is %{public}d", __func__, retCode); + } + return retCode; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/display/hdi_service/media_layer/client/display_layer_proxy.h b/display/hdi_service/media_layer/client/display_layer_proxy.h new file mode 100755 index 0000000000000000000000000000000000000000..6c15c2af64eaaf2f03096edc4ec7be3e87243311 --- /dev/null +++ b/display/hdi_service/media_layer/client/display_layer_proxy.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-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_LAYER_PROXY_V1_0_H +#define HDI_DISPLAY_LAYER_PROXY_V1_0_H + +#include +#include "idisplay_layer.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class DisplayLayerProxy : public IRemoteProxy { +public: + explicit DisplayLayerProxy(const sptr& impl) : IRemoteProxy(impl) {} + virtual ~DisplayLayerProxy() {} + + virtual DispErrCode InitDisplay(unsigned int devId) override; + virtual DispErrCode DeinitDisplay(unsigned int devId) override; + virtual DispErrCode GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) override; + virtual DispErrCode CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) override; + virtual DispErrCode CloseLayer(unsigned int devId, unsigned int layerId) override; + virtual DispErrCode SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) override; + virtual DispErrCode GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) override; + virtual DispErrCode SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) override; + virtual DispErrCode GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) override; + virtual DispErrCode SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) override; + virtual DispErrCode GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) override; + virtual DispErrCode SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) override; + virtual DispErrCode SetLayerBuffer(unsigned int devId, unsigned int layerId, const BufferHandle &buffer, + int fence) override; + +private: + static constexpr int CMD_DISPLAY_LAYER_REMOTE_INIT_DISPLAY = 0; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_DEINIT_DISPLAY = 1; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_GET_DISPLAY_INFO = 2; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_CREATE_LAYER = 3; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_CLOSE_LAYER = 4; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_VISIBLE = 5; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_VISIBLE_STATE = 6; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_RECT = 7; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_RECT = 8; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_ZORDER = 9; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_GET_LAYER_ZORDER = 10; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_SET_TRANSFORM_MODE = 11; + static constexpr int CMD_DISPLAY_LAYER_REMOTE_SET_LAYER_BUFFER = 12; + + static inline BrokerDelegator delegator_; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_DISPLAY_LAYER_PROXY_V1_0_H diff --git a/display/hdi_service/media_layer/client/idisplay_layer.h b/display/hdi_service/media_layer/client/idisplay_layer.h new file mode 100755 index 0000000000000000000000000000000000000000..c1516e66a04c02e111ff3cf5f0ed1a1a241ba161 --- /dev/null +++ b/display/hdi_service/media_layer/client/idisplay_layer.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2020-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. + */ + +/** + * @addtogroup Display + * @{ + * + * @brief Defines driver functions of the display module. + * + * This module provides driver functions for the graphics subsystem, including graphics layer management, + * device control, graphics hardware acceleration, display memory management, and callbacks. + * + * @since 1.0 + * @version 1.0 + */ + +/** + * @file display_layer.h + * + * @brief Declares the driver functions for implementing layer operations. + * + * @since 1.0 + * @version 2.0 + */ + +#ifndef HDI_DISPLAY_LAYER_PXY_V1_0_H +#define HDI_DISPLAY_LAYER_PXY_V1_0_H + +#include +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class IDisplayLayer : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"HDI.DISPLAY.LAYER.V1_0"); + virtual ~IDisplayLayer() {} + + /** + * @brief Get the service object by service name. + * + * @param serviceName The service name. + * + * @return Returns the point to display layer service. + * + * @since 1.0 + * @version 1.0 + */ + static sptr Get(const char *serviceName); + + /** + * @brief Initializes a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see DeinitDisplay + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode InitDisplay(unsigned int devId) = 0; + + /** + * @brief Deinitializes a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see InitDisplay + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode DeinitDisplay(unsigned int devId) = 0; + + /** + * @brief Obtains information about a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param dispInfo Indicates the pointer to the display device information obtained. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) = 0; + + /** + * @brief Opens a layer on a specified display device. + * + * Before using a layer on the GUI, you must open the layer based on the layer information. After the layer is + * opened, you can obtain the layer ID and then use other functions based on the layer ID. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerInfo Indicates the pointer to the layer information passed to open a layer, including the layer + * type, layer size, and pixel format. + * @param layerId Indicates the pointer to the layer ID, which identifies a unique layer. The layer ID is returned + * to the GUI after the layer is successfully opened. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see CloseLayer + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) = 0; + + /** + * @brief Closes a layer that is no longer required on a specified display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see OpenLayer + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode CloseLayer(unsigned int devId, unsigned int layerId) = 0; + + /** + * @brief Sets whether a layer is visible. + * + * A visible layer is displayed on the screen, whereas an invisible layer is not displayed on the screen. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param visible Indicates the visibility to set for the layer. The value true means to set the layer to be + * visible, and false means the opposite. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see GetLayerVisibleState + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) = 0; + + /** + * @brief Checks whether a layer is visible. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param visible Indicates the pointer to the obtained layer visibility. The value true indicates that the + * layer is visible, and false indicates that the layer is invisible. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerVisible + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) = 0; + + /** + * @brief Sets the size of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param rect Indicates the pointer to the layer size to set, in pixels. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerRect + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) = 0; + + /** + * @brief Obtains the size of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param rect Indicates the pointer to the obtained layer size. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerRect + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) = 0; + + /** + * @brief Sets the z-order for a layer. + * + * A larger z-order value indicates a higher layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param zorder Indicates the z-order to set. The value is an integer ranging from 0 to 255. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see GetLayerZorder + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) = 0; + + /** + * @brief Obtains the z-order of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param zorder Indicates the pointer to the obtained z-order. The value is an integer ranging from 0 to 255. + * A larger z-order value indicates a higher layer. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerZorder + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) = 0; + + /** + * @brief Sets the transform mode for rotating, scaling, or moving a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param type Indicates the transformation mode to set. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) = 0; + + /** + * @brief Set the buffer for a layer. + * + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param buffer Indiactes pointer of the buffer handle, the buffer handle should contain all the information of the + * buffer which will been used for composition + * @param fence Indiactes the fd of a sync file + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 2.0 + * @version 2.0 + */ + virtual DispErrCode SetLayerBuffer(unsigned int devId, unsigned int layerId, const BufferHandle &buffer, + int fence) = 0; + +}; // class IDisplayLayer + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_DISPLAY_LAYER_V1_0_INTERFACE_H +/** @} */ diff --git a/display/hdi_service/media_layer/server/BUILD.gn b/display/hdi_service/media_layer/server/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..6e04a63aca4aba3b2f6b6b629a4e0e06559f8a3d --- /dev/null +++ b/display/hdi_service/media_layer/server/BUILD.gn @@ -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. + +import("//build/ohos.gni") +import("//drivers/adapter/uhdf2/uhdf.gni") + +group("media_layer_service") { + if (is_standard_system) { + deps = [ ":libhdi_media_layer_service" ] + } +} + +if (is_standard_system) { + ohos_shared_library("libhdi_media_layer_service") { + include_dirs = [ + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + ] + + sources = [ + "display_hdi_driver.cpp", + "display_layer_service_impl.cpp", + "display_layer_service_stub.cpp", + ] + + deps = [ + "$hdf_uhdf_path/hdi:libhdi", + "$hdf_uhdf_path/host:libhdf_host", + "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", + "$hdf_uhdf_path/osal:libhdf_utils", + "//drivers/peripheral/display/hal:hdi_display_gralloc", + "//foundation/graphic/standard/utils:buffer_handle", + ] + + if (target_cpu == "arm") { + deps += [ "//drivers/peripheral/display/hal:hdi_display_layer" ] + } + + if (is_standard_system) { + external_deps = [ + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + ] + } else { + external_deps = [ "hilog:libhilog" ] + } + + subsystem_name = "hdf" + part_name = "hdf" + } +} diff --git a/display/hdi_service/media_layer/server/display_hdi_driver.cpp b/display/hdi_service/media_layer/server/display_hdi_driver.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e359fb3b9175f2a0e3e6f12f9ed0d2add8486f45 --- /dev/null +++ b/display/hdi_service/media_layer/server/display_hdi_driver.cpp @@ -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. + */ + +#include +#include +#include +#include +#include "display_layer_service_stub.h" + +#define HDF_LOG_TAG display_hdi_service + +using HdfDisplayHdiService = struct _HdfDisplayHdiService { + struct IDeviceIoService ioservice; + void *instance; +}; + +static int32_t DisplayHdiServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, + struct HdfSBuf *data, struct HdfSBuf *reply) +{ + HdfDisplayHdiService *displayHdiService = CONTAINER_OF(client->device->service, HdfDisplayHdiService, ioservice); + return LayerServiceOnRemoteRequest(displayHdiService->instance, cmdId, data, reply); +} + +int HdfDisplayHostDriverInit(struct HdfDeviceObject *deviceObject) +{ + HDF_LOGI("%{public}s: enter", __func__); + return HDF_SUCCESS; +} + +int HdfDisplayHostDriverBind(struct HdfDeviceObject *deviceObject) +{ + HdfDisplayHdiService *displayHdiService = + reinterpret_cast(OsalMemAlloc(sizeof(HdfDisplayHdiService))); + if (displayHdiService == NULL) { + HDF_LOGE("%{public}s: OsalMemAlloc HdfDisplayHdiService failed", __func__); + return HDF_FAILURE; + } + + displayHdiService->ioservice.Dispatch = DisplayHdiServiceDispatch; + displayHdiService->ioservice.Open = NULL; + displayHdiService->ioservice.Release = NULL; + displayHdiService->instance = LayerStubInstance(); + + deviceObject->service = &displayHdiService->ioservice; + HDF_LOGI("%{public}s: exit succ", __func__); + return HDF_SUCCESS; +} + +void HdfDisplayHostDriverRelease(HdfDeviceObject *deviceObject) +{ + HdfDisplayHdiService *displayHdiService = CONTAINER_OF(deviceObject->service, HdfDisplayHdiService, ioservice); + OsalMemFree(displayHdiService); +} + +struct HdfDriverEntry g_displayHostDriverEntry = { + .moduleVersion = 1, + .moduleName = "hdi_display_layer_service", + .Bind = HdfDisplayHostDriverBind, + .Init = HdfDisplayHostDriverInit, + .Release = HdfDisplayHostDriverRelease, +}; + +#ifndef __cplusplus +extern "C" { +#endif + +HDF_INIT(g_displayHostDriverEntry); + +#ifndef __cplusplus +} +#endif diff --git a/display/hdi_service/media_layer/server/display_layer_service_impl.cpp b/display/hdi_service/media_layer/server/display_layer_service_impl.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8701cf3137be348d2a525ed31b88995c3d0ae972 --- /dev/null +++ b/display/hdi_service/media_layer/server/display_layer_service_impl.cpp @@ -0,0 +1,217 @@ +/* + * 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_layer_service_impl.h" +#include +#include +#include "display_gralloc.h" +#include "display_layer.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +static LayerFuncs *g_layerFuncs = nullptr; +static GrallocFuncs *g_grallocFuncs = nullptr; + +DispErrCode DisplayLayerService::InitDisplay(unsigned int devId) +{ + if (g_layerFuncs != nullptr) { + return DISPLAY_SUCCESS; + } + + int32_t ret = LayerInitialize(&g_layerFuncs); + if (ret != DISPLAY_SUCCESS || g_layerFuncs == nullptr) { + HDF_LOGE("layer init fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + + if (g_layerFuncs->InitDisplay == nullptr || g_layerFuncs->CreateLayer == nullptr || + g_layerFuncs->GetDisplayInfo == nullptr) { + HDF_LOGE("layer func is invalid"); + return DISPLAY_FAILURE; + } + + ret = g_layerFuncs->InitDisplay(devId); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("init display fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + + if (g_grallocFuncs == nullptr){ + ret = GrallocInitialize(&g_grallocFuncs); + if (ret != DISPLAY_SUCCESS || g_grallocFuncs == nullptr) { + LayerUninitialize(g_layerFuncs); + g_layerFuncs = nullptr; + HDF_LOGE("%{public}s: GrallocInitialize fail, ret=%{public}d",__func__, ret); + return DISPLAY_FAILURE; + } + } + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerService::DeinitDisplay(unsigned int devId) +{ + if (g_layerFuncs != nullptr && g_layerFuncs->DeinitDisplay != nullptr) { + (void)g_layerFuncs->DeinitDisplay(devId); + } + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerService::GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) +{ + if (g_layerFuncs == nullptr) { + HDF_LOGE("video display not inited"); + return DISPLAY_FAILURE; + } + + int32_t ret = g_layerFuncs->GetDisplayInfo(devId, dispInfo.get()); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("get display info fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerService::CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) +{ + int32_t ret; + LayerInfo info = layerInfo; + if (g_layerFuncs == nullptr) { + ret = InitDisplay(devId); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("InitDisplay fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + std::shared_ptr dispInfo = std::make_shared(); + ret = GetDisplayInfo(devId, dispInfo); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("InitDisplay fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + if (info.height == 0 && info.width == 0) { + info.width = dispInfo->width; + info.height = dispInfo->height; + } + } + + ret = g_layerFuncs->CreateLayer(devId, &info, &layerId); + if (ret != DISPLAY_SUCCESS) { + HDF_LOGE("create layer fail, ret=%{public}d", ret); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerService::CloseLayer(unsigned int devId, unsigned int layerId) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->CloseLayer == nullptr) { + HDF_LOGE("may not inited or CloseLayer nullptr"); + return DISPLAY_FAILURE; + } + (void)g_layerFuncs->CloseLayer(devId, layerId); + return DISPLAY_SUCCESS; +} + +DispErrCode DisplayLayerService::SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->SetLayerVisible == nullptr) { + HDF_LOGE("may not inited or SetLayerVisible nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->SetLayerVisible(devId, layerId, visible); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->GetLayerVisibleState == nullptr) { + HDF_LOGE("may not inited or GetLayerVisibleState nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->GetLayerVisibleState(devId, layerId, &visible); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->SetLayerSize == nullptr) { + HDF_LOGE("may not inited or SetLayerSize nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->SetLayerSize(devId, layerId, &rect); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->GetLayerSize == nullptr) { + HDF_LOGE("may not inited or GetLayerSize nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->GetLayerSize(devId, layerId, rect.get()); + + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->SetLayerZorder == nullptr) { + HDF_LOGE("may not inited or SetLayerZorder nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->SetLayerZorder(devId, layerId, zorder); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->GetLayerZorder == nullptr) { + HDF_LOGE("may not inited or GetLayerZorder nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->GetLayerZorder(devId, layerId, &zorder); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->SetTransformMode == nullptr) { + HDF_LOGE("may not inited or SetTransformMode nullptr"); + return DISPLAY_FAILURE; + } + int32_t ret = g_layerFuncs->SetTransformMode(devId, layerId, type); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +DispErrCode DisplayLayerService::SetLayerBuffer(unsigned int devId, unsigned int layerId, const BufferHandle &buffer, int fence) +{ + if (g_layerFuncs == nullptr || g_layerFuncs->SetLayerBuffer == nullptr) { + HDF_LOGE("may not inited or SetLayerBuffer nullptr"); + return DISPLAY_FAILURE; + } + BufferHandle bufferTemp = buffer; + bufferTemp.virAddr = g_grallocFuncs->Mmap(&bufferTemp); + int32_t ret = g_layerFuncs->SetLayerBuffer(devId, layerId, &bufferTemp, fence); + (void)g_grallocFuncs->Unmap(&bufferTemp); + return (ret == DISPLAY_SUCCESS) ? DISPLAY_SUCCESS : DISPLAY_FAILURE; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS diff --git a/display/hdi_service/media_layer/server/display_layer_service_impl.h b/display/hdi_service/media_layer/server/display_layer_service_impl.h new file mode 100755 index 0000000000000000000000000000000000000000..582c5190b25c67fbdf724395d3d6b5cb1bea3f91 --- /dev/null +++ b/display/hdi_service/media_layer/server/display_layer_service_impl.h @@ -0,0 +1,49 @@ +/* + * 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_LAYER_SERVICE_IMPL_V1_0_H +#define HDI_DISPLAY_LAYER_SERVICE_IMPL_V1_0_H + +#include "idisplay_layer.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class DisplayLayerService : public IDisplayLayer { +public: + + virtual DispErrCode InitDisplay(unsigned int devId) override; + virtual DispErrCode DeinitDisplay(unsigned int devId) override; + virtual DispErrCode GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) override; + virtual DispErrCode CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) override; + virtual DispErrCode CloseLayer(unsigned int devId, unsigned int layerId) override; + virtual DispErrCode SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) override; + virtual DispErrCode GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) override; + virtual DispErrCode SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) override; + virtual DispErrCode GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) override; + virtual DispErrCode SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) override; + virtual DispErrCode GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) override; + virtual DispErrCode SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) override; + virtual DispErrCode SetLayerBuffer(unsigned int devId, unsigned int layerId, const BufferHandle &buffer, int fence) override; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_DISPLAY_LAYER_SERVICE_IMPL_V1_0_H \ No newline at end of file diff --git a/display/hdi_service/media_layer/server/display_layer_service_stub.cpp b/display/hdi_service/media_layer/server/display_layer_service_stub.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5fad37aec08c15dd93d94da6728c3ae338d7aeb2 --- /dev/null +++ b/display/hdi_service/media_layer/server/display_layer_service_stub.cpp @@ -0,0 +1,389 @@ +/* + * 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_layer_service_stub.h" +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +DisplayLayerStub::DisplayLayerStub() +{ +} + +DispErrCode DisplayLayerStub::Init() +{ + layerService_ = std::make_shared(); + if (layerService_ == nullptr) { + HDF_LOGE("%{public}s: layer service start failed", __func__); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubInitDisplay( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + + DispErrCode retCode = layerService_->InitDisplay(devId); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubDeinitDisplay( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + + DispErrCode retCode = layerService_->DeinitDisplay(devId); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubGetDisplayInfo( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + std::shared_ptr dispInfo = std::make_shared(); + + DispErrCode retCode = layerService_->GetDisplayInfo(devId, dispInfo); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + + bool flag = reply.WriteUint32(dispInfo->width); + flag |= reply.WriteUint32(dispInfo->height); + flag |= reply.WriteInt32(dispInfo->rotAngle); + if (!flag) { + HDF_LOGE("%{public}s: write display info failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubCreateLayer( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = 0; + LayerInfo pLayerInfo; + + pLayerInfo.width = data.ReadInt32(); + pLayerInfo.height = data.ReadInt32(); + pLayerInfo.type = static_cast(data.ReadInt32()); + pLayerInfo.bpp = data.ReadInt32(); + pLayerInfo.pixFormat = static_cast(data.ReadInt32()); + + DispErrCode retCode = layerService_->CreateLayer(devId, pLayerInfo, layerId); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + + if (!reply.WriteUint32(layerId)) { + HDF_LOGE("%{public}s: write layerId failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubCloseLayer( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + + DispErrCode retCode = layerService_->CloseLayer(devId, layerId); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubSetLayerVisible( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + bool visible = data.ReadBool(); + + DispErrCode retCode = layerService_->SetLayerVisible(devId, layerId, visible); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubGetLayerVisibleState( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + bool visible = false; + + DispErrCode retCode = layerService_->GetLayerVisibleState(devId, layerId, visible); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + + if (!reply.WriteBool(visible)) { + HDF_LOGE("%{public}s: write visible state failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubSetLayerRect( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + IRect rect; + + rect.x = data.ReadInt32(); + rect.y = data.ReadInt32(); + rect.w = data.ReadInt32(); + rect.h = data.ReadInt32(); + + DispErrCode retCode = layerService_->SetLayerRect(devId, layerId, rect); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubGetLayerRect( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + std::shared_ptr rect = std::make_shared(); + + DispErrCode retCode = layerService_->GetLayerRect(devId, layerId, rect); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + + bool flag = reply.WriteInt32(rect->x); + flag |= reply.WriteInt32(rect->y); + flag |= reply.WriteInt32(rect->w); + flag |= reply.WriteInt32(rect->h); + if (!flag) { + HDF_LOGE("%{public}s: write rect failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubSetLayerZorder( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + uint32_t zorder = data.ReadUint32(); + + DispErrCode retCode = layerService_->SetLayerZorder(devId, layerId, zorder); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubGetLayerZorder( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + uint32_t zorder = 0; + + DispErrCode retCode = layerService_->GetLayerZorder(devId, layerId, zorder); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + + if (!reply.WriteUint32(zorder)) { + HDF_LOGE("%{public}s: write zorder failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubSetLayerTransformMode( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + TransformType transForm = static_cast(data.ReadUint32()); + + DispErrCode retCode = layerService_->SetTransformMode(devId, layerId, transForm); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubSetLayerBuffer( + MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + uint32_t devId = data.ReadUint32(); + uint32_t layerId = data.ReadUint32(); + BufferHandle *buffer = nullptr; + + buffer = OHOS::ReadBufferHandle(data); + if (buffer == nullptr) { + HDF_LOGE("%{public}s: read bufferHandle failed", __func__); + return DISPLAY_FAILURE; + } + buffer->virAddr = nullptr; + uint32_t fence = data.ReadInt32(); + + DispErrCode retCode = layerService_->SetLayerBuffer(devId, layerId, *buffer, fence); + (void)FreeBufferHandle(buffer); + if (!reply.WriteInt32(static_cast(retCode))) { + HDF_LOGE("%{public}s: write retcode failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +int32_t DisplayLayerStub::LayerStubOnRemoteRequest(int cmdId, MessageParcel &data, + MessageParcel &reply, MessageOption &option) +{ + switch (cmdId) { + case CMD_DISPLAY_LAYER_INIT_DISPLAY: { + return LayerStubInitDisplay(data, reply, option); + } + case CMD_DISPLAY_LAYER_DEINIT_DISPLAY: { + return LayerStubDeinitDisplay(data, reply, option); + } + case CMD_DISPLAY_LAYER_GET_DISPLAY_INFO: { + return LayerStubGetDisplayInfo(data, reply, option); + } + case CMD_DISPLAY_LAYER_CREATE_LAYER: { + return LayerStubCreateLayer(data, reply, option); + } + case CMD_DISPLAY_LAYER_CLOSE_LAYER: { + return LayerStubCloseLayer(data, reply, option); + } + case CMD_DISPLAY_LAYER_SET_LAYER_BUFFER: { + return LayerStubSetLayerBuffer(data, reply, option); + } + case CMD_DISPLAY_LAYER_SET_LAYER_RECT: { + return LayerStubSetLayerRect(data, reply, option); + } + case CMD_DISPLAY_LAYER_GET_LAYER_RECT: { + return LayerStubGetLayerRect(data, reply, option); + } + case CMD_DISPLAY_LAYER_SET_LAYER_ZORDER: { + return LayerStubSetLayerZorder(data, reply, option); + } + case CMD_DISPLAY_LAYER_GET_LAYER_ZORDER: { + return LayerStubGetLayerZorder(data, reply, option); + } + case CMD_DISPLAY_LAYER_SET_LAYER_VISIBLE: { + return LayerStubSetLayerVisible(data, reply, option); + } + case CMD_DISPLAY_LAYER_GET_LAYER_VISIBLE_STATE: { + return LayerStubGetLayerVisibleState(data, reply, option); + } + case CMD_DISPLAY_LAYER_SET_TRANSFORM_MODE: { + return LayerStubSetLayerTransformMode(data, reply, option); + } + default: { + HDF_LOGE("%{public}s: not support cmd %{public}d", __func__, cmdId); + return HDF_ERR_INVALID_PARAM; + } + } + return HDF_SUCCESS; +} + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +using namespace OHOS::HDI::Display::V1_0; + +void *LayerStubInstance() +{ + DisplayLayerStub *stub = + new (std::nothrow) DisplayLayerStub(); + if (stub == nullptr) { + HDF_LOGE("%{public}s: display layer stub create failed", __func__); + return nullptr; + } + + DispErrCode ret = stub->Init(); + if (ret != DISPLAY_SUCCESS) { + delete stub; + stub = nullptr; + return nullptr; + } + return reinterpret_cast(stub); +} + +void DestroyLayerStub(void *stubObj) +{ + delete reinterpret_cast(stubObj); + stubObj = nullptr; +} + +int32_t LayerServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + if (stub == nullptr) { + HDF_LOGE("%{public}s:stub is nullptr", __func__); + return HDF_FAILURE; + } + + DisplayLayerStub *layerStub = + reinterpret_cast(stub); + OHOS::MessageParcel *dataParcel = nullptr; + OHOS::MessageParcel *replyParcel = nullptr; + + if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + OHOS::MessageOption option; + return layerStub->LayerStubOnRemoteRequest(cmdId, *dataParcel, *replyParcel, option); +} diff --git a/display/hdi_service/media_layer/server/display_layer_service_stub.h b/display/hdi_service/media_layer/server/display_layer_service_stub.h new file mode 100755 index 0000000000000000000000000000000000000000..90af419bb547e950ac8b37349824d8c0a2e3568d --- /dev/null +++ b/display/hdi_service/media_layer/server/display_layer_service_stub.h @@ -0,0 +1,82 @@ +/* + * 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_LAYER_SERVICE_STUB_V1_0_H +#define HDI_DISPLAY_LAYER_SERVICE_STUB_V1_0_H + +#include +#include +#include +#include "idisplay_layer.h" +#include "display_layer_service_impl.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +enum { + CMD_DISPLAY_LAYER_INIT_DISPLAY = 0, + CMD_DISPLAY_LAYER_DEINIT_DISPLAY, + CMD_DISPLAY_LAYER_GET_DISPLAY_INFO, + CMD_DISPLAY_LAYER_CREATE_LAYER, + CMD_DISPLAY_LAYER_CLOSE_LAYER, + CMD_DISPLAY_LAYER_SET_LAYER_VISIBLE, + CMD_DISPLAY_LAYER_GET_LAYER_VISIBLE_STATE, + CMD_DISPLAY_LAYER_SET_LAYER_RECT, + CMD_DISPLAY_LAYER_GET_LAYER_RECT, + CMD_DISPLAY_LAYER_SET_LAYER_ZORDER, + CMD_DISPLAY_LAYER_GET_LAYER_ZORDER, + CMD_DISPLAY_LAYER_SET_TRANSFORM_MODE, + CMD_DISPLAY_LAYER_SET_LAYER_BUFFER, +}; + +class DisplayLayerStub { +public: + DisplayLayerStub(); + virtual ~DisplayLayerStub() {} + + DispErrCode Init(); + int32_t LayerStubInitDisplay(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubDeinitDisplay(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubGetDisplayInfo(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubCreateLayer(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubCloseLayer(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubSetLayerVisible(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubGetLayerVisibleState(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubSetLayerRect(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubGetLayerRect(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubSetLayerZorder(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubGetLayerZorder(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubSetLayerTransformMode(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubSetLayerBuffer(MessageParcel& data, MessageParcel& reply, MessageOption& option); + int32_t LayerStubOnRemoteRequest(int cmdId, MessageParcel& data, MessageParcel& reply, MessageOption& option); + +private: + std::shared_ptr layerService_ = nullptr; +}; + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +void *LayerStubInstance(); + +void DestroyLayerStub(void *obj); + +int32_t LayerServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply); + +#endif // HDI_DISPLAY_LAYER_SERVICE_STUB_V1_0_H \ No newline at end of file diff --git a/display/hdi_service/media_layer/server/idisplay_layer.h b/display/hdi_service/media_layer/server/idisplay_layer.h new file mode 100755 index 0000000000000000000000000000000000000000..d59c0fd5ff9760c579594fc32d872b282f60a0c7 --- /dev/null +++ b/display/hdi_service/media_layer/server/idisplay_layer.h @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2020-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. + */ + +/** + * @addtogroup Display + * @{ + * + * @brief Defines driver functions of the display module. + * + * This module provides driver functions for the graphics subsystem, including graphics layer management, + * device control, graphics hardware acceleration, display memory management, and callbacks. + * + * @since 1.0 + * @version 1.0 + */ + +/** + * @file display_layer.h + * + * @brief Declares the driver functions for implementing layer operations. + * + * @since 1.0 + * @version 2.0 + */ + +#ifndef HDI_DISPLAY_LAYER_STB_V1_0_H +#define HDI_DISPLAY_LAYER_STB_V1_0_H + +#include +#include "display_type.h" + +namespace OHOS { +namespace HDI { +namespace Display { +namespace V1_0 { + +class IDisplayLayer { +public: + explicit IDisplayLayer() {} + virtual ~IDisplayLayer() {} + + /** + * @brief Initializes a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see DeinitDisplay + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode InitDisplay(unsigned int devId) = 0; + + /** + * @brief Deinitializes a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see InitDisplay + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode DeinitDisplay(unsigned int devId) = 0; + + /** + * @brief Obtains information about a display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param dispInfo Indicates the pointer to the display device information obtained. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetDisplayInfo(unsigned int devId, std::shared_ptr &dispInfo) = 0; + + /** + * @brief Opens a layer on a specified display device. + * + * Before using a layer on the GUI, you must open the layer based on the layer information. After the layer is + * opened, you can obtain the layer ID and then use other functions based on the layer ID. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerInfo Indicates the pointer to the layer information passed to open a layer, including the layer + * type, layer size, and pixel format. + * @param layerId Indicates the pointer to the layer ID, which identifies a unique layer. The layer ID is returned + * to the GUI after the layer is successfully opened. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see CloseLayer + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode CreateLayer(unsigned int devId, LayerInfo &layerInfo, unsigned int &layerId) = 0; + + /** + * @brief Closes a layer that is no longer required on a specified display device. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see OpenLayer + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode CloseLayer(unsigned int devId, unsigned int layerId) = 0; + + /** + * @brief Sets whether a layer is visible. + * + * A visible layer is displayed on the screen, whereas an invisible layer is not displayed on the screen. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param visible Indicates the visibility to set for the layer. The value true means to set the layer to be + * visible, and false means the opposite. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see GetLayerVisibleState + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerVisible(unsigned int devId, unsigned int layerId, bool visible) = 0; + + /** + * @brief Checks whether a layer is visible. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param visible Indicates the pointer to the obtained layer visibility. The value true indicates that the + * layer is visible, and false indicates that the layer is invisible. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerVisible + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerVisibleState(unsigned int devId, unsigned int layerId, bool &visible) = 0; + + /** + * @brief Sets the size of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param rect Indicates the pointer to the layer size to set, in pixels. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerRect + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerRect(unsigned int devId, unsigned int layerId, IRect &rect) = 0; + + /** + * @brief Obtains the size of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param rect Indicates the pointer to the obtained layer size. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerRect + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerRect(unsigned int devId, unsigned int layerId, std::shared_ptr &rect) = 0; + + /** + * @brief Sets the z-order for a layer. + * + * A larger z-order value indicates a higher layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param zorder Indicates the z-order to set. The value is an integer ranging from 0 to 255. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see GetLayerZorder + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int zorder) = 0; + + /** + * @brief Obtains the z-order of a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param zorder Indicates the pointer to the obtained z-order. The value is an integer ranging from 0 to 255. + * A larger z-order value indicates a higher layer. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @see SetLayerZorder + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode GetLayerZorder(unsigned int devId, unsigned int layerId, unsigned int &zorder) = 0; + + /** + * @brief Sets the transform mode for rotating, scaling, or moving a layer. + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param type Indicates the transformation mode to set. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 1.0 + * @version 1.0 + */ + virtual DispErrCode SetTransformMode(unsigned int devId, unsigned int layerId, TransformType &type) = 0; + + /** + * @brief Set the buffer for a layer. + * + * + * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates the first + * display device and 4 indicates the last display device. + * @param layerId Indicates the layer ID, which identifies a unique layer. You can perform operations on the layer + * with the specified layer ID. + * @param buffer Indiactes pointer of the buffer handle, the buffer handle should contain all the information of the + * buffer which will been used for composition + * @param fence Indiactes the fd of a sync file + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + * @since 2.0 + * @version 2.0 + */ + virtual DispErrCode SetLayerBuffer(unsigned int devId, unsigned int layerId, const BufferHandle &buffer, + int fence) = 0; + +}; // class IDisplayLayer + +} // namespace V1_0 +} // namespace Display +} // namespace HDI +} // namespace OHOS + +#endif // HDI_DISPLAY_LAYER_STB_V1_0_H +/** @} */ diff --git a/display/interfaces/hdi_cpp/client/BUILD.gn b/display/interfaces/hdi_cpp/client/BUILD.gn old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/client/display_layer_proxy.cpp b/display/interfaces/hdi_cpp/client/display_layer_proxy.cpp old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/client/display_layer_proxy.h b/display/interfaces/hdi_cpp/client/display_layer_proxy.h old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/client/idisplay_layer.h b/display/interfaces/hdi_cpp/client/idisplay_layer.h old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/BUILD.gn b/display/interfaces/hdi_cpp/server/BUILD.gn old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/display_hdi_driver.cpp b/display/interfaces/hdi_cpp/server/display_hdi_driver.cpp old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/display_layer_service_impl.cpp b/display/interfaces/hdi_cpp/server/display_layer_service_impl.cpp old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/display_layer_service_impl.h b/display/interfaces/hdi_cpp/server/display_layer_service_impl.h old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/display_layer_service_stub.cpp b/display/interfaces/hdi_cpp/server/display_layer_service_stub.cpp old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/display_layer_service_stub.h b/display/interfaces/hdi_cpp/server/display_layer_service_stub.h old mode 100644 new mode 100755 diff --git a/display/interfaces/hdi_cpp/server/idisplay_layer.h b/display/interfaces/hdi_cpp/server/idisplay_layer.h old mode 100644 new mode 100755 diff --git a/display/interfaces/include/display_device.h b/display/interfaces/include/display_device.h index d0cfd7579fb082b52fc96451d6e8aa58c0692ff9..542718098426ccc01396a906c63dee36070fa49d 100644 --- a/display/interfaces/include/display_device.h +++ b/display/interfaces/include/display_device.h @@ -42,84 +42,493 @@ extern "C" { #endif +/* * + * @brief Called when a hot plug event occurs. + * + * This callback must be registered by calling RegHotPlugCallback. + * + * @param devId Indicates the ID of the display device. This ID is generated by the HDI implementation layer and transferred to the graphics service through the current callback. It identifies the display device to connect. + * @param connected Indicates the connection status of the display device. The value true means that the display device is connected, and false means the opposite. + * @param data Indicates the private data carried by the graphics service. This parameter carries the private data address transferred when RegHotPlugCallback is called. For details, see {@link RegHotPlugCallback}. + * + * + * @since 1.0 + * @version 1.0 + */ +typedef void (*HotPlugCallback)(uint32_t devId, bool connected, void *data); + +/* * + * @brief Called when a VBLANK event occurs. + * + * This callback must be registered by calling RegDisplayVBlankCallback. + * + * @param sequence Indicates the VBLANK sequence, which is an accumulated value. + * @param ns Indicates the timestamp (in ns) of the VBLANK event. + * @param data Indicates the pointer to the private data carried by the graphics service. This parameter carries + * the address passed when RegDisplayVBlankCallback is called. + * + * @since 1.0 + * @version 1.0 + */ +typedef void (*VBlankCallback)(unsigned int sequence, uint64_t ns, void *data); + +/* * + * @brief Called when the graphics service needs to refresh data frames. + * + * This callback must be registered by calling RegDisplayRefreshCallback. + * + * @param devId Indicates the ID of the display device. + * @param data Indicates the pointer to the private data carried by the graphics service. This parameter carries + * the address passed when RegDisplayRefreshCallback is called. + * + * @since 1.0 + * @version 1.0 + */ +typedef void (*RefreshCallback)(uint32_t devId, void *data); + /** * @brief Defines pointers to the functions of the display device. */ typedef struct { - /** - * @brief Sets the power status. + /* * + * @brief Registers the callback to be invoked when a hot plug event occurs. * - * When the OS enters the sleep mode or wakes up from the sleep mode, the display service or - * the power management module can set the power status of the display device, so that the driver IC - * of the device can normally enter the specified state. + * * - * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates - * the first display device and 4 indicates the last display device. - * @param status Indicates the power status to set. The display service determines whether to set the - * display device to the on or off state based on this setting. For details, see @link PowerStatus}. + * @param callback Indicates the instance used to notify the graphics service of a hot plug event occurred. + * @param data Indicates the pointer to the private data returned to the graphics service in the HotPlugCallback callback. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * @since 1.0 * @version 1.0 */ - int32_t (*SetDisplayPowerStatus)(uint32_t devId, DispPowerStatus status); + int32_t (*RegHotPlugCallback)(HotPlugCallback callback, void *data); + + /* * + * @brief Registers the callback to be invoked when a VBLANK event occurs. + * + * + * + * @param devId Indicates the ID of the display device. + * @param callback Indicates the instance used to notify the graphics service of the VBLANK event occurred when DisplayVsync is enabled. + * @param data Indicates the pointer to the private data returned to the graphics service in the VBlankCallback callback. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*RegDisplayVBlankCallback)(uint32_t devId, VBlankCallback callback, void *data); + + /* * + * @brief Called when the graphics service needs to refresh data frames. + * + * + * + * @param devId Indicates the ID of the display device. + * @param callback Indicates the instance used to notify the graphics service of the request for refreshing data frames. + * @param data Indicates the pointer to the private data returned to the graphics service in the RefreshCallback callback. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*RegDisplayRefreshCallback)(uint32_t devId, RefreshCallback callback, void *data); + + /* * + * @brief Obtains the capabilities of a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param info Indicates the pointer to the capabilities supported by the display device. For details, see {@link DisplayCapability}. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplayCapability)(uint32_t devId, DisplayCapability *info); + + /* * + * @brief Obtains the display modes supported by a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param num Indicates the pointer to the number of modes supported by the display device. + * @param modes Indicates the pointer to the information about all modes supported by the display device, including all supported resolutions and refresh rates. Each mode has an ID, which will be used when + * the mode is set or obtained. For details, see {@link DisplayModeInfo}. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplaySuppportedModes)(uint32_t devId, int *num, DisplayModeInfo *modes); - /** - * @brief Obtains the power status. + /* * + * @brief Obtains the current display mode of a display device. * - * You can use this function to obtain the power status of the display device specified by devId. + * * - * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates - * the first display device and 4 indicates the last display device. - * @param status Indicates the power status of the display device specified by devId. For details, - * see {@link PowerStatus}. + * @param devId Indicates the ID of the display device. + * @param modeId indicates the pointer to the ID of the current display mode of the device. The display mode ID is written by this API. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplayMode)(uint32_t devId, uint32_t *modeId); + + /* * + * @brief Sets the display mode of a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param modeId Indicates the ID of the display mode. The device is switched to the display mode specified by this parameter in this interface. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayMode)(uint32_t devId, uint32_t modeId); + + /* * + * @brief Obtains the power status of a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param status Indicates the pointer to the power status of the device. The status is written by this interface. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * @since 1.0 * @version 1.0 */ int32_t (*GetDisplayPowerStatus)(uint32_t devId, DispPowerStatus *status); - /** - * @brief Sets the backlight level. + /* * + * @brief Sets the power status of a display device. * - * You can use this function to set the backlight level of the display device specified by devId. * - * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates - * the first display device and 4 indicates the last display device. - * @param level Indicates the backlight level to set. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @param devId Indicates the ID of the display device. + * @param status Indicates the power status to set. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * @since 1.0 * @version 1.0 */ - int32_t (*SetDisplayBacklight)(uint32_t devId, uint32_t level); + int32_t (*SetDisplayPowerStatus)(uint32_t devId, DispPowerStatus status); - /** - * @brief Obtains the backlight level. + /* * + * @brief Obtains the backlight value of a display device. + * * - * You can use this function to obtain the backlight level of the display device specified by devId. * - * @param devId Indicates the ID of a display device. The value ranges from 0 to 4, where 0 indicates - * the first display device and 4 indicates the last display device. - * @param level Indicates the backlight level. + * @param devId Indicates the ID of the display device. + * @param level Indicates the pointer to the backlight value of the device. The backlight value is written by this interface. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * @since 1.0 * @version 1.0 */ int32_t (*GetDisplayBacklight)(uint32_t devId, uint32_t *level); + + /* * + * @brief Sets the backlight value for a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param level Indicates the backlight value to set. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayBacklight)(uint32_t devId, uint32_t level); + + /* * + * @brief Obtains the property for a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param id Indicates the property ID returned by GetDisplayCapability. + * @param level Indicates the pointer to the property corresponding to the property ID. The property value is written by this interface. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplayProperty)(uint32_t devId, uint32_t id, uint64_t *value); + + /* * + * @brief Sets the property for a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param id Indicates the property ID returned by GetDisplayCapability. + * @param value Indicates the property to set. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayProperty)(uint32_t devId, uint32_t id, uint64_t value); + + /* * + * @brief Prepares for the composition to be performed by a display device. + * + * Before the composition, the graphics service needs to notify the display device of the preparation to be made through this interface. + * + * @param devId Indicates the ID of the display device. + * @param needFlushFb Indicates the pointer that specifies whether the graphics service needs to reset the display framebuffer by using SetDisplayClientBuffer before the commit operation. + * The value true means that the framebuffer needs to be reset, and false means the opposite. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*PrepareDisplayLayers)(uint32_t devId, bool *needFlushFb); + + /* * + * @brief Obtains the layers whose composition types have changed. + * + * In the preparation for composition, the display device changes the composition type for each layer based on the composition capability of the device. This function returns the layers whose composition types have changed. + * + * @param devId Indicates the ID of the display device. + * @param num Indicates the pointer to the number of layers whose composition types have changed. + * @param Layers Indicates the pointer to the start address of the layer array. + * @param Layers Indicates the pointer to the start address of the composition type array. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplayCompChange)(uint32_t devId, uint32_t *num, uint32_t *Layers, int32_t *type); + + /* * + * @brief Sets the cropped region for a display device. + * + * You can use this interface to set the cropped region of the client buffer of the display device. The cropped region cannot exceed the size of the client buffer. + * + * @param devId Indicates the ID of the display device. + * @param rect Indicates the pointer to the cropped region of the client buffer. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayClientCrop)(uint32_t devId, IRect *rect); + + /* * + * @brief Sets the display region for a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * @param rect Indicates the pointer to the display region. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayClientDestRect)(uint32_t devId, IRect *rect); + + /* * + * @brief Sets the display buffer for a display device. + * + * The display buffer stores the hardware composition result of the display device. + * + * @param devId Indicates the ID of the display device. + * @param buffer Indicates the pointer to the display buffer. + * @param fence Indicates the sync fence that specifies whether the display buffer can be accessed. The display buffer is created and released by the graphics service. It can be accessed only when the sync fence is in the signaled state. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayClientBuffer)(uint32_t devId, const BufferHandle *buffer, int32_t fence); + + /* * + * @brief Sets the dirty region for a display device. + * + * The dirty region consists of multiple rectangular regions. The rectangular regions can be refreshed based on the settings. + * + * @param devId Indicates the ID of the display device. + * @param num Indicates the number of rectangles. + * @param rect Indicates the pointer to the start address of the rectangle array. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayClientDamage)(uint32_t devId, uint32_t num, IRect *rect); + + /* * + * @brief Enables or disables the vertical sync signal. + * + * When the vertical sync signal is generated, the VBlankCallback callback registered by RegDisplayVBlankCallback + * will be invoked. + * The vertical sync signal must be enabled when the graphics service needs to refresh the display, and disabled when display refresh is not required. The display does not need to refresh when VBlankCallback is invoked and the graphics service composes layers and sends the composition result to the device for display. + * @param devId Indicates the ID of the display device. + * @param enabled Specifies whether to enable the vertical sync signal. The value true means to enable the vertical sync signal, and false means to disable it. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetDisplayVsyncEnabled)(uint32_t devId, bool enabled); + + /* * + * @brief Obtains the fences of the display layers after the commit operation. + * + * + * + * @param devId Indicates the ID of the display device. + * @param num Indicates the pointer to the number of layers. + * @param layers Indicates the pointer to the start address of the layer array. + * @param fences Indicates the pointer to the start address of the fence array. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetDisplayReleaseFence)(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *fences); + + /* * + * @brief Commits the request for composition and display. + * + * If there is a hardware composition layer, the composition is performed and the composition result is sent to the hardware for display. + * + * + * @param devId Indicates the ID of the display device. + * @param num Indicates the pointer to the number of layers. + * @param layers Indicates the pointer to the start address of the layer array. + * @param fences Indicates the pointer to the start address of the fence array. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*Commit)(uint32_t devId, int32_t *fence); + + /* * + * @brief Invokes the display device commands. + * + * This function extends the APIs between the graphics service and implementation layer, eliminating the need to add new APIs. + * + * + * @param devId Indicates the ID of the display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*InvokeDisplayCmd)(uint32_t devId, ...); + + /* * + * @brief Creates a virtual display device. + * + * + * + * @param width Indicates the pixel width of the display device. + * @param height Indicates the pixel height of the display device. + * @param format Indicates the pointer to the pixel format of the display device. + * For details, see {@link PixelFormat}. The format can be modified based on hardware requirements and returned to the graphics service. + * @param devId Indicates the pointer to the ID of the virtual display device created. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*CreateVirtualDisplay)(uint32_t width, uint32_t height, int32_t *format, uint32_t *devId); + + /* * + * @brief Destroys a virtual display device. + * + * + * + * @param devId Indicates the ID of the display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*DestroyVirtualDisplay)(uint32_t devId); + + /* * + * @brief Sets the output buffer for a virtual display device. + * + * This buffer stores the output of the virtual display device. The buffer can be used only after the sync fence is in the signaled state. + * + * @param devId Indicates the ID of the display device. + * @param buffer Indicates the pointer to the output buffer. + * @param fence Indicates the sync fence. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*SetVirtualDisplayBuffer)(uint32_t devId, BufferHandle *buffer, int32_t fence); + + /* * + * @brief Obtains the writeback frame of a display device. + * + * This function is used to obtain data of the writeback endpoint specified by devId. The data is written to the specified buffer by this interface. + * + * @param devId Indicates the ID of the display device. + * @param buffer Indicates the pointer to the buffer of the writeback endpoint data. + * @param fence Indicates the pointer to the sync fence. When calling this interface, the graphics service needs to pass the release fence of the buffer to + * specify whether data can be written to the buffer. Then, acquire fence of the buffer needs to be written and sent to + * the graphics service to specify whether the writeback data has been written to the buffer. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*GetWriteBackFrame)(uint32_t devId, BufferHandle *buffer, int32_t *fence); + + /* * + * @brief Creates a writeback endpoint for a display device. + * + * If the number of writeback endpoints exceeds the limit, a failure message will be returned. + * + * @param devId Indicates the pointer to the ID of the display device. After a writeback endpoint is created, the device ID of the writeback endpoint is written in this parameter and returned to the graphics service. + * @param width Indicates the writeback pixel width. + * @param height Indicates the writeback pixel height. + * @param format Indicates the pointer to the writeback point data format. For details, see {@link PixelFormat}. The format can be modified based on hardware requirements and returned to the graphics service. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*CreateWriteBack)(uint32_t *devId, uint32_t width, uint32_t height, int32_t *format); + + /* * + * @brief Destroys the writeback endpoint of a display device. + * + * + * + * @param devId Indicates the ID of the display device. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @since 1.0 + * @version 1.0 + */ + int32_t (*DestroyWriteBack)(uint32_t devId); } DeviceFuncs; /** - * @brief Initializes the control functions of the display device. You can apply for the resources for + * @brief Initializes the control functions of a display device. * You can apply for resources for * using control functions and then operate the display device by using the control functions. * * @param funcs Indicates the double pointer to the control functions of the display device. The caller obtains * the double pointer to operate the display device. The memory is allocated during initialization, and therefore * the caller does not need to allocate the memory. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * * @since 1.0 * @version 1.0 @@ -127,13 +536,13 @@ typedef struct { int32_t DeviceInitialize(DeviceFuncs **funcs); /** - * @brief Uninitializes control functions of the display device. The resources used by - * the control functions will be released. + * @brief Uninitializes control functions of the display device. * The resources used by + * the control functions will be released. In other words, the memory allocated during initialization of the control functions will be released. + * + * @param funcs Indicates the double pointer to the control functions of the display device. * * - * @param funcs Indicates the double pointer to control functions of the display device. It is used to release - * the memory allocated during initialization of the control functions. * - * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} otherwise. * @since 1.0 * @version 1.0 */ @@ -143,4 +552,4 @@ int32_t DeviceUninitialize(DeviceFuncs *funcs); } #endif #endif -/* @} */ \ No newline at end of file +/* @} */ diff --git a/display/test/BUILD.gn b/display/test/BUILD.gn index fff7462f7f6574c123ef9fc32c3efe51ccd5d5fd..9e2012a6d77998d7141a48127a2abd697c79f167 100644 --- a/display/test/BUILD.gn +++ b/display/test/BUILD.gn @@ -13,15 +13,16 @@ if (defined(ohos_lite)) { import("//build/lite/config/component/lite_component.gni") - import("//build/lite/config/test.gni") lite_component("hdf_test_display") { - # add hdf subsystem unittest if (ohos_build_type == "debug") { if (board_name == "hi3516dv300" || board_name == "hispark_taurus") { - deps = [ "unittest:hdf_peripheral_display_test" ] + deps = [ "unittest/lite:hdf_peripheral_display_test" ] } } features = [] } +} else { + group("hdf_test_display") { + } } diff --git a/display/test/resource/gfx_test.bmp b/display/test/resource/gfx_test.bmp old mode 100644 new mode 100755 diff --git a/display/test/unittest/BUILD.gn b/display/test/unittest/lite/BUILD.gn similarity index 93% rename from display/test/unittest/BUILD.gn rename to display/test/unittest/lite/BUILD.gn index 884972783114e0a8f2a296e9075fbf07f9e3d318..1b4628ba4722bc3727f09ae9821828e22fae1251 100644 --- a/display/test/unittest/BUILD.gn +++ b/display/test/unittest/lite/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//build/lite/config/component/lite_component.gni") import("//build/lite/config/test.gni") unittest("hdf_peripheral_display_test") { @@ -34,9 +35,9 @@ unittest("hdf_peripheral_display_test") { ] sources = [ - "./common/display_test.c", - "./common/hdi_display_test.cpp", - "./common/loadbmp_test.c", + "display_test.c", + "hdi_display_test.cpp", + "loadbmp_test.c", ] deps = [ diff --git a/display/test/unittest/common/display_test.c b/display/test/unittest/lite/display_test.c similarity index 99% rename from display/test/unittest/common/display_test.c rename to display/test/unittest/lite/display_test.c index c57590c628231102a1312ad10f373af2c7980dfb..a86be58ba2171bfa315090c41eaac431fcc43185 100644 --- a/display/test/unittest/common/display_test.c +++ b/display/test/unittest/lite/display_test.c @@ -328,7 +328,7 @@ int32_t BlitTest(void) // clean the layer buffer (void)memset_s(g_displayTest.buffer.data.virAddr, layerBufSize, 0, layerBufSize); // load bmp test picture - ret = LoadBmp((const int8_t *)PIC_RES_PATH, &pictureBuf); + ret = LoadBmp((const int8_t *)"./gfx_test.bmp", &pictureBuf); if (ret != DISPLAY_SUCCESS) { HDF_LOGE("%s: LoadBmp fail", __func__); return DISPLAY_FAILURE; diff --git a/display/test/unittest/common/display_test.h b/display/test/unittest/lite/display_test.h similarity index 94% rename from display/test/unittest/common/display_test.h rename to display/test/unittest/lite/display_test.h index 9f0450ce7ccb63dcc930cf390b8ebd4658954784..b2c3ed4325807544b6164f2009d235cf119eca4d 100644 --- a/display/test/unittest/common/display_test.h +++ b/display/test/unittest/lite/display_test.h @@ -59,12 +59,6 @@ extern "C" { /* LCD division coefficient */ #define LCD_DIV_COE 0x182ed6 -#ifdef __LITEOS__ -#define PIC_RES_PATH "/user/data/gfx_test.bmp" -#else -#define PIC_RES_PATH "/storage/data/gfx_test.bmp" -#endif - typedef struct { LayerFuncs *layerFuncs; GrallocFuncs *grallocFuncs; diff --git a/display/test/unittest/common/hdi_display_test.cpp b/display/test/unittest/lite/hdi_display_test.cpp similarity index 100% rename from display/test/unittest/common/hdi_display_test.cpp rename to display/test/unittest/lite/hdi_display_test.cpp diff --git a/display/test/unittest/common/loadbmp_test.c b/display/test/unittest/lite/loadbmp_test.c similarity index 100% rename from display/test/unittest/common/loadbmp_test.c rename to display/test/unittest/lite/loadbmp_test.c diff --git a/display/test/unittest/common/loadbmp_test.h b/display/test/unittest/lite/loadbmp_test.h similarity index 100% rename from display/test/unittest/common/loadbmp_test.h rename to display/test/unittest/lite/loadbmp_test.h diff --git a/display/test/unittest/standard/BUILD.gn b/display/test/unittest/standard/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..32389bdbba8ad5d5be98d55a7c04643ad5f8feff --- /dev/null +++ b/display/test/unittest/standard/BUILD.gn @@ -0,0 +1,123 @@ +# 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. + +import("//build/test.gni") + +group("hdf_unittest_display") { + testonly = true + deps = [ + ":devicetest", + # ":gralloctest", + # ":gfxtest" + ] +} + +module_output_path = "hdf/display" + +config("module_private_config") { + visibility = [ ":*" ] +} + +ohos_static_library("disp_hdi_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 = "disp_hdi_test_common" + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + deps = [ "//utils/native/base:utils" ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +} + +ohos_unittest("gralloctest") { + module_out_path = module_output_path + sources = [ "display_gralloc/display_gralloc_test.cpp" ] + deps = [ + "//drivers/peripheral/display/hal/default_standard:displaygralloc", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + ] + include_dirs = [ + "common", + "//drivers/peripheral/display/hal/default_standard/include", + "//drivers/peripheral/display/hal/default_standard/src/display_gralloc", + "//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_unittest("gfxtest") { + module_out_path = module_output_path + sources = [ + "display_gfx/display_gfx_test.cpp", + "display_gfx/soft_blit.cpp", + ] + deps = [ + "//drivers/peripheral/display/hal:hdi_display_gfx", + "//drivers/peripheral/display/hal/default_standard:displaygralloc", + "//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_unittest("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 = [ + ":disp_hdi_test_common", + "//drivers/peripheral/display/hal:hdi_display_gfx", + "//drivers/peripheral/display/hal/default_standard:display_device_drm", + "//drivers/peripheral/display/hal/default_standard:displaygralloc", + "//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/display/test/unittest/standard/common/display_test.h b/display/test/unittest/standard/common/display_test.h new file mode 100644 index 0000000000000000000000000000000000000000..dc4983de1732506bd7fd524cb780f7bd53b46b49 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/common/display_test_utils.cpp b/display/test/unittest/standard/common/display_test_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c30b6328b52006493bbbb1d09323b7b55e7fbb13 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/common/display_test_utils.h b/display/test/unittest/standard/common/display_test_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..ab42971d21955533bb9694993beb85d790c6008f --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_composition_check.cpp b/display/test/unittest/standard/display_device/hdi_composition_check.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9ce468c0c6de95f0f1ea98fc7dee49640ce22eb --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_composition_check.h b/display/test/unittest/standard/display_device/hdi_composition_check.h new file mode 100644 index 0000000000000000000000000000000000000000..a913f5c00fce0facd95eb1814f3eae1eacff28f0 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_device_test.cpp b/display/test/unittest/standard/display_device/hdi_device_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c73a07941c4b3db7b85cc68b640160e0b65da17f --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_device_test.h b/display/test/unittest/standard/display_device/hdi_device_test.h new file mode 100644 index 0000000000000000000000000000000000000000..84fb82266784ab2b150bb06e2edd0f0628b8520e --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_device.cpp b/display/test/unittest/standard/display_device/hdi_test_device.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55a93213faa3bdba12f3f72e9187e2ee0bce7b35 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_device.h b/display/test/unittest/standard/display_device/hdi_test_device.h new file mode 100644 index 0000000000000000000000000000000000000000..4dff09445998c594d8f8a00277fbe4e47e0f7cf0 --- /dev/null +++ b/display/test/unittest/standard/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 \ No newline at end of file diff --git a/display/test/unittest/standard/display_device/hdi_test_device_common.h b/display/test/unittest/standard/display_device/hdi_test_device_common.h new file mode 100644 index 0000000000000000000000000000000000000000..0f3aaa65685adcc530b7a372e90121e4c5f12339 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_display.cpp b/display/test/unittest/standard/display_device/hdi_test_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87f91a74e132adc6f07f738171a131393dc540a0 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_display.h b/display/test/unittest/standard/display_device/hdi_test_display.h new file mode 100644 index 0000000000000000000000000000000000000000..e028b2625af004a453e0cc0e41ea281542023706 --- /dev/null +++ b/display/test/unittest/standard/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 \ No newline at end of file diff --git a/display/test/unittest/standard/display_device/hdi_test_layer.cpp b/display/test/unittest/standard/display_device/hdi_test_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f62ad127d5bc2afdeb9b9f2e0aa1926a2a7c4d00 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_layer.h b/display/test/unittest/standard/display_device/hdi_test_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..918cb369753c2c26f17851792a130aee8ce6f660 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_render_utils.cpp b/display/test/unittest/standard/display_device/hdi_test_render_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6c3281f5328434e23f0a1cf7aaa4c4a209259cb --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_device/hdi_test_render_utils.h b/display/test/unittest/standard/display_device/hdi_test_render_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..f08ee50d08784f2177b2b50fc535ab131784caab --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gfx/display_gfx_test.cpp b/display/test/unittest/standard/display_gfx/display_gfx_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab74654da28d207fd429757b139826e3f2226ec4 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gfx/display_gfx_test.h b/display/test/unittest/standard/display_gfx/display_gfx_test.h new file mode 100644 index 0000000000000000000000000000000000000000..20fbe992b74bfe0d84b1bf2e2ebc98f3adc8c716 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gfx/soft_blit.cpp b/display/test/unittest/standard/display_gfx/soft_blit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2da1f190e92bf422c14b1979e350d9628e614187 --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gfx/soft_blit.h b/display/test/unittest/standard/display_gfx/soft_blit.h new file mode 100644 index 0000000000000000000000000000000000000000..fac6c36c326b237aa2d985891026c9f823ed56ff --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gralloc/display_gralloc_test.cpp b/display/test/unittest/standard/display_gralloc/display_gralloc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..751e52070b83560939eead7279a47be01aee762f --- /dev/null +++ b/display/test/unittest/standard/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/display/test/unittest/standard/display_gralloc/display_gralloc_test.h b/display/test/unittest/standard/display_gralloc/display_gralloc_test.h new file mode 100644 index 0000000000000000000000000000000000000000..8e3c718ac00f15ea53853191811236eb5ae53248 --- /dev/null +++ b/display/test/unittest/standard/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