aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:10:32 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:10:32 +0000
commit81827bc9c51358e5ec88576d6283b99b2c6d1186 (patch)
tree0be8b55408ec891b7c275a1eb9e4f0310702b339
parent43a80df8adebda4596e369768db5e3cb9d1b1601 (diff)
parent39e9dc65f3a608c85124d4014b07ede70680f18b (diff)
downloaddrm_hwcomposer-android14-mainline-uwb-release.tar.gz
Change-Id: I8a1f558319d104af9872fe9b6a6fc173f9116751
-rwxr-xr-x.ci/.gitlab-ci-checkcommit.sh2
-rw-r--r--.ci/Makefile5
-rw-r--r--.clang-tidy3
-rw-r--r--.gitlab-ci.yml4
-rw-r--r--Android.bp12
-rw-r--r--OWNERS2
-rw-r--r--README.md2
-rw-r--r--backend/Backend.cpp6
-rw-r--r--bufferinfo/BufferInfo.h57
-rw-r--r--bufferinfo/BufferInfoGetter.cpp24
-rw-r--r--bufferinfo/BufferInfoGetter.h11
-rw-r--r--bufferinfo/BufferInfoMapperMetadata.cpp60
-rw-r--r--bufferinfo/BufferInfoMapperMetadata.h4
-rw-r--r--bufferinfo/legacy/BufferInfoImagination.cpp30
-rw-r--r--bufferinfo/legacy/BufferInfoImagination.h2
-rw-r--r--bufferinfo/legacy/BufferInfoLibdrm.cpp45
-rw-r--r--bufferinfo/legacy/BufferInfoLibdrm.h5
-rw-r--r--bufferinfo/legacy/BufferInfoMaliHisi.cpp46
-rw-r--r--bufferinfo/legacy/BufferInfoMaliHisi.h2
-rw-r--r--bufferinfo/legacy/BufferInfoMaliMediatek.cpp30
-rw-r--r--bufferinfo/legacy/BufferInfoMaliMediatek.h2
-rw-r--r--bufferinfo/legacy/BufferInfoMaliMeson.cpp30
-rw-r--r--bufferinfo/legacy/BufferInfoMaliMeson.h2
-rw-r--r--bufferinfo/legacy/BufferInfoMinigbm.cpp34
-rw-r--r--bufferinfo/legacy/BufferInfoMinigbm.h2
-rw-r--r--compositor/DrmKmsPlan.cpp2
-rw-r--r--compositor/DrmKmsPlan.h6
-rw-r--r--compositor/LayerData.h81
-rw-r--r--drm/DrmAtomicStateManager.cpp137
-rw-r--r--drm/DrmAtomicStateManager.h58
-rw-r--r--drm/DrmDevice.cpp20
-rw-r--r--drm/DrmDevice.h18
-rw-r--r--drm/DrmDisplayPipeline.cpp12
-rw-r--r--drm/DrmFbImporter.cpp15
-rw-r--r--drm/DrmFbImporter.h8
-rw-r--r--drm/DrmPlane.cpp118
-rw-r--r--drm/DrmPlane.h16
-rw-r--r--drm/ResourceManager.cpp24
-rw-r--r--drm/ResourceManager.h1
-rw-r--r--hwc2_device/DrmHwcTwo.cpp10
-rw-r--r--hwc2_device/HwcDisplay.cpp167
-rw-r--r--hwc2_device/HwcDisplay.h8
-rw-r--r--hwc2_device/HwcLayer.cpp186
-rw-r--r--hwc2_device/HwcLayer.h103
-rw-r--r--include/drmhwcgralloc.h42
-rw-r--r--include/drmhwcomposer.h89
-rw-r--r--tests/Android.bp5
-rw-r--r--utils/UniqueFd.h6
-rw-r--r--utils/Worker.h3
-rw-r--r--utils/hwcutils.cpp49
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
diff --git a/Android.bp b/Android.bp
index c9c94af..a7a2e94 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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",
diff --git a/OWNERS b/OWNERS
index dd8e743..cead4fc 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,5 @@
adelva@google.com
dimitrysh@google.com
-john.stultz@linaro.org
+jstultz@google.com
marcheu@google.com
seanpaul@google.com
diff --git a/README.md b/README.md
index 05ddc79..e98b5ae 100644
--- a/README.md
+++ b/README.md
@@ -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