diff --git a/display/buffer/BUILD.gn b/display/buffer/BUILD.gn index dba9c8cc8d2f90ab04645a7afdb0f518cff8f9ed..43ea2e3129aaf605d09bdccc2556b505011f0467 100644 --- a/display/buffer/BUILD.gn +++ b/display/buffer/BUILD.gn @@ -15,5 +15,8 @@ import("//build/ohos.gni") import("./../display_config.gni") group("display_buffer_entry") { - deps = [ "hdi_service:hdf_display_buffer_service" ] + deps = [ + "hdi_service:hdf_display_buffer_service", + "vdi_base:display_buffer_vdi_impl_default", + ] } diff --git a/display/buffer/hdi_service/include/idisplay_buffer_vdi.h b/display/buffer/hdi_service/include/idisplay_buffer_vdi.h index efeb94d1f8a33bec176dd3117c7a5a6094cfda6b..367ea89ca61cdf459830bdb9b756f9a822b828cd 100644 --- a/display/buffer/hdi_service/include/idisplay_buffer_vdi.h +++ b/display/buffer/hdi_service/include/idisplay_buffer_vdi.h @@ -26,6 +26,9 @@ namespace Display { namespace Buffer { namespace V1_0 { +#ifdef BUFFER_VDI_DEFAULT_LIBRARY_ENABLE +#define DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY "libdisplay_buffer_vdi_impl_default.z.so" +#endif // BUFFER_VDI_DEFAULT_LIBRARY_ENABLE #define DISPLAY_BUFFER_VDI_LIBRARY "libdisplay_buffer_vdi_impl.z.so" class IDisplayBufferVdi { diff --git a/display/buffer/hdi_service/src/allocator_service.cpp b/display/buffer/hdi_service/src/allocator_service.cpp index 2e2008e36e08c0743bc69c01fe8129e1ff92426e..a1bbdc1cc247e774f4b1c9e519918ef0c529b3aa 100644 --- a/display/buffer/hdi_service/src/allocator_service.cpp +++ b/display/buffer/hdi_service/src/allocator_service.cpp @@ -46,7 +46,7 @@ AllocatorService::AllocatorService() vdiImpl_ = createVdi_(); CHECK_NULLPOINTER_RETURN(vdiImpl_); } else { - HDF_LOGE("%{public}s: Load buffer VDI failed, lib: %{public}s", __func__, DISPLAY_BUFFER_VDI_LIBRARY); + HDF_LOGE("%{public}s: Load buffer VDI failed", __func__); } } @@ -64,9 +64,15 @@ int32_t AllocatorService::LoadVdi() { const char* errStr = dlerror(); if (errStr != nullptr) { - HDF_LOGI("%{public}s: allocator loadvid, clear earlier dlerror: %{public}s", __func__, errStr); + HDF_LOGI("%{public}s: allocator load vdi, clear earlier dlerror: %{public}s", __func__, errStr); } +#ifdef BUFFER_VDI_DEFAULT_LIBRARY_ENABLE + libHandle_ = dlopen(DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("display buffer load default vdi library: %{public}s", DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY); +#else libHandle_ = dlopen(DISPLAY_BUFFER_VDI_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("display buffer load vendor vdi library: %{public}s", DISPLAY_BUFFER_VDI_LIBRARY); +#endif // BUFFER_VDI_DEFAULT_LIBRARY_ENABLE CHECK_NULLPOINTER_RETURN_VALUE(libHandle_, HDF_FAILURE); createVdi_ = reinterpret_cast(dlsym(libHandle_, "CreateDisplayBufferVdi")); diff --git a/display/buffer/hdi_service/src/mapper_service.cpp b/display/buffer/hdi_service/src/mapper_service.cpp index 132abe1e7cdb29a7ee0cfde699450f4baccbe1ab..2f8232978a0a1523113dd2b2b4be26b0a1be4783 100644 --- a/display/buffer/hdi_service/src/mapper_service.cpp +++ b/display/buffer/hdi_service/src/mapper_service.cpp @@ -46,7 +46,7 @@ MapperService::MapperService() vdiImpl_ = createVdi_(); CHECK_NULLPOINTER_RETURN(vdiImpl_); } else { - HDF_LOGE("%{public}s: Load buffer VDI failed, lib: %{public}s", __func__, DISPLAY_BUFFER_VDI_LIBRARY); + HDF_LOGE("%{public}s: Load buffer VDI failed", __func__); } } @@ -64,9 +64,15 @@ int32_t MapperService::LoadVdi() { const char* errStr = dlerror(); if (errStr != nullptr) { - HDF_LOGI("%{public}s: mapper loadvid, clear earlier dlerror: %{public}s", __func__, errStr); + HDF_LOGI("%{public}s: mapper load vdi, clear earlier dlerror: %{public}s", __func__, errStr); } +#ifdef BUFFER_VDI_DEFAULT_LIBRARY_ENABLE + libHandle_ = dlopen(DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("display buffer load default vdi library: %{public}s", DISPLAY_BUFFER_VDI_DEFAULT_LIBRARY); +#else libHandle_ = dlopen(DISPLAY_BUFFER_VDI_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("display buffer load vendor vdi library: %{public}s", DISPLAY_BUFFER_VDI_LIBRARY); +#endif // BUFFER_VDI_DEFAULT_LIBRARY_ENABLE CHECK_NULLPOINTER_RETURN_VALUE(libHandle_, HDF_FAILURE); createVdi_ = reinterpret_cast(dlsym(libHandle_, "CreateDisplayBufferVdi")); diff --git a/display/buffer/vdi_base/BUILD.gn b/display/buffer/vdi_base/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4ceab3deaeb3dbcba28df23ee1fdb220cee2692e --- /dev/null +++ b/display/buffer/vdi_base/BUILD.gn @@ -0,0 +1,65 @@ +# Copyright (C) 2021-2023 HiHope Open Source Organization . +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") + +root_path = "../../../../.." + +config("libdisplay_buffer_vdi_impl_default_config") { + include_dirs = [ "include/" ] +} + +ohos_shared_library("display_buffer_vdi_impl_default") { + sources = [ + "src/display_buffer_vdi_impl.cpp", + "src/display_gralloc_gbm.cpp", + "src/hi_gbm.cpp", + ] + + public_configs = [ ":libdisplay_buffer_vdi_impl_default_config" ] + + include_dirs = [ + "include/", + "${root_path}/drivers/peripheral/base", + "${root_path}/drivers/interface/display/composer/hdifd_parcelable", + "${root_path}/drivers/interface/display/buffer", + "${root_path}/drivers/peripheral/display/utils/include", + "${root_path}/drivers/peripheral/display/buffer/hdi_service/include", + "${root_path}/foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + ] + + output_name = "display_buffer_vdi_impl_default" + + cflags = [ + "-DGRALLOC_GBM_SUPPORT", + "-Wno-macro-redefined", + ] + + deps = [ "${root_path}/third_party/libdrm:libdrm" ] + + external_deps = [ + "c_utils:utils", + "drivers_interface_display:display_buffer_idl_headers", + "drivers_interface_display:display_composer_idl_headers", + "hdf_core:libhdf_utils", + "hilog:libhilog", + "ipc:ipc_single", + ] + + install_enable = false + install_images = [ chipset_base_dir ] + innerapi_tags = [ "chipsetsdk" ] + subsystem_name = "hdf" + part_name = "drivers_peripheral_display" +} diff --git a/display/buffer/vdi_base/include/display_buffer_vdi_impl.h b/display/buffer/vdi_base/include/display_buffer_vdi_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..9cb70a4b6a7bc3ed17a8c64e8002d928346ab14c --- /dev/null +++ b/display/buffer/vdi_base/include/display_buffer_vdi_impl.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 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_BUFFER_VDI_IMPL_H +#define DISPLAY_BUFFER_VDI_IMPL_H + +#include "buffer_handle.h" +#include "idisplay_buffer_vdi.h" +#include "v1_0/display_buffer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Buffer::V1_0; + +class DisplayBufferVdiImpl : public IDisplayBufferVdi { +public: + DisplayBufferVdiImpl(); + virtual ~DisplayBufferVdiImpl(); + + 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 int32_t Unmap(const BufferHandle& handle) const override; + virtual int32_t FlushCache(const BufferHandle& handle) const override; + virtual int32_t InvalidateCache(const BufferHandle& handle) const override; + virtual int32_t IsSupportedAlloc(const std::vector& infos, + std::vector& supporteds) const override; +}; +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS +#endif // DISPLAY_BUFFER_VDI_IMPL_H diff --git a/display/buffer/vdi_base/include/display_gralloc_gbm.h b/display/buffer/vdi_base/include/display_gralloc_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..0f7cbdcf289b584daa8734b80c23d5220f7f9558 --- /dev/null +++ b/display/buffer/vdi_base/include/display_gralloc_gbm.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021-2023 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 "buffer_handle.h" +#include "hdf_dlist.h" +#include "hdf_log.h" +#include "v1_0/display_buffer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Buffer::V1_0; + +using GrallocManager = struct { + struct gbm_device *gbmDevice; + int drmFd; + struct DListHead gbmBoHead; + int32_t referCount; +}; + +using GbmBoList = struct { + struct DListHead entry; + struct gbm_bo *bo; + int fd; +}; + +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(void); +int32_t GbmGrallocInitialize(void); + +#ifdef GRALLOC_LOCK_DEBUG +#define GRALLOC_LOCK(format, ...) \ + do { \ + HDF_LOGE("[%{public}s@%{public}s:%{public}d]" format "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ + pthread_mutex_lock(&g_lock); \ + } while (0) + +#define GRALLOC_UNLOCK(format, ...) \ + do { \ + HDF_LOGE("[%{public}s@%{public}s:%{public}d]" format "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ + pthread_mutex_unlock(&g_lock); \ + } while (0) +#else +#define GRALLOC_LOCK(format, ...) \ + do { \ + pthread_mutex_lock(&g_lock); \ + } while (0) + +#define GRALLOC_UNLOCK(format, ...) \ + do { \ + pthread_mutex_unlock(&g_lock); \ + } while (0) +#endif +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS +#endif // DISPLAY_GRALLOC_GBM_H diff --git a/display/buffer/vdi_base/include/display_gralloc_private.h b/display/buffer/vdi_base/include/display_gralloc_private.h new file mode 100644 index 0000000000000000000000000000000000000000..2a9e7566510496daa80952d60404e47f6b3c7a77 --- /dev/null +++ b/display/buffer/vdi_base/include/display_gralloc_private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2023 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 "buffer_handle.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 diff --git a/display/buffer/vdi_base/include/hi_gbm.h b/display/buffer/vdi_base/include/hi_gbm.h new file mode 100644 index 0000000000000000000000000000000000000000..c804b2c0b93ac010f2a3345e34bdc4f1f05d0df2 --- /dev/null +++ b/display/buffer/vdi_base/include/hi_gbm.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021-2023 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 + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +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 *HdiGbmCreateDevice(int fd); +void HdiGbmDeviceDestroy(struct gbm_device *gbm); +struct gbm_bo *HdiGbmBoCreate(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); +uint32_t hdi_gbm_bo_get_size(struct gbm_bo *bo); +void HdiGbmBoDestroy(struct gbm_bo *bo); +int HdiGbmBoGetFd(struct gbm_bo *bo); +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS +#endif // HI_GBM_H diff --git a/display/buffer/vdi_base/include/hi_gbm_internal.h b/display/buffer/vdi_base/include/hi_gbm_internal.h new file mode 100644 index 0000000000000000000000000000000000000000..7bdcd3e88d5be49f10447f92916c80460ce1a6f0 --- /dev/null +++ b/display/buffer/vdi_base/include/hi_gbm_internal.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021-2023 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 + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) +#define ALIGN_UP(x, a) ((((x) + ((a)-1)) / (a)) * (a)) +const uint32_t HEIGHT_ALIGN = 2U; +const uint32_t WIDTH_ALIGN = 8U; + +const uint32_t MAX_PLANES = 3U; + +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; +}; +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS +#endif // HI_GBM_INTERNEL_H diff --git a/display/buffer/vdi_base/include/hisilicon_drm.h b/display/buffer/vdi_base/include/hisilicon_drm.h new file mode 100644 index 0000000000000000000000000000000000000000..391fd8d6b0c4404b8d2f571c360a6a24b966a8aa --- /dev/null +++ b/display/buffer/vdi_base/include/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/buffer/vdi_base/src/display_buffer_vdi_impl.cpp b/display/buffer/vdi_base/src/display_buffer_vdi_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26abf665cdb00d5c3651ffec748ffdbad9c703c5 --- /dev/null +++ b/display/buffer/vdi_base/src/display_buffer_vdi_impl.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023 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_buffer_vdi_impl.h" +#include "cinttypes" +#include "display_log.h" +#include "display_gralloc_gbm.h" +#include "hdf_base.h" +#include "v1_0/display_composer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Composer::V1_0; + +DisplayBufferVdiImpl::DisplayBufferVdiImpl() +{ +#ifdef GRALLOC_GBM_SUPPORT + int ret = GbmGrallocInitialize(); + if (ret != HDF_SUCCESS) { + DISPLAY_LOGE("gbm construct failed"); + } +#endif +} + +DisplayBufferVdiImpl::~DisplayBufferVdiImpl() +{ +#ifdef GRALLOC_GBM_SUPPORT + if (GbmGrallocUninitialize() != HDF_SUCCESS) { + DISPLAY_LOGE("gbm distruct failed"); + } +#endif +} + +int32_t DisplayBufferVdiImpl::AllocMem(const AllocInfo& info, BufferHandle*& handle) const +{ + return GbmAllocMem(&info, &handle); +} + +void DisplayBufferVdiImpl::FreeMem(const BufferHandle& handle) const +{ + GbmFreeMem(const_cast(&handle)); +} + +void* DisplayBufferVdiImpl::Mmap(const BufferHandle& handle) const +{ + return GbmMmap(const_cast(&handle)); +} + +int32_t DisplayBufferVdiImpl::Unmap(const BufferHandle& handle) const +{ + return GbmUnmap(const_cast(&handle)); +} + +int32_t DisplayBufferVdiImpl::FlushCache(const BufferHandle& handle) const +{ + return GbmFlushCache(const_cast(&handle)); +} + +int32_t DisplayBufferVdiImpl::InvalidateCache(const BufferHandle& handle) const +{ + return GbmInvalidateCache(const_cast(&handle)); +} + +int32_t DisplayBufferVdiImpl::IsSupportedAlloc(const std::vector& infos, + std::vector& supporteds) const +{ + return HDF_ERR_NOT_SUPPORT; +} + +extern "C" IDisplayBufferVdi* CreateDisplayBufferVdi() +{ + return new DisplayBufferVdiImpl(); +} + +extern "C" void DestroyDisplayBufferVdi(IDisplayBufferVdi* vdi) +{ + delete vdi; +} +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS diff --git a/display/buffer/vdi_base/src/display_gralloc_gbm.cpp b/display/buffer/vdi_base/src/display_gralloc_gbm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00aa16cdf1369209b4ad39ec0f4e3e6538c5987b --- /dev/null +++ b/display/buffer/vdi_base/src/display_gralloc_gbm.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2021-2023 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 +#include "drm_fourcc.h" +#include "hisilicon_drm.h" +#include "hi_gbm.h" +#include "hdf_dlist.h" +#include "display_gralloc_private.h" +#include "display_log.h" +#include "v1_0/display_composer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Composer::V1_0; +using namespace OHOS::HDI::Display::Buffer::V1_0; + +const char *g_drmFileNode = "/dev/dri/renderD128"; +static GrallocManager *g_grallocManager = nullptr; +static pthread_mutex_t g_lock; + +using PixelFormatConvertTbl = struct { + uint32_t drmFormat; + PixelFormat pixFormat; +}; + +using ValueStrMap = struct { + uint32_t value; + const char *str; +}; + +static GrallocManager *GetGrallocManager(void) +{ + if (g_grallocManager == nullptr) { + 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 == nullptr) { + DISPLAY_LOGE("gralloc manager malloc failed"); + } + } + return g_grallocManager; +} + +const char *GetPixelFmtStr(PixelFormat format) +{ + static const ValueStrMap PIXEL_STR_MAPS[] = { + {PIXEL_FMT_CLUT8, "PIXEL_FMT_CLUT8"}, {PIXEL_FMT_CLUT1, "PIXEL_FMT_CLUT1"}, + {PIXEL_FMT_CLUT4, "PIXEL_FMT_CLUT4"}, {PIXEL_FMT_RGB_565, "PIXEL_FMT_RGB_565"}, + {PIXEL_FMT_RGBA_5658, "IXEL_FMT_RGBA_5658"}, {PIXEL_FMT_RGBX_4444, "PIXEL_FMT_RGBX_4444"}, + {PIXEL_FMT_RGBA_4444, "PIXEL_FMT_RGBA_4444"}, {PIXEL_FMT_RGB_444, "PIXEL_FMT_RGB_444"}, + {PIXEL_FMT_RGBX_5551, "PIXEL_FMT_RGBX_5551"}, {PIXEL_FMT_RGBA_5551, "PIXEL_FMT_RGBA_5551"}, + {PIXEL_FMT_RGB_555, "PIXEL_FMT_RGB_555"}, {PIXEL_FMT_RGBX_8888, "PIXEL_FMT_RGBX_8888"}, + {PIXEL_FMT_RGBA_8888, "PIXEL_FMT_RGBA_8888"}, {PIXEL_FMT_RGB_888, "PIXEL_FMT_RGB_888"}, + {PIXEL_FMT_BGR_565, "PIXEL_FMT_BGR_565"}, {PIXEL_FMT_BGRX_4444, "PIXEL_FMT_BGRX_4444"}, + {PIXEL_FMT_BGRA_4444, "PIXEL_FMT_BGRA_4444"}, {PIXEL_FMT_BGRX_5551, "PIXEL_FMT_BGRX_5551"}, + {PIXEL_FMT_BGRA_5551, "PIXEL_FMT_BGRA_5551"}, {PIXEL_FMT_BGRX_8888, "PIXEL_FMT_BGRX_8888"}, + {PIXEL_FMT_BGRA_8888, "PIXEL_FMT_BGRA_8888"}, {PIXEL_FMT_YUV_422_I, "PIXEL_FMT_YUV_422_I"}, + {PIXEL_FMT_YUV_422_I, "PIXEL_FMT_YUV_422_I"}, {PIXEL_FMT_YCBCR_422_SP, "PIXEL_FMT_YCBCR_422_SP"}, + {PIXEL_FMT_YCRCB_422_SP, "PIXEL_FMT_YCRCB_422_SP"}, {PIXEL_FMT_YCBCR_420_SP, "PIXEL_FMT_YCBCR_420_SP"}, + {PIXEL_FMT_YCRCB_420_SP, "PIXEL_FMT_YCRCB_420_SP"}, {PIXEL_FMT_YCBCR_422_P, "PIXEL_FMT_YCBCR_422_P"}, + {PIXEL_FMT_YCRCB_422_P, "PIXEL_FMT_YCRCB_422_P"}, {PIXEL_FMT_YCBCR_420_P, "PIXEL_FMT_YCBCR_420_P"}, + {PIXEL_FMT_YCRCB_420_P, "PIXEL_FMT_YCRCB_420_P"}, {PIXEL_FMT_YUYV_422_PKG, "PIXEL_FMT_YUYV_422_PKG"}, + {PIXEL_FMT_UYVY_422_PKG, "PIXEL_FMT_UYVY_422_PKG"}, {PIXEL_FMT_YVYU_422_PKG, "PIXEL_FMT_YVYU_422_PKG"}, + {PIXEL_FMT_VYUY_422_PKG, "PIXEL_FMT_VYUY_422_PKG"}, {PIXEL_FMT_BUTT, "PIXEL_FMT_BUTT"}, + }; + static const char *unknown = "unknown format"; + for (uint32_t i = 0; i < sizeof(PIXEL_STR_MAPS) / sizeof(PIXEL_STR_MAPS[0]); i++) { + if (PIXEL_STR_MAPS[i].value == static_cast(format)) { + return PIXEL_STR_MAPS[i].str; + } + } + DISPLAY_LOGE("GetPixelFmtStr unknown format %{public}d", format); + return unknown; +} + +const char *GetDrmFmtStr(uint32_t format) +{ + static const ValueStrMap FORMAT_STR_MAPS[] = { + {DRM_FORMAT_C8, "DRM_FORMAT_C8" }, {DRM_FORMAT_R8, "DRM_FORMAT_R8" }, + {DRM_FORMAT_R16, "DRM_FORMAT_R16"}, {DRM_FORMAT_RG88, "DRM_FORMAT_RG88"}, + {DRM_FORMAT_GR88, "DRM_FORMAT_GR88"}, {DRM_FORMAT_RG1616, "DRM_FORMAT_RG1616"}, + {DRM_FORMAT_GR1616, "DRM_FORMAT_GR1616"}, {DRM_FORMAT_RGB332, "DRM_FORMAT_RGB332"}, + {DRM_FORMAT_BGR233, "DRM_FORMAT_BGR233"}, {DRM_FORMAT_XRGB4444, "DRM_FORMAT_XRGB4444"}, + {DRM_FORMAT_XBGR4444, "DRM_FORMAT_XBGR4444"}, {DRM_FORMAT_RGBX4444, "DRM_FORMAT_RGBX4444"}, + {DRM_FORMAT_BGRX4444, "DRM_FORMAT_BGRX4444"}, {DRM_FORMAT_ARGB4444, "DRM_FORMAT_ARGB4444"}, + {DRM_FORMAT_ABGR4444, "DRM_FORMAT_ABGR4444"}, {DRM_FORMAT_RGBA4444, "DRM_FORMAT_RGBA4444"}, + {DRM_FORMAT_BGRA4444, "DRM_FORMAT_BGRA4444"}, {DRM_FORMAT_XRGB1555, "DRM_FORMAT_XRGB1555"}, + {DRM_FORMAT_XBGR1555, "DRM_FORMAT_XBGR1555"}, {DRM_FORMAT_RGBX5551, "DRM_FORMAT_RGBX5551"}, + {DRM_FORMAT_BGRX5551, "DRM_FORMAT_BGRX5551"}, {DRM_FORMAT_ARGB1555, "DRM_FORMAT_ARGB1555"}, + {DRM_FORMAT_ABGR1555, "DRM_FORMAT_ABGR1555"}, {DRM_FORMAT_RGBA5551, "DRM_FORMAT_RGBA5551"}, + {DRM_FORMAT_BGRA5551, "DRM_FORMAT_BGRA5551"}, {DRM_FORMAT_RGB565, "DRM_FORMAT_RGB565"}, + {DRM_FORMAT_BGR565, "DRM_FORMAT_BGR565"}, {DRM_FORMAT_RGB888, "DRM_FORMAT_RGB888"}, + {DRM_FORMAT_BGR888, "DRM_FORMAT_BGR888"}, {DRM_FORMAT_XRGB8888, "DRM_FORMAT_XRGB8888"}, + {DRM_FORMAT_XBGR8888, "DRM_FORMAT_XBGR8888"}, {DRM_FORMAT_RGBX8888, "DRM_FORMAT_RGBX8888"}, + {DRM_FORMAT_BGRX8888, "DRM_FORMAT_BGRX8888"}, {DRM_FORMAT_ARGB8888, "DRM_FORMAT_ARGB8888"}, + {DRM_FORMAT_ABGR8888, "DRM_FORMAT_ABGR8888"}, {DRM_FORMAT_RGBA8888, "DRM_FORMAT_RGBA8888"}, + {DRM_FORMAT_BGRA8888, "DRM_FORMAT_BGRA8888"}, {DRM_FORMAT_XRGB2101010, "DRM_FORMAT_XRGB2101010"}, + {DRM_FORMAT_BGRX1010102, "DRM_FORMAT_BGRX1010102"}, {DRM_FORMAT_ARGB2101010, "DRM_FORMAT_ARGB2101010"}, + {DRM_FORMAT_ABGR2101010, "DRM_FORMAT_ABGR2101010"}, {DRM_FORMAT_RGBA1010102, "DRM_FORMAT_RGBA1010102"}, + {DRM_FORMAT_YVYU, "DRM_FORMAT_YVYU"}, {DRM_FORMAT_UYVY, "DRM_FORMAT_UYVY"}, + {DRM_FORMAT_VYUY, "DRM_FORMAT_VYUY"}, {DRM_FORMAT_AYUV, "DRM_FORMAT_AYUV"}, + {DRM_FORMAT_NV12, "DRM_FORMAT_NV12"}, {DRM_FORMAT_NV21, "DRM_FORMAT_NV21"}, + {DRM_FORMAT_NV16, "DRM_FORMAT_NV16"}, {DRM_FORMAT_NV61, "DRM_FORMAT_NV61"}, + {DRM_FORMAT_NV24, "DRM_FORMAT_NV24"}, {DRM_FORMAT_NV42, "DRM_FORMAT_NV42"}, + {DRM_FORMAT_YUV410, "DRM_FORMAT_YUV410"}, {DRM_FORMAT_YVU410, "DRM_FORMAT_YVU410"}, + {DRM_FORMAT_YUV411, "DRM_FORMAT_YUV411"}, {DRM_FORMAT_YVU411, "DRM_FORMAT_YVU411"}, + {DRM_FORMAT_YUV420, "DRM_FORMAT_YUV420"}, {DRM_FORMAT_YVU420, "DRM_FORMAT_YVU420"}, + {DRM_FORMAT_YUV422, "DRM_FORMAT_YUV422"}, {DRM_FORMAT_YVU422, "DRM_FORMAT_YVU422"}, + {DRM_FORMAT_YUV444, "DRM_FORMAT_YUV444"}, {DRM_FORMAT_YVU444, "DRM_FORMAT_YVU444"}, + }; + + static const char *unknown = "unknown drm format"; + for (uint32_t i = 0; i < sizeof(FORMAT_STR_MAPS) / sizeof(FORMAT_STR_MAPS[0]); i++) { + if (FORMAT_STR_MAPS[i].value == format) { + return FORMAT_STR_MAPS[i].str; + } + } + DISPLAY_LOGE("GetDrmFmtStr unknown format %{public}d", format); + return unknown; +} + +static uint32_t ConvertFormatToDrm(PixelFormat fmtIn) +{ + static const PixelFormatConvertTbl CONVERT_TABLE[] = { + {DRM_FORMAT_RGBX8888, PIXEL_FMT_RGBX_8888}, {DRM_FORMAT_RGBA8888, PIXEL_FMT_RGBA_8888}, + {DRM_FORMAT_RGB888, PIXEL_FMT_RGB_888}, {DRM_FORMAT_RGB565, PIXEL_FMT_BGR_565}, + {DRM_FORMAT_BGRX4444, PIXEL_FMT_BGRX_4444}, {DRM_FORMAT_BGRA4444, PIXEL_FMT_BGRA_4444}, + {DRM_FORMAT_RGBA4444, PIXEL_FMT_RGBA_4444}, {DRM_FORMAT_RGBX4444, PIXEL_FMT_RGBX_4444}, + {DRM_FORMAT_BGRX5551, PIXEL_FMT_BGRX_5551}, {DRM_FORMAT_BGRA5551, PIXEL_FMT_BGRA_5551}, + {DRM_FORMAT_BGRX8888, PIXEL_FMT_BGRX_8888}, {DRM_FORMAT_BGRA8888, PIXEL_FMT_BGRA_8888}, + {DRM_FORMAT_NV12, PIXEL_FMT_YCBCR_420_SP}, {DRM_FORMAT_NV21, PIXEL_FMT_YCRCB_420_SP}, + {DRM_FORMAT_YUV420, PIXEL_FMT_YCBCR_420_P}, {DRM_FORMAT_YVU420, PIXEL_FMT_YCRCB_420_P}, + {DRM_FORMAT_NV16, PIXEL_FMT_YCBCR_422_SP}, {DRM_FORMAT_NV61, PIXEL_FMT_YCRCB_422_SP}, + {DRM_FORMAT_YUV422, PIXEL_FMT_YCBCR_422_P}, {DRM_FORMAT_YVU422, PIXEL_FMT_YCRCB_422_P}, + }; + uint32_t fmtOut = 0; + for (uint32_t i = 0; i < sizeof(CONVERT_TABLE) / sizeof(CONVERT_TABLE[0]); i++) { + if (CONVERT_TABLE[i].pixFormat == fmtIn) { + fmtOut = CONVERT_TABLE[i].drmFormat; + } + } + DISPLAY_LOGD("fmtIn %{public}d : %{public}s, outFmt %{public}d : %{public}s", fmtIn, + GetPixelFmtStr(fmtIn), fmtOut, GetDrmFmtStr(fmtOut)); + return fmtOut; +} + +static uint64_t ConvertUsageToGbm(uint64_t inUsage) +{ + uint64_t outUsage = GBM_BO_USE_TEXTURING; + if (inUsage & HBM_USE_CPU_READ) { + outUsage |= GBM_BO_USE_SW_READ_OFTEN; + } + if (inUsage & HBM_USE_CPU_WRITE) { + outUsage |= GBM_BO_USE_SW_WRITE_OFTEN; + } + DISPLAY_LOGD("outUsage 0x%{public}" PRIx64 "", outUsage); + return outUsage; +} + +static int32_t InitGbmDevice(const char *drmFile, GrallocManager *grallocManager) +{ + DISPLAY_LOGD(); + if (grallocManager->gbmDevice == nullptr) { + char path[PATH_MAX] = {0}; + if (realpath(drmFile, path) == nullptr) { + DISPLAY_LOGE(" drm File : %{public}s is not a realpath, errno: %{public}s", drmFile, strerror(errno)); + return HDF_ERR_INVALID_PARAM; + } + int drmFd = open(path, O_RDWR); + if (drmFd < 0) { + DISPLAY_LOGE("drm file:%{public}s open failed %{public}s", drmFile, strerror(errno)); + return HDF_ERR_BAD_FD; + } + drmDropMaster(drmFd); + struct gbm_device *gbmDevice = HdiGbmCreateDevice(drmFd); + grallocManager->drmFd = drmFd; + if (gbmDevice == nullptr) { + close(drmFd); + grallocManager->drmFd = -1; + DISPLAY_LOGE("gbm device create failed"); + return HDF_FAILURE; + } + grallocManager->gbmDevice = gbmDevice; + grallocManager->drmFd = drmFd; + DListHeadInit(&grallocManager->gbmBoHead); + } + return HDF_SUCCESS; +} + +static void DeInitGbmDevice(GrallocManager *grallocManager) +{ + DISPLAY_LOGD(); + HdiGbmDeviceDestroy(grallocManager->gbmDevice); + if (grallocManager->drmFd > 0) { + close(grallocManager->drmFd); + grallocManager->drmFd = -1; + } + grallocManager->gbmDevice = nullptr; +} + +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), HDF_ERR_INVALID_PARAM, DISPLAY_LOGE("dma buffer sync memset_s failed")); + + if (handle->usage & HBM_USE_CPU_WRITE) { + syncPrm.flags |= DMA_BUF_SYNC_WRITE; + } + + if (handle->usage & HBM_USE_CPU_READ) { + syncPrm.flags |= DMA_BUF_SYNC_READ; + } + + if (start) { + syncPrm.flags |= DMA_BUF_SYNC_START; + } else { + syncPrm.flags |= DMA_BUF_SYNC_END; + } + int retry = 6; + int ret; + do { + ret = ioctl(handle->fd, DMA_BUF_IOCTL_SYNC, &syncPrm); + } while ((retry--) && (ret != -EAGAIN) && (ret != -EINTR)); + + if (ret < 0) { + DISPLAY_LOGE("sync failed"); + return HDF_ERR_DEVICE_BUSY; + } + return HDF_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 = nullptr; + bufferHandle->size = hdi_gbm_bo_get_size(bo); +} + +int32_t GbmAllocMem(const AllocInfo *info, BufferHandle **buffer) +{ + DISPLAY_CHK_RETURN((info == nullptr), HDF_FAILURE, DISPLAY_LOGE("info is null")); + DISPLAY_CHK_RETURN((buffer == nullptr), HDF_FAILURE, DISPLAY_LOGE("buffer is null")); + PriBufferHandle *priBuffer = nullptr; + uint32_t drmFmt = ConvertFormatToDrm(static_cast(info->format)); + DISPLAY_CHK_RETURN((drmFmt == INVALID_PIXEL_FMT), HDF_ERR_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 == nullptr), HDF_ERR_INVALID_PARAM, DISPLAY_LOGE("gralloc manager failed"); + GRALLOC_UNLOCK()); + struct gbm_bo *bo = + HdiGbmBoCreate(grallocManager->gbmDevice, info->width, info->height, drmFmt, ConvertUsageToGbm(info->usage)); + DISPLAY_CHK_RETURN((bo == nullptr), HDF_DEV_ERR_NO_MEMORY, DISPLAY_LOGE("gbm create bo failed"); \ + GRALLOC_UNLOCK()); + + int fd = HdiGbmBoGetFd(bo); + DISPLAY_CHK_RETURN((fd < 0), HDF_ERR_BAD_FD, DISPLAY_LOGE("gbm can not get fd"); \ + HdiGbmBoDestroy(bo); \ + GRALLOC_UNLOCK()); + + errno_t eok = EOK; + priBuffer = (PriBufferHandle *)malloc(sizeof(PriBufferHandle)); + if (priBuffer == nullptr) { + DISPLAY_LOGE("bufferhandle malloc failed"); + goto error; + } + + eok = memset_s(priBuffer, sizeof(PriBufferHandle), 0, sizeof(PriBufferHandle)); + if (eok != EOK) { + DISPLAY_LOGE("memset_s failed"); + goto error; + } + DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_PARAM_ERR, DISPLAY_LOGE("memset_s failed")); + + InitBufferHandle(bo, fd, info, priBuffer); + *buffer = &priBuffer->hdl; + HdiGbmBoDestroy(bo); + GRALLOC_UNLOCK(); + return HDF_SUCCESS; +error: + close(fd); + HdiGbmBoDestroy(bo); + if (priBuffer != nullptr) { + free(priBuffer); + } + GRALLOC_UNLOCK(); + return HDF_FAILURE; +} + +static void CloseBufferHandle(BufferHandle *handle) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((handle == nullptr), 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 == nullptr), DISPLAY_LOGE("buffer is null")); + if ((buffer->virAddr != nullptr) && (GbmUnmap(buffer) != HDF_SUCCESS)) { + DISPLAY_LOGE("freeMem unmap buffer failed"); + } + CloseBufferHandle(buffer); + free(buffer); +} + +void *GbmMmap(BufferHandle *buffer) +{ + void *virAddr = nullptr; + DISPLAY_LOGD(); + if (buffer == nullptr) { + DISPLAY_LOGE("gbmmap the buffer handle is nullptr"); + return nullptr; + } + if (buffer->virAddr != nullptr) { + DISPLAY_LOGD("the buffer has virtual addr"); + return buffer->virAddr; + } + virAddr = mmap(nullptr, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, buffer->fd, 0); + if (virAddr == reinterpret_cast(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 == nullptr) { + DISPLAY_LOGE("gbmumap the buffer handle is null"); + return HDF_FAILURE; + } + + if (buffer->virAddr == nullptr) { + DISPLAY_LOGE("virAddr is nullptr , has not map the buffer"); + return HDF_ERR_INVALID_PARAM; + } + int ret = munmap(buffer->virAddr, buffer->size); + if (ret != 0) { + DISPLAY_LOGE("munmap failed err: %{public}s", strerror(errno)); + return HDF_FAILURE; + } + buffer->virAddr = nullptr; + return HDF_SUCCESS; +} + +int32_t GbmInvalidateCache(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + return DmaBufferSync(buffer, true); +} + +int32_t GbmFlushCache(BufferHandle *buffer) +{ + DISPLAY_LOGD(); + return DmaBufferSync(buffer, false); +} + +int32_t GbmGrallocUninitialize(void) +{ + DISPLAY_LOGD(); + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == nullptr), HDF_ERR_INVALID_PARAM, DISPLAY_LOGE("gralloc manager failed"); \ + GRALLOC_UNLOCK()); + grallocManager->referCount--; + if (grallocManager->referCount < 0) { + DeInitGbmDevice(grallocManager); + free(g_grallocManager); + g_grallocManager = nullptr; + } + GRALLOC_UNLOCK(); + return HDF_SUCCESS; +} + +int32_t GbmGrallocInitialize(void) +{ + DISPLAY_LOGD(); + GRALLOC_LOCK(); + GrallocManager *grallocManager = GetGrallocManager(); + DISPLAY_CHK_RETURN((grallocManager == nullptr), HDF_ERR_INVALID_PARAM, DISPLAY_LOGE("gralloc manager failed"); \ + GRALLOC_UNLOCK()); + int ret = InitGbmDevice(g_drmFileNode, grallocManager); + DISPLAY_CHK_RETURN((ret != HDF_SUCCESS), ret, DISPLAY_LOGE("gralloc manager failed"); \ + GRALLOC_UNLOCK()); + grallocManager->referCount++; + GRALLOC_UNLOCK(); + return HDF_SUCCESS; +} +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS diff --git a/display/buffer/vdi_base/src/hi_gbm.cpp b/display/buffer/vdi_base/src/hi_gbm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1611958b8550676ab494ec199fd89f114da75872 --- /dev/null +++ b/display/buffer/vdi_base/src/hi_gbm.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2021-2023 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_log.h" +#include "hi_gbm_internal.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +#ifdef ROCKCHIP_CMA +#define ROCKCHIP_BO_CONTIG (1 << 0) +#endif + +using PlaneLayoutInfo = struct { + uint32_t numPlanes; + uint32_t radio[MAX_PLANES]; +}; + +using FormatInfo = struct { + uint32_t format; + uint32_t bitsPerPixel; // bits per pixel for first plane + const PlaneLayoutInfo *planes; +}; + +static const PlaneLayoutInfo YUV_420SP_LAYOUT = { + .numPlanes = 2, + .radio = { 4, 2 }, +}; + +static const PlaneLayoutInfo YUV_420P_LAYOUT = { + .numPlanes = 3, + .radio = { 4, 1, 1 }, +}; + +static const PlaneLayoutInfo YUV_422SP_LAYOUT = { + .numPlanes = 2, + .radio = { 4, 4 }, +}; + +static const PlaneLayoutInfo YUV_422P_LAYOUT = { + .numPlanes = 3, + .radio = { 4, 2, 2 }, +}; + +static const FormatInfo *GetFormatInfo(uint32_t format) +{ + static const FormatInfo FMT_INFOS[] = { + {DRM_FORMAT_RGBX8888, 32, nullptr}, {DRM_FORMAT_RGBA8888, 32, nullptr}, + {DRM_FORMAT_BGRX8888, 32, nullptr}, {DRM_FORMAT_BGRA8888, 32, nullptr}, + {DRM_FORMAT_RGB888, 24, nullptr}, {DRM_FORMAT_RGB565, 16, nullptr}, + {DRM_FORMAT_BGRX4444, 16, nullptr}, {DRM_FORMAT_BGRA4444, 16, nullptr}, + {DRM_FORMAT_RGBA4444, 16, nullptr}, {DRM_FORMAT_RGBX4444, 16, nullptr}, + {DRM_FORMAT_BGRX5551, 16, nullptr}, {DRM_FORMAT_BGRA5551, 16, nullptr}, + {DRM_FORMAT_NV12, 8, &YUV_420SP_LAYOUT}, {DRM_FORMAT_NV21, 8, &YUV_420SP_LAYOUT}, + {DRM_FORMAT_NV16, 8, &YUV_422SP_LAYOUT}, {DRM_FORMAT_NV61, 8, &YUV_422SP_LAYOUT}, + {DRM_FORMAT_YUV420, 8, &YUV_420P_LAYOUT}, {DRM_FORMAT_YVU420, 8, &YUV_420P_LAYOUT}, + {DRM_FORMAT_YUV422, 8, &YUV_422P_LAYOUT}, {DRM_FORMAT_YVU422, 8, &YUV_422P_LAYOUT}, + }; + + for (uint32_t i = 0; i < sizeof(FMT_INFOS) / sizeof(FormatInfo); i++) { + if (FMT_INFOS[i].format == format) { + return &FMT_INFOS[i]; + } + } + DISPLAY_LOGE("the format can not support"); + return nullptr; +} + +void InitGbmBo(struct gbm_bo *bo, const struct drm_mode_create_dumb *dumb) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((dumb == nullptr), DISPLAY_LOGE("dumb is null")); + DISPLAY_CHK_RETURN_NOT_VALUE((bo == nullptr), 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) +{ + uint32_t tmpHeight = height; + const FormatInfo *fmtInfo = GetFormatInfo(format); + if ((fmtInfo != nullptr) && (fmtInfo->planes != nullptr)) { + 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) { + tmpHeight = DIV_ROUND_UP((height * sum), fmtInfo->planes->radio[0]); + } + DISPLAY_LOGD("height adjust to : %{public}d", tmpHeight); + } + return tmpHeight; +} + +struct gbm_bo *HdiGbmBoCreate(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, + uint32_t usage) +{ + DISPLAY_UNUSED(usage); + int ret; + struct gbm_bo *bo; + struct drm_mode_create_dumb dumb = { 0 }; + const FormatInfo *fmtInfo = GetFormatInfo(format); + DISPLAY_CHK_RETURN((fmtInfo == nullptr), nullptr, + DISPLAY_LOGE("formt: 0x%{public}x can not get layout info", format)); + bo = (struct gbm_bo *)calloc(1, sizeof(struct gbm_bo)); + DISPLAY_CHK_RETURN((bo == nullptr), nullptr, DISPLAY_LOGE("gbm bo create fialed no memery")); + (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo)); + bo->width = width; + bo->height = height; + bo->gbm = gbm; + bo->format = format; + // init create_dumb + dumb.height = ALIGN_UP(AdjustStrideFromFormat(format, height), HEIGHT_ALIGN); + dumb.width = ALIGN_UP(width, WIDTH_ALIGN); + dumb.flags = 0; + dumb.bpp = fmtInfo->bitsPerPixel; + ret = drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb); + DISPLAY_LOGD("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), nullptr, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno)); + InitGbmBo(bo, &dumb); + DISPLAY_LOGD( + "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 *HdiGbmCreateDevice(int fd) +{ + struct gbm_device *gbm = (struct gbm_device *)calloc(1, sizeof(struct gbm_device)); + DISPLAY_CHK_RETURN((gbm == nullptr), nullptr, DISPLAY_LOGE("memory calloc failed")); + gbm->fd = fd; + return gbm; +} + +void HdiGbmDeviceDestroy(struct gbm_device *gbm) +{ + free(gbm); +} + +uint32_t hdi_gbm_bo_get_stride(struct gbm_bo *bo) +{ + DISPLAY_CHK_RETURN((bo == nullptr), 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 == nullptr), 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 == nullptr), 0, DISPLAY_LOGE("the bo is null")); + return bo->height; +} + +uint32_t hdi_gbm_bo_get_size(struct gbm_bo *bo) +{ + DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null")); + return bo->size; +} + +void HdiGbmBoDestroy(struct gbm_bo *bo) +{ + int ret; + DISPLAY_CHK_RETURN_NOT_VALUE((bo == nullptr), 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 HdiGbmBoGetFd(struct gbm_bo *bo) +{ + int fd; + int 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; +} +} // namespace DISPLAY +} // namespace HDI +} // namespace OHOS diff --git a/display/bundle.json b/display/bundle.json index 0f135aaef65e9c09c364e0833d6f97553ad093a9..0346a6dbab208cdbd048ca95f72feda18f5873e2 100755 --- a/display/bundle.json +++ b/display/bundle.json @@ -26,12 +26,14 @@ "ipc", "drivers_interface_display", "graphic_chipsetsdk", - "hilog", "init", "memory_utils", "hitrace", "googletest", "thirdparty_benchmark" + ], + "third_party": [ + "libdrm" ] }, "build": { diff --git a/display/composer/BUILD.gn b/display/composer/BUILD.gn index 8e64f1bd412abf053cd43639466173b8bc7b7b7c..0dc42e14f87d53867f2adbecfdfb68a5b9ae28ca 100644 --- a/display/composer/BUILD.gn +++ b/display/composer/BUILD.gn @@ -14,5 +14,8 @@ import("./../display_config.gni") group("display_composer_entry") { - deps = [ "hdi_service:display_composer_hdi_service" ] + deps = [ + "hdi_service:display_composer_hdi_service", + "vdi_base:display_composer_vdi_impl_default", + ] } diff --git a/display/composer/hdi_service/include/idisplay_composer_vdi.h b/display/composer/hdi_service/include/idisplay_composer_vdi.h index 0765a837c20e38f5b1a783da7b918fd2f611f974..0aae45ac7e080e93445dd7d6ece3a1508ccdad5b 100644 --- a/display/composer/hdi_service/include/idisplay_composer_vdi.h +++ b/display/composer/hdi_service/include/idisplay_composer_vdi.h @@ -28,6 +28,9 @@ namespace Composer { namespace V1_0 { using namespace OHOS::HDI::Display::Composer::V1_0; +#ifdef COMPOSER_VDI_DEFAULT_LIBRARY_ENABLE +#define DISPLAY_COMPOSER_VDI_DEFAULT_LIBRARY "libdisplay_composer_vdi_impl_default.z.so" +#endif // COMPOSER_VDI_DEFAULT_LIBRARY_ENABLE #define DISPLAY_COMPOSER_VDI_LIBRARY "libdisplay_composer_vdi_impl.z.so" class IDisplayComposerVdi { public: diff --git a/display/composer/hdi_service/src/display_composer_service.cpp b/display/composer/hdi_service/src/display_composer_service.cpp index 9e51cc8aae1744b691e9537bcdc161b84d8b79eb..a861b60963c2a3c1e70a48937fcca5fd73a16c2e 100644 --- a/display/composer/hdi_service/src/display_composer_service.cpp +++ b/display/composer/hdi_service/src/display_composer_service.cpp @@ -79,9 +79,15 @@ int32_t DisplayComposerService::LoadVdi() { const char* errStr = dlerror(); if (errStr != nullptr) { - DISPLAY_LOGI("composer loadvid, clear earlier dlerror: %{public}s", errStr); + DISPLAY_LOGI("composer load vdi, clear earlier dlerror: %{public}s", errStr); } +#ifdef COMPOSER_VDI_DEFAULT_LIBRARY_ENABLE + libHandle_ = dlopen(DISPLAY_COMPOSER_VDI_DEFAULT_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("composer load default vdi library: %{public}s", DISPLAY_COMPOSER_VDI_DEFAULT_LIBRARY); +#else libHandle_ = dlopen(DISPLAY_COMPOSER_VDI_LIBRARY, RTLD_LAZY); + DISPLAY_LOGI("composer load vendor vdi library: %{public}s", DISPLAY_COMPOSER_VDI_LIBRARY); +#endif // COMPOSER_VDI_DEFAULT_LIBRARY_ENABLE CHECK_NULLPOINTER_RETURN_VALUE(libHandle_, HDF_FAILURE); createVdiFunc_ = reinterpret_cast(dlsym(libHandle_, "CreateComposerVdi")); diff --git a/display/composer/vdi_base/BUILD.gn b/display/composer/vdi_base/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..84781f5b767ed104e8fd26227990fae0ddc61f91 --- /dev/null +++ b/display/composer/vdi_base/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (C) 2021-2023 HiHope Open Source Organization . +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") + +root_path = "../../../../.." + +ohos_shared_library("display_composer_vdi_impl_default") { + sources = [ + "src/display_composer_vdi_impl.cpp", + "src/drm_connector.cpp", + "src/drm_crtc.cpp", + "src/drm_device.cpp", + "src/drm_display.cpp", + "src/drm_encoder.cpp", + "src/drm_plane.cpp", + "src/drm_vsync_worker.cpp", + "src/hdi_composer.cpp", + "src/hdi_device_interface.cpp", + "src/hdi_display.cpp", + "src/hdi_drm_composition.cpp", + "src/hdi_drm_layer.cpp", + "src/hdi_gfx_composition.cpp", + "src/hdi_layer.cpp", + "src/hdi_netlink_monitor.cpp", + "src/hdi_session.cpp", + ] + output_name = "display_composer_vdi_impl_default" + include_dirs = [ + "include/", + "../../buffer/vdi_base/include", + "${root_path}/drivers/peripheral/display/buffer/hdi_service/include", + "${root_path}/drivers/peripheral/display/composer/hdi_service/include", + "${root_path}/drivers/peripheral/display/utils/include", + "${root_path}/drivers/peripheral/base", + "${root_path}/drivers/interface/display/composer", + "${root_path}/foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "${root_path}/drivers/interface/display/composer/hdifd_parcelable", + ] + + deps = [ + "${root_path}/third_party/libdrm:libdrm", + "../../buffer/vdi_base:display_buffer_vdi_impl_default", + ] + cflags_cc = [ + "-Wno-error=unused-function", + "-Wno-error=missing-braces", + "-Wno-error=#warnings", + ] + external_deps = [ + "c_utils:utils", + "drivers_interface_display:display_buffer_idl_headers", + "drivers_interface_display:display_composer_idl_headers", + "graphic_chipsetsdk:buffer_handle", + "hdf_core:libhdf_utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + ] + install_enable = false + install_images = [ chipset_base_dir ] + subsystem_name = "hdf" + part_name = "drivers_peripheral_display" +} diff --git a/display/composer/vdi_base/include/display_composer_vdi_impl.h b/display/composer/vdi_base/include/display_composer_vdi_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..82bd192637aef5c58fe34e96a217fc0d8445ccaa --- /dev/null +++ b/display/composer/vdi_base/include/display_composer_vdi_impl.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 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_COMPOSER_VDI_IMPL_H +#define DISPLAY_COMPOSER_VDI_IMPL_H + +#include +#include "hdi_session.h" +#include "idisplay_composer_vdi.h" +#include "v1_0/display_composer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Composer; +using namespace OHOS::HDI::Display::Composer::V1_0; + +class DisplayComposerVdiImpl : public IDisplayComposerVdi { +public: + DisplayComposerVdiImpl(); + virtual ~DisplayComposerVdiImpl(); + virtual int32_t RegHotPlugCallback(HotPlugCallback cb, void* data) override; + virtual int32_t GetDisplayCapability(uint32_t devId, DisplayCapability& info) override; + virtual int32_t GetDisplaySupportedModes(uint32_t devId, std::vector& modes) override; + virtual int32_t GetDisplayMode(uint32_t devId, uint32_t& modeId) override; + virtual int32_t SetDisplayMode(uint32_t devId, uint32_t modeId) override; + virtual int32_t GetDisplayPowerStatus(uint32_t devId, DispPowerStatus& status) override; + virtual int32_t SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status) override; + virtual int32_t GetDisplayBacklight(uint32_t devId, uint32_t& level) override; + virtual int32_t SetDisplayBacklight(uint32_t devId, uint32_t level) override; + virtual int32_t GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t& value) override; + virtual int32_t GetDisplayCompChange(uint32_t devId, std::vector& layers, + std::vector& types) override; + virtual int32_t SetDisplayClientCrop(uint32_t devId, const IRect& rect) override; + virtual int32_t SetDisplayClientBuffer(uint32_t devId, const BufferHandle& buffer, int32_t fence) override; + virtual int32_t SetDisplayClientDamage(uint32_t devId, std::vector& rects) override; + virtual int32_t SetDisplayVsyncEnabled(uint32_t devId, bool enabled) override; + virtual int32_t RegDisplayVBlankCallback(uint32_t devId, VBlankCallback cb, void* data) override; + virtual int32_t GetDisplayReleaseFence(uint32_t devId, std::vector& layers, + std::vector& fences) override; + virtual int32_t CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t& format, uint32_t& devId) override; + virtual int32_t DestroyVirtualDisplay(uint32_t devId) override; + virtual int32_t SetVirtualDisplayBuffer(uint32_t devId, const BufferHandle& buffer, const int32_t fence) override; + virtual int32_t SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value) override; + virtual int32_t Commit(uint32_t devId, int32_t& fence) override; + virtual int32_t CreateLayer(uint32_t devId, const LayerInfo& layerInfo, uint32_t& layerId) override; + virtual int32_t DestroyLayer(uint32_t devId, uint32_t layerId) override; + virtual int32_t PrepareDisplayLayers(uint32_t devId, bool& needFlushFb) override; + virtual int32_t SetLayerAlpha(uint32_t devId, uint32_t layerId, const LayerAlpha& alpha) override; + virtual int32_t SetLayerRegion(uint32_t devId, uint32_t layerId, const IRect& rect) override; + virtual int32_t SetLayerCrop(uint32_t devId, uint32_t layerId, const IRect& rect) override; + virtual int32_t SetLayerZorder(uint32_t devId, uint32_t layerId, uint32_t zorder) override; + virtual int32_t SetLayerPreMulti(uint32_t devId, uint32_t layerId, bool preMul) override; + virtual int32_t SetLayerTransformMode(uint32_t devId, uint32_t layerId, TransformType type) override; + virtual int32_t SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, const std::vector& rects) override; + virtual int32_t SetLayerVisibleRegion(uint32_t devId, uint32_t layerId, std::vector& rects) override; + virtual int32_t SetLayerBuffer(uint32_t devId, uint32_t layerId, + const BufferHandle& buffer, int32_t fence) override; + virtual int32_t SetLayerCompositionType(uint32_t devId, uint32_t layerId, CompositionType type) override; + virtual int32_t SetLayerBlendType(uint32_t devId, uint32_t layerId, BlendType type) override; + virtual int32_t SetLayerMaskInfo(uint32_t devId, uint32_t layerId, const MaskInfo maskInfo) override; + virtual int32_t SetLayerColor(uint32_t devId, uint32_t layerId, const LayerColor& layerColor) override; +}; +} // DISPLAY +} // HDI +} // OHOS +#endif // DISPLAY_COMPOSER_VDI_IMPL_H diff --git a/display/composer/vdi_base/include/display_gfx.h b/display/composer/vdi_base/include/display_gfx.h new file mode 100644 index 0000000000000000000000000000000000000000..874340e15050175169fdbcaa03df3b79cb303c9f --- /dev/null +++ b/display/composer/vdi_base/include/display_gfx.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023 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_H +#define DISPLAY_GFX_H +#include "v1_0/display_composer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Composer::V1_0; +/** + * @brief Defines pointers to the hardware acceleration driver functions. + */ +using GfxFuncs = struct { + /** + * @brief Initializes hardware acceleration. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*InitGfx)(void); + + /** + * @brief Deinitializes hardware acceleration. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*DeinitGfx)(void); + + /** + * @brief Fills a rectangle with a given color on the canvas. + * + * @param surface Indicates the pointer to the canvas. + * @param rect Indicates the pointer to the rectangle to fill. + * @param color Indicates the color to fill. + * @param opt Indicates the pointer to the hardware acceleration option. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*FillRect)(ISurface *surface, IRect *rect, uint32_t color, GfxOpt *opt); + + /** + * @brief Draws a rectangle with a given color on the canvas. + * + * @param surface Indicates the pointer to the canvas. + * @param rect Indicates the pointer to the rectangle to draw. + * @param color Indicates the color to draw. + * @param opt Indicates the pointer to the hardware acceleration option. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*DrawRectangle)(ISurface *surface, Rectangle *rect, uint32_t color, GfxOpt *opt); + + /** + * @brief Draws a straight line with a given color on the canvas. + * + * @param surface Indicates the pointer to the canvas. + * @param line Indicates the pointer to the line to draw. + * @param opt Indicates the pointer to the hardware acceleration option. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*DrawLine)(ISurface *surface, ILine *line, GfxOpt *opt); + + /** + * @brief Draws a circle with a specified center and radius on the canvas using a given color. + * + * @param surface Indicates the pointer to the canvas. + * @param circle Indicates the pointer to the circle to draw. + * @param opt Indicates the pointer to the hardware acceleration option. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*DrawCircle)(ISurface *surface, ICircle *circle, GfxOpt *opt); + + /** + * @brief Blits bitmaps. + * + * During bit blit, color space conversion (CSC), scaling, and rotation can be implemented. + * + * @param srcSurface Indicates the pointer to the source bitmap. + * @param srcRect Indicates the pointer to the rectangle of the source bitmap. + * @param dstSurface Indicates the pointer to the destination bitmap. + * @param dstRect Indicates the pointer to the rectangle of the destination bitmap. + * @param opt Indicates the pointer to the hardware acceleration option. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*Blit)(ISurface *srcSurface, IRect *srcRect, ISurface *dstSurface, IRect *dstRect, GfxOpt *opt); + + /** + * @brief Synchronizes hardware acceleration when it is used to draw and blit bitmaps. + * + * This function blocks the process until hardware acceleration is complete. + * + * @param timeOut Indicates the timeout duration for hardware acceleration synchronization. The value 0 + * indicates no timeout, so the process waits until hardware acceleration is complete. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ + int32_t (*Sync)(int32_t timeOut); +}; + +/** + * @brief Initializes the hardware acceleration module to obtain the pointer to functions for hardware acceleration + * operations. + * + * @param funcs Indicates the double pointer to functions for hardware acceleration operations. Memory is allocated + * automatically when you initiate the hardware acceleration module, so you can simply use the pointer to gain access + * to the functions. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ +int32_t GfxInitialize(GfxFuncs **funcs); + +/** + * @brief Deinitializes the hardware acceleration module to release the pointer to functions for hardware + * acceleration operations. + * + * @param funcs Indicates the pointer to the functions for hardware acceleration operations. + * + * @return Returns 0 if the operation is successful; returns an error code defined in {@link DispErrCode} + * otherwise. + */ +int32_t GfxUninitialize(GfxFuncs *funcs); +} // DISPLAY +} // HDI +} // OHOS +#endif +/** @} */ diff --git a/display/composer/vdi_base/include/drm_connector.h b/display/composer/vdi_base/include/drm_connector.h new file mode 100644 index 0000000000000000000000000000000000000000..b12d610a92add144b1b1fb608900ad685ae89954 --- /dev/null +++ b/display/composer/vdi_base/include/drm_connector.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021-2023 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 "drm_encoder.h" +#include "hdi_device_common.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const std::string PROP_DPMS = "DPMS"; +const std::string PROP_CRTCID = "CRTC_ID"; +const std::string PROP_BRIGHTNESS = "brightness"; +class DrmDevice; +class DrmModeBlock; + +class DrmMode { +public: + DrmMode() {}; + DrmMode(drmModeModeInfo &modeInfo, uint32_t id) : mModeInfo(modeInfo), mId(id) {} + virtual ~DrmMode() {}; + drmModeModeInfoPtr GetModeInfoPtr() + { + return &mModeInfo; + } + void ConvertToHdiMode(DisplayModeInfo &hdiMode); + +private: + drmModeModeInfo mModeInfo = { 0 }; + int32_t mId = -1; +}; + +class DrmModeBlock { +public: + explicit DrmModeBlock(DrmMode &mode); + virtual ~DrmModeBlock(); + int32_t Init(DrmMode &mode); + uint32_t GetBlockId() const + { + return mBlockId; + } + +private: + uint32_t mBlockId = DRM_INVALID_ID; +}; + +class DrmConnector { +public: + DrmConnector(drmModeConnector c, FdPtr &fd); + virtual ~DrmConnector() {}; + uint32_t GetId() const + { + return mId; + } + uint32_t GetEncoderId() const + { + return mEncoderId; + } + void SetEncoderId(uint32_t id) + { + mEncoderId = id; + } + void GetDisplayCap(DisplayCapability &cap); + int32_t Init(DrmDevice &drmDevice); + int32_t PickIdleCrtcId(IdMapPtr &encoders, IdMapPtr &crtcs, uint32_t &crtcId); + int32_t GetDisplaySupportedModes(uint32_t *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(); + bool HandleHotplug(IdMapPtr &encoders, IdMapPtr &crtcs, bool plugIn); + std::shared_ptr UpdateCrtcId(IdMapPtr &encoders, IdMapPtr &crtcs, + bool plugIn, drmModeConnectorPtr c, int *crtc_id); + 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 mSupportLayers = 0; + uint32_t mVirtualDispCount = 0; + bool mSupportWriteBack = false; + uint32_t mPropertyCount = 0; + 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/composer/vdi_base/include/drm_crtc.h b/display/composer/vdi_base/include/drm_crtc.h new file mode 100644 index 0000000000000000000000000000000000000000..49a8d6d73bb26e00a33886d83dcc7ddf5fdbdfba --- /dev/null +++ b/display/composer/vdi_base/include/drm_crtc.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_CRTC_H +#define DRM_CRTC_H +#include +#include +#include +#include +#include "hdi_device_common.h" +#include "hdi_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const std::string PROP_ACTIVE = "ACTIVE"; +const std::string PROP_MODEID = "MODE_ID"; +const std::string PROP_OUTFENCE = "OUT_FENCE_PTR"; + +class DrmDevice; + +class DrmCrtc { +public: + DrmCrtc(drmModeCrtcPtr c, uint32_t pipe); + virtual ~DrmCrtc() {}; + int32_t BindToDisplay(uint32_t id); + void UnBindDisplay(uint32_t id); + bool CanBind(); + uint32_t GetId() const + { + return mId; + } + uint32_t GetModePropId() const + { + return mModePropId; + } + uint32_t GetOutFencePropId() const + { + return mOutFencePropId; + } + uint32_t GetActivePropId() const + { + return mActivePropId; + } + uint32_t GetPipe() const + { + return mPipe; + } + int32_t Init(DrmDevice &drmDevice); + int32_t SetActivieMode(int32_t id); + int32_t GetActiveModeId() const + { + return mActiveModeId; + } + bool NeedModeSet() + { + return mNeedModeSet; + } + void ClearModeSet() + { + mNeedModeSet = false; + } + uint32_t GetPlaneMask() + { + return mPlaneMask; + } +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; + uint32_t mPlaneMask = 0; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_CRTC_H \ No newline at end of file diff --git a/display/composer/vdi_base/include/drm_device.h b/display/composer/vdi_base/include/drm_device.h new file mode 100644 index 0000000000000000000000000000000000000000..ac2be678e09e01e64b76059f211df59da60a870e --- /dev/null +++ b/display/composer/vdi_base/include/drm_device.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 DRM_DEVICE_H +#define DRM_DEVICE_H +#include +#include +#include +#include +#include "drm_connector.h" +#include "drm_crtc.h" +#include "drm_encoder.h" +#include "drm_plane.h" +#include "hdi_device_common.h" +#include "hdi_device_interface.h" +#include "hdi_display.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +class DrmPropertyEnum { +public: + explicit DrmPropertyEnum(drm_mode_property_enum *e) : value(e->value), name(e->name) { + } + ~DrmPropertyEnum() {}; + + uint64_t value; + std::string name; +}; + +struct DrmProperty { + uint32_t propId; + uint64_t value; + uint32_t type; + uint32_t flags; + std::string name; + std::vector values; + std::vector enums; + std::vector blob_ids; +}; + +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(); + ~DrmDevice() override {} + + 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); + std::unordered_map> DiscoveryDisplay() override; + int32_t Init() override; + void DeInit() override; + bool HandleHotplug(uint32_t dispId, bool plugIn) override; + +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; + std::unordered_map dispConnectorIdMaps_; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_DEVICE_H diff --git a/display/composer/vdi_base/include/drm_display.h b/display/composer/vdi_base/include/drm_display.h new file mode 100644 index 0000000000000000000000000000000000000000..785008bd294ae8472a7e5106495d4bab6059b972 --- /dev/null +++ b/display/composer/vdi_base/include/drm_display.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_DISPLAY_H +#define DRM_DISPLAY_H +#include +#include +#include "drm_connector.h" +#include "drm_crtc.h" +#include "drm_device.h" +#include "drm_plane.h" +#include "hdi_composer.h" +#include "hdi_drm_composition.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class DrmDisplay : public HdiDisplay { +public: + DrmDisplay(std::shared_ptr connector, std::shared_ptr crtc, + std::shared_ptr drmDevice); + + ~DrmDisplay() override; + + int32_t Init() override; + int32_t GetDisplayCapability(DisplayCapability *info) override; + int32_t GetDisplaySupportedModes(uint32_t *num, DisplayModeInfo *modes) override; + int32_t GetDisplayMode(uint32_t *modeId) override; + int32_t SetDisplayMode(uint32_t modeId) override; + int32_t GetDisplayPowerStatus(DispPowerStatus *status) override; + int32_t SetDisplayPowerStatus(DispPowerStatus status) override; + int32_t GetDisplayBacklight(uint32_t *value) override; + int32_t SetDisplayBacklight(uint32_t value) override; + int32_t ChosePreferenceMode(); + int32_t RegDisplayVBlankCallback(VBlankCallback cb, void *data) override; + int32_t WaitForVBlank(uint64_t *ns) override; + bool IsConnected() override; + int32_t SetDisplayVsyncEnabled(bool enabled) override; + HdiDrmComposition *GetDrmComposition(); + +protected: + std::unique_ptr CreateHdiLayer(LayerType type) override; + +private: + int32_t PushFirstFrame(); + int32_t ConvertToHdiPowerState(uint32_t drmPowerState, DispPowerStatus &hdiPowerState); + int32_t ConvertToDrmPowerState(DispPowerStatus hdiPowerState, uint32_t &drmPowerState); + std::shared_ptr mDrmDevice; + std::shared_ptr mConnector; + std::shared_ptr mCrtc; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DISPLAY_H diff --git a/display/composer/vdi_base/include/drm_encoder.h b/display/composer/vdi_base/include/drm_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..0601ad2af2a725c45ac7ce1b2b60ea54185a7674 --- /dev/null +++ b/display/composer/vdi_base/include/drm_encoder.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2023 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 + +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 diff --git a/display/composer/vdi_base/include/drm_plane.h b/display/composer/vdi_base/include/drm_plane.h new file mode 100644 index 0000000000000000000000000000000000000000..d0bd9c9796a0145eaad494442ca9f7e65445f835 --- /dev/null +++ b/display/composer/vdi_base/include/drm_plane.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DRM_PLANE_H +#define DRM_PLANE_H +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +enum class DrmPropertyType { + DRM_PROPERTY_TYPE_INT, + DRM_PROPERTY_TYPE_ENUM, + DRM_PROPERTY_TYPE_OBJECT, + DRM_PROPERTY_TYPE_BLOB, + DRM_PROPERTY_TYPE_BITMASK, + DRM_PROPERTY_TYPE_INVALID, +}; + +enum class DrmPlaneType { + DRM_PLANE_TYPE_CLUSTER0_WIN0 = 1 << 0, + DRM_PLANE_TYPE_CLUSTER0_WIN1 = 1 << 1, + + DRM_PLANE_TYPE_CLUSTER1_WIN0 = 1 << 2, + DRM_PLANE_TYPE_CLUSTER1_WIN1 = 1 << 3, + + DRM_PLANE_TYPE_ESMART0_WIN0 = 1 << 4, + DRM_PLANE_TYPE_ESMART0_WIN1 = 1 << 5, + DRM_PLANE_TYPE_ESMART0_WIN2 = 1 << 6, + DRM_PLANE_TYPE_ESMART0_WIN3 = 1 << 7, + + DRM_PLANE_TYPE_ESMART1_WIN0 = 1 << 8, + DRM_PLANE_TYPE_ESMART1_WIN1 = 1 << 9, + DRM_PLANE_TYPE_ESMART1_WIN2 = 1 << 10, + DRM_PLANE_TYPE_ESMART1_WIN3 = 1 << 11, + + DRM_PLANE_TYPE_SMART0_WIN0 = 1 << 12, + DRM_PLANE_TYPE_SMART0_WIN1 = 1 << 13, + DRM_PLANE_TYPE_SMART0_WIN2 = 1 << 14, + DRM_PLANE_TYPE_SMART0_WIN3 = 1 << 15, + + DRM_PLANE_TYPE_SMART1_WIN0 = 1 << 16, + DRM_PLANE_TYPE_SMART1_WIN1 = 1 << 17, + DRM_PLANE_TYPE_SMART1_WIN2 = 1 << 18, + DRM_PLANE_TYPE_SMART1_WIN3 = 1 << 19, + + DRM_PLANE_TYPE_CLUSTER0_MASK = 0x3, + DRM_PLANE_TYPE_CLUSTER1_MASK = 0xc, + DRM_PLANE_TYPE_CLUSTER_MASK = 0xf, + DRM_PLANE_TYPE_ESMART0_MASK = 0xf0, + DRM_PLANE_TYPE_ESMART1_MASK = 0xf00, + DRM_PLANE_TYPE_SMART0_MASK = 0xf000, + DRM_PLANE_TYPE_SMART1_MASK = 0xf0000, + DRM_PLANE_TYPE_Unknown = 0xffffffff, +}; + +struct PlaneMaskName { + DrmPlaneType mask; + const char *name; +}; + +struct PlaneTypeName { + DrmPlaneType type; + const char *name; +}; + +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"; + +const std::string PROP_CRTC_X_ID = "CRTC_X"; +const std::string PROP_CRTC_Y_ID = "CRTC_Y"; +const std::string PROP_CRTC_W_ID = "CRTC_W"; +const std::string PROP_CRTC_H_ID = "CRTC_H"; + +const std::string PROP_SRC_X_ID = "SRC_X"; +const std::string PROP_SRC_Y_ID = "SRC_Y"; +const std::string PROP_SRC_W_ID = "SRC_W"; +const std::string PROP_SRC_H_ID = "SRC_H"; + +const std::string PROP_ZPOS_ID = "zpos"; + +class DrmDevice; + +class DrmPlane { +public: + explicit DrmPlane(drmModePlane &p); + virtual ~DrmPlane(); + int32_t Init(DrmDevice &drmDevice); + int GetCrtcProp(DrmDevice &drmDevice); + int GetSrcProp(DrmDevice &drmDevice); + uint32_t GetId() const + { + return mId; + } + uint32_t GetPropFbId() const + { + return mPropFbId; + } + uint32_t GetPropCrtc_xId() const + { + return mPropCrtc_xId; + } + uint32_t GetPropCrtc_yId() const + { + return mPropCrtc_yId; + } + uint32_t GetPropCrtc_wId() const + { + return mPropCrtc_wId; + } + uint32_t GetPropCrtc_hId() const + { + return mPropCrtc_hId; + } + uint32_t GetPropSrc_xId() const + { + return mPropSrc_xId; + } + uint32_t GetPropSrc_yId() const + { + return mPropSrc_yId; + } + uint32_t GetPropSrc_wId() const + { + return mPropSrc_wId; + } + uint32_t GetPropSrc_hId() const + { + return mPropSrc_hId; + } + uint32_t GetPropZposId() const + { + return mPropZposId; + } + 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); + } + uint32_t GetCrtcId() + { + return mCrtcId; + } + uint32_t GetPipe() + { + return mPipe; + } + DrmPlaneType GetWinType() + { + return mWinType; + } + std::string GetName() + { + return mName; + } +private: + uint32_t mId = 0; + uint32_t mPossibleCrtcs = 0; + uint32_t mCrtcId = 0; + uint32_t mPropFbId = 0; + uint32_t mPropFenceInId = 0; + uint32_t mPropCrtcId = 0; + DrmPlaneType mWinType = DrmPlaneType::DRM_PLANE_TYPE_Unknown; + std::string mName; + + uint32_t mPropCrtc_xId = 0; + uint32_t mPropCrtc_yId = 0; + uint32_t mPropCrtc_wId = 0; + uint32_t mPropCrtc_hId = 0; + + uint32_t mPropSrc_xId = 0; + uint32_t mPropSrc_yId = 0; + uint32_t mPropSrc_wId = 0; + uint32_t mPropSrc_hId = 0; + + uint32_t mPropZposId = 0; + + uint32_t mPipe = 0; + uint32_t mType = 0; + std::vector mFormats; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // DRM_PLANE_H diff --git a/display/composer/vdi_base/include/drm_vsync_worker.h b/display/composer/vdi_base/include/drm_vsync_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..d0572065ad19d9bcc286f8a219b1e0402d8f1ae3 --- /dev/null +++ b/display/composer/vdi_base/include/drm_vsync_worker.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-2023 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 "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 diff --git a/display/composer/vdi_base/include/hdi_composer.h b/display/composer/vdi_base/include/hdi_composer.h new file mode 100644 index 0000000000000000000000000000000000000000..b93d17e869b64ea7b739a71b9aa76ec0a740e751 --- /dev/null +++ b/display/composer/vdi_base/include/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/composer/vdi_base/include/hdi_device_common.h b/display/composer/vdi_base/include/hdi_device_common.h new file mode 100644 index 0000000000000000000000000000000000000000..1d90d0462e83fa930341c9bb61988a0c5e7ccce5 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_device_common.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-2023 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 "common/include/display_common.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +const int32_t INVALID_MODE_ID = -1; +const uint32_t DRM_INVALID_ID = 0xFFFFFFFF; +template using IdMapPtr = std::unordered_map>; +class DrmEncoder; +class DrmCrtc; +class DrmPlane; +class DrmDevice; +class DrmConnector; +class VsyncCallBack; +class DrmVsyncWorker; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DEVICE_COMMON_H diff --git a/display/composer/vdi_base/include/hdi_device_interface.h b/display/composer/vdi_base/include/hdi_device_interface.h new file mode 100644 index 0000000000000000000000000000000000000000..c345fadadd42e22e0d9a5ec9769d402f6b69671b --- /dev/null +++ b/display/composer/vdi_base/include/hdi_device_interface.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HDI_DEVICE_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 bool HandleHotplug(uint32_t dispId, bool plugIn) = 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/composer/vdi_base/include/hdi_display.h b/display/composer/vdi_base/include/hdi_display.h new file mode 100644 index 0000000000000000000000000000000000000000..0e8e598ab01b4c663028e24d17008e03308a9797 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_display.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-2023 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 "hdi_composer.h" +#include "hdi_layer.h" +#include "v1_0/display_composer_type.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, uint32_t pipe); + virtual void Vsync(unsigned int sequence, uint64_t ns); + virtual ~VsyncCallBack() {} + uint32_t GetPipe() + { + return mPipe; + } +private: + VBlankCallback mVBlankCb; + void *mData; + uint32_t mPipe; +}; + + +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 GetDisplaySupportedModes(uint32_t *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 DestroyLayer(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 diff --git a/display/composer/vdi_base/include/hdi_drm_composition.h b/display/composer/vdi_base/include/hdi_drm_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..49dfcfeec7d2f82024d96da8154e2c04c5ba0b76 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_drm_composition.h @@ -0,0 +1,75 @@ +/* + * 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(const std::shared_ptr &connector, + const std::shared_ptr &crtc, + const std::shared_ptr &drmDevice); + ~HdiDrmComposition() override {} + int32_t Init() override; + int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer) override; + int32_t Apply(bool modeSet) override; + int32_t UpdateMode(std::unique_ptr &modeBlock); + +private: + int32_t ApplyPlane(HdiDrmLayer &layer, HdiLayer &hlayer, DrmPlane &drmPlane, drmModeAtomicReqPtr pset); + int32_t SetSrcProperty(DrmPlane &drmPlane, drmModeAtomicReqPtr pset, int32_t bufferW, int32_t bufferH); + int32_t SetCrtcProperty(DrmPlane &drmPlane, drmModeAtomicReqPtr pset, int32_t bufferW, int32_t bufferH); + int32_t RemoveUnusePlane(drmModeAtomicReqPtr pset); + int32_t FindPlaneAndApply(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 diff --git a/display/composer/vdi_base/include/hdi_drm_layer.h b/display/composer/vdi_base/include/hdi_drm_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..b8eaef32e528c74c6eabec35b04a9a075e80d6ab --- /dev/null +++ b/display/composer/vdi_base/include/hdi_drm_layer.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021-2023 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 "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) {} + ~HdiDrmLayer() override {} + // Return value optimization + DrmGemBuffer *GetGemBuffer(); + +private: + std::unique_ptr mCurrentBuffer; + std::unique_ptr mLastBuffer; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_DRM_LAYER_H diff --git a/display/composer/vdi_base/include/hdi_gfx_composition.h b/display/composer/vdi_base/include/hdi_gfx_composition.h new file mode 100644 index 0000000000000000000000000000000000000000..cd1207927515a31760446d74f71f2fb01d8a927d --- /dev/null +++ b/display/composer/vdi_base/include/hdi_gfx_composition.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_GFX_COMPOSITION_H +#define HDI_GFX_COMPOSITION_H +#include "display_gfx.h" +#include "hdi_composer.h" +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiGfxComposition : public HdiComposition { +public: + int32_t Init(void) override; + int32_t SetLayers(std::vector &layers, HdiLayer &clientLayer) override; + int32_t Apply(bool modeSet) override; + ~HdiGfxComposition() override + { + (void)GfxModuleDeinit(); + } + +private: + bool CanHandle(HdiLayer &hdiLayer); + bool UseCompositionClient(std::vector &layers); + void InitGfxSurface(ISurface &iSurface, HdiLayerBuffer &buffer); + int32_t BlitLayer(HdiLayer &src, HdiLayer &dst); + int32_t ClearRect(HdiLayer &src, HdiLayer &dst); + int32_t GfxModuleInit(void); + int32_t GfxModuleDeinit(void); + void *mGfxModule = nullptr; + GfxFuncs *mGfxFuncs = nullptr; + HdiLayer *mClientLayer; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_GFX_COMPOSITION_H diff --git a/display/composer/vdi_base/include/hdi_layer.h b/display/composer/vdi_base/include/hdi_layer.h new file mode 100644 index 0000000000000000000000000000000000000000..a5310c61696097deb601e0c5192a0f943d7d51e8 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_layer.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2021-2023 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 "v1_0/display_composer_type.h" +#include "hdi_device_common.h" +#include "hdi_shared_fd.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Composer::V1_0; +const uint32_t INVALIDE_LAYER_ID = 0xffffffff; +const uint32_t FENCE_TIMEOUT = 3000; +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); + + void WaitAcquireFence(); + virtual int32_t SetLayerRegion(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 SetLayerTransformMode(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() + { + mIdSets.erase(mId); + } + +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; + int32_t mFenceTimeOut = FENCE_TIMEOUT; + TransformType mTransformType = ROTATE_BUTT; + 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 diff --git a/display/composer/vdi_base/include/hdi_netlink_monitor.h b/display/composer/vdi_base/include/hdi_netlink_monitor.h new file mode 100644 index 0000000000000000000000000000000000000000..6a7d8ff17a17e30de9d43263ceaa409f1c860681 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_netlink_monitor.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 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/composer/vdi_base/include/hdi_session.h b/display/composer/vdi_base/include/hdi_session.h new file mode 100644 index 0000000000000000000000000000000000000000..2314bf58c8de8fb60ea2a3b05e0d06669b873932 --- /dev/null +++ b/display/composer/vdi_base/include/hdi_session.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021-2023 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 "common/include/display_common.h" +#include "display_log.h" +#include "hdi_device_interface.h" +#include "hdi_display.h" +#include "hdi_netlink_monitor.h" +#include "v1_0/display_composer_type.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); + void HandleHotplug(bool plugIn); + +private: + std::shared_ptr mNetLinkMonitor; + std::unordered_map> mHdiDisplays; + std::vector> mHdiDevices; + std::unordered_map mHotPlugCallBacks; +}; +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY + +#endif // HDI_SESSION_H diff --git a/display/composer/vdi_base/include/hdi_shared_fd.h b/display/composer/vdi_base/include/hdi_shared_fd.h new file mode 100644 index 0000000000000000000000000000000000000000..1314c0750ef9eb2cd1d54335ae35d5ed07644f1c --- /dev/null +++ b/display/composer/vdi_base/include/hdi_shared_fd.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-2023 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 +#include "display_log.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +class HdiFd { +public: + HdiFd() + { + DISPLAY_LOGD(); + } + explicit HdiFd(int fd) : mFd(fd) + { + DISPLAY_LOGD("mFd %{public}d", mFd); + } + int GetFd() const + { + return mFd; + }; + + HdiFd &operator = (int fd) + { + if (mFd >= 0) { + close(mFd); + } + mFd = fd; + return *this; + } + + virtual ~HdiFd() + { + if (mFd >= 0) { + close(mFd); + } + } + +private: + int mFd = -1; +}; + +using FdPtr = std::shared_ptr; +} // OHOS +} // HDIO +} // DISPLAY + +#endif // HDI_SHARED_FD diff --git a/display/composer/vdi_base/src/display_composer_vdi_impl.cpp b/display/composer/vdi_base/src/display_composer_vdi_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b61a0c7e6249bc53434c948086e88fa00a0086c0 --- /dev/null +++ b/display/composer/vdi_base/src/display_composer_vdi_impl.cpp @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 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_composer_vdi_impl.h" +#include +#include "display_log.h" +#include "hdf_log.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +DisplayComposerVdiImpl::DisplayComposerVdiImpl() +{ +} + +DisplayComposerVdiImpl::~DisplayComposerVdiImpl() +{ +} + +int32_t DisplayComposerVdiImpl::RegHotPlugCallback(HotPlugCallback cb, void* data) +{ + HdiSession::GetInstance().RegHotPlugCallback(cb, data); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayCapability(uint32_t devId, DisplayCapability& info) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCapability, &info); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplaySupportedModes(uint32_t devId, std::vector& modes) +{ + DisplayModeInfo* placeHoler = nullptr; + uint32_t num = 0; + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplaySupportedModes, + &num, placeHoler); + if (ec != DISPLAY_SUCCESS) { + DISPLAY_LOGE("failed, ec=%{public}d", ec); + return HDF_FAILURE; + } + if (num != 0) { + modes.resize(num); + ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplaySupportedModes, &num, + modes.data()); + } + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayMode(uint32_t devId, uint32_t& modeId) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayMode, &modeId); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetDisplayMode(uint32_t devId, uint32_t modeId) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayMode, modeId); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayPowerStatus(uint32_t devId, DispPowerStatus& status) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayPowerStatus, &status); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayPowerStatus, status); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayBacklight(uint32_t devId, uint32_t& level) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayBacklight, &level); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetDisplayBacklight(uint32_t devId, uint32_t level) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayBacklight, level); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t& value) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::GetDisplayCompChange(uint32_t devId, std::vector& layers, + std::vector& types) +{ + uint32_t* layersHoler = nullptr; + int32_t* typesHoler = nullptr; + uint32_t num = 0; + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCompChange, &num, + layersHoler, typesHoler); + if (ec == HDF_SUCCESS && num != 0) { + layers.resize(num); + types.resize(num); + ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCompChange, &num, + layers.data(), types.data()); + } + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetDisplayClientCrop(uint32_t devId, const IRect& rect) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetDisplayClientBuffer(uint32_t devId, const BufferHandle& buffer, int32_t fence) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayClientBuffer, &buffer, + fence); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetDisplayClientDamage(uint32_t devId, std::vector& rects) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetDisplayVsyncEnabled(uint32_t devId, bool enabled) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayVsyncEnabled, enabled); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::RegDisplayVBlankCallback(uint32_t devId, VBlankCallback cb, void* data) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::RegDisplayVBlankCallback, cb, data); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::GetDisplayReleaseFence(uint32_t devId, std::vector& layers, + std::vector& fences) +{ + uint32_t* layersHoler = nullptr; + int32_t* typesHoler = nullptr; + uint32_t num = 0; + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayReleaseFence, &num, + layersHoler, typesHoler); + if (ec == HDF_SUCCESS && num != 0) { + layers.resize(num); + fences.resize(num); + ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayReleaseFence, &num, + layers.data(), fences.data()); + } + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t& format, uint32_t& devId) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::DestroyVirtualDisplay(uint32_t devId) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetVirtualDisplayBuffer(uint32_t devId, const BufferHandle& buffer, const int32_t fence) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::Commit(uint32_t devId, int32_t& fence) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::Commit, &fence); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::CreateLayer(uint32_t devId, const LayerInfo& layerInfo, uint32_t& layerId) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CreateLayer, &layerInfo, &layerId); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::DestroyLayer(uint32_t devId, uint32_t layerId) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::DestroyLayer, layerId); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::PrepareDisplayLayers(uint32_t devId, bool& needFlushFb) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::PrepareDisplayLayers, &needFlushFb); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerAlpha(uint32_t devId, uint32_t layerId, const LayerAlpha& alpha) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerAlpha, + const_cast(&alpha)); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerRegion(uint32_t devId, uint32_t layerId, const IRect& rect) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerRegion, + const_cast(&rect)); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerCrop(uint32_t devId, uint32_t layerId, const IRect& rect) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCrop, + const_cast(&rect)); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerZorder(uint32_t devId, uint32_t layerId, uint32_t zorder) +{ + int32_t ec = HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetLayerZorder, layerId, zorder); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerPreMulti(uint32_t devId, uint32_t layerId, bool preMul) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerPreMulti, preMul); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerTransformMode(uint32_t devId, uint32_t layerId, TransformType type) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerTransformMode, type); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, const std::vector& rects) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerDirtyRegion, + const_cast(rects.data())); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerVisibleRegion(uint32_t devId, uint32_t layerId, std::vector& rects) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetLayerBuffer(uint32_t devId, uint32_t layerId, const BufferHandle& buffer, + int32_t fence) +{ + const BufferHandle* holder = &buffer; + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBuffer, holder, fence); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerCompositionType(uint32_t devId, uint32_t layerId, CompositionType type) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerCompositionType, type); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerBlendType(uint32_t devId, uint32_t layerId, BlendType type) +{ + int32_t ec = HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerBlendType, type); + DISPLAY_CHK_RETURN(ec != DISPLAY_SUCCESS, HDF_FAILURE, DISPLAY_LOGE("failed, ec=%{public}d", ec)); + return HDF_SUCCESS; +} + +int32_t DisplayComposerVdiImpl::SetLayerMaskInfo(uint32_t devId, uint32_t layerId, const MaskInfo maskInfo) +{ + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +int32_t DisplayComposerVdiImpl::SetLayerColor(uint32_t devId, uint32_t layerId, const LayerColor& layerColor) +{ + DISPLAY_LOGE("%s layerColor: r=%{public}d, g=%{public}d, b=%{public}d, a=%{public}d", + __func__, layerColor.r, layerColor.g, layerColor.b, layerColor.a); + DISPLAY_LOGE("%s is not supported", __func__); + return HDF_ERR_NOT_SUPPORT; +} + +extern "C" IDisplayComposerVdi *CreateComposerVdi() +{ + return new DisplayComposerVdiImpl(); +} + +extern "C" void DestroyComposerVdi(IDisplayComposerVdi* vdi) +{ + delete vdi; +} +} // DISPLAY +} // HDI +} // OHOS diff --git a/display/composer/vdi_base/src/drm_connector.cpp b/display/composer/vdi_base/src/drm_connector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..82a648ef08cffa6d6a25667b3c25277db1a4b740 --- /dev/null +++ b/display/composer/vdi_base/src/drm_connector.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_connector.h" +#include +#include +#include +#include +#include "display_log.h" +#include "drm_device.h" +#include "drm_vsync_worker.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +void DrmMode::ConvertToHdiMode(DisplayModeInfo &hdiMode) +{ + hdiMode.height = mModeInfo.vdisplay; + hdiMode.width = mModeInfo.hdisplay; + hdiMode.freshRate = mModeInfo.vrefresh; + hdiMode.id = mId; +} + +DrmConnector::DrmConnector(drmModeConnector c, FdPtr &fd) + : mId(c.connector_id), + mPhyWidth(c.mmWidth), + mPhyHeight(c.mmHeight), + mEncoderId(c.encoder_id), + mConnectState(c.connection), + mDrmFdPtr(fd) +{ + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + DISPLAY_LOGD("the connect state is %{public}d", mConnectState); + + for (int i = 0; i < c.count_encoders; i++) { + mPossibleEncoders.push_back(c.encoders[i]); + DISPLAY_LOGD("add possible encoder id %{public}d", c.encoders[i]); + } + + ConvertToHdiType(c.connector_type, mType); + ConvertTypeToName(mType, mName); + InitModes(c); + DISPLAY_LOGD("name %{public}s", mName.c_str()); +} + +void DrmConnector::InitModes(drmModeConnector c) +{ + DISPLAY_LOGD("id %{public}d mode size %{public}d", mId, c.count_modes); + mModes.clear(); + mPreferenceId = INVALID_MODE_ID; + for (int i = 0; i < c.count_modes; i++) { + drmModeModeInfoPtr mode = c.modes + i; + DISPLAY_LOGD("mode: hdisplay %{public}d, vdisplay %{public}d vrefresh %{public}d type %{public}d", + mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->type); + if ((mPreferenceId == INVALID_MODE_ID) && (mode->type & DRM_MODE_TYPE_PREFERRED)) { + DISPLAY_LOGD("set it to prefernce id %{public}d", i); + mPreferenceId = i; + } + mModes.emplace(i, DrmMode { *mode, i }); + } + DISPLAY_LOGD("mode count %{public}zd", mModes.size()); +} + +int32_t DrmConnector::Init(DrmDevice &drmDevice) +{ + int32_t ret; + DrmProperty prop; + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((mDrmFdPtr == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("the mDrmFdPtr is nullptr")); + DISPLAY_CHK_RETURN((mDrmFdPtr->GetFd() == -1), DISPLAY_FAILURE, DISPLAY_LOGE("the drm fd is -1")); + // find dpms prop + ret = drmDevice.GetConnectorProperty(*this, PROP_DPMS, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not get mode prop id")); + mPropDpmsId = prop.propId; + mDpmsState = prop.value; + DISPLAY_LOGD("dpms state : %{public}" PRIu64 "", mDpmsState); + // find the crtcid + ret = drmDevice.GetConnectorProperty(*this, PROP_CRTCID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get out fence prop id")); + mPropCrtcId = prop.propId; + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + DISPLAY_LOGD("mPropCrtcId %{public}d", mPropCrtcId); + // find the brightness + ret = drmDevice.GetConnectorProperty(*this, PROP_BRIGHTNESS, prop); + if (ret == DISPLAY_SUCCESS) { + mPropBrightnessId = prop.propId; + mBrightnessLevel = static_cast(prop.value); + DISPLAY_LOGD("prop brightness is %{public}d, level is %{public}d", mPropBrightnessId, mBrightnessLevel); + } else { + DISPLAY_LOGW("can not get the brightness prop, can not set the brightness"); + } + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::GetBrightness(uint32_t& level) +{ + if (mPropBrightnessId == DRM_INVALID_ID) { + DISPLAY_LOGE("the prop id of brightness is invalid"); + return DISPLAY_NOT_SUPPORT; + } + level = mBrightnessLevel; + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::SetBrightness(uint32_t level) +{ + static int32_t brFd = 0; + const int32_t buffer_size = 10; /* buffer size */ + char buffer[buffer_size]; + + DISPLAY_LOGD("set %{public}d", level); + if (mPropBrightnessId == DRM_INVALID_ID) { + DISPLAY_LOGE("the prop id of brightness is invalid"); + return DISPLAY_NOT_SUPPORT; + } + if (brFd <= 0) { + brFd = open("/sys/class/backlight/backlight/brightness", O_RDWR); + if (brFd < 0) { + DISPLAY_LOGE("open brightness file failed\n"); + return DISPLAY_NOT_SUPPORT; + } + } + errno_t ret = memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); + if (ret != EOK) { + DISPLAY_LOGE("memset_s failed\n"); + return DISPLAY_FAILURE; + } + int bytes = sprintf_s(buffer, sizeof(buffer), "%d\n", level); + if (bytes < 0) { + DISPLAY_LOGE("change failed\n"); + return DISPLAY_FAILURE; + } + write(brFd, buffer, bytes); + mBrightnessLevel = level; + return DISPLAY_SUCCESS; +} + +void DrmConnector::GetDisplayCap(DisplayCapability &cap) +{ + cap.phyHeight = mPhyHeight; + cap.phyWidth = mPhyWidth; + cap.type = mType; + memcpy_s(const_cast(cap.name.c_str()), cap.name.size(), mName.c_str(), mName.size()); + if (mName.size() >= sizeof(cap.name)) { + cap.name[sizeof(cap.name) - 1] = 0; + } else { + cap.name[mName.size()] = 0; + } + cap.supportLayers = mSupportLayers; + cap.virtualDispCount = mVirtualDispCount; + cap.supportWriteBack = mSupportWriteBack; + cap.propertyCount = mPropertyCount; +} + +void DrmConnector::ConvertTypeToName(uint32_t type, std::string &name) +{ + DISPLAY_LOGD("type %{public}d", type); + switch (type) { + case DISP_INTF_VGA: + name = "VGA"; + break; + case DISP_INTF_HDMI: + name = "HDMI"; + break; + case DISP_INTF_MIPI: + name = "MIPI"; + break; + default: + name = "Unknown"; + break; + } +} + +void DrmConnector::ConvertToHdiType(uint32_t type, InterfaceType &hdiType) +{ + switch (type) { + case DRM_MODE_CONNECTOR_VGA: + hdiType = DISP_INTF_VGA; + break; + case DRM_MODE_CONNECTOR_DSI: + hdiType = DISP_INTF_MIPI; + break; + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + hdiType = DISP_INTF_HDMI; + break; + default: + hdiType = DISP_INTF_BUTT; + break; + } +} +int32_t DrmConnector::TryPickEncoder(IdMapPtr &encoders, uint32_t encoderId, IdMapPtr &crtcs, + uint32_t &crtcId) +{ + int ret; + auto encoderIter = encoders.find(encoderId); + if (encoderIter == encoders.end()) { + DISPLAY_LOGW("can not find encoder for id : %{public}d", encoderId); + return DISPLAY_FAILURE; + } + + auto &encoder = encoderIter->second; + DISPLAY_LOGD("connector : %{public}d encoder : %{public}d", mId, encoder->GetId()); + ret = encoder->PickIdleCrtcId(crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick encoder : %{public}d", mId, encoder->GetId())); + return DISPLAY_FAILURE; +} + +int32_t DrmConnector::PickIdleCrtcId(IdMapPtr &encoders, IdMapPtr &crtcs, uint32_t &crtcId) +{ + DISPLAY_LOGD(); + DISPLAY_LOGD("encoder_id %{public}d", mEncoderId); + int ret = TryPickEncoder(encoders, mEncoderId, crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick endcoder : %{public}d crtcId : %{public}d", + mId, mEncoderId, crtcId)); + + for (auto encoder : mPossibleEncoders) { + ret = TryPickEncoder(encoders, encoder, crtcs, crtcId); + DISPLAY_CHK_RETURN((ret == DISPLAY_SUCCESS), DISPLAY_SUCCESS, + DISPLAY_LOGD("connector : %{public}d pick endcoder : %{public}d crtcId : %{public}d", mId, mEncoderId, + crtcId)); + } + + DISPLAY_LOGW("can not pick a crtc for connector"); + return DISPLAY_FAILURE; +} + +int32_t DrmConnector::UpdateModes() +{ + int drmFd = mDrmFdPtr->GetFd(); + drmModeConnectorPtr c = drmModeGetConnector(drmFd, mId); + DISPLAY_CHK_RETURN((c == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get connector")); + mConnectState = c->connection; + // init the modes + InitModes(*c); + drmModeFreeConnector(c); + return DISPLAY_SUCCESS; +} + +std::shared_ptr DrmConnector::UpdateCrtcId(IdMapPtr &encoders, + IdMapPtr &crtcs, bool plugIn, drmModeConnectorPtr c, int *crtc_id) +{ + std::shared_ptr crtc = nullptr; + int encoderid = c->encoders[0]; + auto encoderIter = encoders.find(encoderid); + if (encoderIter == encoders.end()) { + DISPLAY_LOGW("can not find encoder for id : %{public}d", encoderid); + return crtc; + } + + auto &encoder = encoderIter->second; + int possibleCrtcs = encoder->GetPossibleCrtcs(); + + for (auto crtcIter = crtcs.begin(); crtcIter != crtcs.end(); ++crtcIter) { + auto &posCrts = crtcIter->second; + if (possibleCrtcs == (1<GetPipe())) { + DISPLAY_LOGD("find crtc id %{public}d, pipe %{public}d", posCrts->GetId(), posCrts->GetPipe()); + crtc = posCrts; + *crtc_id = posCrts->GetId(); + } + } + if (plugIn) { + encoder->SetCrtcId(*crtc_id); + mEncoderId = c->encoders[0]; + } else if (!plugIn) { + *crtc_id = 0; + mEncoderId = 0; + encoder->SetCrtcId(0); + } + return crtc; +} + +bool DrmConnector::HandleHotplug(IdMapPtr &encoders, + IdMapPtr &crtcs, bool plugIn) +{ + DISPLAY_LOGD("plug %{public}d", plugIn); + int drmFd = mDrmFdPtr->GetFd(); + int ret; + int crtc_id = 0; + std::shared_ptr crtc; + uint32_t blob_id; + drmModeAtomicReq *pset = drmModeAtomicAlloc(); + DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR, + DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno)); + + drmModeConnectorPtr c = drmModeGetConnector(drmFd, mId); + DISPLAY_CHK_RETURN((c == nullptr), false, DISPLAY_LOGE("can not get connector")); + if (mConnectState == c->connection) { + drmModeFreeConnector(c); + return false; + } else { + crtc = UpdateCrtcId(encoders, crtcs, plugIn, c, &crtc_id); + if (crtc == nullptr) { + return DISPLAY_FAILURE; + } + DISPLAY_LOGD("get crtc id %{public}d ", crtc_id); + + DrmVsyncWorker::GetInstance().EnableVsync(plugIn); + drmModeCreatePropertyBlob(drmFd, &c->modes[0], + sizeof(c->modes[0]), &blob_id); + ret = drmModeAtomicAddProperty(pset, crtc->GetId(), crtc->GetActivePropId(), (int)plugIn); + ret |= drmModeAtomicAddProperty(pset, crtc->GetId(), crtc->GetModePropId(), blob_id); + ret |= drmModeAtomicAddProperty(pset, GetId(), GetPropCrtcId(), crtc_id); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); + + ret = drmModeAtomicCommit(drmFd, pset, DRM_MODE_ATOMIC_ALLOW_MODESET, nullptr); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); + drmModeAtomicFree(pset); + + mConnectState = c->connection; + InitModes(*c); + drmModeFreeConnector(c); + return true; + } +} + +int32_t DrmConnector::GetDisplaySupportedModes(uint32_t *num, DisplayModeInfo *modes) +{ + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + *num = static_cast(mModes.size()); + if (modes != nullptr) { + int i = 0; + for (const auto &modeMap : mModes) { + DrmMode mode = modeMap.second; + mode.ConvertToHdiMode(*(modes + i)); + i++; + } + } + return DISPLAY_SUCCESS; +} + +int32_t DrmConnector::SetDpmsState(uint64_t dmps) +{ + DISPLAY_LOGD("dmps %{public}" PRIu64 "", dmps); + int ret = drmModeConnectorSetProperty(mDrmFdPtr->GetFd(), mId, mPropDpmsId, dmps); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("can not set dpms")); + mDpmsState = dmps; + return DISPLAY_SUCCESS; +} + +bool DrmConnector::IsConnected() +{ + return (mConnectState == DRM_MODE_CONNECTED); +} + +int32_t DrmConnector::GetModeFromId(int32_t id, DrmMode &mode) +{ + DISPLAY_LOGD(); + auto iter = mModes.find(id); + if (iter == mModes.end()) { + return DISPLAY_FAILURE; + } + mode = mModes[id]; + return DISPLAY_SUCCESS; +} + +std::unique_ptr DrmConnector::GetModeBlockFromId(int32_t id) +{ + DISPLAY_LOGD("id %{public}d", id); + auto iter = mModes.find(id); + DISPLAY_CHK_RETURN((iter == mModes.end()), nullptr, DISPLAY_LOGE("can not the mode %{public}d", id)); + return std::make_unique(mModes[id]); +} + +DrmModeBlock::DrmModeBlock(DrmMode &mode) +{ + DISPLAY_LOGD(); + Init(mode); +} + +int32_t DrmModeBlock::Init(DrmMode &mode) +{ + int ret; + int drmFd = 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 = DrmDevice::GetDrmFd(); + if ((mBlockId != DRM_INVALID_ID) && (drmFd >= 0)) { + int ret = drmModeDestroyPropertyBlob(drmFd, mBlockId); + if (ret != 0) { + DISPLAY_LOGE("destroy property blob failed errno %{public}d", errno); + } + } else { + DISPLAY_LOGE("can not destruct the block id %{public}d drmFd %{public}d", mBlockId, drmFd); + } +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/drm_crtc.cpp b/display/composer/vdi_base/src/drm_crtc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd4197302cc0da02c93f35be2ee3bef6879b026c --- /dev/null +++ b/display/composer/vdi_base/src/drm_crtc.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021-2023 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_log.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +struct PlaneMaskName planeMaskNames[] = { + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER0_MASK, "Cluster0" }, + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER1_MASK, "Cluster1" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART0_MASK, "Esmart0" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART1_MASK, "Esmart1" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART0_MASK, "Smart0" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART1_MASK, "Smart1" }, + { DrmPlaneType::DRM_PLANE_TYPE_Unknown, "unknown" }, +}; + +DrmCrtc::DrmCrtc(drmModeCrtcPtr c, uint32_t pipe) : mId(c->crtc_id), mPipe(pipe), mPlaneMask(0) +{ +} + +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; + + // Plane mask + mPlaneMask = 0; + ret = drmDevice.GetCrtcProperty(*this, "PLANE_MASK", prop); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("Failed to get plane_mask property"); + } else { + for (int i = 0; i < static_cast(ARRAY_SIZE(planeMaskNames)); i++) { + for (auto &drmEnum : prop.enums) { + if (!strncmp(drmEnum.name.c_str(), (const char*)planeMaskNames[i].name, + strlen(drmEnum.name.c_str())) && (prop.value & (1LL << drmEnum.value)) > 0) { + mPlaneMask |= static_cast(planeMaskNames[i].mask); + DISPLAY_LOGI("crtc id %{public}d, plane name %{public}s value %{public}llx", + GetId(), (const char*)planeMaskNames[i].name, + (long long)planeMaskNames[i].mask); + } + } + } + } + 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/composer/vdi_base/src/drm_device.cpp b/display/composer/vdi_base/src/drm_device.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9628213ba102d1e3572d39c6c2ae7a8b594526e5 --- /dev/null +++ b/display/composer/vdi_base/src/drm_device.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_device.h" +#include +#include +#include +#include +#include +#include "display_log.h" +#include "drm_display.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +FdPtr DrmDevice::mDrmFd = nullptr; +std::shared_ptr DrmDevice::mInstance; + +std::shared_ptr DrmDevice::Create() +{ + DISPLAY_LOGD(); + if (mDrmFd == nullptr) { + const std::string name("rockchip"); + int drmFd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); // drmOpen(name.c_str(), nullptr); + if (drmFd < 0) { + DISPLAY_LOGE("drm file:%{public}s open failed %{public}s", name.c_str(), strerror(errno)); + return nullptr; + } + DISPLAY_LOGD("the drm fd is %{public}d", drmFd); + mDrmFd = std::make_shared(drmFd); + } + if (mInstance == nullptr) { + mInstance = std::make_shared(); + } + return mInstance; +} + +int DrmDevice::GetDrmFd() +{ + if (mDrmFd == nullptr) { + DISPLAY_LOGE("the drmfd is null not open"); + return -1; + } + return mDrmFd->GetFd(); +} + +using PixelFormatConvertTbl = struct PixFmtConvertTbl { + uint32_t drmFormat; + PixelFormat pixFormat; +}; + +uint32_t DrmDevice::ConvertToDrmFormat(PixelFormat fmtIn) +{ + static const PixelFormatConvertTbl convertTable[] = { + {DRM_FORMAT_XBGR8888, PIXEL_FMT_RGBX_8888}, {DRM_FORMAT_ABGR8888, PIXEL_FMT_RGBA_8888}, + {DRM_FORMAT_RGB888, PIXEL_FMT_RGB_888}, {DRM_FORMAT_RGB565, PIXEL_FMT_BGR_565}, + {DRM_FORMAT_BGRX4444, PIXEL_FMT_BGRX_4444}, {DRM_FORMAT_BGRA4444, PIXEL_FMT_BGRA_4444}, + {DRM_FORMAT_RGBA4444, PIXEL_FMT_RGBA_4444}, {DRM_FORMAT_RGBX4444, PIXEL_FMT_RGBX_4444}, + {DRM_FORMAT_BGRX5551, PIXEL_FMT_BGRX_5551}, {DRM_FORMAT_BGRA5551, PIXEL_FMT_BGRA_5551}, + {DRM_FORMAT_BGRX8888, PIXEL_FMT_BGRX_8888}, {DRM_FORMAT_ARGB8888, PIXEL_FMT_BGRA_8888}, + {DRM_FORMAT_NV12, PIXEL_FMT_YCBCR_420_SP}, {DRM_FORMAT_NV21, PIXEL_FMT_YCRCB_420_SP}, + {DRM_FORMAT_YUV420, PIXEL_FMT_YCBCR_420_P}, {DRM_FORMAT_YVU420, PIXEL_FMT_YCRCB_420_P}, + {DRM_FORMAT_NV16, PIXEL_FMT_YCBCR_422_SP}, {DRM_FORMAT_NV61, PIXEL_FMT_YCRCB_422_SP}, + {DRM_FORMAT_YUV422, PIXEL_FMT_YCBCR_422_P}, {DRM_FORMAT_YVU422, PIXEL_FMT_YCRCB_422_P}, + }; + uint32_t fmtOut = 0; + for (uint32_t i = 0; i < sizeof(convertTable) / sizeof(convertTable[0]); i++) { + if (convertTable[i].pixFormat == fmtIn) { + fmtOut = convertTable[i].drmFormat; + } + } + DISPLAY_LOGD("fmtIn %{public}d, outFmt %{public}d", fmtIn, fmtOut); + return fmtOut; +} + +DrmDevice::DrmDevice() {} + +int32_t DrmDevice::GetCrtcProperty(const DrmCrtc &crtc, const std::string &name, DrmProperty &prop) +{ + return GetProperty(crtc.GetId(), DRM_MODE_OBJECT_CRTC, name, prop); +} + +int32_t DrmDevice::GetConnectorProperty(const DrmConnector &connector, const std::string &name, DrmProperty &prop) +{ + return GetProperty(connector.GetId(), DRM_MODE_OBJECT_CONNECTOR, name, prop); +} + +int32_t DrmDevice::GetPlaneProperty(const DrmPlane &plane, const std::string &name, DrmProperty &prop) +{ + return GetProperty(plane.GetId(), DRM_MODE_OBJECT_PLANE, name, prop); +} + +int32_t DrmDevice::GetProperty(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]; + prop.name = p->name; + prop.flags = p->flags; + + for (int i = 0; i < p->count_values; ++i) { + prop.values.push_back(p->values[i]); + } + for (int i = 0; i < p->count_enums; ++i) { + prop.enums.push_back(DrmPropertyEnum(&p->enums[i])); + } + + for (int i = 0; i < p->count_blobs; ++i) { + prop.blob_ids.push_back(p->blob_ids[i]); + } + if (prop.flags & DRM_MODE_PROP_RANGE) { + prop.type = static_cast(DrmPropertyType::DRM_PROPERTY_TYPE_INT); + } else if (prop.flags & DRM_MODE_PROP_ENUM) { + prop.type = static_cast(DrmPropertyType::DRM_PROPERTY_TYPE_ENUM); + } else if (prop.flags & DRM_MODE_PROP_OBJECT) { + prop.type = static_cast(DrmPropertyType::DRM_PROPERTY_TYPE_OBJECT); + } else if (prop.flags & DRM_MODE_PROP_BLOB) { + prop.type = static_cast(DrmPropertyType::DRM_PROPERTY_TYPE_BLOB); + } else if (prop.flags & DRM_MODE_PROP_BITMASK) { + prop.type = static_cast(DrmPropertyType::DRM_PROPERTY_TYPE_BITMASK); + } + } + drmModeFreeProperty(p); + } + drmModeFreeObjectProperties(props); + return found ? DISPLAY_SUCCESS : DISPLAY_NOT_SUPPORT; +} + +int32_t DrmDevice::Init() +{ + int ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, + DISPLAY_LOGE("DRM_CLIENT_CAP_UNIVERSAL_PLANES set failed %{public}s", strerror(errno))); + ret = drmSetClientCap(GetDrmFd(), DRM_CLIENT_CAP_ATOMIC, 1); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, + DISPLAY_LOGE("DRM_CLIENT_CAP_ATOMIC set failed %{public}s", strerror(errno))); + + ret = drmSetMaster(GetDrmFd()); + DISPLAY_CHK_RETURN((ret), DISPLAY_FAILURE, DISPLAY_LOGE("can not set to master errno : %{public}d", errno)); + DISPLAY_LOGE("chenyf master"); + ret = drmIsMaster(GetDrmFd()); + DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("is not master : %{public}d", errno)); + + return DISPLAY_SUCCESS; +} + +void DrmDevice::DeInit() +{ + mDisplays.clear(); + mCrtcs.clear(); +} + +void DrmDevice::FindAllCrtc(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mCrtcs.clear(); + for (int i = 0; i < res->count_crtcs; i++) { + drmModeCrtcPtr crtc = drmModeGetCrtc(GetDrmFd(), res->crtcs[i]); + if (!crtc) { + DISPLAY_LOGE("can not get crtc %{public}d", i); + continue; + } + uint32_t crtc_id = crtc->crtc_id; + std::shared_ptr drmCrtc = std::make_shared(crtc, i); + int ret = drmCrtc->Init(*this); + drmModeFreeCrtc(crtc); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("crtc %{public}d init failed", i); + continue; + } + mCrtcs.emplace(crtc_id, std::move(drmCrtc)); + } +} + +void DrmDevice::FindAllEncoder(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mEncoders.clear(); + for (int i = 0; i < res->count_encoders; i++) { + drmModeEncoderPtr encoder = drmModeGetEncoder(GetDrmFd(), res->encoders[i]); + if (!encoder) { + DISPLAY_LOGE("can not get encoder %{public}d", i); + continue; + } + std::shared_ptr drmEncoder = std::make_shared(*encoder); + mEncoders.emplace(encoder->encoder_id, std::move(drmEncoder)); + drmModeFreeEncoder(encoder); + } + DISPLAY_LOGD("find encoder count %{public}zd", mEncoders.size()); +} + +void DrmDevice::FindAllConnector(const drmModeResPtr &res) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((res == nullptr), DISPLAY_LOGE("the res is null")); + mConnectors.clear(); + int ret; + for (int i = 0; i < res->count_connectors; i++) { + drmModeConnectorPtr connector = drmModeGetConnector(GetDrmFd(), res->connectors[i]); + if (!connector) { + DISPLAY_LOGE("can not get connector mode %{public}d", i); + continue; + } + std::shared_ptr drmConnector = std::make_shared(*connector, mDrmFd); + ret = drmConnector->Init(*this); + drmModeFreeConnector(connector); + if (ret != DISPLAY_SUCCESS) { + continue; + } + int connectorId = drmConnector->GetId(); + mConnectors.emplace(connectorId, std::move(drmConnector)); + } + DISPLAY_LOGD("find connector count %{public}zd", mConnectors.size()); +} + +void DrmDevice::FindAllPlane() +{ + mPlanes.clear(); + int ret; + drmModePlaneResPtr planeRes = drmModeGetPlaneResources(GetDrmFd()); + DISPLAY_CHK_RETURN_NOT_VALUE((planeRes == nullptr), DISPLAY_LOGE("can not get plane resource")); + DISPLAY_LOGD("count_planes %{public}d", planeRes->count_planes); + for (uint32_t i = 0; i < planeRes->count_planes; i++) { + drmModePlanePtr p = drmModeGetPlane(GetDrmFd(), planeRes->planes[i]); + if (!p) { + DISPLAY_LOGE("can not get plane %{public}d", i); + continue; + } + std::shared_ptr drmPlane = std::make_shared(*p); + DISPLAY_LOGD(); + ret = drmPlane->Init(*this); + DISPLAY_LOGD(); + drmModeFreePlane(p); + if (ret != DISPLAY_SUCCESS) { + DISPLAY_LOGE("drm plane %{public}d init failed", i); + continue; + } + mPlanes.emplace_back(std::move(drmPlane)); + } + DISPLAY_LOGD("find plane count %{public}zd", mPlanes.size()); +} + +std::shared_ptr DrmDevice::GetDrmEncoderFromId(uint32_t id) +{ + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmConnectorFromId(uint32_t id) +{ + return nullptr; +} + +std::shared_ptr DrmDevice::GetDrmCrtcFromId(uint32_t id) +{ + 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())) { + planes.push_back(plane); + } + } + DISPLAY_LOGD("the planes count %{public}zd", planes.size()); + return planes; +} + +bool DrmDevice::HandleHotplug(uint32_t dispId, bool plugIn) +{ + uint32_t find = 0; + uint32_t connectorId; + + for (auto &dispConnectorIdMap : dispConnectorIdMaps_) { + if (dispConnectorIdMap.first == dispId) { + connectorId = dispConnectorIdMap.second; + find = 1; + break; + } + } + if (find) { + for (auto &connectorPair : mConnectors) { + auto connector = connectorPair.second; + if (connectorId == connector->GetId()) { + if (connector->HandleHotplug(mEncoders, mCrtcs, plugIn) == true) { + connector->Init(*this); + return true; + } + } + } + } + return false; +} + +std::unordered_map> DrmDevice::DiscoveryDisplay() +{ + uint32_t dispId; + uint32_t connectorId; + + dispConnectorIdMaps_.clear(); + mDisplays.clear(); + drmModeResPtr res = drmModeGetResources(GetDrmFd()); + DISPLAY_CHK_RETURN((res == nullptr), mDisplays, DISPLAY_LOGE("can not get drm resource")); + // discovery all drm resource + FindAllCrtc(res); + FindAllEncoder(res); + FindAllConnector(res); + FindAllPlane(); + DISPLAY_LOGD(); + // travel all connector + for (auto &connectorPair : mConnectors) { + auto connector = connectorPair.second; + uint32_t crtcId = 0; + int32_t ret = connector->PickIdleCrtcId(mEncoders, mCrtcs, crtcId); + if (ret != DISPLAY_SUCCESS) { + continue; + } + DISPLAY_LOGD(); + + auto crtcIter = mCrtcs.find(crtcId); + if (crtcIter == mCrtcs.end()) { + DISPLAY_LOGE("can not find crtc for the id %{public}d", connector->GetId()); + continue; + } + DISPLAY_LOGD(); + auto crtc = crtcIter->second; + // create the display + std::shared_ptr display = std::make_shared(connector, crtc, mInstance); + DISPLAY_LOGD(); + display->Init(); + dispId = display->GetId(); + connectorId = connector->GetId(); + mDisplays.emplace(dispId, std::move(display)); + dispConnectorIdMaps_.emplace(dispId, connectorId); + } + DISPLAY_LOGD("find display size %{public}zd", mDisplays.size()); + return mDisplays; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/drm_display.cpp b/display/composer/vdi_base/src/drm_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b13a83b8131c9487ede9632cabf6a17737cdfcf --- /dev/null +++ b/display/composer/vdi_base/src/drm_display.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2021-2023 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 +#include "display_buffer_vdi_impl.h" +#include "display_log.h" +#include "drm_device.h" +#include "drm_vsync_worker.h" +#include "hdi_drm_composition.h" +#include "hdi_gfx_composition.h" +#include "idisplay_buffer_vdi.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +using namespace OHOS::HDI::Display::Buffer::V1_0; +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::GetDisplaySupportedModes(uint32_t *num, DisplayModeInfo *modes) +{ + mConnector->GetDisplaySupportedModes(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) +{ + static int32_t fb_fd = -1; + int32_t err = -1; + const uint32_t FBIOBLANK = 0x4611; /* arg: 0 or vesa level + 1 */ + const uint32_t FB_BLANK_UNBLANK = 0; /* screen: unblanked, hsync: on, vsync: on */ + const uint32_t FB_BLANK_POWERDOWN = 4; /* screen: blanked, hsync: off, vsync: off */ + + DISPLAY_LOGD("SetDisplayPowerStatus power state %{public}u", status); + if (fb_fd < 0) { + fb_fd = open("/dev/graphics/fb0", O_RDWR); + if (fb_fd < 0) { + DISPLAY_LOGE("oepn fb0 file failed\n"); + return DISPLAY_NOT_SUPPORT; + } + } + switch (status) { + case POWER_STATUS_OFF: + case POWER_STATUS_STANDBY: + case POWER_STATUS_SUSPEND: + err = ioctl(fb_fd, FBIOBLANK, FB_BLANK_POWERDOWN); + break; + case POWER_STATUS_ON: + err = ioctl(fb_fd, FBIOBLANK, FB_BLANK_UNBLANK); + break; + default: + err = DISPLAY_FAILURE; + break; + } + if (err < 0) { + DISPLAY_LOGE("ioctl fb0 failed\n"); + return DISPLAY_FAILURE; + } + + 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() +{ + std::shared_ptr hdiImpl = std::make_shared(); + int ret = DISPLAY_SUCCESS; + DrmMode mode; + ret = mConnector->GetModeFromId(mCrtc->GetActiveModeId(), mode); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("can not get the mode from id %{public}d", mCrtc->GetActiveModeId())); + const 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 = hdiImpl->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) { + uint32_t num = 0; + ret = GetDisplaySupportedModes(&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) +{ + (void)data; + std::shared_ptr vsyncCb = std::make_shared(cb, data, mCrtc->GetPipe()); + 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/composer/vdi_base/src/drm_encoder.cpp b/display/composer/vdi_base/src/drm_encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84ab6a79bb8a16f4410c1194411aa54616ca843a --- /dev/null +++ b/display/composer/vdi_base/src/drm_encoder.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021-2023 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); + for (crtcIter = crtcs.begin(); crtcIter != crtcs.end(); ++crtcIter) { + auto &posCrts = crtcIter->second; + if (mPossibleCrtcs == (1<GetPipe())) { + DISPLAY_LOGD("find crtc id %{public}d, pipe %{public}d", posCrts->GetId(), posCrts->GetPipe()); + break; + } + } + } + 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/composer/vdi_base/src/drm_plane.cpp b/display/composer/vdi_base/src/drm_plane.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e77278c200d8c5c34cde4c74fc7355982107c7b3 --- /dev/null +++ b/display/composer/vdi_base/src/drm_plane.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "drm_plane.h" +#include "drm_device.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +struct PlaneTypeName planeTypeNames[] = { + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER0_WIN0, "Cluster0-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER0_WIN1, "Cluster0-win1" }, + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER1_WIN0, "Cluster1-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_CLUSTER1_WIN1, "Cluster1-win1" }, + + { DrmPlaneType::DRM_PLANE_TYPE_ESMART0_WIN0, "Esmart0-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART0_WIN1, "Esmart0-win1" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART0_WIN2, "Esmart0-win2" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART0_WIN3, "Esmart0-win3" }, + + { DrmPlaneType::DRM_PLANE_TYPE_ESMART1_WIN0, "Esmart1-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART1_WIN1, "Esmart1-win1" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART1_WIN2, "Esmart1-win2" }, + { DrmPlaneType::DRM_PLANE_TYPE_ESMART1_WIN3, "Esmart1-win3" }, + + { DrmPlaneType::DRM_PLANE_TYPE_SMART0_WIN0, "Smart0-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART0_WIN1, "Smart0-win1" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART0_WIN2, "Smart0-win2" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART0_WIN3, "Smart0-win3" }, + + { DrmPlaneType::DRM_PLANE_TYPE_SMART1_WIN0, "Smart1-win0" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART1_WIN1, "Smart1-win1" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART1_WIN2, "Smart1-win2" }, + { DrmPlaneType::DRM_PLANE_TYPE_SMART1_WIN3, "Smart1-win3" }, + + { DrmPlaneType::DRM_PLANE_TYPE_Unknown, "unknown" }, +}; + +DrmPlane::DrmPlane(drmModePlane &p) + : mId(p.plane_id), mPossibleCrtcs(p.possible_crtcs), mCrtcId(p.crtc_id), + mFormats(p.formats, p.formats + p.count_formats) +{} + +DrmPlane::~DrmPlane() +{ + DISPLAY_LOGD(); +} + +int DrmPlane::GetCrtcProp(DrmDevice &drmDevice) +{ + int32_t ret; + int32_t crtc_x, crtc_y, crtc_w, crtc_h; + DrmProperty prop; + + ret = drmDevice.GetPlaneProperty(*this, PROP_CRTC_X_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc_x prop id")); + mPropCrtc_xId = prop.propId; + crtc_x = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_CRTC_Y_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc_y prop id")); + mPropCrtc_yId = prop.propId; + crtc_y = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_CRTC_W_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc_w prop id")); + mPropCrtc_wId = prop.propId; + crtc_w = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_CRTC_H_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc_h prop id")); + mPropCrtc_hId = prop.propId; + crtc_h = prop.value; + + DISPLAY_LOGE("plane %{public}d crtc_x %{public}d crtc_y %{public}d crtc_w %{public}d crtc_h %{public}d", + GetId(), crtc_x, crtc_y, crtc_w, crtc_h); + + return 0; +} + +int DrmPlane::GetSrcProp(DrmDevice &drmDevice) +{ + int32_t ret; + int32_t src_x, src_y, src_w, src_h; + DrmProperty prop; + + ret = drmDevice.GetPlaneProperty(*this, PROP_SRC_X_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane src_x prop id")); + mPropSrc_xId = prop.propId; + src_x = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_SRC_Y_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane src_y prop id")); + mPropSrc_yId = prop.propId; + src_y = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_SRC_W_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane src_w prop id")); + mPropSrc_wId = prop.propId; + src_w = prop.value; + + ret = drmDevice.GetPlaneProperty(*this, PROP_SRC_H_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane src_h prop id")); + mPropSrc_hId = prop.propId; + src_h = prop.value; + + DISPLAY_LOGE("plane %{public}d src_x %{public}d src_y %{public}d src_w %{public}d src_h %{public}d", + GetId(), src_x, src_y, src_w, src_h); + + return 0; +} + +int32_t DrmPlane::Init(DrmDevice &drmDevice) +{ + DISPLAY_LOGD(); + int32_t ret; + uint32_t find_name = 0; + DrmProperty prop; + GetCrtcProp(drmDevice); + GetSrcProp(drmDevice); + 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_ZPOS_ID, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc prop id")); + mPropZposId = prop.propId; + + ret = drmDevice.GetPlaneProperty(*this, "NAME", prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc prop id")); + + for (int i = 0; i < static_castARRAY_SIZE(planeTypeNames); i++) { + find_name = 0; + + for (auto &drmEnum : prop.enums) { + if (!strncmp(drmEnum.name.c_str(), (const char*)planeTypeNames[i].name, + strlen(planeTypeNames[i].name))) { + find_name = (1LL << drmEnum.value); + } + } + + if (find_name) { + DISPLAY_LOGI("find plane id %{public}d, type %{public}x %{public}s", + GetId(), planeTypeNames[i].type, planeTypeNames[i].name); + mWinType = planeTypeNames[i].type; + mName = planeTypeNames[i].name; + break; + } + } + + ret = drmDevice.GetPlaneProperty(*this, PROP_TYPE, prop); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("cat not get pane crtc prop id")); + switch (prop.value) { + case DRM_PLANE_TYPE_OVERLAY: + case DRM_PLANE_TYPE_PRIMARY: + case DRM_PLANE_TYPE_CURSOR: + mType = static_cast(prop.value); + break; + default: + DISPLAY_LOGE("unknown type value %{public}" PRIu64 "", prop.value); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/drm_vsync_worker.cpp b/display/composer/vdi_base/src/drm_vsync_worker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fd364f38e7c62013a896fc2098eebb99b6210ed --- /dev/null +++ b/display/composer/vdi_base/src/drm_vsync_worker.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021-2023 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_log.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, + } + }; + /* The drmWaitVBlank need set the crtc pipe when there are multi crtcs in the system. */ + if (mCallBack->GetPipe() == 1) + vblank.request.type = drmVBlankSeqType((int)(vblank.request.type) | (int)DRM_VBLANK_SECONDARY); + int ret = drmWaitVBlank(mDrmFd, &vblank); + DISPLAY_CHK_RETURN((ret < 0), 0, + DISPLAY_LOGE("wait vblank failed ret : %{public}d errno %{public}d", ret, errno)); + sq = vblank.reply.sequence; + return (uint64_t)(vblank.reply.tval_sec * SEC_TO_NSEC + vblank.reply.tval_usec * USEC_TO_NSEC); +} + + +void DrmVsyncWorker::EnableVsync(bool enable) +{ + DISPLAY_LOGD(); + { + std::lock_guard lg(mMutex); + mEnable = enable; + } + mCondition.notify_one(); +} + +void DrmVsyncWorker::WorkThread() +{ + DISPLAY_LOGD(); + unsigned int seq = 0; + while (WaitSignalAndCheckRuning()) { + // wait the vblank + uint64_t time = WaitNextVBlank(seq); + if (mCallBack != nullptr) { + mCallBack->Vsync(seq, time); + } else { + DISPLAY_LOGE("the callbac is nullptr"); + } + } +} + +void DrmVsyncWorker::ReqesterVBlankCb(std::shared_ptr &cb) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN_NOT_VALUE((cb == nullptr), DISPLAY_LOGE("the VBlankCallback is nullptr ")); + mCallBack = cb; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/hdi_composer.cpp b/display/composer/vdi_base/src/hdi_composer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bd0aec1cbf038ebe1a7c3e9cc545bf90b9ef1c8 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_composer.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_composer.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiComposer::HdiComposer(std::unique_ptr pre, std::unique_ptr post) +{ + mPreComp = std::move(pre); + mPostComp = std::move(post); +} + +int32_t HdiComposer::Prepare(std::vector &layers, HdiLayer &clientLayer) +{ + int ret = mPreComp->SetLayers(layers, clientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("pre composition prepare failed")); + ret = mPostComp->SetLayers(layers, clientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("post composition prepare failed")); + return DISPLAY_SUCCESS; +} + +int32_t HdiComposer::Commit(bool modeSet) +{ + int ret = mPreComp->Apply(modeSet); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("pre composition apply failed")); + DISPLAY_LOGD("commit modSet=%{public}d", modeSet); + 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/composer/vdi_base/src/hdi_device_interface.cpp b/display/composer/vdi_base/src/hdi_device_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44de85979de0cb960b156eeb9b2729e40b85c627 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_device_interface.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2023 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_log.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; +} +} +} +} diff --git a/display/composer/vdi_base/src/hdi_display.cpp b/display/composer/vdi_base/src/hdi_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c5cab55f9c9368cb803e57f6777e3992a8310cd --- /dev/null +++ b/display/composer/vdi_base/src/hdi_display.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021-2023 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_log.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +uint32_t HdiDisplay::mIdleId = 0; +std::unordered_set HdiDisplay::mIdSets; + +uint32_t HdiDisplay::GetIdleId() +{ + const uint32_t oldIdleId = mIdleId; + uint32_t id = INVALIDE_DISPLAY_ID; + // ensure the mIdleId not INVALIDE_DISPLAY_ID + mIdleId = mIdleId % INVALIDE_DISPLAY_ID; + do { + auto iter = mIdSets.find(mIdleId); + if (iter == mIdSets.end()) { + id = mIdleId; + break; + } + mIdleId = (mIdleId + 1) % INVALIDE_DISPLAY_ID; + } while (oldIdleId != mIdleId); + mIdSets.emplace(id); + mIdleId++; + return id; +} + + +int32_t HdiDisplay::Init() +{ + DISPLAY_LOGD(); + uint32_t id = GetIdleId(); + DISPLAY_CHK_RETURN((id == INVALIDE_DISPLAY_ID), DISPLAY_FAILURE, DISPLAY_LOGE("have no id to used")); + mId = id; + auto layer = CreateHdiLayer(LAYER_TYPE_GRAPHIC); + DISPLAY_CHK_RETURN((layer.get() == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create hdi layer for client")); + mClientLayer = std::move(layer); + DISPLAY_LOGD("the id is %{public}d", id); + return DISPLAY_SUCCESS; +} + + +HdiDisplay::~HdiDisplay() +{ + mIdSets.erase(mId); +} + +int32_t HdiDisplay::SetLayerZorder(uint32_t layerId, uint32_t zorder) +{ + DISPLAY_LOGD("layerId : %{public}d", layerId); + auto iter = mLayersMap.find(layerId); + DISPLAY_CHK_RETURN((iter == mLayersMap.end()), DISPLAY_FAILURE, + DISPLAY_LOGE("can not find the layer %{public}d", layerId)); + auto layer = mLayersMap[layerId].get(); + if (layer->GetZorder() == zorder) { + DISPLAY_LOGD("zorder no change layerId %{public}d, zorder %{public}d", layerId, zorder); + return DISPLAY_SUCCESS; + } + // reset to sort + auto zRange = mLayers.equal_range(layer); + 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::DestroyLayer(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) = dup(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; + uint32_t topZpos = 3; + for (auto c : mLayers) { + layers.push_back(c); + } + DISPLAY_LOGD(" mLayers size %{public}zu layers size %{public}zu", mLayers.size(), layers.size()); + + /* Set the target layer to the top. + * It would not by cover by other layer. + */ + mClientLayer->SetLayerZorder(topZpos); + + 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 = dup(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, uint32_t displayId) : mVBlankCb(cb), + mData(data), mPipe(displayId) +{ +} + +void VsyncCallBack::Vsync(unsigned int sequence, uint64_t ns) +{ + DISPLAY_CHK_RETURN_NOT_VALUE((mVBlankCb == nullptr), DISPLAY_LOGE("the callback is nullptr")); + mVBlankCb(sequence, ns, mData); +} +} +} +} diff --git a/display/composer/vdi_base/src/hdi_drm_composition.cpp b/display/composer/vdi_base/src/hdi_drm_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e6e88beae5f37ab1f141ffbcd369a61eb23eadc --- /dev/null +++ b/display/composer/vdi_base/src/hdi_drm_composition.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2021-2023 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(const std::shared_ptr &connector, + const std::shared_ptr &crtc, + const 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); + 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::SetCrtcProperty(DrmPlane &drmPlane, + drmModeAtomicReqPtr pset, + int32_t bufferW, + int32_t bufferH) +{ + int ret; + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_xId(), 0); + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropCrtc_xId %{public}d, crop.x %{public}d", drmPlane.GetId(), + drmPlane.GetPropCrtc_xId(), 0); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_yId(), 0); + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropCrtc_yId %{public}d, crop.y %{public}d", drmPlane.GetId(), + drmPlane.GetPropCrtc_yId(), 0); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_wId(), bufferW); + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropCrtc_wId %{public}d, crop.w %{public}d", drmPlane.GetId(), + drmPlane.GetPropCrtc_wId(), bufferW); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropCrtc_hId(), bufferH); + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropCrtc_hId %{public}d, crop.h %{public}d", drmPlane.GetId(), + drmPlane.GetPropCrtc_xId(), bufferH); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::SetSrcProperty(DrmPlane &drmPlane, + drmModeAtomicReqPtr pset, + int32_t bufferW, + int32_t bufferH) +{ + int ret; + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 0 << 16); // 16:shift left 16 bits + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropSrc_xId %{public}d, displayRect.x %{public}d", + drmPlane.GetId(), drmPlane.GetPropSrc_xId(), 0); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 0 << 16); // 16:shift left 16 bits + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropSrc_yId %{public}d, displayRect.y %{public}d", + drmPlane.GetId(), drmPlane.GetPropSrc_yId(), 0); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_wId(), + bufferW << 16); // 16:shift left 16 bits + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropCrtc_wId %{public}d, displayRect.w %{public}d", + drmPlane.GetId(), drmPlane.GetPropSrc_wId(), bufferW); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropSrc_hId(), + bufferH << 16); // 16:shift left 16 bits + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropSrc_hId %{public}d, displayRect.h %{public}d", + drmPlane.GetId(), drmPlane.GetPropSrc_hId(), bufferH); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the fb planeid fialed errno : %{public}d", errno)); + + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::ApplyPlane(HdiDrmLayer &layer, + HdiLayer &hlayer, + DrmPlane &drmPlane, + drmModeAtomicReqPtr pset) +{ + int ret; + int fenceFd = layer.GetAcquireFenceFd(); + int propId = drmPlane.GetPropFenceInId(); + HdiLayerBuffer *layerBuffer = hlayer.GetCurrentBuffer(); + int32_t bufferW = layerBuffer->GetWight(); + int32_t bufferH = layerBuffer->GetHeight(); + + 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")); + } + } + + ret = SetCrtcProperty(drmPlane, pset, bufferW, bufferH); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set Crtc fialed errno : %{public}d", errno)); + + ret = SetSrcProperty(drmPlane, pset, bufferW, bufferH); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set Src fialed errno : %{public}d", errno)); + + ret = drmModeAtomicAddProperty(pset, drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder()); + DISPLAY_LOGD("set the fb planeid %{public}d, GetPropZposId %{public}d, zpos %{public}d", + drmPlane.GetId(), drmPlane.GetPropZposId(), layer.GetZorder()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the zpos fialed errno : %{public}d", errno)); + + // 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) +{ + // set the mode + DISPLAY_LOGD(); + if (mCrtc->NeedModeSet()) { + int drmFd = mDrmDevice->GetDrmFd(); + drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); + modeBlock = mConnector->GetModeBlockFromId(mCrtc->GetActiveModeId()); + if ((modeBlock != nullptr) && (modeBlock->GetBlockId() != DRM_INVALID_ID)) { + // set to active + DISPLAY_LOGD("set crtc to active"); + int ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetActivePropId(), 1); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the active prop errno %{public}d", errno)); + + // set the mode id + DISPLAY_LOGD("set the mode"); + ret = drmModeAtomicAddProperty(pset, mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId()); + DISPLAY_LOGD("set the mode planeId %{public}d, propId %{public}d, GetBlockId: %{public}d", + mCrtc->GetId(), mCrtc->GetModePropId(), modeBlock->GetBlockId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the mode prop errno %{public}d", errno)); + ret = drmModeAtomicAddProperty(pset, mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_LOGD("set the connector id: %{public}d, propId %{public}d, crtcId %{public}d", + mConnector->GetId(), mConnector->GetPropCrtcId(), mCrtc->GetId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, + DISPLAY_LOGE("can not add the crtc id prop %{public}d", errno)); + + uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + ret = drmModeAtomicCommit(drmFd, pset, flags, nullptr); + DISPLAY_CHK_RETURN((ret != 0), DISPLAY_FAILURE, + DISPLAY_LOGE("drmModeAtomicCommit failed %{public}d errno %{public}d", ret, errno)); + mCrtc->ClearModeSet(); + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::RemoveUnusePlane(drmModeAtomicReqPtr pset) +{ + int ret = 0; + /* Remove useless planes from the drm */ + for (uint32_t j = 0; j < mPlanes.size(); j++) { + auto &drmPlane = mPlanes[j]; + if ((static_cast(drmPlane->GetWinType()) & mCrtc->GetPlaneMask()) && drmPlane->GetPipe() == 0) { + DISPLAY_LOGD("no used plane %{public}s id %{public}d", drmPlane->GetName().c_str(), drmPlane->GetId()); + ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0); + ret = drmModeAtomicAddProperty(pset, drmPlane->GetId(), drmPlane->GetPropFbId(), 0); + drmPlane->UnBindPipe(); + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::FindPlaneAndApply(drmModeAtomicReqPtr pset) +{ + int32_t ret = 0; + for (uint32_t i = 0; i < mCompLayers.size(); i++) { + HdiDrmLayer *layer = static_cast(mCompLayers[i]); + HdiLayer *hlayer = mCompLayers[i]; + for (uint32_t j = 0; j < mPlanes.size(); j++) { + auto &drmPlane = mPlanes[j]; + if (drmPlane->GetPipe() != 0 && drmPlane->GetPipe() != (1 << mCrtc->GetPipe())) { + DISPLAY_LOGD("plane %{public}d used pipe %{public}d crtc pipe %{public}d", drmPlane->GetId(), + drmPlane->GetPipe(), mCrtc->GetPipe()); + continue; + } + /* Check whether the plane belond to the crtc */ + if (!(static_cast(drmPlane->GetWinType()) & mCrtc->GetPlaneMask())) { + continue; + } + DISPLAY_LOGD("use plane %{public}d WinType %{public}x crtc %{public}d PlaneMask %{public}x", + drmPlane->GetId(), drmPlane->GetWinType(), mCrtc->GetId(), mCrtc->GetPlaneMask()); + + if (drmPlane->GetCrtcId() == mCrtc->GetId() || drmPlane->GetCrtcId() == 0) { + ret = ApplyPlane(*layer, *hlayer, *drmPlane, pset); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), ret, DISPLAY_LOGE("apply plane failed")); + /* mark the plane is used by crtc */ + drmPlane->BindToPipe(1 << mCrtc->GetPipe()); + break; + } + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiDrmComposition::Apply(bool modeSet) +{ + uint64_t crtcOutFence = -1; + int ret = 0; + std::unique_ptr modeBlock; + int drmFd = mDrmDevice->GetDrmFd(); + + ret = UpdateMode(modeBlock); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("update mode failed")); + + DISPLAY_LOGD("mPlane size: %{public}zd mCompLayers size: %{public}zd", mPlanes.size(), mCompLayers.size()); + DISPLAY_CHK_RETURN((mPlanes.size() < mCompLayers.size()), DISPLAY_FAILURE, DISPLAY_LOGE("plane not enough")); + drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); + DISPLAY_CHK_RETURN((pset == nullptr), DISPLAY_NULL_PTR, + DISPLAY_LOGE("drm atomic alloc failed errno %{public}d", errno)); + AtomicReqPtr atomicReqPtr = AtomicReqPtr(pset); + + // set the outFence property + ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(), + (uint64_t)&crtcOutFence); + + DISPLAY_LOGD("Apply Set OutFence crtc id: %{public}d, fencePropId %{public}d", mCrtc->GetId(), + mCrtc->GetOutFencePropId()); + DISPLAY_CHK_RETURN((ret < 0), DISPLAY_FAILURE, DISPLAY_LOGE("set the outfence property of crtc failed ")); + + // set the plane info. + DISPLAY_LOGD("mCompLayers size %{public}zd", mCompLayers.size()); + DISPLAY_LOGD("crtc id %{public}d connect id %{public}d encoder id %{public}d", mCrtc->GetId(), + mConnector->GetId(), mConnector->GetEncoderId()); + + /* Bind the plane not used by other crtcs to the crtc. */ + FindPlaneAndApply(atomicReqPtr.Get()); + /* Remove useless planes from the drm */ + RemoveUnusePlane(atomicReqPtr.Get()); + + 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)); + + // 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)); + + uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK; + + 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/composer/vdi_base/src/hdi_drm_layer.cpp b/display/composer/vdi_base/src/hdi_drm_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..723c93c2633da743cd0aded2cbec8185d8775f50 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_drm_layer.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021-2023 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 "display_log.h" +#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_LOGD("can not free gem handle %{public}d errno : %{public}d", mGemHandle, errno); + } + } +} + +bool DrmGemBuffer::IsValid() +{ + DISPLAY_LOGD(); + return (mGemHandle != INVALID_DRM_ID) && (mFdId != INVALID_DRM_ID); +} + +DrmGemBuffer *HdiDrmLayer::GetGemBuffer() +{ + DISPLAY_LOGD(); + std::unique_ptr ptr = std::make_unique(DrmDevice::GetDrmFd(), *GetCurrentBuffer()); + mLastBuffer = std::move(mCurrentBuffer); + mCurrentBuffer = std::move(ptr); + return mCurrentBuffer.get(); +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/hdi_gfx_composition.cpp b/display/composer/vdi_base/src/hdi_gfx_composition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d9f544e1b993e1a6d76e8b19d9afcf5b52fe35a --- /dev/null +++ b/display/composer/vdi_base/src/hdi_gfx_composition.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hdi_gfx_composition.h" +#include +#include +#include +#include "display_log.h" +#include "display_gfx.h" +#include "hitrace_meter.h" +#include "v1_0/display_composer_type.h" + +using namespace OHOS::HDI::Display::Composer::V1_0; + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +int32_t HdiGfxComposition::Init(void) +{ + DISPLAY_LOGD(); + int32_t ret = GfxModuleInit(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS) || (mGfxFuncs == nullptr), DISPLAY_FAILURE, + DISPLAY_LOGE("GfxModuleInit failed")); + ret = mGfxFuncs->InitGfx(); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("gfx init failed")); + return DISPLAY_SUCCESS; +} + +int32_t HdiGfxComposition::GfxModuleInit(void) +{ + DISPLAY_LOGD(); + mGfxModule = dlopen("libdisplay_gfx.z.so", RTLD_NOW | RTLD_NOLOAD); + if (mGfxModule != nullptr) { + DISPLAY_LOGI("Module '%{public}s' already loaded", "libdisplay_gfx.z.so"); + } else { + DISPLAY_LOGI("Loading module '%{public}s'", "libdisplay_gfx.z.so"); + mGfxModule = dlopen("libdisplay_gfx.z.so", RTLD_NOW); + if (mGfxModule == nullptr) { + DISPLAY_LOGE("Failed to load module: %{public}s", dlerror()); + return DISPLAY_FAILURE; + } + } + + using InitFunc = int32_t (*)(GfxFuncs **funcs); + InitFunc func = reinterpret_cast(dlsym(mGfxModule, "GfxInitialize")); + if (func == nullptr) { + DISPLAY_LOGE("Failed to lookup %{public}s function: %s", "GfxInitialize", dlerror()); + dlclose(mGfxModule); + return DISPLAY_FAILURE; + } + return func(&mGfxFuncs); +} + +int32_t HdiGfxComposition::GfxModuleDeinit(void) +{ + DISPLAY_LOGD(); + int32_t ret = DISPLAY_SUCCESS; + if (mGfxModule == nullptr) { + using DeinitFunc = int32_t (*)(GfxFuncs *funcs); + DeinitFunc func = reinterpret_cast(dlsym(mGfxModule, "GfxUninitialize")); + if (func == nullptr) { + DISPLAY_LOGE("Failed to lookup %{public}s function: %s", "GfxUninitialize", dlerror()); + } else { + ret = func(mGfxFuncs); + } + dlclose(mGfxModule); + } + return ret; +} + +bool HdiGfxComposition::CanHandle(HdiLayer &hdiLayer) +{ + DISPLAY_LOGD(); + (void)hdiLayer; + return true; +} + +bool HdiGfxComposition::UseCompositionClient(std::vector &layers) +{ + const int32_t MAX_LAYER_COUNT = 4; + int32_t layerCount = 0; + bool hasCompositionClient = false; + + for (auto &layer : layers) { + if (!CanHandle(*layer)) { + continue; + } + CompositionType type = layer->GetCompositionType(); + layerCount += (type != COMPOSITION_VIDEO) && (type != COMPOSITION_CURSOR); + hasCompositionClient = hasCompositionClient || (type == COMPOSITION_CLIENT); + } + return hasCompositionClient || (layerCount > MAX_LAYER_COUNT); +} + +int32_t HdiGfxComposition::SetLayers(std::vector &layers, HdiLayer &clientLayer) +{ + DISPLAY_LOGD("layers size %{public}zd", layers.size()); + CompositionType defaultCompType = UseCompositionClient(layers) ? COMPOSITION_CLIENT : COMPOSITION_DEVICE; + mClientLayer = &clientLayer; + mCompLayers.clear(); + for (auto &layer : layers) { + if (!CanHandle(*layer)) { + continue; + } + + if ((layer->GetCompositionType() == COMPOSITION_VIDEO) || + (layer->GetCompositionType() == COMPOSITION_CURSOR)) { + layer->SetDeviceSelect(layer->GetCompositionType()); + } else { + layer->SetDeviceSelect(defaultCompType); + } + + mCompLayers.push_back(layer); + } + DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size()); + return DISPLAY_SUCCESS; +} + +void HdiGfxComposition::InitGfxSurface(ISurface &iSurface, HdiLayerBuffer &buffer) +{ + iSurface.width = buffer.GetWight(); + iSurface.height = buffer.GetHeight(); + iSurface.phyAddr = buffer.GetFb(); // buffer.GetPhysicalAddr(); + iSurface.enColorFmt = (PixelFormat)buffer.GetFormat(); + iSurface.stride = buffer.GetStride(); + iSurface.bAlphaExt1555 = true; + iSurface.bAlphaMax255 = true; + iSurface.alpha0 = 0XFF; + iSurface.alpha1 = 0XFF; + DISPLAY_LOGD("iSurface fd %{public}d w:%{public}d h:%{public}d addr:0x%{public}" \ + PRIx64 " fmt:%{public}d stride:%{public}d", + buffer.GetFb(), iSurface.width, iSurface.height, + buffer.GetPhysicalAddr(), iSurface.enColorFmt, iSurface.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 }; + StartTrace(HITRACE_TAG_HDF, "HDI:DISP:WaitAcquireFence"); + src.WaitAcquireFence(); + FinishTrace(HITRACE_TAG_HDF); + 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 iSurface"); + 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 iSurface"); + InitGfxSurface(dstSurface, *dstBuffer); + + opt.blendType = src.GetLayerBlenType(); + DISPLAY_LOGD("blendType %{public}d", opt.blendType); + opt.enPixelAlpha = true; + opt.enableScale = true; + + if (src.GetAlpha().enGlobalAlpha) { // is alpha is 0xff we not set it + opt.enGlobalAlpha = true; + srcSurface.alpha0 = src.GetAlpha().gAlpha; + DISPLAY_LOGD("src alpha %{public}x", src.GetAlpha().gAlpha); + } + opt.rotateType = src.GetTransFormType(); + DISPLAY_LOGD(" the roate type is %{public}d", opt.rotateType); + IRect crop = src.GetLayerCrop(); + IRect displayRect = src.GetLayerDisplayRect(); + DISPLAY_LOGD("crop x: %{public}d y : %{public}d w : %{public}d h: %{public}d", crop.x, crop.y, crop.w, crop.h); + DISPLAY_LOGD("displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", + displayRect.x, displayRect.y, displayRect.w, displayRect.h); + DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Blit: mGfxFuncs is null")); + return mGfxFuncs->Blit(&srcSurface, &crop, &dstSurface, &displayRect, &opt); +} + +int32_t HdiGfxComposition::ClearRect(HdiLayer &src, HdiLayer &dst) +{ + ISurface dstSurface = { 0 }; + GfxOpt opt = { 0 }; + DISPLAY_LOGD(); + HdiLayerBuffer *dstBuffer = dst.GetCurrentBuffer(); + DISPLAY_CHK_RETURN((dstBuffer == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not get client layer buffer")); + InitGfxSurface(dstSurface, *dstBuffer); + IRect rect = src.GetLayerDisplayRect(); + DISPLAY_CHK_RETURN(mGfxFuncs == nullptr, DISPLAY_FAILURE, DISPLAY_LOGE("Rect: mGfxFuncs is null")); + return mGfxFuncs->FillRect(&dstSurface, &rect, 0, &opt); +} + +int32_t HdiGfxComposition::Apply(bool modeSet) +{ + StartTrace(HITRACE_TAG_HDF, "HDI:DISP:Apply"); + int32_t ret; + DISPLAY_LOGD("composer layers size %{public}zd", mCompLayers.size()); + for (uint32_t i = 0; i < mCompLayers.size(); i++) { + HdiLayer *layer = mCompLayers[i]; + CompositionType compType = layer->GetCompositionType(); + switch (compType) { + case COMPOSITION_VIDEO: + ret = ClearRect(*layer, *mClientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("clear layer %{public}d failed", i)); + break; + case COMPOSITION_DEVICE: + ret = BlitLayer(*layer, *mClientLayer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, + DISPLAY_LOGE("blit layer %{public}d failed ", i)); + break; + default: + DISPLAY_LOGE("the gfx composition can not surpport the type %{public}d", compType); + break; + } + } + FinishTrace(HITRACE_TAG_HDF); + return DISPLAY_SUCCESS; +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/hdi_layer.cpp b/display/composer/vdi_base/src/hdi_layer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9174c810816ef016c5e4d850b0c4489ecdca808 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_layer.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2021-2023 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 +#include +#include +#include +#include +#include +#include +#include "display_buffer_vdi_impl.h" +#include "v1_0/display_composer_type.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +uint32_t HdiLayer::mIdleId = 0; +std::unordered_set HdiLayer::mIdSets; +std::shared_ptr g_buffer; +constexpr int TIME_BUFFER_MAX_LEN = 15; +const std::string PATH_PREFIX = "/data/local/traces/"; + +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 = dup(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::SetLayerRegion(IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr")); + DISPLAY_LOGD(" displayRect x: %{public}d y : %{public}d w : %{public}d h : %{public}d", rect->x, rect->y, + rect->w, rect->h); + mDisplayRect = *rect; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerCrop(IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in rect is nullptr")); + DISPLAY_LOGD("id : %{public}d crop x: %{public}d y : %{public}d w : %{public}d h : %{public}d", mId, + rect->x, rect->y, rect->w, rect->h); + mCrop = *rect; + return DISPLAY_SUCCESS; +} + +void HdiLayer::SetLayerZorder(uint32_t zorder) +{ + DISPLAY_LOGD("id : %{public}d zorder : %{public}d ", mId, zorder); + mZorder = zorder; +} + +int32_t HdiLayer::SetLayerPreMulti(bool preMul) +{ + DISPLAY_LOGD(); + mPreMul = preMul; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerAlpha(LayerAlpha *alpha) +{ + DISPLAY_CHK_RETURN((alpha == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("in alpha is nullptr")); + DISPLAY_LOGD("enable alpha %{public}d galpha 0x%{public}x", alpha->enGlobalAlpha, alpha->gAlpha); + mAlpha = *alpha; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerTransformMode(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; +} + +static std::string GetFileName(const BufferHandle *buffer) +{ + struct timeval tv; + char nowStr[TIME_BUFFER_MAX_LEN] = {0}; + + gettimeofday(&tv, nullptr); + if (strftime(nowStr, sizeof(nowStr), "%m-%d-%H-%M-%S", localtime(&tv.tv_sec)) == 0) { + DISPLAY_LOGE("strftime failed"); + return ""; + }; + + std::ostringstream strStream; + strStream << "hdi_layer_" << nowStr << "_" << tv.tv_usec << "_" << buffer->width << "_" << buffer->height << ".img"; + return strStream.str(); +} + +static int32_t DumpLayerBuffer(BufferHandle *buffer) +{ + CHECK_NULLPOINTER_RETURN_VALUE(buffer, DISPLAY_NULL_PTR); + + int32_t ret = 0; + if (g_buffer== nullptr) { + IDisplayBufferVdi* dispBuf = new DisplayBufferVdiImpl(); + DISPLAY_CHK_RETURN((dispBuf == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("dispBuf init failed")); + g_buffer.reset(dispBuf); + } + + std::string fileName = GetFileName(buffer); + DISPLAY_CHK_RETURN((fileName == ""), DISPLAY_FAILURE, DISPLAY_LOGE("GetFileName failed")); + DISPLAY_LOGI("fileName = %{public}s", fileName.c_str()); + + std::stringstream filePath; + filePath << PATH_PREFIX << fileName; + std::ofstream rawDataFile(filePath.str(), std::ofstream::binary); + DISPLAY_CHK_RETURN((!rawDataFile.good()), DISPLAY_FAILURE, DISPLAY_LOGE("open file failed, %{public}s", + std::strerror(errno))); + + void *buffAddr = g_buffer->Mmap(*buffer); + DISPLAY_CHK_RETURN((buffAddr == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("Mmap buffer failed")); + + rawDataFile.write(static_cast(buffAddr), buffer->size); + rawDataFile.close(); + + ret = g_buffer->Unmap(*buffer); + DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("Unmap buffer failed")); + 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 = dup(fence); + if (access("/data/hdi_dump_layer", F_OK) != -1) { + if (DumpLayerBuffer(const_cast(buffer)) != DISPLAY_SUCCESS) { + DISPLAY_LOGE("dump layer buffer failed"); + } + } + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerCompositionType(CompositionType type) +{ + DISPLAY_LOGD("CompositionType type %{public}d", type); + mCompositionType = type; + return DISPLAY_SUCCESS; +} + +int32_t HdiLayer::SetLayerBlendType(BlendType type) +{ + DISPLAY_LOGD("BlendType type %{public}d", type); + mBlendType = type; + return DISPLAY_SUCCESS; +} + +void HdiLayer::SetPixel(const BufferHandle &handle, int x, int y, uint32_t color) +{ + const int32_t pixelBytes = 4; + DISPLAY_CHK_RETURN_NOT_VALUE((handle.format <= 0), + DISPLAY_LOGE("CheckPixel do not support format %{public}d", handle.format)); + DISPLAY_CHK_RETURN_NOT_VALUE((handle.virAddr == nullptr), DISPLAY_LOGE("CheckPixel viraddr is null must map it")); + DISPLAY_CHK_RETURN_NOT_VALUE((x < 0 || x >= handle.width), + DISPLAY_LOGE("CheckPixel invalid parameter x:%{public}d width:%{public}d", x, handle.width)); + DISPLAY_CHK_RETURN_NOT_VALUE((y < 0 || y >= handle.height), + DISPLAY_LOGE("CheckPixel invalid parameter y:%{public}d height:%{public}d", y, handle.height)); + int32_t position = y * handle.width + x; + if ((position * pixelBytes) > handle.size) { + DISPLAY_LOGE("the pixel postion outside\n"); + } + uint32_t *pixel = reinterpret_cast(handle.virAddr) + position; + *pixel = color; +} + +void HdiLayer::ClearColor(uint32_t color) +{ + DISPLAY_LOGD(); + BufferHandle &handle = mHdiBuffer->mHandle; + for (int32_t x = 0; x < handle.width; x++) { + for (int32_t y = 0; y < handle.height; y++) { + SetPixel(handle, x, y, color); + } + } +} + +void HdiLayer::WaitAcquireFence() +{ + int fd = GetAcquireFenceFd(); + if (fd < 0) { + DISPLAY_LOGE("fd is invalid"); + return; + } + sync_wait(fd, mFenceTimeOut); +} +} // namespace OHOS +} // namespace HDI +} // namespace DISPLAY diff --git a/display/composer/vdi_base/src/hdi_netlink_monitor.cpp b/display/composer/vdi_base/src/hdi_netlink_monitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9b9c6150dc14c76ae8041766e0c8639e98013c7 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_netlink_monitor.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021-2023 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 +#include +#include +#include "hdi_session.h" + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiNetLinkMonitor::HdiNetLinkMonitor() +{ + DISPLAY_LOGD(); +} + +int HdiNetLinkMonitor::Init() +{ + DISPLAY_LOGD(); + mThread = std::make_unique(std::bind(&HdiNetLinkMonitor::MonitorThread, this)); + mThread->detach(); + mRunning = true; + return DISPLAY_SUCCESS; +} + +HdiNetLinkMonitor::~HdiNetLinkMonitor() +{ + DISPLAY_LOGD(); + if (mScoketFd >= 0) { + close(mScoketFd); + } +} + +static int ThreadInit() +{ + int ret; + int fd = -1; + const int32_t bufferSize = 1024; + struct sockaddr_nl snl; + + bzero(&snl, sizeof(struct sockaddr_nl)); + snl.nl_family = AF_NETLINK; + snl.nl_pid = getpid(); + snl.nl_groups = 1; + fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + DISPLAY_CHK_RETURN(fd < 0, DISPLAY_FAILURE, DISPLAY_LOGE("socket fail")); + ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); + if (ret == -1) { + DISPLAY_LOGE("setsockopt fail"); + close(fd); + return -1; + } + ret = bind(fd, reinterpret_cast(&snl), sizeof(struct sockaddr_nl)); + if (ret < 0) { + DISPLAY_LOGE("bind fail"); + close(fd); + return -1; + } + return fd; +} + +static void ParseUeventMessage(const char *buf, uint32_t len) +{ + uint32_t num; + + for (num = 0; num < len;) { + const char *event = buf + num; + if (strcmp(event, "STATE=HDMI=0") == 0) { + HdiSession::GetInstance().HandleHotplug(false); + break; + } else if (strcmp(event, "STATE=HDMI=1") == 0) { + HdiSession::GetInstance().HandleHotplug(true); + break; + } + num += strlen(event) + 1; + } +} + +void HdiNetLinkMonitor::MonitorThread() +{ + constexpr int BUFFER_SIZE = 2048; /* buffer for the variables */ + int len; + int fd = -1; + + fd = ThreadInit(); + DISPLAY_CHK_RETURN_NOT_VALUE(fd < 0, DISPLAY_LOGE("socket fail")); + mScoketFd = fd; + while (mRunning) { + char buf[BUFFER_SIZE] = { 0 }; + len = read(fd, &buf, sizeof(buf)); + if (len < 0) { + DISPLAY_LOGE("read uevent message fail"); + break; + } + ParseUeventMessage(buf, len); + } +} +} // DISPLAY +} // HDI +} // OHOS diff --git a/display/composer/vdi_base/src/hdi_session.cpp b/display/composer/vdi_base/src/hdi_session.cpp new file mode 100644 index 0000000000000000000000000000000000000000..836107ccfb5722da0debaa51dc1100d9e45a1df2 --- /dev/null +++ b/display/composer/vdi_base/src/hdi_session.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2021-2023 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 "common/include/display_common.h" +#include "display_log.h" +#include "v1_0/display_composer_type.h" +#include "hdf_trace.h" +#include "hdi_netlink_monitor.h" + +#define DISPLAY_TRACE HdfTrace trace(__func__, "HDI:DISP:") + +namespace OHOS { +namespace HDI { +namespace DISPLAY { +HdiSession &HdiSession::GetInstance() +{ + static HdiSession instance; + static std::once_flag once; + std::call_once(once, [&]() { instance.Init(); }); + return instance; +} + +void HdiSession::Init() +{ + DISPLAY_LOGD(); + mHdiDevices = HdiDeviceInterface::DiscoveryDevice(); + DISPLAY_LOGD("devices size %{public}zd", mHdiDevices.size()); + mHdiDisplays.clear(); + for (auto device : mHdiDevices) { + auto displays = device->DiscoveryDisplay(); + /* Register the connectors instead of display device. + * There are several connectors in one display device + * in rockchip platform. + */ + for (auto display : displays) { + mHdiDisplays[display.first] = display.second; + } + } + mNetLinkMonitor = std::make_shared(); + mNetLinkMonitor->Init(); +} + +void HdiSession::HandleHotplug(bool plugIn) +{ + for (auto device : mHdiDevices) { + for (auto displayMap : mHdiDisplays) { + auto display = displayMap.second; + auto isSuccess = device->HandleHotplug(display->GetId(), plugIn); + if (isSuccess == true) { + DoHotPlugCallback(display->GetId(), plugIn); + } + } + } +} + +int32_t HdiSession::RegHotPlugCallback(HotPlugCallback callback, void *data) +{ + DISPLAY_CHK_RETURN((callback == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the callback is nullptr")); + mHotPlugCallBacks.emplace(callback, data); + for (auto displayMap : mHdiDisplays) { + auto display = displayMap.second; + if (display->IsConnected()) { + DoHotPlugCallback(display->GetId(), true); + } + } + return DISPLAY_SUCCESS; +} + +void HdiSession::DoHotPlugCallback(uint32_t devId, bool connect) +{ + DISPLAY_LOGD(); + for (const auto &callback : mHotPlugCallBacks) { + callback.first(devId, connect, callback.second); + } +} +} // OHOS +} // HDI +} // DISPLAY + +using namespace OHOS::HDI::DISPLAY; +static int32_t RegHotPlugCallback(HotPlugCallback callback, void *data) +{ + DISPLAY_LOGD(); + HdiSession::GetInstance().RegHotPlugCallback(callback, data); + return DISPLAY_SUCCESS; +} + +static int32_t GetDisplayCapability(uint32_t devId, DisplayCapability *info) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN(info == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("info is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCapability, info); +} + +static int32_t GetDisplaySupportedModes(uint32_t devId, uint32_t *num, DisplayModeInfo *modes) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN(num == nullptr, DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplaySupportedModes, num, modes); +} + +static int32_t GetDisplayMode(uint32_t devId, uint32_t *mode) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((mode == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("mode is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayMode, mode); +} + +static int32_t SetDisplayMode(uint32_t devId, uint32_t mode) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayMode, mode); +} + +static int32_t GetDisplayPowerStatus(uint32_t devId, DispPowerStatus *status) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((status == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("status is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayPowerStatus, status); +} + +static int32_t SetDisplayPowerStatus(uint32_t devId, DispPowerStatus status) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayPowerStatus, status); +} + +static int32_t GetDisplayBacklight(uint32_t devId, uint32_t *value) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayBacklight, value); +} + +static int32_t SetDisplayBacklight(uint32_t devId, uint32_t value) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayBacklight, value); +} + +static int32_t GetDisplayProperty(uint32_t devId, uint32_t id, uint64_t *value) +{ + DISPLAY_LOGD(); + (void)id; + DISPLAY_CHK_RETURN((value == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("value is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayProperty(uint32_t devId, uint32_t id, uint64_t value) +{ + DISPLAY_LOGD(); + (void)id; + return DISPLAY_NOT_SUPPORT; +} + +static int32_t PrepareDisplayLayers(uint32_t devId, bool *needFlushFb) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((needFlushFb == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("needFlushFb is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::PrepareDisplayLayers, needFlushFb); +} + +static int32_t GetDisplayCompChange(uint32_t devId, uint32_t *num, uint32_t *layers, int32_t *type) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((num == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("num is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::GetDisplayCompChange, num, layers, type); +} + +static int32_t SetDisplayClientCrop(uint32_t devId, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == nullptr), 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 == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + return DISPLAY_NOT_SUPPORT; +} + +static int32_t SetDisplayClientBuffer(uint32_t devId, const BufferHandle *buffer, int32_t fence) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::SetDisplayClientBuffer, buffer, fence); +} + +static int32_t SetDisplayClientDamage(uint32_t devId, uint32_t num, IRect *rect) +{ + DISPLAY_LOGD(); + (void)num; + DISPLAY_CHK_RETURN((rect == nullptr), 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); +} + +static int32_t Commit(uint32_t devId, int32_t *fence) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((fence == nullptr), 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 == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("layerId is nullptr")); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::CreateLayer, layerInfo, layerId); +} + +static int32_t DestroyLayer(uint32_t devId, uint32_t layerId) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallDisplayFunction(devId, &HdiDisplay::DestroyLayer, layerId); +} + +static int32_t SetLayerRegion(uint32_t devId, uint32_t layerId, IRect *rect) +{ + DISPLAY_CHK_RETURN((rect == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("rect is nullptr")); + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerRegion, rect); +} + +static int32_t SetLayerCrop(uint32_t devId, uint32_t layerId, IRect *rect) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((rect == nullptr), 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 == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("alpha is nullptr")); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerAlpha, alpha); +} + +static int32_t SetLayerTransformMode(uint32_t devId, uint32_t layerId, TransformType type) +{ + DISPLAY_LOGD(); + return HdiSession::GetInstance().CallLayerFunction(devId, layerId, &HdiLayer::SetLayerTransformMode, type); +} + +static int32_t SetLayerDirtyRegion(uint32_t devId, uint32_t layerId, IRect *region) +{ + DISPLAY_LOGD(); + DISPLAY_CHK_RETURN((region == nullptr), 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 == nullptr), 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); +} +