diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:14:06 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:14:06 +0000 |
commit | c09538b27339abf329d27ac4a3aa1f53bfc1e8f5 (patch) | |
tree | 0be8b55408ec891b7c275a1eb9e4f0310702b339 | |
parent | efc30aa9b6cc682e839c2c97ae9985394d7aa9a4 (diff) | |
parent | 39e9dc65f3a608c85124d4014b07ede70680f18b (diff) | |
download | drm_hwcomposer-aml_net_340913000.tar.gz |
Snap for 10447354 from 39e9dc65f3a608c85124d4014b07ede70680f18b to mainline-networking-releaseaml_net_341710020aml_net_341610030aml_net_341510050aml_net_341510000aml_net_341411030aml_net_341311010aml_net_341310020aml_net_341014000aml_net_340913000android14-mainline-networking-release
Change-Id: I4a1f244d625457011700f7cc89fd4f2418223061
50 files changed, 982 insertions, 624 deletions
diff --git a/.ci/.gitlab-ci-checkcommit.sh b/.ci/.gitlab-ci-checkcommit.sh index c9c2e49..c6f7c4e 100755 --- a/.ci/.gitlab-ci-checkcommit.sh +++ b/.ci/.gitlab-ci-checkcommit.sh @@ -50,7 +50,7 @@ git log --pretty='%h' FETCH_HEAD..HEAD | while read h; do exit 1 fi - git show "$h" -- | clang-format-diff-13 -p 1 -style=file > /tmp/format-fixup.patch + git show "$h" -- | clang-format-diff-14 -p 1 -style=file > /tmp/format-fixup.patch if [ -s /tmp/format-fixup.patch ]; then cat /tmp/format-fixup.patch >&2 exit 1 diff --git a/.ci/Makefile b/.ci/Makefile index a0e4b73..581c6d9 100644 --- a/.ci/Makefile +++ b/.ci/Makefile @@ -2,8 +2,8 @@ INCLUDE_DIRS := . ../libdrm/include/drm include ./.ci/android_headers ./tests/test_include SYSTEM_INCLUDE_DIRS := /usr/include/libdrm -CLANG := clang++-13 -CLANG_TIDY := clang-tidy-13 +CLANG := clang++-14 +CLANG_TIDY := clang-tidy-14 OUT_DIR := /tmp/drm_hwcomposer/build SRC_DIR := . @@ -43,6 +43,7 @@ TIDY_CHECKS_FINE := * \ -cppcoreguidelines-pro-type-vararg \ -hicpp-vararg \ -hicpp-signed-bitwise \ + -readability-identifier-length \ TIDY_CHECKS_NORMAL := \ $(TIDY_CHECKS_FINE) \ diff --git a/.clang-tidy b/.clang-tidy index 3731a29..e1d92ed 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,3 @@ -# Turn all the warnings from the checks above into errors. -WarningsAsErrors: "*" - #HeaderFilterRegex: "^.*external/drm_hwcomposer/.*.h$" FormatStyle: google diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 89ac1b8..eb0c265 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,11 @@ -image: ubuntu:21.10 +image: ubuntu:22.04 variables: DEBIAN_FRONTEND: noninteractive before_script: - apt-get --quiet update --yes >/dev/null - - apt-get --quiet install --yes clang-13 clang-tidy-13 clang-format-13 git libdrm-dev blueprint-tools libgtest-dev make >/dev/null + - apt-get --quiet install --yes clang-14 clang-tidy-14 clang-format-14 git libdrm-dev blueprint-tools libgtest-dev make >/dev/null stages: - build @@ -37,10 +37,7 @@ cc_library_static { srcs: ["utils/Worker.cpp"], - include_dirs: [ - "external/drm_hwcomposer", - "external/drm_hwcomposer/include", - ], + include_dirs: ["external/drm_hwcomposer"], cflags: [ "-Wall", @@ -68,10 +65,7 @@ cc_defaults { "libutils", ], - include_dirs: [ - "external/drm_hwcomposer", - "external/drm_hwcomposer/include", - ], + include_dirs: ["external/drm_hwcomposer"], static_libs: ["libdrmhwc_utils"], @@ -118,8 +112,6 @@ filegroup { "drm/UEventListener.cpp", "drm/VSyncWorker.cpp", - "utils/hwcutils.cpp", - "backend/Backend.cpp", "backend/BackendClient.cpp", "backend/BackendManager.cpp", @@ -1,5 +1,5 @@ adelva@google.com dimitrysh@google.com -john.stultz@linaro.org +jstultz@google.com marcheu@google.com seanpaul@google.com @@ -16,7 +16,7 @@ A short list of contribution guidelines: you with formatting of your patches: ``` - git diff | clang-format-diff-13 -p 1 -style=file + git diff | clang-format-diff-14 -p 1 -style=file ``` * Hardware specific changes should be tested on relevant platforms before diff --git a/backend/Backend.cpp b/backend/Backend.cpp index f6d9c18..ba0518a 100644 --- a/backend/Backend.cpp +++ b/backend/Backend.cpp @@ -83,9 +83,9 @@ std::tuple<int, size_t> Backend::GetClientLayers( bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) { return !HardwareSupportsLayerType(layer->GetSfType()) || - !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->GetBuffer()) || + !layer->IsLayerUsableAsDevice() || display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || - (layer->RequireScalingOrPhasing() && + (layer->GetLayerData().pi.RequireScalingOrPhasing() && display->GetHwc2()->GetResMan().ForcedScalingWithGpu()); } @@ -99,7 +99,7 @@ uint32_t Backend::CalcPixOps(const std::vector<HwcLayer *> &layers, uint32_t pixops = 0; for (size_t z_order = 0; z_order < layers.size(); ++z_order) { if (z_order >= first_z && z_order < first_z + size) { - hwc_rect_t df = layers[z_order]->GetDisplayFrame(); + hwc_rect_t &df = layers[z_order]->GetLayerData().pi.display_frame; pixops += (df.right - df.left) * (df.bottom - df.top); } } diff --git a/bufferinfo/BufferInfo.h b/bufferinfo/BufferInfo.h new file mode 100644 index 0000000..b2297f9 --- /dev/null +++ b/bufferinfo/BufferInfo.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstdint> + +constexpr int kBufferMaxPlanes = 4; + +enum class BufferColorSpace : int32_t { + kUndefined, + kItuRec601, + kItuRec709, + kItuRec2020, +}; + +enum class BufferSampleRange : int32_t { + kUndefined, + kFullRange, + kLimitedRange, +}; + +enum class BufferBlendMode : int32_t { + kUndefined, + kNone, + kPreMult, + kCoverage, +}; + +struct BufferInfo { + uint32_t width; + uint32_t height; + uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ + uint32_t pitches[kBufferMaxPlanes]; + uint32_t offsets[kBufferMaxPlanes]; + /* sizes[] is used only by mapper@4 metadata getter for internal purposes */ + uint32_t sizes[kBufferMaxPlanes]; + int prime_fds[kBufferMaxPlanes]; + uint64_t modifiers[kBufferMaxPlanes]; + + BufferColorSpace color_space; + BufferSampleRange sample_range; + BufferBlendMode blend_mode; +}; diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp index 0cfd7e5..95c1a23 100644 --- a/bufferinfo/BufferInfoGetter.cpp +++ b/bufferinfo/BufferInfoGetter.cpp @@ -22,9 +22,14 @@ #include "BufferInfoMapperMetadata.h" #endif +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include <xf86drm.h> #include <xf86drmMode.h> +#include <mutex> + #include "utils/log.h" #include "utils/properties.h" @@ -48,17 +53,18 @@ BufferInfoGetter *BufferInfoGetter::GetInstance() { return inst.get(); } -bool BufferInfoGetter::IsHandleUsable(buffer_handle_t handle) { - hwc_drm_bo_t bo; - memset(&bo, 0, sizeof(hwc_drm_bo_t)); - - if (ConvertBoInfo(handle, &bo) != 0) { - return false; +std::optional<BufferUniqueId> BufferInfoGetter::GetUniqueId( + buffer_handle_t handle) { + struct stat sb {}; + if (fstat(handle->data[0], &sb) != 0) { + return {}; } - if (bo.prime_fds[0] == 0) { - return false; + + if (sb.st_size == 0) { + return {}; } - return true; + + return static_cast<BufferUniqueId>(sb.st_ino); } int LegacyBufferInfoGetter::Init() { diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h index 59184a4..5591296 100644 --- a/bufferinfo/BufferInfoGetter.h +++ b/bufferinfo/BufferInfoGetter.h @@ -20,8 +20,10 @@ #include <drm/drm_fourcc.h> #include <hardware/gralloc.h> +#include <optional> + +#include "BufferInfo.h" #include "drm/DrmDevice.h" -#include "drmhwcgralloc.h" #ifndef DRM_FORMAT_INVALID #define DRM_FORMAT_INVALID 0 @@ -29,13 +31,16 @@ namespace android { +using BufferUniqueId = uint64_t; + class BufferInfoGetter { public: virtual ~BufferInfoGetter() = default; - virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; + virtual auto GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> = 0; - bool IsHandleUsable(buffer_handle_t handle); + virtual std::optional<BufferUniqueId> GetUniqueId(buffer_handle_t handle); static BufferInfoGetter *GetInstance(); diff --git a/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp index 2f08a76..bdacb74 100644 --- a/bufferinfo/BufferInfoMapperMetadata.cpp +++ b/bufferinfo/BufferInfoMapperMetadata.cpp @@ -46,7 +46,7 @@ BufferInfoGetter *BufferInfoMapperMetadata::CreateInstance() { * so that it can be overridden. */ int __attribute__((weak)) -BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { +BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, BufferInfo *bo) { int fd_index = 0; if (handle->numFds <= 0) { @@ -54,7 +54,7 @@ BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { return android::BAD_VALUE; } - for (int i = 0; i < kHwcDrmBoMaxPlanes; i++) { + for (int i = 0; i < kBufferMaxPlanes; i++) { /* If no size, we're out of usable planes */ if (bo->sizes[i] <= 0) { if (i == 0) { @@ -86,71 +86,63 @@ BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { return 0; } -int BufferInfoMapperMetadata::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +auto BufferInfoMapperMetadata::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { GraphicBufferMapper &mapper = GraphicBufferMapper::getInstance(); if (handle == nullptr) - return -EINVAL; + return {}; - uint64_t usage = 0; - int err = mapper.getUsage(handle, &usage); - if (err != 0) { - ALOGE("Failed to get usage err=%d", err); - return err; - } - bo->usage = static_cast<uint32_t>(usage); - - ui::PixelFormat hal_format; - err = mapper.getPixelFormatRequested(handle, &hal_format); - if (err != 0) { - ALOGE("Failed to get HAL Pixel Format err=%d", err); - return err; - } - bo->hal_format = static_cast<uint32_t>(hal_format); + BufferInfo bi{}; - err = mapper.getPixelFormatFourCC(handle, &bo->format); + int err = mapper.getPixelFormatFourCC(handle, &bi.format); if (err != 0) { ALOGE("Failed to get FourCC format err=%d", err); - return err; + return {}; } - err = mapper.getPixelFormatModifier(handle, &bo->modifiers[0]); + err = mapper.getPixelFormatModifier(handle, &bi.modifiers[0]); if (err != 0) { ALOGE("Failed to get DRM Modifier err=%d", err); - return err; + return {}; } uint64_t width = 0; err = mapper.getWidth(handle, &width); if (err != 0) { ALOGE("Failed to get Width err=%d", err); - return err; + return {}; } - bo->width = static_cast<uint32_t>(width); + bi.width = static_cast<uint32_t>(width); uint64_t height = 0; err = mapper.getHeight(handle, &height); if (err != 0) { ALOGE("Failed to get Height err=%d", err); - return err; + return {}; } - bo->height = static_cast<uint32_t>(height); + bi.height = static_cast<uint32_t>(height); std::vector<ui::PlaneLayout> layouts; err = mapper.getPlaneLayouts(handle, &layouts); if (err != 0) { ALOGE("Failed to get Plane Layouts err=%d", err); - return err; + return {}; } for (uint32_t i = 0; i < layouts.size(); i++) { - bo->modifiers[i] = bo->modifiers[0]; - bo->pitches[i] = layouts[i].strideInBytes; - bo->offsets[i] = layouts[i].offsetInBytes; - bo->sizes[i] = layouts[i].totalSizeInBytes; + bi.modifiers[i] = bi.modifiers[0]; + bi.pitches[i] = layouts[i].strideInBytes; + bi.offsets[i] = layouts[i].offsetInBytes; + bi.sizes[i] = layouts[i].totalSizeInBytes; + } + + err = GetFds(handle, &bi); + if (err != 0) { + ALOGE("Failed to get fds (err=%d)", err); + return {}; } - return GetFds(handle, bo); + return bi; } } // namespace android diff --git a/bufferinfo/BufferInfoMapperMetadata.h b/bufferinfo/BufferInfoMapperMetadata.h index d335705..ab269dc 100644 --- a/bufferinfo/BufferInfoMapperMetadata.h +++ b/bufferinfo/BufferInfoMapperMetadata.h @@ -25,9 +25,9 @@ class BufferInfoMapperMetadata : public BufferInfoGetter { public: using BufferInfoGetter::BufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; - int GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo); + int GetFds(buffer_handle_t handle, BufferInfo *bo); static BufferInfoGetter *CreateInstance(); }; diff --git a/bufferinfo/legacy/BufferInfoImagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp index 691dd14..6d917c2 100644 --- a/bufferinfo/legacy/BufferInfoImagination.cpp +++ b/bufferinfo/legacy/BufferInfoImagination.cpp @@ -29,40 +29,40 @@ namespace android { LEGACY_BUFFER_INFO_GETTER(BufferInfoImagination); -int BufferInfoImagination::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +auto BufferInfoImagination::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { auto *hnd = (IMG_native_handle_t *)handle; if (!hnd) - return -EINVAL; + return {}; /* Extra bits are responsible for buffer compression and memory layout */ if (hnd->iFormat & ~0x10f) { ALOGV("Special buffer formats are not supported"); - return -EINVAL; + return {}; } - bo->width = hnd->iWidth; - bo->height = hnd->iHeight; - bo->usage = hnd->usage; - bo->prime_fds[0] = hnd->fd[0]; - bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3; - bo->hal_format = hnd->iFormat; + BufferInfo bi{}; + + bi.width = hnd->iWidth; + bi.height = hnd->iHeight; + bi.prime_fds[0] = hnd->fd[0]; + bi.pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3; switch (hnd->iFormat) { #ifdef HAL_PIXEL_FORMAT_BGRX_8888 case HAL_PIXEL_FORMAT_BGRX_8888: - bo->format = DRM_FORMAT_XRGB8888; + bi.format = DRM_FORMAT_XRGB8888; break; #endif default: - bo->format = ConvertHalFormatToDrm(hnd->iFormat & 0xf); - if (bo->format == DRM_FORMAT_INVALID) { + bi.format = ConvertHalFormatToDrm(hnd->iFormat & 0xf); + if (bi.format == DRM_FORMAT_INVALID) { ALOGV("Cannot convert hal format to drm format %u", hnd->iFormat); - return -EINVAL; + return {}; } } - return 0; + return bi; } } // namespace android diff --git a/bufferinfo/legacy/BufferInfoImagination.h b/bufferinfo/legacy/BufferInfoImagination.h index 765b279..635e3b5 100644 --- a/bufferinfo/legacy/BufferInfoImagination.h +++ b/bufferinfo/legacy/BufferInfoImagination.h @@ -27,7 +27,7 @@ class BufferInfoImagination : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; }; } // namespace android diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp index 6baf6bb..ac71ec0 100644 --- a/bufferinfo/legacy/BufferInfoLibdrm.cpp +++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp @@ -91,8 +91,8 @@ static bool is_yuv(uint32_t native) { return false; } -bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, - hwc_drm_bo_t *bo) { +bool BufferInfoLibdrm::GetYuvPlaneInfo(uint32_t hal_format, int num_fds, + buffer_handle_t handle, BufferInfo *bo) { struct android_ycbcr ycbcr {}; enum chroma_order chroma_order {}; int ret = 0; @@ -136,12 +136,12 @@ bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, /* .chroma_step is the byte distance between the same chroma channel * values of subsequent pixels, assumed to be the same for Cb and Cr. */ - bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step); + bo->format = get_fourcc_yuv(hal_format, chroma_order, ycbcr.chroma_step); if (bo->format == UINT32_MAX) { ALOGW( "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = " "%d", - bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb", + hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb", (int)ycbcr.chroma_step); return false; } @@ -162,14 +162,16 @@ bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, return true; } -int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { +auto BufferInfoLibdrm::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { gralloc_handle_t *gr_handle = gralloc_handle(handle); if (!gr_handle) - return -EINVAL; + return {}; + + BufferInfo bi{}; - bo->width = gr_handle->width; - bo->height = gr_handle->height; - bo->hal_format = gr_handle->format; + bi.width = gr_handle->width; + bi.height = gr_handle->height; #if GRALLOC_HANDLE_VERSION < 4 static std::once_flag once; @@ -179,35 +181,34 @@ int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { }); #endif #if GRALLOC_HANDLE_VERSION == 4 - bo->modifiers[0] = gr_handle->modifier; + bi.modifiers[0] = gr_handle->modifier; #endif - bo->usage = gr_handle->usage; - bo->prime_fds[0] = gr_handle->prime_fd; + bi.prime_fds[0] = gr_handle->prime_fd; if (is_yuv(gr_handle->format)) { - if (!GetYuvPlaneInfo(handle->numFds, handle, bo)) - return -EINVAL; + if (!GetYuvPlaneInfo(gr_handle->format, handle->numFds, handle, &bi)) + return {}; } else { - bo->pitches[0] = gr_handle->stride; - bo->offsets[0] = 0; + bi.pitches[0] = gr_handle->stride; + bi.offsets[0] = 0; /* FOSS graphic components (gbm_gralloc, mesa3d) are translating * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping * the R and B components. Same must be done here. */ - switch (bo->hal_format) { + switch (gr_handle->format) { case HAL_PIXEL_FORMAT_RGB_565: - bo->format = DRM_FORMAT_RGB565; + bi.format = DRM_FORMAT_RGB565; break; default: - bo->format = ConvertHalFormatToDrm(gr_handle->format); + bi.format = ConvertHalFormatToDrm(gr_handle->format); } - if (bo->format == DRM_FORMAT_INVALID) - return -EINVAL; + if (bi.format == DRM_FORMAT_INVALID) + return {}; } - return 0; + return bi; } constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator"; diff --git a/bufferinfo/legacy/BufferInfoLibdrm.h b/bufferinfo/legacy/BufferInfoLibdrm.h index cad8add..7f5b08c 100644 --- a/bufferinfo/legacy/BufferInfoLibdrm.h +++ b/bufferinfo/legacy/BufferInfoLibdrm.h @@ -26,11 +26,12 @@ namespace android { class BufferInfoLibdrm : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; int ValidateGralloc() override; private: - bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo); + bool GetYuvPlaneInfo(uint32_t hal_format, int num_fds, buffer_handle_t handle, + BufferInfo *bo); }; } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.cpp b/bufferinfo/legacy/BufferInfoMaliHisi.cpp index 5fc413a..1c7f4d0 100644 --- a/bufferinfo/legacy/BufferInfoMaliHisi.cpp +++ b/bufferinfo/legacy/BufferInfoMaliHisi.cpp @@ -66,33 +66,33 @@ uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers( } #endif -int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +auto BufferInfoMaliHisi::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { bool is_rgb = false; const auto *hnd = (private_handle_t const *)handle; if (!hnd) - return -EINVAL; + return {}; if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) - return -EINVAL; + return {}; uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); if (fmt == DRM_FORMAT_INVALID) - return -EINVAL; + return {}; + + BufferInfo bi{}; is_rgb = IsDrmFormatRgb(fmt); - bo->modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format, - is_rgb); - - bo->width = hnd->width; - bo->height = hnd->height; - bo->hal_format = hnd->req_format; - bo->format = fmt; - bo->usage = hnd->usage; - bo->pitches[0] = hnd->byte_stride; - bo->prime_fds[0] = hnd->share_fd; - bo->offsets[0] = 0; + bi.modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format, + is_rgb); + + bi.width = hnd->width; + bi.height = hnd->height; + bi.format = fmt; + bi.pitches[0] = hnd->byte_stride; + bi.prime_fds[0] = hnd->share_fd; + bi.offsets[0] = 0; switch (fmt) { case DRM_FORMAT_YVU420: { @@ -106,20 +106,20 @@ int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle, int v_size = vu_stride * (adjusted_height / 2); /* V plane*/ - bo->prime_fds[1] = hnd->share_fd; - bo->pitches[1] = vu_stride; - bo->offsets[1] = y_size; + bi.prime_fds[1] = hnd->share_fd; + bi.pitches[1] = vu_stride; + bi.offsets[1] = y_size; /* U plane */ - bo->prime_fds[2] = hnd->share_fd; - bo->pitches[2] = vu_stride; - bo->offsets[2] = y_size + v_size; + bi.prime_fds[2] = hnd->share_fd; + bi.pitches[2] = vu_stride; + bi.offsets[2] = y_size + v_size; break; } default: break; } - return 0; + return bi; } } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.h b/bufferinfo/legacy/BufferInfoMaliHisi.h index 698a0d3..cc37491 100644 --- a/bufferinfo/legacy/BufferInfoMaliHisi.h +++ b/bufferinfo/legacy/BufferInfoMaliHisi.h @@ -27,7 +27,7 @@ class BufferInfoMaliHisi : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; private: uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb); diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp index 7e6f3a8..2e10460 100644 --- a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp +++ b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp @@ -32,26 +32,26 @@ namespace android { LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMediatek); -int BufferInfoMaliMediatek::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +auto BufferInfoMaliMediatek::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { const auto *hnd = (private_handle_t const *)handle; if (!hnd) - return -EINVAL; + return {}; uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); if (fmt == DRM_FORMAT_INVALID) - return -EINVAL; - - bo->width = hnd->width; - bo->height = hnd->height; - bo->hal_format = hnd->req_format; - bo->format = fmt; - bo->usage = hnd->consumer_usage | hnd->producer_usage; - bo->prime_fds[0] = hnd->share_fd; - bo->pitches[0] = hnd->byte_stride; - bo->offsets[0] = 0; - - return 0; + return {}; + + BufferInfo bi{}; + + bi.width = hnd->width; + bi.height = hnd->height; + bi.format = fmt; + bi.prime_fds[0] = hnd->share_fd; + bi.pitches[0] = hnd->byte_stride; + bi.offsets[0] = 0; + + return bi; } } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.h b/bufferinfo/legacy/BufferInfoMaliMediatek.h index 1204818..43d987a 100644 --- a/bufferinfo/legacy/BufferInfoMaliMediatek.h +++ b/bufferinfo/legacy/BufferInfoMaliMediatek.h @@ -27,7 +27,7 @@ class BufferInfoMaliMediatek : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; }; } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliMeson.cpp b/bufferinfo/legacy/BufferInfoMaliMeson.cpp index 9daf542..8160296 100644 --- a/bufferinfo/legacy/BufferInfoMaliMeson.cpp +++ b/bufferinfo/legacy/BufferInfoMaliMeson.cpp @@ -61,32 +61,32 @@ uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( } #endif -int BufferInfoMaliMeson::ConvertBoInfo(buffer_handle_t handle, - hwc_drm_bo_t *bo) { +auto BufferInfoMaliMeson::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { const auto *hnd = (private_handle_t const *)handle; if (!hnd) - return -EINVAL; + return {}; if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) - return -EINVAL; + return {}; uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); if (fmt == DRM_FORMAT_INVALID) - return -EINVAL; + return {}; - bo->modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( + BufferInfo bi{}; + + bi.modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( hnd->internal_format); - bo->width = hnd->width; - bo->height = hnd->height; - bo->hal_format = hnd->req_format; - bo->format = fmt; - bo->usage = hnd->usage; - bo->prime_fds[0] = hnd->share_fd; - bo->pitches[0] = hnd->byte_stride; - bo->offsets[0] = 0; + bi.width = hnd->width; + bi.height = hnd->height; + bi.format = fmt; + bi.prime_fds[0] = hnd->share_fd; + bi.pitches[0] = hnd->byte_stride; + bi.offsets[0] = 0; - return 0; + return bi; } } // namespace android diff --git a/bufferinfo/legacy/BufferInfoMaliMeson.h b/bufferinfo/legacy/BufferInfoMaliMeson.h index ce5d3f9..3b6fab0 100644 --- a/bufferinfo/legacy/BufferInfoMaliMeson.h +++ b/bufferinfo/legacy/BufferInfoMaliMeson.h @@ -26,7 +26,7 @@ namespace android { class BufferInfoMaliMeson : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; private: uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags); diff --git a/bufferinfo/legacy/BufferInfoMinigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp index 777c2b7..c5a9e98 100644 --- a/bufferinfo/legacy/BufferInfoMinigbm.cpp +++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp @@ -43,11 +43,14 @@ struct cros_gralloc0_buffer_info { int stride[4]; }; -int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { +auto BufferInfoMinigbm::GetBoInfo(buffer_handle_t handle) + -> std::optional<BufferInfo> { if (handle == nullptr) { - return -EINVAL; + return {}; } + BufferInfo bi{}; + uint32_t width{}; uint32_t height{}; if (gralloc_->perform(gralloc_, CROS_GRALLOC_DRM_GET_DIMENSIONS, handle, @@ -55,7 +58,7 @@ int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ALOGE( "CROS_GRALLOC_DRM_GET_DIMENSIONS operation has failed. " "Please ensure you are using the latest minigbm."); - return -EINVAL; + return {}; } int32_t droid_format{}; @@ -64,7 +67,7 @@ int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ALOGE( "CROS_GRALLOC_DRM_GET_FORMAT operation has failed. " "Please ensure you are using the latest minigbm."); - return -EINVAL; + return {}; } uint32_t usage{}; @@ -73,7 +76,7 @@ int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ALOGE( "CROS_GRALLOC_DRM_GET_USAGE operation has failed. " "Please ensure you are using the latest minigbm."); - return -EINVAL; + return {}; } struct cros_gralloc0_buffer_info info {}; @@ -82,25 +85,22 @@ int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ALOGE( "CROS_GRALLOC_DRM_GET_BUFFER_INFO operation has failed. " "Please ensure you are using the latest minigbm."); - return -EINVAL; + return {}; } - bo->width = width; - bo->height = height; + bi.width = width; + bi.height = height; - bo->hal_format = droid_format; - - bo->format = info.drm_fourcc; - bo->usage = usage; + bi.format = info.drm_fourcc; for (int i = 0; i < info.num_fds; i++) { - bo->modifiers[i] = info.modifier; - bo->prime_fds[i] = info.fds[i]; - bo->pitches[i] = info.stride[i]; - bo->offsets[i] = info.offset[i]; + bi.modifiers[i] = info.modifier; + bi.prime_fds[i] = info.fds[i]; + bi.pitches[i] = info.stride[i]; + bi.offsets[i] = info.offset[i]; } - return 0; + return bi; } constexpr char cros_gralloc_module_name[] = "CrOS Gralloc"; diff --git a/bufferinfo/legacy/BufferInfoMinigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h index 04cc2ae..40d9926 100644 --- a/bufferinfo/legacy/BufferInfoMinigbm.h +++ b/bufferinfo/legacy/BufferInfoMinigbm.h @@ -26,7 +26,7 @@ namespace android { class BufferInfoMinigbm : public LegacyBufferInfoGetter { public: using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + auto GetBoInfo(buffer_handle_t handle) -> std::optional<BufferInfo> override; int ValidateGralloc() override; }; diff --git a/compositor/DrmKmsPlan.cpp b/compositor/DrmKmsPlan.cpp index 966bd4e..6289b84 100644 --- a/compositor/DrmKmsPlan.cpp +++ b/compositor/DrmKmsPlan.cpp @@ -24,7 +24,7 @@ namespace android { auto DrmKmsPlan::CreateDrmKmsPlan(DrmDisplayPipeline &pipe, - std::vector<DrmHwcLayer> composition) + std::vector<LayerData> composition) -> std::unique_ptr<DrmKmsPlan> { auto plan = std::make_unique<DrmKmsPlan>(); diff --git a/compositor/DrmKmsPlan.h b/compositor/DrmKmsPlan.h index 35e66e9..91f636e 100644 --- a/compositor/DrmKmsPlan.h +++ b/compositor/DrmKmsPlan.h @@ -20,7 +20,7 @@ #include <memory> #include <vector> -#include "drmhwcomposer.h" +#include "LayerData.h" namespace android { @@ -28,7 +28,7 @@ class DrmDevice; struct DrmKmsPlan { struct LayerToPlaneJoining { - DrmHwcLayer layer; + LayerData layer; std::shared_ptr<BindingOwner<DrmPlane>> plane; int z_pos; }; @@ -36,7 +36,7 @@ struct DrmKmsPlan { std::vector<LayerToPlaneJoining> plan; static auto CreateDrmKmsPlan(DrmDisplayPipeline &pipe, - std::vector<DrmHwcLayer> composition) + std::vector<LayerData> composition) -> std::unique_ptr<DrmKmsPlan>; }; diff --git a/compositor/LayerData.h b/compositor/LayerData.h new file mode 100644 index 0000000..d04514d --- /dev/null +++ b/compositor/LayerData.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <hardware/hardware.h> +#include <hardware/hwcomposer.h> + +#include <cmath> +#include <cstdbool> +#include <cstdint> +#include <optional> +#include <vector> + +#include "bufferinfo/BufferInfo.h" +#include "drm/DrmFbImporter.h" +#include "utils/UniqueFd.h" + +namespace android { + +class DrmFbIdHandle; + +enum LayerTransform : uint32_t { + kIdentity = 0, + kFlipH = 1 << 0, + kFlipV = 1 << 1, + kRotate90 = 1 << 2, + kRotate180 = 1 << 3, + kRotate270 = 1 << 4, +}; + +struct PresentInfo { + LayerTransform transform{}; + uint16_t alpha = UINT16_MAX; + hwc_frect_t source_crop{}; + hwc_rect_t display_frame{}; + + bool RequireScalingOrPhasing() const { + float src_width = source_crop.right - source_crop.left; + float src_height = source_crop.bottom - source_crop.top; + + auto dest_width = float(display_frame.right - display_frame.left); + auto dest_height = float(display_frame.bottom - display_frame.top); + + bool scaling = src_width != dest_width || src_height != dest_height; + bool phasing = (source_crop.left - std::floor(source_crop.left) != 0) || + (source_crop.top - std::floor(source_crop.top) != 0); + return scaling || phasing; + } +}; + +struct LayerData { + auto Clone() { + LayerData clonned; + clonned.bi = bi; + clonned.fb = fb; + clonned.pi = pi; + clonned.acquire_fence = std::move(acquire_fence); + return clonned; + } + + std::optional<BufferInfo> bi; + std::shared_ptr<DrmFbIdHandle> fb; + PresentInfo pi; + UniqueFd acquire_fence; +}; + +} // namespace android diff --git a/drm/DrmAtomicStateManager.cpp b/drm/DrmAtomicStateManager.cpp index 65fb19e..5d2eebd 100644 --- a/drm/DrmAtomicStateManager.cpp +++ b/drm/DrmAtomicStateManager.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#undef NDEBUG /* Required for assert to work */ + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #define LOG_TAG "hwc-drm-atomic-state-manager" @@ -26,6 +28,7 @@ #include <utils/Trace.h> #include <array> +#include <cassert> #include <cstdlib> #include <ctime> #include <sstream> @@ -70,13 +73,15 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int { return -ENOMEM; } - int64_t out_fence = -1; - if (crtc->GetOutFencePtrProperty() && - !crtc->GetOutFencePtrProperty().AtomicSet(*pset, uint64_t(&out_fence))) { + int out_fence = -1; + if (!crtc->GetOutFencePtrProperty().AtomicSet(*pset, uint64_t(&out_fence))) { return -EINVAL; } + bool nonblock = true; + if (args.active) { + nonblock = false; new_frame_state.crtc_active_state = *args.active; if (!crtc->GetActiveProperty().AtomicSet(*pset, *args.active ? 1 : 0) || !connector->GetCrtcIdProperty().AtomicSet(*pset, crtc->GetId())) { @@ -100,14 +105,13 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int { auto unused_planes = new_frame_state.used_planes; if (args.composition) { - new_frame_state.used_framebuffers.clear(); new_frame_state.used_planes.clear(); for (auto &joining : args.composition->plan) { DrmPlane *plane = joining.plane->Get(); - DrmHwcLayer &layer = joining.layer; + LayerData &layer = joining.layer; - new_frame_state.used_framebuffers.emplace_back(layer.fb_id_handle); + new_frame_state.used_framebuffers.emplace_back(layer.fb); new_frame_state.used_planes.emplace_back(joining.plane); /* Remove from 'unused' list, since plane is re-used */ @@ -130,31 +134,126 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int { } uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; - if (args.test_only) - flags |= DRM_MODE_ATOMIC_TEST_ONLY; + + if (args.test_only) { + return drmModeAtomicCommit(drm->GetFd(), pset.get(), + flags | DRM_MODE_ATOMIC_TEST_ONLY, drm); + } + + if (last_present_fence_) { + ATRACE_NAME("WaitPriorFramePresented"); + + constexpr int kTimeoutMs = 500; + int err = sync_wait(last_present_fence_.Get(), kTimeoutMs); + if (err != 0) { + ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)", + last_present_fence_.Get(), err, errno); + } + + CleanupPriorFrameResources(); + } + + if (nonblock) { + flags |= DRM_MODE_ATOMIC_NONBLOCK; + } int err = drmModeAtomicCommit(drm->GetFd(), pset.get(), flags, drm); + if (err != 0) { - if (!args.test_only) - ALOGE("Failed to commit pset ret=%d\n", err); + ALOGE("Failed to commit pset ret=%d\n", err); return err; } - if (!args.test_only) { - if (args.display_mode) { - /* TODO(nobody): we still need this for synthetic vsync, remove after - * vsync reworked */ - connector->SetActiveMode(*args.display_mode); + if (nonblock) { + last_present_fence_ = UniqueFd::Dup(out_fence); + staged_frame_state_ = std::move(new_frame_state); + frames_staged_++; + ptt_->Notify(); + } else { + active_frame_state_ = std::move(new_frame_state); + } + + if (args.display_mode) { + /* TODO(nobody): we still need this for synthetic vsync, remove after + * vsync reworked */ + connector->SetActiveMode(*args.display_mode); + } + + args.out_fence = UniqueFd(out_fence); + + return 0; +} + +PresentTrackerThread::PresentTrackerThread(DrmAtomicStateManager *st_man) + : st_man_(st_man), + mutex_(&st_man_->pipe_->device->GetResMan().GetMainLock()) { + pt_ = std::thread(&PresentTrackerThread::PresentTrackerThreadFn, this); +} + +PresentTrackerThread::~PresentTrackerThread() { + ALOGI("PresentTrackerThread successfully destroyed"); +} + +void PresentTrackerThread::PresentTrackerThreadFn() { + /* object should be destroyed on thread exit */ + auto self = std::unique_ptr<PresentTrackerThread>(this); + + int tracking_at_the_moment = -1; + + for (;;) { + UniqueFd present_fence; + + { + std::unique_lock lk(*mutex_); + cv_.wait(lk, [&] { + return st_man_ == nullptr || + st_man_->frames_staged_ > tracking_at_the_moment; + }); + + if (st_man_ == nullptr) { + break; + } + + tracking_at_the_moment = st_man_->frames_staged_; + + present_fence = UniqueFd::Dup(st_man_->last_present_fence_.Get()); + if (!present_fence) { + continue; + } } - active_frame_state_ = std::move(new_frame_state); + { + ATRACE_NAME("AsyncWaitForBuffersSwap"); + constexpr int kTimeoutMs = 500; + int err = sync_wait(present_fence.Get(), kTimeoutMs); + if (err != 0) { + ALOGE("sync_wait(fd=%i) returned: %i (errno: %i)", present_fence.Get(), + err, errno); + } + } - if (crtc->GetOutFencePtrProperty()) { - args.out_fence = UniqueFd((int)out_fence); + { + std::unique_lock lk(*mutex_); + if (st_man_ == nullptr) { + break; + } + + /* If resources is already cleaned-up by main thread, skip */ + if (tracking_at_the_moment > st_man_->frames_tracked_) { + st_man_->CleanupPriorFrameResources(); + } } } +} - return 0; +void DrmAtomicStateManager::CleanupPriorFrameResources() { + assert(frames_staged_ - frames_tracked_ == 1); + assert(last_present_fence_); + + ATRACE_NAME("CleanupPriorFrameResources"); + frames_tracked_++; + active_frame_state_ = std::move(staged_frame_state_); + last_present_fence_ = {}; } auto DrmAtomicStateManager::ExecuteAtomicCommit(AtomicCommitArgs &args) -> int { diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h index 08a1c13..b0b85ac 100644 --- a/drm/DrmAtomicStateManager.h +++ b/drm/DrmAtomicStateManager.h @@ -26,10 +26,10 @@ #include <tuple> #include "compositor/DrmKmsPlan.h" +#include "compositor/LayerData.h" #include "drm/DrmPlane.h" #include "drm/ResourceManager.h" #include "drm/VSyncWorker.h" -#include "drmhwcomposer.h" namespace android { @@ -49,11 +49,45 @@ struct AtomicCommitArgs { } }; +class PresentTrackerThread { + public: + explicit PresentTrackerThread(DrmAtomicStateManager *st_man); + + ~PresentTrackerThread(); + + void Stop() { + /* Exit thread by signalling that object is no longer valid */ + st_man_ = nullptr; + Notify(); + pt_.detach(); + } + + void Notify() { + cv_.notify_all(); + } + + private: + DrmAtomicStateManager *st_man_{}; + + void PresentTrackerThreadFn(); + + std::condition_variable cv_; + std::thread pt_; + std::mutex *mutex_; +}; + class DrmAtomicStateManager { + friend class PresentTrackerThread; + public: - explicit DrmAtomicStateManager(DrmDisplayPipeline *pipe) : pipe_(pipe){}; + explicit DrmAtomicStateManager(DrmDisplayPipeline *pipe) + : pipe_(pipe), + ptt_(std::make_unique<PresentTrackerThread>(this).release()){}; + DrmAtomicStateManager(const DrmAtomicStateManager &) = delete; - ~DrmAtomicStateManager() = default; + ~DrmAtomicStateManager() { + ptt_->Stop(); + } auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int; auto ActivateDisplayUsingDPMS() -> int; @@ -70,20 +104,32 @@ class DrmAtomicStateManager { DrmModeUserPropertyBlobUnique mode_blob; + int release_fence_pt_index{}; + /* To avoid setting the inactive state twice, which will fail the commit */ bool crtc_active_state{}; } active_frame_state_; auto NewFrameState() -> KmsState { + auto *prev_frame_state = &active_frame_state_; return (KmsState){ - .used_planes = active_frame_state_.used_planes, - .used_framebuffers = active_frame_state_.used_framebuffers, - .crtc_active_state = active_frame_state_.crtc_active_state, + .used_planes = prev_frame_state->used_planes, + .crtc_active_state = prev_frame_state->crtc_active_state, }; } DrmDisplayPipeline *const pipe_; + + void CleanupPriorFrameResources(); + + /* Present (swap) tracking */ + PresentTrackerThread *ptt_; + KmsState staged_frame_state_; + UniqueFd last_present_fence_; + int frames_staged_{}; + int frames_tracked_{}; }; + } // namespace android #endif // ANDROID_DRM_DISPLAY_COMPOSITOR_H_ diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp index fd4589e..0f73f1f 100644 --- a/drm/DrmDevice.cpp +++ b/drm/DrmDevice.cpp @@ -18,7 +18,6 @@ #include "DrmDevice.h" -#include <fcntl.h> #include <xf86drm.h> #include <xf86drmMode.h> @@ -28,12 +27,29 @@ #include "drm/DrmAtomicStateManager.h" #include "drm/DrmPlane.h" +#include "drm/ResourceManager.h" #include "utils/log.h" #include "utils/properties.h" namespace android { -DrmDevice::DrmDevice() { +auto DrmDevice::CreateInstance(std::string const &path, + ResourceManager *res_man) + -> std::unique_ptr<DrmDevice> { + if (!IsKMSDev(path.c_str())) { + return {}; + } + + auto device = std::unique_ptr<DrmDevice>(new DrmDevice(res_man)); + + if (device->Init(path.c_str()) != 0) { + return {}; + } + + return device; +} + +DrmDevice::DrmDevice(ResourceManager *res_man) : res_man_(res_man) { drm_fb_importer_ = std::make_unique<DrmFbImporter>(*this); } diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h index f2530ee..4cf0132 100644 --- a/drm/DrmDevice.h +++ b/drm/DrmDevice.h @@ -31,18 +31,23 @@ namespace android { class DrmFbImporter; class DrmPlane; +class ResourceManager; class DrmDevice { public: - DrmDevice(); ~DrmDevice() = default; - auto Init(const char *path) -> int; + static auto CreateInstance(std::string const &path, ResourceManager *res_man) + -> std::unique_ptr<DrmDevice>; auto GetFd() const { return fd_.Get(); } + auto &GetResMan() { + return *res_man_; + } + auto GetConnectors() -> const std::vector<std::unique_ptr<DrmConnector>> &; auto GetPlanes() -> const std::vector<std::unique_ptr<DrmPlane>> &; auto GetCrtcs() -> const std::vector<std::unique_ptr<DrmCrtc>> &; @@ -69,8 +74,6 @@ class DrmDevice { return *drm_fb_importer_; } - static auto IsKMSDev(const char *path) -> bool; - auto FindCrtcById(uint32_t id) const -> DrmCrtc * { for (const auto &crtc : crtcs_) { if (crtc->GetId() == id) { @@ -95,6 +98,11 @@ class DrmDevice { DrmProperty *property) const; private: + explicit DrmDevice(ResourceManager *res_man); + auto Init(const char *path) -> int; + + static auto IsKMSDev(const char *path) -> bool; + UniqueFd fd_; std::vector<std::unique_ptr<DrmConnector>> connectors_; @@ -109,6 +117,8 @@ class DrmDevice { bool HasAddFb2ModifiersSupport_{}; std::unique_ptr<DrmFbImporter> drm_fb_importer_; + + ResourceManager *const res_man_; }; } // namespace android diff --git a/drm/DrmDisplayPipeline.cpp b/drm/DrmDisplayPipeline.cpp index f993d28..e81544d 100644 --- a/drm/DrmDisplayPipeline.cpp +++ b/drm/DrmDisplayPipeline.cpp @@ -86,15 +86,15 @@ static auto TryCreatePipeline(DrmDevice &dev, DrmConnector &connector, return {}; } - if (primary_planes.size() > 1) { - ALOGE("Found more than 1 primary plane for CRTC %d", crtc.GetId()); - return {}; + for (const auto &plane : primary_planes) { + pipe->primary_plane = plane->BindPipeline(pipe.get()); + if (pipe->primary_plane) { + break; + } } - pipe->primary_plane = primary_planes[0]->BindPipeline(pipe.get()); if (!pipe->primary_plane) { - ALOGE("Primary plane %d is already owned. Internal error.", - primary_planes[0]->GetId()); + ALOGE("Failed to bind primary plane"); return {}; } diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp index eeab076..585b789 100644 --- a/drm/DrmFbImporter.cpp +++ b/drm/DrmFbImporter.cpp @@ -15,11 +15,14 @@ */ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define LOG_TAG "hwc-platform-drm-generic" #include "DrmFbImporter.h" #include <hardware/gralloc.h> +#include <utils/Trace.h> #include <xf86drm.h> #include <xf86drmMode.h> @@ -31,9 +34,11 @@ namespace android { -auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, +auto DrmFbIdHandle::CreateInstance(BufferInfo *bo, GemHandle first_gem_handle, DrmDevice &drm) -> std::shared_ptr<DrmFbIdHandle> { + ATRACE_NAME("Import dmabufs and register FB"); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage std::shared_ptr<DrmFbIdHandle> local(new DrmFbIdHandle(drm)); @@ -69,11 +74,11 @@ auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, /* Create framebuffer object */ if (!has_modifiers) { err = drmModeAddFB2(drm.GetFd(), bo->width, bo->height, bo->format, - &local->gem_handles_[0], &bo->pitches[0], + local->gem_handles_.data(), &bo->pitches[0], &bo->offsets[0], &local->fb_id_, 0); } else { err = drmModeAddFB2WithModifiers(drm.GetFd(), bo->width, bo->height, - bo->format, &local->gem_handles_[0], + bo->format, local->gem_handles_.data(), &bo->pitches[0], &bo->offsets[0], &bo->modifiers[0], &local->fb_id_, DRM_MODE_FB_MODIFIERS); @@ -87,6 +92,8 @@ auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, } DrmFbIdHandle::~DrmFbIdHandle() { + ATRACE_NAME("Close FB and dmabufs"); + /* Destroy framebuffer object */ if (drmModeRmFB(drm_->GetFd(), fb_id_) != 0) { ALOGE("Failed to rm fb"); @@ -116,7 +123,7 @@ DrmFbIdHandle::~DrmFbIdHandle() { } } -auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo) +auto DrmFbImporter::GetOrCreateFbId(BufferInfo *bo) -> std::shared_ptr<DrmFbIdHandle> { /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */ GemHandle first_handle = 0; diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h index 7f17bbe..9e94238 100644 --- a/drm/DrmFbImporter.h +++ b/drm/DrmFbImporter.h @@ -23,8 +23,8 @@ #include <array> #include <map> +#include "bufferinfo/BufferInfo.h" #include "drm/DrmDevice.h" -#include "drmhwcgralloc.h" #ifndef DRM_FORMAT_INVALID #define DRM_FORMAT_INVALID 0 @@ -36,7 +36,7 @@ namespace android { class DrmFbIdHandle { public: - static auto CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, + static auto CreateInstance(BufferInfo *bo, GemHandle first_gem_handle, DrmDevice &drm) -> std::shared_ptr<DrmFbIdHandle>; ~DrmFbIdHandle(); @@ -55,7 +55,7 @@ class DrmFbIdHandle { DrmDevice *const drm_; uint32_t fb_id_{}; - std::array<GemHandle, kHwcDrmBoMaxPlanes> gem_handles_{}; + std::array<GemHandle, kBufferMaxPlanes> gem_handles_{}; }; class DrmFbImporter { @@ -67,7 +67,7 @@ class DrmFbImporter { auto operator=(const DrmFbImporter &) = delete; auto operator=(DrmFbImporter &&) = delete; - auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr<DrmFbIdHandle>; + auto GetOrCreateFbId(BufferInfo *bo) -> std::shared_ptr<DrmFbIdHandle>; private: void CleanupEmptyCacheElements() { diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp index 28f48f3..5051d35 100644 --- a/drm/DrmPlane.cpp +++ b/drm/DrmPlane.cpp @@ -91,17 +91,17 @@ int DrmPlane::Init() { GetPlaneProperty("zpos", zpos_property_, Presence::kOptional); if (GetPlaneProperty("rotation", rotation_property_, Presence::kOptional)) { - rotation_property_.AddEnumToMap("rotate-0", DrmHwcTransform::kIdentity, + rotation_property_.AddEnumToMap("rotate-0", LayerTransform::kIdentity, transform_enum_map_); - rotation_property_.AddEnumToMap("rotate-90", DrmHwcTransform::kRotate90, + rotation_property_.AddEnumToMap("rotate-90", LayerTransform::kRotate90, transform_enum_map_); - rotation_property_.AddEnumToMap("rotate-180", DrmHwcTransform::kRotate180, + rotation_property_.AddEnumToMap("rotate-180", LayerTransform::kRotate180, transform_enum_map_); - rotation_property_.AddEnumToMap("rotate-270", DrmHwcTransform::kRotate270, + rotation_property_.AddEnumToMap("rotate-270", LayerTransform::kRotate270, transform_enum_map_); - rotation_property_.AddEnumToMap("reflect-x", DrmHwcTransform::kFlipH, + rotation_property_.AddEnumToMap("reflect-x", LayerTransform::kFlipH, transform_enum_map_); - rotation_property_.AddEnumToMap("reflect-y", DrmHwcTransform::kFlipV, + rotation_property_.AddEnumToMap("reflect-y", LayerTransform::kFlipV, transform_enum_map_); } @@ -109,11 +109,11 @@ int DrmPlane::Init() { if (GetPlaneProperty("pixel blend mode", blend_property_, Presence::kOptional)) { - blend_property_.AddEnumToMap("Pre-multiplied", DrmHwcBlending::kPreMult, + blend_property_.AddEnumToMap("Pre-multiplied", BufferBlendMode::kPreMult, blending_enum_map_); - blend_property_.AddEnumToMap("Coverage", DrmHwcBlending::kCoverage, + blend_property_.AddEnumToMap("Coverage", BufferBlendMode::kCoverage, blending_enum_map_); - blend_property_.AddEnumToMap("None", DrmHwcBlending::kNone, + blend_property_.AddEnumToMap("None", BufferBlendMode::kNone, blending_enum_map_); } @@ -123,23 +123,23 @@ int DrmPlane::Init() { if (GetPlaneProperty("COLOR_ENCODING", color_encoding_propery_, Presence::kOptional)) { color_encoding_propery_.AddEnumToMap("ITU-R BT.709 YCbCr", - DrmHwcColorSpace::kItuRec709, + BufferColorSpace::kItuRec709, color_encoding_enum_map_); color_encoding_propery_.AddEnumToMap("ITU-R BT.601 YCbCr", - DrmHwcColorSpace::kItuRec601, + BufferColorSpace::kItuRec601, color_encoding_enum_map_); color_encoding_propery_.AddEnumToMap("ITU-R BT.2020 YCbCr", - DrmHwcColorSpace::kItuRec2020, + BufferColorSpace::kItuRec2020, color_encoding_enum_map_); } if (GetPlaneProperty("COLOR_RANGE", color_range_property_, Presence::kOptional)) { color_range_property_.AddEnumToMap("YCbCr full range", - DrmHwcSampleRange::kFullRange, + BufferSampleRange::kFullRange, color_range_enum_map_); color_range_property_.AddEnumToMap("YCbCr limited range", - DrmHwcSampleRange::kLimitedRange, + BufferSampleRange::kLimitedRange, color_range_enum_map_); } } @@ -148,35 +148,52 @@ int DrmPlane::Init() { } bool DrmPlane::IsCrtcSupported(const DrmCrtc &crtc) const { + unsigned int crtc_property_value = 0; + std::tie(std::ignore, crtc_property_value) = crtc_property_.value(); + if (crtc_property_value != 0 && crtc_property_value != crtc.GetId() && + GetType() == DRM_PLANE_TYPE_PRIMARY) { + // Some DRM driver such as omap_drm allows sharing primary plane between + // CRTCs, but the primay plane could not be shared if it has been used by + // any CRTC already, which is protected by the plane_switching_crtc function + // in the kernel drivers/gpu/drm/drm_atomic.c file. + // The current drm_hwc design is not ready to support such scenario yet, + // so adding the CRTC status check here to workaorund for now. + ALOGW( + "%s: This Plane(id=%d) is activated for Crtc(id=%d), could not be used " + "for Crtc (id=%d)", + __FUNCTION__, GetId(), crtc_property_value, crtc.GetId()); + return false; + } + return ((1 << crtc.GetIndexInResArray()) & plane_->possible_crtcs) != 0; } -bool DrmPlane::IsValidForLayer(DrmHwcLayer *layer) { +bool DrmPlane::IsValidForLayer(LayerData *layer) { if (!rotation_property_) { - if (layer->transform != DrmHwcTransform::kIdentity) { + if (layer->pi.transform != LayerTransform::kIdentity) { ALOGV("No rotation property on plane %d", GetId()); return false; } } else { - if (transform_enum_map_.count(layer->transform) == 0) { + if (transform_enum_map_.count(layer->pi.transform) == 0) { ALOGV("Transform is not supported on plane %d", GetId()); return false; } } - if (alpha_property_.id() == 0 && layer->alpha != UINT16_MAX) { + if (alpha_property_.id() == 0 && layer->pi.alpha != UINT16_MAX) { ALOGV("Alpha is not supported on plane %d", GetId()); return false; } - if (blending_enum_map_.count(layer->blending) == 0 && - layer->blending != DrmHwcBlending::kNone && - layer->blending != DrmHwcBlending::kPreMult) { + if (blending_enum_map_.count(layer->bi->blend_mode) == 0 && + layer->bi->blend_mode != BufferBlendMode::kNone && + layer->bi->blend_mode != BufferBlendMode::kPreMult) { ALOGV("Blending is not supported on plane %d", GetId()); return false; } - uint32_t format = layer->buffer_info.format; + uint32_t format = layer->bi->format; if (!IsFormatSupported(format)) { ALOGV("Plane %d does not supports %c%c%c%c format", GetId(), format, format >> 8, format >> 16, format >> 24); @@ -198,17 +215,17 @@ bool DrmPlane::HasNonRgbFormat() const { }) != std::end(formats_); } -static uint64_t ToDrmRotation(DrmHwcTransform transform) { +static uint64_t ToDrmRotation(LayerTransform transform) { uint64_t rotation = 0; - if ((transform & DrmHwcTransform::kFlipH) != 0) + if ((transform & LayerTransform::kFlipH) != 0) rotation |= DRM_MODE_REFLECT_X; - if ((transform & DrmHwcTransform::kFlipV) != 0) + if ((transform & LayerTransform::kFlipV) != 0) rotation |= DRM_MODE_REFLECT_Y; - if ((transform & DrmHwcTransform::kRotate90) != 0) + if ((transform & LayerTransform::kRotate90) != 0) rotation |= DRM_MODE_ROTATE_90; - else if ((transform & DrmHwcTransform::kRotate180) != 0) + else if ((transform & LayerTransform::kRotate180) != 0) rotation |= DRM_MODE_ROTATE_180; - else if ((transform & DrmHwcTransform::kRotate270) != 0) + else if ((transform & LayerTransform::kRotate270) != 0) rotation |= DRM_MODE_ROTATE_270; else rotation |= DRM_MODE_ROTATE_0; @@ -222,9 +239,9 @@ static int To1616FixPt(float in) { return int(in * (1 << kBitShift)); } -auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer, +auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, LayerData &layer, uint32_t zpos, uint32_t crtc_id) -> int { - if (!layer.fb_id_handle) { + if (!layer.fb) { ALOGE("Expected a valid framebuffer for pset"); return -EINVAL; } @@ -245,46 +262,45 @@ auto DrmPlane::AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer, return -EINVAL; } + auto &disp = layer.pi.display_frame; + auto &src = layer.pi.source_crop; if (!crtc_property_.AtomicSet(pset, crtc_id) || - !fb_property_.AtomicSet(pset, layer.fb_id_handle->GetFbId()) || - !crtc_x_property_.AtomicSet(pset, layer.display_frame.left) || - !crtc_y_property_.AtomicSet(pset, layer.display_frame.top) || - !crtc_w_property_.AtomicSet(pset, layer.display_frame.right - - layer.display_frame.left) || - !crtc_h_property_.AtomicSet(pset, layer.display_frame.bottom - - layer.display_frame.top) || - !src_x_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.left)) || - !src_y_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.top)) || - !src_w_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.right - - layer.source_crop.left)) || - !src_h_property_.AtomicSet(pset, To1616FixPt(layer.source_crop.bottom - - layer.source_crop.top))) { + !fb_property_.AtomicSet(pset, layer.fb->GetFbId()) || + !crtc_x_property_.AtomicSet(pset, disp.left) || + !crtc_y_property_.AtomicSet(pset, disp.top) || + !crtc_w_property_.AtomicSet(pset, disp.right - disp.left) || + !crtc_h_property_.AtomicSet(pset, disp.bottom - disp.top) || + !src_x_property_.AtomicSet(pset, To1616FixPt(src.left)) || + !src_y_property_.AtomicSet(pset, To1616FixPt(src.top)) || + !src_w_property_.AtomicSet(pset, To1616FixPt(src.right - src.left)) || + !src_h_property_.AtomicSet(pset, To1616FixPt(src.bottom - src.top))) { return -EINVAL; } if (rotation_property_ && - !rotation_property_.AtomicSet(pset, ToDrmRotation(layer.transform))) { + !rotation_property_.AtomicSet(pset, ToDrmRotation(layer.pi.transform))) { return -EINVAL; } - if (alpha_property_ && !alpha_property_.AtomicSet(pset, layer.alpha)) { + if (alpha_property_ && !alpha_property_.AtomicSet(pset, layer.pi.alpha)) { return -EINVAL; } - if (blending_enum_map_.count(layer.blending) != 0 && - !blend_property_.AtomicSet(pset, blending_enum_map_[layer.blending])) { + if (blending_enum_map_.count(layer.bi->blend_mode) != 0 && + !blend_property_.AtomicSet(pset, + blending_enum_map_[layer.bi->blend_mode])) { return -EINVAL; } - if (color_encoding_enum_map_.count(layer.color_space) != 0 && + if (color_encoding_enum_map_.count(layer.bi->color_space) != 0 && !color_encoding_propery_ - .AtomicSet(pset, color_encoding_enum_map_[layer.color_space])) { + .AtomicSet(pset, color_encoding_enum_map_[layer.bi->color_space])) { return -EINVAL; } - if (color_range_enum_map_.count(layer.sample_range) != 0 && + if (color_range_enum_map_.count(layer.bi->sample_range) != 0 && !color_range_property_ - .AtomicSet(pset, color_range_enum_map_[layer.sample_range])) { + .AtomicSet(pset, color_range_enum_map_[layer.bi->sample_range])) { return -EINVAL; } diff --git a/drm/DrmPlane.h b/drm/DrmPlane.h index 65f458f..31f0a33 100644 --- a/drm/DrmPlane.h +++ b/drm/DrmPlane.h @@ -24,12 +24,12 @@ #include "DrmCrtc.h" #include "DrmProperty.h" -#include "drmhwcomposer.h" +#include "compositor/LayerData.h" namespace android { class DrmDevice; -struct DrmHwcLayer; +struct LayerData; class DrmPlane : public PipelineBindable<DrmPlane> { public: @@ -40,7 +40,7 @@ class DrmPlane : public PipelineBindable<DrmPlane> { -> std::unique_ptr<DrmPlane>; bool IsCrtcSupported(const DrmCrtc &crtc) const; - bool IsValidForLayer(DrmHwcLayer *layer); + bool IsValidForLayer(LayerData *layer); auto GetType() const { return type_; @@ -49,7 +49,7 @@ class DrmPlane : public PipelineBindable<DrmPlane> { bool IsFormatSupported(uint32_t format) const; bool HasNonRgbFormat() const; - auto AtomicSetState(drmModeAtomicReq &pset, DrmHwcLayer &layer, uint32_t zpos, + auto AtomicSetState(drmModeAtomicReq &pset, LayerData &layer, uint32_t zpos, uint32_t crtc_id) -> int; auto AtomicDisablePlane(drmModeAtomicReq &pset) -> int; auto &GetZPosProperty() const { @@ -94,10 +94,10 @@ class DrmPlane : public PipelineBindable<DrmPlane> { DrmProperty color_encoding_propery_; DrmProperty color_range_property_; - std::map<DrmHwcBlending, uint64_t> blending_enum_map_; - std::map<DrmHwcColorSpace, uint64_t> color_encoding_enum_map_; - std::map<DrmHwcSampleRange, uint64_t> color_range_enum_map_; - std::map<DrmHwcTransform, uint64_t> transform_enum_map_; + std::map<BufferBlendMode, uint64_t> blending_enum_map_; + std::map<BufferColorSpace, uint64_t> color_encoding_enum_map_; + std::map<BufferSampleRange, uint64_t> color_range_enum_map_; + std::map<LayerTransform, uint64_t> transform_enum_map_; }; } // namespace android diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp index c8235e9..dbf0993 100644 --- a/drm/ResourceManager.cpp +++ b/drm/ResourceManager.cpp @@ -18,7 +18,6 @@ #include "ResourceManager.h" -#include <fcntl.h> #include <sys/stat.h> #include <ctime> @@ -58,7 +57,10 @@ void ResourceManager::Init() { int path_len = property_get("vendor.hwc.drm.device", path_pattern, "/dev/dri/card%"); if (path_pattern[path_len - 1] != '%') { - AddDrmDevice(std::string(path_pattern)); + auto dev = DrmDevice::CreateInstance(path_pattern, this); + if (dev) { + drms_.emplace_back(std::move(dev)); + } } else { path_pattern[path_len - 1] = '\0'; for (int idx = 0;; ++idx) { @@ -69,8 +71,9 @@ void ResourceManager::Init() { if (stat(path.str().c_str(), &buf) != 0) break; - if (DrmDevice::IsKMSDev(path.str().c_str())) { - AddDrmDevice(path.str()); + auto dev = DrmDevice::CreateInstance(path.str(), this); + if (dev) { + drms_.emplace_back(std::move(dev)); } } } @@ -108,13 +111,6 @@ void ResourceManager::DeInit() { initialized_ = false; } -int ResourceManager::AddDrmDevice(const std::string &path) { - auto drm = std::make_unique<DrmDevice>(); - int ret = drm->Init(path.c_str()); - drms_.push_back(std::move(drm)); - return ret; -} - auto ResourceManager::GetTimeMonotonicNs() -> int64_t { struct timespec ts {}; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -136,8 +132,10 @@ void ResourceManager::UpdateFrontendDisplays() { if (connected) { auto pipeline = DrmDisplayPipeline::CreatePipeline(*conn); - frontend_interface_->BindDisplay(pipeline.get()); - attached_pipelines_[conn] = std::move(pipeline); + if (pipeline) { + frontend_interface_->BindDisplay(pipeline.get()); + attached_pipelines_[conn] = std::move(pipeline); + } } else { auto &pipeline = attached_pipelines_[conn]; frontend_interface_->UnbindDisplay(pipeline.get()); diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h index 88ba878..144d00e 100644 --- a/drm/ResourceManager.h +++ b/drm/ResourceManager.h @@ -59,7 +59,6 @@ class ResourceManager { static auto GetTimeMonotonicNs() -> int64_t; private: - auto AddDrmDevice(std::string const &path) -> int; auto GetOrderedConnectors() -> std::vector<DrmConnector *>; void UpdateFrontendDisplays(); void DetachAllFrontendDisplays(); diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp index e689419..4accb07 100644 --- a/hwc2_device/DrmHwcTwo.cpp +++ b/hwc2_device/DrmHwcTwo.cpp @@ -177,8 +177,14 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, resource_manager_.Init(); } else { resource_manager_.DeInit(); - /* Headless display may still be here, remove it */ - displays_.erase(kPrimaryDisplay); + /* Headless display may still be here. Remove it! */ + if (displays_.count(kPrimaryDisplay) != 0) { + displays_[kPrimaryDisplay]->Deinit(); + auto &mutex = GetResMan().GetMainLock(); + mutex.unlock(); + displays_.erase(kPrimaryDisplay); + mutex.lock(); + } } break; } diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index cedac19..d968ab3 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -90,6 +90,7 @@ HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, : hwc2_(hwc2), handle_(handle), type_(type), + client_layer_(this), color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { // clang-format off color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0, @@ -102,24 +103,51 @@ HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, HwcDisplay::~HwcDisplay() = default; void HwcDisplay::SetPipeline(DrmDisplayPipeline *pipeline) { + Deinit(); + pipeline_ = pipeline; - if (pipeline != nullptr) { - ChosePreferredConfig(); + if (pipeline != nullptr || handle_ == kPrimaryDisplay) { Init(); - hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ true); } else { - backend_.reset(); + hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false); + } +} + +void HwcDisplay::Deinit() { + if (pipeline_ != nullptr) { + AtomicCommitArgs a_args{}; + a_args.composition = std::make_shared<DrmKmsPlan>(); + GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); +/* + * TODO: + * Unfortunately the following causes regressions on db845c + * with VtsHalGraphicsComposerV2_3TargetTest due to the display + * never coming back. Patches to avoiding that issue on the + * the kernel side unfortunately causes further crashes in + * drm_hwcomposer, because the client detach takes longer then the + * 1 second max VTS expects. So for now as a workaround, lets skip + * deactivating the display on deinit, which matches previous + * behavior prior to commit d0494d9b8097 + */ +#if 0 + a_args.composition = {}; + a_args.active = false; + GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); +#endif + vsync_worker_.Init(nullptr, [](int64_t) {}); - SetClientTarget(nullptr, -1, 0, {}); - if (handle_ != kPrimaryDisplay) { - hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false); - } + current_plan_.reset(); + backend_.reset(); } + + SetClientTarget(nullptr, -1, 0, {}); } HWC2::Error HwcDisplay::Init() { + ChosePreferredConfig(); + int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) { const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock()); if (vsync_event_en_) { @@ -176,7 +204,7 @@ HWC2::Error HwcDisplay::AcceptDisplayChanges() { } HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) { - layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer()); + layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer(this)); *layer = static_cast<hwc2_layer_t>(layer_idx_); ++layer_idx_; return HWC2::Error::None; @@ -379,6 +407,9 @@ HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types, /* Find API details at: * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767 + * + * Called after PresentDisplay(), CLIENT is expecting release fence for the + * prior buffer (not the one assigned to the layer at the moment). */ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, @@ -390,8 +421,13 @@ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, uint32_t num_layers = 0; - for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) { + for (auto &l : layers_) { + if (!l.second.GetPriorBufferScanOutFlag() || !present_fence_) { + continue; + } + ++num_layers; + if (layers == nullptr || fences == nullptr) continue; @@ -401,9 +437,10 @@ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, } layers[num_layers - 1] = l.first; - fences[num_layers - 1] = l.second.GetReleaseFence().Release(); + fences[num_layers - 1] = UniqueFd::Dup(present_fence_.Get()).Release(); } *num_elements = num_layers; + return HWC2::Error::None; } @@ -457,18 +494,26 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { if (z_map.empty()) return HWC2::Error::BadLayer; - std::vector<DrmHwcLayer> composition_layers; + std::vector<LayerData> composition_layers; + + /* Import & populate */ + for (std::pair<const uint32_t, HwcLayer *> &l : z_map) { + l.second->PopulateLayerData(a_args.test_only); + } // now that they're ordered by z, add them to the composition for (std::pair<const uint32_t, HwcLayer *> &l : z_map) { - DrmHwcLayer layer; - l.second->PopulateDrmLayer(&layer); - int ret = layer.ImportBuffer(GetPipe().device); - if (ret) { - ALOGE("Failed to import layer, ret=%d", ret); - return HWC2::Error::NoResources; + if (!l.second->IsLayerUsableAsDevice()) { + /* This will be normally triggered on validation of the first frame + * containing CLIENT layer. At this moment client buffer is not yet + * provided by the CLIENT. + * This may be triggered once in HwcLayer lifecycle in case FB can't be + * imported. For example when non-contiguous buffer is imported into + * contiguous-only DRM/KMS driver. + */ + return HWC2::Error::BadLayer; } - composition_layers.emplace_back(std::move(layer)); + composition_layers.emplace_back(l.second->GetLayerData().Clone()); } /* Store plan to ensure shared planes won't be stolen by other display @@ -508,9 +553,9 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { /* Find API details at: * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805 */ -HWC2::Error HwcDisplay::PresentDisplay(int32_t *present_fence) { +HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) { if (IsInHeadlessMode()) { - *present_fence = -1; + *out_present_fence = -1; return HWC2::Error::None; } HWC2::Error ret{}; @@ -525,13 +570,14 @@ HWC2::Error HwcDisplay::PresentDisplay(int32_t *present_fence) { if (ret == HWC2::Error::BadLayer) { // Can we really have no client or device layers? - *present_fence = -1; + *out_present_fence = -1; return HWC2::Error::None; } if (ret != HWC2::Error::None) return ret; - *present_fence = a_args.out_fence.Release(); + this->present_fence_ = UniqueFd::Dup(a_args.out_fence.Get()); + *out_present_fence = a_args.out_fence.Release(); ++frame_no_; return HWC2::Error::None; @@ -571,18 +617,25 @@ HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target, * https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h;l=350;drc=944b68180b008456ed2eb4d4d329e33b19bd5166 */ if (target == nullptr) { + client_layer_.SwChainClearCache(); return HWC2::Error::None; } - /* TODO: Do not update source_crop every call. - * It makes sense to do it once after every hotplug event. */ - HwcDrmBo bo{}; - BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo); + if (IsInHeadlessMode()) { + return HWC2::Error::None; + } + client_layer_.PopulateLayerData(/*test = */ true); + if (!client_layer_.IsLayerUsableAsDevice()) { + ALOGE("Client layer must be always usable by DRM/KMS"); + return HWC2::Error::BadLayer; + } + + auto &bi = client_layer_.GetLayerData().bi; hwc_frect_t source_crop = {.left = 0.0F, .top = 0.0F, - .right = static_cast<float>(bo.width), - .bottom = static_cast<float>(bo.height)}; + .right = static_cast<float>(bi->width), + .bottom = static_cast<float>(bi->height)}; client_layer_.SetLayerSourceCrop(source_crop); return HWC2::Error::None; @@ -621,11 +674,8 @@ HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t /*buffer*/, } HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { - if (IsInHeadlessMode()) { - return HWC2::Error::None; - } - auto mode = static_cast<HWC2::PowerMode>(mode_in); + AtomicCommitArgs a_args{}; switch (mode) { @@ -633,22 +683,30 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { a_args.active = false; break; case HWC2::PowerMode::On: - /* - * Setting the display to active before we have a composition - * can break some drivers, so skip setting a_args.active to - * true, as the next composition frame will implicitly activate - * the display - */ - return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0 - ? HWC2::Error::None - : HWC2::Error::BadParameter; + a_args.active = true; break; case HWC2::PowerMode::Doze: case HWC2::PowerMode::DozeSuspend: return HWC2::Error::Unsupported; default: - ALOGI("Power mode %d is unsupported\n", mode); + ALOGE("Incorrect power mode value (%d)\n", mode); return HWC2::Error::BadParameter; + } + + if (IsInHeadlessMode()) { + return HWC2::Error::None; + } + + if (a_args.active) { + /* + * Setting the display to active before we have a composition + * can break some drivers, so skip setting a_args.active to + * true, as the next composition frame will implicitly activate + * the display + */ + return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0 + ? HWC2::Error::None + : HWC2::Error::BadParameter; }; int err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); @@ -673,6 +731,16 @@ HWC2::Error HwcDisplay::ValidateDisplay(uint32_t *num_types, *num_types = *num_requests = 0; return HWC2::Error::None; } + + /* In current drm_hwc design in case previous frame layer was not validated as + * a CLIENT, it is used by display controller (Front buffer). We have to store + * this state to provide the CLIENT with the release fences for such buffers. + */ + for (auto &l : layers_) { + l.second.SetPriorBufferScanOutFlag(l.second.GetValidatedType() != + HWC2::Composition::Client); + } + return backend_->ValidateDisplay(this, num_types, num_requests); } @@ -782,19 +850,16 @@ HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) { if (IsInHeadlessMode()) { - return HWC2::Error::None; + return HWC2::Error::Unsupported; } - auto blob = GetPipe().connector->Get()->GetEdidBlob(); - - *outPort = handle_ - 1; + auto blob = GetPipe().connector->Get()->GetEdidBlob(); if (!blob) { - if (outData == nullptr) { - *outDataSize = 0; - } - return HWC2::Error::None; + return HWC2::Error::Unsupported; } + *outPort = handle_; /* TDOD(nobody): What should be here? */ + if (outData) { *outDataSize = std::min(*outDataSize, blob->length); memcpy(outData, blob->data, *outDataSize); diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index 98d8e9b..d79efb0 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -22,10 +22,10 @@ #include <optional> #include "HwcDisplayConfigs.h" +#include "compositor/LayerData.h" #include "drm/DrmAtomicStateManager.h" #include "drm/ResourceManager.h" #include "drm/VSyncWorker.h" -#include "drmhwcomposer.h" #include "hwc2_device/HwcLayer.h" namespace android { @@ -106,7 +106,7 @@ class HwcDisplay { float *min_luminance); HWC2::Error GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, int32_t *fences); - HWC2::Error PresentDisplay(int32_t *present_fence); + HWC2::Error PresentDisplay(int32_t *out_present_fence); HWC2::Error SetActiveConfig(hwc2_config_t config); HWC2::Error ChosePreferredConfig(); HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence, @@ -180,6 +180,8 @@ class HwcDisplay { return !pipeline_; } + void Deinit(); + private: enum ClientFlattenningState : int32_t { Disabled = -3, @@ -197,6 +199,8 @@ class HwcDisplay { DrmHwcTwo *const hwc2_; + UniqueFd present_fence_; + std::optional<DrmMode> staged_mode_; int64_t staged_mode_change_time_{}; uint32_t staged_mode_config_id_{}; diff --git a/hwc2_device/HwcLayer.cpp b/hwc2_device/HwcLayer.cpp index 66babda..c278732 100644 --- a/hwc2_device/HwcLayer.cpp +++ b/hwc2_device/HwcLayer.cpp @@ -18,8 +18,8 @@ #include "HwcLayer.h" -#include <fcntl.h> - +#include "HwcDisplay.h" +#include "bufferinfo/BufferInfoGetter.h" #include "utils/log.h" namespace android { @@ -32,17 +32,17 @@ HWC2::Error HwcLayer::SetCursorPosition(int32_t /*x*/, int32_t /*y*/) { HWC2::Error HwcLayer::SetLayerBlendMode(int32_t mode) { switch (static_cast<HWC2::BlendMode>(mode)) { case HWC2::BlendMode::None: - blending_ = DrmHwcBlending::kNone; + blend_mode_ = BufferBlendMode::kNone; break; case HWC2::BlendMode::Premultiplied: - blending_ = DrmHwcBlending::kPreMult; + blend_mode_ = BufferBlendMode::kPreMult; break; case HWC2::BlendMode::Coverage: - blending_ = DrmHwcBlending::kCoverage; + blend_mode_ = BufferBlendMode::kCoverage; break; default: - ALOGE("Unknown blending mode b=%d", blending_); - blending_ = DrmHwcBlending::kNone; + ALOGE("Unknown blending mode b=%d", blend_mode_); + blend_mode_ = BufferBlendMode::kUndefined; break; } return HWC2::Error::None; @@ -53,8 +53,10 @@ HWC2::Error HwcLayer::SetLayerBlendMode(int32_t mode) { */ HWC2::Error HwcLayer::SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence) { - buffer_ = buffer; acquire_fence_ = UniqueFd(acquire_fence); + buffer_handle_ = buffer; + buffer_handle_updated_ = true; + return HWC2::Error::None; } @@ -72,54 +74,54 @@ HWC2::Error HwcLayer::SetLayerCompositionType(int32_t type) { HWC2::Error HwcLayer::SetLayerDataspace(int32_t dataspace) { switch (dataspace & HAL_DATASPACE_STANDARD_MASK) { case HAL_DATASPACE_STANDARD_BT709: - color_space_ = DrmHwcColorSpace::kItuRec709; + color_space_ = BufferColorSpace::kItuRec709; break; case HAL_DATASPACE_STANDARD_BT601_625: case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED: case HAL_DATASPACE_STANDARD_BT601_525: case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED: - color_space_ = DrmHwcColorSpace::kItuRec601; + color_space_ = BufferColorSpace::kItuRec601; break; case HAL_DATASPACE_STANDARD_BT2020: case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: - color_space_ = DrmHwcColorSpace::kItuRec2020; + color_space_ = BufferColorSpace::kItuRec2020; break; default: - color_space_ = DrmHwcColorSpace::kUndefined; + color_space_ = BufferColorSpace::kUndefined; } switch (dataspace & HAL_DATASPACE_RANGE_MASK) { case HAL_DATASPACE_RANGE_FULL: - sample_range_ = DrmHwcSampleRange::kFullRange; + sample_range_ = BufferSampleRange::kFullRange; break; case HAL_DATASPACE_RANGE_LIMITED: - sample_range_ = DrmHwcSampleRange::kLimitedRange; + sample_range_ = BufferSampleRange::kLimitedRange; break; default: - sample_range_ = DrmHwcSampleRange::kUndefined; + sample_range_ = BufferSampleRange::kUndefined; } return HWC2::Error::None; } HWC2::Error HwcLayer::SetLayerDisplayFrame(hwc_rect_t frame) { - display_frame_ = frame; + layer_data_.pi.display_frame = frame; return HWC2::Error::None; } HWC2::Error HwcLayer::SetLayerPlaneAlpha(float alpha) { - alpha_ = alpha; + layer_data_.pi.alpha = std::lround(alpha * UINT16_MAX); return HWC2::Error::None; } // NOLINTNEXTLINE(readability-convert-member-functions-to-static) HWC2::Error HwcLayer::SetLayerSidebandStream( - const native_handle_t * /*stream*/) { + const native_handle_t* /*stream*/) { // TODO(nobody): We don't support sideband return HWC2::Error::Unsupported; } HWC2::Error HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) { - source_crop_ = crop; + layer_data_.pi.source_crop = crop; return HWC2::Error::None; } @@ -137,19 +139,19 @@ HWC2::Error HwcLayer::SetLayerTransform(int32_t transform) { // redundant in this case. 90* rotation can be combined with either horizontal // flip or vertical flip, so treat it differently if (transform == HWC_TRANSFORM_ROT_270) { - l_transform = DrmHwcTransform::kRotate270; + l_transform = LayerTransform::kRotate270; } else if (transform == HWC_TRANSFORM_ROT_180) { - l_transform = DrmHwcTransform::kRotate180; + l_transform = LayerTransform::kRotate180; } else { if ((transform & HWC_TRANSFORM_FLIP_H) != 0) - l_transform |= DrmHwcTransform::kFlipH; + l_transform |= LayerTransform::kFlipH; if ((transform & HWC_TRANSFORM_FLIP_V) != 0) - l_transform |= DrmHwcTransform::kFlipV; + l_transform |= LayerTransform::kFlipV; if ((transform & HWC_TRANSFORM_ROT_90) != 0) - l_transform |= DrmHwcTransform::kRotate90; + l_transform |= LayerTransform::kRotate90; } - transform_ = static_cast<DrmHwcTransform>(l_transform); + layer_data_.pi.transform = static_cast<LayerTransform>(l_transform); return HWC2::Error::None; } @@ -164,17 +166,129 @@ HWC2::Error HwcLayer::SetLayerZOrder(uint32_t order) { return HWC2::Error::None; } -void HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { - layer->sf_handle = buffer_; - // TODO(rsglobal): Avoid extra fd duplication - layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC)); - layer->display_frame = display_frame_; - layer->alpha = std::lround(alpha_ * UINT16_MAX); - layer->blending = blending_; - layer->source_crop = source_crop_; - layer->transform = transform_; - layer->color_space = color_space_; - layer->sample_range = sample_range_; +void HwcLayer::ImportFb() { + if (!IsLayerUsableAsDevice() || !buffer_handle_updated_) { + return; + } + buffer_handle_updated_ = false; + + layer_data_.fb = {}; + + auto unique_id = BufferInfoGetter::GetInstance()->GetUniqueId(buffer_handle_); + if (unique_id && SwChainGetBufferFromCache(*unique_id)) { + return; + } + + layer_data_.bi = BufferInfoGetter::GetInstance()->GetBoInfo(buffer_handle_); + if (!layer_data_.bi) { + ALOGW("Unable to get buffer information (0x%p)", buffer_handle_); + bi_get_failed_ = true; + return; + } + + layer_data_ + .fb = parent_->GetPipe().device->GetDrmFbImporter().GetOrCreateFbId( + &layer_data_.bi.value()); + + if (!layer_data_.fb) { + ALOGV("Unable to create framebuffer object for buffer 0x%p", + buffer_handle_); + fb_import_failed_ = true; + return; + } + + if (unique_id) { + SwChainAddCurrentBuffer(*unique_id); + } +} + +void HwcLayer::PopulateLayerData(bool test) { + ImportFb(); + + if (blend_mode_ != BufferBlendMode::kUndefined) { + layer_data_.bi->blend_mode = blend_mode_; + } + if (color_space_ != BufferColorSpace::kUndefined) { + layer_data_.bi->color_space = color_space_; + } + if (sample_range_ != BufferSampleRange::kUndefined) { + layer_data_.bi->sample_range = sample_range_; + } + + if (!test) { + layer_data_.acquire_fence = std::move(acquire_fence_); + } +} + +/* SwapChain Cache */ + +bool HwcLayer::SwChainGetBufferFromCache(BufferUniqueId unique_id) { + if (swchain_lookup_table_.count(unique_id) == 0) { + return false; + } + + int seq = swchain_lookup_table_[unique_id]; + + if (swchain_cache_.count(seq) == 0) { + return false; + } + + auto& el = swchain_cache_[seq]; + if (!el.bi) { + return false; + } + + layer_data_.bi = el.bi; + layer_data_.fb = el.fb; + + return true; +} + +void HwcLayer::SwChainReassemble(BufferUniqueId unique_id) { + if (swchain_lookup_table_.count(unique_id) != 0) { + if (swchain_lookup_table_[unique_id] == + int(swchain_lookup_table_.size()) - 1) { + /* Skip same buffer */ + return; + } + if (swchain_lookup_table_[unique_id] == 0) { + swchain_reassembled_ = true; + return; + } + /* Tracking error */ + SwChainClearCache(); + return; + } + + swchain_lookup_table_[unique_id] = int(swchain_lookup_table_.size()); +} + +void HwcLayer::SwChainAddCurrentBuffer(BufferUniqueId unique_id) { + if (!swchain_reassembled_) { + SwChainReassemble(unique_id); + } + + if (swchain_reassembled_) { + if (swchain_lookup_table_.count(unique_id) == 0) { + SwChainClearCache(); + return; + } + + int seq = swchain_lookup_table_[unique_id]; + + if (swchain_cache_.count(seq) == 0) { + swchain_cache_[seq] = {}; + } + + swchain_cache_[seq].bi = layer_data_.bi; + swchain_cache_[seq].fb = layer_data_.fb; + } +} + +void HwcLayer::SwChainClearCache() { + swchain_cache_.clear(); + swchain_lookup_table_.clear(); + swchain_reassembled_ = false; } } // namespace android
\ No newline at end of file diff --git a/hwc2_device/HwcLayer.h b/hwc2_device/HwcLayer.h index df4ce6d..41b3dbb 100644 --- a/hwc2_device/HwcLayer.h +++ b/hwc2_device/HwcLayer.h @@ -19,14 +19,17 @@ #include <hardware/hwcomposer2.h> -#include <cmath> - -#include "drmhwcomposer.h" +#include "bufferinfo/BufferInfoGetter.h" +#include "compositor/LayerData.h" namespace android { +class HwcDisplay; + class HwcLayer { public: + explicit HwcLayer(HwcDisplay *parent_display) : parent_(parent_display){}; + HWC2::Composition GetSfType() const { return sf_type_; } @@ -43,35 +46,20 @@ class HwcLayer { return sf_type_ != validated_type_; } - uint32_t GetZOrder() const { - return z_order_; - } - - buffer_handle_t GetBuffer() { - return buffer_; + bool GetPriorBufferScanOutFlag() const { + return prior_buffer_scanout_flag_; } - hwc_rect_t GetDisplayFrame() { - return display_frame_; + void SetPriorBufferScanOutFlag(bool state) { + prior_buffer_scanout_flag_ = state; } - UniqueFd GetReleaseFence() { - return std::move(release_fence_); + uint32_t GetZOrder() const { + return z_order_; } - void PopulateDrmLayer(DrmHwcLayer *layer); - - bool RequireScalingOrPhasing() const { - float src_width = source_crop_.right - source_crop_.left; - float src_height = source_crop_.bottom - source_crop_.top; - - auto dest_width = float(display_frame_.right - display_frame_.left); - auto dest_height = float(display_frame_.bottom - display_frame_.top); - - bool scaling = src_width != dest_width || src_height != dest_height; - bool phasing = (source_crop_.left - std::floor(source_crop_.left) != 0) || - (source_crop_.top - std::floor(source_crop_.top) != 0); - return scaling || phasing; + auto &GetLayerData() { + return layer_data_; } // Layer hooks @@ -96,26 +84,59 @@ class HwcLayer { HWC2::Composition sf_type_ = HWC2::Composition::Invalid; HWC2::Composition validated_type_ = HWC2::Composition::Invalid; - buffer_handle_t buffer_ = nullptr; - hwc_rect_t display_frame_; - static constexpr float kOpaqueFloat = 1.0F; - float alpha_ = kOpaqueFloat; - hwc_frect_t source_crop_; - DrmHwcTransform transform_ = DrmHwcTransform::kIdentity; uint32_t z_order_ = 0; - DrmHwcBlending blending_ = DrmHwcBlending::kNone; - DrmHwcColorSpace color_space_ = DrmHwcColorSpace::kUndefined; - DrmHwcSampleRange sample_range_ = DrmHwcSampleRange::kUndefined; + LayerData layer_data_; + /* Should be populated to layer_data_.acquire_fence only before presenting */ UniqueFd acquire_fence_; - /* - * Release fence is not used. - * There is no release fence support available in the DRM/KMS. In case no - * release fence provided application will use this buffer for writing when - * the next frame present fence is signaled. + /* The following buffer data can have 2 sources: + * 1 - Mapper@4 metadata API + * 2 - HWC@2 API + * We keep ability to have 2 sources in drm_hwc. It may be useful for CLIENT + * layer, at this moment HWC@2 API can't specify blending mode for this layer, + * but Mapper@4 can do that */ - UniqueFd release_fence_; + BufferColorSpace color_space_{}; + BufferSampleRange sample_range_{}; + BufferBlendMode blend_mode_{}; + buffer_handle_t buffer_handle_{}; + bool buffer_handle_updated_{}; + + bool prior_buffer_scanout_flag_{}; + + HwcDisplay *const parent_; + + /* Layer state */ + public: + void PopulateLayerData(bool test); + + bool IsLayerUsableAsDevice() const { + return !bi_get_failed_ && !fb_import_failed_ && buffer_handle_ != nullptr; + } + + private: + void ImportFb(); + bool bi_get_failed_{}; + bool fb_import_failed_{}; + + /* SwapChain Cache */ + public: + void SwChainClearCache(); + + private: + struct SwapChainElement { + std::optional<BufferInfo> bi; + std::shared_ptr<DrmFbIdHandle> fb; + }; + + bool SwChainGetBufferFromCache(BufferUniqueId unique_id); + void SwChainReassemble(BufferUniqueId unique_id); + void SwChainAddCurrentBuffer(BufferUniqueId unique_id); + + std::map<int /*seq_no*/, SwapChainElement> swchain_cache_; + std::map<BufferUniqueId, int /*seq_no*/> swchain_lookup_table_; + bool swchain_reassembled_{}; }; } // namespace android diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h deleted file mode 100644 index 949912d..0000000 --- a/include/drmhwcgralloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 ANDROID_DRMHWCGRALLOC_H_ -#define ANDROID_DRMHWCGRALLOC_H_ - -#include <cstdint> - -constexpr int kHwcDrmBoMaxPlanes = 4; - -struct HwcDrmBo { - uint32_t width; - uint32_t height; - uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ - uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */ - uint32_t usage; - uint32_t pitches[kHwcDrmBoMaxPlanes]; - uint32_t offsets[kHwcDrmBoMaxPlanes]; - /* sizes[] is used only by mapper@4 metadata getter for internal purposes */ - uint32_t sizes[kHwcDrmBoMaxPlanes]; - int prime_fds[kHwcDrmBoMaxPlanes]; - uint64_t modifiers[kHwcDrmBoMaxPlanes]; - int acquire_fence_fd; -}; - -// NOLINTNEXTLINE(readability-identifier-naming) -using hwc_drm_bo_t = HwcDrmBo; - -#endif // ANDROID_DRMHWCGRALLOC_H_ diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h deleted file mode 100644 index 4fb0efd..0000000 --- a/include/drmhwcomposer.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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 ANDROID_DRM_HWCOMPOSER_H_ -#define ANDROID_DRM_HWCOMPOSER_H_ - -#include <hardware/hardware.h> -#include <hardware/hwcomposer.h> - -#include <cstdbool> -#include <cstdint> -#include <vector> - -#include "drm/DrmFbImporter.h" -#include "drmhwcgralloc.h" -#include "utils/UniqueFd.h" - -namespace android { - -class DrmFbIdHandle; - -enum class DrmHwcColorSpace : int32_t { - kUndefined, - kItuRec601, - kItuRec709, - kItuRec2020, -}; - -enum class DrmHwcSampleRange : int32_t { - kUndefined, - kFullRange, - kLimitedRange, -}; - -enum DrmHwcTransform : uint32_t { - kIdentity = 0, - kFlipH = 1 << 0, - kFlipV = 1 << 1, - kRotate90 = 1 << 2, - kRotate180 = 1 << 3, - kRotate270 = 1 << 4, -}; - -enum class DrmHwcBlending : int32_t { - kNone, - kPreMult, - kCoverage, -}; - -struct DrmHwcLayer { - buffer_handle_t sf_handle = nullptr; - hwc_drm_bo_t buffer_info{}; - std::shared_ptr<DrmFbIdHandle> fb_id_handle; - - int gralloc_buffer_usage = 0; - DrmHwcTransform transform{}; - DrmHwcBlending blending = DrmHwcBlending::kNone; - uint16_t alpha = UINT16_MAX; - hwc_frect_t source_crop; - hwc_rect_t display_frame; - DrmHwcColorSpace color_space; - DrmHwcSampleRange sample_range; - - UniqueFd acquire_fence; - - int ImportBuffer(DrmDevice *drm_device); - - bool IsProtected() const { - return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) == - GRALLOC_USAGE_PROTECTED; - } -}; - -} // namespace android - -#endif diff --git a/tests/Android.bp b/tests/Android.bp index b25342e..f3ebb71 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -37,10 +37,7 @@ cc_test { header_libs: ["libhardware_headers"], static_libs: ["libdrmhwc_utils"], shared_libs: ["hwcomposer.drm"], - include_dirs: [ - "external/drm_hwcomposer", - "external/drm_hwcomposer/include", - ], + include_dirs: ["external/drm_hwcomposer"], } // Tool for listening and dumping uevents diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h index 1a390ba..d747a7f 100644 --- a/utils/UniqueFd.h +++ b/utils/UniqueFd.h @@ -17,6 +17,7 @@ #ifndef UNIQUEFD_H_ #define UNIQUEFD_H_ +#include <fcntl.h> #include <unistd.h> #include <memory> @@ -73,6 +74,11 @@ class UniqueFd { return fd_; } + static auto Dup(int fd) { + // NOLINTNEXTLINE(android-cloexec-dup): fcntl has issue (see issue #63) + return UniqueFd(dup(fd)); + } + explicit operator bool() const { return fd_ != kEmptyFd; } diff --git a/utils/Worker.h b/utils/Worker.h index ab01d5f..74cfdc4 100644 --- a/utils/Worker.h +++ b/utils/Worker.h @@ -44,9 +44,10 @@ class Worker { return initialized_; } + virtual ~Worker(); + protected: Worker(const char *name, int priority); - virtual ~Worker(); int InitWorker(); virtual void Routine() = 0; diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp deleted file mode 100644 index c537b99..0000000 --- a/utils/hwcutils.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define ATRACE_TAG ATRACE_TAG_GRAPHICS -#define LOG_TAG "hwc-drm-utils" - -#include <utils/log.h> - -#include <cerrno> - -#include "bufferinfo/BufferInfoGetter.h" -#include "drm/DrmFbImporter.h" -#include "drmhwcomposer.h" - -namespace android { - -int DrmHwcLayer::ImportBuffer(DrmDevice *drm_device) { - buffer_info = hwc_drm_bo_t{}; - - int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(sf_handle, - &buffer_info); - if (ret != 0) { - ALOGE("Failed to convert buffer info %d", ret); - return ret; - } - - fb_id_handle = drm_device->GetDrmFbImporter().GetOrCreateFbId(&buffer_info); - if (!fb_id_handle) { - ALOGE("Failed to import buffer"); - return -EINVAL; - } - - return 0; -} - -} // namespace android |