From 219951b283619fb814a3994af6fa7eb7dcb52b0c Mon Sep 17 00:00:00 2001 From: "Li, HaihongX" Date: Mon, 2 Aug 2021 11:23:34 +0800 Subject: [PATCH] Update drm_hwcomposer Part 1: 0001-Update-drm-hwcomposer.patch Update drm_hwcomposer git clone https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer.git Aligned to commit 8adf544306db75a3fb0843b9977693d2a817bf5d Part 2: 0002-Fix-issue-and-add-some-properties.patch Fix issue and add some properties 1. Fix issue caused by crtc count and connector count doesn't match. 2. Multi-plane support Multi-plane can be enabled by property vendor.hwcomposer.planes.enabling. By default, only one plane is used if the property is not set. vendor.hwcomposer.planes.enabling=1 #support all planes vendor.hwcomposer.planes.enabling=0 #only support PRIMARY by default 3. Select preferred mode If the property 'vendor.hwcomposer.preferred.mode.limit' does not exist, or set to '1' then only support preferred mode. If the property 'vendor.hwcomposer.preferred.mode.limit' is set to '0', support all modes. vendor.hwcomposer.preferred.mode.limit=1#only support preferred mode vendor.hwcomposer.preferred.mode.limit=0#support all modes 4. Select specific mode This function is controlled by 2 properties. vendor.hwcomposer.connector.id vendor.hwcomposer.mode.id If the properties 'vendor.hwcomposer.connector.id' and 'vendor.hwcomposer.mode.id' are all set, then only support the selected mode indicated by 'vendor.hwcomposer.mode.id'. If any one of the properties 'vendor.hwcomposer.connector.id' and 'vendor.hwcomposer.mode.id' is not set, then to check the property 'vendor.hwcomposer.preferred.mode.limit'. vendor.hwcomposer.connector.id=117 vendor.hwcomposer.mode.id=2 5. With these properties, hwc can provide flexibility for performance tuning and bug triage. 6. Find mode id cat /sys/kernel/debug/dri/0/i915_display_info.The output like below: [CONNECTOR:117:DP-4]: status: connected modes: "1920x1080": 62 144500 1920 1968 2000 2080 1080 1083 1088 1112 0x48 0x9 "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0xa "1680x1050": 60 146250 1680 1784 1960 2240 1050 1053 1059 1089 0x40 0x6 "1680x945": 60 131481 1680 1784 1960 2240 945 946 949 978 0x0 0x6 mode id starts from 1, and increases with a step of 1 in order. "1920x1080": 62 144500 1920 1968 2000 2080 1080 1083 1088 1112 0x48 0x9 mode id is 1 "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0xa mode id is 2 "1680x1050": 60 146250 1680 1784 1960 2240 1050 1053 1059 1089 0x40 0x6 mode id is 3 "1680x945": 60 131481 1680 1784 1960 2240 945 946 949 978 0x0 0x6 mode id is 4 7. The property can be set in /vendor/default.prop. 8. Support 'SetActiveConfigWithConstraints' interface needed by vts. 9. Fix multi-display issue. Part 3: 0003-Fix-hotplug-issue-and-add-vsync2.4-callback.patch Fix hotplug issue and add vsync2.4 callback 1. Once unplug event comes, display.ClearDisplay() will be invoked. Then DrmDisplayCompositor::active_composition_ will be set to nullptr, so in function DrmDisplayCompositor::IsFlatteningNeeded(), should check active_composition_ is not nullptr. 2. For android can't delete primary display, so when unplug event comes and belongs to primary display, don't invoke hotplug callback to notify upper. 3. Add vsync2.4 callback. 4. Set connector dpms property with DRM_MODE_DPMS_OFF if unpluging, DRM_MODE_DPMS_ON if pluging,to enable irq,fix type-c hotplug issue. 5. Set DrmDevice::mode_id_ with 0 at beginning of DrmConnector::UpdateModes(). Part 4: 0004-Set-the-primary-display-as-internal-display.patch Set the primary display as internal display Celadon connect monitor with HDMI/DP/Type-C port, which is regarded as external display, but android by default assume there is one internal display, so need to set the primary display as internal display. Tracked-On: OAM-99705 Signed-off-by: Li, HaihongX --- .../0001-Update-drm_hwcomposer.patch | 9866 +++++++++++++++++ .../0001-update-drm-hwcomposer.patch | 4994 --------- ...02-Fix-issue-and-add-some-properties.patch | 328 + ...plug-issue-and-add-vsync2.4-callback.patch | 246 + ...-primary-display-as-internal-display.patch | 32 + 5 files changed, 10472 insertions(+), 4994 deletions(-) create mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0001-Update-drm_hwcomposer.patch delete mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0001-update-drm-hwcomposer.patch create mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0002-Fix-issue-and-add-some-properties.patch create mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0003-Fix-hotplug-issue-and-add-vsync2.4-callback.patch create mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0004-Set-the-primary-display-as-internal-display.patch diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0001-Update-drm_hwcomposer.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0001-Update-drm_hwcomposer.patch new file mode 100644 index 0000000000..4f025bee7b --- /dev/null +++ b/aosp_diff/preliminary/external/drm_hwcomposer/0001-Update-drm_hwcomposer.patch @@ -0,0 +1,9866 @@ +From 4d0c8e32e184f957ef7bfa7e753b98c8da303011 Mon Sep 17 00:00:00 2001 +From: "Li, HaihongX" +Date: Thu, 19 Aug 2021 09:51:31 +0800 +Subject: [PATCH 1/3] Update drm_hwcomposer + +git clone +https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer.git +Aligned to commit 8adf544306db75a3fb0843b9977693d2a817bf5d + +Tracked-On: OAM-99705 +Signed-off-by: Li, HaihongX +--- + Android.bp | 87 +-- + drmhwctwo.cpp => DrmHwcTwo.cpp | 562 +++++++++--------- + include/drmhwctwo.h => DrmHwcTwo.h | 199 ++++--- + METADATA | 3 - + OWNERS | 5 - + README.md | 34 +- + backend/Backend.cpp | 172 ++++++ + backend/Backend.h | 49 ++ + backend/BackendClient.cpp | 38 ++ + backend/BackendClient.h | 32 + + backend/BackendManager.cpp | 80 +++ + backend/BackendManager.h | 57 ++ + backend/BackendRCarDu.cpp | 48 ++ + backend/BackendRCarDu.h | 31 + + bufferinfo/BufferInfoGetter.cpp | 120 ++++ + bufferinfo/BufferInfoGetter.h | 79 +++ + bufferinfo/BufferInfoMapperMetadata.cpp | 145 +++++ + bufferinfo/BufferInfoMapperMetadata.h | 36 ++ + .../legacy/BufferInfoImagination.cpp | 49 +- + bufferinfo/legacy/BufferInfoImagination.h | 34 ++ + bufferinfo/legacy/BufferInfoLibdrm.cpp | 205 +++++++ + bufferinfo/legacy/BufferInfoLibdrm.h | 37 ++ + bufferinfo/legacy/BufferInfoMaliHisi.cpp | 125 ++++ + .../legacy/BufferInfoMaliHisi.h | 20 +- + bufferinfo/legacy/BufferInfoMaliMediatek.cpp | 57 ++ + bufferinfo/legacy/BufferInfoMaliMediatek.h | 34 ++ + .../legacy/BufferInfoMaliMeson.cpp | 46 +- + .../legacy/BufferInfoMaliMeson.h | 17 +- + bufferinfo/legacy/BufferInfoMinigbm.cpp | 58 ++ + .../legacy/BufferInfoMinigbm.h | 14 +- + ...position.cpp => DrmDisplayComposition.cpp} | 59 +- + .../DrmDisplayComposition.h | 74 +-- + ...ompositor.cpp => DrmDisplayCompositor.cpp} | 538 ++++------------- + .../DrmDisplayCompositor.h | 65 +- + .../platform.cpp => compositor/Planner.cpp | 75 +-- + include/platform.h => compositor/Planner.h | 49 +- + drm/{drmconnector.cpp => DrmConnector.cpp} | 57 +- + include/drmconnector.h => drm/DrmConnector.h | 13 +- + drm/{drmcrtc.cpp => DrmCrtc.cpp} | 9 +- + include/drmcrtc.h => drm/DrmCrtc.h | 6 +- + drm/{drmdevice.cpp => DrmDevice.cpp} | 137 +++-- + include/drmdevice.h => drm/DrmDevice.h | 44 +- + drm/{drmencoder.cpp => DrmEncoder.cpp} | 17 +- + include/drmencoder.h => drm/DrmEncoder.h | 7 +- + ...eventlistener.cpp => DrmEventListener.cpp} | 69 ++- + .../DrmEventListener.h | 6 +- + drm/DrmFbImporter.cpp | 151 +++++ + drm/DrmFbImporter.h | 94 +++ + drm/{drmmode.cpp => DrmMode.cpp} | 14 +- + include/drmmode.h => drm/DrmMode.h | 1 + + drm/{drmplane.cpp => DrmPlane.cpp} | 130 +++- + include/drmplane.h => drm/DrmPlane.h | 20 +- + drm/{drmproperty.cpp => DrmProperty.cpp} | 36 +- + include/drmproperty.h => drm/DrmProperty.h | 6 +- + ...esourcemanager.cpp => ResourceManager.cpp} | 80 ++- + .../ResourceManager.h | 13 +- + drm/{vsyncworker.cpp => VSyncWorker.cpp} | 88 ++- + include/vsyncworker.h => drm/VSyncWorker.h | 24 +- + include/autofd.h | 106 ---- + include/drmframebuffer.h | 107 ---- + include/drmhwcgralloc.h | 5 - + include/drmhwcomposer.h | 106 +--- + platform/platformdrmgeneric.cpp | 252 -------- + platform/platformdrmgeneric.h | 64 -- + platform/platformhisi.cpp | 197 ------ + platform/platformimagination.h | 22 - + platform/platformminigbm.cpp | 72 --- + presubmit.sh | 21 + + tests/Android.bp | 24 +- + tests/test_include/cros_gralloc_handle.h | 53 ++ + tests/test_include/gralloc_helper.h | 54 ++ + tests/test_include/gralloc_priv.h | 69 +++ + tests/test_include/img_gralloc1_public.h | 253 ++++++++ + tests/test_include/mali_gralloc_buffer.h | 271 +++++++++ + tests/test_include/mali_gralloc_formats.h | 270 +++++++++ + .../mali_gralloc_private_interface_types.h | 88 +++ + tests/test_include/mali_gralloc_usages.h | 94 +++ + tests/worker_test.cpp | 25 +- + utils/UniqueFd.h | 111 ++++ + utils/{worker.cpp => Worker.cpp} | 5 +- + include/worker.h => utils/Worker.h | 2 +- + utils/autolock.cpp | 5 +- + {include => utils}/autolock.h | 0 + utils/hwcutils.cpp | 129 +--- + utils/log.h | 26 + + utils/properties.h | 28 + + 86 files changed, 4309 insertions(+), 2505 deletions(-) + rename drmhwctwo.cpp => DrmHwcTwo.cpp (78%) + rename include/drmhwctwo.h => DrmHwcTwo.h (80%) + delete mode 100644 METADATA + delete mode 100644 OWNERS + create mode 100644 backend/Backend.cpp + create mode 100644 backend/Backend.h + create mode 100644 backend/BackendClient.cpp + create mode 100644 backend/BackendClient.h + create mode 100644 backend/BackendManager.cpp + create mode 100644 backend/BackendManager.h + create mode 100644 backend/BackendRCarDu.cpp + create mode 100644 backend/BackendRCarDu.h + create mode 100644 bufferinfo/BufferInfoGetter.cpp + create mode 100644 bufferinfo/BufferInfoGetter.h + create mode 100644 bufferinfo/BufferInfoMapperMetadata.cpp + create mode 100644 bufferinfo/BufferInfoMapperMetadata.h + rename platform/platformimagination.cpp => bufferinfo/legacy/BufferInfoImagination.cpp (50%) + create mode 100644 bufferinfo/legacy/BufferInfoImagination.h + create mode 100644 bufferinfo/legacy/BufferInfoLibdrm.cpp + create mode 100644 bufferinfo/legacy/BufferInfoLibdrm.h + create mode 100644 bufferinfo/legacy/BufferInfoMaliHisi.cpp + rename platform/platformhisi.h => bufferinfo/legacy/BufferInfoMaliHisi.h (69%) + create mode 100644 bufferinfo/legacy/BufferInfoMaliMediatek.cpp + create mode 100644 bufferinfo/legacy/BufferInfoMaliMediatek.h + rename platform/platformmeson.cpp => bufferinfo/legacy/BufferInfoMaliMeson.cpp (63%) + rename platform/platformmeson.h => bufferinfo/legacy/BufferInfoMaliMeson.h (76%) + create mode 100644 bufferinfo/legacy/BufferInfoMinigbm.cpp + rename platform/platformminigbm.h => bufferinfo/legacy/BufferInfoMinigbm.h (75%) + rename compositor/{drmdisplaycomposition.cpp => DrmDisplayComposition.cpp} (87%) + rename include/drmdisplaycomposition.h => compositor/DrmDisplayComposition.h (70%) + rename compositor/{drmdisplaycompositor.cpp => DrmDisplayCompositor.cpp} (58%) + rename include/drmdisplaycompositor.h => compositor/DrmDisplayCompositor.h (71%) + rename platform/platform.cpp => compositor/Planner.cpp (64%) + rename include/platform.h => compositor/Planner.h (73%) + rename drm/{drmconnector.cpp => DrmConnector.cpp} (86%) + rename include/drmconnector.h => drm/DrmConnector.h (93%) + rename drm/{drmcrtc.cpp => DrmCrtc.cpp} (95%) + rename include/drmcrtc.h => drm/DrmCrtc.h (97%) + rename drm/{drmdevice.cpp => DrmDevice.cpp} (85%) + rename include/drmdevice.h => drm/DrmDevice.h (81%) + rename drm/{drmencoder.cpp => DrmEncoder.cpp} (79%) + rename include/drmencoder.h => drm/DrmEncoder.h (94%) + rename drm/{drmeventlistener.cpp => DrmEventListener.cpp} (68%) + rename include/drmeventlistener.h => drm/DrmEventListener.h (95%) + create mode 100644 drm/DrmFbImporter.cpp + create mode 100644 drm/DrmFbImporter.h + rename drm/{drmmode.cpp => DrmMode.cpp} (93%) + rename include/drmmode.h => drm/DrmMode.h (99%) + rename drm/{drmplane.cpp => DrmPlane.cpp} (56%) + rename include/drmplane.h => drm/DrmPlane.h (84%) + rename drm/{drmproperty.cpp => DrmProperty.cpp} (83%) + rename include/drmproperty.h => drm/DrmProperty.h (92%) + rename drm/{resourcemanager.cpp => ResourceManager.cpp} (66%) + rename include/resourcemanager.h => drm/ResourceManager.h (87%) + rename drm/{vsyncworker.cpp => VSyncWorker.cpp} (66%) + rename include/vsyncworker.h => drm/VSyncWorker.h (77%) + delete mode 100644 include/autofd.h + delete mode 100644 include/drmframebuffer.h + delete mode 100644 platform/platformdrmgeneric.cpp + delete mode 100644 platform/platformdrmgeneric.h + delete mode 100644 platform/platformhisi.cpp + delete mode 100644 platform/platformimagination.h + delete mode 100644 platform/platformminigbm.cpp + create mode 100755 presubmit.sh + create mode 100644 tests/test_include/cros_gralloc_handle.h + create mode 100644 tests/test_include/gralloc_helper.h + create mode 100644 tests/test_include/gralloc_priv.h + create mode 100644 tests/test_include/img_gralloc1_public.h + create mode 100644 tests/test_include/mali_gralloc_buffer.h + create mode 100644 tests/test_include/mali_gralloc_formats.h + create mode 100644 tests/test_include/mali_gralloc_private_interface_types.h + create mode 100644 tests/test_include/mali_gralloc_usages.h + create mode 100644 utils/UniqueFd.h + rename utils/{worker.cpp => Worker.cpp} (94%) + rename include/worker.h => utils/Worker.h (100%) + rename {include => utils}/autolock.h (100%) + create mode 100644 utils/log.h + create mode 100644 utils/properties.h + +diff --git a/Android.bp b/Android.bp +index 8bcd1aa..ddf66fb 100644 +--- a/Android.bp ++++ b/Android.bp +@@ -18,9 +18,12 @@ + cc_library_static { + name: "libdrmhwc_utils", + +- srcs: ["utils/worker.cpp"], ++ srcs: ["utils/Worker.cpp"], + +- include_dirs: ["external/drm_hwcomposer/include"], ++ include_dirs: [ ++ "external/drm_hwcomposer", ++ "external/drm_hwcomposer/include", ++ ], + + cflags: [ + "-Wall", +@@ -41,13 +44,17 @@ cc_defaults { + "libcutils", + "libdrm", + "libhardware", ++ "libhidlbase", + "liblog", + "libsync", + "libui", + "libutils", + ], + +- include_dirs: ["external/drm_hwcomposer/include"], ++ include_dirs: [ ++ "external/drm_hwcomposer", ++ "external/drm_hwcomposer/include", ++ ], + + static_libs: ["libdrmhwc_utils"], + +@@ -57,8 +64,8 @@ cc_defaults { + ], + + cppflags: [ +- "-DHWC2_USE_CPP11", + "-DHWC2_INCLUDE_STRINGIFICATION", ++ "-DHWC2_USE_CPP11", + ], + + product_variables: { +@@ -70,30 +77,39 @@ cc_defaults { + relative_install_path: "hw", + vendor: true, + } ++ + cc_library_static { + name: "drm_hwcomposer", + defaults: ["hwcomposer.drm_defaults"], + srcs: [ +- "drmhwctwo.cpp", +- +- "compositor/drmdisplaycomposition.cpp", +- "compositor/drmdisplaycompositor.cpp", +- +- "drm/drmconnector.cpp", +- "drm/drmcrtc.cpp", +- "drm/drmdevice.cpp", +- "drm/drmencoder.cpp", +- "drm/drmeventlistener.cpp", +- "drm/drmmode.cpp", +- "drm/drmplane.cpp", +- "drm/drmproperty.cpp", +- "drm/resourcemanager.cpp", +- "drm/vsyncworker.cpp", +- +- "platform/platform.cpp", ++ "DrmHwcTwo.cpp", ++ ++ "bufferinfo/BufferInfoGetter.cpp", ++ "bufferinfo/BufferInfoMapperMetadata.cpp", ++ ++ "compositor/DrmDisplayComposition.cpp", ++ "compositor/DrmDisplayCompositor.cpp", ++ "compositor/Planner.cpp", ++ ++ "drm/DrmConnector.cpp", ++ "drm/DrmCrtc.cpp", ++ "drm/DrmDevice.cpp", ++ "drm/DrmEncoder.cpp", ++ "drm/DrmEventListener.cpp", ++ "drm/DrmFbImporter.cpp", ++ "drm/DrmMode.cpp", ++ "drm/DrmPlane.cpp", ++ "drm/DrmProperty.cpp", ++ "drm/ResourceManager.cpp", ++ "drm/VSyncWorker.cpp", + + "utils/autolock.cpp", + "utils/hwcutils.cpp", ++ ++ "backend/Backend.cpp", ++ "backend/BackendClient.cpp", ++ "backend/BackendManager.cpp", ++ "backend/BackendRCarDu.cpp", + ], + } + +@@ -101,44 +117,37 @@ cc_library_shared { + name: "hwcomposer.drm", + defaults: ["hwcomposer.drm_defaults"], + whole_static_libs: ["drm_hwcomposer"], +- srcs: ["platform/platformdrmgeneric.cpp"], +- cppflags: ["-DUSE_DRM_GENERIC_IMPORTER"], ++ srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"], + } + + cc_library_shared { + name: "hwcomposer.drm_minigbm", + defaults: ["hwcomposer.drm_defaults"], + whole_static_libs: ["drm_hwcomposer"], +- srcs: [ +- "platform/platformdrmgeneric.cpp", +- "platform/platformminigbm.cpp", +- ], ++ srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"], + include_dirs: ["external/minigbm/cros_gralloc"], + } + + // Used by hwcomposer.drm_imagination + filegroup { + name: "drm_hwcomposer_platformimagination", +- srcs: [ +- "platform/platformdrmgeneric.cpp", +- "platform/platformimagination.cpp", +- ], ++ srcs: ["bufferinfo/legacy/BufferInfoImagination.cpp"], + } + + // Used by hwcomposer.drm_hikey and hwcomposer.drm_hikey960 + filegroup { + name: "drm_hwcomposer_platformhisi", +- srcs: [ +- "platform/platformdrmgeneric.cpp", +- "platform/platformhisi.cpp", +- ], ++ srcs: ["bufferinfo/legacy/BufferInfoMaliHisi.cpp"], + } + + // Used by hwcomposer.drm_meson + filegroup { + name: "drm_hwcomposer_platformmeson", +- srcs: [ +- "platform/platformdrmgeneric.cpp", +- "platform/platformmeson.cpp", +- ], ++ srcs: ["bufferinfo/legacy/BufferInfoMaliMeson.cpp"], ++} ++ ++// Used by hwcomposer.drm_mediatek ++filegroup { ++ name: "drm_hwcomposer_platformmediatek", ++ srcs: ["bufferinfo/legacy/BufferInfoMaliMediatek.cpp"], + } +diff --git a/drmhwctwo.cpp b/DrmHwcTwo.cpp +similarity index 78% +rename from drmhwctwo.cpp +rename to DrmHwcTwo.cpp +index 5afc96d..d141f16 100644 +--- a/drmhwctwo.cpp ++++ b/DrmHwcTwo.cpp +@@ -17,39 +17,28 @@ + #define ATRACE_TAG ATRACE_TAG_GRAPHICS + #define LOG_TAG "hwc-drm-two" + +-#include "drmhwctwo.h" +-#include "drmdisplaycomposition.h" +-#include "drmhwcomposer.h" +-#include "platform.h" +-#include "vsyncworker.h" ++#include "DrmHwcTwo.h" + +-#include +-#include +- +-#include ++#include + #include + #include +-#include +- +-namespace android { ++#include ++#include + +-class DrmVsyncCallback : public VsyncCallback { +- public: +- DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook) +- : data_(data), hook_(hook) { +- } ++#include ++#include ++#include ++#include + +- void Callback(int display, int64_t timestamp) { +- auto hook = reinterpret_cast(hook_); +- hook(data_, display, timestamp); +- } ++#include "backend/BackendManager.h" ++#include "bufferinfo/BufferInfoGetter.h" ++#include "compositor/DrmDisplayComposition.h" ++#include "utils/log.h" ++#include "utils/properties.h" + +- private: +- hwc2_callback_data_t data_; +- hwc2_function_pointer_t hook_; +-}; ++namespace android { + +-DrmHwcTwo::DrmHwcTwo() { ++DrmHwcTwo::DrmHwcTwo() : hwc2_device() { + common.tag = HARDWARE_DEVICE_TAG; + common.version = HWC_DEVICE_API_VERSION_2_0; + common.close = HookDevClose; +@@ -60,22 +49,21 @@ DrmHwcTwo::DrmHwcTwo() { + HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ, + HWC2::DisplayType type) { + DrmDevice *drm = resource_manager_.GetDrmDevice(displ); +- std::shared_ptr importer = resource_manager_.GetImporter(displ); +- if (!drm || !importer) { +- ALOGE("Failed to get a valid drmresource and importer"); ++ if (!drm) { ++ ALOGE("Failed to get a valid drmresource"); + return HWC2::Error::NoResources; + } + displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ), +- std::forward_as_tuple(&resource_manager_, drm, importer, +- displ, type)); ++ std::forward_as_tuple(&resource_manager_, drm, displ, ++ type)); + + DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast(displ)); + if (!crtc) { + ALOGE("Failed to get crtc for display %d", static_cast(displ)); + return HWC2::Error::BadDisplay; + } +- std::vector display_planes; +- for (auto &plane : drm->planes()) { ++ auto display_planes = std::vector(); ++ for (const auto &plane : drm->planes()) { + if (plane->GetCrtcSupported(*crtc)) + display_planes.push_back(plane.get()); + } +@@ -99,8 +87,9 @@ HWC2::Error DrmHwcTwo::Init() { + } + } + +- auto &drmDevices = resource_manager_.getDrmDevices(); +- for (auto &device : drmDevices) { ++ const auto &drm_devices = resource_manager_.getDrmDevices(); ++ for (const auto &device : drm_devices) { ++ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get())); + } + return ret; +@@ -119,12 +108,12 @@ static inline void supported(char const *func) { + HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t width, uint32_t height, + int32_t *format, + hwc2_display_t *display) { +- // TODO: Implement virtual display ++ // TODO(nobody): Implement virtual display + return unsupported(__func__, width, height, format, display); + } + + HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) { +- // TODO: Implement virtual display ++ // TODO(nobody): Implement virtual display + return unsupported(__func__, display); + } + +@@ -132,45 +121,43 @@ std::string DrmHwcTwo::HwcDisplay::DumpDelta( + DrmHwcTwo::HwcDisplay::Stats delta) { + if (delta.total_pixops_ == 0) + return "No stats yet"; +- double Ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_); +- +- return (std::stringstream() +- << " Total frames count: " << delta.total_frames_ << "\n" +- << " Failed to test commit frames: " << delta.failed_kms_validate_ +- << "\n" +- << " Failed to commit frames: " << delta.failed_kms_present_ << "\n" +- << ((delta.failed_kms_present_ > 0) +- ? " !!! Internal failure, FIX it please\n" +- : "") +- << " Flattened frames: " << delta.frames_flattened_ << "\n" +- << " Pixel operations (free units)" +- << " : [TOTAL: " << delta.total_pixops_ +- << " / GPU: " << delta.gpu_pixops_ << "]\n" +- << " Composition efficiency: " << Ratio) +- .str(); ++ double ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_); ++ ++ std::stringstream ss; ++ ss << " Total frames count: " << delta.total_frames_ << "\n" ++ << " Failed to test commit frames: " << delta.failed_kms_validate_ << "\n" ++ << " Failed to commit frames: " << delta.failed_kms_present_ << "\n" ++ << ((delta.failed_kms_present_ > 0) ++ ? " !!! Internal failure, FIX it please\n" ++ : "") ++ << " Flattened frames: " << delta.frames_flattened_ << "\n" ++ << " Pixel operations (free units)" ++ << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_ ++ << "]\n" ++ << " Composition efficiency: " << ratio; ++ ++ return ss.str(); + } + + std::string DrmHwcTwo::HwcDisplay::Dump() { +- auto out = (std::stringstream() +- << "- Display on: " << connector_->name() << "\n" +- << " Flattening state: " << compositor_.GetFlatteningState() +- << "\n" +- << "Statistics since system boot:\n" +- << DumpDelta(total_stats_) << "\n\n" +- << "Statistics since last dumpsys request:\n" +- << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n") +- .str(); ++ std::stringstream ss; ++ ss << "- Display on: " << connector_->name() << "\n" ++ << " Flattening state: " << compositor_.GetFlatteningState() << "\n" ++ << "Statistics since system boot:\n" ++ << DumpDelta(total_stats_) << "\n\n" ++ << "Statistics since last dumpsys request:\n" ++ << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n"; + + memcpy(&prev_stats_, &total_stats_, sizeof(Stats)); +- return out; ++ return ss.str(); + } + + void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) { + supported(__func__); + + if (outBuffer != nullptr) { +- auto copiedBytes = mDumpString.copy(outBuffer, *outSize); +- *outSize = static_cast(copiedBytes); ++ auto copied_bytes = mDumpString.copy(outBuffer, *outSize); ++ *outSize = static_cast(copied_bytes); + return; + } + +@@ -186,7 +173,7 @@ void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) { + } + + uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() { +- // TODO: Implement virtual display ++ // TODO(nobody): Implement virtual display + unsupported(__func__); + return 0; + } +@@ -195,19 +182,12 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, + hwc2_callback_data_t data, + hwc2_function_pointer_t function) { + supported(__func__); +- auto callback = static_cast(descriptor); +- +- if (!function) { +- callbacks_.erase(callback); +- return HWC2::Error::None; +- } + +- callbacks_.emplace(callback, HwcCallback(data, function)); +- +- switch (callback) { ++ switch (static_cast(descriptor)) { + case HWC2::Callback::Hotplug: { +- auto &drmDevices = resource_manager_.getDrmDevices(); +- for (auto &device : drmDevices) ++ SetHotplugCallback(data, function); ++ const auto &drm_devices = resource_manager_.getDrmDevices(); ++ for (const auto &device : drm_devices) + HandleInitialHotplugState(device.get()); + break; + } +@@ -230,12 +210,10 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, + } + + DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager, +- DrmDevice *drm, +- std::shared_ptr importer, +- hwc2_display_t handle, HWC2::DisplayType type) ++ DrmDevice *drm, hwc2_display_t handle, ++ HWC2::DisplayType type) + : resource_manager_(resource_manager), + drm_(drm), +- importer_(importer), + handle_(handle), + type_(type), + color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { +@@ -271,8 +249,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector *planes) { + // Split up the given display planes into primary and overlay to properly + // interface with the composition + char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; +- property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1"); +- bool use_overlay_planes = atoi(use_overlay_planes_prop); ++ property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop, ++ "1"); ++ bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr, 10); + for (auto &plane : *planes) { + if (plane->type() == DRM_PLANE_TYPE_PRIMARY) + primary_planes_.push_back(plane); +@@ -298,34 +277,35 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector *planes) { + return HWC2::Error::BadDisplay; + } + ++ ret = BackendManager::GetInstance().SetBackendForDisplay(this); ++ if (ret) { ++ ALOGE("Failed to set backend for d=%d %d\n", display, ret); ++ return HWC2::Error::BadDisplay; ++ } ++ + return ChosePreferredConfig(); + } + + HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() { + // Fetch the number of modes from the display +- uint32_t num_configs; +- HWC2::Error err = GetDisplayConfigs(&num_configs, NULL); ++ uint32_t num_configs = 0; ++ HWC2::Error err = GetDisplayConfigs(&num_configs, nullptr); + if (err != HWC2::Error::None || !num_configs) + return err; + + return SetActiveConfig(connector_->get_preferred_mode_id()); + } + +-HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( ++void DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( + hwc2_callback_data_t data, hwc2_function_pointer_t func) { + supported(__func__); +- auto callback = std::make_shared(data, func); +- vsync_worker_.RegisterCallback(std::move(callback)); +- return HWC2::Error::None; ++ vsync_worker_.RegisterClientCallback(data, func); + } + + void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback( + hwc2_callback_data_t data, hwc2_function_pointer_t func) { + supported(__func__); +- auto hook = reinterpret_cast(func); +- compositor_.SetRefreshCallback([data, hook](int display) { +- hook(data, static_cast(display)); +- }); ++ compositor_.SetRefreshCallback(data, func); + } + + HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() { +@@ -394,11 +374,10 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetClientTargetSupport(uint32_t width, + if (width > max.first || height > max.second) + return HWC2::Error::Unsupported; + +- if (dataspace != HAL_DATASPACE_UNKNOWN && +- dataspace != HAL_DATASPACE_STANDARD_UNSPECIFIED) ++ if (dataspace != HAL_DATASPACE_UNKNOWN) + return HWC2::Error::Unsupported; + +- // TODO: Validate format can be handled by either GL or planes ++ // TODO(nobody): Validate format can be handled by either GL or planes + return HWC2::Error::None; + } + +@@ -441,7 +420,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config, + break; + case HWC2::Attribute::VsyncPeriod: + // in nanoseconds +- *value = 1000 * 1000 * 1000 / mode->v_refresh(); ++ *value = 1000.0 * 1000.0 * 1000.0 / mode->v_refresh(); + break; + case HWC2::Attribute::DpiX: + // Dots per 1000 inches +@@ -451,6 +430,11 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config, + // Dots per 1000 inches + *value = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1; + break; ++#if PLATFORM_SDK_VERSION > 29 ++ case HWC2::Attribute::ConfigGroup: ++ *value = 0; /* TODO: Add support for config groups */ ++ break; ++#endif + default: + *value = -1; + return HWC2::Error::BadConfig; +@@ -482,7 +466,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, + // at least one non-interlaced alternative and only offer a single WxH@R + // mode with at least the prefered mode from in DrmConnector::UpdateModes() + +- // TODO: Remove the following block of code until AOSP handles all modes ++ // TODO(nobody): Remove the following block of code until AOSP handles all ++ // modes + std::vector sel_modes; + + // Add the preferred mode first to be sure it's not dropped +@@ -501,11 +486,11 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, + // Cycle over the modes and filter out "similar" modes, keeping only the + // first ones in the order given by DRM (from CEA ids and timings order) + for (const DrmMode &mode : connector_->modes()) { +- // TODO: Remove this when 3D Attributes are in AOSP ++ // TODO(nobody): Remove this when 3D Attributes are in AOSP + if (mode.flags() & DRM_MODE_FLAG_3D_MASK) + continue; + +- // TODO: Remove this when the Interlaced attribute is in AOSP ++ // TODO(nobody): Remove this when the Interlaced attribute is in AOSP + if (mode.flags() & DRM_MODE_FLAG_INTERLACE) { + auto m = std::find_if(connector_->modes().begin(), + connector_->modes().end(), +@@ -522,7 +507,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, + + // Search for a similar WxH@R mode in the filtered list and drop it if + // another mode with the same WxH@R has already been selected +- // TODO: Remove this when AOSP handles duplicates modes ++ // TODO(nobody): Remove this when AOSP handles duplicates modes + auto m = std::find_if(sel_modes.begin(), sel_modes.end(), + [&mode](DrmMode const &m) { + return m.h_display() == mode.h_display() && +@@ -570,7 +555,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayRequests(int32_t *display_requests, + hwc2_layer_t *layers, + int32_t *layer_requests) { + supported(__func__); +- // TODO: I think virtual display should request ++ // TODO(nobody): I think virtual display should request + // HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here + unsupported(__func__, display_requests, num_elements, layers, layer_requests); + *num_elements = 0; +@@ -597,6 +582,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetHdrCapabilities( + return HWC2::Error::None; + } + ++/* Find API details at: ++ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767 ++ */ + HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements, + hwc2_layer_t *layers, + int32_t *fences) { +@@ -605,47 +593,35 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements, + + for (std::pair &l : layers_) { + ++num_layers; +- if (layers == NULL || fences == NULL) { ++ if (layers == nullptr || fences == nullptr) + continue; +- } else if (num_layers > *num_elements) { ++ ++ if (num_layers > *num_elements) { + ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements); + return HWC2::Error::None; + } + + layers[num_layers - 1] = l.first; +- fences[num_layers - 1] = l.second.take_release_fence(); ++ fences[num_layers - 1] = l.second.release_fence_.Release(); + } + *num_elements = num_layers; + return HWC2::Error::None; + } + +-void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(int fd) { +- if (fd < 0) ++void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(UniqueFd fd) { ++ if (!fd) { + return; ++ } + +- if (present_fence_.get() >= 0) { +- int old_fence = present_fence_.get(); +- present_fence_.Set(sync_merge("dc_present", old_fence, fd)); +- close(fd); ++ if (present_fence_) { ++ present_fence_ = UniqueFd( ++ sync_merge("dc_present", present_fence_.Get(), fd.Get())); + } else { +- present_fence_.Set(fd); ++ present_fence_ = std::move(fd); + } + } + +-bool DrmHwcTwo::HwcDisplay::HardwareSupportsLayerType( +- HWC2::Composition comp_type) { +- return comp_type == HWC2::Composition::Device || +- comp_type == HWC2::Composition::Cursor; +-} +- + HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { +- std::vector layers_map; +- layers_map.emplace_back(); +- DrmCompositionDisplayLayersMap &map = layers_map.back(); +- +- map.display = static_cast(handle_); +- map.geometry_changed = true; // TODO: Fix this +- + // order the layers by z-order + bool use_client_layer = false; + uint32_t client_z_order = UINT32_MAX; +@@ -670,24 +646,26 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { + if (z_map.empty()) + return HWC2::Error::BadLayer; + ++ std::vector composition_layers; ++ + // now that they're ordered by z, add them to the composition + for (std::pair &l : z_map) { + DrmHwcLayer layer; + l.second->PopulateDrmLayer(&layer); +- int ret = layer.ImportBuffer(importer_.get()); ++ int ret = layer.ImportBuffer(drm_); + if (ret) { + ALOGE("Failed to import layer, ret=%d", ret); + return HWC2::Error::NoResources; + } +- map.layers.emplace_back(std::move(layer)); ++ composition_layers.emplace_back(std::move(layer)); + } + +- std::unique_ptr composition = compositor_ +- .CreateComposition(); +- composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_); ++ auto composition = std::make_unique(crtc_, ++ planner_.get()); + +- // TODO: Don't always assume geometry changed +- int ret = composition->SetLayers(map.layers.data(), map.layers.size(), true); ++ // TODO(nobody): Don't always assume geometry changed ++ int ret = composition->SetLayers(composition_layers.data(), ++ composition_layers.size(), true); + if (ret) { + ALOGE("Failed to set layers in the composition ret=%d", ret); + return HWC2::Error::BadLayer; +@@ -725,6 +703,9 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { + return HWC2::Error::None; + } + ++/* 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 DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) { + supported(__func__); + HWC2::Error ret; +@@ -761,10 +742,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { + return HWC2::Error::BadConfig; + } + +- std::unique_ptr composition = compositor_ +- .CreateComposition(); +- composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_); ++ auto composition = std::make_unique(crtc_, ++ planner_.get()); + int ret = composition->SetDisplayMode(*mode); ++ if (ret) { ++ return HWC2::Error::BadConfig; ++ } + ret = compositor_.ApplyComposition(std::move(composition)); + if (ret) { + ALOGE("Failed to queue dpms composition on %d", ret); +@@ -779,34 +762,46 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { + .right = static_cast(mode->h_display()), + .bottom = static_cast(mode->v_display())}; + client_layer_.SetLayerDisplayFrame(display_frame); +- hwc_frect_t source_crop = {.left = 0.0f, +- .top = 0.0f, +- .right = mode->h_display() + 0.0f, +- .bottom = mode->v_display() + 0.0f}; +- client_layer_.SetLayerSourceCrop(source_crop); + + return HWC2::Error::None; + } + ++/* Find API details at: ++ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861 ++ */ + HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target, + int32_t acquire_fence, + int32_t dataspace, + hwc_region_t /*damage*/) { + supported(__func__); +- UniqueFd uf(acquire_fence); + + client_layer_.set_buffer(target); +- client_layer_.set_acquire_fence(uf.get()); ++ client_layer_.acquire_fence_ = UniqueFd(acquire_fence); + client_layer_.SetLayerDataspace(dataspace); ++ ++ /* TODO: Do not update source_crop every call. ++ * It makes sense to do it once after every hotplug event. */ ++ hwc_drm_bo bo{}; ++ BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo); ++ ++ hwc_frect_t source_crop = {.left = 0.0F, ++ .top = 0.0F, ++ .right = bo.width + 0.0F, ++ .bottom = bo.height + 0.0F}; ++ client_layer_.SetLayerSourceCrop(source_crop); ++ + return HWC2::Error::None; + } + + HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) { + supported(__func__); + +- if (mode != HAL_COLOR_MODE_NATIVE) ++ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) + return HWC2::Error::BadParameter; + ++ if (mode != HAL_COLOR_MODE_NATIVE) ++ return HWC2::Error::Unsupported; ++ + color_mode_ = mode; + return HWC2::Error::None; + } +@@ -831,7 +826,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetColorTransform(const float *matrix, + HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer, + int32_t release_fence) { + supported(__func__); +- // TODO: Need virtual display support ++ // TODO(nobody): Need virtual display support + return unsupported(__func__, buffer, release_fence); + } + +@@ -854,9 +849,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { + return HWC2::Error::BadParameter; + }; + +- std::unique_ptr composition = compositor_ +- .CreateComposition(); +- composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_); ++ auto composition = std::make_unique(crtc_, ++ planner_.get()); + composition->SetDpmsMode(dpms_value); + int ret = compositor_.ApplyComposition(std::move(composition)); + if (ret) { +@@ -872,138 +866,105 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetVsyncEnabled(int32_t enabled) { + return HWC2::Error::None; + } + +-uint32_t DrmHwcTwo::HwcDisplay::CalcPixOps( +- std::map &z_map, size_t first_z, +- size_t size) { +- uint32_t pixops = 0; +- for (std::pair &l : z_map) { +- if (l.first >= first_z && l.first < first_z + size) { +- hwc_rect_t df = l.second->display_frame(); +- pixops += (df.right - df.left) * (df.bottom - df.top); +- } +- } +- return pixops; ++HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, ++ uint32_t *num_requests) { ++ supported(__func__); ++ ++ return backend_->ValidateDisplay(this, num_types, num_requests); + } + +-void DrmHwcTwo::HwcDisplay::MarkValidated( +- std::map &z_map, size_t client_first_z, +- size_t client_size) { +- for (std::pair &l : z_map) { +- if (l.first >= client_first_z && l.first < client_first_z + client_size) +- l.second->set_validated_type(HWC2::Composition::Client); +- else +- l.second->set_validated_type(HWC2::Composition::Device); ++std::vector ++DrmHwcTwo::HwcDisplay::GetOrderLayersByZPos() { ++ std::vector ordered_layers; ++ ordered_layers.reserve(layers_.size()); ++ ++ for (auto &[handle, layer] : layers_) { ++ ordered_layers.emplace_back(&layer); + } ++ ++ std::sort(std::begin(ordered_layers), std::end(ordered_layers), ++ [](const DrmHwcTwo::HwcLayer *lhs, const DrmHwcTwo::HwcLayer *rhs) { ++ return lhs->z_order() < rhs->z_order(); ++ }); ++ ++ return ordered_layers; + } + +-HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, +- uint32_t *num_requests) { +- supported(__func__); +- *num_types = 0; +- *num_requests = 0; +- size_t avail_planes = primary_planes_.size() + overlay_planes_.size(); ++#if PLATFORM_SDK_VERSION > 29 ++HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { ++ if (connector_->internal()) ++ *outType = static_cast(HWC2::DisplayConnectionType::Internal); ++ else if (connector_->external()) ++ *outType = static_cast(HWC2::DisplayConnectionType::External); ++ else ++ return HWC2::Error::BadConfig; + +- /* +- * If more layers then planes, save one plane +- * for client composited layers +- */ +- if (avail_planes < layers_.size()) +- avail_planes--; ++ return HWC2::Error::None; ++} + +- std::map z_map, z_map_tmp; +- uint32_t z_index = 0; +- // First create a map of layers and z_order values +- for (std::pair &l : layers_) +- z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second)); +- // normalise the map so that the lowest z_order layer has key 0 +- for (std::pair &l : z_map_tmp) +- z_map.emplace(std::make_pair(z_index++, l.second)); ++HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayVsyncPeriod( ++ hwc2_vsync_period_t *outVsyncPeriod /* ns */) { ++ supported(__func__); ++ DrmMode const &mode = connector_->active_mode(); ++ if (mode.id() == 0) ++ return HWC2::Error::BadConfig; + +- uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0; ++ *outVsyncPeriod = 1E9 / mode.v_refresh(); ++ return HWC2::Error::None; ++} + +- int client_start = -1, client_size = 0; ++HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfigWithConstraints( ++ hwc2_config_t /*config*/, ++ hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, ++ hwc_vsync_period_change_timeline_t *outTimeline) { ++ supported(__func__); + +- if (compositor_.ShouldFlattenOnClient()) { +- client_start = 0; +- client_size = z_map.size(); +- MarkValidated(z_map, client_start, client_size); +- } else { +- for (std::pair &l : z_map) { +- if (!HardwareSupportsLayerType(l.second->sf_type()) || +- !importer_->CanImportBuffer(l.second->buffer()) || +- color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY || +- (l.second->RequireScalingOrPhasing() && +- resource_manager_->ForcedScalingWithGpu())) { +- if (client_start < 0) +- client_start = l.first; +- client_size = (l.first - client_start) + 1; +- } +- } ++ if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) { ++ return HWC2::Error::BadParameter; ++ } + +- int extra_client = (z_map.size() - client_size) - avail_planes; +- if (extra_client > 0) { +- int start = 0, steps; +- if (client_size != 0) { +- int prepend = std::min(client_start, extra_client); +- int append = std::min(int(z_map.size() - (client_start + client_size)), +- extra_client); +- start = client_start - prepend; +- client_size += extra_client; +- steps = 1 + std::min(std::min(append, prepend), +- int(z_map.size()) - (start + client_size)); +- } else { +- client_size = extra_client; +- steps = 1 + z_map.size() - extra_client; +- } +- +- gpu_pixops = INT_MAX; +- for (int i = 0; i < steps; i++) { +- uint32_t po = CalcPixOps(z_map, start + i, client_size); +- if (po < gpu_pixops) { +- gpu_pixops = po; +- client_start = start + i; +- } +- } +- } ++ return HWC2::Error::BadConfig; ++} + +- MarkValidated(z_map, client_start, client_size); ++HWC2::Error DrmHwcTwo::HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) { ++ return HWC2::Error::Unsupported; ++} + +- bool testing_needed = !(client_start == 0 && client_size == z_map.size()); ++HWC2::Error DrmHwcTwo::HwcDisplay::GetSupportedContentTypes( ++ uint32_t *outNumSupportedContentTypes, ++ const uint32_t *outSupportedContentTypes) { ++ if (outSupportedContentTypes == nullptr) ++ *outNumSupportedContentTypes = 0; + +- if (testing_needed && CreateComposition(true) != HWC2::Error::None) { +- ++total_stats_.failed_kms_validate_; +- gpu_pixops = total_pixops; +- client_size = z_map.size(); +- MarkValidated(z_map, 0, client_size); +- } +- } ++ return HWC2::Error::None; ++} + +- *num_types = client_size; ++HWC2::Error DrmHwcTwo::HwcDisplay::SetContentType(int32_t contentType) { ++ supported(__func__); + +- total_stats_.frames_flattened_ = compositor_.GetFlattenedFramesCount(); +- total_stats_.gpu_pixops_ += gpu_pixops; +- total_stats_.total_pixops_ += total_pixops; ++ if (contentType != HWC2_CONTENT_TYPE_NONE) ++ return HWC2::Error::Unsupported; ++ ++ /* TODO: Map to the DRM Connector property: ++ * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809 ++ */ + +- return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; ++ return HWC2::Error::None; + } ++#endif + + #if PLATFORM_SDK_VERSION > 28 + HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData( + uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) { + supported(__func__); + +- drmModePropertyBlobPtr blob; +- int ret; +- uint64_t blob_id; ++ drmModePropertyBlobPtr blob = nullptr; + +- std::tie(ret, blob_id) = connector_->edid_property().value(); +- if (ret) { ++ if (connector_->GetEdidBlob(blob)) { + ALOGE("Failed to get edid property value."); + return HWC2::Error::Unsupported; + } + +- blob = drmModeGetPropertyBlob(drm_->fd(), blob_id); +- + if (outData) { + *outDataSize = std::min(*outDataSize, blob->length); + memcpy(outData, blob->data, *outDataSize); +@@ -1019,7 +980,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities( + uint32_t *outNumCapabilities, uint32_t *outCapabilities) { + unsupported(__func__, outCapabilities); + +- if (outNumCapabilities == NULL) { ++ if (outNumCapabilities == nullptr) { + return HWC2::Error::BadParameter; + } + +@@ -1061,10 +1022,19 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetRenderIntents( + + HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode, + int32_t intent) { +- if (mode != HAL_COLOR_MODE_NATIVE) ++ if (intent < HAL_RENDER_INTENT_COLORIMETRIC || ++ intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE) + return HWC2::Error::BadParameter; +- if (intent != HAL_RENDER_INTENT_COLORIMETRIC) ++ ++ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) + return HWC2::Error::BadParameter; ++ ++ if (mode != HAL_COLOR_MODE_NATIVE) ++ return HWC2::Error::Unsupported; ++ ++ if (intent != HAL_RENDER_INTENT_COLORIMETRIC) ++ return HWC2::Error::Unsupported; ++ + color_mode_ = mode; + return HWC2::Error::None; + } +@@ -1084,18 +1054,20 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) { + return HWC2::Error::None; + } + ++/* Find API details at: ++ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=2314 ++ */ + HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer, + int32_t acquire_fence) { + supported(__func__); +- UniqueFd uf(acquire_fence); + + set_buffer(buffer); +- set_acquire_fence(uf.get()); ++ acquire_fence_ = UniqueFd(acquire_fence); + return HWC2::Error::None; + } + + HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) { +- // TODO: Put to client composition here? ++ // TODO(nobody): Put to client composition here? + supported(__func__); + layer_color_ = color; + return HWC2::Error::None; +@@ -1127,7 +1099,7 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerPlaneAlpha(float alpha) { + HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSidebandStream( + const native_handle_t *stream) { + supported(__func__); +- // TODO: We don't support sideband ++ // TODO(nobody): We don't support sideband + return unsupported(__func__, stream); + } + +@@ -1139,7 +1111,7 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) { + + HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSurfaceDamage(hwc_region_t damage) { + supported(__func__); +- // TODO: We don't use surface damage, marking as unsupported ++ // TODO(nobody): We don't use surface damage, marking as unsupported + unsupported(__func__, damage); + return HWC2::Error::None; + } +@@ -1152,7 +1124,7 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t transform) { + + HWC2::Error DrmHwcTwo::HwcLayer::SetLayerVisibleRegion(hwc_region_t visible) { + supported(__func__); +- // TODO: We don't use this information, marking as unsupported ++ // TODO(nobody): We don't use this information, marking as unsupported + unsupported(__func__, visible); + return HWC2::Error::None; + } +@@ -1181,30 +1153,28 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { + break; + } + +- OutputFd release_fence = release_fence_output(); +- + layer->sf_handle = buffer_; +- layer->acquire_fence = acquire_fence_.Release(); +- layer->release_fence = std::move(release_fence); +- layer->SetDisplayFrame(display_frame_); +- layer->alpha = static_cast(65535.0f * alpha_ + 0.5f); +- layer->SetSourceCrop(source_crop_); ++ // TODO(rsglobal): Avoid extra fd duplication ++ layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC)); ++ layer->display_frame = display_frame_; ++ layer->alpha = lround(65535.0F * alpha_); ++ layer->source_crop = source_crop_; + layer->SetTransform(static_cast(transform_)); ++ layer->dataspace = dataspace_; + } + + void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { +- auto cb = callbacks_.find(HWC2::Callback::Hotplug); +- if (cb == callbacks_.end()) +- return; ++ const std::lock_guard lock(hotplug_callback_lock); + +- auto hotplug = reinterpret_cast(cb->second.func); +- hotplug(cb->second.data, displayid, +- (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED +- : HWC2_CONNECTION_DISCONNECTED)); ++ if (hotplug_callback_hook_ && hotplug_callback_data_) ++ hotplug_callback_hook_(hotplug_callback_data_, displayid, ++ state == DRM_MODE_CONNECTED ++ ? HWC2_CONNECTION_CONNECTED ++ : HWC2_CONNECTION_DISCONNECTED); + } + + void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { +- for (auto &conn : drmDevice->connectors()) { ++ for (const auto &conn : drmDevice->connectors()) { + if (conn->state() != DRM_MODE_CONNECTED) + continue; + HandleDisplayHotplug(conn->display(), conn->state()); +@@ -1212,7 +1182,7 @@ void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { + } + + void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) { +- for (auto &conn : drm_->connectors()) { ++ for (const auto &conn : drm_->connectors()) { + drmModeConnection old_state = conn->state(); + drmModeConnection cur_state = conn->UpdateModes() + ? DRM_MODE_UNKNOWNCONNECTION +@@ -1418,6 +1388,36 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction( + DisplayHook); + #endif /* PLATFORM_SDK_VERSION > 28 */ ++#if PLATFORM_SDK_VERSION > 29 ++ case HWC2::FunctionDescriptor::GetDisplayConnectionType: ++ return ToHook( ++ DisplayHook); ++ case HWC2::FunctionDescriptor::GetDisplayVsyncPeriod: ++ return ToHook( ++ DisplayHook); ++ case HWC2::FunctionDescriptor::SetActiveConfigWithConstraints: ++ return ToHook( ++ DisplayHook); ++ case HWC2::FunctionDescriptor::SetAutoLowLatencyMode: ++ return ToHook( ++ DisplayHook); ++ case HWC2::FunctionDescriptor::GetSupportedContentTypes: ++ return ToHook( ++ DisplayHook); ++ case HWC2::FunctionDescriptor::SetContentType: ++ return ToHook( ++ DisplayHook); ++#endif + // Layer functions + case HWC2::FunctionDescriptor::SetCursorPosition: + return ToHook( +@@ -1478,7 +1478,7 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction( + &HwcLayer::SetLayerZOrder, uint32_t>); + case HWC2::FunctionDescriptor::Invalid: + default: +- return NULL; ++ return nullptr; + } + } + +@@ -1486,7 +1486,7 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction( + int DrmHwcTwo::HookDevOpen(const struct hw_module_t *module, const char *name, + struct hw_device_t **dev) { + supported(__func__); +- if (strcmp(name, HWC_HARDWARE_COMPOSER)) { ++ if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) { + ALOGE("Invalid module name- %s", name); + return -EINVAL; + } +@@ -1503,17 +1503,19 @@ int DrmHwcTwo::HookDevOpen(const struct hw_module_t *module, const char *name, + return -EINVAL; + } + +- ctx->common.module = const_cast(module); ++ ctx->common.module = (hw_module_t *)module; + *dev = &ctx->common; +- ctx.release(); ++ ctx.release(); // NOLINT(bugprone-unused-return-value) + return 0; + } + } // namespace android + ++// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + static struct hw_module_methods_t hwc2_module_methods = { + .open = android::DrmHwcTwo::HookDevOpen, + }; + ++// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = HARDWARE_MODULE_API_VERSION(2, 0), +@@ -1521,6 +1523,6 @@ hw_module_t HAL_MODULE_INFO_SYM = { + .name = "DrmHwcTwo module", + .author = "The Android Open Source Project", + .methods = &hwc2_module_methods, +- .dso = NULL, ++ .dso = nullptr, + .reserved = {0}, + }; +diff --git a/include/drmhwctwo.h b/DrmHwcTwo.h +similarity index 80% +rename from include/drmhwctwo.h +rename to DrmHwcTwo.h +index 1f226bc..111c664 100644 +--- a/include/drmhwctwo.h ++++ b/DrmHwcTwo.h +@@ -14,20 +14,25 @@ + * limitations under the License. + */ + +-#include "drmdisplaycompositor.h" +-#include "drmhwcomposer.h" +-#include "platform.h" +-#include "resourcemanager.h" +-#include "vsyncworker.h" ++#ifndef ANDROID_DRM_HWC_TWO_H_ ++#define ANDROID_DRM_HWC_TWO_H_ + + #include +- + #include ++ + #include + #include + ++#include "compositor/DrmDisplayCompositor.h" ++#include "compositor/Planner.h" ++#include "drm/ResourceManager.h" ++#include "drm/VSyncWorker.h" ++#include "drmhwcomposer.h" ++ + namespace android { + ++class Backend; ++ + class DrmHwcTwo : public hwc2_device_t { + public: + static int HookDevOpen(const struct hw_module_t *module, const char *name, +@@ -37,7 +42,17 @@ class DrmHwcTwo : public hwc2_device_t { + + HWC2::Error Init(); + +- private: ++ hwc2_callback_data_t hotplug_callback_data_ = NULL; ++ HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL; ++ std::mutex hotplug_callback_lock; ++ ++ void SetHotplugCallback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook) { ++ const std::lock_guard lock(hotplug_callback_lock); ++ hotplug_callback_data_ = data; ++ hotplug_callback_hook_ = reinterpret_cast(hook); ++ } ++ + class HwcLayer { + public: + HWC2::Composition sf_type() const { +@@ -67,27 +82,6 @@ class DrmHwcTwo : public hwc2_device_t { + buffer_ = buffer; + } + +- int take_acquire_fence() { +- return acquire_fence_.Release(); +- } +- void set_acquire_fence(int acquire_fence) { +- acquire_fence_.Set(dup(acquire_fence)); +- } +- +- int release_fence() { +- return release_fence_.get(); +- } +- int take_release_fence() { +- return release_fence_.Release(); +- } +- void manage_release_fence() { +- release_fence_.Set(release_fence_raw_); +- release_fence_raw_ = -1; +- } +- OutputFd release_fence_output() { +- return OutputFd(&release_fence_raw_); +- } +- + hwc_rect_t display_frame() { + return display_frame_; + } +@@ -121,7 +115,17 @@ class DrmHwcTwo : public hwc2_device_t { + HWC2::Error SetLayerSurfaceDamage(hwc_region_t damage); + HWC2::Error SetLayerTransform(int32_t transform); + HWC2::Error SetLayerVisibleRegion(hwc_region_t visible); +- HWC2::Error SetLayerZOrder(uint32_t z); ++ HWC2::Error SetLayerZOrder(uint32_t order); ++ ++ 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. ++ */ ++ UniqueFd release_fence_; + + private: + // sf_type_ stores the initial type given to us by surfaceflinger, +@@ -131,9 +135,6 @@ class DrmHwcTwo : public hwc2_device_t { + + HWC2::BlendMode blending_ = HWC2::BlendMode::None; + buffer_handle_t buffer_ = NULL; +- UniqueFd acquire_fence_; +- int release_fence_raw_ = -1; +- UniqueFd release_fence_; + hwc_rect_t display_frame_; + float alpha_ = 1.0f; + hwc_frect_t source_crop_; +@@ -145,26 +146,19 @@ class DrmHwcTwo : public hwc2_device_t { + android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN; + }; + +- struct HwcCallback { +- HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f) +- : data(d), func(f) { +- } +- hwc2_callback_data_t data; +- hwc2_function_pointer_t func; +- }; +- + class HwcDisplay { + public: + HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, +- std::shared_ptr importer, hwc2_display_t handle, +- HWC2::DisplayType type); ++ hwc2_display_t handle, HWC2::DisplayType type); + HwcDisplay(const HwcDisplay &) = delete; + HWC2::Error Init(std::vector *planes); + +- HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, +- hwc2_function_pointer_t func); ++ void RegisterVsyncCallback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t func); + void RegisterRefreshCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t func); ++ HWC2::Error CreateComposition(bool test); ++ std::vector GetOrderLayersByZPos(); + + void ClearDisplay(); + +@@ -204,6 +198,22 @@ class DrmHwcTwo : public hwc2_device_t { + HWC2::Error GetDisplayBrightnessSupport(bool *supported); + HWC2::Error SetDisplayBrightness(float); + #endif ++#if PLATFORM_SDK_VERSION > 29 ++ HWC2::Error GetDisplayConnectionType(uint32_t *outType); ++ HWC2::Error GetDisplayVsyncPeriod(hwc2_vsync_period_t *outVsyncPeriod); ++ ++ HWC2::Error SetActiveConfigWithConstraints( ++ hwc2_config_t config, ++ hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, ++ hwc_vsync_period_change_timeline_t *outTimeline); ++ HWC2::Error SetAutoLowLatencyMode(bool on); ++ HWC2::Error GetSupportedContentTypes( ++ uint32_t *outNumSupportedContentTypes, ++ const uint32_t *outSupportedContentTypes); ++ ++ HWC2::Error SetContentType(int32_t contentType); ++#endif ++ + HWC2::Error GetDozeSupport(int32_t *support); + HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, + float *max_luminance, +@@ -229,26 +239,83 @@ class DrmHwcTwo : public hwc2_device_t { + return &it->second; + } + ++ /* Statistics */ ++ struct Stats { ++ Stats minus(Stats b) { ++ return {total_frames_ - b.total_frames_, ++ total_pixops_ - b.total_pixops_, ++ gpu_pixops_ - b.gpu_pixops_, ++ failed_kms_validate_ - b.failed_kms_validate_, ++ failed_kms_present_ - b.failed_kms_present_, ++ frames_flattened_ - b.frames_flattened_}; ++ } ++ ++ uint32_t total_frames_ = 0; ++ uint64_t total_pixops_ = 0; ++ uint64_t gpu_pixops_ = 0; ++ uint32_t failed_kms_validate_ = 0; ++ uint32_t failed_kms_present_ = 0; ++ uint32_t frames_flattened_ = 0; ++ }; ++ ++ const Backend *backend() const { ++ return backend_.get(); ++ } ++ void set_backend(std::unique_ptr backend) { ++ backend_ = std::move(backend); ++ } ++ ++ const std::vector &primary_planes() const { ++ return primary_planes_; ++ } ++ ++ const std::vector &overlay_planes() const { ++ return overlay_planes_; ++ } ++ ++ std::map &layers() { ++ return layers_; ++ } ++ ++ const DrmDisplayCompositor &compositor() const { ++ return compositor_; ++ } ++ ++ const DrmDevice *drm() const { ++ return drm_; ++ } ++ ++ const DrmConnector *connector() const { ++ return connector_; ++ } ++ ++ ResourceManager *resource_manager() const { ++ return resource_manager_; ++ } ++ ++ android_color_transform_t &color_transform_hint() { ++ return color_transform_hint_; ++ } ++ ++ Stats &total_stats() { ++ return total_stats_; ++ } ++ + private: +- HWC2::Error CreateComposition(bool test); +- void AddFenceToPresentFence(int fd); +- bool HardwareSupportsLayerType(HWC2::Composition comp_type); +- uint32_t CalcPixOps(std::map &z_map, +- size_t first_z, size_t size); +- void MarkValidated(std::map &z_map, +- size_t client_first_z, size_t client_size); ++ void AddFenceToPresentFence(UniqueFd fd); + + constexpr static size_t MATRIX_SIZE = 16; + + ResourceManager *resource_manager_; + DrmDevice *drm_; + DrmDisplayCompositor compositor_; +- std::shared_ptr importer_; + std::unique_ptr planner_; + + std::vector primary_planes_; + std::vector overlay_planes_; + ++ std::unique_ptr backend_; ++ + VSyncWorker vsync_worker_; + DrmConnector *connector_ = NULL; + DrmCrtc *crtc_ = NULL; +@@ -258,29 +325,13 @@ class DrmHwcTwo : public hwc2_device_t { + std::map layers_; + HwcLayer client_layer_; + UniqueFd present_fence_; +- int32_t color_mode_; +- std::array color_transform_matrix_; ++ int32_t color_mode_{}; ++ std::array color_transform_matrix_{}; + android_color_transform_t color_transform_hint_; + + uint32_t frame_no_ = 0; +- /* Statistics */ +- struct Stats { +- Stats minus(Stats b) { +- return {total_frames_ - b.total_frames_, +- total_pixops_ - b.total_pixops_, +- gpu_pixops_ - b.gpu_pixops_, +- failed_kms_validate_ - b.failed_kms_validate_, +- failed_kms_present_ - b.failed_kms_present_, +- frames_flattened_ - b.frames_flattened_}; +- } +- +- uint32_t total_frames_ = 0; +- uint64_t total_pixops_ = 0; +- uint64_t gpu_pixops_ = 0; +- uint32_t failed_kms_validate_ = 0; +- uint32_t failed_kms_present_ = 0; +- uint32_t frames_flattened_ = 0; +- } total_stats_, prev_stats_; ++ Stats total_stats_; ++ Stats prev_stats_; + std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta); + }; + +@@ -296,6 +347,7 @@ class DrmHwcTwo : public hwc2_device_t { + DrmDevice *drm_; + }; + ++ private: + static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { + return static_cast(dev); + } +@@ -365,8 +417,9 @@ class DrmHwcTwo : public hwc2_device_t { + + ResourceManager resource_manager_; + std::map displays_; +- std::map callbacks_; + + std::string mDumpString; + }; + } // namespace android ++ ++#endif +diff --git a/METADATA b/METADATA +deleted file mode 100644 +index d97975c..0000000 +--- a/METADATA ++++ /dev/null +@@ -1,3 +0,0 @@ +-third_party { +- license_type: NOTICE +-} +diff --git a/OWNERS b/OWNERS +deleted file mode 100644 +index 75e29ae..0000000 +--- a/OWNERS ++++ /dev/null +@@ -1,5 +0,0 @@ +-adelva@google.com +-john.stultz@linaro.org +-marcheu@google.com +-seanpaul@google.com +-zachr@google.com +diff --git a/README.md b/README.md +index 05f1364..728bc76 100644 +--- a/README.md ++++ b/README.md +@@ -1,19 +1,29 @@ +-drm_hwcomposer ++drm\_hwcomposer + ====== + +-Patches to drm_hwcomposer are very much welcome, we really want this to be the +-universal HW composer implementation for Android and similar platforms +-So please bring on porting patches, bugfixes, improvements for documentation +-and new features. ++Patches to drm\_hwcomposer are very much welcome, we really want this to be the ++universal HW composer implementation for Android and similar platforms. So ++please bring on porting patches, bugfixes, improvements for documentation and ++new features. + + A short list of contribution guidelines: +-* Submit changes via gitlab merge requests on gitlab.freedesktop.org +-* drm_hwcomposer is Apache 2.0 Licensed and we require contributions to follow the developer's certificate of origin: http://developercertificate.org/ +-* When submitting new code please follow the naming conventions documented in the generated documentation. Also please make full use of all the helpers and convenience macros provided by drm_hwcomposer. The below command can help you with formatting of your patches: +- +- `git diff | clang-format-diff-5.0 -p 1 -style=file` +-* Hardware specific changes should be tested on relevant platforms before committing. ++* Submit changes via gitlab merge requests on gitlab.freedesktop.org. ++* drm\_hwcomposer is Apache 2.0 Licensed and we require contributions to follow ++ the developer's certificate of origin: http://developercertificate.org/. ++* When submitting new code please follow the naming conventions documented in ++ the generated documentation. Also please make full use of all the helpers and ++ convenience macros provided by drm\_hwcomposer. The below command can help ++ you with formatting of your patches: + +-If you need inspiration, please checkout our [TODO issues](https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/issues?label_name%5B%5D=TODO) ++ ``` ++ git diff | clang-format-diff-11 -p 1 -style=file ++ ``` ++ ++* Hardware specific changes should be tested on relevant platforms before ++ committing. ++ ++If you need inspiration, please checkout our [TODO issues][1]. + + Happy hacking! ++ ++[1]: https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/issues?label_name%5B%5D=TODO +diff --git a/backend/Backend.cpp b/backend/Backend.cpp +new file mode 100644 +index 0000000..312faed +--- /dev/null ++++ b/backend/Backend.cpp +@@ -0,0 +1,172 @@ ++/* ++ * Copyright (C) 2020 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. ++ */ ++ ++#include "Backend.h" ++ ++#include ++ ++#include "BackendManager.h" ++#include "bufferinfo/BufferInfoGetter.h" ++ ++namespace android { ++ ++HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, ++ uint32_t *num_types, ++ uint32_t *num_requests) { ++ *num_types = 0; ++ *num_requests = 0; ++ ++ auto layers = display->GetOrderLayersByZPos(); ++ ++ int client_start = -1; ++ size_t client_size = 0; ++ ++ if (display->compositor().ShouldFlattenOnClient()) { ++ client_start = 0; ++ client_size = layers.size(); ++ MarkValidated(layers, client_start, client_size); ++ } else { ++ std::tie(client_start, client_size) = GetClientLayers(display, layers); ++ ++ MarkValidated(layers, client_start, client_size); ++ ++ bool testing_needed = !(client_start == 0 && client_size == layers.size()); ++ ++ if (testing_needed && ++ display->CreateComposition(true) != HWC2::Error::None) { ++ ++display->total_stats().failed_kms_validate_; ++ client_start = 0; ++ client_size = layers.size(); ++ MarkValidated(layers, 0, client_size); ++ } ++ } ++ ++ *num_types = client_size; ++ ++ display->total_stats().frames_flattened_ = display->compositor() ++ .GetFlattenedFramesCount(); ++ display->total_stats().gpu_pixops_ += CalcPixOps(layers, client_start, ++ client_size); ++ display->total_stats().total_pixops_ += CalcPixOps(layers, 0, layers.size()); ++ ++ return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; ++} ++ ++std::tuple Backend::GetClientLayers( ++ DrmHwcTwo::HwcDisplay *display, ++ const std::vector &layers) { ++ int client_start = -1; ++ size_t client_size = 0; ++ ++ for (int z_order = 0; z_order < layers.size(); ++z_order) { ++ if (IsClientLayer(display, layers[z_order])) { ++ if (client_start < 0) ++ client_start = (int)z_order; ++ client_size = (z_order - client_start) + 1; ++ } ++ } ++ ++ return GetExtraClientRange(display, layers, client_start, client_size); ++} ++ ++bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display, ++ DrmHwcTwo::HwcLayer *layer) { ++ return !HardwareSupportsLayerType(layer->sf_type()) || ++ !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) || ++ display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || ++ (layer->RequireScalingOrPhasing() && ++ display->resource_manager()->ForcedScalingWithGpu()); ++} ++ ++bool Backend::HardwareSupportsLayerType(HWC2::Composition comp_type) { ++ return comp_type == HWC2::Composition::Device || ++ comp_type == HWC2::Composition::Cursor; ++} ++ ++uint32_t Backend::CalcPixOps(const std::vector &layers, ++ size_t first_z, size_t size) { ++ uint32_t pixops = 0; ++ for (int 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]->display_frame(); ++ pixops += (df.right - df.left) * (df.bottom - df.top); ++ } ++ } ++ return pixops; ++} ++ ++void Backend::MarkValidated(std::vector &layers, ++ size_t client_first_z, size_t client_size) { ++ for (int z_order = 0; z_order < layers.size(); ++z_order) { ++ if (z_order >= client_first_z && z_order < client_first_z + client_size) ++ layers[z_order]->set_validated_type(HWC2::Composition::Client); ++ else ++ layers[z_order]->set_validated_type(HWC2::Composition::Device); ++ } ++} ++ ++std::tuple Backend::GetExtraClientRange( ++ DrmHwcTwo::HwcDisplay *display, ++ const std::vector &layers, int client_start, ++ size_t client_size) { ++ size_t avail_planes = display->primary_planes().size() + ++ display->overlay_planes().size(); ++ ++ /* ++ * If more layers then planes, save one plane ++ * for client composited layers ++ */ ++ if (avail_planes < display->layers().size()) ++ avail_planes--; ++ ++ int extra_client = int(layers.size() - client_size) - int(avail_planes); ++ ++ if (extra_client > 0) { ++ int start = 0; ++ size_t steps = 0; ++ if (client_size != 0) { ++ int prepend = std::min(client_start, extra_client); ++ int append = std::min(int(layers.size()) - ++ int(client_start + client_size), ++ extra_client); ++ start = client_start - (int)prepend; ++ client_size += extra_client; ++ steps = 1 + std::min(std::min(append, prepend), ++ int(layers.size()) - int(start + client_size)); ++ } else { ++ client_size = extra_client; ++ steps = 1 + layers.size() - extra_client; ++ } ++ ++ uint32_t gpu_pixops = INT_MAX; ++ for (int i = 0; i < steps; i++) { ++ uint32_t po = CalcPixOps(layers, start + i, client_size); ++ if (po < gpu_pixops) { ++ gpu_pixops = po; ++ client_start = start + i; ++ } ++ } ++ } ++ ++ return std::make_tuple(client_start, client_size); ++} ++ ++// clang-format off ++// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) ++REGISTER_BACKEND("generic", Backend); ++// clang-format on ++ ++} // namespace android +diff --git a/backend/Backend.h b/backend/Backend.h +new file mode 100644 +index 0000000..fc9a733 +--- /dev/null ++++ b/backend/Backend.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2020 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_BACKEND_H ++#define ANDROID_BACKEND_H ++ ++#include "DrmHwcTwo.h" ++ ++namespace android { ++ ++class Backend { ++ public: ++ virtual ~Backend() = default; ++ virtual HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, ++ uint32_t *num_types, ++ uint32_t *num_requests); ++ virtual std::tuple GetClientLayers( ++ DrmHwcTwo::HwcDisplay *display, ++ const std::vector &layers); ++ virtual bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, ++ DrmHwcTwo::HwcLayer *layer); ++ ++ protected: ++ bool HardwareSupportsLayerType(HWC2::Composition comp_type); ++ uint32_t CalcPixOps(const std::vector &layers, ++ size_t first_z, size_t size); ++ void MarkValidated(std::vector &layers, ++ size_t client_first_z, size_t client_size); ++ std::tuple GetExtraClientRange( ++ DrmHwcTwo::HwcDisplay *display, ++ const std::vector &layers, int client_start, ++ size_t client_size); ++}; ++} // namespace android ++ ++#endif +diff --git a/backend/BackendClient.cpp b/backend/BackendClient.cpp +new file mode 100644 +index 0000000..49963b8 +--- /dev/null ++++ b/backend/BackendClient.cpp +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2020 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. ++ */ ++ ++#include "BackendClient.h" ++ ++#include "BackendManager.h" ++ ++namespace android { ++ ++HWC2::Error BackendClient::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, ++ uint32_t *num_types, ++ uint32_t * /*num_requests*/) { ++ for (auto & [ layer_handle, layer ] : display->layers()) { ++ layer.set_validated_type(HWC2::Composition::Client); ++ ++*num_types; ++ } ++ return HWC2::Error::HasChanges; ++} ++ ++// clang-format off ++// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) ++REGISTER_BACKEND("client", BackendClient); ++// clang-format on ++ ++} // namespace android +diff --git a/backend/BackendClient.h b/backend/BackendClient.h +new file mode 100644 +index 0000000..13543f1 +--- /dev/null ++++ b/backend/BackendClient.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2020 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_BACKEND_CLIENT_H ++#define ANDROID_BACKEND_CLIENT_H ++ ++#include "Backend.h" ++ ++namespace android { ++ ++class BackendClient : public Backend { ++ public: ++ HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, ++ uint32_t *num_types, ++ uint32_t *num_requests) override; ++}; ++} // namespace android ++ ++#endif +diff --git a/backend/BackendManager.cpp b/backend/BackendManager.cpp +new file mode 100644 +index 0000000..7b89761 +--- /dev/null ++++ b/backend/BackendManager.cpp +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-backend" ++ ++#include "BackendManager.h" ++ ++#include "utils/log.h" ++#include "utils/properties.h" ++ ++namespace android { ++ ++// NOLINTNEXTLINE(cert-err58-cpp) ++const std::vector BackendManager::kClientDevices = { ++ "kirin", ++ "mediatek-drm", ++}; ++ ++BackendManager &BackendManager::GetInstance() { ++ static BackendManager backend_manager; ++ ++ return backend_manager; ++} ++ ++int BackendManager::RegisterBackend(const std::string &name, ++ backend_constructor_t backend_constructor) { ++ available_backends_[name] = std::move(backend_constructor); ++ return 0; ++} ++ ++int BackendManager::SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display) { ++ std::string driver_name(display->drm()->GetName()); ++ char backend_override[PROPERTY_VALUE_MAX]; ++ property_get("vendor.hwc.backend_override", backend_override, ++ driver_name.c_str()); ++ std::string backend_name(backend_override); ++ ++ display->set_backend(GetBackendByName(backend_name)); ++ if (!display->backend()) { ++ ALOGE("Failed to set backend '%s' for '%s' and driver '%s'", ++ backend_name.c_str(), display->connector()->name().c_str(), ++ driver_name.c_str()); ++ return -EINVAL; ++ } ++ ++ ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set", ++ backend_name.c_str(), display->connector()->name().c_str(), ++ driver_name.c_str()); ++ ++ return 0; ++} ++ ++std::unique_ptr BackendManager::GetBackendByName(std::string &name) { ++ if (available_backends_.empty()) { ++ ALOGE("No backends are specified"); ++ return nullptr; ++ } ++ ++ auto it = available_backends_.find(name); ++ if (it == available_backends_.end()) { ++ auto it = std::find(kClientDevices.begin(), kClientDevices.end(), name); ++ name = it == kClientDevices.end() ? "generic" : "client"; ++ } ++ ++ return available_backends_[name](); ++} ++} // namespace android +diff --git a/backend/BackendManager.h b/backend/BackendManager.h +new file mode 100644 +index 0000000..9b314db +--- /dev/null ++++ b/backend/BackendManager.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2020 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_BACKEND_MANAGER_H ++#define ANDROID_BACKEND_MANAGER_H ++ ++#include ++#include ++#include ++#include ++ ++#include "Backend.h" ++ ++#define REGISTER_BACKEND(name_str_, backend_) \ ++ static int \ ++ backend = BackendManager::GetInstance() \ ++ .RegisterBackend(name_str_, \ ++ []() -> std::unique_ptr { \ ++ return std::make_unique(); \ ++ }); ++ ++namespace android { ++ ++class BackendManager { ++ public: ++ using backend_constructor_t = std::function()>; ++ static BackendManager &GetInstance(); ++ int RegisterBackend(const std::string &name, ++ backend_constructor_t backend_constructor); ++ int SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display); ++ std::unique_ptr GetBackendByName(std::string &name); ++ HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, ++ uint32_t *num_types, uint32_t *num_requests); ++ ++ private: ++ BackendManager() = default; ++ ++ static const std::vector kClientDevices; ++ ++ std::map available_backends_; ++}; ++} // namespace android ++ ++#endif +diff --git a/backend/BackendRCarDu.cpp b/backend/BackendRCarDu.cpp +new file mode 100644 +index 0000000..b012797 +--- /dev/null ++++ b/backend/BackendRCarDu.cpp +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2020 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. ++ */ ++ ++#include "BackendRCarDu.h" ++ ++#include "BackendManager.h" ++#include "bufferinfo/BufferInfoGetter.h" ++#include "drm_fourcc.h" ++ ++namespace android { ++ ++bool BackendRCarDu::IsClientLayer(DrmHwcTwo::HwcDisplay *display, ++ DrmHwcTwo::HwcLayer *layer) { ++ hwc_drm_bo_t bo; ++ ++ int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(layer->buffer(), ++ &bo); ++ if (ret) ++ return true; ++ ++ if (bo.format == DRM_FORMAT_ABGR8888) ++ return true; ++ ++ if (layer->RequireScalingOrPhasing()) ++ return true; ++ ++ return Backend::IsClientLayer(display, layer); ++} ++ ++// clang-format off ++// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp) ++REGISTER_BACKEND("rcar-du", BackendRCarDu); ++// clang-format on ++ ++} // namespace android +\ No newline at end of file +diff --git a/backend/BackendRCarDu.h b/backend/BackendRCarDu.h +new file mode 100644 +index 0000000..8a1011a +--- /dev/null ++++ b/backend/BackendRCarDu.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (C) 2020 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 HWC_DISPLAY_BACKEND_RCAR_DU_H ++#define HWC_DISPLAY_BACKEND_RCAR_DU_H ++ ++#include "Backend.h" ++ ++namespace android { ++ ++class BackendRCarDu : public Backend { ++ public: ++ bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, ++ DrmHwcTwo::HwcLayer *layer) override; ++}; ++} // namespace android ++ ++#endif +diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp +new file mode 100644 +index 0000000..7f7f8ae +--- /dev/null ++++ b/bufferinfo/BufferInfoGetter.cpp +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-buffer-info-getter" ++ ++#include "BufferInfoGetter.h" ++ ++#if PLATFORM_SDK_VERSION >= 30 ++#include "BufferInfoMapperMetadata.h" ++#endif ++ ++#include ++#include ++ ++#include "utils/log.h" ++#include "utils/properties.h" ++ ++namespace android { ++ ++BufferInfoGetter *BufferInfoGetter::GetInstance() { ++ static std::unique_ptr inst; ++ if (inst == nullptr) { ++#if PLATFORM_SDK_VERSION >= 30 ++ inst.reset(BufferInfoMapperMetadata::CreateInstance()); ++ if (inst == nullptr) { ++ ALOGW( ++ "Generic buffer getter is not available. Falling back to legacy..."); ++#endif ++ inst = LegacyBufferInfoGetter::CreateInstance(); ++#if PLATFORM_SDK_VERSION >= 30 ++ } ++#endif ++ } ++ ++ 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; ++ } ++ if (bo.prime_fds[0] == 0) { ++ return false; ++ } ++ return true; ++} ++ ++int LegacyBufferInfoGetter::Init() { ++ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, ++ (const hw_module_t **)&gralloc_); ++ if (ret) { ++ ALOGE("Failed to open gralloc module"); ++ return ret; ++ } ++ ++ ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, ++ gralloc_->common.author); ++ ++ return 0; ++} ++ ++uint32_t LegacyBufferInfoGetter::ConvertHalFormatToDrm(uint32_t hal_format) { ++ switch (hal_format) { ++ case HAL_PIXEL_FORMAT_RGB_888: ++ return DRM_FORMAT_BGR888; ++ case HAL_PIXEL_FORMAT_BGRA_8888: ++ return DRM_FORMAT_ARGB8888; ++ case HAL_PIXEL_FORMAT_RGBX_8888: ++ return DRM_FORMAT_XBGR8888; ++ case HAL_PIXEL_FORMAT_RGBA_8888: ++ return DRM_FORMAT_ABGR8888; ++ case HAL_PIXEL_FORMAT_RGB_565: ++ return DRM_FORMAT_BGR565; ++ case HAL_PIXEL_FORMAT_YV12: ++ return DRM_FORMAT_YVU420; ++ case HAL_PIXEL_FORMAT_RGBA_1010102: ++ return DRM_FORMAT_ABGR2101010; ++ default: ++ ALOGE("Cannot convert hal format to drm format %u", hal_format); ++ return DRM_FORMAT_INVALID; ++ } ++} ++ ++bool BufferInfoGetter::IsDrmFormatRgb(uint32_t drm_format) { ++ switch (drm_format) { ++ case DRM_FORMAT_ARGB8888: ++ case DRM_FORMAT_XBGR8888: ++ case DRM_FORMAT_ABGR8888: ++ case DRM_FORMAT_BGR888: ++ case DRM_FORMAT_BGR565: ++ case DRM_FORMAT_ABGR2101010: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++__attribute__((weak)) std::unique_ptr ++LegacyBufferInfoGetter::CreateInstance() { ++ ALOGE("No legacy buffer info getters available"); ++ return nullptr; ++} ++ ++} // namespace android +diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h +new file mode 100644 +index 0000000..60ca985 +--- /dev/null ++++ b/bufferinfo/BufferInfoGetter.h +@@ -0,0 +1,79 @@ ++/* ++ * Copyright (C) 2020 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_BUFFERINFOGETTER_H_ ++#define ANDROID_BUFFERINFOGETTER_H_ ++ ++#include ++#include ++ ++#include "drm/DrmDevice.h" ++#include "drmhwcgralloc.h" ++ ++#ifndef DRM_FORMAT_INVALID ++#define DRM_FORMAT_INVALID 0 ++#endif ++ ++namespace android { ++ ++class BufferInfoGetter { ++ public: ++ virtual ~BufferInfoGetter() { ++ } ++ ++ virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; ++ ++ bool IsHandleUsable(buffer_handle_t handle); ++ ++ static BufferInfoGetter *GetInstance(); ++ ++ static bool IsDrmFormatRgb(uint32_t drm_format); ++}; ++ ++class LegacyBufferInfoGetter : public BufferInfoGetter { ++ public: ++ using BufferInfoGetter::BufferInfoGetter; ++ ++ int Init(); ++ ++ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override = 0; ++ ++ static std::unique_ptr CreateInstance(); ++ ++ static uint32_t ConvertHalFormatToDrm(uint32_t hal_format); ++ const gralloc_module_t *gralloc_; ++}; ++ ++#ifdef DISABLE_LEGACY_GETTERS ++#define LEGACY_BUFFER_INFO_GETTER(getter_) ++#else ++#define LEGACY_BUFFER_INFO_GETTER(getter_) \ ++ std::unique_ptr \ ++ LegacyBufferInfoGetter::CreateInstance() { \ ++ auto instance = std::make_unique(); \ ++ if (instance) { \ ++ int ret = instance->Init(); \ ++ if (ret) { \ ++ ALOGE("Failed to initialize the " #getter_ " getter %d", ret); \ ++ instance.reset(); \ ++ } \ ++ } \ ++ return std::move(instance); \ ++ } ++#endif ++ ++} // namespace android ++#endif +diff --git a/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp +new file mode 100644 +index 0000000..23a9072 +--- /dev/null ++++ b/bufferinfo/BufferInfoMapperMetadata.cpp +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2020 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. ++ */ ++ ++#if PLATFORM_SDK_VERSION >= 30 ++ ++#define LOG_TAG "hwc-bufferinfo-mappermetadata" ++ ++#include "BufferInfoMapperMetadata.h" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "utils/log.h" ++ ++namespace android { ++ ++BufferInfoGetter *BufferInfoMapperMetadata::CreateInstance() { ++ if (GraphicBufferMapper::getInstance().getMapperVersion() < ++ GraphicBufferMapper::GRALLOC_4) ++ return nullptr; ++ ++ return new BufferInfoMapperMetadata(); ++} ++ ++/* The implementation below makes assumptions on the order and number of file ++ * descriptors that Gralloc places in the native_handle_t and as such it very ++ * likely needs to be adapted to match the particular Gralloc implementation ++ * used in the system. For this reason it is been declared as a weak symbol, ++ * so that it can be overridden. ++ */ ++int __attribute__((weak)) ++BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { ++ int num_fds = handle->numFds; ++ ++ if (num_fds >= 1 && num_fds <= 2) { ++ if (IsDrmFormatRgb(bo->format)) { ++ bo->prime_fds[0] = handle->data[0]; ++ } else { ++ bo->prime_fds[0] = bo->prime_fds[1] = bo->prime_fds[2] = handle->data[0]; ++ } ++ if (bo->prime_fds[0] <= 0) { ++ ALOGE("Encountered invalid fd %d", bo->prime_fds[0]); ++ return android::BAD_VALUE; ++ } ++ ++ } else if (num_fds >= 3) { ++ bo->prime_fds[0] = handle->data[0]; ++ bo->prime_fds[1] = handle->data[1]; ++ bo->prime_fds[2] = handle->data[2]; ++ for (int i = 0; i < 3; i++) { ++ if (bo->prime_fds[i] <= 0) { ++ ALOGE("Encountered invalid fd %d", bo->prime_fds[i]); ++ return android::BAD_VALUE; ++ } ++ } ++ } ++ return 0; ++} ++ ++int BufferInfoMapperMetadata::ConvertBoInfo(buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ GraphicBufferMapper &mapper = GraphicBufferMapper::getInstance(); ++ if (!handle) ++ return -EINVAL; ++ ++ uint64_t usage = 0; ++ int err = mapper.getUsage(handle, &usage); ++ if (err) { ++ ALOGE("Failed to get usage err=%d", err); ++ return err; ++ } ++ bo->usage = static_cast(usage); ++ ++ ui::PixelFormat hal_format; ++ err = mapper.getPixelFormatRequested(handle, &hal_format); ++ if (err) { ++ ALOGE("Failed to get HAL Pixel Format err=%d", err); ++ return err; ++ } ++ bo->hal_format = static_cast(hal_format); ++ ++ err = mapper.getPixelFormatFourCC(handle, &bo->format); ++ if (err) { ++ ALOGE("Failed to get FourCC format err=%d", err); ++ return err; ++ } ++ ++ err = mapper.getPixelFormatModifier(handle, &bo->modifiers[0]); ++ if (err) { ++ ALOGE("Failed to get DRM Modifier err=%d", err); ++ return err; ++ } ++ ++ uint64_t width = 0; ++ err = mapper.getWidth(handle, &width); ++ if (err) { ++ ALOGE("Failed to get Width err=%d", err); ++ return err; ++ } ++ bo->width = static_cast(width); ++ ++ uint64_t height = 0; ++ err = mapper.getHeight(handle, &height); ++ if (err) { ++ ALOGE("Failed to get Height err=%d", err); ++ return err; ++ } ++ bo->height = static_cast(height); ++ ++ std::vector layouts; ++ err = mapper.getPlaneLayouts(handle, &layouts); ++ if (err) { ++ ALOGE("Failed to get Plane Layouts err=%d", err); ++ return err; ++ } ++ ++ 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; ++ } ++ ++ return GetFds(handle, bo); ++} ++ ++} // namespace android ++ ++#endif +diff --git a/bufferinfo/BufferInfoMapperMetadata.h b/bufferinfo/BufferInfoMapperMetadata.h +new file mode 100644 +index 0000000..d335705 +--- /dev/null ++++ b/bufferinfo/BufferInfoMapperMetadata.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2020 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 PLATFORMIMAGINATION_H ++#define PLATFORMIMAGINATION_H ++ ++#include "bufferinfo/BufferInfoGetter.h" ++ ++namespace android { ++ ++class BufferInfoMapperMetadata : public BufferInfoGetter { ++ public: ++ using BufferInfoGetter::BufferInfoGetter; ++ ++ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; ++ ++ int GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo); ++ ++ static BufferInfoGetter *CreateInstance(); ++}; ++} // namespace android ++ ++#endif // PLATFORMIMAGINATION_H +diff --git a/platform/platformimagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp +similarity index 50% +rename from platform/platformimagination.cpp +rename to bufferinfo/legacy/BufferInfoImagination.cpp +index bd4a4c3..d646072 100644 +--- a/platform/platformimagination.cpp ++++ b/bufferinfo/legacy/BufferInfoImagination.cpp +@@ -1,30 +1,35 @@ +-#define LOG_TAG "hwc-platform-imagination" ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-imagination" ++ ++#include "BufferInfoImagination.h" + +-#include "platformimagination.h" +-#include + #include + + #include "img_gralloc1_public.h" ++#include "utils/log.h" + + namespace android { + +-Importer *Importer::CreateInstance(DrmDevice *drm) { +- ImaginationImporter *importer = new ImaginationImporter(drm); +- if (!importer) +- return NULL; +- +- int ret = importer->Init(); +- if (ret) { +- ALOGE("Failed to initialize the Imagination importer %d", ret); +- delete importer; +- return NULL; +- } +- return importer; +-} ++LEGACY_BUFFER_INFO_GETTER(BufferInfoImagination); + +-int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, +- hwc_drm_bo_t *bo) { +- IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle; ++int BufferInfoImagination::ConvertBoInfo(buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ auto *hnd = (IMG_native_handle_t *)handle; + if (!hnd) + return -EINVAL; + +@@ -40,7 +45,6 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, + bo->prime_fds[0] = hnd->fd[0]; + bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3; + bo->hal_format = hnd->iFormat; +- bo->pixel_stride = hnd->aiStride[0]; + + switch (hnd->iFormat) { + #ifdef HAL_PIXEL_FORMAT_BGRX_8888 +@@ -59,9 +63,4 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, + return 0; + } + +-std::unique_ptr Planner::CreateInstance(DrmDevice *) { +- std::unique_ptr planner(new Planner); +- planner->AddStage(); +- return planner; +-} + } // namespace android +diff --git a/bufferinfo/legacy/BufferInfoImagination.h b/bufferinfo/legacy/BufferInfoImagination.h +new file mode 100644 +index 0000000..765b279 +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoImagination.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2020 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 BUFFERINFOIMAGINATION_H ++#define BUFFERINFOIMAGINATION_H ++ ++#include ++ ++#include "bufferinfo/BufferInfoGetter.h" ++ ++namespace android { ++ ++class BufferInfoImagination : public LegacyBufferInfoGetter { ++ public: ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; ++ ++ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; ++}; ++} // namespace android ++ ++#endif // PLATFORMIMAGINATION_H +diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp +new file mode 100644 +index 0000000..52f792f +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp +@@ -0,0 +1,205 @@ ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-libdrm" ++ ++#include "BufferInfoLibdrm.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "utils/log.h" ++#include "utils/properties.h" ++ ++namespace android { ++ ++LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm); ++ ++enum chroma_order { ++ kYCbCr, ++ kYCrCb, ++}; ++ ++struct DroidYuvFormat { ++ /* Lookup keys */ ++ int native; /* HAL_PIXEL_FORMAT_ */ ++ enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */ ++ int chroma_step; /* Distance in bytes between subsequent chroma pixels. */ ++ ++ /* Result */ ++ int fourcc; /* DRM_FORMAT_ */ ++}; ++ ++/* The following table is used to look up a DRI image FourCC based ++ * on native format and information contained in android_ycbcr struct. */ ++static const struct DroidYuvFormat kDroidYuvFormats[] = { ++ /* Native format, YCrCb, Chroma step, DRI image FourCC */ ++ {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 2, DRM_FORMAT_NV12}, ++ {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 1, DRM_FORMAT_YUV420}, ++ {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCrCb, 1, DRM_FORMAT_YVU420}, ++ {HAL_PIXEL_FORMAT_YV12, kYCrCb, 1, DRM_FORMAT_YVU420}, ++ /* HACK: See droid_create_image_from_prime_fds() and ++ * https://issuetracker.google.com/32077885. */ ++ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 2, DRM_FORMAT_NV12}, ++ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 1, DRM_FORMAT_YUV420}, ++ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_YVU420}, ++ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_AYUV}, ++ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_XYUV8888}, ++}; ++ ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++ ++static int get_fourcc_yuv(int native, enum chroma_order chroma_order, ++ int chroma_step) { ++ for (auto droid_yuv_format : kDroidYuvFormats) ++ if (droid_yuv_format.native == native && ++ droid_yuv_format.chroma_order == chroma_order && ++ droid_yuv_format.chroma_step == chroma_step) ++ return droid_yuv_format.fourcc; ++ ++ return -1; ++} ++ ++static bool is_yuv(int native) { ++ for (auto droid_yuv_format : kDroidYuvFormats) ++ if (droid_yuv_format.native == native) ++ return true; ++ ++ return false; ++} ++ ++bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ struct android_ycbcr ycbcr {}; ++ enum chroma_order chroma_order {}; ++ int ret = 0; ++ ++ if (!gralloc_->lock_ycbcr) { ++ static std::once_flag once; ++ std::call_once(once, ++ []() { ALOGW("Gralloc does not support lock_ycbcr()"); }); ++ return false; ++ } ++ ++ memset(&ycbcr, 0, sizeof(ycbcr)); ++ ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr); ++ if (ret) { ++ ALOGW("gralloc->lock_ycbcr failed: %d", ret); ++ return false; ++ } ++ gralloc_->unlock(gralloc_, handle); ++ ++ /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags ++ * it will return the .y/.cb/.cr pointers based on a NULL pointer, ++ * so they can be interpreted as offsets. */ ++ bo->offsets[0] = (size_t)ycbcr.y; ++ /* We assume here that all the planes are located in one DMA-buf. */ ++ if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) { ++ chroma_order = kYCrCb; ++ bo->offsets[1] = (size_t)ycbcr.cr; ++ bo->offsets[2] = (size_t)ycbcr.cb; ++ } else { ++ chroma_order = kYCbCr; ++ bo->offsets[1] = (size_t)ycbcr.cb; ++ bo->offsets[2] = (size_t)ycbcr.cr; ++ } ++ ++ /* .ystride is the line length (in bytes) of the Y plane, ++ * .cstride is the line length (in bytes) of any of the remaining ++ * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully ++ * planar formats. */ ++ bo->pitches[0] = ycbcr.ystride; ++ bo->pitches[1] = bo->pitches[2] = ycbcr.cstride; ++ ++ /* .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); ++ if (bo->format == -1) { ++ ALOGW( ++ "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = " ++ "%d", ++ bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb", ++ (int)ycbcr.chroma_step); ++ return false; ++ } ++ ++ /* ++ * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that ++ * the single-fd case cannot happen. So handle eithe single ++ * fd or fd-per-plane case: ++ */ ++ if (num_fds == 1) { ++ bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0]; ++ } else { ++ int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3; ++ if (num_fds != expected_planes) ++ return false; ++ } ++ ++ return true; ++} ++ ++int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ++ gralloc_handle_t *gr_handle = gralloc_handle(handle); ++ if (!gr_handle) ++ return -EINVAL; ++ ++ bo->width = gr_handle->width; ++ bo->height = gr_handle->height; ++ bo->hal_format = gr_handle->format; ++ ++#if GRALLOC_HANDLE_VERSION < 4 ++ static std::once_flag once; ++ std::call_once(once, []() { ++ ALOGE( ++ "libdrm < v2.4.97 has broken gralloc_handle structure. Please update."); ++ }); ++#endif ++#if GRALLOC_HANDLE_VERSION == 4 ++ bo->modifiers[0] = gr_handle->modifier; ++#endif ++ ++ bo->usage = gr_handle->usage; ++ bo->prime_fds[0] = gr_handle->prime_fd; ++ ++ if (is_yuv(gr_handle->format)) { ++ if (!GetYuvPlaneInfo(handle->numFds, handle, bo)) ++ return -EINVAL; ++ } else { ++ bo->pitches[0] = gr_handle->stride; ++ bo->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) { ++ case HAL_PIXEL_FORMAT_RGB_565: ++ bo->format = DRM_FORMAT_RGB565; ++ break; ++ default: ++ bo->format = ConvertHalFormatToDrm(gr_handle->format); ++ } ++ ++ if (bo->format == DRM_FORMAT_INVALID) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++} // namespace android +diff --git a/bufferinfo/legacy/BufferInfoLibdrm.h b/bufferinfo/legacy/BufferInfoLibdrm.h +new file mode 100644 +index 0000000..4d37d00 +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoLibdrm.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2020 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 BUFFERINFOLIBDRM_H_ ++#define BUFFERINFOLIBDRM_H_ ++ ++#include ++ ++#include "bufferinfo/BufferInfoGetter.h" ++ ++namespace android { ++ ++class BufferInfoLibdrm : public LegacyBufferInfoGetter { ++ public: ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; ++ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; ++ ++ private: ++ bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo); ++}; ++ ++} // namespace android ++ ++#endif +diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.cpp b/bufferinfo/legacy/BufferInfoMaliHisi.cpp +new file mode 100644 +index 0000000..5fc413a +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoMaliHisi.cpp +@@ -0,0 +1,125 @@ ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-hisi" ++ ++#include "BufferInfoMaliHisi.h" ++ ++#include ++#include ++ ++#include ++ ++#include "gralloc_priv.h" ++#include "utils/log.h" ++ ++#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) ++ ++namespace android { ++ ++LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliHisi); ++ ++#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ ++ defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) ++uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers(uint64_t flags, ++ bool is_rgb) { ++ uint64_t features = 0UL; ++ ++ if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) ++ features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; ++ ++ if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) ++ features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); ++ ++ if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) ++ features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; ++ ++ if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) ++ features |= AFBC_FORMAT_MOD_TILED; ++ ++ if (features) { ++ if (is_rgb) ++ features |= AFBC_FORMAT_MOD_YTR; ++ ++ return DRM_FORMAT_MOD_ARM_AFBC(features); ++ } ++ ++ return 0; ++} ++#else ++uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers( ++ uint64_t /* flags */, bool /* is_rgb */) { ++ return 0; ++} ++#endif ++ ++int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ bool is_rgb = false; ++ ++ const auto *hnd = (private_handle_t const *)handle; ++ if (!hnd) ++ return -EINVAL; ++ ++ if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) ++ return -EINVAL; ++ ++ uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); ++ if (fmt == DRM_FORMAT_INVALID) ++ return -EINVAL; ++ ++ 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; ++ ++ switch (fmt) { ++ case DRM_FORMAT_YVU420: { ++ int align = 128; ++ if (hnd->usage & ++ (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) ++ align = 16; ++ int adjusted_height = MALI_ALIGN(hnd->height, 2); ++ int y_size = adjusted_height * hnd->byte_stride; ++ int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); ++ 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; ++ /* U plane */ ++ bo->prime_fds[2] = hnd->share_fd; ++ bo->pitches[2] = vu_stride; ++ bo->offsets[2] = y_size + v_size; ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++} // namespace android +diff --git a/platform/platformhisi.h b/bufferinfo/legacy/BufferInfoMaliHisi.h +similarity index 69% +rename from platform/platformhisi.h +rename to bufferinfo/legacy/BufferInfoMaliHisi.h +index f127bdb..698a0d3 100644 +--- a/platform/platformhisi.h ++++ b/bufferinfo/legacy/BufferInfoMaliHisi.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2015 The Android Open Source Project ++ * Copyright (C) 2020 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. +@@ -14,29 +14,23 @@ + * limitations under the License. + */ + +-#ifndef ANDROID_PLATFORM_HISI_H_ +-#define ANDROID_PLATFORM_HISI_H_ +- +-#include "drmdevice.h" +-#include "platform.h" +-#include "platformdrmgeneric.h" +- +-#include ++#ifndef BUFFERINFOMALIHISI_H_ ++#define BUFFERINFOMALIHISI_H_ + + #include + ++#include "bufferinfo/BufferInfoGetter.h" ++ + namespace android { + +-class HisiImporter : public DrmGenericImporter { ++class BufferInfoMaliHisi : public LegacyBufferInfoGetter { + public: +- using DrmGenericImporter::DrmGenericImporter; ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + + private: + uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb); +- +- bool IsDrmFormatRgb(uint32_t drm_format); + }; + } // namespace android + +diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp +new file mode 100644 +index 0000000..7e6f3a8 +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-mediatek" ++ ++#include "BufferInfoMaliMediatek.h" ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "gralloc_priv.h" ++#include "utils/log.h" ++ ++namespace android { ++ ++LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMediatek); ++ ++int BufferInfoMaliMediatek::ConvertBoInfo(buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ const auto *hnd = (private_handle_t const *)handle; ++ if (!hnd) ++ return -EINVAL; ++ ++ 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; ++} ++ ++} // namespace android +diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.h b/bufferinfo/legacy/BufferInfoMaliMediatek.h +new file mode 100644 +index 0000000..1204818 +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoMaliMediatek.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2020 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 BUFFERINFOMALIMTK_H_ ++#define BUFFERINFOMALIMTK_H_ ++ ++#include ++ ++#include "bufferinfo/BufferInfoGetter.h" ++ ++namespace android { ++ ++class BufferInfoMaliMediatek : public LegacyBufferInfoGetter { ++ public: ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; ++ ++ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; ++}; ++} // namespace android ++ ++#endif +diff --git a/platform/platformmeson.cpp b/bufferinfo/legacy/BufferInfoMaliMeson.cpp +similarity index 63% +rename from platform/platformmeson.cpp +rename to bufferinfo/legacy/BufferInfoMaliMeson.cpp +index ad3aff1..9daf542 100644 +--- a/platform/platformmeson.cpp ++++ b/bufferinfo/legacy/BufferInfoMaliMeson.cpp +@@ -14,40 +14,26 @@ + * limitations under the License. + */ + +-#define LOG_TAG "hwc-platform-meson" ++#define LOG_TAG "hwc-bufferinfo-mali-meson" + +-#include "platformmeson.h" +-#include "drmdevice.h" +-#include "platform.h" ++#include "BufferInfoMaliMeson.h" + +-#include + #include + #include ++ + #include + +-#include +-#include + #include "gralloc_priv.h" ++#include "utils/log.h" + + namespace android { + +-Importer *Importer::CreateInstance(DrmDevice *drm) { +- MesonImporter *importer = new MesonImporter(drm); +- if (!importer) +- return NULL; +- +- int ret = importer->Init(); +- if (ret) { +- ALOGE("Failed to initialize the meson importer %d", ret); +- delete importer; +- return NULL; +- } +- return importer; +-} ++LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMeson); + + #if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ + defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) +-uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { ++uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( ++ uint64_t flags) { + uint64_t features = 0UL; + + if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) { +@@ -69,15 +55,15 @@ uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { + return 0; + } + #else +-uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers( ++uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( + uint64_t /* flags */) { + return 0; + } + #endif + +-int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { +- private_handle_t const *hnd = reinterpret_cast( +- handle); ++int BufferInfoMaliMeson::ConvertBoInfo(buffer_handle_t handle, ++ hwc_drm_bo_t *bo) { ++ const auto *hnd = (private_handle_t const *)handle; + if (!hnd) + return -EINVAL; + +@@ -88,7 +74,7 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { + if (fmt == DRM_FORMAT_INVALID) + return -EINVAL; + +- bo->modifiers[0] = MesonImporter::ConvertGrallocFormatToDrmModifiers( ++ bo->modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( + hnd->internal_format); + + bo->width = hnd->width; +@@ -96,19 +82,11 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { + bo->hal_format = hnd->req_format; + bo->format = fmt; + bo->usage = hnd->usage; +- bo->pixel_stride = hnd->stride; + bo->prime_fds[0] = hnd->share_fd; + bo->pitches[0] = hnd->byte_stride; + bo->offsets[0] = 0; + +- bo->with_modifiers = true; +- + return 0; + } + +-std::unique_ptr Planner::CreateInstance(DrmDevice *) { +- std::unique_ptr planner(new Planner); +- planner->AddStage(); +- return planner; +-} + } // namespace android +diff --git a/platform/platformmeson.h b/bufferinfo/legacy/BufferInfoMaliMeson.h +similarity index 76% +rename from platform/platformmeson.h +rename to bufferinfo/legacy/BufferInfoMaliMeson.h +index f29b796..ce5d3f9 100644 +--- a/platform/platformmeson.h ++++ b/bufferinfo/legacy/BufferInfoMaliMeson.h +@@ -14,23 +14,18 @@ + * limitations under the License. + */ + +-#ifndef ANDROID_PLATFORM_HISI_H_ +-#define ANDROID_PLATFORM_HISI_H_ +- +-#include "drmdevice.h" +-#include "platform.h" +-#include "platformdrmgeneric.h" +- +-#include ++#ifndef BUFFERINFOMALIHISI_H_ ++#define BUFFERINFOMALIHISI_H_ + + #include + ++#include "bufferinfo/BufferInfoGetter.h" ++ + namespace android { + +-class MesonImporter : public DrmGenericImporter { ++class BufferInfoMaliMeson : public LegacyBufferInfoGetter { + public: +- using DrmGenericImporter::DrmGenericImporter; +- ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + + private: +diff --git a/bufferinfo/legacy/BufferInfoMinigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp +new file mode 100644 +index 0000000..d030dff +--- /dev/null ++++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2018 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 LOG_TAG "hwc-bufferinfo-minigbm" ++ ++#include "BufferInfoMinigbm.h" ++ ++#include ++#include ++ ++#include "cros_gralloc_handle.h" ++#include "utils/log.h" ++ ++#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7') ++ ++namespace android { ++ ++LEGACY_BUFFER_INFO_GETTER(BufferInfoMinigbm); ++ ++int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { ++ auto *gr_handle = (cros_gralloc_handle *)handle; ++ if (!gr_handle) ++ return -EINVAL; ++ ++ bo->width = gr_handle->width; ++ bo->height = gr_handle->height; ++ bo->hal_format = gr_handle->droid_format; ++ ++ bo->format = gr_handle->format; ++ if (bo->format == DRM_FORMAT_YVU420_ANDROID) ++ bo->format = DRM_FORMAT_YVU420; ++ ++ bo->usage = gr_handle->usage; ++ ++ for (int i = 0; i < gr_handle->num_planes; i++) { ++ bo->modifiers[i] = gr_handle->format_modifier; ++ bo->prime_fds[i] = gr_handle->fds[i]; ++ bo->pitches[i] = gr_handle->strides[i]; ++ bo->offsets[i] = gr_handle->offsets[i]; ++ } ++ ++ return 0; ++} ++ ++} // namespace android +diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h +similarity index 75% +rename from platform/platformminigbm.h +rename to bufferinfo/legacy/BufferInfoMinigbm.h +index 053b2aa..bff9d74 100644 +--- a/platform/platformminigbm.h ++++ b/bufferinfo/legacy/BufferInfoMinigbm.h +@@ -14,20 +14,18 @@ + * limitations under the License. + */ + +-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_ +-#define ANDROID_PLATFORM_DRM_MINIGBM_H_ +- +-#include "drmdevice.h" +-#include "platform.h" +-#include "platformdrmgeneric.h" ++#ifndef BUFFERINFOMINIGBM_H_ ++#define BUFFERINFOMINIGBM_H_ + + #include + ++#include "bufferinfo/BufferInfoGetter.h" ++ + namespace android { + +-class DrmMinigbmImporter : public DrmGenericImporter { ++class BufferInfoMinigbm : public LegacyBufferInfoGetter { + public: +- using DrmGenericImporter::DrmGenericImporter; ++ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; + int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; + }; + +diff --git a/compositor/drmdisplaycomposition.cpp b/compositor/DrmDisplayComposition.cpp +similarity index 87% +rename from compositor/drmdisplaycomposition.cpp +rename to compositor/DrmDisplayComposition.cpp +index b710fe1..13760ef 100644 +--- a/compositor/drmdisplaycomposition.cpp ++++ b/compositor/DrmDisplayComposition.cpp +@@ -16,37 +16,25 @@ + + #define LOG_TAG "hwc-drm-display-composition" + +-#include "drmdisplaycomposition.h" +-#include "drmcrtc.h" +-#include "drmdevice.h" +-#include "drmdisplaycompositor.h" +-#include "drmplane.h" +-#include "platform.h" ++#include "DrmDisplayComposition.h" + +-#include ++#include ++#include + + #include ++#include + #include + +-#include +-#include +-#include ++#include "DrmDisplayCompositor.h" ++#include "Planner.h" ++#include "drm/DrmDevice.h" ++#include "utils/log.h" + + namespace android { + +-DrmDisplayComposition::~DrmDisplayComposition() { +-} +- +-int DrmDisplayComposition::Init(DrmDevice *drm, DrmCrtc *crtc, +- Importer *importer, Planner *planner, +- uint64_t frame_no) { +- drm_ = drm; +- crtc_ = crtc; // Can be NULL if we haven't modeset yet +- importer_ = importer; +- planner_ = planner; +- frame_no_ = frame_no; +- +- return 0; ++DrmDisplayComposition::DrmDisplayComposition(DrmCrtc *crtc, Planner *planner) ++ : crtc_(crtc), // Can be NULL if we haven't modeset yet ++ planner_(planner) { + } + + bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) { +@@ -77,8 +65,10 @@ int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) { + } + + int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) { +- if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET)) ++ if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET)) { ++ ALOGE("SetDisplayMode() Failed to validate composition type"); + return -EINVAL; ++ } + display_mode_ = display_mode; + dpms_mode_ = DRM_MODE_DPMS_ON; + type_ = DRM_COMPOSITION_TYPE_MODESET; +@@ -86,8 +76,7 @@ int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) { + } + + int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) { +- composition_planes_.emplace_back(DrmCompositionPlane::Type::kDisable, plane, +- crtc_); ++ composition_planes_.emplace_back(DrmCompositionPlane::Type::kDisable, plane); + return 0; + } + +@@ -106,7 +95,7 @@ int DrmDisplayComposition::Plan(std::vector *primary_planes, + for (size_t i = 0; i < layers_.size(); ++i) + to_composite.emplace(std::make_pair(i, &layers_[i])); + +- int ret; ++ int ret = 0; + std::tie(ret, + composition_planes_) = planner_->ProvisionPlanes(to_composite, crtc_, + primary_planes, +@@ -125,7 +114,7 @@ int DrmDisplayComposition::Plan(std::vector *primary_planes, + // make sure that source layers are ordered based on zorder + std::sort(i.source_layers().begin(), i.source_layers().end()); + +- std::vector *container; ++ std::vector *container = nullptr; + if (i.plane()->type() == DRM_PLANE_TYPE_PRIMARY) + container = primary_planes; + else +@@ -167,14 +156,10 @@ static const char *DPMSModeToString(int dpms_mode) { + } + } + +-static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) { +- if (!buffer) { +- *out << "buffer="; +- return; +- } +- ++static void DumpBuffer(const DrmHwcLayer &layer, std::ostringstream *out) { + *out << "buffer[w/h/format]="; +- *out << buffer->width << "/" << buffer->height << "/" << buffer->format; ++ *out << layer.buffer_info.width << "/" << layer.buffer_info.height << "/" ++ << layer.buffer_info.format; + } + + static void DumpTransform(uint32_t transform, std::ostringstream *out) { +@@ -213,7 +198,7 @@ static void DumpTransform(uint32_t transform, std::ostringstream *out) { + separator = true; + } + +- uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipH | ++ uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipV | + DrmHwcTransform::kRotate90 | + DrmHwcTransform::kRotate180 | + DrmHwcTransform::kRotate270; +@@ -260,7 +245,7 @@ void DrmDisplayComposition::Dump(std::ostringstream *out) const { + const DrmHwcLayer &layer = layers_[i]; + *out << " [" << i << "] "; + +- DumpBuffer(layer.buffer, out); ++ DumpBuffer(layer, out); + + if (layer.protected_usage()) + *out << " protected"; +diff --git a/include/drmdisplaycomposition.h b/compositor/DrmDisplayComposition.h +similarity index 70% +rename from include/drmdisplaycomposition.h +rename to compositor/DrmDisplayComposition.h +index 2a5b1a4..1738630 100644 +--- a/include/drmdisplaycomposition.h ++++ b/compositor/DrmDisplayComposition.h +@@ -17,21 +17,20 @@ + #ifndef ANDROID_DRM_DISPLAY_COMPOSITION_H_ + #define ANDROID_DRM_DISPLAY_COMPOSITION_H_ + +-#include "drmcrtc.h" +-#include "drmhwcomposer.h" +-#include "drmplane.h" ++#include ++#include + + #include + #include + +-#include +-#include ++#include "drm/DrmCrtc.h" ++#include "drm/DrmPlane.h" ++#include "drmhwcomposer.h" + + namespace android { + + class Importer; + class Planner; +-class SquashState; + + enum DrmCompositionType { + DRM_COMPOSITION_TYPE_EMPTY, +@@ -40,20 +39,6 @@ enum DrmCompositionType { + DRM_COMPOSITION_TYPE_MODESET, + }; + +-struct DrmCompositionDisplayLayersMap { +- int display; +- bool geometry_changed = true; +- std::vector layers; +- +- DrmCompositionDisplayLayersMap() = default; +- DrmCompositionDisplayLayersMap(DrmCompositionDisplayLayersMap &&rhs) = +- default; +-}; +- +-struct DrmCompositionRegion { +- std::vector source_layers; +-}; +- + class DrmCompositionPlane { + public: + enum class Type : int32_t { +@@ -64,15 +49,10 @@ class DrmCompositionPlane { + DrmCompositionPlane() = default; + DrmCompositionPlane(DrmCompositionPlane &&rhs) = default; + DrmCompositionPlane &operator=(DrmCompositionPlane &&other) = default; +- DrmCompositionPlane(Type type, DrmPlane *plane, DrmCrtc *crtc) +- : type_(type), plane_(plane), crtc_(crtc) { ++ DrmCompositionPlane(Type type, DrmPlane *plane) : type_(type), plane_(plane) { + } +- DrmCompositionPlane(Type type, DrmPlane *plane, DrmCrtc *crtc, +- size_t source_layer) +- : type_(type), +- plane_(plane), +- crtc_(crtc), +- source_layers_(1, source_layer) { ++ DrmCompositionPlane(Type type, DrmPlane *plane, size_t source_layer) ++ : type_(type), plane_(plane), source_layers_(1, source_layer) { + } + + Type type() const { +@@ -86,10 +66,6 @@ class DrmCompositionPlane { + plane_ = plane; + } + +- DrmCrtc *crtc() const { +- return crtc_; +- } +- + std::vector &source_layers() { + return source_layers_; + } +@@ -101,18 +77,14 @@ class DrmCompositionPlane { + private: + Type type_ = Type::kDisable; + DrmPlane *plane_ = NULL; +- DrmCrtc *crtc_ = NULL; + std::vector source_layers_; + }; + + class DrmDisplayComposition { + public: +- DrmDisplayComposition() = default; + DrmDisplayComposition(const DrmDisplayComposition &) = delete; +- ~DrmDisplayComposition(); +- +- int Init(DrmDevice *drm, DrmCrtc *crtc, Importer *importer, Planner *planner, +- uint64_t frame_no); ++ DrmDisplayComposition(DrmCrtc *crtc, Planner *planner); ++ ~DrmDisplayComposition() = default; + + int SetLayers(DrmHwcLayer *layers, size_t num_layers, bool geometry_changed); + int AddPlaneComposition(DrmCompositionPlane plane); +@@ -135,10 +107,6 @@ class DrmDisplayComposition { + return geometry_changed_; + } + +- uint64_t frame_no() const { +- return frame_no_; +- } +- + DrmCompositionType type() const { + return type_; + } +@@ -155,43 +123,27 @@ class DrmDisplayComposition { + return crtc_; + } + +- Importer *importer() const { +- return importer_; +- } +- + Planner *planner() const { + return planner_; + } + +- int take_out_fence() { +- return out_fence_.Release(); +- } +- +- void set_out_fence(int out_fence) { +- out_fence_.Set(out_fence); +- } +- + void Dump(std::ostringstream *out) const; + ++ UniqueFd out_fence_; ++ + private: + bool validate_composition_type(DrmCompositionType desired); + +- DrmDevice *drm_ = NULL; + DrmCrtc *crtc_ = NULL; +- Importer *importer_ = NULL; + Planner *planner_ = NULL; + + DrmCompositionType type_ = DRM_COMPOSITION_TYPE_EMPTY; + uint32_t dpms_mode_ = DRM_MODE_DPMS_ON; + DrmMode display_mode_; + +- UniqueFd out_fence_ = -1; +- +- bool geometry_changed_; ++ bool geometry_changed_ = true; + std::vector layers_; + std::vector composition_planes_; +- +- uint64_t frame_no_ = 0; + }; + } // namespace android + +diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/DrmDisplayCompositor.cpp +similarity index 58% +rename from compositor/drmdisplaycompositor.cpp +rename to compositor/DrmDisplayCompositor.cpp +index 1519736..a1fe50f 100644 +--- a/compositor/drmdisplaycompositor.cpp ++++ b/compositor/DrmDisplayCompositor.cpp +@@ -17,27 +17,25 @@ + #define ATRACE_TAG ATRACE_TAG_GRAPHICS + #define LOG_TAG "hwc-drm-display-compositor" + +-#include "drmdisplaycompositor.h" ++#include "DrmDisplayCompositor.h" + ++#include + #include + #include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include + #include + #include + +-#include "autolock.h" +-#include "drmcrtc.h" +-#include "drmdevice.h" +-#include "drmplane.h" ++#include ++#include ++#include ++#include ++#include + +-static const uint32_t kWaitWritebackFence = 100; // ms ++#include "drm/DrmCrtc.h" ++#include "drm/DrmDevice.h" ++#include "drm/DrmPlane.h" ++#include "utils/autolock.h" ++#include "utils/log.h" + + namespace android { + +@@ -52,11 +50,11 @@ std::ostream &operator<<(std::ostream &str, FlatteningState state) { + + class CompositorVsyncCallback : public VsyncCallback { + public: +- CompositorVsyncCallback(DrmDisplayCompositor *compositor) ++ explicit CompositorVsyncCallback(DrmDisplayCompositor *compositor) + : compositor_(compositor) { + } + +- void Callback(int display, int64_t timestamp) { ++ void Callback(int display, int64_t timestamp) override { + compositor_->Vsync(display, timestamp); + } + +@@ -65,7 +63,7 @@ class CompositorVsyncCallback : public VsyncCallback { + }; + + DrmDisplayCompositor::DrmDisplayCompositor() +- : resource_manager_(NULL), ++ : resource_manager_(nullptr), + display_(-1), + initialized_(false), + active_(false), +@@ -73,10 +71,9 @@ DrmDisplayCompositor::DrmDisplayCompositor() + dump_frames_composited_(0), + dump_last_timestamp_ns_(0), + flatten_countdown_(FLATTEN_COUNTDOWN_INIT), +- writeback_fence_(-1), + flattening_state_(FlatteningState::kNone), + frames_flattened_(0) { +- struct timespec ts; ++ struct timespec ts {}; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + return; + dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; +@@ -113,7 +110,7 @@ int DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display) { + ALOGE("Could not find drmdevice for display"); + return -EINVAL; + } +- int ret = pthread_mutex_init(&lock_, NULL); ++ int ret = pthread_mutex_init(&lock_, nullptr); + if (ret) { + ALOGE("Failed to initialize drm compositor lock %d\n", ret); + return ret; +@@ -128,11 +125,6 @@ int DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display) { + return 0; + } + +-std::unique_ptr DrmDisplayCompositor::CreateComposition() +- const { +- return std::unique_ptr(new DrmDisplayComposition()); +-} +- + std::unique_ptr + DrmDisplayCompositor::CreateInitializedComposition() const { + DrmDevice *drm = resource_manager_->GetDrmDevice(display_); +@@ -141,18 +133,8 @@ DrmDisplayCompositor::CreateInitializedComposition() const { + ALOGE("Failed to find crtc for display = %d", display_); + return std::unique_ptr(); + } +- std::unique_ptr comp = CreateComposition(); +- std::shared_ptr importer = resource_manager_->GetImporter(display_); +- if (!importer) { +- ALOGE("Failed to find resources for display = %d", display_); +- return std::unique_ptr(); +- } +- int ret = comp->Init(drm, crtc, importer.get(), planner_.get(), 0); +- if (ret) { +- ALOGE("Failed to init composition for display = %d", display_); +- return std::unique_ptr(); +- } +- return comp; ++ ++ return std::make_unique(crtc, planner_.get()); + } + + FlatteningState DrmDisplayCompositor::GetFlatteningState() const { +@@ -172,7 +154,7 @@ std::tuple + DrmDisplayCompositor::GetActiveModeResolution() { + DrmDevice *drm = resource_manager_->GetDrmDevice(display_); + DrmConnector *connector = drm->GetConnectorForDisplay(display_); +- if (connector == NULL) { ++ if (connector == nullptr) { + ALOGE("Failed to determine display mode: no connector for display %d", + display_); + return std::make_tuple(0, 0, -ENODEV); +@@ -189,7 +171,7 @@ int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { + return -ENOMEM; + } + +- int ret; ++ int ret = 0; + std::vector &comp_planes = display_comp + ->composition_planes(); + for (DrmCompositionPlane &comp_plane : comp_planes) { +@@ -216,49 +198,8 @@ int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { + return 0; + } + +-int DrmDisplayCompositor::SetupWritebackCommit(drmModeAtomicReqPtr pset, +- uint32_t crtc_id, +- DrmConnector *writeback_conn, +- DrmHwcBuffer *writeback_buffer) { +- int ret = 0; +- if (writeback_conn->writeback_fb_id().id() == 0 || +- writeback_conn->writeback_out_fence().id() == 0) { +- ALOGE("Writeback properties don't exit"); +- return -EINVAL; +- } +- if ((*writeback_buffer)->fb_id == 0) { +- ALOGE("Invalid writeback buffer"); +- return -EINVAL; +- } +- ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), +- writeback_conn->writeback_fb_id().id(), +- (*writeback_buffer)->fb_id); +- if (ret < 0) { +- ALOGE("Failed to add writeback_fb_id"); +- return ret; +- } +- ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), +- writeback_conn->writeback_out_fence().id(), +- (uint64_t)&writeback_fence_); +- if (ret < 0) { +- ALOGE("Failed to add writeback_out_fence"); +- return ret; +- } +- +- ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), +- writeback_conn->crtc_id_property().id(), +- crtc_id); +- if (ret < 0) { +- ALOGE("Failed to attach writeback"); +- return ret; +- } +- return 0; +-} +- + int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, +- bool test_only, +- DrmConnector *writeback_conn, +- DrmHwcBuffer *writeback_buffer) { ++ bool test_only) { + ATRACE_CALL(); + + int ret = 0; +@@ -286,18 +227,6 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + return -ENOMEM; + } + +- if (writeback_buffer != NULL) { +- if (writeback_conn == NULL) { +- ALOGE("Invalid arguments requested writeback without writeback conn"); +- return -EINVAL; +- } +- ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn, +- writeback_buffer); +- if (ret < 0) { +- ALOGE("Failed to Setup Writeback Commit ret = %d", ret); +- return ret; +- } +- } + if (crtc->out_fence_ptr_property().id() != 0) { + ret = drmModeAtomicAddProperty(pset, crtc->id(), + crtc->out_fence_ptr_property().id(), +@@ -332,7 +261,6 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + + for (DrmCompositionPlane &comp_plane : comp_planes) { + DrmPlane *plane = comp_plane.plane(); +- DrmCrtc *crtc = comp_plane.crtc(); + std::vector &source_layers = comp_plane.source_layers(); + + int fb_id = -1; +@@ -341,7 +269,9 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + hwc_frect_t source_crop; + uint64_t rotation = 0; + uint64_t alpha = 0xFFFF; +- uint64_t blend; ++ uint64_t blend = UINT64_MAX; ++ uint64_t color_encoding = UINT64_MAX; ++ uint64_t color_range = UINT64_MAX; + + if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) { + if (source_layers.size() > 1) { +@@ -356,12 +286,12 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + break; + } + DrmHwcLayer &layer = layers[source_layers.front()]; +- if (!layer.buffer) { ++ if (!layer.FbIdHandle) { + ALOGE("Expected a valid framebuffer for pset"); + break; + } +- fb_id = layer.buffer->fb_id; +- fence_fd = layer.acquire_fence.get(); ++ fb_id = layer.FbIdHandle->GetFbId(); ++ fence_fd = layer.acquire_fence.Get(); + display_frame = layer.display_frame; + source_crop = layer.source_crop; + alpha = layer.alpha; +@@ -427,6 +357,45 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + break; + } + } ++ ++ if (plane->color_encoding_propery().id()) { ++ switch (layer.dataspace & HAL_DATASPACE_STANDARD_MASK) { ++ case HAL_DATASPACE_STANDARD_BT709: ++ std::tie(color_encoding, ++ ret) = plane->color_encoding_propery() ++ .GetEnumValueWithName("ITU-R BT.709 YCbCr"); ++ 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: ++ std::tie(color_encoding, ++ ret) = plane->color_encoding_propery() ++ .GetEnumValueWithName("ITU-R BT.601 YCbCr"); ++ break; ++ case HAL_DATASPACE_STANDARD_BT2020: ++ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: ++ std::tie(color_encoding, ++ ret) = plane->color_encoding_propery() ++ .GetEnumValueWithName("ITU-R BT.2020 YCbCr"); ++ break; ++ } ++ } ++ ++ if (plane->color_range_property().id()) { ++ switch (layer.dataspace & HAL_DATASPACE_RANGE_MASK) { ++ case HAL_DATASPACE_RANGE_FULL: ++ std::tie(color_range, ++ ret) = plane->color_range_property() ++ .GetEnumValueWithName("YCbCr full range"); ++ break; ++ case HAL_DATASPACE_RANGE_LIMITED: ++ std::tie(color_range, ++ ret) = plane->color_range_property() ++ .GetEnumValueWithName("YCbCr limited range"); ++ break; ++ } ++ } + } + + // Disable the plane if there's no framebuffer +@@ -500,7 +469,7 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + } + } + +- if (plane->blend_property().id()) { ++ if (plane->blend_property().id() && blend != UINT64_MAX) { + ret = drmModeAtomicAddProperty(pset, plane->id(), + plane->blend_property().id(), blend) < 0; + if (ret) { +@@ -509,6 +478,28 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + break; + } + } ++ ++ if (plane->color_encoding_propery().id() && color_encoding != UINT64_MAX) { ++ ret = drmModeAtomicAddProperty(pset, plane->id(), ++ plane->color_encoding_propery().id(), ++ color_encoding) < 0; ++ if (ret) { ++ ALOGE("Failed to add COLOR_ENCODING property %d to plane %d", ++ plane->color_encoding_propery().id(), plane->id()); ++ break; ++ } ++ } ++ ++ if (plane->color_range_property().id() && color_range != UINT64_MAX) { ++ ret = drmModeAtomicAddProperty(pset, plane->id(), ++ plane->color_range_property().id(), ++ color_range) < 0; ++ if (ret) { ++ ALOGE("Failed to add COLOR_RANGE property %d to plane %d", ++ plane->color_range_property().id(), plane->id()); ++ break; ++ } ++ } + } + + if (!ret) { +@@ -549,7 +540,7 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + } + + if (crtc->out_fence_ptr_property().id()) { +- display_comp->set_out_fence((int)out_fences[crtc->pipe()]); ++ display_comp->out_fence_ = UniqueFd((int)out_fences[crtc->pipe()]); + } + + return ret; +@@ -575,8 +566,7 @@ int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) { + + std::tuple DrmDisplayCompositor::CreateModeBlob( + const DrmMode &mode) { +- struct drm_mode_modeinfo drm_mode; +- memset(&drm_mode, 0, sizeof(drm_mode)); ++ struct drm_mode_modeinfo drm_mode {}; + mode.ToDrmModeModeInfo(&drm_mode); + + uint32_t id = 0; +@@ -598,23 +588,17 @@ void DrmDisplayCompositor::ClearDisplay() { + if (DisablePlanes(active_composition_.get())) + return; + +- active_composition_.reset(NULL); +- vsync_worker_.VSyncControl(false); ++ active_composition_.reset(nullptr); + } + + void DrmDisplayCompositor::ApplyFrame( +- std::unique_ptr composition, int status, +- bool writeback) { ++ std::unique_ptr composition, int status) { + AutoLock lock(&lock_, __func__); + if (lock.Lock()) + return; + int ret = status; + + if (!ret) { +- if (writeback && !CountdownExpired()) { +- ALOGE("Abort playing back scene"); +- return; +- } + ret = CommitFrame(composition.get(), false); + } + +@@ -635,7 +619,7 @@ void DrmDisplayCompositor::ApplyFrame( + } else { + SetFlattening(FlatteningState::kClientDone); + } +- vsync_worker_.VSyncControl(!writeback); ++ vsync_worker_.VSyncControl(true); + } + + int DrmDisplayCompositor::ApplyComposition( +@@ -685,118 +669,10 @@ int DrmDisplayCompositor::TestComposition(DrmDisplayComposition *composition) { + return CommitFrame(composition, true); + } + +-// Flatten a scene on the display by using a writeback connector +-// and returns the composition result as a DrmHwcLayer. +-int DrmDisplayCompositor::FlattenOnDisplay( +- std::unique_ptr &src, DrmConnector *writeback_conn, +- DrmMode &src_mode, DrmHwcLayer *writeback_layer) { +- int ret = 0; +- DrmDevice *drm = resource_manager_->GetDrmDevice(display_); +- ret = writeback_conn->UpdateModes(); +- if (ret) { +- ALOGE("Failed to update modes %d", ret); +- return ret; +- } +- for (const DrmMode &mode : writeback_conn->modes()) { +- if (mode.h_display() == src_mode.h_display() && +- mode.v_display() == src_mode.v_display()) { +- mode_.mode = mode; +- if (mode_.blob_id) +- drm->DestroyPropertyBlob(mode_.blob_id); +- std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode); +- if (ret) { +- ALOGE("Failed to create mode blob for display %d", display_); +- return ret; +- } +- mode_.needs_modeset = true; +- break; +- } +- } +- if (mode_.blob_id <= 0) { +- ALOGE("Failed to find similar mode"); +- return -EINVAL; +- } +- +- DrmCrtc *crtc = drm->GetCrtcForDisplay(display_); +- if (!crtc) { +- ALOGE("Failed to find crtc for display %d", display_); +- return -EINVAL; +- } +- // TODO what happens if planes could go to both CRTCs, I don't think it's +- // handled anywhere +- std::vector primary_planes; +- std::vector overlay_planes; +- for (auto &plane : drm->planes()) { +- if (!plane->GetCrtcSupported(*crtc)) +- continue; +- if (plane->type() == DRM_PLANE_TYPE_PRIMARY) +- primary_planes.push_back(plane.get()); +- else if (plane->type() == DRM_PLANE_TYPE_OVERLAY) +- overlay_planes.push_back(plane.get()); +- } +- +- ret = src->Plan(&primary_planes, &overlay_planes); +- if (ret) { +- ALOGE("Failed to plan the composition ret = %d", ret); +- return ret; +- } +- +- // Disable the planes we're not using +- for (auto i = primary_planes.begin(); i != primary_planes.end();) { +- src->AddPlaneDisable(*i); +- i = primary_planes.erase(i); +- } +- for (auto i = overlay_planes.begin(); i != overlay_planes.end();) { +- src->AddPlaneDisable(*i); +- i = overlay_planes.erase(i); +- } +- +- AutoLock lock(&lock_, __func__); +- ret = lock.Lock(); +- if (ret) +- return ret; +- DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_]; +- framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; +- if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) { +- ALOGE("Failed to allocate writeback buffer"); +- return -ENOMEM; +- } +- DrmHwcBuffer *writeback_buffer = &writeback_layer->buffer; +- writeback_layer->sf_handle = writeback_fb->buffer()->handle; +- ret = writeback_layer->ImportBuffer( +- resource_manager_->GetImporter(display_).get()); +- if (ret) { +- ALOGE("Failed to import writeback buffer"); +- return ret; +- } +- +- ret = CommitFrame(src.get(), true, writeback_conn, writeback_buffer); +- if (ret) { +- ALOGE("Atomic check failed"); +- return ret; +- } +- ret = CommitFrame(src.get(), false, writeback_conn, writeback_buffer); +- if (ret) { +- ALOGE("Atomic commit failed"); +- return ret; +- } +- +- ret = sync_wait(writeback_fence_, kWaitWritebackFence); +- writeback_layer->acquire_fence.Set(writeback_fence_); +- writeback_fence_ = -1; +- if (ret) { +- ALOGE("Failed to wait on writeback fence"); +- return ret; +- } +- return 0; +-} +- + void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) { + if (flattening_state_ != new_state) { + switch (flattening_state_) { + case FlatteningState::kClientDone: +- case FlatteningState::kConcurrent: +- case FlatteningState::kSerial: + ++frames_flattened_; + break; + case FlatteningState::kClientRequested: +@@ -813,7 +689,9 @@ bool DrmDisplayCompositor::IsFlatteningNeeded() const { + } + + int DrmDisplayCompositor::FlattenOnClient() { +- if (refresh_display_cb_) { ++ const std::lock_guard lock(refresh_callback_lock); ++ ++ if (refresh_callback_hook_ && refresh_callback_data_) { + { + AutoLock lock(&lock_, __func__); + if (!IsFlatteningNeeded()) { +@@ -829,224 +707,16 @@ int DrmDisplayCompositor::FlattenOnClient() { + "No writeback connector available, " + "falling back to client composition"); + SetFlattening(FlatteningState::kClientRequested); +- refresh_display_cb_(display_); ++ refresh_callback_hook_(refresh_callback_data_, display_); + return 0; +- } else { +- ALOGV("No writeback connector available"); +- return -EINVAL; +- } +-} +- +-// Flatten a scene by enabling the writeback connector attached +-// to the same CRTC as the one driving the display. +-int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) { +- ALOGV("FlattenSerial by enabling writeback connector to the same crtc"); +- // Flattened composition with only one layer that is obtained +- // using the writeback connector +- std::unique_ptr +- writeback_comp = CreateInitializedComposition(); +- if (!writeback_comp) +- return -EINVAL; +- +- AutoLock lock(&lock_, __func__); +- int ret = lock.Lock(); +- if (ret) +- return ret; +- if (!IsFlatteningNeeded()) { +- ALOGV("Flattening is not needed"); +- SetFlattening(FlatteningState::kNotNeeded); +- return -EALREADY; +- } +- +- DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_]; +- framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; +- lock.Unlock(); +- +- if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) { +- ALOGE("Failed to allocate writeback buffer"); +- return -ENOMEM; +- } +- writeback_comp->layers().emplace_back(); +- +- DrmHwcLayer &writeback_layer = writeback_comp->layers().back(); +- writeback_layer.sf_handle = writeback_fb->buffer()->handle; +- writeback_layer.source_crop = {0, 0, (float)mode_.mode.h_display(), +- (float)mode_.mode.v_display()}; +- writeback_layer.display_frame = {0, 0, (int)mode_.mode.h_display(), +- (int)mode_.mode.v_display()}; +- ret = writeback_layer.ImportBuffer( +- resource_manager_->GetImporter(display_).get()); +- if (ret || writeback_comp->layers().size() != 1) { +- ALOGE("Failed to import writeback buffer"); +- return ret; +- } +- +- drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); +- if (!pset) { +- ALOGE("Failed to allocate property set"); +- return -ENOMEM; +- } +- DrmDevice *drm = resource_manager_->GetDrmDevice(display_); +- DrmCrtc *crtc = drm->GetCrtcForDisplay(display_); +- if (!crtc) { +- ALOGE("Failed to find crtc for display %d", display_); +- return -EINVAL; +- } +- ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn, +- &writeback_layer.buffer); +- if (ret < 0) { +- ALOGE("Failed to Setup Writeback Commit"); +- return ret; +- } +- ret = drmModeAtomicCommit(drm->fd(), pset, 0, drm); +- if (ret) { +- ALOGE("Failed to enable writeback %d", ret); +- return ret; +- } +- ret = sync_wait(writeback_fence_, kWaitWritebackFence); +- writeback_layer.acquire_fence.Set(writeback_fence_); +- writeback_fence_ = -1; +- if (ret) { +- ALOGE("Failed to wait on writeback fence"); +- return ret; +- } +- +- DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, NULL, +- crtc); +- for (auto &drmplane : drm->planes()) { +- if (!drmplane->GetCrtcSupported(*crtc)) +- continue; +- if (!squashed_comp.plane() && drmplane->type() == DRM_PLANE_TYPE_PRIMARY) +- squashed_comp.set_plane(drmplane.get()); +- else +- writeback_comp->AddPlaneDisable(drmplane.get()); +- } +- squashed_comp.source_layers().push_back(0); +- ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp)); +- if (ret) { +- ALOGE("Failed to add flatten scene"); +- return ret; +- } +- +- ApplyFrame(std::move(writeback_comp), 0, true); +- return 0; +-} +- +-// Flatten a scene by using a crtc which works concurrent with +-// the one driving the display. +-int DrmDisplayCompositor::FlattenConcurrent(DrmConnector *writeback_conn) { +- ALOGV("FlattenConcurrent by using an unused crtc/display"); +- int ret = 0; +- DrmDisplayCompositor drmdisplaycompositor; +- ret = drmdisplaycompositor.Init(resource_manager_, writeback_conn->display()); +- if (ret) { +- ALOGE("Failed to init drmdisplaycompositor = %d", ret); +- return ret; +- } +- // Copy of the active_composition, needed because of two things: +- // 1) Not to hold the lock for the whole time we are accessing +- // active_composition +- // 2) It will be committed on a crtc that might not be on the same +- // dri node, so buffers need to be imported on the right node. +- std::unique_ptr +- copy_comp = drmdisplaycompositor.CreateInitializedComposition(); +- +- // Writeback composition that will be committed to the display. +- std::unique_ptr +- writeback_comp = CreateInitializedComposition(); +- +- if (!copy_comp || !writeback_comp) +- return -EINVAL; +- AutoLock lock(&lock_, __func__); +- ret = lock.Lock(); +- if (ret) +- return ret; +- if (!IsFlatteningNeeded()) { +- ALOGV("Flattening is not needed"); +- SetFlattening(FlatteningState::kNotNeeded); +- return -EALREADY; +- } +- DrmCrtc *crtc = active_composition_->crtc(); +- +- std::vector copy_layers; +- for (DrmHwcLayer &src_layer : active_composition_->layers()) { +- DrmHwcLayer copy; +- ret = copy.InitFromDrmHwcLayer(&src_layer, +- resource_manager_ +- ->GetImporter(writeback_conn->display()) +- .get()); +- if (ret) { +- ALOGE("Failed to import buffer ret = %d", ret); +- return -EINVAL; +- } +- copy_layers.emplace_back(std::move(copy)); +- } +- ret = copy_comp->SetLayers(copy_layers.data(), copy_layers.size(), true); +- if (ret) { +- ALOGE("Failed to set copy_comp layers"); +- return ret; + } + +- lock.Unlock(); +- DrmHwcLayer writeback_layer; +- ret = drmdisplaycompositor.FlattenOnDisplay(copy_comp, writeback_conn, +- mode_.mode, &writeback_layer); +- if (ret) { +- ALOGE("Failed to flatten on display ret = %d", ret); +- return ret; +- } +- +- DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, NULL, +- crtc); +- for (auto &drmplane : resource_manager_->GetDrmDevice(display_)->planes()) { +- if (!drmplane->GetCrtcSupported(*crtc)) +- continue; +- if (drmplane->type() == DRM_PLANE_TYPE_PRIMARY) +- squashed_comp.set_plane(drmplane.get()); +- else +- writeback_comp->AddPlaneDisable(drmplane.get()); +- } +- writeback_comp->layers().emplace_back(); +- DrmHwcLayer &next_layer = writeback_comp->layers().back(); +- next_layer.sf_handle = writeback_layer.get_usable_handle(); +- next_layer.blending = DrmHwcBlending::kPreMult; +- next_layer.source_crop = {0, 0, (float)mode_.mode.h_display(), +- (float)mode_.mode.v_display()}; +- next_layer.display_frame = {0, 0, (int)mode_.mode.h_display(), +- (int)mode_.mode.v_display()}; +- ret = next_layer.ImportBuffer(resource_manager_->GetImporter(display_).get()); +- if (ret) { +- ALOGE("Failed to import framebuffer for display %d", ret); +- return ret; +- } +- squashed_comp.source_layers().push_back(0); +- ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp)); +- if (ret) { +- ALOGE("Failed to add plane composition %d", ret); +- return ret; +- } +- ApplyFrame(std::move(writeback_comp), 0, true); +- return ret; ++ ALOGV("No writeback connector available"); ++ return -EINVAL; + } + + int DrmDisplayCompositor::FlattenActiveComposition() { +- DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector( +- display_); +- if (!active_composition_ || !writeback_conn) { +- // Try to fallback to GPU composition on client, since it is more +- // power-efficient than composition on device side +- return FlattenOnClient(); +- } +- +- if (writeback_conn->display() != display_) { +- SetFlattening(FlatteningState::kConcurrent); +- return FlattenConcurrent(writeback_conn); +- } else { +- SetFlattening(FlatteningState::kSerial); +- return FlattenSerial(writeback_conn); +- } +- +- return 0; ++ return FlattenOnClient(); + } + + bool DrmDisplayCompositor::CountdownExpired() const { +@@ -1075,7 +745,7 @@ void DrmDisplayCompositor::Dump(std::ostringstream *out) const { + uint64_t num_frames = dump_frames_composited_; + dump_frames_composited_ = 0; + +- struct timespec ts; ++ struct timespec ts {}; + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + if (ret) { + pthread_mutex_unlock(&lock_); +@@ -1084,7 +754,7 @@ void DrmDisplayCompositor::Dump(std::ostringstream *out) const { + + uint64_t cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; + uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000); +- float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f; ++ float fps = num_ms ? (num_frames * 1000.0F) / (num_ms) : 0.0F; + + *out << "--DrmDisplayCompositor[" << display_ + << "]: num_frames=" << num_frames << " num_ms=" << num_ms +diff --git a/include/drmdisplaycompositor.h b/compositor/DrmDisplayCompositor.h +similarity index 71% +rename from include/drmdisplaycompositor.h +rename to compositor/DrmDisplayCompositor.h +index 26e2572..c0eed0c 100644 +--- a/include/drmdisplaycompositor.h ++++ b/compositor/DrmDisplayCompositor.h +@@ -17,23 +17,20 @@ + #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_ + #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_ + +-#include "drmdisplaycomposition.h" +-#include "drmframebuffer.h" +-#include "drmhwcomposer.h" +-#include "resourcemanager.h" +-#include "vsyncworker.h" +- ++#include ++#include + #include ++ ++#include + #include + #include + #include + +-#include +-#include +- +-// One for the front, one for the back, and one for cases where we need to +-// squash a frame that the hw can't display with hw overlays. +-#define DRM_DISPLAY_BUFFERS 3 ++#include "DrmDisplayComposition.h" ++#include "Planner.h" ++#include "drm/ResourceManager.h" ++#include "drm/VSyncWorker.h" ++#include "drmhwcomposer.h" + + // If a scene is still for this number of vblanks flatten it to reduce power + // consumption. +@@ -46,8 +43,6 @@ enum class FlatteningState { + kNotNeeded, + kClientRequested, + kClientDone, +- kSerial, +- kConcurrent + }; + + std::ostream &operator<<(std::ostream &str, FlatteningState state); +@@ -59,12 +54,17 @@ class DrmDisplayCompositor { + + int Init(ResourceManager *resource_manager, int display); + +- template +- void SetRefreshCallback(Fn &&refresh_cb) { +- refresh_display_cb_ = std::forward(refresh_cb); ++ hwc2_callback_data_t refresh_callback_data_ = NULL; ++ HWC2_PFN_REFRESH refresh_callback_hook_ = NULL; ++ std::mutex refresh_callback_lock; ++ ++ void SetRefreshCallback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook) { ++ const std::lock_guard lock(refresh_callback_lock); ++ refresh_callback_data_ = data; ++ refresh_callback_hook_ = reinterpret_cast(hook); + } + +- std::unique_ptr CreateComposition() const; + std::unique_ptr CreateInitializedComposition() const; + int ApplyComposition(std::unique_ptr composition); + int TestComposition(DrmDisplayComposition *composition); +@@ -72,10 +72,11 @@ class DrmDisplayCompositor { + void Dump(std::ostringstream *out) const; + void Vsync(int display, int64_t timestamp); + void ClearDisplay(); +- int TakeOutFence() { +- if (!active_composition_) +- return -1; +- return active_composition_->take_out_fence(); ++ UniqueFd TakeOutFence() { ++ if (!active_composition_) { ++ return UniqueFd(); ++ } ++ return std::move(active_composition_->out_fence_); + } + + FlatteningState GetFlatteningState() const; +@@ -99,27 +100,17 @@ class DrmDisplayCompositor { + static const int kAcquireWaitTries = 5; + static const int kAcquireWaitTimeoutMs = 100; + +- int CommitFrame(DrmDisplayComposition *display_comp, bool test_only, +- DrmConnector *writeback_conn = NULL, +- DrmHwcBuffer *writeback_buffer = NULL); +- int SetupWritebackCommit(drmModeAtomicReqPtr pset, uint32_t crtc_id, +- DrmConnector *writeback_conn, +- DrmHwcBuffer *writeback_buffer); ++ int CommitFrame(DrmDisplayComposition *display_comp, bool test_only); + int ApplyDpms(DrmDisplayComposition *display_comp); + int DisablePlanes(DrmDisplayComposition *display_comp); + + void ApplyFrame(std::unique_ptr composition, +- int status, bool writeback = false); ++ int status); + + void SetFlattening(FlatteningState new_state); + bool IsFlatteningNeeded() const; + int FlattenActiveComposition(); + int FlattenOnClient(); +- int FlattenSerial(DrmConnector *writeback_conn); +- int FlattenConcurrent(DrmConnector *writeback_conn); +- int FlattenOnDisplay(std::unique_ptr &src, +- DrmConnector *writeback_conn, DrmMode &src_mode, +- DrmHwcLayer *writeback_layer); + + bool CountdownExpired() const; + +@@ -136,11 +127,8 @@ class DrmDisplayCompositor { + + ModeState mode_; + +- int framebuffer_index_; +- DrmFramebuffer framebuffers_[DRM_DISPLAY_BUFFERS]; +- + // mutable since we need to acquire in Dump() +- mutable pthread_mutex_t lock_; ++ mutable pthread_mutex_t lock_{}; + + // State tracking progress since our last Dump(). These are mutable since + // we need to reset them on every Dump() call. +@@ -149,7 +137,6 @@ class DrmDisplayCompositor { + VSyncWorker vsync_worker_; + int64_t flatten_countdown_; + std::unique_ptr planner_; +- int writeback_fence_; + + FlatteningState flattening_state_; + uint32_t frames_flattened_; +diff --git a/platform/platform.cpp b/compositor/Planner.cpp +similarity index 64% +rename from platform/platform.cpp +rename to compositor/Planner.cpp +index b7a47c7..42259d1 100644 +--- a/platform/platform.cpp ++++ b/compositor/Planner.cpp +@@ -16,13 +16,21 @@ + + #define LOG_TAG "hwc-platform" + +-#include "platform.h" +-#include "drmdevice.h" ++#include "Planner.h" + +-#include ++#include ++ ++#include "drm/DrmDevice.h" ++#include "utils/log.h" + + namespace android { + ++std::unique_ptr Planner::CreateInstance(DrmDevice * /*device*/) { ++ std::unique_ptr planner(new Planner); ++ planner->AddStage(); ++ return planner; ++} ++ + std::vector Planner::GetUsablePlanes( + DrmCrtc *crtc, std::vector *primary_planes, + std::vector *overlay_planes) { +@@ -36,50 +44,6 @@ std::vector Planner::GetUsablePlanes( + return usable_planes; + } + +-int Planner::PlanStage::ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer) { +- int ret = 0; +- uint64_t blend; +- +- if ((plane->rotation_property().id() == 0) && +- layer->transform != DrmHwcTransform::kIdentity) { +- ALOGE("Rotation is not supported on plane %d", plane->id()); +- return -EINVAL; +- } +- +- if (plane->alpha_property().id() == 0 && layer->alpha != 0xffff) { +- ALOGE("Alpha is not supported on plane %d", plane->id()); +- return -EINVAL; +- } +- +- if (plane->blend_property().id() == 0) { +- if ((layer->blending != DrmHwcBlending::kNone) && +- (layer->blending != DrmHwcBlending::kPreMult)) { +- ALOGE("Blending is not supported on plane %d", plane->id()); +- return -EINVAL; +- } +- } else { +- switch (layer->blending) { +- case DrmHwcBlending::kPreMult: +- std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName( +- "Pre-multiplied"); +- break; +- case DrmHwcBlending::kCoverage: +- std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName( +- "Coverage"); +- break; +- case DrmHwcBlending::kNone: +- default: +- std::tie(blend, +- ret) = plane->blend_property().GetEnumValueWithName("None"); +- break; +- } +- if (ret) +- ALOGE("Expected a valid blend mode on plane %d", plane->id()); +- } +- +- return ret; +-} +- + std::tuple> Planner::ProvisionPlanes( + std::map &layers, DrmCrtc *crtc, + std::vector *primary_planes, +@@ -94,7 +58,7 @@ std::tuple> Planner::ProvisionPlanes( + + // Go through the provisioning stages and provision planes + for (auto &i : stages_) { +- int ret = i->ProvisionPlanes(&composition, layers, crtc, &planes); ++ int ret = i->ProvisionPlanes(&composition, layers, &planes); + if (ret) { + ALOGE("Failed provision stage with ret %d", ret); + return std::make_tuple(ret, std::vector()); +@@ -106,24 +70,22 @@ std::tuple> Planner::ProvisionPlanes( + + int PlanStageProtected::ProvisionPlanes( + std::vector *composition, +- std::map &layers, DrmCrtc *crtc, ++ std::map &layers, + std::vector *planes) { +- int ret; +- int protected_zorder = -1; ++ int ret = 0; + for (auto i = layers.begin(); i != layers.end();) { + if (!i->second->protected_usage()) { + ++i; + continue; + } + +- ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, crtc, ++ ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, + std::make_pair(i->first, i->second)); + if (ret) { + ALOGE("Failed to dedicate protected layer! Dropping it."); + return ret; + } + +- protected_zorder = i->first; + i = layers.erase(i); + } + +@@ -132,16 +94,17 @@ int PlanStageProtected::ProvisionPlanes( + + int PlanStageGreedy::ProvisionPlanes( + std::vector *composition, +- std::map &layers, DrmCrtc *crtc, ++ std::map &layers, + std::vector *planes) { + // Fill up the remaining planes + for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) { + int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, +- crtc, std::make_pair(i->first, i->second)); ++ std::make_pair(i->first, i->second)); + // We don't have any planes left + if (ret == -ENOENT) + break; +- else if (ret) { ++ ++ if (ret) { + ALOGE("Failed to emplace layer %zu, dropping it", i->first); + return ret; + } +diff --git a/include/platform.h b/compositor/Planner.h +similarity index 73% +rename from include/platform.h +rename to compositor/Planner.h +index 6775e29..3390acb 100644 +--- a/include/platform.h ++++ b/compositor/Planner.h +@@ -17,46 +17,20 @@ + #ifndef ANDROID_DRM_PLATFORM_H_ + #define ANDROID_DRM_PLATFORM_H_ + +-#include "drmdisplaycomposition.h" +-#include "drmhwcomposer.h" +- + #include + #include + + #include ++#include + #include + ++#include "compositor/DrmDisplayComposition.h" ++#include "drmhwcomposer.h" ++ + namespace android { + + class DrmDevice; + +-class Importer { +- public: +- virtual ~Importer() { +- } +- +- // Creates a platform-specific importer instance +- static Importer *CreateInstance(DrmDevice *drm); +- +- // Imports the buffer referred to by handle into bo. +- // +- // Note: This can be called from a different thread than ReleaseBuffer. The +- // implementation is responsible for ensuring thread safety. +- virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; +- +- // Releases the buffer object (ie: does the inverse of ImportBuffer) +- // +- // Note: This can be called from a different thread than ImportBuffer. The +- // implementation is responsible for ensuring thread safety. +- virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; +- +- // Checks if importer can import the buffer. +- virtual bool CanImportBuffer(buffer_handle_t handle) = 0; +- +- // Convert platform-dependent buffer format to drm_hwc internal format. +- virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; +-}; +- + class Planner { + public: + class PlanStage { +@@ -66,7 +40,6 @@ class Planner { + + virtual int ProvisionPlanes(std::vector *composition, + std::map &layers, +- DrmCrtc *crtc, + std::vector *planes) = 0; + + protected: +@@ -79,18 +52,16 @@ class Planner { + return plane; + } + +- static int ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer); +- + // Inserts the given layer:plane in the composition at the back + static int Emplace(std::vector *composition, + std::vector *planes, +- DrmCompositionPlane::Type type, DrmCrtc *crtc, ++ DrmCompositionPlane::Type type, + std::pair layer) { + DrmPlane *plane = PopPlane(planes); + std::vector unused_planes; + int ret = -ENOENT; + while (plane) { +- ret = ValidatePlane(plane, layer.second); ++ ret = plane->IsValidForLayer(layer.second) ? 0 : -EINVAL; + if (!ret) + break; + if (!plane->zpos_property().is_immutable()) +@@ -99,7 +70,7 @@ class Planner { + } + + if (!ret) { +- composition->emplace_back(type, plane, crtc, layer.first); ++ composition->emplace_back(type, plane, layer.first); + planes->insert(planes->begin(), unused_planes.begin(), + unused_planes.end()); + } +@@ -126,7 +97,7 @@ class Planner { + std::vector *overlay_planes); + + template +- void AddStage(A &&... args) { ++ void AddStage(A &&...args) { + stages_.emplace_back( + std::unique_ptr(new T(std::forward(args)...))); + } +@@ -144,7 +115,7 @@ class Planner { + class PlanStageProtected : public Planner::PlanStage { + public: + int ProvisionPlanes(std::vector *composition, +- std::map &layers, DrmCrtc *crtc, ++ std::map &layers, + std::vector *planes); + }; + +@@ -154,7 +125,7 @@ class PlanStageProtected : public Planner::PlanStage { + class PlanStageGreedy : public Planner::PlanStage { + public: + int ProvisionPlanes(std::vector *composition, +- std::map &layers, DrmCrtc *crtc, ++ std::map &layers, + std::vector *planes); + }; + } // namespace android +diff --git a/drm/drmconnector.cpp b/drm/DrmConnector.cpp +similarity index 86% +rename from drm/drmconnector.cpp +rename to drm/DrmConnector.cpp +index 81c2b98..0468527 100644 +--- a/drm/drmconnector.cpp ++++ b/drm/DrmConnector.cpp +@@ -16,21 +16,21 @@ + + #define LOG_TAG "hwc-drm-connector" + +-#include "drmconnector.h" +-#include "drmdevice.h" ++#include "DrmConnector.h" + +-#include +-#include ++#include + + #include ++#include ++#include + #include + +-#include +-#include ++#include "DrmDevice.h" ++#include "utils/log.h" + + namespace android { + +-constexpr size_t TYPES_COUNT = 17; ++constexpr size_t kTypesCount = 17; + + DrmConnector::DrmConnector(DrmDevice *drm, drmModeConnectorPtr c, + DrmEncoder *current_encoder, +@@ -58,10 +58,7 @@ int DrmConnector::Init() { + ALOGE("Could not get CRTC_ID property\n"); + return ret; + } +- ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_); +- if (ret) { +- ALOGW("Could not get EDID property\n"); +- } ++ UpdateEdidProperty(); + if (writeback()) { + ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS", + &writeback_pixel_formats_); +@@ -85,6 +82,30 @@ int DrmConnector::Init() { + return 0; + } + ++int DrmConnector::UpdateEdidProperty() { ++ int ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_); ++ if (ret) { ++ ALOGW("Could not get EDID property\n"); ++ } ++ return ret; ++} ++ ++int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) { ++ uint64_t blob_id = 0; ++ int ret = UpdateEdidProperty(); ++ if (ret) { ++ return ret; ++ } ++ ++ std::tie(ret, blob_id) = edid_property().value(); ++ if (ret) { ++ return ret; ++ } ++ ++ blob = drmModeGetPropertyBlob(drm_->fd(), blob_id); ++ return !blob; ++} ++ + uint32_t DrmConnector::id() const { + return id_; + } +@@ -123,19 +144,19 @@ bool DrmConnector::valid_type() const { + } + + std::string DrmConnector::name() const { +- constexpr std::array names = ++ constexpr std::array kNames = + {"None", "VGA", "DVI-I", "DVI-D", "DVI-A", "Composite", + "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI-A", + "HDMI-B", "TV", "eDP", "Virtual", "DSI"}; + +- if (type_ < TYPES_COUNT) { ++ if (type_ < kTypesCount) { + std::ostringstream name_buf; +- name_buf << names[type_] << "-" << type_id_; ++ name_buf << kNames[type_] << "-" << type_id_; + return name_buf.str(); +- } else { +- ALOGE("Unknown type in connector %d, could not make his name", id_); +- return "None"; + } ++ ++ ALOGE("Unknown type in connector %d, could not make his name", id_); ++ return "None"; + } + + int DrmConnector::UpdateModes() { +@@ -173,7 +194,7 @@ int DrmConnector::UpdateModes() { + } + } + modes_.swap(new_modes); +- if (!preferred_mode_found && modes_.size() != 0) { ++ if (!preferred_mode_found && !modes_.empty()) { + preferred_mode_id_ = modes_[0].id(); + } + return 0; +diff --git a/include/drmconnector.h b/drm/DrmConnector.h +similarity index 93% +rename from include/drmconnector.h +rename to drm/DrmConnector.h +index dc64b38..3bc18c8 100644 +--- a/include/drmconnector.h ++++ b/drm/DrmConnector.h +@@ -17,15 +17,16 @@ + #ifndef ANDROID_DRM_CONNECTOR_H_ + #define ANDROID_DRM_CONNECTOR_H_ + +-#include "drmencoder.h" +-#include "drmmode.h" +-#include "drmproperty.h" +- + #include + #include ++ + #include + #include + ++#include "DrmEncoder.h" ++#include "DrmMode.h" ++#include "DrmProperty.h" ++ + namespace android { + + class DrmDevice; +@@ -39,6 +40,8 @@ class DrmConnector { + DrmConnector &operator=(const DrmProperty &) = delete; + + int Init(); ++ int UpdateEdidProperty(); ++ int GetEdidBlob(drmModePropertyBlobPtr &blob); + + uint32_t id() const; + +@@ -108,7 +111,7 @@ class DrmConnector { + + std::vector possible_encoders_; + +- uint32_t preferred_mode_id_; ++ uint32_t preferred_mode_id_{}; + }; + } // namespace android + +diff --git a/drm/drmcrtc.cpp b/drm/DrmCrtc.cpp +similarity index 95% +rename from drm/drmcrtc.cpp +rename to drm/DrmCrtc.cpp +index b627291..4da08fe 100644 +--- a/drm/drmcrtc.cpp ++++ b/drm/DrmCrtc.cpp +@@ -16,13 +16,14 @@ + + #define LOG_TAG "hwc-drm-crtc" + +-#include "drmcrtc.h" +-#include "drmdevice.h" ++#include "DrmCrtc.h" + +-#include ++#include + #include + +-#include ++#include ++ ++#include "DrmDevice.h" + + namespace android { + +diff --git a/include/drmcrtc.h b/drm/DrmCrtc.h +similarity index 97% +rename from include/drmcrtc.h +rename to drm/DrmCrtc.h +index 3075f9b..7972bef 100644 +--- a/include/drmcrtc.h ++++ b/drm/DrmCrtc.h +@@ -17,12 +17,12 @@ + #ifndef ANDROID_DRM_CRTC_H_ + #define ANDROID_DRM_CRTC_H_ + +-#include "drmmode.h" +-#include "drmproperty.h" +- + #include + #include + ++#include "DrmMode.h" ++#include "DrmProperty.h" ++ + namespace android { + + class DrmDevice; +diff --git a/drm/drmdevice.cpp b/drm/DrmDevice.cpp +similarity index 85% +rename from drm/drmdevice.cpp +rename to drm/DrmDevice.cpp +index bef41d8..abc8edc 100644 +--- a/drm/drmdevice.cpp ++++ b/drm/DrmDevice.cpp +@@ -16,41 +16,37 @@ + + #define LOG_TAG "hwc-drm-device" + +-#include "drmdevice.h" +-#include "drmconnector.h" +-#include "drmcrtc.h" +-#include "drmencoder.h" +-#include "drmeventlistener.h" +-#include "drmplane.h" +- +-#include ++#include "DrmDevice.h" ++ + #include +-#include + #include + #include +-#include + + #include + #include ++#include ++#include ++#include ++#include + #include + +-#include +-#include ++#include "utils/log.h" ++#include "utils/properties.h" + +-static void trim_left(std::string &str) { +- str.erase(std::begin(str), +- std::find_if(std::begin(str), std::end(str), +- [](int ch) { return !std::isspace(ch); })); ++static void trim_left(std::string *str) { ++ str->erase(std::begin(*str), ++ std::find_if(std::begin(*str), std::end(*str), ++ [](int ch) { return std::isspace(ch) == 0; })); + } + +-static void trim_right(std::string &str) { +- str.erase(std::find_if(std::rbegin(str), std::rend(str), +- [](int ch) { return !std::isspace(ch); }) +- .base(), +- std::end(str)); ++static void trim_right(std::string *str) { ++ str->erase(std::find_if(std::rbegin(*str), std::rend(*str), ++ [](int ch) { return std::isspace(ch) == 0; }) ++ .base(), ++ std::end(*str)); + } + +-static void trim(std::string &str) { ++static void trim(std::string *str) { + trim_left(str); + trim_right(str); + } +@@ -58,25 +54,25 @@ static void trim(std::string &str) { + namespace android { + + static std::vector read_primary_display_order_prop() { +- std::array display_order_buf; +- property_get("hwc.drm.primary_display_order", display_order_buf.data(), ++ std::array display_order_buf{}; ++ property_get("vendor.hwc.drm.primary_display_order", display_order_buf.data(), + "..."); + + std::vector display_order; + std::istringstream str(display_order_buf.data()); +- for (std::string conn_name = ""; std::getline(str, conn_name, ',');) { +- trim(conn_name); ++ for (std::string conn_name; std::getline(str, conn_name, ',');) { ++ trim(&conn_name); + display_order.push_back(std::move(conn_name)); + } + return display_order; + } + + static std::vector make_primary_display_candidates( +- std::vector> &connectors) { ++ const std::vector> &connectors) { + std::vector primary_candidates; + std::transform(std::begin(connectors), std::end(connectors), + std::back_inserter(primary_candidates), +- [](std::unique_ptr &conn) { ++ [](const std::unique_ptr &conn) { + return conn.get(); + }); + primary_candidates.erase(std::remove_if(std::begin(primary_candidates), +@@ -116,6 +112,8 @@ static std::vector make_primary_display_candidates( + } + + DrmDevice::DrmDevice() : event_listener_(this) { ++ self.reset(this); ++ mDrmFbImporter = std::make_unique(self); + } + + DrmDevice::~DrmDevice() { +@@ -124,7 +122,7 @@ DrmDevice::~DrmDevice() { + + std::tuple DrmDevice::Init(const char *path, int num_displays) { + /* TODO: Use drmOpenControl here instead */ +- fd_.Set(open(path, O_RDWR)); ++ fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC)); + if (fd() < 0) { + ALOGE("Failed to open dri %s: %s", path, strerror(errno)); + return std::make_tuple(-ENODEV, 0); +@@ -150,6 +148,19 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + } + #endif + ++ uint64_t cap_value = 0; ++ if (drmGetCap(fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) { ++ ALOGW("drmGetCap failed. Fallback to no modifier support."); ++ cap_value = 0; ++ } ++ HasAddFb2ModifiersSupport_ = cap_value != 0; ++ ++ drmSetMaster(fd()); ++ if (!drmIsMaster(fd())) { ++ ALOGE("DRM/KMS master access required"); ++ return std::make_tuple(-EACCES, 0); ++ } ++ + drmModeResPtr res = drmModeGetResources(fd()); + if (!res) { + ALOGE("Failed to get DrmDevice resources"); +@@ -194,7 +205,7 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + } + + std::vector possible_crtcs; +- DrmCrtc *current_crtc = NULL; ++ DrmCrtc *current_crtc = nullptr; + for (auto &crtc : crtcs_) { + if ((1 << crtc->pipe()) & e->possible_crtcs) + possible_crtcs.push_back(crtc.get()); +@@ -226,7 +237,7 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + } + + std::vector possible_encoders; +- DrmEncoder *current_encoder = NULL; ++ DrmEncoder *current_encoder = nullptr; + for (int j = 0; j < c->count_encoders; ++j) { + for (auto &encoder : encoders_) { + if (encoder->id() == c->encoders[j]) +@@ -254,7 +265,7 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + } + + // Primary display priority: +- // 1) hwc.drm.primary_display_order property ++ // 1) vendor.hwc.drm.primary_display_order property + // 2) internal connectors + // 3) anything else + std::vector +@@ -267,8 +278,8 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + found_primary = true; + } else { + ALOGE( +- "Failed to find primary display from \"hwc.drm.primary_display_order\" " +- "property"); ++ "Failed to find primary display from " ++ "\"vendor.hwc.drm.primary_display_order\" property"); + } + + // If no priority display were found then pick first available as primary and +@@ -349,22 +360,22 @@ bool DrmDevice::HandlesDisplay(int display) const { + } + + DrmConnector *DrmDevice::GetConnectorForDisplay(int display) const { +- for (auto &conn : connectors_) { ++ for (const auto &conn : connectors_) { + if (conn->display() == display) + return conn.get(); + } +- return NULL; ++ return nullptr; + } + + DrmConnector *DrmDevice::GetWritebackConnectorForDisplay(int display) const { +- for (auto &conn : writeback_connectors_) { ++ for (const auto &conn : writeback_connectors_) { + if (conn->display() == display) + return conn.get(); + } +- return NULL; ++ return nullptr; + } + +-// TODO what happens when hotplugging ++// TODO(nobody): what happens when hotplugging + DrmConnector *DrmDevice::AvailableWritebackConnector(int display) const { + DrmConnector *writeback_conn = GetWritebackConnectorForDisplay(display); + DrmConnector *display_conn = GetConnectorForDisplay(display); +@@ -375,7 +386,7 @@ DrmConnector *DrmDevice::AvailableWritebackConnector(int display) const { + return writeback_conn; + + // Use another CRTC if available and doesn't have any connector +- for (auto &crtc : crtcs_) { ++ for (const auto &crtc : crtcs_) { + if (crtc->display() == display) + continue; + display_conn = GetConnectorForDisplay(crtc->display()); +@@ -386,23 +397,23 @@ DrmConnector *DrmDevice::AvailableWritebackConnector(int display) const { + if (writeback_conn) + return writeback_conn; + } +- return NULL; ++ return nullptr; + } + + DrmCrtc *DrmDevice::GetCrtcForDisplay(int display) const { +- for (auto &crtc : crtcs_) { ++ for (const auto &crtc : crtcs_) { + if (crtc->display() == display) + return crtc.get(); + } +- return NULL; ++ return nullptr; + } + + DrmPlane *DrmDevice::GetPlane(uint32_t id) const { +- for (auto &plane : planes_) { ++ for (const auto &plane : planes_) { + if (plane->id() == id) + return plane.get(); + } +- return NULL; ++ return nullptr; + } + + const std::vector> &DrmDevice::crtcs() const { +@@ -446,7 +457,9 @@ int DrmDevice::CreateDisplayPipe(DrmConnector *connector) { + int ret = TryEncoderForDisplay(display, connector->encoder()); + if (!ret) { + return 0; +- } else if (ret != -EAGAIN) { ++ } ++ ++ if (ret != -EAGAIN) { + ALOGE("Could not set mode %d/%d", display, ret); + return ret; + } +@@ -457,7 +470,9 @@ int DrmDevice::CreateDisplayPipe(DrmConnector *connector) { + if (!ret) { + connector->set_encoder(enc); + return 0; +- } else if (ret != -EAGAIN) { ++ } ++ ++ if (ret != -EAGAIN) { + ALOGE("Could not set mode %d/%d", display, ret); + return ret; + } +@@ -470,7 +485,7 @@ int DrmDevice::CreateDisplayPipe(DrmConnector *connector) { + // Attach writeback connector to the CRTC linked to the display_conn + int DrmDevice::AttachWriteback(DrmConnector *display_conn) { + DrmCrtc *display_crtc = display_conn->encoder()->crtc(); +- if (GetWritebackConnectorForDisplay(display_crtc->display()) != NULL) { ++ if (GetWritebackConnectorForDisplay(display_crtc->display()) != nullptr) { + ALOGE("Display already has writeback attach to it"); + return -EINVAL; + } +@@ -496,9 +511,8 @@ int DrmDevice::AttachWriteback(DrmConnector *display_conn) { + } + + int DrmDevice::CreatePropertyBlob(void *data, size_t length, +- uint32_t *blob_id) { +- struct drm_mode_create_blob create_blob; +- memset(&create_blob, 0, sizeof(create_blob)); ++ uint32_t *blob_id) const { ++ struct drm_mode_create_blob create_blob {}; + create_blob.length = length; + create_blob.data = (__u64)data; + +@@ -511,12 +525,11 @@ int DrmDevice::CreatePropertyBlob(void *data, size_t length, + return 0; + } + +-int DrmDevice::DestroyPropertyBlob(uint32_t blob_id) { ++int DrmDevice::DestroyPropertyBlob(uint32_t blob_id) const { + if (!blob_id) + return 0; + +- struct drm_mode_destroy_blob destroy_blob; +- memset(&destroy_blob, 0, sizeof(destroy_blob)); ++ struct drm_mode_destroy_blob destroy_blob {}; + destroy_blob.blob_id = (__u32)blob_id; + int ret = drmIoctl(fd(), DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob); + if (ret) { +@@ -531,8 +544,8 @@ DrmEventListener *DrmDevice::event_listener() { + } + + int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type, +- const char *prop_name, DrmProperty *property) { +- drmModeObjectPropertiesPtr props; ++ const char *prop_name, DrmProperty *property) const { ++ drmModeObjectPropertiesPtr props = nullptr; + + props = drmModeObjectGetProperties(fd(), obj_id, obj_type); + if (!props) { +@@ -570,4 +583,16 @@ int DrmDevice::GetConnectorProperty(const DrmConnector &connector, + return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name, + property); + } ++ ++std::string DrmDevice::GetName() const { ++ auto *ver = drmGetVersion(fd()); ++ if (!ver) { ++ ALOGW("Failed to get drm version for fd=%d", fd()); ++ return "generic"; ++ } ++ ++ std::string name(ver->name); ++ drmFreeVersion(ver); ++ return name; ++} + } // namespace android +diff --git a/include/drmdevice.h b/drm/DrmDevice.h +similarity index 81% +rename from include/drmdevice.h +rename to drm/DrmDevice.h +index 91dd38b..dfca263 100644 +--- a/include/drmdevice.h ++++ b/drm/DrmDevice.h +@@ -17,18 +17,24 @@ + #ifndef ANDROID_DRM_H_ + #define ANDROID_DRM_H_ + +-#include "drmconnector.h" +-#include "drmcrtc.h" +-#include "drmencoder.h" +-#include "drmeventlistener.h" +-#include "drmplane.h" +-#include "platform.h" +- + #include ++ ++#include + #include + ++#include "DrmConnector.h" ++#include "DrmCrtc.h" ++#include "DrmEncoder.h" ++#include "DrmEventListener.h" ++#include "DrmFbImporter.h" ++#include "DrmPlane.h" ++#include "utils/UniqueFd.h" ++ + namespace android { + ++class DrmFbImporter; ++class DrmPlane; ++ + class DrmDevice { + public: + DrmDevice(); +@@ -37,7 +43,7 @@ class DrmDevice { + std::tuple Init(const char *path, int num_displays); + + int fd() const { +- return fd_.get(); ++ return fd_.Get(); + } + + const std::vector> &connectors() const { +@@ -70,20 +76,30 @@ class DrmDevice { + int GetConnectorProperty(const DrmConnector &connector, const char *prop_name, + DrmProperty *property); + ++ std::string GetName() const; ++ + const std::vector> &crtcs() const; + uint32_t next_mode_id(); + +- int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id); +- int DestroyPropertyBlob(uint32_t blob_id); ++ int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id) const; ++ int DestroyPropertyBlob(uint32_t blob_id) const; + bool HandlesDisplay(int display) const; + void RegisterHotplugHandler(DrmEventHandler *handler) { + event_listener_.RegisterHotplugHandler(handler); + } + ++ bool HasAddFb2ModifiersSupport() const { ++ return HasAddFb2ModifiersSupport_; ++ } ++ ++ DrmFbImporter &GetDrmFbImporter() { ++ return *mDrmFbImporter.get(); ++ } ++ + private: + int TryEncoderForDisplay(int display, DrmEncoder *enc); + int GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name, +- DrmProperty *property); ++ DrmProperty *property) const; + + int CreateDisplayPipe(DrmConnector *connector); + int AttachWriteback(DrmConnector *display_conn); +@@ -101,6 +117,12 @@ class DrmDevice { + std::pair min_resolution_; + std::pair max_resolution_; + std::map displays_; ++ ++ bool HasAddFb2ModifiersSupport_{}; ++ ++ std::shared_ptr self; ++ ++ std::unique_ptr mDrmFbImporter; + }; + } // namespace android + +diff --git a/drm/drmencoder.cpp b/drm/DrmEncoder.cpp +similarity index 79% +rename from drm/drmencoder.cpp +rename to drm/DrmEncoder.cpp +index c36fca1..ad05f88 100644 +--- a/drm/drmencoder.cpp ++++ b/drm/DrmEncoder.cpp +@@ -14,21 +14,22 @@ + * limitations under the License. + */ + +-#include "drmencoder.h" +-#include "drmcrtc.h" +-#include "drmdevice.h" ++#include "DrmEncoder.h" + +-#include + #include + ++#include ++ ++#include "DrmDevice.h" ++ + namespace android { + + DrmEncoder::DrmEncoder(drmModeEncoderPtr e, DrmCrtc *current_crtc, +- const std::vector &possible_crtcs) ++ std::vector possible_crtcs) + : id_(e->encoder_id), + crtc_(current_crtc), + display_(-1), +- possible_crtcs_(possible_crtcs) { ++ possible_crtcs_(std::move(possible_crtcs)) { + } + + uint32_t DrmEncoder::id() const { +@@ -39,8 +40,8 @@ DrmCrtc *DrmEncoder::crtc() const { + return crtc_; + } + +-bool DrmEncoder::CanClone(DrmEncoder *possible_clone) { +- return possible_clones_.find(possible_clone) != possible_clones_.end(); ++bool DrmEncoder::CanClone(DrmEncoder *encoder) { ++ return possible_clones_.find(encoder) != possible_clones_.end(); + } + + void DrmEncoder::AddPossibleClone(DrmEncoder *possible_clone) { +diff --git a/include/drmencoder.h b/drm/DrmEncoder.h +similarity index 94% +rename from include/drmencoder.h +rename to drm/DrmEncoder.h +index 8a7f682..4c01bc1 100644 +--- a/include/drmencoder.h ++++ b/drm/DrmEncoder.h +@@ -17,19 +17,20 @@ + #ifndef ANDROID_DRM_ENCODER_H_ + #define ANDROID_DRM_ENCODER_H_ + +-#include "drmcrtc.h" +- + #include + #include ++ + #include + #include + ++#include "DrmCrtc.h" ++ + namespace android { + + class DrmEncoder { + public: + DrmEncoder(drmModeEncoderPtr e, DrmCrtc *current_crtc, +- const std::vector &possible_crtcs); ++ std::vector possible_crtcs); + DrmEncoder(const DrmEncoder &) = delete; + DrmEncoder &operator=(const DrmEncoder &) = delete; + +diff --git a/drm/drmeventlistener.cpp b/drm/DrmEventListener.cpp +similarity index 68% +rename from drm/drmeventlistener.cpp +rename to drm/DrmEventListener.cpp +index ccee0d6..b303653 100644 +--- a/drm/drmeventlistener.cpp ++++ b/drm/DrmEventListener.cpp +@@ -16,19 +16,22 @@ + + #define LOG_TAG "hwc-drm-event-listener" + +-#include "drmeventlistener.h" +-#include "drmdevice.h" ++#include "DrmEventListener.h" + +-#include +-#include + #include + #include +- +-#include +-#include +-#include + #include + ++#include ++#include ++#include ++ ++#include "DrmDevice.h" ++#include "utils/log.h" ++ ++/* Originally defined in system/core/libsystem/include/system/graphics.h */ ++#define HAL_PRIORITY_URGENT_DISPLAY (-8) ++ + namespace android { + + DrmEventListener::DrmEventListener(DrmDevice *drm) +@@ -36,28 +39,29 @@ DrmEventListener::DrmEventListener(DrmDevice *drm) + } + + int DrmEventListener::Init() { +- uevent_fd_.Set(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)); +- if (uevent_fd_.get() < 0) { ++ uevent_fd_ = UniqueFd( ++ socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)); ++ if (!uevent_fd_) { + ALOGE("Failed to open uevent socket: %s", strerror(errno)); +- return uevent_fd_.get(); ++ return -errno; + } + +- struct sockaddr_nl addr; +- memset(&addr, 0, sizeof(addr)); ++ struct sockaddr_nl addr {}; + addr.nl_family = AF_NETLINK; + addr.nl_pid = 0; + addr.nl_groups = 0xFFFFFFFF; + +- int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr)); ++ int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr)); + if (ret) { + ALOGE("Failed to bind uevent socket: %s", strerror(errno)); + return -errno; + } + ++ // NOLINTNEXTLINE(readability-isolate-declaration) + FD_ZERO(&fds_); + FD_SET(drm_->fd(), &fds_); +- FD_SET(uevent_fd_.get(), &fds_); +- max_fd_ = std::max(drm_->fd(), uevent_fd_.get()); ++ FD_SET(uevent_fd_.Get(), &fds_); ++ max_fd_ = std::max(drm_->fd(), uevent_fd_.Get()); + + return InitWorker(); + } +@@ -70,19 +74,20 @@ void DrmEventListener::RegisterHotplugHandler(DrmEventHandler *handler) { + void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) { +- DrmEventHandler *handler = (DrmEventHandler *)user_data; ++ auto *handler = (DrmEventHandler *)user_data; + if (!handler) + return; + + handler->HandleEvent((uint64_t)tv_sec * 1000 * 1000 + tv_usec); +- delete handler; ++ delete handler; // NOLINT(cppcoreguidelines-owning-memory) + } + + void DrmEventListener::UEventHandler() { + char buffer[1024]; +- int ret; ++ int ret = 0; ++ ++ struct timespec ts {}; + +- struct timespec ts; + uint64_t timestamp = 0; + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + if (!ret) +@@ -91,10 +96,11 @@ void DrmEventListener::UEventHandler() { + ALOGE("Failed to get monotonic clock on hotplug %d", ret); + + while (true) { +- ret = read(uevent_fd_.get(), &buffer, sizeof(buffer)); +- if (ret == 0) { ++ ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer)); ++ if (ret == 0) + return; +- } else if (ret < 0) { ++ ++ if (ret < 0) { + ALOGE("Got error reading uevent %d", ret); + return; + } +@@ -102,12 +108,13 @@ void DrmEventListener::UEventHandler() { + if (!hotplug_handler_) + continue; + +- bool drm_event = false, hotplug_event = false; +- for (int i = 0; i < ret;) { ++ bool drm_event = false; ++ bool hotplug_event = false; ++ for (uint32_t i = 0; i < ret;) { + char *event = buffer + i; +- if (strcmp(event, "DEVTYPE=drm_minor")) ++ if (strcmp(event, "DEVTYPE=drm_minor") != 0) + drm_event = true; +- else if (strcmp(event, "HOTPLUG=1")) ++ else if (strcmp(event, "HOTPLUG=1") != 0) + hotplug_event = true; + + i += strlen(event) + 1; +@@ -119,20 +126,20 @@ void DrmEventListener::UEventHandler() { + } + + void DrmEventListener::Routine() { +- int ret; ++ int ret = 0; + do { +- ret = select(max_fd_ + 1, &fds_, NULL, NULL, NULL); ++ ret = select(max_fd_ + 1, &fds_, nullptr, nullptr, nullptr); + } while (ret == -1 && errno == EINTR); + + if (FD_ISSET(drm_->fd(), &fds_)) { + drmEventContext event_context = + {.version = 2, +- .vblank_handler = NULL, ++ .vblank_handler = nullptr, + .page_flip_handler = DrmEventListener::FlipHandler}; + drmHandleEvent(drm_->fd(), &event_context); + } + +- if (FD_ISSET(uevent_fd_.get(), &fds_)) ++ if (FD_ISSET(uevent_fd_.Get(), &fds_)) + UEventHandler(); + } + } // namespace android +diff --git a/include/drmeventlistener.h b/drm/DrmEventListener.h +similarity index 95% +rename from include/drmeventlistener.h +rename to drm/DrmEventListener.h +index 95672ee..f1f7310 100644 +--- a/include/drmeventlistener.h ++++ b/drm/DrmEventListener.h +@@ -17,8 +17,8 @@ + #ifndef ANDROID_DRM_EVENT_LISTENER_H_ + #define ANDROID_DRM_EVENT_LISTENER_H_ + +-#include "autofd.h" +-#include "worker.h" ++#include "utils/UniqueFd.h" ++#include "utils/Worker.h" + + namespace android { + +@@ -53,7 +53,7 @@ class DrmEventListener : public Worker { + private: + void UEventHandler(); + +- fd_set fds_; ++ fd_set fds_{}; + UniqueFd uevent_fd_; + int max_fd_ = -1; + +diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp +new file mode 100644 +index 0000000..592fc48 +--- /dev/null ++++ b/drm/DrmFbImporter.cpp +@@ -0,0 +1,151 @@ ++/* ++ * Copyright (C) 2021 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. ++ */ ++ ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define LOG_TAG "hwc-platform-drm-generic" ++ ++#include "DrmFbImporter.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "utils/log.h" ++#include "utils/properties.h" ++ ++namespace android { ++ ++auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, ++ const std::shared_ptr &drm) ++ -> std::shared_ptr { ++ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage ++ std::shared_ptr local(new DrmFbIdHandle(drm)); ++ ++ local->gem_handles_[0] = first_gem_handle; ++ int32_t err = 0; ++ ++ /* Framebuffer object creation require gem handle for every used plane */ ++ for (int i = 1; i < local->gem_handles_.size(); i++) { ++ if (bo->prime_fds[i] > 0) { ++ if (bo->prime_fds[i] != bo->prime_fds[0]) { ++ err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i], ++ &local->gem_handles_.at(i)); ++ if (err != 0) { ++ ALOGE("failed to import prime fd %d errno=%d", bo->prime_fds[i], ++ errno); ++ } ++ } else { ++ local->gem_handles_.at(i) = local->gem_handles_[0]; ++ } ++ } ++ } ++ ++ bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE && ++ bo->modifiers[0] != DRM_FORMAT_MOD_INVALID; ++ ++ if (!drm->HasAddFb2ModifiersSupport() && has_modifiers) { ++ ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64, ++ bo->modifiers[0]); ++ local.reset(); ++ return local; ++ } ++ ++ /* Create framebuffer object */ ++ if (!has_modifiers) { ++ err = drmModeAddFB2(drm->fd(), bo->width, bo->height, bo->format, ++ &local->gem_handles_[0], &bo->pitches[0], ++ &bo->offsets[0], &local->fb_id_, 0); ++ } else { ++ err = drmModeAddFB2WithModifiers(drm->fd(), bo->width, bo->height, ++ bo->format, &local->gem_handles_[0], ++ &bo->pitches[0], &bo->offsets[0], ++ &bo->modifiers[0], &local->fb_id_, ++ DRM_MODE_FB_MODIFIERS); ++ } ++ if (err != 0) { ++ ALOGE("could not create drm fb %d", err); ++ local.reset(); ++ } ++ ++ return local; ++} ++ ++DrmFbIdHandle::~DrmFbIdHandle() { ++ /* Destroy framebuffer object */ ++ if (drmModeRmFB(drm_->fd(), fb_id_) != 0) { ++ ALOGE("Failed to rm fb"); ++ } ++ ++ /* Close GEM handles. ++ * ++ * WARNING: TODO(nobody): ++ * From Linux side libweston relies on libgbm to get KMS handle and never ++ * closes it (handle is closed by libgbm on buffer destruction) ++ * Probably we should offer similar approach to users (at least on user ++ * request via system properties) ++ */ ++ struct drm_gem_close gem_close {}; ++ for (unsigned int gem_handle : gem_handles_) { ++ if (gem_handle == 0) { ++ continue; ++ } ++ gem_close.handle = gem_handle; ++ int32_t err = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); ++ if (err != 0) { ++ ALOGE("Failed to close gem handle %d, errno: %d", gem_handle, errno); ++ } ++ } ++} ++ ++auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo) ++ -> std::shared_ptr { ++ /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */ ++ GemHandle first_handle = 0; ++ int32_t err = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &first_handle); ++ ++ if (err != 0) { ++ ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err); ++ return std::shared_ptr(); ++ } ++ ++ auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle); ++ ++ if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) { ++ if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second.lock()) { ++ return drm_fb_id_handle_shared; ++ } ++ drm_fb_id_handle_cache_.erase(drm_fb_id_cached); ++ } ++ ++ /* Cleanup cached empty weak pointers */ ++ const int minimal_cleanup_size = 128; ++ if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) { ++ CleanupEmptyCacheElements(); ++ } ++ ++ /* No DrmFbIdHandle found in cache, create framebuffer object */ ++ auto fb_id_handle = DrmFbIdHandle::CreateInstance(bo, first_handle, drm_); ++ if (fb_id_handle) { ++ drm_fb_id_handle_cache_[first_handle] = fb_id_handle; ++ } ++ ++ return fb_id_handle; ++} ++ ++} // namespace android +diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h +new file mode 100644 +index 0000000..167aa60 +--- /dev/null ++++ b/drm/DrmFbImporter.h +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (C) 2021 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 DRM_DRMFBIMPORTER_H_ ++#define DRM_DRMFBIMPORTER_H_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "drm/DrmDevice.h" ++#include "drmhwcgralloc.h" ++ ++#ifndef DRM_FORMAT_INVALID ++#define DRM_FORMAT_INVALID 0 ++#endif ++ ++using GemHandle = uint32_t; ++ ++namespace android { ++ ++class DrmFbIdHandle { ++ public: ++ static auto CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, ++ const std::shared_ptr &drm) ++ -> std::shared_ptr; ++ ++ ~DrmFbIdHandle(); ++ DrmFbIdHandle(DrmFbIdHandle &&) = delete; ++ DrmFbIdHandle(const DrmFbIdHandle &) = delete; ++ auto operator=(const DrmFbIdHandle &) = delete; ++ auto operator=(DrmFbIdHandle &&) = delete; ++ ++ auto GetFbId [[nodiscard]] () const -> uint32_t { ++ return fb_id_; ++ } ++ ++ private: ++ explicit DrmFbIdHandle(std::shared_ptr drm) ++ : drm_(std::move(drm)){}; ++ ++ const std::shared_ptr drm_; ++ ++ uint32_t fb_id_{}; ++ std::array gem_handles_{}; ++}; ++ ++class DrmFbImporter { ++ public: ++ explicit DrmFbImporter(std::shared_ptr drm) ++ : drm_(std::move(drm)){}; ++ ~DrmFbImporter() = default; ++ DrmFbImporter(const DrmFbImporter &) = delete; ++ DrmFbImporter(DrmFbImporter &&) = delete; ++ auto operator=(const DrmFbImporter &) = delete; ++ auto operator=(DrmFbImporter &&) = delete; ++ ++ auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr; ++ ++ private: ++ void CleanupEmptyCacheElements() { ++ for (auto it = drm_fb_id_handle_cache_.begin(); ++ it != drm_fb_id_handle_cache_.end();) { ++ if (it->second.expired()) { ++ it = drm_fb_id_handle_cache_.erase(it); ++ } else { ++ ++it; ++ } ++ } ++ } ++ ++ const std::shared_ptr drm_; ++ ++ std::map> drm_fb_id_handle_cache_; ++}; ++ ++} // namespace android ++ ++#endif +diff --git a/drm/drmmode.cpp b/drm/DrmMode.cpp +similarity index 93% +rename from drm/drmmode.cpp +rename to drm/DrmMode.cpp +index c3ab385..dd25758 100644 +--- a/drm/drmmode.cpp ++++ b/drm/DrmMode.cpp +@@ -14,18 +14,16 @@ + * limitations under the License. + */ + +-#include "drmmode.h" +-#include "drmdevice.h" ++#include "DrmMode.h" + +-#include +-#include +-#include ++#include ++ ++#include "DrmDevice.h" + + namespace android { + + DrmMode::DrmMode(drmModeModeInfoPtr m) +- : id_(0), +- clock_(m->clock), ++ : clock_(m->clock), + h_display_(m->hdisplay), + h_sync_start_(m->hsync_start), + h_sync_end_(m->hsync_end), +@@ -123,7 +121,7 @@ uint32_t DrmMode::v_scan() const { + + float DrmMode::v_refresh() const { + // Always recalculate refresh to report correct float rate +- return clock_ / (float)(v_total_ * h_total_) * 1000.0f; ++ return clock_ / (float)(v_total_ * h_total_) * 1000.0F; + } + + uint32_t DrmMode::flags() const { +diff --git a/include/drmmode.h b/drm/DrmMode.h +similarity index 99% +rename from include/drmmode.h +rename to drm/DrmMode.h +index 4cc06b1..313a8ea 100644 +--- a/include/drmmode.h ++++ b/drm/DrmMode.h +@@ -19,6 +19,7 @@ + + #include + #include ++ + #include + + namespace android { +diff --git a/drm/drmplane.cpp b/drm/DrmPlane.cpp +similarity index 56% +rename from drm/drmplane.cpp +rename to drm/DrmPlane.cpp +index 6f1bf9b..6433fb6 100644 +--- a/drm/drmplane.cpp ++++ b/drm/DrmPlane.cpp +@@ -16,20 +16,24 @@ + + #define LOG_TAG "hwc-drm-plane" + +-#include "drmplane.h" +-#include "drmdevice.h" ++#include "DrmPlane.h" + +-#include +-#include ++#include ++#include + #include ++#include + +-#include +-#include ++#include "DrmDevice.h" ++#include "bufferinfo/BufferInfoGetter.h" ++#include "utils/log.h" + + namespace android { + + DrmPlane::DrmPlane(DrmDevice *drm, drmModePlanePtr p) +- : drm_(drm), id_(p->plane_id), possible_crtc_mask_(p->possible_crtcs) { ++ : drm_(drm), ++ id_(p->plane_id), ++ possible_crtc_mask_(p->possible_crtcs), ++ formats_(p->formats, p->formats + p->count_formats) { + } + + int DrmPlane::Init() { +@@ -41,7 +45,7 @@ int DrmPlane::Init() { + return ret; + } + +- uint64_t type; ++ uint64_t type = 0; + std::tie(ret, type) = p.value(); + if (ret) { + ALOGE("Failed to get plane type property value"); +@@ -138,6 +142,17 @@ int DrmPlane::Init() { + if (ret) + ALOGI("Could not get IN_FENCE_FD property"); + ++ if (HasNonRgbFormat()) { ++ ret = drm_->GetPlaneProperty(*this, "COLOR_ENCODING", ++ &color_encoding_propery_); ++ if (ret) ++ ALOGI("Could not get COLOR_ENCODING property"); ++ ++ ret = drm_->GetPlaneProperty(*this, "COLOR_RANGE", &color_range_property_); ++ if (ret) ++ ALOGI("Could not get COLOR_RANGE property"); ++ } ++ + return 0; + } + +@@ -146,13 +161,102 @@ uint32_t DrmPlane::id() const { + } + + bool DrmPlane::GetCrtcSupported(const DrmCrtc &crtc) const { +- return !!((1 << crtc.pipe()) & possible_crtc_mask_); ++ return ((1 << crtc.pipe()) & possible_crtc_mask_) != 0; ++} ++ ++bool DrmPlane::IsValidForLayer(DrmHwcLayer *layer) { ++ if (rotation_property_.id() == 0) { ++ if (layer->transform != DrmHwcTransform::kIdentity) { ++ ALOGV("Rotation is not supported on plane %d", id_); ++ return false; ++ } ++ } else { ++ // For rotation checks, we assume the hardware reports its capabilities ++ // consistently (e.g. a 270 degree rotation is a 90 degree rotation + H ++ // flip + V flip; it wouldn't make sense to support all of the latter but ++ // not the former). ++ int ret = 0; ++ const std::pair transforms[] = ++ {{kFlipH, "reflect-x"}, ++ {kFlipV, "reflect-y"}, ++ {kRotate90, "rotate-90"}, ++ {kRotate180, "rotate-180"}, ++ {kRotate270, "rotate-270"}}; ++ ++ for (const auto &[transform, name] : transforms) { ++ if (layer->transform & transform) { ++ std::tie(std::ignore, ++ ret) = rotation_property_.GetEnumValueWithName(name); ++ if (ret) { ++ ALOGV("Rotation '%s' is not supported on plane %d", name.c_str(), ++ id_); ++ return false; ++ } ++ } ++ } ++ } ++ ++ if (alpha_property_.id() == 0 && layer->alpha != 0xffff) { ++ ALOGV("Alpha is not supported on plane %d", id_); ++ return false; ++ } ++ ++ if (blend_property_.id() == 0) { ++ if ((layer->blending != DrmHwcBlending::kNone) && ++ (layer->blending != DrmHwcBlending::kPreMult)) { ++ ALOGV("Blending is not supported on plane %d", id_); ++ return false; ++ } ++ } else { ++ int ret = 0; ++ ++ switch (layer->blending) { ++ case DrmHwcBlending::kPreMult: ++ std::tie(std::ignore, ++ ret) = blend_property_.GetEnumValueWithName("Pre-multiplied"); ++ break; ++ case DrmHwcBlending::kCoverage: ++ std::tie(std::ignore, ++ ret) = blend_property_.GetEnumValueWithName("Coverage"); ++ break; ++ case DrmHwcBlending::kNone: ++ default: ++ std::tie(std::ignore, ++ ret) = blend_property_.GetEnumValueWithName("None"); ++ break; ++ } ++ if (ret) { ++ ALOGV("Expected a valid blend mode on plane %d", id_); ++ return false; ++ } ++ } ++ ++ uint32_t format = layer->buffer_info.format; ++ if (!IsFormatSupported(format)) { ++ ALOGV("Plane %d does not supports %c%c%c%c format", id_, format, ++ format >> 8, format >> 16, format >> 24); ++ return false; ++ } ++ ++ return true; + } + + uint32_t DrmPlane::type() const { + return type_; + } + ++bool DrmPlane::IsFormatSupported(uint32_t format) const { ++ return std::find(std::begin(formats_), std::end(formats_), format) != ++ std::end(formats_); ++} ++ ++bool DrmPlane::HasNonRgbFormat() const { ++ return std::find_if_not(std::begin(formats_), std::end(formats_), ++ [](uint32_t format) { ++ return BufferInfoGetter::IsDrmFormatRgb(format); ++ }) != std::end(formats_); ++} ++ + const DrmProperty &DrmPlane::crtc_property() const { + return crtc_property_; + } +@@ -212,4 +316,12 @@ const DrmProperty &DrmPlane::blend_property() const { + const DrmProperty &DrmPlane::in_fence_fd_property() const { + return in_fence_fd_property_; + } ++ ++const DrmProperty &DrmPlane::color_encoding_propery() const { ++ return color_encoding_propery_; ++} ++ ++const DrmProperty &DrmPlane::color_range_property() const { ++ return color_range_property_; ++} + } // namespace android +diff --git a/include/drmplane.h b/drm/DrmPlane.h +similarity index 84% +rename from include/drmplane.h +rename to drm/DrmPlane.h +index 43e0e8a..862a0f3 100644 +--- a/include/drmplane.h ++++ b/drm/DrmPlane.h +@@ -17,13 +17,15 @@ + #ifndef ANDROID_DRM_PLANE_H_ + #define ANDROID_DRM_PLANE_H_ + +-#include "drmcrtc.h" +-#include "drmproperty.h" +- + #include + #include ++ + #include + ++#include "DrmCrtc.h" ++#include "DrmProperty.h" ++#include "drmhwcomposer.h" ++ + namespace android { + + class DrmDevice; +@@ -39,9 +41,13 @@ class DrmPlane { + uint32_t id() const; + + bool GetCrtcSupported(const DrmCrtc &crtc) const; ++ bool IsValidForLayer(DrmHwcLayer *layer); + + uint32_t type() const; + ++ bool IsFormatSupported(uint32_t format) const; ++ bool HasNonRgbFormat() const; ++ + const DrmProperty &crtc_property() const; + const DrmProperty &fb_property() const; + const DrmProperty &crtc_x_property() const; +@@ -57,6 +63,8 @@ class DrmPlane { + const DrmProperty &alpha_property() const; + const DrmProperty &blend_property() const; + const DrmProperty &in_fence_fd_property() const; ++ const DrmProperty &color_encoding_propery() const; ++ const DrmProperty &color_range_property() const; + + private: + DrmDevice *drm_; +@@ -64,7 +72,9 @@ class DrmPlane { + + uint32_t possible_crtc_mask_; + +- uint32_t type_; ++ uint32_t type_{}; ++ ++ std::vector formats_; + + DrmProperty crtc_property_; + DrmProperty fb_property_; +@@ -81,6 +91,8 @@ class DrmPlane { + DrmProperty alpha_property_; + DrmProperty blend_property_; + DrmProperty in_fence_fd_property_; ++ DrmProperty color_encoding_propery_; ++ DrmProperty color_range_property_; + }; + } // namespace android + +diff --git a/drm/drmproperty.cpp b/drm/DrmProperty.cpp +similarity index 83% +rename from drm/drmproperty.cpp +rename to drm/DrmProperty.cpp +index 3aeed13..8e6f7e5 100644 +--- a/drm/drmproperty.cpp ++++ b/drm/DrmProperty.cpp +@@ -14,14 +14,15 @@ + * limitations under the License. + */ + +-#include "drmproperty.h" +-#include "drmdevice.h" ++#include "DrmProperty.h" + +-#include +-#include ++#include ++ ++#include ++#include + #include + +-#include ++#include "DrmDevice.h" + + namespace android { + +@@ -29,11 +30,7 @@ DrmProperty::DrmPropertyEnum::DrmPropertyEnum(drm_mode_property_enum *e) + : value_(e->value), name_(e->name) { + } + +-DrmProperty::DrmPropertyEnum::~DrmPropertyEnum() { +-} +- +-DrmProperty::DrmProperty(drmModePropertyPtr p, uint64_t value) +- : id_(0), type_(DRM_PROPERTY_TYPE_INVALID), flags_(0), name_("") { ++DrmProperty::DrmProperty(drmModePropertyPtr p, uint64_t value) { + Init(p, value); + } + +@@ -44,13 +41,13 @@ void DrmProperty::Init(drmModePropertyPtr p, uint64_t value) { + value_ = value; + + for (int i = 0; i < p->count_values; ++i) +- values_.push_back(p->values[i]); ++ values_.emplace_back(p->values[i]); + + for (int i = 0; i < p->count_enums; ++i) +- enums_.push_back(DrmPropertyEnum(&p->enums[i])); ++ enums_.emplace_back(DrmPropertyEnum(&p->enums[i])); + + for (int i = 0; i < p->count_blobs; ++i) +- blob_ids_.push_back(p->blob_ids[i]); ++ blob_ids_.emplace_back(p->blob_ids[i]); + + if (flags_ & DRM_MODE_PROP_RANGE) + type_ = DRM_PROPERTY_TYPE_INT; +@@ -60,6 +57,8 @@ void DrmProperty::Init(drmModePropertyPtr p, uint64_t value) { + type_ = DRM_PROPERTY_TYPE_OBJECT; + else if (flags_ & DRM_MODE_PROP_BLOB) + type_ = DRM_PROPERTY_TYPE_BLOB; ++ else if (flags_ & DRM_MODE_PROP_BITMASK) ++ type_ = DRM_PROPERTY_TYPE_BITMASK; + } + + uint32_t DrmProperty::id() const { +@@ -74,7 +73,7 @@ std::tuple DrmProperty::value() const { + if (type_ == DRM_PROPERTY_TYPE_BLOB) + return std::make_tuple(0, value_); + +- if (values_.size() == 0) ++ if (values_.empty()) + return std::make_tuple(-ENOENT, 0); + + switch (type_) { +@@ -90,6 +89,7 @@ std::tuple DrmProperty::value() const { + case DRM_PROPERTY_TYPE_OBJECT: + return std::make_tuple(0, value_); + ++ case DRM_PROPERTY_TYPE_BITMASK: + default: + return std::make_tuple(-EINVAL, 0); + } +@@ -106,7 +106,7 @@ bool DrmProperty::is_range() const { + std::tuple DrmProperty::range_min() const { + if (!is_range()) + return std::make_tuple(-EINVAL, 0); +- if (values_.size() < 1) ++ if (values_.empty()) + return std::make_tuple(-ENOENT, 0); + + return std::make_tuple(0, values_[0]); +@@ -122,9 +122,9 @@ std::tuple DrmProperty::range_max() const { + } + + std::tuple DrmProperty::GetEnumValueWithName( +- std::string name) const { +- for (auto it : enums_) { +- if (it.name_.compare(name) == 0) { ++ const std::string &name) const { ++ for (const auto &it : enums_) { ++ if (it.name_ == name) { + return std::make_tuple(it.value_, 0); + } + } +diff --git a/include/drmproperty.h b/drm/DrmProperty.h +similarity index 92% +rename from include/drmproperty.h +rename to drm/DrmProperty.h +index 2d92ca1..70678fd 100644 +--- a/include/drmproperty.h ++++ b/drm/DrmProperty.h +@@ -19,6 +19,7 @@ + + #include + #include ++ + #include + #include + +@@ -29,6 +30,7 @@ enum DrmPropertyType { + DRM_PROPERTY_TYPE_ENUM, + DRM_PROPERTY_TYPE_OBJECT, + DRM_PROPERTY_TYPE_BLOB, ++ DRM_PROPERTY_TYPE_BITMASK, + DRM_PROPERTY_TYPE_INVALID, + }; + +@@ -40,7 +42,7 @@ class DrmProperty { + DrmProperty &operator=(const DrmProperty &) = delete; + + void Init(drmModePropertyPtr p, uint64_t value); +- std::tuple GetEnumValueWithName(std::string name) const; ++ std::tuple GetEnumValueWithName(const std::string &name) const; + + uint32_t id() const; + std::string name() const; +@@ -56,7 +58,7 @@ class DrmProperty { + class DrmPropertyEnum { + public: + DrmPropertyEnum(drm_mode_property_enum *e); +- ~DrmPropertyEnum(); ++ ~DrmPropertyEnum() = default; + + uint64_t value_; + std::string name_; +diff --git a/drm/resourcemanager.cpp b/drm/ResourceManager.cpp +similarity index 66% +rename from drm/resourcemanager.cpp +rename to drm/ResourceManager.cpp +index da1a2db..ef44180 100644 +--- a/drm/resourcemanager.cpp ++++ b/drm/ResourceManager.cpp +@@ -16,23 +16,28 @@ + + #define LOG_TAG "hwc-resource-manager" + +-#include "resourcemanager.h" ++#include "ResourceManager.h" ++ ++#include ++#include + +-#include +-#include + #include +-#include ++ ++#include "bufferinfo/BufferInfoGetter.h" ++#include "utils/log.h" ++#include "utils/properties.h" + + namespace android { + +-ResourceManager::ResourceManager() : num_displays_(0), gralloc_(NULL) { ++ResourceManager::ResourceManager() : num_displays_(0), gralloc_(nullptr) { + } + + int ResourceManager::Init() { + char path_pattern[PROPERTY_VALUE_MAX]; + // Could be a valid path or it can have at the end of it the wildcard % + // which means that it will try open all devices until an error is met. +- int path_len = property_get("hwc.drm.device", path_pattern, "/dev/dri/card0"); ++ int path_len = property_get("vendor.hwc.drm.device", path_pattern, ++ "/dev/dri/card%"); + int ret = 0; + if (path_pattern[path_len - 1] != '%') { + ret = AddDrmDevice(std::string(path_pattern)); +@@ -41,7 +46,13 @@ int ResourceManager::Init() { + for (int idx = 0; !ret; ++idx) { + std::ostringstream path; + path << path_pattern << idx; +- ret = AddDrmDevice(path.str()); ++ ++ struct stat buf {}; ++ if (stat(path.str().c_str(), &buf)) ++ break; ++ ++ if (IsKMSDev(path.str().c_str())) ++ ret = AddDrmDevice(path.str()); + } + } + +@@ -51,26 +62,23 @@ int ResourceManager::Init() { + } + + char scale_with_gpu[PROPERTY_VALUE_MAX]; +- property_get("hwc.drm.scale_with_gpu", scale_with_gpu, "0"); ++ property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0"); + scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1)); + ++ if (!BufferInfoGetter::GetInstance()) { ++ ALOGE("Failed to initialize BufferInfoGetter"); ++ return -EINVAL; ++ } ++ + return hw_get_module(GRALLOC_HARDWARE_MODULE_ID, + (const hw_module_t **)&gralloc_); + } + +-int ResourceManager::AddDrmDevice(std::string path) { +- std::unique_ptr drm = std::make_unique(); +- int displays_added, ret; ++int ResourceManager::AddDrmDevice(const std::string &path) { ++ auto drm = std::make_unique(); ++ int displays_added = 0; ++ int ret = 0; + std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_); +- if (ret) +- return ret; +- std::shared_ptr importer; +- importer.reset(Importer::CreateInstance(drm.get())); +- if (!importer) { +- ALOGE("Failed to create importer instance"); +- return -ENODEV; +- } +- importers_.push_back(importer); + drms_.push_back(std::move(drm)); + num_displays_ += displays_added; + return ret; +@@ -78,7 +86,7 @@ int ResourceManager::AddDrmDevice(std::string path) { + + DrmConnector *ResourceManager::AvailableWritebackConnector(int display) { + DrmDevice *drm_device = GetDrmDevice(display); +- DrmConnector *writeback_conn = NULL; ++ DrmConnector *writeback_conn = nullptr; + if (drm_device) { + writeback_conn = drm_device->AvailableWritebackConnector(display); + if (writeback_conn) +@@ -94,20 +102,32 @@ DrmConnector *ResourceManager::AvailableWritebackConnector(int display) { + return writeback_conn; + } + ++bool ResourceManager::IsKMSDev(const char *path) { ++ int fd = open(path, O_RDWR | O_CLOEXEC); ++ if (fd < 0) ++ return false; ++ ++ auto *res = drmModeGetResources(fd); ++ if (!res) { ++ close(fd); ++ return false; ++ } ++ ++ bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && ++ res->count_encoders > 0; ++ ++ drmModeFreeResources(res); ++ close(fd); ++ ++ return is_kms; ++} ++ + DrmDevice *ResourceManager::GetDrmDevice(int display) { + for (auto &drm : drms_) { + if (drm->HandlesDisplay(display)) + return drm.get(); + } +- return NULL; +-} +- +-std::shared_ptr ResourceManager::GetImporter(int display) { +- for (unsigned int i = 0; i < drms_.size(); i++) { +- if (drms_[i]->HandlesDisplay(display)) +- return importers_[i]; +- } +- return NULL; ++ return nullptr; + } + + const gralloc_module_t *ResourceManager::gralloc() { +diff --git a/include/resourcemanager.h b/drm/ResourceManager.h +similarity index 87% +rename from include/resourcemanager.h +rename to drm/ResourceManager.h +index 7a86828..9b4155b 100644 +--- a/include/resourcemanager.h ++++ b/drm/ResourceManager.h +@@ -17,11 +17,11 @@ + #ifndef RESOURCEMANAGER_H + #define RESOURCEMANAGER_H + +-#include "drmdevice.h" +-#include "platform.h" +- + #include + ++#include "DrmDevice.h" ++#include "DrmFbImporter.h" ++ + namespace android { + + class ResourceManager { +@@ -31,7 +31,6 @@ class ResourceManager { + ResourceManager &operator=(const ResourceManager &) = delete; + int Init(); + DrmDevice *GetDrmDevice(int display); +- std::shared_ptr GetImporter(int display); + const gralloc_module_t *gralloc(); + DrmConnector *AvailableWritebackConnector(int display); + const std::vector> &getDrmDevices() const { +@@ -45,14 +44,14 @@ class ResourceManager { + } + + private: +- int AddDrmDevice(std::string path); ++ int AddDrmDevice(std::string const &path); ++ static bool IsKMSDev(const char *path); + + int num_displays_; + std::vector> drms_; +- std::vector> importers_; + const gralloc_module_t *gralloc_; + +- bool scale_with_gpu_; ++ bool scale_with_gpu_{}; + }; + } // namespace android + +diff --git a/drm/vsyncworker.cpp b/drm/VSyncWorker.cpp +similarity index 66% +rename from drm/vsyncworker.cpp +rename to drm/VSyncWorker.cpp +index 08ab301..25eeeab 100644 +--- a/drm/vsyncworker.cpp ++++ b/drm/VSyncWorker.cpp +@@ -16,32 +16,27 @@ + + #define LOG_TAG "hwc-vsync-worker" + +-#include "vsyncworker.h" +-#include "drmdevice.h" +-#include "worker.h" ++#include "VSyncWorker.h" + +-#include +-#include + #include + #include +-#include + +-#include +-#include ++#include ++#include ++#include ++ ++#include "utils/log.h" + + namespace android { + + VSyncWorker::VSyncWorker() + : Worker("vsync", HAL_PRIORITY_URGENT_DISPLAY), +- drm_(NULL), ++ drm_(nullptr), + display_(-1), + enabled_(false), + last_timestamp_(-1) { + } + +-VSyncWorker::~VSyncWorker() { +-} +- + int VSyncWorker::Init(DrmDevice *drm, int display) { + drm_ = drm; + display_ = display; +@@ -51,7 +46,15 @@ int VSyncWorker::Init(DrmDevice *drm, int display) { + + void VSyncWorker::RegisterCallback(std::shared_ptr callback) { + Lock(); +- callback_ = callback; ++ callback_ = std::move(callback); ++ Unlock(); ++} ++ ++void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook) { ++ Lock(); ++ vsync_callback_data_ = data; ++ vsync_callback_hook_ = (HWC2_PFN_VSYNC)hook; + Unlock(); + } + +@@ -77,7 +80,7 @@ void VSyncWorker::VSyncControl(bool enabled) { + * Thus, we must sleep until timestamp 687 to maintain phase with the last + * timestamp. + */ +-int64_t VSyncWorker::GetPhasedVSync(int64_t frame_ns, int64_t current) { ++int64_t VSyncWorker::GetPhasedVSync(int64_t frame_ns, int64_t current) const { + if (last_timestamp_ < 0) + return current + frame_ns; + +@@ -88,24 +91,26 @@ int64_t VSyncWorker::GetPhasedVSync(int64_t frame_ns, int64_t current) { + static const int64_t kOneSecondNs = 1 * 1000 * 1000 * 1000; + + int VSyncWorker::SyntheticWaitVBlank(int64_t *timestamp) { +- struct timespec vsync; ++ struct timespec vsync {}; + int ret = clock_gettime(CLOCK_MONOTONIC, &vsync); ++ if (ret) ++ return ret; + +- float refresh = 60.0f; // Default to 60Hz refresh rate ++ float refresh = 60.0F; // Default to 60Hz refresh rate + DrmConnector *conn = drm_->GetConnectorForDisplay(display_); +- if (conn && conn->active_mode().v_refresh() != 0.0f) ++ if (conn && conn->active_mode().v_refresh() != 0.0F) + refresh = conn->active_mode().v_refresh(); + else + ALOGW("Vsync worker active with conn=%p refresh=%f\n", conn, +- conn ? conn->active_mode().v_refresh() : 0.0f); ++ conn ? conn->active_mode().v_refresh() : 0.0F); + + int64_t phased_timestamp = GetPhasedVSync(kOneSecondNs / refresh, + vsync.tv_sec * kOneSecondNs + + vsync.tv_nsec); + vsync.tv_sec = phased_timestamp / kOneSecondNs; +- vsync.tv_nsec = phased_timestamp - (vsync.tv_sec * kOneSecondNs); ++ vsync.tv_nsec = int(phased_timestamp - (vsync.tv_sec * kOneSecondNs)); + do { +- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &vsync, NULL); ++ ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &vsync, nullptr); + } while (ret == -1 && errno == EINTR); + if (ret) + return ret; +@@ -115,7 +120,7 @@ int VSyncWorker::SyntheticWaitVBlank(int64_t *timestamp) { + } + + void VSyncWorker::Routine() { +- int ret; ++ int ret = 0; + + Lock(); + if (!enabled_) { +@@ -143,11 +148,12 @@ void VSyncWorker::Routine() { + DRM_VBLANK_RELATIVE | (high_crtc & DRM_VBLANK_HIGH_CRTC_MASK)); + vblank.request.sequence = 1; + +- int64_t timestamp; ++ int64_t timestamp = 0; + ret = drmWaitVBlank(drm_->fd(), &vblank); +- if (ret == -EINTR) { ++ if (ret == -EINTR) + return; +- } else if (ret) { ++ ++ if (ret) { + ret = SyntheticWaitVBlank(×tamp); + if (ret) + return; +@@ -156,37 +162,17 @@ void VSyncWorker::Routine() { + (int64_t)vblank.reply.tval_usec * 1000; + } + +- /* +- * VSync could be disabled during routine execution so it could potentially +- * lead to crash since callback's inner hook could be invalid anymore. We have +- * no control over lifetime of this hook, therefore we can't rely that it'll +- * be valid after vsync disabling. +- * +- * Blocking VSyncControl to wait until routine +- * will finish execution is logically correct way to fix this issue, but it +- * creates visible lags and stutters, so we have to resort to other ways of +- * mitigating this issue. +- * +- * Doing check before attempt to invoke callback drastically shortens the +- * window when such situation could happen and that allows us to practically +- * avoid this issue. +- * +- * Please note that issue described below is different one and it is related +- * to RegisterCallback, not to disabling vsync via VSyncControl. +- */ + if (!enabled_) + return; +- /* +- * There's a race here where a change in callback_ will not take effect until +- * the next subsequent requested vsync. This is unavoidable since we can't +- * call the vsync hook while holding the thread lock. +- * +- * We could shorten the race window by caching callback_ right before calling +- * the hook. However, in practice, callback_ is only updated once, so it's not +- * worth the overhead. +- */ ++ + if (callback) + callback->Callback(display, timestamp); ++ ++ Lock(); ++ if (enabled_ && vsync_callback_hook_ && vsync_callback_data_) ++ vsync_callback_hook_(vsync_callback_data_, display, timestamp); ++ Unlock(); ++ + last_timestamp_ = timestamp; + } + } // namespace android +diff --git a/include/vsyncworker.h b/drm/VSyncWorker.h +similarity index 77% +rename from include/vsyncworker.h +rename to drm/VSyncWorker.h +index 96f7432..b43918c 100644 +--- a/include/vsyncworker.h ++++ b/drm/VSyncWorker.h +@@ -17,31 +17,34 @@ + #ifndef ANDROID_EVENT_WORKER_H_ + #define ANDROID_EVENT_WORKER_H_ + +-#include "drmdevice.h" +-#include "worker.h" +- ++#include ++#include ++#include + #include ++ ++#include + #include + +-#include +-#include ++#include "DrmDevice.h" ++#include "utils/Worker.h" + + namespace android { + + class VsyncCallback { + public: +- virtual ~VsyncCallback() { +- } ++ virtual ~VsyncCallback() = default; + virtual void Callback(int display, int64_t timestamp) = 0; + }; + + class VSyncWorker : public Worker { + public: + VSyncWorker(); +- ~VSyncWorker() override; ++ ~VSyncWorker() override = default; + + int Init(DrmDevice *drm, int display); + void RegisterCallback(std::shared_ptr callback); ++ void RegisterClientCallback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook); + + void VSyncControl(bool enabled); + +@@ -49,7 +52,7 @@ class VSyncWorker : public Worker { + void Routine() override; + + private: +- int64_t GetPhasedVSync(int64_t frame_ns, int64_t current); ++ int64_t GetPhasedVSync(int64_t frame_ns, int64_t current) const; + int SyntheticWaitVBlank(int64_t *timestamp); + + DrmDevice *drm_; +@@ -62,6 +65,9 @@ class VSyncWorker : public Worker { + int display_; + std::atomic_bool enabled_; + int64_t last_timestamp_; ++ ++ hwc2_callback_data_t vsync_callback_data_ = NULL; ++ HWC2_PFN_VSYNC vsync_callback_hook_ = NULL; + }; + } // namespace android + +diff --git a/include/autofd.h b/include/autofd.h +deleted file mode 100644 +index 9af6c22..0000000 +--- a/include/autofd.h ++++ /dev/null +@@ -1,106 +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_AUTO_FD_H_ +-#define ANDROID_AUTO_FD_H_ +- +-#include +- +-namespace android { +- +-class UniqueFd { +- public: +- UniqueFd() = default; +- UniqueFd(int fd) : fd_(fd) { +- } +- UniqueFd(UniqueFd &&rhs) { +- fd_ = rhs.fd_; +- rhs.fd_ = -1; +- } +- +- UniqueFd &operator=(UniqueFd &&rhs) { +- Set(rhs.Release()); +- return *this; +- } +- +- ~UniqueFd() { +- if (fd_ >= 0) +- close(fd_); +- } +- +- int Release() { +- int old_fd = fd_; +- fd_ = -1; +- return old_fd; +- } +- +- int Set(int fd) { +- if (fd_ >= 0) +- close(fd_); +- fd_ = fd; +- return fd_; +- } +- +- void Close() { +- if (fd_ >= 0) +- close(fd_); +- fd_ = -1; +- } +- +- int get() const { +- return fd_; +- } +- +- private: +- int fd_ = -1; +-}; +- +-struct OutputFd { +- OutputFd() = default; +- OutputFd(int *fd) : fd_(fd) { +- } +- OutputFd(OutputFd &&rhs) { +- fd_ = rhs.fd_; +- rhs.fd_ = NULL; +- } +- +- OutputFd &operator=(OutputFd &&rhs) { +- fd_ = rhs.fd_; +- rhs.fd_ = NULL; +- return *this; +- } +- +- int Set(int fd) { +- if (*fd_ >= 0) +- close(*fd_); +- *fd_ = fd; +- return fd; +- } +- +- int get() { +- return *fd_; +- } +- +- operator bool() const { +- return fd_ != NULL; +- } +- +- private: +- int *fd_ = NULL; +-}; +-} // namespace android +- +-#endif +diff --git a/include/drmframebuffer.h b/include/drmframebuffer.h +deleted file mode 100644 +index 9032d3a..0000000 +--- a/include/drmframebuffer.h ++++ /dev/null +@@ -1,107 +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_FRAMEBUFFER_ +-#define ANDROID_DRM_FRAMEBUFFER_ +- +-#include +- +-#include +- +-#include +- +-namespace android { +- +-struct DrmFramebuffer { +- DrmFramebuffer() : release_fence_fd_(-1) { +- } +- +- ~DrmFramebuffer() { +- if (release_fence_fd() >= 0) +- close(release_fence_fd()); +- } +- +- bool is_valid() { +- return buffer_ != NULL; +- } +- +- sp buffer() { +- return buffer_; +- } +- +- int release_fence_fd() { +- return release_fence_fd_; +- } +- +- void set_release_fence_fd(int fd) { +- if (release_fence_fd_ >= 0) +- close(release_fence_fd_); +- release_fence_fd_ = fd; +- } +- +- bool Allocate(uint32_t w, uint32_t h) { +- if (is_valid()) { +- if (buffer_->getWidth() == w && buffer_->getHeight() == h) +- return true; +- +- if (release_fence_fd_ >= 0) { +- if (sync_wait(release_fence_fd_, kReleaseWaitTimeoutMs) != 0) { +- ALOGE("Wait for release fence failed\n"); +- return false; +- } +- } +- Clear(); +- } +- buffer_ = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_888, +- GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | +- GRALLOC_USAGE_HW_COMPOSER); +- release_fence_fd_ = -1; +- return is_valid(); +- } +- +- void Clear() { +- if (!is_valid()) +- return; +- +- if (release_fence_fd_ >= 0) { +- close(release_fence_fd_); +- release_fence_fd_ = -1; +- } +- +- buffer_.clear(); +- } +- +- int WaitReleased(int timeout_milliseconds) { +- if (!is_valid()) +- return 0; +- if (release_fence_fd_ < 0) +- return 0; +- +- int ret = sync_wait(release_fence_fd_, timeout_milliseconds); +- return ret; +- } +- +- // Somewhat arbitrarily chosen, but wanted to stay below 3000ms, which is the +- // system timeout +- static const int kReleaseWaitTimeoutMs = 1500; +- +- private: +- sp buffer_; +- int release_fence_fd_; +-}; +-} // namespace android +- +-#endif // ANDROID_DRM_FRAMEBUFFER_ +diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h +index b959714..db54802 100644 +--- a/include/drmhwcgralloc.h ++++ b/include/drmhwcgralloc.h +@@ -26,16 +26,11 @@ typedef struct hwc_drm_bo { + uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ + uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */ + uint32_t usage; +- uint32_t pixel_stride; + uint32_t pitches[HWC_DRM_BO_MAX_PLANES]; + uint32_t offsets[HWC_DRM_BO_MAX_PLANES]; + uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES]; +- uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES]; + uint64_t modifiers[HWC_DRM_BO_MAX_PLANES]; +- uint32_t fb_id; +- bool with_modifiers; + int acquire_fence_fd; +- void *priv; + } hwc_drm_bo_t; + + #endif // ANDROID_DRMHWCGRALLOC_H_ +diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h +index 69313d9..22af12b 100644 +--- a/include/drmhwcomposer.h ++++ b/include/drmhwcomposer.h +@@ -17,100 +17,20 @@ + #ifndef ANDROID_DRM_HWCOMPOSER_H_ + #define ANDROID_DRM_HWCOMPOSER_H_ + ++#include ++#include + #include + #include + + #include + +-#include +-#include +-#include "autofd.h" ++#include "drm/DrmFbImporter.h" + #include "drmhwcgralloc.h" +- +-struct hwc_import_context; +- +-int hwc_import_init(struct hwc_import_context **ctx); +-int hwc_import_destroy(struct hwc_import_context *ctx); +- +-int hwc_import_bo_create(int fd, struct hwc_import_context *ctx, +- buffer_handle_t buf, struct hwc_drm_bo *bo); +-bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx, +- struct hwc_drm_bo *bo); ++#include "utils/UniqueFd.h" + + namespace android { + +-class Importer; +- +-class DrmHwcBuffer { +- public: +- DrmHwcBuffer() = default; +- DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer) +- : bo_(bo), importer_(importer) { +- } +- DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) { +- rhs.importer_ = NULL; +- } +- +- ~DrmHwcBuffer() { +- Clear(); +- } +- +- DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) { +- Clear(); +- importer_ = rhs.importer_; +- rhs.importer_ = NULL; +- bo_ = rhs.bo_; +- return *this; +- } +- +- operator bool() const { +- return importer_ != NULL; +- } +- +- const hwc_drm_bo *operator->() const; +- +- void Clear(); +- +- int ImportBuffer(buffer_handle_t handle, Importer *importer); +- +- private: +- hwc_drm_bo bo_; +- Importer *importer_ = NULL; +-}; +- +-class DrmHwcNativeHandle { +- public: +- DrmHwcNativeHandle() = default; +- +- DrmHwcNativeHandle(native_handle_t *handle) : handle_(handle) { +- } +- +- DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) { +- handle_ = rhs.handle_; +- rhs.handle_ = NULL; +- } +- +- ~DrmHwcNativeHandle(); +- +- DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) { +- Clear(); +- handle_ = rhs.handle_; +- rhs.handle_ = NULL; +- return *this; +- } +- +- int CopyBufferHandle(buffer_handle_t handle, int width, int height, +- int layerCount, int format, int usage, int stride); +- +- void Clear(); +- +- buffer_handle_t get() const { +- return handle_; +- } +- +- private: +- native_handle_t *handle_ = NULL; +-}; ++class DrmFbIdHandle; + + enum DrmHwcTransform { + kIdentity = 0, +@@ -129,28 +49,22 @@ enum class DrmHwcBlending : int32_t { + + struct DrmHwcLayer { + buffer_handle_t sf_handle = NULL; ++ hwc_drm_bo_t buffer_info{}; ++ std::shared_ptr FbIdHandle; ++ + int gralloc_buffer_usage = 0; +- DrmHwcBuffer buffer; +- DrmHwcNativeHandle handle; + uint32_t transform; + DrmHwcBlending blending = DrmHwcBlending::kNone; + uint16_t alpha = 0xffff; + hwc_frect_t source_crop; + hwc_rect_t display_frame; ++ android_dataspace_t dataspace; + + UniqueFd acquire_fence; +- OutputFd release_fence; + +- int ImportBuffer(Importer *importer); +- int InitFromDrmHwcLayer(DrmHwcLayer *layer, Importer *importer); ++ int ImportBuffer(DrmDevice *drmDevice); + + void SetTransform(int32_t sf_transform); +- void SetSourceCrop(hwc_frect_t const &crop); +- void SetDisplayFrame(hwc_rect_t const &frame); +- +- buffer_handle_t get_usable_handle() const { +- return handle.get() != NULL ? handle.get() : sf_handle; +- } + + bool protected_usage() const { + return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) == +diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp +deleted file mode 100644 +index 1aa8160..0000000 +--- a/platform/platformdrmgeneric.cpp ++++ /dev/null +@@ -1,252 +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. +- */ +- +-#define LOG_TAG "hwc-platform-drm-generic" +- +-#include "platformdrmgeneric.h" +-#include "drmdevice.h" +-#include "platform.h" +- +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-namespace android { +- +-#ifdef USE_DRM_GENERIC_IMPORTER +-// static +-Importer *Importer::CreateInstance(DrmDevice *drm) { +- DrmGenericImporter *importer = new DrmGenericImporter(drm); +- if (!importer) +- return NULL; +- +- int ret = importer->Init(); +- if (ret) { +- ALOGE("Failed to initialize the nv importer %d", ret); +- delete importer; +- return NULL; +- } +- return importer; +-} +-#endif +- +-DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) +- : drm_(drm), exclude_non_hwfb_(false) { +-} +- +-DrmGenericImporter::~DrmGenericImporter() { +-} +- +-int DrmGenericImporter::Init() { +- int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, +- (const hw_module_t **)&gralloc_); +- if (ret) { +- ALOGE("Failed to open gralloc module"); +- return ret; +- } +- +- ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, +- gralloc_->common.author); +- +- char exclude_non_hwfb_prop[PROPERTY_VALUE_MAX]; +- property_get("hwc.drm.exclude_non_hwfb_imports", exclude_non_hwfb_prop, "0"); +- exclude_non_hwfb_ = static_cast(strncmp(exclude_non_hwfb_prop, "0", 1)); +- +- return 0; +-} +- +-uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) { +- switch (hal_format) { +- case HAL_PIXEL_FORMAT_RGB_888: +- return DRM_FORMAT_BGR888; +- case HAL_PIXEL_FORMAT_BGRA_8888: +- return DRM_FORMAT_ARGB8888; +- case HAL_PIXEL_FORMAT_RGBX_8888: +- return DRM_FORMAT_XBGR8888; +- case HAL_PIXEL_FORMAT_RGBA_8888: +- return DRM_FORMAT_ABGR8888; +- case HAL_PIXEL_FORMAT_RGB_565: +- return DRM_FORMAT_BGR565; +- case HAL_PIXEL_FORMAT_YV12: +- return DRM_FORMAT_YVU420; +- default: +- ALOGE("Cannot convert hal format to drm format %u", hal_format); +- return DRM_FORMAT_INVALID; +- } +-} +- +-uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) { +- switch (drm_format) { +- case DRM_FORMAT_ARGB8888: +- case DRM_FORMAT_XBGR8888: +- case DRM_FORMAT_ABGR8888: +- return 32; +- case DRM_FORMAT_BGR888: +- return 24; +- case DRM_FORMAT_BGR565: +- return 16; +- case DRM_FORMAT_YVU420: +- return 12; +- default: +- ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format); +- return 32; +- } +-} +- +-int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle, +- hwc_drm_bo_t *bo) { +- gralloc_handle_t *gr_handle = gralloc_handle(handle); +- if (!gr_handle) +- return -EINVAL; +- +- bo->width = gr_handle->width; +- bo->height = gr_handle->height; +- bo->hal_format = gr_handle->format; +- bo->format = ConvertHalFormatToDrm(gr_handle->format); +- if (bo->format == DRM_FORMAT_INVALID) +- return -EINVAL; +- bo->usage = gr_handle->usage; +- bo->pixel_stride = (gr_handle->stride * 8) / +- DrmFormatToBitsPerPixel(bo->format); +- bo->prime_fds[0] = gr_handle->prime_fd; +- bo->pitches[0] = gr_handle->stride; +- bo->offsets[0] = 0; +- +- return 0; +-} +- +-int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { +- memset(bo, 0, sizeof(hwc_drm_bo_t)); +- +- int ret = ConvertBoInfo(handle, bo); +- if (ret) +- return ret; +- +- ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]); +- if (ret) { +- ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret); +- return ret; +- } +- +- for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) { +- int fd = bo->prime_fds[i]; +- if (fd != 0) { +- if (fd != bo->prime_fds[0]) { +- ALOGE("Multiplanar FBs are not supported by this version of composer"); +- return -ENOTSUP; +- } +- bo->gem_handles[i] = bo->gem_handles[0]; +- } +- } +- +- if (!bo->with_modifiers) +- ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, +- bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, +- 0); +- else +- ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, +- bo->format, bo->gem_handles, bo->pitches, +- bo->offsets, bo->modifiers, &bo->fb_id, +- bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS +- : 0); +- +- if (ret) { +- ALOGE("could not create drm fb %d", ret); +- return ret; +- } +- +- ImportHandle(bo->gem_handles[0]); +- +- return ret; +-} +- +-int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { +- if (bo->fb_id) +- if (drmModeRmFB(drm_->fd(), bo->fb_id)) +- ALOGE("Failed to rm fb"); +- +- for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { +- if (!bo->gem_handles[i]) +- continue; +- +- if (ReleaseHandle(bo->gem_handles[i])) { +- ALOGE("Failed to release gem handle %d", bo->gem_handles[i]); +- } else { +- for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++) +- if (bo->gem_handles[j] == bo->gem_handles[i]) +- bo->gem_handles[j] = 0; +- bo->gem_handles[i] = 0; +- } +- } +- return 0; +-} +- +-bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) { +- hwc_drm_bo_t bo; +- +- int ret = ConvertBoInfo(handle, &bo); +- if (ret) +- return false; +- +- if (bo.prime_fds[0] == 0) +- return false; +- +- if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB)) +- return false; +- +- return true; +-} +- +-#ifdef USE_DRM_GENERIC_IMPORTER +-std::unique_ptr Planner::CreateInstance(DrmDevice *) { +- std::unique_ptr planner(new Planner); +- planner->AddStage(); +- return planner; +-} +-#endif +- +-int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { +- gem_refcount_[gem_handle]++; +- +- return 0; +-} +- +-int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { +- if (--gem_refcount_[gem_handle]) +- return 0; +- +- gem_refcount_.erase(gem_handle); +- +- return CloseHandle(gem_handle); +-} +- +-int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { +- struct drm_gem_close gem_close; +- +- memset(&gem_close, 0, sizeof(gem_close)); +- +- gem_close.handle = gem_handle; +- int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); +- if (ret) +- ALOGE("Failed to close gem handle %d %d", gem_handle, ret); +- +- return ret; +-} +-} +diff --git a/platform/platformdrmgeneric.h b/platform/platformdrmgeneric.h +deleted file mode 100644 +index f9d923f..0000000 +--- a/platform/platformdrmgeneric.h ++++ /dev/null +@@ -1,64 +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_PLATFORM_DRM_GENERIC_H_ +-#define ANDROID_PLATFORM_DRM_GENERIC_H_ +- +-#include "drmdevice.h" +-#include "platform.h" +- +-#include +-#include +- +-#include +- +-#ifndef DRM_FORMAT_INVALID +-#define DRM_FORMAT_INVALID 0 +-#endif +- +-namespace android { +- +-class DrmGenericImporter : public Importer { +- public: +- DrmGenericImporter(DrmDevice *drm); +- ~DrmGenericImporter() override; +- +- int Init(); +- +- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; +- int ReleaseBuffer(hwc_drm_bo_t *bo) override; +- bool CanImportBuffer(buffer_handle_t handle) override; +- int ImportHandle(uint32_t gem_handle); +- int ReleaseHandle(uint32_t gem_handle); +- +- int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; +- +- uint32_t ConvertHalFormatToDrm(uint32_t hal_format); +- uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format); +- +- protected: +- DrmDevice *drm_; +- +- private: +- const gralloc_module_t *gralloc_; +- bool exclude_non_hwfb_; +- +- int CloseHandle(uint32_t gem_handle); +- std::map gem_refcount_; +-}; +-} // namespace android +- +-#endif +diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp +deleted file mode 100644 +index 1f1478f..0000000 +--- a/platform/platformhisi.cpp ++++ /dev/null +@@ -1,197 +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. +- */ +- +-#define LOG_TAG "hwc-platform-hisi" +- +-#include "platformhisi.h" +-#include "drmdevice.h" +-#include "platform.h" +- +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include "gralloc_priv.h" +- +-#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) +- +-namespace android { +- +-Importer *Importer::CreateInstance(DrmDevice *drm) { +- HisiImporter *importer = new HisiImporter(drm); +- if (!importer) +- return NULL; +- +- int ret = importer->Init(); +- if (ret) { +- ALOGE("Failed to initialize the hisi importer %d", ret); +- delete importer; +- return NULL; +- } +- return importer; +-} +- +-#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ +- defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) +-uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags, +- bool is_rgb) { +- uint64_t features = 0UL; +- +- if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) +- features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; +- +- if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) +- features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); +- +- if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) +- features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; +- +- if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) +- features |= AFBC_FORMAT_MOD_TILED; +- +- if (features) { +- if (is_rgb) +- features |= AFBC_FORMAT_MOD_YTR; +- +- return DRM_FORMAT_MOD_ARM_AFBC(features); +- } +- +- return 0; +-} +-#else +-uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t /* flags */, +- bool /* is_rgb */) { +- return 0; +-} +-#endif +- +-bool HisiImporter::IsDrmFormatRgb(uint32_t drm_format) { +- switch (drm_format) { +- case DRM_FORMAT_ARGB8888: +- case DRM_FORMAT_XBGR8888: +- case DRM_FORMAT_ABGR8888: +- case DRM_FORMAT_BGR888: +- case DRM_FORMAT_BGR565: +- return true; +- case DRM_FORMAT_YVU420: +- return false; +- default: +- ALOGV("Unsupported format %u assuming rgb?", drm_format); +- return true; +- } +-} +- +-int HisiImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { +- bool is_rgb; +- +- private_handle_t const *hnd = reinterpret_cast( +- handle); +- if (!hnd) +- return -EINVAL; +- +- if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) +- return -EINVAL; +- +- uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); +- if (fmt == DRM_FORMAT_INVALID) +- return -EINVAL; +- +- is_rgb = HisiImporter::IsDrmFormatRgb(fmt); +- bo->modifiers[0] = HisiImporter:: +- 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->pixel_stride = hnd->stride; +- bo->pitches[0] = hnd->byte_stride; +- bo->prime_fds[0] = hnd->share_fd; +- bo->offsets[0] = 0; +- +- switch (fmt) { +- case DRM_FORMAT_YVU420: { +- int align = 128; +- if (hnd->usage & +- (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) +- align = 16; +- int adjusted_height = MALI_ALIGN(hnd->height, 2); +- int y_size = adjusted_height * hnd->byte_stride; +- int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); +- 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; +- /* U plane */ +- bo->prime_fds[2] = hnd->share_fd; +- bo->pitches[2] = vu_stride; +- bo->offsets[2] = y_size + v_size; +- break; +- } +- default: +- break; +- } +- +- bo->with_modifiers = true; +- +- return 0; +-} +- +-class PlanStageHiSi : public Planner::PlanStage { +- public: +- int ProvisionPlanes(std::vector *composition, +- std::map &layers, DrmCrtc *crtc, +- std::vector *planes) { +- int layers_added = 0; +- // Fill up as many DRM planes as we can with buffers that have HW_FB usage. +- // Buffers without HW_FB should have been filtered out with +- // CanImportBuffer(), if we meet one here, just skip it. +- for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) { +- if (!(i->second->gralloc_buffer_usage & GRALLOC_USAGE_HW_FB)) +- continue; +- +- int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, +- crtc, std::make_pair(i->first, i->second)); +- layers_added++; +- // We don't have any planes left +- if (ret == -ENOENT) +- break; +- else if (ret) { +- ALOGE("Failed to emplace layer %zu, dropping it", i->first); +- return ret; +- } +- } +- // If we didn't emplace anything, return an error to ensure we force client +- // compositing. +- if (!layers_added) +- return -EINVAL; +- +- return 0; +- } +-}; +- +-std::unique_ptr Planner::CreateInstance(DrmDevice *) { +- std::unique_ptr planner(new Planner); +- planner->AddStage(); +- return planner; +-} +-} // namespace android +diff --git a/platform/platformimagination.h b/platform/platformimagination.h +deleted file mode 100644 +index f2a7cb7..0000000 +--- a/platform/platformimagination.h ++++ /dev/null +@@ -1,22 +0,0 @@ +-#ifndef PLATFORMIMAGINATION_H +-#define PLATFORMIMAGINATION_H +- +-#include "drmdevice.h" +-#include "platform.h" +-#include "platformdrmgeneric.h" +- +-#include +- +-#include +- +-namespace android { +- +-class ImaginationImporter : public DrmGenericImporter { +- public: +- using DrmGenericImporter::DrmGenericImporter; +- +- int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; +-}; +-} // namespace android +- +-#endif // PLATFORMIMAGINATION_H +diff --git a/platform/platformminigbm.cpp b/platform/platformminigbm.cpp +deleted file mode 100644 +index df195d3..0000000 +--- a/platform/platformminigbm.cpp ++++ /dev/null +@@ -1,72 +0,0 @@ +-/* +- * Copyright (C) 2018 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 LOG_TAG "hwc-platform-drm-minigbm" +- +-#include "platformminigbm.h" +-#include "drmdevice.h" +-#include "platform.h" +- +-#include +-#include +- +-#include +-#include +- +-#include "cros_gralloc_handle.h" +- +-namespace android { +- +-Importer *Importer::CreateInstance(DrmDevice *drm) { +- DrmMinigbmImporter *importer = new DrmMinigbmImporter(drm); +- if (!importer) +- return NULL; +- +- int ret = importer->Init(); +- if (ret) { +- ALOGE("Failed to initialize the minigbm importer %d", ret); +- delete importer; +- return NULL; +- } +- return importer; +-} +- +-int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, +- hwc_drm_bo_t *bo) { +- cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; +- if (!gr_handle) +- return -EINVAL; +- +- bo->width = gr_handle->width; +- bo->height = gr_handle->height; +- bo->hal_format = gr_handle->droid_format; +- bo->format = gr_handle->format; +- bo->usage = gr_handle->usage; +- bo->pixel_stride = gr_handle->pixel_stride; +- bo->prime_fds[0] = gr_handle->fds[0]; +- bo->pitches[0] = gr_handle->strides[0]; +- bo->offsets[0] = gr_handle->offsets[0]; +- +- return 0; +-} +- +-std::unique_ptr Planner::CreateInstance(DrmDevice *) { +- std::unique_ptr planner(new Planner); +- planner->AddStage(); +- return planner; +-} +- +-} // namespace android +diff --git a/presubmit.sh b/presubmit.sh +new file mode 100755 +index 0000000..249aaf5 +--- /dev/null ++++ b/presubmit.sh +@@ -0,0 +1,21 @@ ++#!/bin/bash ++ ++set -e ++ ++echo "Run native build:" ++ ++./.ci/.gitlab-ci-clang-build.sh ++ ++echo "Run style check:" ++ ++./.ci/.gitlab-ci-checkcommit.sh ++ ++echo "Run coarse clang-tidy check:" ++ ++./.ci/.gitlab-ci-clang-tidy-coarse.sh ++ ++echo "Run fine clang-tidy check:" ++ ++./.ci/.gitlab-ci-clang-tidy-fine.sh ++ ++echo -e "\n\e[32m --- SUCCESS ---" +diff --git a/tests/Android.bp b/tests/Android.bp +index 7e550ff..e30898c 100644 +--- a/tests/Android.bp ++++ b/tests/Android.bp +@@ -1,4 +1,23 @@ ++cc_library_shared { ++ name: "hwcomposer.filegroups_build_test", ++ defaults: ["hwcomposer.drm_defaults"], ++ whole_static_libs: ["drm_hwcomposer"], + ++ srcs: [ ++ ":drm_hwcomposer_platformhisi", ++ ":drm_hwcomposer_platformimagination", ++ ":drm_hwcomposer_platformmediatek", ++ ":drm_hwcomposer_platformmeson", ++ ], ++ ++ local_include_dirs: [ ++ "test_include", ++ ], ++ ++ cppflags: [ ++ "-DDISABLE_LEGACY_GETTERS", ++ ], ++} + + cc_test { + name: "hwc-drm-tests", +@@ -9,5 +28,8 @@ cc_test { + header_libs: ["libhardware_headers"], + static_libs: ["libdrmhwc_utils"], + shared_libs: ["hwcomposer.drm"], +- include_dirs: ["external/drm_hwcomposer/include"], ++ include_dirs: [ ++ "external/drm_hwcomposer", ++ "external/drm_hwcomposer/include", ++ ], + } +diff --git a/tests/test_include/cros_gralloc_handle.h b/tests/test_include/cros_gralloc_handle.h +new file mode 100644 +index 0000000..d77d777 +--- /dev/null ++++ b/tests/test_include/cros_gralloc_handle.h +@@ -0,0 +1,53 @@ ++// clang-format off ++/* ++ * Copyright 2016 The Chromium OS Authors. All rights reserved. ++ * Use of this source code is governed by a BSD-style license that can be ++ * found in the LICENSE file. ++ */ ++ ++#ifndef CROS_GRALLOC_HANDLE_H ++#define CROS_GRALLOC_HANDLE_H ++ ++#include ++#include ++ ++#define DRV_MAX_PLANES 4 ++#define DRV_MAX_FDS (DRV_MAX_PLANES + 1) ++ ++struct cros_gralloc_handle : public native_handle_t { ++ /* ++ * File descriptors must immediately follow the native_handle_t base and used file ++ * descriptors must be packed at the beginning of this array to work with ++ * native_handle_clone(). ++ * ++ * This field contains 'num_planes' plane file descriptors followed by an optional metadata ++ * reserved region file descriptor if 'reserved_region_size' is greater than zero. ++ */ ++ int32_t fds[DRV_MAX_FDS]; ++ uint32_t strides[DRV_MAX_PLANES]; ++ uint32_t offsets[DRV_MAX_PLANES]; ++ uint32_t sizes[DRV_MAX_PLANES]; ++ uint32_t id; ++ uint32_t width; ++ uint32_t height; ++ uint32_t format; /* DRM format */ ++ uint32_t tiling; ++ uint64_t format_modifier; ++ uint64_t use_flags; /* Buffer creation flags */ ++ uint32_t magic; ++ uint32_t pixel_stride; ++ int32_t droid_format; ++ int32_t usage; /* Android usage. */ ++ uint32_t num_planes; ++ uint64_t reserved_region_size; ++ uint64_t total_size; /* Total allocation size */ ++ /* ++ * Name is a null terminated char array located at handle->base.data[handle->name_offset]. ++ */ ++ uint32_t name_offset; ++} __attribute__((packed)); ++ ++typedef const struct cros_gralloc_handle *cros_gralloc_handle_t; ++ ++#endif ++// clang-format on +diff --git a/tests/test_include/gralloc_helper.h b/tests/test_include/gralloc_helper.h +new file mode 100644 +index 0000000..b6cd24d +--- /dev/null ++++ b/tests/test_include/gralloc_helper.h +@@ -0,0 +1,54 @@ ++// clang-format off ++/* ++ * Copyright (C) 2010-2017 ARM Limited. All rights reserved. ++ * ++ * Copyright (C) 2008 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 GRALLOC_HELPER_H_ ++#define GRALLOC_HELPER_H_ ++ ++#include ++#include ++#include "utils/log.h" ++ ++#ifndef AWAR ++#define AWAR(fmt, args...) \ ++ __android_log_print(ANDROID_LOG_WARN, "[Gralloc-Warning]", "%s:%d " fmt, __func__, __LINE__, ##args) ++#endif ++#ifndef AINF ++#define AINF(fmt, args...) __android_log_print(ANDROID_LOG_INFO, "[Gralloc]", fmt, ##args) ++#endif ++#ifndef AERR ++#define AERR(fmt, args...) \ ++ __android_log_print(ANDROID_LOG_ERROR, "[Gralloc-ERROR]", "%s:%d " fmt, __func__, __LINE__, ##args) ++#endif ++#ifndef AERR_IF ++#define AERR_IF(eq, fmt, args...) \ ++ if ((eq)) \ ++ AERR(fmt, args) ++#endif ++ ++#define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) ++ ++#define GRALLOC_UNUSED(x) ((void)x) ++ ++static inline size_t round_up_to_page_size(size_t x) ++{ ++ return (x + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); ++} ++ ++#endif /* GRALLOC_HELPER_H_ */ ++// clang-format on +diff --git a/tests/test_include/gralloc_priv.h b/tests/test_include/gralloc_priv.h +new file mode 100644 +index 0000000..e771a69 +--- /dev/null ++++ b/tests/test_include/gralloc_priv.h +@@ -0,0 +1,69 @@ ++// clang-format off ++/* ++ * Copyright (C) 2017 ARM Limited. All rights reserved. ++ * ++ * Copyright (C) 2008 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 GRALLOC_PRIV_H_ ++#define GRALLOC_PRIV_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "utils/log.h" ++ ++#if GRALLOC_USE_GRALLOC1_API ++#include ++#else ++#include ++#endif ++/** ++ * mali_gralloc_formats.h needs the define for GRALLOC_MODULE_API_VERSION_0_3 and ++ * GRALLOC_MODULE_API_VERSION_1_0, so include or before ++ * including mali_gralloc_formats.h ++ **/ ++#include "mali_gralloc_formats.h" ++#include "mali_gralloc_usages.h" ++#include "gralloc_helper.h" ++ ++#if defined(GRALLOC_MODULE_API_VERSION_0_3) || \ ++ (defined(GRALLOC_MODULE_API_VERSION_1_0) && !defined(GRALLOC_DISABLE_PRIVATE_BUFFER_DEF)) ++ ++/* ++ * This header file contains the private buffer definition. For gralloc 0.3 it will ++ * always be exposed, but for gralloc 1.0 it will be removed at some point in the future. ++ * ++ * GRALLOC_DISABLE_PRIVATE_BUFFER_DEF is intended for DDKs to test while implementing ++ * the new private API. ++ */ ++#include "mali_gralloc_buffer.h" ++#endif ++ ++#if defined(GRALLOC_MODULE_API_VERSION_1_0) ++ ++/* gralloc 1.0 supports the new private interface that abstracts ++ * the private buffer definition to a set of defined APIs. ++ */ ++#include "mali_gralloc_private_interface.h" ++#endif ++ ++#endif /* GRALLOC_PRIV_H_ */ ++// clang-format on +diff --git a/tests/test_include/img_gralloc1_public.h b/tests/test_include/img_gralloc1_public.h +new file mode 100644 +index 0000000..aef435f +--- /dev/null ++++ b/tests/test_include/img_gralloc1_public.h +@@ -0,0 +1,253 @@ ++// clang-format off ++/* Copyright (c) Imagination Technologies Ltd. ++ * ++ * The contents of this file are subject to the MIT license as set out below. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef HAL_PUBLIC_H ++#define HAL_PUBLIC_H ++ ++/* Authors of third party hardware composer (HWC) modules will need to include ++ * this header to access functionality in the gralloc and framebuffer HALs. ++ */ ++ ++#include ++#if 0 /* Header below is not used by drm_hwcomposer */ ++#include ++#endif ++ ++#define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L)) ++#define HW_ALIGN 16 ++ ++/* This can be tuned down as appropriate for the SOC. ++ * ++ * IMG formats are usually a single sub-alloc. ++ * Some OEM video formats are two sub-allocs (Y, UV planes). ++ * Future OEM video formats might be three sub-allocs (Y, U, V planes). ++ */ ++#define MAX_SUB_ALLOCS 3 ++ ++/* Format is not YCbCr (e.g. a RGB format) - bIsYUVFormat should be false */ ++#define YUV_CHROMA_ORDER_NONE 0 ++/* Cb follows Y */ ++#define YUV_CHROMA_ORDER_CBCR_UV 1 ++/* Cr follows Y */ ++#define YUV_CHROMA_ORDER_CRCB_VU 2 ++ ++typedef struct ++{ ++ native_handle_t base; ++ ++ /* These fields can be sent cross process. They are also valid ++ * to duplicate within the same process. ++ * ++ * A table is stored within psPrivateData on gralloc_module_t (this ++ * is obviously per-process) which maps stamps to a mapped ++ * PVRSRV_CLIENT_MEM_INFO in that process. Each map entry has a lock ++ * count associated with it, satisfying the requirements of the ++ * Android API. This also prevents us from leaking maps/allocations. ++ * ++ * This table has entries inserted either by alloc() ++ * (alloc_device_t) or map() (gralloc_module_t). Entries are removed ++ * by free() (alloc_device_t) and unmap() (gralloc_module_t). ++ * ++ * As a special case for framebuffer_device_t, framebuffer_open() ++ * will add and framebuffer_close() will remove from this table. ++ */ ++ ++#define IMG_NATIVE_HANDLE_NUMFDS MAX_SUB_ALLOCS ++ /* The `fd' field is used to "export" a meminfo to another process. ++ * Therefore, it is allocated by alloc_device_t, and consumed by ++ * gralloc_module_t. The framebuffer_device_t does not need a handle, ++ * and the special value IMG_FRAMEBUFFER_FD is used instead. ++ */ ++ int fd[MAX_SUB_ALLOCS]; ++ ++#define IMG_NATIVE_HANDLE_NUMINTS \ ++ ((sizeof(unsigned long long) / sizeof(int)) + 5 + MAX_SUB_ALLOCS + 1 + MAX_SUB_ALLOCS + MAX_SUB_ALLOCS) ++ /* A KERNEL unique identifier for any exported kernel meminfo. Each ++ * exported kernel meminfo will have a unique stamp, but note that in ++ * userspace, several meminfos across multiple processes could have ++ * the same stamp. As the native_handle can be dup(2)'d, there could be ++ * multiple handles with the same stamp but different file descriptors. ++ */ ++ unsigned long long ui64Stamp; ++ ++ /* This is used for buffer usage validation when locking a buffer, ++ * and also in WSEGL (for the composition bypass feature). ++ */ ++ int usage; ++ ++ /* In order to do efficient cache flushes we need the buffer dimensions ++ * and format. These are available on the ANativeWindowBuffer, ++ * but the platform doesn't pass them down to the graphics HAL. ++ */ ++ int iWidth; ++ int iHeight; ++ int iFormat; ++ unsigned int uiBpp; ++ ++ /* The ion allocation path doesn't allow for the allocation size and ++ * mapping flags to be communicated cross-process automatically. ++ * Cache these here so we can map buffers in client processes. ++ */ ++ unsigned int uiAllocSize[MAX_SUB_ALLOCS]; ++ unsigned int uiFlags; ++ /* For multi-planar allocations, there will be multiple hstrides */ ++ int aiStride[MAX_SUB_ALLOCS]; ++ ++ /* For multi-planar allocations, there will be multiple vstrides */ ++ int aiVStride[MAX_SUB_ALLOCS]; ++ ++} ++__attribute__((aligned(sizeof(int)),packed)) IMG_native_handle_t; ++ ++typedef struct ++{ ++ int l, t, w, h; ++} ++IMG_write_lock_rect_t; ++ ++typedef int (*IMG_buffer_format_compute_params_pfn)( ++ unsigned int uiPlane, int *piWidth, int *piHeight, ++ int *piStride, int *piVStride, unsigned long *pulPlaneOffset); ++ ++typedef struct IMG_buffer_format_public_t ++{ ++ /* Buffer formats are returned as a linked list */ ++ struct IMG_buffer_format_public_t *psNext; ++ ++ /* HAL_PIXEL_FORMAT_... enumerant */ ++ int iHalPixelFormat; ++ ++ /* WSEGL_PIXELFORMAT_... enumerant */ ++ int iWSEGLPixelFormat; ++ ++ /* Friendly name for format */ ++ const char *const szName; ++ ++ /* Bits (not bytes) per pixel */ ++ unsigned int uiBpp; ++ ++ /* Supported HW usage bits. If this is GRALLOC_USAGE_HW_MASK, all usages ++ * are supported. Used for HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. ++ */ ++ int iSupportedUsage; ++ ++ /* YUV output format */ ++ int bIsYUVFormat; ++ ++ /* YCBCR_ORDERING_* defined the order of the Cb/Cr values */ ++ int eYUVChromaOrder; ++ ++ /* Utility function for adjusting YUV per-plane parameters */ ++ IMG_buffer_format_compute_params_pfn pfnComputeParams; ++} ++IMG_buffer_format_public_t; ++ ++#if 0 /* Not used by drm_hwcomposer but require additional dependencies */ ++ ++typedef struct ++{ ++ /* Base memtrack record, copied to caller */ ++ struct memtrack_record base; ++ ++ /* Record type, for filtering cached records */ ++ enum memtrack_type eType; ++ ++ /* Process ID, for filtering cached records */ ++ pid_t pid; ++} ++IMG_memtrack_record_public_t; ++ ++typedef struct IMG_gralloc_module_public_t ++{ ++ gralloc_module_t base; ++ ++ /* This function is deprecated and might be NULL. Do not use it. */ ++ int (*GetPhyAddrs)(gralloc_module_t const* module, ++ buffer_handle_t handle, void **ppvPhyAddr); ++ ++ /* Obtain HAL's registered format list */ ++ const IMG_buffer_format_public_t *(*GetBufferFormats)(void); ++ ++ int (*GetImplementationFormat) (struct IMG_gralloc_module_public_t const *psGrallocModule, int usage); ++ ++ int (*GetMemTrackRecords)(struct IMG_gralloc_module_public_t const *module, ++ IMG_memtrack_record_public_t **ppsRecords, ++ size_t *puNumRecords); ++ ++ /* Custom-blit components in lieu of overlay hardware */ ++ int (*Blit)(struct IMG_gralloc_module_public_t const *module, ++ buffer_handle_t src, ++ void *dest[MAX_SUB_ALLOCS], int format); ++ ++ int (*Blit2)(struct IMG_gralloc_module_public_t const *module, ++ buffer_handle_t src, buffer_handle_t dest, ++ int w, int h, int x, int y); ++ ++ int (*Blit3)(struct IMG_gralloc_module_public_t const *module, ++ unsigned long long ui64SrcStamp, int iSrcWidth, ++ int iSrcHeight, int iSrcFormat, int eSrcRotation, ++ buffer_handle_t dest, int eDestRotation); ++} ++IMG_gralloc_module_public_t; ++ ++#endif ++ ++/** ++ * pixel format definitions ++ */ ++ ++enum { ++ /* ++ * 0x100 = 0x1FF ++ * ++ * This range is reserved for pixel formats that are specific to the HAL ++ * implementation. Implementations can use any value in this range to ++ * communicate video pixel formats between their HAL modules. These ++ * formats must not have an alpha channel. Additionally, an EGLimage ++ * created from a gralloc buffer of one of these formats must be ++ * supported for use with the GL_OES_EGL_image_external OpenGL ES ++ * extension. ++ */ ++ ++ /* ++ * These are vendor specific pixel format, by (informal) convention ++ * IMGTec formats start from the top of the range, TI formats start from ++ * the bottom ++ */ ++ HAL_PIXEL_FORMAT_TI_NV12 = 0x100, ++ HAL_PIXEL_FORMAT_TI_UNUSED = 0x101, ++ HAL_PIXEL_FORMAT_TI_NV12_1D = 0x102, ++ HAL_PIXEL_FORMAT_TI_Y8 = 0x103, ++ HAL_PIXEL_FORMAT_TI_Y16 = 0x104, ++ HAL_PIXEL_FORMAT_TI_UYVY = 0x105, ++ HAL_PIXEL_FORMAT_BGRX_8888 = 0x1FF, ++ ++ /* generic format missing from Android list, not specific to vendor ++ * implementation ++ */ ++ HAL_PIXEL_FORMAT_NV12 = 0x3231564E, // FourCC for NV12 ++}; ++ ++#endif /* HAL_PUBLIC_H */ ++// clang-format on +diff --git a/tests/test_include/mali_gralloc_buffer.h b/tests/test_include/mali_gralloc_buffer.h +new file mode 100644 +index 0000000..83f77c2 +--- /dev/null ++++ b/tests/test_include/mali_gralloc_buffer.h +@@ -0,0 +1,271 @@ ++// clang-format off ++/* ++ * Copyright (C) 2017 ARM Limited. All rights reserved. ++ * ++ * Copyright (C) 2008 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 MALI_GRALLOC_BUFFER_H_ ++#define MALI_GRALLOC_BUFFER_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include "mali_gralloc_private_interface_types.h" ++ ++/* NOTE: ++ * If your framebuffer device driver is integrated with dma_buf, you will have to ++ * change this IOCTL definition to reflect your integration with the framebuffer ++ * device. ++ * Expected return value is a structure filled with a file descriptor ++ * backing your framebuffer device memory. ++ */ ++struct fb_dmabuf_export ++{ ++ __u32 fd; ++ __u32 flags; ++}; ++#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) ++ ++/* the max string size of GRALLOC_HARDWARE_GPU0 & GRALLOC_HARDWARE_FB0 ++ * 8 is big enough for "gpu0" & "fb0" currently ++ */ ++#define MALI_GRALLOC_HARDWARE_MAX_STR_LEN 8 ++#define NUM_FB_BUFFERS 2 ++ ++/* Define number of shared file descriptors */ ++#define GRALLOC_ARM_NUM_FDS 2 ++ ++#define NUM_INTS_IN_PRIVATE_HANDLE ((sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds) ++ ++#define SZ_4K 0x00001000 ++#define SZ_2M 0x00200000 ++ ++struct private_handle_t; ++ ++#ifndef __cplusplus ++/* C99 with pedantic don't allow anonymous unions which is used in below struct ++ * Disable pedantic for C for this struct only. ++ */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wpedantic" ++#endif ++ ++#ifdef __cplusplus ++struct private_handle_t : public native_handle ++{ ++#else ++struct private_handle_t ++{ ++ struct native_handle nativeHandle; ++#endif ++ ++#ifdef __cplusplus ++ /* Never intended to be used from C code */ ++ enum ++ { ++ PRIV_FLAGS_FRAMEBUFFER = 0x00000001, ++ PRIV_FLAGS_USES_ION_COMPOUND_HEAP = 0x00000002, ++ PRIV_FLAGS_USES_ION = 0x00000004, ++ PRIV_FLAGS_USES_ION_DMA_HEAP = 0x00000008 ++ }; ++ ++ enum ++ { ++ LOCK_STATE_WRITE = 1 << 31, ++ LOCK_STATE_MAPPED = 1 << 30, ++ LOCK_STATE_READ_MASK = 0x3FFFFFFF ++ }; ++#endif ++ ++ /* ++ * Shared file descriptor for dma_buf sharing. This must be the first element in the ++ * structure so that binder knows where it is and can properly share it between ++ * processes. ++ * DO NOT MOVE THIS ELEMENT! ++ */ ++ int share_fd; ++ int share_attr_fd; ++ ++ // ints ++ int magic; ++ int req_format; ++ uint64_t internal_format; ++ int byte_stride; ++ int flags; ++ int size; ++ int width; ++ int height; ++ int internalWidth; ++ int internalHeight; ++ int stride; ++ union ++ { ++ void *base; ++ uint64_t padding; ++ }; ++ union { ++ uint64_t consumer_usage; ++ uint64_t usage; ++ }; ++ uint64_t producer_usage; ++ uint64_t backing_store_id; ++ int backing_store_size; ++ int writeOwner; ++ int allocating_pid; ++ int remote_pid; ++ int ref_count; ++ // locally mapped shared attribute area ++ union ++ { ++ void *attr_base; ++ uint64_t padding3; ++ }; ++ ++ mali_gralloc_yuv_info yuv_info; ++ ++ // Following members is for framebuffer only ++ int fd; ++ union ++ { ++ off_t offset; ++ uint64_t padding4; ++ }; ++ ++ /* ++ * min_pgsz denotes minimum phys_page size used by this buffer. ++ * if buffer memory is physical contiguous set min_pgsz to buff->size ++ * if not sure buff's real phys_page size, you can use SZ_4K for safe. ++ */ ++ int min_pgsz; ++#ifdef __cplusplus ++ /* ++ * We track the number of integers in the structure. There are 16 unconditional ++ * integers (magic - pid, yuv_info, fd and offset). Note that the fd element is ++ * considered an int not an fd because it is not intended to be used outside the ++ * surface flinger process. The GRALLOC_ARM_NUM_INTS variable is used to track the ++ * number of integers that are conditionally included. Similar considerations apply ++ * to the number of fds. ++ */ ++ static const int sNumFds = GRALLOC_ARM_NUM_FDS; ++ static const int sMagic = 0x3141592; ++ ++ private_handle_t(int _flags, int _size, void *_base, uint64_t _consumer_usage, uint64_t _producer_usage, ++ int fb_file, off_t fb_offset) ++ : share_fd(-1) ++ , share_attr_fd(-1) ++ , magic(sMagic) ++ , flags(_flags) ++ , size(_size) ++ , width(0) ++ , height(0) ++ , stride(0) ++ , base(_base) ++ , consumer_usage(_consumer_usage) ++ , producer_usage(_producer_usage) ++ , backing_store_id(0x0) ++ , backing_store_size(0) ++ , writeOwner(0) ++ , allocating_pid(getpid()) ++ , remote_pid(-1) ++ , ref_count(1) ++ , attr_base(MAP_FAILED) ++ , yuv_info(MALI_YUV_NO_INFO) ++ , fd(fb_file) ++ , offset(fb_offset) ++ { ++ version = sizeof(native_handle); ++ numFds = sNumFds; ++ numInts = NUM_INTS_IN_PRIVATE_HANDLE; ++ } ++ ++ private_handle_t(int _flags, int _size, int _min_pgsz, uint64_t _consumer_usage, uint64_t _producer_usage, ++ int _shared_fd, int _req_format, uint64_t _internal_format, int _byte_stride, int _width, ++ int _height, int _stride, int _internalWidth, int _internalHeight, int _backing_store_size) ++ : share_fd(_shared_fd) ++ , share_attr_fd(-1) ++ , magic(sMagic) ++ , req_format(_req_format) ++ , internal_format(_internal_format) ++ , byte_stride(_byte_stride) ++ , flags(_flags) ++ , size(_size) ++ , width(_width) ++ , height(_height) ++ , internalWidth(_internalWidth) ++ , internalHeight(_internalHeight) ++ , stride(_stride) ++ , base(NULL) ++ , consumer_usage(_consumer_usage) ++ , producer_usage(_producer_usage) ++ , backing_store_id(0x0) ++ , backing_store_size(_backing_store_size) ++ , writeOwner(0) ++ , allocating_pid(getpid()) ++ , remote_pid(-1) ++ , ref_count(1) ++ , attr_base(MAP_FAILED) ++ , yuv_info(MALI_YUV_NO_INFO) ++ , fd(-1) ++ , offset(0) ++ , min_pgsz(_min_pgsz) ++ { ++ version = sizeof(native_handle); ++ numFds = sNumFds; ++ numInts = NUM_INTS_IN_PRIVATE_HANDLE; ++ } ++ ++ ~private_handle_t() ++ { ++ magic = 0; ++ } ++ ++ bool usesPhysicallyContiguousMemory() ++ { ++ return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false; ++ } ++ ++ static int validate(const native_handle *h) ++ { ++ const private_handle_t *hnd = (const private_handle_t *)h; ++ ++ if (!h || h->version != sizeof(native_handle) || h->numInts != NUM_INTS_IN_PRIVATE_HANDLE || ++ h->numFds != sNumFds || hnd->magic != sMagic) ++ { ++ return -EINVAL; ++ } ++ ++ return 0; ++ } ++ ++ static private_handle_t *dynamicCast(const native_handle *in) ++ { ++ if (validate(in) == 0) ++ { ++ return (private_handle_t *)in; ++ } ++ ++ return NULL; ++ } ++#endif ++}; ++#ifndef __cplusplus ++/* Restore previous diagnostic for pedantic */ ++#pragma GCC diagnostic pop ++#endif ++ ++#endif /* MALI_GRALLOC_BUFFER_H_ */ ++// clang-format on +diff --git a/tests/test_include/mali_gralloc_formats.h b/tests/test_include/mali_gralloc_formats.h +new file mode 100644 +index 0000000..e62ce5e +--- /dev/null ++++ b/tests/test_include/mali_gralloc_formats.h +@@ -0,0 +1,270 @@ ++// clang-format off ++/* ++ * Copyright (C) 2016-2017 ARM Limited. All rights reserved. ++ * ++ * Copyright (C) 2008 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 MALI_GRALLOC_FORMATS_H_ ++#define MALI_GRALLOC_FORMATS_H_ ++ ++#include ++ ++/* Internal formats are represented in gralloc as a 64bit identifier ++ * where the 32 lower bits are a base format and the 32 upper bits are modifiers. ++ * ++ * Modifier bits are divided into mutually exclusive ones and those that are not. ++ */ ++/* Internal format type */ ++typedef uint64_t mali_gralloc_internal_format; ++ ++/* Internal format masks */ ++#define MALI_GRALLOC_INTFMT_FMT_MASK 0x00000000ffffffffULL ++#define MALI_GRALLOC_INTFMT_EXT_MASK 0xffffffff00000000ULL ++#define MALI_GRALLOC_INTFMT_ME_EXT_MASK 0x0000ffff00000000ULL ++#define MALI_GRALLOC_INTFMT_REG_EXT_MASK 0xffff000000000000ULL ++ ++/* Internal base formats */ ++ ++/* Base formats that do not have an identical HAL match ++ * are defined starting at the Android private range ++ */ ++#define MALI_GRALLOC_FORMAT_INTERNAL_RANGE_BASE 0x100 ++ ++typedef enum ++{ ++ MALI_GRALLOC_FORMAT_TYPE_USAGE, ++ MALI_GRALLOC_FORMAT_TYPE_INTERNAL, ++} mali_gralloc_format_type; ++ ++typedef enum ++{ ++ /* Internal definitions for HAL formats. */ ++ MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, ++ MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888, ++ MALI_GRALLOC_FORMAT_INTERNAL_RGB_888 = HAL_PIXEL_FORMAT_RGB_888, ++ MALI_GRALLOC_FORMAT_INTERNAL_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, ++ MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, ++ MALI_GRALLOC_FORMAT_INTERNAL_YV12 = HAL_PIXEL_FORMAT_YV12, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y8 = HAL_PIXEL_FORMAT_Y8, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y16 = HAL_PIXEL_FORMAT_Y16, ++ MALI_GRALLOC_FORMAT_INTERNAL_YUV420_888 = HAL_PIXEL_FORMAT_YCbCr_420_888, ++ ++ /* Camera specific HAL formats */ ++ MALI_GRALLOC_FORMAT_INTERNAL_RAW16 = HAL_PIXEL_FORMAT_RAW16, ++ MALI_GRALLOC_FORMAT_INTERNAL_RAW12 = HAL_PIXEL_FORMAT_RAW12, ++ MALI_GRALLOC_FORMAT_INTERNAL_RAW10 = HAL_PIXEL_FORMAT_RAW10, ++ MALI_GRALLOC_FORMAT_INTERNAL_BLOB = HAL_PIXEL_FORMAT_BLOB, ++ ++ /* Flexible YUV formats would be parsed but not have any representation as ++ * internal format itself but one of the ones below ++ */ ++ ++ /* The internal private formats that have no HAL equivivalent are defined ++ * afterwards starting at a specific base range */ ++ MALI_GRALLOC_FORMAT_INTERNAL_NV12 = MALI_GRALLOC_FORMAT_INTERNAL_RANGE_BASE, ++ MALI_GRALLOC_FORMAT_INTERNAL_NV21, ++ MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT, ++ ++ /* Extended YUV formats ++ * ++ * NOTE: P010, P210, and Y410 are only supported uncompressed. ++ */ ++ MALI_GRALLOC_FORMAT_INTERNAL_Y0L2, ++ MALI_GRALLOC_FORMAT_INTERNAL_P010, ++ MALI_GRALLOC_FORMAT_INTERNAL_P210, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y210, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y410, ++ ++ /* Add more internal formats here. Make sure decode_internal_format() is updated. */ ++ ++ /* These are legacy 0.3 gralloc formats used only by the wrap/unwrap macros. */ ++ MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP, ++ MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP, ++ ++ MALI_GRALLOC_FORMAT_INTERNAL_RANGE_LAST, ++} mali_gralloc_pixel_format; ++ ++/* Format Modifier Bits Locations */ ++#define MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START 32 ++#define MALI_GRALLOC_INTFMT_EXTENSION_BIT_START (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START + 16) ++ ++/* Mutually Exclusive Modifier Bits */ ++ ++/* This format will use AFBC */ ++#define MALI_GRALLOC_INTFMT_AFBC_BASIC (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START + 0)) ++ ++/* This format uses AFBC split block mode */ ++#define MALI_GRALLOC_INTFMT_AFBC_SPLITBLK (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START + 1)) ++ ++#define MALI_GRALLOC_INTFMT_UNUSED (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START + 2)) ++ ++/* This format uses AFBC wide block mode */ ++#define MALI_GRALLOC_INTFMT_AFBC_WIDEBLK (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START + 3)) ++ ++/* Regular Modifier Bits */ ++#define MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 0)) ++ ++/* This mask should be used to check or clear support for AFBC for an internal format ++ * These bits are mutually exclusive so this mask should not be used to enable support ++ */ ++#define MALI_GRALLOC_INTFMT_AFBCENABLE_MASK \ ++ ((uint64_t)(MALI_GRALLOC_INTFMT_AFBC_BASIC | MALI_GRALLOC_INTFMT_AFBC_SPLITBLK | MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)) ++ ++/* These are legacy Gralloc 0.3 support macros for passing private formats through the 0.3 alloc interface. ++ * It packs modifier bits together with base format into a 32 bit format identifier. ++ * Gralloc 1.0 interface should use private functions to set private buffer format in the buffer descriptor. ++ * ++ * Packing: ++ * ++ * Bits 15-0: mali_gralloc_pixel_format format ++ * Bits 23-16: mutually exclusive modifier bits ++ * Bits 31-24: regular modifier bits ++ */ ++static inline int mali_gralloc_format_wrapper(int format, int modifiers) ++{ ++ /* Internal formats that are identical to HAL formats ++ * have the same definition. This is convenient for ++ * client parsing code to not have to parse them separately. ++ * ++ * For 3 of the HAL YUV formats that have very large definitions ++ * this causes problems for packing in modifier bits. ++ * Because of this reason we redefine these three formats ++ * while packing/unpacking them. ++ */ ++ if (format == MALI_GRALLOC_FORMAT_INTERNAL_YV12) ++ { ++ format = MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP; ++ } ++ else if (format == MALI_GRALLOC_FORMAT_INTERNAL_Y8) ++ { ++ format = MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP; ++ } ++ else if (format == MALI_GRALLOC_FORMAT_INTERNAL_Y16) ++ { ++ format = MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP; ++ } ++ ++ return (modifiers | format); ++} ++ ++static inline uint64_t mali_gralloc_format_unwrap(int x) ++{ ++ uint64_t internal_format = (uint64_t)(((((uint64_t)(x)) & 0xff000000) << 24) | // Regular modifier bits ++ ((((uint64_t)(x)) & 0x00ff0000) << 16) | // Mutually exclusive modifier bits ++ (((uint64_t)(x)) & 0x0000ffff)); // Private format ++ ++ uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; ++ uint64_t modifiers = internal_format & MALI_GRALLOC_INTFMT_EXT_MASK; ++ ++ if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP) ++ { ++ base_format = MALI_GRALLOC_FORMAT_INTERNAL_YV12; ++ } ++ else if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP) ++ { ++ base_format = MALI_GRALLOC_FORMAT_INTERNAL_Y8; ++ } ++ else if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP) ++ { ++ base_format = MALI_GRALLOC_FORMAT_INTERNAL_Y16; ++ } ++ ++ return (modifiers | base_format); ++} ++ ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER(x) (mali_gralloc_format_wrapper(x, 0)) ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x) (mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_BASIC >> 16))) ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x) \ ++ (mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_SPLITBLK >> 16))) ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDEBLK(x) \ ++ (mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_WIDEBLK >> 16))) ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_BASIC(x) \ ++ (mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS >> 24) | \ ++ (MALI_GRALLOC_INTFMT_AFBC_BASIC >> 16))) ++#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_WIDE(x) \ ++ (mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS >> 24) | \ ++ (MALI_GRALLOC_INTFMT_AFBC_WIDEBLK >> 16))) ++#define GRALLOC_PRIVATE_FORMAT_UNWRAP(x) mali_gralloc_format_unwrap(x) ++ ++/* IP block capability masks */ ++#define MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT ((uint64_t)(1 << 0)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC ((uint64_t)(1 << 1)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK ((uint64_t)(1 << 2)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK ((uint64_t)(1 << 3)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK_YUV_DISABLE ((uint64_t)(1 << 4)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOREAD ((uint64_t)(1 << 5)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOWRITE ((uint64_t)(1 << 6)) ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS ((uint64_t)(1 << 7)) ++ ++#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK \ ++ ((uint64_t)(MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC | MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK | \ ++ MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK | MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS)) ++ ++struct mali_gralloc_format_caps ++{ ++ uint64_t caps_mask; ++}; ++typedef struct mali_gralloc_format_caps mali_gralloc_format_caps; ++ ++#define MALI_GRALLOC_FORMATCAPS_SYM_NAME mali_gralloc_format_capabilities ++#define MALI_GRALLOC_FORMATCAPS_SYM_NAME_STR "mali_gralloc_format_capabilities" ++ ++/* Producer and Consumer definitions */ ++typedef enum ++{ ++ MALI_GRALLOC_PRODUCER_VIDEO_DECODER, ++ MALI_GRALLOC_PRODUCER_GPU, ++ MALI_GRALLOC_PRODUCER_CAMERA, ++} mali_gralloc_producer_type; ++ ++typedef enum ++{ ++ ++ /* For surface composition in SurfaceFlinger a producer ++ * will not know what consumer will process a buffer. ++ * ++ * MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY means the GPU ++ * MUST support the given format but it should be allocated ++ * with preference to the DPU. ++ */ ++ MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY, ++ MALI_GRALLOC_CONSUMER_VIDEO_ENCODER, ++ ++ /* This is used when no known "premium" dpu is configured. ++ * For example, HDLCD/CLCD would be such a dpu. ++ */ ++ MALI_GRALLOC_CONSUMER_GPU_EXCL, ++} mali_gralloc_consumer_type; ++ ++/* Internal prototypes */ ++#if defined(GRALLOC_LIBRARY_BUILD) ++uint64_t mali_gralloc_select_format(uint64_t req_format, mali_gralloc_format_type type, uint64_t usage, ++ int buffer_size); ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void mali_gralloc_get_gpu_caps(struct mali_gralloc_format_caps *gpu_caps); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* MALI_GRALLOC_FORMATS_H_ */ ++// clang-format on +diff --git a/tests/test_include/mali_gralloc_private_interface_types.h b/tests/test_include/mali_gralloc_private_interface_types.h +new file mode 100644 +index 0000000..26b7744 +--- /dev/null ++++ b/tests/test_include/mali_gralloc_private_interface_types.h +@@ -0,0 +1,88 @@ ++// clang-format off ++/* ++ * Copyright (C) 2017 ARM Limited. All rights reserved. ++ * ++ * Copyright (C) 2008 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 MALI_GRALLOC_PRIVATE_INTERFACE_TYPES_H_ ++#define MALI_GRALLOC_PRIVATE_INTERFACE_TYPES_H_ ++ ++#define GRALLOC_ARM_BUFFER_ATTR_HDR_INFO_SUPPORT ++ ++typedef enum ++{ ++ MALI_HDR_NO_INFO, ++ MALI_HDR_ST2084, ++ MALI_HDR_HLG, ++ MALI_HDR_LAST ++} mali_transfer_function; ++ ++typedef struct ++{ ++ //values are in units of 0.00002 ++ uint16_t x; ++ uint16_t y; ++} primaries; ++ ++typedef struct ++{ ++ primaries r; ++ primaries g; ++ primaries b; ++ primaries w; ++ uint16_t minDisplayLuminance; // in cd/m^2 ++ uint16_t maxDisplayLuminance; // in 0.0001 cd/m^2 ++ uint16_t maxContentLightLevel; // in cd/m^2 ++ uint16_t maxFrameAverageLightLevel; // in cd/m^2 ++ mali_transfer_function eotf; ++} mali_hdr_info; ++ ++enum ++{ ++ /* CROP_RECT and YUV_TRANS are intended to be ++ * written by producers and read by consumers. ++ * A producer should write these parameters before ++ * it queues a buffer to the consumer. ++ */ ++ ++ /* CROP RECT, defined as an int array of top, left, height, width. Origin in top-left corner */ ++ GRALLOC_ARM_BUFFER_ATTR_CROP_RECT = 1, ++ ++ /* Set if the AFBC format used a YUV transform before compressing */ ++ GRALLOC_ARM_BUFFER_ATTR_AFBC_YUV_TRANS = 2, ++ ++ /* Set if the AFBC format uses sparse allocation */ ++ GRALLOC_ARM_BUFFER_ATTR_AFBC_SPARSE_ALLOC = 3, ++ ++ /* HDR Informations*/ ++ GRALLOC_ARM_BUFFER_ATTR_HDR_INFO = 4, ++ ++ GRALLOC_ARM_BUFFER_ATTR_LAST ++}; ++ ++typedef uint32_t buf_attr; ++ ++typedef enum ++{ ++ MALI_YUV_NO_INFO, ++ MALI_YUV_BT601_NARROW, ++ MALI_YUV_BT601_WIDE, ++ MALI_YUV_BT709_NARROW, ++ MALI_YUV_BT709_WIDE ++} mali_gralloc_yuv_info; ++ ++#endif /* MALI_GRALLOC_PRIVATE_INTERFACE_TYPES_H_ */ ++// clang-format on +diff --git a/tests/test_include/mali_gralloc_usages.h b/tests/test_include/mali_gralloc_usages.h +new file mode 100644 +index 0000000..55de5a0 +--- /dev/null ++++ b/tests/test_include/mali_gralloc_usages.h +@@ -0,0 +1,94 @@ ++// clang-format off ++/* ++ * (C) COPYRIGHT 2017 ARM Limited. All rights reserved. ++ * Copyright (C) 2008 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 MALI_GRALLOC_USAGES_H_ ++#define MALI_GRALLOC_USAGES_H_ ++ ++/* ++ * Below usage types overlap, this is intentional. ++ * The reason is that for Gralloc 0.3 there are very ++ * few usage flags we have at our disposal. ++ * ++ * The overlapping is handled by processing the definitions ++ * in a specific order. ++ * ++ * MALI_GRALLOC_USAGE_PRIVATE_FORMAT and MALI_GRALLOC_USAGE_NO_AFBC ++ * don't overlap and are processed first. ++ * ++ * MALI_GRALLOC_USAGE_YUV_CONF are only for YUV formats and clients ++ * using MALI_GRALLOC_USAGE_NO_AFBC must never allocate YUV formats. ++ * The latter is strictly enforced and allocations will fail. ++ * ++ * MALI_GRALLOC_USAGE_AFBC_PADDING is only valid if MALI_GRALLOC_USAGE_NO_AFBC ++ * is not present. ++ */ ++ ++/* ++ * Gralloc private usage 0-3 are the same in 0.3 and 1.0. ++ * We defined based our usages based on what is available. ++ */ ++#if defined(GRALLOC_MODULE_API_VERSION_1_0) ++typedef enum ++{ ++ /* The client has specified a private format in the format parameter */ ++ MALI_GRALLOC_USAGE_PRIVATE_FORMAT = (int)GRALLOC1_PRODUCER_USAGE_PRIVATE_3, ++ ++ /* Buffer won't be allocated as AFBC */ ++ MALI_GRALLOC_USAGE_NO_AFBC = (int)(GRALLOC1_PRODUCER_USAGE_PRIVATE_1 | GRALLOC1_PRODUCER_USAGE_PRIVATE_2), ++ ++ /* Valid only for YUV allocations */ ++ MALI_GRALLOC_USAGE_YUV_CONF_0 = 0, ++ MALI_GRALLOC_USAGE_YUV_CONF_1 = (int)GRALLOC1_PRODUCER_USAGE_PRIVATE_1, ++ MALI_GRALLOC_USAGE_YUV_CONF_2 = (int)GRALLOC1_PRODUCER_USAGE_PRIVATE_0, ++ MALI_GRALLOC_USAGE_YUV_CONF_3 = (int)(GRALLOC1_PRODUCER_USAGE_PRIVATE_0 | GRALLOC1_PRODUCER_USAGE_PRIVATE_1), ++ MALI_GRALLOC_USAGE_YUV_CONF_MASK = MALI_GRALLOC_USAGE_YUV_CONF_3, ++ ++ /* A very specific alignment is requested on some buffers */ ++ MALI_GRALLOC_USAGE_AFBC_PADDING = (int)GRALLOC1_PRODUCER_USAGE_PRIVATE_2, ++ ++} mali_gralloc_usage_type; ++#elif defined(GRALLOC_MODULE_API_VERSION_0_3) ++typedef enum ++{ ++ /* The client has specified a private format in the format parameter */ ++ MALI_GRALLOC_USAGE_PRIVATE_FORMAT = (int)GRALLOC_USAGE_PRIVATE_3, ++ ++ /* Buffer won't be allocated as AFBC */ ++ MALI_GRALLOC_USAGE_NO_AFBC = (int)(GRALLOC_USAGE_PRIVATE_1 | GRALLOC_USAGE_PRIVATE_2), ++ ++ /* Valid only for YUV allocations */ ++ MALI_GRALLOC_USAGE_YUV_CONF_0 = 0, ++ MALI_GRALLOC_USAGE_YUV_CONF_1 = (int)GRALLOC_USAGE_PRIVATE_1, ++ MALI_GRALLOC_USAGE_YUV_CONF_2 = (int)GRALLOC_USAGE_PRIVATE_0, ++ MALI_GRALLOC_USAGE_YUV_CONF_3 = (int)(GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1), ++ MALI_GRALLOC_USAGE_YUV_CONF_MASK = MALI_GRALLOC_USAGE_YUV_CONF_3, ++ ++ /* A very specific alignment is requested on some buffers */ ++ MALI_GRALLOC_USAGE_AFBC_PADDING = GRALLOC_USAGE_PRIVATE_2, ++ ++} mali_gralloc_usage_type; ++#else ++#if defined(GRALLOC_LIBRARY_BUILD) ++#error "Please include mali_gralloc_module.h before including other gralloc headers when building gralloc itself" ++#else ++#error "Please include either gralloc.h or gralloc1.h header before including gralloc_priv.h" ++#endif ++#endif ++ ++#endif /*MALI_GRALLOC_USAGES_H_*/ ++// clang-format on +diff --git a/tests/worker_test.cpp b/tests/worker_test.cpp +index 82523f0..d1eb2b3 100644 +--- a/tests/worker_test.cpp ++++ b/tests/worker_test.cpp +@@ -1,24 +1,20 @@ ++#include "utils/Worker.h" ++ + #include + #include + + #include + +-#include "worker.h" +- + using android::Worker; + + struct TestWorker : public Worker { +- TestWorker() +- : Worker("test-worker", HAL_PRIORITY_URGENT_DISPLAY), +- value(0), +- enabled_(false) { +- } ++ TestWorker() : Worker("test-worker", HAL_PRIORITY_URGENT_DISPLAY){}; + + int Init() { + return InitWorker(); + } + +- void Routine() { ++ void Routine() override { + Lock(); + if (!enabled_) { + int ret = WaitForSignalOrExitLocked(); +@@ -47,16 +43,17 @@ struct TestWorker : public Worker { + Signal(); + } + +- int value; ++ // NOLINTNEXTLINE: should not be public ++ int value{}; + + private: +- bool enabled_; ++ bool enabled_{}; + }; + + struct WorkerTest : public testing::Test { + TestWorker worker; + +- virtual void SetUp() { ++ void SetUp() override { + worker.Init(); + } + +@@ -65,7 +62,8 @@ struct WorkerTest : public testing::Test { + } + }; + +-TEST_F(WorkerTest, test_worker) { ++// NOLINTNEXTLINE: required by gtest macros ++TEST_F(WorkerTest, TestWorker) { + // already isInitialized so should succeed + ASSERT_TRUE(worker.initialized()); + +@@ -102,7 +100,8 @@ TEST_F(WorkerTest, test_worker) { + ASSERT_FALSE(worker.initialized()); + } + +-TEST_F(WorkerTest, exit_while_running) { ++// NOLINTNEXTLINE: required by gtest macros ++TEST_F(WorkerTest, ExitWhileRunning) { + worker.Control(true); + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h +new file mode 100644 +index 0000000..1a390ba +--- /dev/null ++++ b/utils/UniqueFd.h +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2015, 2021 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 UNIQUEFD_H_ ++#define UNIQUEFD_H_ ++ ++#include ++ ++#include ++ ++namespace android { ++ ++/* ++ * Using UniqueFd: ++ * 1. Create UniqueFd object: ++ * auto fd_obj = UniqueFd(open("SomeFile", xxx)); ++ * ++ * 2. Check whether the fd_obj is empty: ++ * if (!fd_obj) { return -errno; } ++ * ++ * 3. Accessing the file descriptor: ++ * int ret = read(fd_obj.Get(), buf, buf_size); ++ * ++ * 4. Closing the file: ++ * FD will be closed once execution leaves fd_obj scope (on any return, ++ * exception, destruction of class/struct where object is member, etc.). ++ * User can also force closing the fd_obj by calling: ++ * fd_obj = UniqueFd(); ++ * // fd is closed and fd_obj is empty now. ++ * ++ * 5. File descriptor may be transferred to the code, which will close it after ++ * using. This can be done in 2 ways: ++ * a. Duplicate the fd, in this case both fds should be closed separately: ++ * int out_fd = dup(fd_obj.Get(); ++ * ... ++ * close(out_fd); ++ * b. Transfer ownership, use this method if you do not need the fd anymore. ++ * int out_fd = fd_obj.Release(); ++ * // fd_obj is empty now. ++ * ... ++ * close(out_fd); ++ * ++ * 6. Transferring fd into another UniqueFD object: ++ * UniqueFd fd_obj_2 = std::move(fd_obj); ++ * // fd_obj empty now ++ */ ++ ++constexpr int kEmptyFd = -1; ++ ++class UniqueFd { ++ public: ++ UniqueFd() = default; ++ explicit UniqueFd(int fd) : fd_(fd){}; ++ ++ auto Release [[nodiscard]] () -> int { ++ return std::exchange(fd_, kEmptyFd); ++ } ++ ++ auto Get [[nodiscard]] () const -> int { ++ return fd_; ++ } ++ ++ explicit operator bool() const { ++ return fd_ != kEmptyFd; ++ } ++ ++ ~UniqueFd() { ++ Set(kEmptyFd); ++ } ++ ++ /* Allow move semantics */ ++ UniqueFd(UniqueFd &&rhs) noexcept { ++ Set(rhs.Release()); ++ } ++ ++ auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & { ++ Set(rhs.Release()); ++ return *this; ++ } ++ ++ /* Disable copy semantics */ ++ UniqueFd(const UniqueFd &) = delete; ++ auto operator=(const UniqueFd &) = delete; ++ ++ private: ++ void Set(int new_fd) { ++ if (fd_ != kEmptyFd) { ++ close(fd_); ++ } ++ fd_ = new_fd; ++ } ++ ++ int fd_ = kEmptyFd; ++}; ++ ++} // namespace android ++ ++#endif +diff --git a/utils/worker.cpp b/utils/Worker.cpp +similarity index 94% +rename from utils/worker.cpp +rename to utils/Worker.cpp +index 0dceb16..d2b60c8 100644 +--- a/utils/worker.cpp ++++ b/utils/Worker.cpp +@@ -14,7 +14,7 @@ + * limitations under the License. + */ + +-#include "worker.h" ++#include "Worker.h" + + #include + #include +@@ -34,8 +34,7 @@ int Worker::InitWorker() { + if (initialized()) + return -EALREADY; + +- thread_ = std::unique_ptr( +- new std::thread(&Worker::InternalRoutine, this)); ++ thread_ = std::make_unique(&Worker::InternalRoutine, this); + initialized_ = true; + exit_ = false; + +diff --git a/include/worker.h b/utils/Worker.h +similarity index 100% +rename from include/worker.h +rename to utils/Worker.h +index 7909038..73a80da 100644 +--- a/include/worker.h ++++ b/utils/Worker.h +@@ -19,10 +19,10 @@ + + #include + #include +-#include + + #include + #include ++#include + #include + + namespace android { +diff --git a/utils/autolock.cpp b/utils/autolock.cpp +index 4e9552a..3342e46 100644 +--- a/utils/autolock.cpp ++++ b/utils/autolock.cpp +@@ -19,10 +19,11 @@ + + #include "autolock.h" + +-#include + #include + +-#include ++#include ++ ++#include "utils/log.h" + + namespace android { + +diff --git a/include/autolock.h b/utils/autolock.h +similarity index 100% +rename from include/autolock.h +rename to utils/autolock.h +diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp +index 87e3c42..6de6500 100644 +--- a/utils/hwcutils.cpp ++++ b/utils/hwcutils.cpp +@@ -17,138 +17,37 @@ + #define ATRACE_TAG ATRACE_TAG_GRAPHICS + #define LOG_TAG "hwc-drm-utils" + +-#include "drmhwcomposer.h" +-#include "platform.h" +- + #include ++#include + #include + ++#include "bufferinfo/BufferInfoGetter.h" ++#include "drm/DrmFbImporter.h" ++#include "drmhwcomposer.h" ++ + #define UNUSED(x) (void)(x) + + namespace android { + +-const hwc_drm_bo *DrmHwcBuffer::operator->() const { +- if (importer_ == NULL) { +- ALOGE("Access of non-existent BO"); +- exit(1); +- return NULL; +- } +- return &bo_; +-} ++int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) { ++ buffer_info = hwc_drm_bo_t{}; + +-void DrmHwcBuffer::Clear() { +- if (importer_ != NULL) { +- importer_->ReleaseBuffer(&bo_); +- importer_ = NULL; +- } +-} +- +-int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { +- hwc_drm_bo tmp_bo; +- +- int ret = importer->ImportBuffer(handle, &tmp_bo); +- if (ret) +- return ret; +- +- if (importer_ != NULL) { +- importer_->ReleaseBuffer(&bo_); +- } +- +- importer_ = importer; +- +- bo_ = tmp_bo; +- +- return 0; +-} +- +-int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width, +- int height, int layerCount, int format, +- int usage, int stride) { +- native_handle_t *handle_copy; +- GraphicBufferMapper &gm(GraphicBufferMapper::get()); +- int ret; +- +-#ifdef HWC2_USE_OLD_GB_IMPORT +- UNUSED(width); +- UNUSED(height); +- UNUSED(layerCount); +- UNUSED(format); +- UNUSED(usage); +- UNUSED(stride); +- ret = gm.importBuffer(handle, const_cast(&handle_copy)); +-#else +- ret = gm.importBuffer(handle, width, height, layerCount, format, usage, +- stride, const_cast(&handle_copy)); +-#endif ++ int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(sf_handle, ++ &buffer_info); + if (ret) { +- ALOGE("Failed to import buffer handle %d", ret); ++ ALOGE("Failed to convert buffer info %d", ret); + return ret; + } + +- Clear(); +- +- handle_ = handle_copy; +- +- return 0; +-} +- +-DrmHwcNativeHandle::~DrmHwcNativeHandle() { +- Clear(); +-} +- +-void DrmHwcNativeHandle::Clear() { +- if (handle_ != NULL) { +- GraphicBufferMapper &gm(GraphicBufferMapper::get()); +- int ret = gm.freeBuffer(handle_); +- if (ret) { +- ALOGE("Failed to free buffer handle %d", ret); +- } +- handle_ = NULL; ++ FbIdHandle = drmDevice->GetDrmFbImporter().GetOrCreateFbId(&buffer_info); ++ if (!FbIdHandle) { ++ ALOGE("Failed to import buffer"); ++ return -EINVAL; + } +-} +- +-int DrmHwcLayer::ImportBuffer(Importer *importer) { +- int ret = buffer.ImportBuffer(sf_handle, importer); +- if (ret) +- return ret; +- +- const hwc_drm_bo *bo = buffer.operator->(); +- +- unsigned int layer_count; +- for (layer_count = 0; layer_count < HWC_DRM_BO_MAX_PLANES; ++layer_count) +- if (bo->gem_handles[layer_count] == 0) +- break; +- +- ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height, layer_count, +- bo->hal_format, bo->usage, bo->pixel_stride); +- if (ret) +- return ret; +- +- gralloc_buffer_usage = bo->usage; + + return 0; + } + +-int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer, +- Importer *importer) { +- blending = src_layer->blending; +- sf_handle = src_layer->sf_handle; +- acquire_fence = -1; +- display_frame = src_layer->display_frame; +- alpha = src_layer->alpha; +- source_crop = src_layer->source_crop; +- transform = src_layer->transform; +- return ImportBuffer(importer); +-} +- +-void DrmHwcLayer::SetSourceCrop(hwc_frect_t const &crop) { +- source_crop = crop; +-} +- +-void DrmHwcLayer::SetDisplayFrame(hwc_rect_t const &frame) { +- display_frame = frame; +-} +- + void DrmHwcLayer::SetTransform(int32_t sf_transform) { + transform = 0; + // 270* and 180* cannot be combined with flips. More specifically, they +diff --git a/utils/log.h b/utils/log.h +new file mode 100644 +index 0000000..a48d2e7 +--- /dev/null ++++ b/utils/log.h +@@ -0,0 +1,26 @@ ++#ifndef UTILS_LOG_H_ ++#define UTILS_LOG_H_ ++ ++#ifdef ANDROID ++ ++#include ++ ++#else ++ ++#include ++#include ++ ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define ALOGE(args...) printf("ERR: " args) ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define ALOGW(args...) printf("WARN: " args) ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define ALOGI(args...) printf("INFO: " args) ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define ALOGD(args...) printf("DBG:" args) ++// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) ++#define ALOGV(args...) printf("VERBOSE: " args) ++ ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/utils/properties.h b/utils/properties.h +new file mode 100644 +index 0000000..607cbc5 +--- /dev/null ++++ b/utils/properties.h +@@ -0,0 +1,28 @@ ++#ifndef UTILS_PROPERTIES_H_ ++#define UTILS_PROPERTIES_H_ ++ ++#ifdef ANDROID ++ ++#include ++ ++#else ++ ++#include ++#include ++#include ++ ++// NOLINTNEXTLINE(readability-identifier-naming) ++constexpr int PROPERTY_VALUE_MAX = 92; ++ ++auto inline property_get(const char *name, char *value, ++ const char *default_value) -> int { ++ char *prop = std::getenv(name); ++ if (prop == nullptr) { ++ snprintf(value, PROPERTY_VALUE_MAX, "%s", default_value); ++ } ++ return strlen(value); ++} ++ ++#endif ++ ++#endif +\ No newline at end of file +-- +2.32.0 + diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0001-update-drm-hwcomposer.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0001-update-drm-hwcomposer.patch deleted file mode 100644 index fd00dec4bd..0000000000 --- a/aosp_diff/preliminary/external/drm_hwcomposer/0001-update-drm-hwcomposer.patch +++ /dev/null @@ -1,4994 +0,0 @@ -From b17066ffc6cc13a5cc50024067dc2921878c0618 Mon Sep 17 00:00:00 2001 -From: kanlihux -Date: Fri, 26 Feb 2021 22:19:15 +0800 -Subject: [PATCH] update drm hwcomposer - ---- - Android.bp | 84 +++--- - drmhwctwo.cpp => DrmHwcTwo.cpp | 278 +++++++++--------- - include/drmhwctwo.h => DrmHwcTwo.h | 161 +++++++--- - METADATA | 3 - - OWNERS | 5 - - backend/Backend.cpp | 137 +++++++++ - backend/Backend.h | 38 +++ - backend/BackendClient.cpp | 35 +++ - backend/BackendClient.h | 32 ++ - backend/BackendManager.cpp | 79 +++++ - backend/BackendManager.h | 57 ++++ - backend/BackendRCarDu.cpp | 45 +++ - backend/BackendRCarDu.h | 31 ++ - bufferinfo/BufferInfoGetter.cpp | 118 ++++++++ - bufferinfo/BufferInfoGetter.h | 76 +++++ - bufferinfo/BufferInfoMapperMetadata.cpp | 145 +++++++++ - bufferinfo/BufferInfoMapperMetadata.h | 36 +++ - .../legacy/BufferInfoImagination.cpp | 45 ++- - bufferinfo/legacy/BufferInfoImagination.h | 34 +++ - bufferinfo/legacy/BufferInfoLibdrm.cpp | 204 +++++++++++++ - bufferinfo/legacy/BufferInfoLibdrm.h | 37 +++ - bufferinfo/legacy/BufferInfoMaliHisi.cpp | 126 ++++++++ - .../legacy/BufferInfoMaliHisi.h | 20 +- - bufferinfo/legacy/BufferInfoMaliMediatek.cpp | 58 ++++ - bufferinfo/legacy/BufferInfoMaliMediatek.h | 34 +++ - .../legacy/BufferInfoMaliMeson.cpp | 43 +-- - .../legacy/BufferInfoMaliMeson.h | 17 +- - .../legacy/BufferInfoMinigbm.cpp | 50 ++-- - .../legacy/BufferInfoMinigbm.h | 14 +- - ...position.cpp => DrmDisplayComposition.cpp} | 16 +- - .../DrmDisplayComposition.h | 10 +- - ...ompositor.cpp => DrmDisplayCompositor.cpp} | 89 +++++- - .../DrmDisplayCompositor.h | 29 +- - .../platform.cpp => compositor/Planner.cpp | 18 +- - include/platform.h => compositor/Planner.h | 33 +-- - drm/{drmconnector.cpp => DrmConnector.cpp} | 37 ++- - include/drmconnector.h => drm/DrmConnector.h | 11 +- - drm/{drmcrtc.cpp => DrmCrtc.cpp} | 6 +- - include/drmcrtc.h => drm/DrmCrtc.h | 6 +- - drm/{drmdevice.cpp => DrmDevice.cpp} | 41 ++- - include/drmdevice.h => drm/DrmDevice.h | 17 +- - drm/{drmencoder.cpp => DrmEncoder.cpp} | 6 +- - include/drmencoder.h => drm/DrmEncoder.h | 5 +- - ...eventlistener.cpp => DrmEventListener.cpp} | 10 +- - .../DrmEventListener.h | 2 +- - drm/DrmGenericImporter.cpp | 139 +++++++++ - .../DrmGenericImporter.h | 43 +-- - drm/{drmmode.cpp => DrmMode.cpp} | 7 +- - include/drmmode.h => drm/DrmMode.h | 1 + - drm/{drmplane.cpp => DrmPlane.cpp} | 45 ++- - include/drmplane.h => drm/DrmPlane.h | 16 +- - drm/{drmproperty.cpp => DrmProperty.cpp} | 7 +- - include/drmproperty.h => drm/DrmProperty.h | 1 + - ...esourcemanager.cpp => ResourceManager.cpp} | 47 ++- - .../ResourceManager.h | 7 +- - drm/{vsyncworker.cpp => VSyncWorker.cpp} | 51 ++-- - include/vsyncworker.h => drm/VSyncWorker.h | 16 +- - .../{drmframebuffer.h => DrmFramebuffer.h} | 2 - - include/drmhwcgralloc.h | 2 - - include/drmhwcomposer.h | 4 +- - platform/platformdrmgeneric.cpp | 252 ---------------- - platform/platformhisi.cpp | 197 ------------- - platform/platformimagination.h | 22 -- - tests/Android.bp | 5 +- - tests/worker_test.cpp | 4 +- - utils/{worker.cpp => Worker.cpp} | 2 +- - include/worker.h => utils/Worker.h | 2 +- - {include => utils}/autolock.h | 0 - utils/hwcutils.cpp | 50 ++-- - 69 files changed, 2247 insertions(+), 1053 deletions(-) - rename drmhwctwo.cpp => DrmHwcTwo.cpp (90%) - rename include/drmhwctwo.h => DrmHwcTwo.h (83%) - delete mode 100644 METADATA - delete mode 100644 OWNERS - create mode 100644 backend/Backend.cpp - create mode 100644 backend/Backend.h - create mode 100644 backend/BackendClient.cpp - create mode 100644 backend/BackendClient.h - create mode 100644 backend/BackendManager.cpp - create mode 100644 backend/BackendManager.h - create mode 100644 backend/BackendRCarDu.cpp - create mode 100644 backend/BackendRCarDu.h - create mode 100644 bufferinfo/BufferInfoGetter.cpp - create mode 100644 bufferinfo/BufferInfoGetter.h - create mode 100644 bufferinfo/BufferInfoMapperMetadata.cpp - create mode 100644 bufferinfo/BufferInfoMapperMetadata.h - rename platform/platformimagination.cpp => bufferinfo/legacy/BufferInfoImagination.cpp (53%) - create mode 100644 bufferinfo/legacy/BufferInfoImagination.h - create mode 100644 bufferinfo/legacy/BufferInfoLibdrm.cpp - create mode 100644 bufferinfo/legacy/BufferInfoLibdrm.h - create mode 100644 bufferinfo/legacy/BufferInfoMaliHisi.cpp - rename platform/platformhisi.h => bufferinfo/legacy/BufferInfoMaliHisi.h (69%) - create mode 100644 bufferinfo/legacy/BufferInfoMaliMediatek.cpp - create mode 100644 bufferinfo/legacy/BufferInfoMaliMediatek.h - rename platform/platformmeson.cpp => bufferinfo/legacy/BufferInfoMaliMeson.cpp (67%) - rename platform/platformmeson.h => bufferinfo/legacy/BufferInfoMaliMeson.h (76%) - rename platform/platformminigbm.cpp => bufferinfo/legacy/BufferInfoMinigbm.cpp (53%) - rename platform/platformminigbm.h => bufferinfo/legacy/BufferInfoMinigbm.h (75%) - rename compositor/{drmdisplaycomposition.cpp => DrmDisplayComposition.cpp} (98%) - rename include/drmdisplaycomposition.h => compositor/DrmDisplayComposition.h (98%) - rename compositor/{drmdisplaycompositor.cpp => DrmDisplayCompositor.cpp} (92%) - rename include/drmdisplaycompositor.h => compositor/DrmDisplayCompositor.h (89%) - rename platform/platform.cpp => compositor/Planner.cpp (91%) - rename include/platform.h => compositor/Planner.h (81%) - rename drm/{drmconnector.cpp => DrmConnector.cpp} (92%) - rename include/drmconnector.h => drm/DrmConnector.h (94%) - rename drm/{drmcrtc.cpp => DrmCrtc.cpp} (97%) - rename include/drmcrtc.h => drm/DrmCrtc.h (97%) - rename drm/{drmdevice.cpp => DrmDevice.cpp} (96%) - rename include/drmdevice.h => drm/DrmDevice.h (94%) - rename drm/{drmencoder.cpp => DrmEncoder.cpp} (95%) - rename include/drmencoder.h => drm/DrmEncoder.h (98%) - rename drm/{drmeventlistener.cpp => DrmEventListener.cpp} (98%) - rename include/drmeventlistener.h => drm/DrmEventListener.h (98%) - create mode 100644 drm/DrmGenericImporter.cpp - rename platform/platformdrmgeneric.h => drm/DrmGenericImporter.h (61%) - rename drm/{drmmode.cpp => DrmMode.cpp} (96%) - rename include/drmmode.h => drm/DrmMode.h (99%) - rename drm/{drmplane.cpp => DrmPlane.cpp} (80%) - rename include/drmplane.h => drm/DrmPlane.h (87%) - rename drm/{drmproperty.cpp => DrmProperty.cpp} (98%) - rename include/drmproperty.h => drm/DrmProperty.h (99%) - rename drm/{resourcemanager.cpp => ResourceManager.cpp} (75%) - rename include/resourcemanager.h => drm/ResourceManager.h (94%) - rename drm/{vsyncworker.cpp => VSyncWorker.cpp} (75%) - rename include/vsyncworker.h => drm/VSyncWorker.h (84%) - rename include/{drmframebuffer.h => DrmFramebuffer.h} (99%) - delete mode 100644 platform/platformdrmgeneric.cpp - delete mode 100644 platform/platformhisi.cpp - delete mode 100644 platform/platformimagination.h - rename utils/{worker.cpp => Worker.cpp} (99%) - rename include/worker.h => utils/Worker.h (100%) - rename {include => utils}/autolock.h (100%) - -diff --git a/Android.bp b/Android.bp -index 8bcd1aa..20b22ce 100644 ---- a/Android.bp -+++ b/Android.bp -@@ -18,9 +18,12 @@ - cc_library_static { - name: "libdrmhwc_utils", - -- srcs: ["utils/worker.cpp"], -+ srcs: ["utils/Worker.cpp"], - -- include_dirs: ["external/drm_hwcomposer/include"], -+ include_dirs: [ -+ "external/drm_hwcomposer/include", -+ "external/drm_hwcomposer", -+ ], - - cflags: [ - "-Wall", -@@ -41,13 +44,17 @@ cc_defaults { - "libcutils", - "libdrm", - "libhardware", -+ "libhidlbase", - "liblog", - "libsync", - "libui", - "libutils", - ], - -- include_dirs: ["external/drm_hwcomposer/include"], -+ include_dirs: [ -+ "external/drm_hwcomposer/include", -+ "external/drm_hwcomposer", -+ ], - - static_libs: ["libdrmhwc_utils"], - -@@ -74,26 +81,34 @@ cc_library_static { - name: "drm_hwcomposer", - defaults: ["hwcomposer.drm_defaults"], - srcs: [ -- "drmhwctwo.cpp", -- -- "compositor/drmdisplaycomposition.cpp", -- "compositor/drmdisplaycompositor.cpp", -- -- "drm/drmconnector.cpp", -- "drm/drmcrtc.cpp", -- "drm/drmdevice.cpp", -- "drm/drmencoder.cpp", -- "drm/drmeventlistener.cpp", -- "drm/drmmode.cpp", -- "drm/drmplane.cpp", -- "drm/drmproperty.cpp", -- "drm/resourcemanager.cpp", -- "drm/vsyncworker.cpp", -- -- "platform/platform.cpp", -+ "DrmHwcTwo.cpp", -+ -+ "bufferinfo/BufferInfoGetter.cpp", -+ "bufferinfo/BufferInfoMapperMetadata.cpp", -+ -+ "compositor/DrmDisplayComposition.cpp", -+ "compositor/DrmDisplayCompositor.cpp", -+ "compositor/Planner.cpp", -+ -+ "drm/DrmConnector.cpp", -+ "drm/DrmCrtc.cpp", -+ "drm/DrmDevice.cpp", -+ "drm/DrmEncoder.cpp", -+ "drm/DrmEventListener.cpp", -+ "drm/DrmGenericImporter.cpp", -+ "drm/DrmMode.cpp", -+ "drm/DrmPlane.cpp", -+ "drm/DrmProperty.cpp", -+ "drm/ResourceManager.cpp", -+ "drm/VSyncWorker.cpp", - - "utils/autolock.cpp", - "utils/hwcutils.cpp", -+ -+ "backend/BackendManager.cpp", -+ "backend/Backend.cpp", -+ "backend/BackendClient.cpp", -+ "backend/BackendRCarDu.cpp", - ], - } - -@@ -101,44 +116,37 @@ cc_library_shared { - name: "hwcomposer.drm", - defaults: ["hwcomposer.drm_defaults"], - whole_static_libs: ["drm_hwcomposer"], -- srcs: ["platform/platformdrmgeneric.cpp"], -- cppflags: ["-DUSE_DRM_GENERIC_IMPORTER"], -+ srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"], - } - - cc_library_shared { - name: "hwcomposer.drm_minigbm", - defaults: ["hwcomposer.drm_defaults"], - whole_static_libs: ["drm_hwcomposer"], -- srcs: [ -- "platform/platformdrmgeneric.cpp", -- "platform/platformminigbm.cpp", -- ], -+ srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"], - include_dirs: ["external/minigbm/cros_gralloc"], - } - - // Used by hwcomposer.drm_imagination - filegroup { - name: "drm_hwcomposer_platformimagination", -- srcs: [ -- "platform/platformdrmgeneric.cpp", -- "platform/platformimagination.cpp", -- ], -+ srcs: ["bufferinfo/legacy/BufferInfoImagination.cpp"], - } - - // Used by hwcomposer.drm_hikey and hwcomposer.drm_hikey960 - filegroup { - name: "drm_hwcomposer_platformhisi", -- srcs: [ -- "platform/platformdrmgeneric.cpp", -- "platform/platformhisi.cpp", -- ], -+ srcs: ["bufferinfo/legacy/BufferInfoMaliHisi.cpp"], - } - - // Used by hwcomposer.drm_meson - filegroup { - name: "drm_hwcomposer_platformmeson", -- srcs: [ -- "platform/platformdrmgeneric.cpp", -- "platform/platformmeson.cpp", -- ], -+ srcs: ["bufferinfo/legacy/BufferInfoMaliMeson.cpp"], -+} -+ -+// Used by hwcomposer.drm_mediatek -+filegroup { -+ name: "drm_hwcomposer_platformmediatek", -+ srcs: ["bufferinfo/legacy/BufferInfoMaliMediatek.cpp"], - } -diff --git a/drmhwctwo.cpp b/DrmHwcTwo.cpp -similarity index 90% -rename from drmhwctwo.cpp -rename to DrmHwcTwo.cpp -index 5afc96d..db5f351 100644 ---- a/drmhwctwo.cpp -+++ b/DrmHwcTwo.cpp -@@ -17,37 +17,21 @@ - #define ATRACE_TAG ATRACE_TAG_GRAPHICS - #define LOG_TAG "hwc-drm-two" - --#include "drmhwctwo.h" --#include "drmdisplaycomposition.h" --#include "drmhwcomposer.h" --#include "platform.h" --#include "vsyncworker.h" -- --#include --#include -+#include "DrmHwcTwo.h" - - #include - #include - #include -+#include - #include - --namespace android { -- --class DrmVsyncCallback : public VsyncCallback { -- public: -- DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook) -- : data_(data), hook_(hook) { -- } -+#include - -- void Callback(int display, int64_t timestamp) { -- auto hook = reinterpret_cast(hook_); -- hook(data_, display, timestamp); -- } -+#include "backend/BackendManager.h" -+#include "bufferinfo/BufferInfoGetter.h" -+#include "compositor/DrmDisplayComposition.h" - -- private: -- hwc2_callback_data_t data_; -- hwc2_function_pointer_t hook_; --}; -+namespace android { - - DrmHwcTwo::DrmHwcTwo() { - common.tag = HARDWARE_DEVICE_TAG; -@@ -195,17 +179,10 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, - hwc2_callback_data_t data, - hwc2_function_pointer_t function) { - supported(__func__); -- auto callback = static_cast(descriptor); - -- if (!function) { -- callbacks_.erase(callback); -- return HWC2::Error::None; -- } -- -- callbacks_.emplace(callback, HwcCallback(data, function)); -- -- switch (callback) { -+ switch (static_cast(descriptor)) { - case HWC2::Callback::Hotplug: { -+ SetHotplugCallback(data, function); - auto &drmDevices = resource_manager_.getDrmDevices(); - for (auto &device : drmDevices) - HandleInitialHotplugState(device.get()); -@@ -271,7 +248,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector *planes) { - // Split up the given display planes into primary and overlay to properly - // interface with the composition - char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; -- property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1"); -+ property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop, -+ "1"); - bool use_overlay_planes = atoi(use_overlay_planes_prop); - for (auto &plane : *planes) { - if (plane->type() == DRM_PLANE_TYPE_PRIMARY) -@@ -298,6 +276,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector *planes) { - return HWC2::Error::BadDisplay; - } - -+ ret = BackendManager::GetInstance().SetBackendForDisplay(this); -+ if (ret) { -+ ALOGE("Failed to set backend for d=%d %d\n", display, ret); -+ return HWC2::Error::BadDisplay; -+ } -+ - return ChosePreferredConfig(); - } - -@@ -311,21 +295,16 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() { - return SetActiveConfig(connector_->get_preferred_mode_id()); - } - --HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( -+void DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( - hwc2_callback_data_t data, hwc2_function_pointer_t func) { - supported(__func__); -- auto callback = std::make_shared(data, func); -- vsync_worker_.RegisterCallback(std::move(callback)); -- return HWC2::Error::None; -+ vsync_worker_.RegisterClientCallback(data, func); - } - - void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback( - hwc2_callback_data_t data, hwc2_function_pointer_t func) { - supported(__func__); -- auto hook = reinterpret_cast(func); -- compositor_.SetRefreshCallback([data, hook](int display) { -- hook(data, static_cast(display)); -- }); -+ compositor_.SetRefreshCallback(data, func); - } - - HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() { -@@ -451,6 +430,11 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config, - // Dots per 1000 inches - *value = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1; - break; -+#if PLATFORM_SDK_VERSION > 29 -+ case HWC2::Attribute::ConfigGroup: -+ *value = 0; /* TODO: Add support for config groups */ -+ break; -+#endif - default: - *value = -1; - return HWC2::Error::BadConfig; -@@ -779,11 +763,6 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { - .right = static_cast(mode->h_display()), - .bottom = static_cast(mode->v_display())}; - client_layer_.SetLayerDisplayFrame(display_frame); -- hwc_frect_t source_crop = {.left = 0.0f, -- .top = 0.0f, -- .right = mode->h_display() + 0.0f, -- .bottom = mode->v_display() + 0.0f}; -- client_layer_.SetLayerSourceCrop(source_crop); - - return HWC2::Error::None; - } -@@ -798,15 +777,30 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target, - client_layer_.set_buffer(target); - client_layer_.set_acquire_fence(uf.get()); - client_layer_.SetLayerDataspace(dataspace); -+ -+ /* TODO: Do not update source_crop every call. -+ * It makes sense to do it once after every hotplug event. */ -+ hwc_drm_bo bo{}; -+ BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo); -+ -+ hwc_frect_t source_crop = {.left = 0.0f, -+ .top = 0.0f, -+ .right = bo.width + 0.0f, -+ .bottom = bo.height + 0.0f}; -+ client_layer_.SetLayerSourceCrop(source_crop); -+ - return HWC2::Error::None; - } - - HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) { - supported(__func__); - -- if (mode != HAL_COLOR_MODE_NATIVE) -+ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) - return HWC2::Error::BadParameter; - -+ if (mode != HAL_COLOR_MODE_NATIVE) -+ return HWC2::Error::Unsupported; -+ - color_mode_ = mode; - return HWC2::Error::None; - } -@@ -899,93 +893,71 @@ void DrmHwcTwo::HwcDisplay::MarkValidated( - HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types, - uint32_t *num_requests) { - supported(__func__); -- *num_types = 0; -- *num_requests = 0; -- size_t avail_planes = primary_planes_.size() + overlay_planes_.size(); - -- /* -- * If more layers then planes, save one plane -- * for client composited layers -- */ -- if (avail_planes < layers_.size()) -- avail_planes--; -+ return backend_->ValidateDisplay(this, num_types, num_requests); -+} - -- std::map z_map, z_map_tmp; -- uint32_t z_index = 0; -- // First create a map of layers and z_order values -- for (std::pair &l : layers_) -- z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second)); -- // normalise the map so that the lowest z_order layer has key 0 -- for (std::pair &l : z_map_tmp) -- z_map.emplace(std::make_pair(z_index++, l.second)); -+#if PLATFORM_SDK_VERSION > 29 -+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { -+ if (connector_->internal()) -+ *outType = static_cast(HWC2::DisplayConnectionType::Internal); -+ else if (connector_->external()) -+ *outType = static_cast(HWC2::DisplayConnectionType::External); -+ else -+ return HWC2::Error::BadConfig; -+ -+ return HWC2::Error::None; -+} - -- uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0; -+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayVsyncPeriod( -+ hwc2_vsync_period_t *outVsyncPeriod /* ns */) { -+ supported(__func__); -+ DrmMode const &mode = connector_->active_mode(); -+ if (mode.id() == 0) -+ return HWC2::Error::BadConfig; - -- int client_start = -1, client_size = 0; -+ *outVsyncPeriod = 1E9 / mode.v_refresh(); -+ return HWC2::Error::None; -+} - -- if (compositor_.ShouldFlattenOnClient()) { -- client_start = 0; -- client_size = z_map.size(); -- MarkValidated(z_map, client_start, client_size); -- } else { -- for (std::pair &l : z_map) { -- if (!HardwareSupportsLayerType(l.second->sf_type()) || -- !importer_->CanImportBuffer(l.second->buffer()) || -- color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY || -- (l.second->RequireScalingOrPhasing() && -- resource_manager_->ForcedScalingWithGpu())) { -- if (client_start < 0) -- client_start = l.first; -- client_size = (l.first - client_start) + 1; -- } -- } -+HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfigWithConstraints( -+ hwc2_config_t /*config*/, -+ hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, -+ hwc_vsync_period_change_timeline_t *outTimeline) { -+ supported(__func__); - -- int extra_client = (z_map.size() - client_size) - avail_planes; -- if (extra_client > 0) { -- int start = 0, steps; -- if (client_size != 0) { -- int prepend = std::min(client_start, extra_client); -- int append = std::min(int(z_map.size() - (client_start + client_size)), -- extra_client); -- start = client_start - prepend; -- client_size += extra_client; -- steps = 1 + std::min(std::min(append, prepend), -- int(z_map.size()) - (start + client_size)); -- } else { -- client_size = extra_client; -- steps = 1 + z_map.size() - extra_client; -- } -- -- gpu_pixops = INT_MAX; -- for (int i = 0; i < steps; i++) { -- uint32_t po = CalcPixOps(z_map, start + i, client_size); -- if (po < gpu_pixops) { -- gpu_pixops = po; -- client_start = start + i; -- } -- } -- } -+ if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) { -+ return HWC2::Error::BadParameter; -+ } - -- MarkValidated(z_map, client_start, client_size); -+ return HWC2::Error::BadConfig; -+} -+ -+HWC2::Error DrmHwcTwo::HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) { -+ return HWC2::Error::Unsupported; -+} - -- bool testing_needed = !(client_start == 0 && client_size == z_map.size()); -+HWC2::Error DrmHwcTwo::HwcDisplay::GetSupportedContentTypes( -+ uint32_t *outNumSupportedContentTypes, uint32_t *outSupportedContentTypes) { -+ if (outSupportedContentTypes == nullptr) -+ *outNumSupportedContentTypes = 0; - -- if (testing_needed && CreateComposition(true) != HWC2::Error::None) { -- ++total_stats_.failed_kms_validate_; -- gpu_pixops = total_pixops; -- client_size = z_map.size(); -- MarkValidated(z_map, 0, client_size); -- } -- } -+ return HWC2::Error::None; -+} - -- *num_types = client_size; -+HWC2::Error DrmHwcTwo::HwcDisplay::SetContentType(int32_t contentType) { -+ supported(__func__); -+ -+ if (contentType != HWC2_CONTENT_TYPE_NONE) -+ return HWC2::Error::Unsupported; - -- total_stats_.frames_flattened_ = compositor_.GetFlattenedFramesCount(); -- total_stats_.gpu_pixops_ += gpu_pixops; -- total_stats_.total_pixops_ += total_pixops; -+ /* TODO: Map to the DRM Connector property: -+ * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809 -+ */ - -- return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; -+ return HWC2::Error::None; - } -+#endif - - #if PLATFORM_SDK_VERSION > 28 - HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData( -@@ -993,17 +965,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData( - supported(__func__); - - drmModePropertyBlobPtr blob; -- int ret; -- uint64_t blob_id; - -- std::tie(ret, blob_id) = connector_->edid_property().value(); -- if (ret) { -+ if (connector_->GetEdidBlob(blob)) { - ALOGE("Failed to get edid property value."); - return HWC2::Error::Unsupported; - } - -- blob = drmModeGetPropertyBlob(drm_->fd(), blob_id); -- - if (outData) { - *outDataSize = std::min(*outDataSize, blob->length); - memcpy(outData, blob->data, *outDataSize); -@@ -1061,10 +1028,19 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetRenderIntents( - - HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode, - int32_t intent) { -- if (mode != HAL_COLOR_MODE_NATIVE) -+ if (intent < HAL_RENDER_INTENT_COLORIMETRIC || -+ intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE) - return HWC2::Error::BadParameter; -- if (intent != HAL_RENDER_INTENT_COLORIMETRIC) -+ -+ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG) - return HWC2::Error::BadParameter; -+ -+ if (mode != HAL_COLOR_MODE_NATIVE) -+ return HWC2::Error::Unsupported; -+ -+ if (intent != HAL_RENDER_INTENT_COLORIMETRIC) -+ return HWC2::Error::Unsupported; -+ - color_mode_ = mode; - return HWC2::Error::None; - } -@@ -1190,17 +1166,17 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { - layer->alpha = static_cast(65535.0f * alpha_ + 0.5f); - layer->SetSourceCrop(source_crop_); - layer->SetTransform(static_cast(transform_)); -+ layer->dataspace = dataspace_; - } - - void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { -- auto cb = callbacks_.find(HWC2::Callback::Hotplug); -- if (cb == callbacks_.end()) -- return; -+ const std::lock_guard lock(hotplug_callback_lock); - -- auto hotplug = reinterpret_cast(cb->second.func); -- hotplug(cb->second.data, displayid, -- (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED -- : HWC2_CONNECTION_DISCONNECTED)); -+ if (hotplug_callback_hook_ && hotplug_callback_data_) -+ hotplug_callback_hook_(hotplug_callback_data_, displayid, -+ state == DRM_MODE_CONNECTED -+ ? HWC2_CONNECTION_CONNECTED -+ : HWC2_CONNECTION_DISCONNECTED); - } - - void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { -@@ -1418,6 +1394,36 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction( - DisplayHook); - #endif /* PLATFORM_SDK_VERSION > 28 */ -+#if PLATFORM_SDK_VERSION > 29 -+ case HWC2::FunctionDescriptor::GetDisplayConnectionType: -+ return ToHook( -+ DisplayHook); -+ case HWC2::FunctionDescriptor::GetDisplayVsyncPeriod: -+ return ToHook( -+ DisplayHook); -+ case HWC2::FunctionDescriptor::SetActiveConfigWithConstraints: -+ return ToHook( -+ DisplayHook); -+ case HWC2::FunctionDescriptor::SetAutoLowLatencyMode: -+ return ToHook( -+ DisplayHook); -+ case HWC2::FunctionDescriptor::GetSupportedContentTypes: -+ return ToHook( -+ DisplayHook); -+ case HWC2::FunctionDescriptor::SetContentType: -+ return ToHook( -+ DisplayHook); -+#endif - // Layer functions - case HWC2::FunctionDescriptor::SetCursorPosition: - return ToHook( -diff --git a/include/drmhwctwo.h b/DrmHwcTwo.h -similarity index 83% -rename from include/drmhwctwo.h -rename to DrmHwcTwo.h -index 1f226bc..7a08d64 100644 ---- a/include/drmhwctwo.h -+++ b/DrmHwcTwo.h -@@ -14,20 +14,26 @@ - * limitations under the License. - */ - --#include "drmdisplaycompositor.h" --#include "drmhwcomposer.h" --#include "platform.h" --#include "resourcemanager.h" --#include "vsyncworker.h" -+#ifndef ANDROID_DRM_HWC_TWO_H_ -+#define ANDROID_DRM_HWC_TWO_H_ - - #include -- - #include -+ - #include - #include - -+#include "compositor/DrmDisplayCompositor.h" -+#include "compositor/Planner.h" -+#include "drm/DrmGenericImporter.h" -+#include "drm/ResourceManager.h" -+#include "drm/VSyncWorker.h" -+#include "drmhwcomposer.h" -+ - namespace android { - -+class Backend; -+ - class DrmHwcTwo : public hwc2_device_t { - public: - static int HookDevOpen(const struct hw_module_t *module, const char *name, -@@ -37,7 +43,17 @@ class DrmHwcTwo : public hwc2_device_t { - - HWC2::Error Init(); - -- private: -+ hwc2_callback_data_t hotplug_callback_data_ = NULL; -+ HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL; -+ std::mutex hotplug_callback_lock; -+ -+ void SetHotplugCallback(hwc2_callback_data_t data, -+ hwc2_function_pointer_t hook) { -+ const std::lock_guard lock(hotplug_callback_lock); -+ hotplug_callback_data_ = data; -+ hotplug_callback_hook_ = reinterpret_cast(hook); -+ } -+ - class HwcLayer { - public: - HWC2::Composition sf_type() const { -@@ -145,14 +161,6 @@ class DrmHwcTwo : public hwc2_device_t { - android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN; - }; - -- struct HwcCallback { -- HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f) -- : data(d), func(f) { -- } -- hwc2_callback_data_t data; -- hwc2_function_pointer_t func; -- }; -- - class HwcDisplay { - public: - HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm, -@@ -161,10 +169,16 @@ class DrmHwcTwo : public hwc2_device_t { - HwcDisplay(const HwcDisplay &) = delete; - HWC2::Error Init(std::vector *planes); - -- HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, -- hwc2_function_pointer_t func); -+ void RegisterVsyncCallback(hwc2_callback_data_t data, -+ hwc2_function_pointer_t func); - void RegisterRefreshCallback(hwc2_callback_data_t data, - hwc2_function_pointer_t func); -+ HWC2::Error CreateComposition(bool test); -+ bool HardwareSupportsLayerType(HWC2::Composition comp_type); -+ uint32_t CalcPixOps(std::map &z_map, -+ size_t first_z, size_t size); -+ void MarkValidated(std::map &z_map, -+ size_t client_first_z, size_t client_size); - - void ClearDisplay(); - -@@ -204,6 +218,21 @@ class DrmHwcTwo : public hwc2_device_t { - HWC2::Error GetDisplayBrightnessSupport(bool *supported); - HWC2::Error SetDisplayBrightness(float); - #endif -+#if PLATFORM_SDK_VERSION > 29 -+ HWC2::Error GetDisplayConnectionType(uint32_t *outType); -+ HWC2::Error GetDisplayVsyncPeriod(hwc2_vsync_period_t *outVsyncPeriod); -+ -+ HWC2::Error SetActiveConfigWithConstraints( -+ hwc2_config_t config, -+ hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, -+ hwc_vsync_period_change_timeline_t *outTimeline); -+ HWC2::Error SetAutoLowLatencyMode(bool on); -+ HWC2::Error GetSupportedContentTypes(uint32_t *outNumSupportedContentTypes, -+ uint32_t *outSupportedContentTypes); -+ -+ HWC2::Error SetContentType(int32_t contentType); -+#endif -+ - HWC2::Error GetDozeSupport(int32_t *support); - HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types, - float *max_luminance, -@@ -229,14 +258,74 @@ class DrmHwcTwo : public hwc2_device_t { - return &it->second; - } - -+ /* Statistics */ -+ struct Stats { -+ Stats minus(Stats b) { -+ return {total_frames_ - b.total_frames_, -+ total_pixops_ - b.total_pixops_, -+ gpu_pixops_ - b.gpu_pixops_, -+ failed_kms_validate_ - b.failed_kms_validate_, -+ failed_kms_present_ - b.failed_kms_present_, -+ frames_flattened_ - b.frames_flattened_}; -+ } -+ -+ uint32_t total_frames_ = 0; -+ uint64_t total_pixops_ = 0; -+ uint64_t gpu_pixops_ = 0; -+ uint32_t failed_kms_validate_ = 0; -+ uint32_t failed_kms_present_ = 0; -+ uint32_t frames_flattened_ = 0; -+ }; -+ -+ const Backend *backend() const { -+ return backend_.get(); -+ } -+ void set_backend(std::unique_ptr backend) { -+ backend_ = std::move(backend); -+ } -+ -+ const std::vector &primary_planes() const { -+ return primary_planes_; -+ } -+ -+ const std::vector &overlay_planes() const { -+ return overlay_planes_; -+ } -+ -+ std::map &layers() { -+ return layers_; -+ } -+ -+ const DrmDisplayCompositor &compositor() const { -+ return compositor_; -+ } -+ -+ const DrmDevice *drm() const { -+ return drm_; -+ } -+ -+ const DrmConnector *connector() const { -+ return connector_; -+ } -+ -+ const std::shared_ptr &importer() const { -+ return importer_; -+ } -+ -+ ResourceManager *resource_manager() const { -+ return resource_manager_; -+ } -+ -+ android_color_transform_t &color_transform_hint() { -+ return color_transform_hint_; -+ } -+ -+ Stats &total_stats() { -+ return total_stats_; -+ } -+ - private: -- HWC2::Error CreateComposition(bool test); - void AddFenceToPresentFence(int fd); -- bool HardwareSupportsLayerType(HWC2::Composition comp_type); -- uint32_t CalcPixOps(std::map &z_map, -- size_t first_z, size_t size); -- void MarkValidated(std::map &z_map, -- size_t client_first_z, size_t client_size); - - constexpr static size_t MATRIX_SIZE = 16; - -@@ -249,6 +338,8 @@ class DrmHwcTwo : public hwc2_device_t { - std::vector primary_planes_; - std::vector overlay_planes_; - -+ std::unique_ptr backend_; -+ - VSyncWorker vsync_worker_; - DrmConnector *connector_ = NULL; - DrmCrtc *crtc_ = NULL; -@@ -263,24 +354,8 @@ class DrmHwcTwo : public hwc2_device_t { - android_color_transform_t color_transform_hint_; - - uint32_t frame_no_ = 0; -- /* Statistics */ -- struct Stats { -- Stats minus(Stats b) { -- return {total_frames_ - b.total_frames_, -- total_pixops_ - b.total_pixops_, -- gpu_pixops_ - b.gpu_pixops_, -- failed_kms_validate_ - b.failed_kms_validate_, -- failed_kms_present_ - b.failed_kms_present_, -- frames_flattened_ - b.frames_flattened_}; -- } -- -- uint32_t total_frames_ = 0; -- uint64_t total_pixops_ = 0; -- uint64_t gpu_pixops_ = 0; -- uint32_t failed_kms_validate_ = 0; -- uint32_t failed_kms_present_ = 0; -- uint32_t frames_flattened_ = 0; -- } total_stats_, prev_stats_; -+ Stats total_stats_; -+ Stats prev_stats_; - std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta); - }; - -@@ -296,6 +371,7 @@ class DrmHwcTwo : public hwc2_device_t { - DrmDevice *drm_; - }; - -+ private: - static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { - return static_cast(dev); - } -@@ -365,8 +441,9 @@ class DrmHwcTwo : public hwc2_device_t { - - ResourceManager resource_manager_; - std::map displays_; -- std::map callbacks_; - - std::string mDumpString; - }; - } // namespace android -+ -+#endif -diff --git a/METADATA b/METADATA -deleted file mode 100644 -index d97975c..0000000 ---- a/METADATA -+++ /dev/null -@@ -1,3 +0,0 @@ --third_party { -- license_type: NOTICE --} -diff --git a/OWNERS b/OWNERS -deleted file mode 100644 -index 75e29ae..0000000 ---- a/OWNERS -+++ /dev/null -@@ -1,5 +0,0 @@ --adelva@google.com --john.stultz@linaro.org --marcheu@google.com --seanpaul@google.com --zachr@google.com -diff --git a/backend/Backend.cpp b/backend/Backend.cpp -new file mode 100644 -index 0000000..887eb0e ---- /dev/null -+++ b/backend/Backend.cpp -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2020 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. -+ */ -+ -+#include "Backend.h" -+ -+#include "BackendManager.h" -+#include "bufferinfo/BufferInfoGetter.h" -+ -+namespace android { -+ -+HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, -+ uint32_t *num_types, -+ uint32_t *num_requests) { -+ *num_types = 0; -+ *num_requests = 0; -+ size_t avail_planes = display->primary_planes().size() + -+ display->overlay_planes().size(); -+ -+ /* -+ * If more layers then planes, save one plane -+ * for client composited layers -+ */ -+ if (avail_planes < display->layers().size()) -+ avail_planes--; -+ -+ std::map z_map, z_map_tmp; -+ uint32_t z_index = 0; -+ // First create a map of layers and z_order values -+ for (std::pair &l : -+ display->layers()) -+ z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second)); -+ // normalise the map so that the lowest z_order layer has key 0 -+ for (std::pair &l : z_map_tmp) -+ z_map.emplace(std::make_pair(z_index++, l.second)); -+ -+ uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size()); -+ uint32_t gpu_pixops = 0; -+ -+ int client_start = -1, client_size = 0; -+ -+ if (display->compositor().ShouldFlattenOnClient()) { -+ client_start = 0; -+ client_size = z_map.size(); -+ display->MarkValidated(z_map, client_start, client_size); -+ } else { -+ std::tie(client_start, client_size) = GetClientLayers(display, z_map); -+ -+ int extra_client = (z_map.size() - client_size) - avail_planes; -+ if (extra_client > 0) { -+ int start = 0, steps; -+ if (client_size != 0) { -+ int prepend = std::min(client_start, extra_client); -+ int append = std::min(int(z_map.size() - (client_start + client_size)), -+ extra_client); -+ start = client_start - prepend; -+ client_size += extra_client; -+ steps = 1 + std::min(std::min(append, prepend), -+ int(z_map.size()) - (start + client_size)); -+ } else { -+ client_size = extra_client; -+ steps = 1 + z_map.size() - extra_client; -+ } -+ -+ gpu_pixops = INT_MAX; -+ for (int i = 0; i < steps; i++) { -+ uint32_t po = display->CalcPixOps(z_map, start + i, client_size); -+ if (po < gpu_pixops) { -+ gpu_pixops = po; -+ client_start = start + i; -+ } -+ } -+ } -+ -+ display->MarkValidated(z_map, client_start, client_size); -+ -+ bool testing_needed = !(client_start == 0 && client_size == z_map.size()); -+ -+ if (testing_needed && -+ display->CreateComposition(true) != HWC2::Error::None) { -+ ++display->total_stats().failed_kms_validate_; -+ gpu_pixops = total_pixops; -+ client_size = z_map.size(); -+ display->MarkValidated(z_map, 0, client_size); -+ } -+ } -+ -+ *num_types = client_size; -+ -+ display->total_stats().frames_flattened_ = display->compositor() -+ .GetFlattenedFramesCount(); -+ display->total_stats().gpu_pixops_ += gpu_pixops; -+ display->total_stats().total_pixops_ += total_pixops; -+ -+ return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None; -+} -+ -+std::tuple Backend::GetClientLayers( -+ DrmHwcTwo::HwcDisplay *display, -+ const std::map &z_map) { -+ int client_start = -1, client_size = 0; -+ -+ for (auto & [ z_order, layer ] : z_map) { -+ if (IsClientLayer(display, layer)) { -+ if (client_start < 0) -+ client_start = z_order; -+ client_size = (z_order - client_start) + 1; -+ } -+ } -+ -+ return std::make_tuple(client_start, client_size); -+} -+ -+bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display, -+ DrmHwcTwo::HwcLayer *layer) { -+ return !display->HardwareSupportsLayerType(layer->sf_type()) || -+ !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) || -+ display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || -+ (layer->RequireScalingOrPhasing() && -+ display->resource_manager()->ForcedScalingWithGpu()); -+} -+ -+REGISTER_BACKEND("generic", Backend); -+ -+} // namespace android -diff --git a/backend/Backend.h b/backend/Backend.h -new file mode 100644 -index 0000000..898fece ---- /dev/null -+++ b/backend/Backend.h -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (C) 2020 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_BACKEND_H -+#define ANDROID_BACKEND_H -+ -+#include "DrmHwcTwo.h" -+ -+namespace android { -+ -+class Backend { -+ public: -+ virtual ~Backend() = default; -+ virtual HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, -+ uint32_t *num_types, -+ uint32_t *num_requests); -+ virtual std::tuple GetClientLayers( -+ DrmHwcTwo::HwcDisplay *display, -+ const std::map &z_map); -+ virtual bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, -+ DrmHwcTwo::HwcLayer *layer); -+}; -+} // namespace android -+ -+#endif -diff --git a/backend/BackendClient.cpp b/backend/BackendClient.cpp -new file mode 100644 -index 0000000..033a35c ---- /dev/null -+++ b/backend/BackendClient.cpp -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (C) 2020 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. -+ */ -+ -+#include "BackendClient.h" -+ -+#include "BackendManager.h" -+ -+namespace android { -+ -+HWC2::Error BackendClient::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, -+ uint32_t *num_types, -+ uint32_t * /*num_requests*/) { -+ for (auto & [ layer_handle, layer ] : display->layers()) { -+ layer.set_validated_type(HWC2::Composition::Client); -+ ++*num_types; -+ } -+ return HWC2::Error::HasChanges; -+} -+ -+REGISTER_BACKEND("client", BackendClient); -+ -+} // namespace android -diff --git a/backend/BackendClient.h b/backend/BackendClient.h -new file mode 100644 -index 0000000..13543f1 ---- /dev/null -+++ b/backend/BackendClient.h -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2020 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_BACKEND_CLIENT_H -+#define ANDROID_BACKEND_CLIENT_H -+ -+#include "Backend.h" -+ -+namespace android { -+ -+class BackendClient : public Backend { -+ public: -+ HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, -+ uint32_t *num_types, -+ uint32_t *num_requests) override; -+}; -+} // namespace android -+ -+#endif -diff --git a/backend/BackendManager.cpp b/backend/BackendManager.cpp -new file mode 100644 -index 0000000..0bacdcd ---- /dev/null -+++ b/backend/BackendManager.cpp -@@ -0,0 +1,79 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-backend" -+ -+#include "BackendManager.h" -+ -+#include -+#include -+ -+namespace android { -+ -+const std::vector BackendManager::client_devices_ = { -+ "kirin", -+ "mediatek-drm", -+}; -+ -+BackendManager &BackendManager::GetInstance() { -+ static BackendManager backend_manager; -+ -+ return backend_manager; -+} -+ -+int BackendManager::RegisterBackend(const std::string &name, -+ backend_constructor_t backend_constructor) { -+ available_backends_[name] = std::move(backend_constructor); -+ return 0; -+} -+ -+int BackendManager::SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display) { -+ std::string driver_name(display->drm()->GetName()); -+ char backend_override[PROPERTY_VALUE_MAX]; -+ property_get("vendor.hwc.backend_override", backend_override, -+ driver_name.c_str()); -+ std::string backend_name(std::move(backend_override)); -+ -+ display->set_backend(GetBackendByName(backend_name)); -+ if (!display->backend()) { -+ ALOGE("Failed to set backend '%s' for '%s' and driver '%s'", -+ backend_name.c_str(), display->connector()->name().c_str(), -+ driver_name.c_str()); -+ return -EINVAL; -+ } -+ -+ ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set", -+ backend_name.c_str(), display->connector()->name().c_str(), -+ driver_name.c_str()); -+ -+ return 0; -+} -+ -+std::unique_ptr BackendManager::GetBackendByName(std::string &name) { -+ if (!available_backends_.size()) { -+ ALOGE("No backends are specified"); -+ return nullptr; -+ } -+ -+ auto it = available_backends_.find(name); -+ if (it == available_backends_.end()) { -+ auto it = std::find(client_devices_.begin(), client_devices_.end(), name); -+ name = it == client_devices_.end() ? "generic" : "client"; -+ } -+ -+ return available_backends_[name](); -+} -+} // namespace android -diff --git a/backend/BackendManager.h b/backend/BackendManager.h -new file mode 100644 -index 0000000..e86c098 ---- /dev/null -+++ b/backend/BackendManager.h -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2020 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_BACKEND_MANAGER_H -+#define ANDROID_BACKEND_MANAGER_H -+ -+#include -+#include -+#include -+#include -+ -+#include "Backend.h" -+ -+#define REGISTER_BACKEND(name_str_, backend_) \ -+ static int \ -+ backend = BackendManager::GetInstance() \ -+ .RegisterBackend(name_str_, \ -+ []() -> std::unique_ptr { \ -+ return std::make_unique(); \ -+ }); -+ -+namespace android { -+ -+class BackendManager { -+ public: -+ using backend_constructor_t = std::function()>; -+ static BackendManager &GetInstance(); -+ int RegisterBackend(const std::string &name, -+ backend_constructor_t backend_constructor); -+ int SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display); -+ std::unique_ptr GetBackendByName(std::string &name); -+ HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display, -+ uint32_t *num_types, uint32_t *num_requests); -+ -+ private: -+ BackendManager() = default; -+ -+ static const std::vector client_devices_; -+ -+ std::map available_backends_; -+}; -+} // namespace android -+ -+#endif -diff --git a/backend/BackendRCarDu.cpp b/backend/BackendRCarDu.cpp -new file mode 100644 -index 0000000..e85fa71 ---- /dev/null -+++ b/backend/BackendRCarDu.cpp -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2020 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. -+ */ -+ -+#include "BackendRCarDu.h" -+ -+#include "BackendManager.h" -+#include "bufferinfo/BufferInfoGetter.h" -+#include "drm_fourcc.h" -+ -+namespace android { -+ -+bool BackendRCarDu::IsClientLayer(DrmHwcTwo::HwcDisplay *display, -+ DrmHwcTwo::HwcLayer *layer) { -+ hwc_drm_bo_t bo; -+ -+ int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(layer->buffer(), -+ &bo); -+ if (ret) -+ return true; -+ -+ if (bo.format == DRM_FORMAT_ABGR8888) -+ return true; -+ -+ if (layer->RequireScalingOrPhasing()) -+ return true; -+ -+ return Backend::IsClientLayer(display, layer); -+} -+ -+REGISTER_BACKEND("rcar-du", BackendRCarDu); -+ -+} // namespace android -\ No newline at end of file -diff --git a/backend/BackendRCarDu.h b/backend/BackendRCarDu.h -new file mode 100644 -index 0000000..8a1011a ---- /dev/null -+++ b/backend/BackendRCarDu.h -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2020 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 HWC_DISPLAY_BACKEND_RCAR_DU_H -+#define HWC_DISPLAY_BACKEND_RCAR_DU_H -+ -+#include "Backend.h" -+ -+namespace android { -+ -+class BackendRCarDu : public Backend { -+ public: -+ bool IsClientLayer(DrmHwcTwo::HwcDisplay *display, -+ DrmHwcTwo::HwcLayer *layer) override; -+}; -+} // namespace android -+ -+#endif -diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp -new file mode 100644 -index 0000000..afdc50e ---- /dev/null -+++ b/bufferinfo/BufferInfoGetter.cpp -@@ -0,0 +1,118 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-buffer-info-getter" -+ -+#include "BufferInfoGetter.h" -+ -+#if PLATFORM_SDK_VERSION >= 30 -+#include "BufferInfoMapperMetadata.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+namespace android { -+ -+BufferInfoGetter *BufferInfoGetter::GetInstance() { -+ static std::unique_ptr inst; -+ if (inst == nullptr) { -+#if PLATFORM_SDK_VERSION >= 30 -+ inst.reset(BufferInfoMapperMetadata::CreateInstance()); -+ if (inst == nullptr) { -+ ALOGW( -+ "Generic buffer getter is not available. Falling back to legacy..."); -+#endif -+ inst.reset(LegacyBufferInfoGetter::CreateInstance()); -+#if PLATFORM_SDK_VERSION >= 30 -+ } -+#endif -+ } -+ -+ 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; -+ -+ if (bo.prime_fds[0] == 0) -+ return false; -+ -+ return true; -+} -+ -+int LegacyBufferInfoGetter::Init() { -+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, -+ (const hw_module_t **)&gralloc_); -+ if (ret) { -+ ALOGE("Failed to open gralloc module"); -+ return ret; -+ } -+ -+ ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, -+ gralloc_->common.author); -+ -+ return 0; -+} -+ -+uint32_t LegacyBufferInfoGetter::ConvertHalFormatToDrm(uint32_t hal_format) { -+ switch (hal_format) { -+ case HAL_PIXEL_FORMAT_RGB_888: -+ return DRM_FORMAT_BGR888; -+ case HAL_PIXEL_FORMAT_BGRA_8888: -+ return DRM_FORMAT_ARGB8888; -+ case HAL_PIXEL_FORMAT_RGBX_8888: -+ return DRM_FORMAT_XBGR8888; -+ case HAL_PIXEL_FORMAT_RGBA_8888: -+ return DRM_FORMAT_ABGR8888; -+ case HAL_PIXEL_FORMAT_RGB_565: -+ return DRM_FORMAT_BGR565; -+ case HAL_PIXEL_FORMAT_YV12: -+ return DRM_FORMAT_YVU420; -+ default: -+ ALOGE("Cannot convert hal format to drm format %u", hal_format); -+ return DRM_FORMAT_INVALID; -+ } -+} -+ -+bool BufferInfoGetter::IsDrmFormatRgb(uint32_t drm_format) { -+ switch (drm_format) { -+ case DRM_FORMAT_ARGB8888: -+ case DRM_FORMAT_XBGR8888: -+ case DRM_FORMAT_ABGR8888: -+ case DRM_FORMAT_BGR888: -+ case DRM_FORMAT_BGR565: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+__attribute__((weak)) LegacyBufferInfoGetter * -+LegacyBufferInfoGetter::CreateInstance() { -+ ALOGE("No legacy buffer info getters available"); -+ return nullptr; -+} -+ -+} // namespace android -diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h -new file mode 100644 -index 0000000..fad3d16 ---- /dev/null -+++ b/bufferinfo/BufferInfoGetter.h -@@ -0,0 +1,76 @@ -+/* -+ * Copyright (C) 2020 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_BUFFERINFOGETTER_H_ -+#define ANDROID_BUFFERINFOGETTER_H_ -+ -+#include -+#include -+ -+#include "drm/DrmDevice.h" -+#include "drmhwcgralloc.h" -+ -+#ifndef DRM_FORMAT_INVALID -+#define DRM_FORMAT_INVALID 0 -+#endif -+ -+namespace android { -+ -+class BufferInfoGetter { -+ public: -+ virtual ~BufferInfoGetter() { -+ } -+ -+ virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; -+ -+ bool IsHandleUsable(buffer_handle_t handle); -+ -+ static BufferInfoGetter *GetInstance(); -+ -+ static bool IsDrmFormatRgb(uint32_t drm_format); -+}; -+ -+class LegacyBufferInfoGetter : public BufferInfoGetter { -+ public: -+ using BufferInfoGetter::BufferInfoGetter; -+ -+ int Init(); -+ -+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override = 0; -+ -+ static LegacyBufferInfoGetter *CreateInstance(); -+ -+ static uint32_t ConvertHalFormatToDrm(uint32_t hal_format); -+ const gralloc_module_t *gralloc_; -+}; -+ -+#define LEGACY_BUFFER_INFO_GETTER(getter_) \ -+ LegacyBufferInfoGetter *LegacyBufferInfoGetter::CreateInstance() { \ -+ auto *instance = new getter_(); \ -+ if (!instance) \ -+ return NULL; \ -+ \ -+ int ret = instance->Init(); \ -+ if (ret) { \ -+ ALOGE("Failed to initialize the " #getter_ " getter %d", ret); \ -+ delete instance; \ -+ return NULL; \ -+ } \ -+ return instance; \ -+ } -+ -+} // namespace android -+#endif -diff --git a/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp -new file mode 100644 -index 0000000..7d64ce8 ---- /dev/null -+++ b/bufferinfo/BufferInfoMapperMetadata.cpp -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (C) 2020 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. -+ */ -+ -+#if PLATFORM_SDK_VERSION >= 30 -+ -+#define LOG_TAG "hwc-bufferinfo-mappermetadata" -+ -+#include "BufferInfoMapperMetadata.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+using android::hardware::graphics::common::V1_1::BufferUsage; -+ -+namespace android { -+ -+BufferInfoGetter *BufferInfoMapperMetadata::CreateInstance() { -+ if (GraphicBufferMapper::getInstance().getMapperVersion() < -+ GraphicBufferMapper::GRALLOC_4) -+ return nullptr; -+ -+ return new BufferInfoMapperMetadata(); -+} -+ -+/* The implementation below makes assumptions on the order and number of file -+ * descriptors that Gralloc places in the native_handle_t and as such it very -+ * likely needs to be adapted to match the particular Gralloc implementation -+ * used in the system. For this reason it is been declared as a weak symbol, -+ * so that it can be overridden. -+ */ -+int __attribute__((weak)) -+BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) { -+ int num_fds = handle->numFds; -+ -+ if (num_fds >= 1 && num_fds <= 2) { -+ if (IsDrmFormatRgb(bo->format)) { -+ bo->prime_fds[0] = handle->data[0]; -+ } else { -+ bo->prime_fds[0] = bo->prime_fds[1] = bo->prime_fds[2] = handle->data[0]; -+ } -+ if (bo->prime_fds[0] <= 0) { -+ ALOGE("Encountered invalid fd %d", bo->prime_fds[0]); -+ return android::BAD_VALUE; -+ } -+ -+ } else if (num_fds >= 3) { -+ bo->prime_fds[0] = handle->data[0]; -+ bo->prime_fds[1] = handle->data[1]; -+ bo->prime_fds[2] = handle->data[2]; -+ for (int i = 0; i < 3; i++) { -+ if (bo->prime_fds[i] <= 0) { -+ ALOGE("Encountered invalid fd %d", bo->prime_fds[i]); -+ return android::BAD_VALUE; -+ } -+ } -+ } -+ return 0; -+} -+ -+int BufferInfoMapperMetadata::ConvertBoInfo(buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { -+ GraphicBufferMapper &mapper = GraphicBufferMapper::getInstance(); -+ if (!handle) -+ return -EINVAL; -+ -+ uint64_t usage = 0; -+ int err = mapper.getUsage(handle, &usage); -+ if (err) { -+ ALOGE("Failed to get usage err=%d", err); -+ return err; -+ } -+ bo->usage = static_cast(usage); -+ -+ ui::PixelFormat hal_format; -+ err = mapper.getPixelFormatRequested(handle, &hal_format); -+ if (err) { -+ ALOGE("Failed to get HAL Pixel Format err=%d", err); -+ return err; -+ } -+ bo->hal_format = static_cast(hal_format); -+ -+ err = mapper.getPixelFormatFourCC(handle, &bo->format); -+ if (err) { -+ ALOGE("Failed to get FourCC format err=%d", err); -+ return err; -+ } -+ -+ err = mapper.getPixelFormatModifier(handle, &bo->modifiers[0]); -+ if (err) { -+ ALOGE("Failed to get DRM Modifier err=%d", err); -+ return err; -+ } -+ -+ uint64_t width = 0; -+ err = mapper.getWidth(handle, &width); -+ if (err) { -+ ALOGE("Failed to get Width err=%d", err); -+ return err; -+ } -+ bo->width = static_cast(width); -+ -+ uint64_t height = 0; -+ err = mapper.getHeight(handle, &height); -+ if (err) { -+ ALOGE("Failed to get Height err=%d", err); -+ return err; -+ } -+ bo->height = static_cast(height); -+ -+ std::vector layouts; -+ err = mapper.getPlaneLayouts(handle, &layouts); -+ if (err) { -+ ALOGE("Failed to get Plane Layouts err=%d", err); -+ return err; -+ } -+ -+ 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; -+ } -+ -+ return GetFds(handle, bo); -+} -+ -+} // namespace android -+ -+#endif -diff --git a/bufferinfo/BufferInfoMapperMetadata.h b/bufferinfo/BufferInfoMapperMetadata.h -new file mode 100644 -index 0000000..d335705 ---- /dev/null -+++ b/bufferinfo/BufferInfoMapperMetadata.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2020 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 PLATFORMIMAGINATION_H -+#define PLATFORMIMAGINATION_H -+ -+#include "bufferinfo/BufferInfoGetter.h" -+ -+namespace android { -+ -+class BufferInfoMapperMetadata : public BufferInfoGetter { -+ public: -+ using BufferInfoGetter::BufferInfoGetter; -+ -+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -+ -+ int GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo); -+ -+ static BufferInfoGetter *CreateInstance(); -+}; -+} // namespace android -+ -+#endif // PLATFORMIMAGINATION_H -diff --git a/platform/platformimagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp -similarity index 53% -rename from platform/platformimagination.cpp -rename to bufferinfo/legacy/BufferInfoImagination.cpp -index bd4a4c3..84c177e 100644 ---- a/platform/platformimagination.cpp -+++ b/bufferinfo/legacy/BufferInfoImagination.cpp -@@ -1,6 +1,23 @@ --#define LOG_TAG "hwc-platform-imagination" -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-imagination" -+ -+#include "BufferInfoImagination.h" - --#include "platformimagination.h" - #include - #include - -@@ -8,22 +25,10 @@ - - namespace android { - --Importer *Importer::CreateInstance(DrmDevice *drm) { -- ImaginationImporter *importer = new ImaginationImporter(drm); -- if (!importer) -- return NULL; -- -- int ret = importer->Init(); -- if (ret) { -- ALOGE("Failed to initialize the Imagination importer %d", ret); -- delete importer; -- return NULL; -- } -- return importer; --} -+LEGACY_BUFFER_INFO_GETTER(BufferInfoImagination); - --int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, -- hwc_drm_bo_t *bo) { -+int BufferInfoImagination::ConvertBoInfo(buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { - IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle; - if (!hnd) - return -EINVAL; -@@ -40,7 +45,6 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, - bo->prime_fds[0] = hnd->fd[0]; - bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3; - bo->hal_format = hnd->iFormat; -- bo->pixel_stride = hnd->aiStride[0]; - - switch (hnd->iFormat) { - #ifdef HAL_PIXEL_FORMAT_BGRX_8888 -@@ -59,9 +63,4 @@ int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle, - return 0; - } - --std::unique_ptr Planner::CreateInstance(DrmDevice *) { -- std::unique_ptr planner(new Planner); -- planner->AddStage(); -- return planner; --} - } // namespace android -diff --git a/bufferinfo/legacy/BufferInfoImagination.h b/bufferinfo/legacy/BufferInfoImagination.h -new file mode 100644 -index 0000000..765b279 ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoImagination.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2020 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 BUFFERINFOIMAGINATION_H -+#define BUFFERINFOIMAGINATION_H -+ -+#include -+ -+#include "bufferinfo/BufferInfoGetter.h" -+ -+namespace android { -+ -+class BufferInfoImagination : public LegacyBufferInfoGetter { -+ public: -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; -+ -+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -+}; -+} // namespace android -+ -+#endif // PLATFORMIMAGINATION_H -diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp -new file mode 100644 -index 0000000..c794810 ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp -@@ -0,0 +1,204 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-libdrm" -+ -+#include "BufferInfoLibdrm.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+namespace android { -+ -+LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm); -+ -+enum chroma_order { -+ YCbCr, -+ YCrCb, -+}; -+ -+struct droid_yuv_format { -+ /* Lookup keys */ -+ int native; /* HAL_PIXEL_FORMAT_ */ -+ enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */ -+ int chroma_step; /* Distance in bytes between subsequent chroma pixels. */ -+ -+ /* Result */ -+ int fourcc; /* DRM_FORMAT_ */ -+}; -+ -+/* The following table is used to look up a DRI image FourCC based -+ * on native format and information contained in android_ycbcr struct. */ -+static const struct droid_yuv_format droid_yuv_formats[] = { -+ /* Native format, YCrCb, Chroma step, DRI image FourCC */ -+ {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12}, -+ {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420}, -+ {HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420}, -+ {HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420}, -+ /* HACK: See droid_create_image_from_prime_fds() and -+ * https://issuetracker.google.com/32077885. */ -+ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12}, -+ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420}, -+ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420}, -+ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV}, -+ {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888}, -+}; -+ -+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -+ -+static int get_fourcc_yuv(int native, enum chroma_order chroma_order, -+ int chroma_step) { -+ for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) -+ if (droid_yuv_formats[i].native == native && -+ droid_yuv_formats[i].chroma_order == chroma_order && -+ droid_yuv_formats[i].chroma_step == chroma_step) -+ return droid_yuv_formats[i].fourcc; -+ -+ return -1; -+} -+ -+static bool is_yuv(int native) { -+ for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i) -+ if (droid_yuv_formats[i].native == native) -+ return true; -+ -+ return false; -+} -+ -+bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { -+ struct android_ycbcr ycbcr; -+ enum chroma_order chroma_order; -+ int ret; -+ -+ if (!gralloc_->lock_ycbcr) { -+ static std::once_flag once; -+ std::call_once(once, -+ []() { ALOGW("Gralloc does not support lock_ycbcr()"); }); -+ return false; -+ } -+ -+ memset(&ycbcr, 0, sizeof(ycbcr)); -+ ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr); -+ if (ret) { -+ ALOGW("gralloc->lock_ycbcr failed: %d", ret); -+ return false; -+ } -+ gralloc_->unlock(gralloc_, handle); -+ -+ /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags -+ * it will return the .y/.cb/.cr pointers based on a NULL pointer, -+ * so they can be interpreted as offsets. */ -+ bo->offsets[0] = (size_t)ycbcr.y; -+ /* We assume here that all the planes are located in one DMA-buf. */ -+ if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) { -+ chroma_order = YCrCb; -+ bo->offsets[1] = (size_t)ycbcr.cr; -+ bo->offsets[2] = (size_t)ycbcr.cb; -+ } else { -+ chroma_order = YCbCr; -+ bo->offsets[1] = (size_t)ycbcr.cb; -+ bo->offsets[2] = (size_t)ycbcr.cr; -+ } -+ -+ /* .ystride is the line length (in bytes) of the Y plane, -+ * .cstride is the line length (in bytes) of any of the remaining -+ * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully -+ * planar formats. */ -+ bo->pitches[0] = ycbcr.ystride; -+ bo->pitches[1] = bo->pitches[2] = ycbcr.cstride; -+ -+ /* .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); -+ if (bo->format == -1) { -+ ALOGW( -+ "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = " -+ "%d", -+ bo->hal_format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", -+ (int)ycbcr.chroma_step); -+ return false; -+ } -+ -+ /* -+ * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that -+ * the single-fd case cannot happen. So handle eithe single -+ * fd or fd-per-plane case: -+ */ -+ if (num_fds == 1) { -+ bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0]; -+ } else { -+ int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3; -+ if (num_fds != expected_planes) -+ return false; -+ } -+ -+ return true; -+} -+ -+int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { -+ gralloc_handle_t *gr_handle = gralloc_handle(handle); -+ if (!gr_handle) -+ return -EINVAL; -+ -+ bo->width = gr_handle->width; -+ bo->height = gr_handle->height; -+ bo->hal_format = gr_handle->format; -+ -+#if GRALLOC_HANDLE_VERSION < 4 -+ static std::once_flag once; -+ std::call_once(once, []() { -+ ALOGE( -+ "libdrm < v2.4.97 has broken gralloc_handle structure. Please update."); -+ }); -+#endif -+#if GRALLOC_HANDLE_VERSION == 4 -+ bo->modifiers[0] = gr_handle->modifier; -+#endif -+ -+ bo->usage = gr_handle->usage; -+ bo->prime_fds[0] = gr_handle->prime_fd; -+ -+ if (is_yuv(gr_handle->format)) { -+ if (!GetYuvPlaneInfo(handle->numFds, handle, bo)) -+ return -EINVAL; -+ } else { -+ bo->pitches[0] = gr_handle->stride; -+ bo->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) { -+ case HAL_PIXEL_FORMAT_RGB_565: -+ bo->format = DRM_FORMAT_RGB565; -+ break; -+ default: -+ bo->format = ConvertHalFormatToDrm(gr_handle->format); -+ } -+ -+ if (bo->format == DRM_FORMAT_INVALID) -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+} // namespace android -diff --git a/bufferinfo/legacy/BufferInfoLibdrm.h b/bufferinfo/legacy/BufferInfoLibdrm.h -new file mode 100644 -index 0000000..4d37d00 ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoLibdrm.h -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (C) 2020 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 BUFFERINFOLIBDRM_H_ -+#define BUFFERINFOLIBDRM_H_ -+ -+#include -+ -+#include "bufferinfo/BufferInfoGetter.h" -+ -+namespace android { -+ -+class BufferInfoLibdrm : public LegacyBufferInfoGetter { -+ public: -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; -+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -+ -+ private: -+ bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo); -+}; -+ -+} // namespace android -+ -+#endif -diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.cpp b/bufferinfo/legacy/BufferInfoMaliHisi.cpp -new file mode 100644 -index 0000000..877a83f ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoMaliHisi.cpp -@@ -0,0 +1,126 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-hisi" -+ -+#include "BufferInfoMaliHisi.h" -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "gralloc_priv.h" -+ -+#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) -+ -+namespace android { -+ -+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliHisi); -+ -+#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ -+ defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) -+uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers(uint64_t flags, -+ bool is_rgb) { -+ uint64_t features = 0UL; -+ -+ if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) -+ features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; -+ -+ if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) -+ features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); -+ -+ if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) -+ features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; -+ -+ if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) -+ features |= AFBC_FORMAT_MOD_TILED; -+ -+ if (features) { -+ if (is_rgb) -+ features |= AFBC_FORMAT_MOD_YTR; -+ -+ return DRM_FORMAT_MOD_ARM_AFBC(features); -+ } -+ -+ return 0; -+} -+#else -+uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers( -+ uint64_t /* flags */, bool /* is_rgb */) { -+ return 0; -+} -+#endif -+ -+int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { -+ bool is_rgb; -+ -+ private_handle_t const *hnd = reinterpret_cast( -+ handle); -+ if (!hnd) -+ return -EINVAL; -+ -+ if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) -+ return -EINVAL; -+ -+ uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); -+ if (fmt == DRM_FORMAT_INVALID) -+ return -EINVAL; -+ -+ 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; -+ -+ switch (fmt) { -+ case DRM_FORMAT_YVU420: { -+ int align = 128; -+ if (hnd->usage & -+ (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) -+ align = 16; -+ int adjusted_height = MALI_ALIGN(hnd->height, 2); -+ int y_size = adjusted_height * hnd->byte_stride; -+ int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); -+ 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; -+ /* U plane */ -+ bo->prime_fds[2] = hnd->share_fd; -+ bo->pitches[2] = vu_stride; -+ bo->offsets[2] = y_size + v_size; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+} // namespace android -diff --git a/platform/platformhisi.h b/bufferinfo/legacy/BufferInfoMaliHisi.h -similarity index 69% -rename from platform/platformhisi.h -rename to bufferinfo/legacy/BufferInfoMaliHisi.h -index f127bdb..698a0d3 100644 ---- a/platform/platformhisi.h -+++ b/bufferinfo/legacy/BufferInfoMaliHisi.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2015 The Android Open Source Project -+ * Copyright (C) 2020 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. -@@ -14,29 +14,23 @@ - * limitations under the License. - */ - --#ifndef ANDROID_PLATFORM_HISI_H_ --#define ANDROID_PLATFORM_HISI_H_ -- --#include "drmdevice.h" --#include "platform.h" --#include "platformdrmgeneric.h" -- --#include -+#ifndef BUFFERINFOMALIHISI_H_ -+#define BUFFERINFOMALIHISI_H_ - - #include - -+#include "bufferinfo/BufferInfoGetter.h" -+ - namespace android { - --class HisiImporter : public DrmGenericImporter { -+class BufferInfoMaliHisi : public LegacyBufferInfoGetter { - public: -- using DrmGenericImporter::DrmGenericImporter; -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; - - private: - uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb); -- -- bool IsDrmFormatRgb(uint32_t drm_format); - }; - } // namespace android - -diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp -new file mode 100644 -index 0000000..ce47343 ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-bufferinfo-mali-mediatek" -+ -+#include "BufferInfoMaliMediatek.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "gralloc_priv.h" -+ -+namespace android { -+ -+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMediatek); -+ -+int BufferInfoMaliMediatek::ConvertBoInfo(buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { -+ private_handle_t const *hnd = reinterpret_cast( -+ handle); -+ if (!hnd) -+ return -EINVAL; -+ -+ 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; -+} -+ -+} // namespace android -diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.h b/bufferinfo/legacy/BufferInfoMaliMediatek.h -new file mode 100644 -index 0000000..1204818 ---- /dev/null -+++ b/bufferinfo/legacy/BufferInfoMaliMediatek.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (C) 2020 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 BUFFERINFOMALIMTK_H_ -+#define BUFFERINFOMALIMTK_H_ -+ -+#include -+ -+#include "bufferinfo/BufferInfoGetter.h" -+ -+namespace android { -+ -+class BufferInfoMaliMediatek : public LegacyBufferInfoGetter { -+ public: -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; -+ -+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -+}; -+} // namespace android -+ -+#endif -diff --git a/platform/platformmeson.cpp b/bufferinfo/legacy/BufferInfoMaliMeson.cpp -similarity index 67% -rename from platform/platformmeson.cpp -rename to bufferinfo/legacy/BufferInfoMaliMeson.cpp -index ad3aff1..cf7a873 100644 ---- a/platform/platformmeson.cpp -+++ b/bufferinfo/legacy/BufferInfoMaliMeson.cpp -@@ -14,40 +14,26 @@ - * limitations under the License. - */ - --#define LOG_TAG "hwc-platform-meson" -+#define LOG_TAG "hwc-bufferinfo-mali-meson" - --#include "platformmeson.h" --#include "drmdevice.h" --#include "platform.h" -+#include "BufferInfoMaliMeson.h" - --#include -+#include - #include - #include -+ - #include - --#include --#include - #include "gralloc_priv.h" - - namespace android { - --Importer *Importer::CreateInstance(DrmDevice *drm) { -- MesonImporter *importer = new MesonImporter(drm); -- if (!importer) -- return NULL; -- -- int ret = importer->Init(); -- if (ret) { -- ALOGE("Failed to initialize the meson importer %d", ret); -- delete importer; -- return NULL; -- } -- return importer; --} -+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMeson); - - #if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ - defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) --uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { -+uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( -+ uint64_t flags) { - uint64_t features = 0UL; - - if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) { -@@ -69,13 +55,14 @@ uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) { - return 0; - } - #else --uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers( -+uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( - uint64_t /* flags */) { - return 0; - } - #endif - --int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { -+int BufferInfoMaliMeson::ConvertBoInfo(buffer_handle_t handle, -+ hwc_drm_bo_t *bo) { - private_handle_t const *hnd = reinterpret_cast( - handle); - if (!hnd) -@@ -88,7 +75,7 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { - if (fmt == DRM_FORMAT_INVALID) - return -EINVAL; - -- bo->modifiers[0] = MesonImporter::ConvertGrallocFormatToDrmModifiers( -+ bo->modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers( - hnd->internal_format); - - bo->width = hnd->width; -@@ -96,19 +83,11 @@ int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { - bo->hal_format = hnd->req_format; - bo->format = fmt; - bo->usage = hnd->usage; -- bo->pixel_stride = hnd->stride; - bo->prime_fds[0] = hnd->share_fd; - bo->pitches[0] = hnd->byte_stride; - bo->offsets[0] = 0; - -- bo->with_modifiers = true; -- - return 0; - } - --std::unique_ptr Planner::CreateInstance(DrmDevice *) { -- std::unique_ptr planner(new Planner); -- planner->AddStage(); -- return planner; --} - } // namespace android -diff --git a/platform/platformmeson.h b/bufferinfo/legacy/BufferInfoMaliMeson.h -similarity index 76% -rename from platform/platformmeson.h -rename to bufferinfo/legacy/BufferInfoMaliMeson.h -index f29b796..ce5d3f9 100644 ---- a/platform/platformmeson.h -+++ b/bufferinfo/legacy/BufferInfoMaliMeson.h -@@ -14,23 +14,18 @@ - * limitations under the License. - */ - --#ifndef ANDROID_PLATFORM_HISI_H_ --#define ANDROID_PLATFORM_HISI_H_ -- --#include "drmdevice.h" --#include "platform.h" --#include "platformdrmgeneric.h" -- --#include -+#ifndef BUFFERINFOMALIHISI_H_ -+#define BUFFERINFOMALIHISI_H_ - - #include - -+#include "bufferinfo/BufferInfoGetter.h" -+ - namespace android { - --class MesonImporter : public DrmGenericImporter { -+class BufferInfoMaliMeson : public LegacyBufferInfoGetter { - public: -- using DrmGenericImporter::DrmGenericImporter; -- -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; - - private: -diff --git a/platform/platformminigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp -similarity index 53% -rename from platform/platformminigbm.cpp -rename to bufferinfo/legacy/BufferInfoMinigbm.cpp -index df195d3..d5ffa1f 100644 ---- a/platform/platformminigbm.cpp -+++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp -@@ -14,38 +14,23 @@ - * limitations under the License. - */ - --#define LOG_TAG "hwc-platform-drm-minigbm" -+#define LOG_TAG "hwc-bufferinfo-minigbm" - --#include "platformminigbm.h" --#include "drmdevice.h" --#include "platform.h" -+#include "BufferInfoMinigbm.h" - -+#include - #include - #include - --#include --#include -- - #include "cros_gralloc_handle.h" - --namespace android { -+#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7') - --Importer *Importer::CreateInstance(DrmDevice *drm) { -- DrmMinigbmImporter *importer = new DrmMinigbmImporter(drm); -- if (!importer) -- return NULL; -+namespace android { - -- int ret = importer->Init(); -- if (ret) { -- ALOGE("Failed to initialize the minigbm importer %d", ret); -- delete importer; -- return NULL; -- } -- return importer; --} -+LEGACY_BUFFER_INFO_GETTER(BufferInfoMinigbm); - --int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, -- hwc_drm_bo_t *bo) { -+int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { - cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; - if (!gr_handle) - return -EINVAL; -@@ -53,20 +38,21 @@ int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle, - bo->width = gr_handle->width; - bo->height = gr_handle->height; - bo->hal_format = gr_handle->droid_format; -+ - bo->format = gr_handle->format; -+ if (bo->format == DRM_FORMAT_YVU420_ANDROID) -+ bo->format = DRM_FORMAT_YVU420; -+ - bo->usage = gr_handle->usage; -- bo->pixel_stride = gr_handle->pixel_stride; -- bo->prime_fds[0] = gr_handle->fds[0]; -- bo->pitches[0] = gr_handle->strides[0]; -- bo->offsets[0] = gr_handle->offsets[0]; - -- return 0; --} -+ for (int i = 0; i < gr_handle->num_planes; i++) { -+ bo->modifiers[i] = gr_handle->format_modifier; -+ bo->prime_fds[i] = gr_handle->fds[i]; -+ bo->pitches[i] = gr_handle->strides[i]; -+ bo->offsets[i] = gr_handle->offsets[i]; -+ } - --std::unique_ptr Planner::CreateInstance(DrmDevice *) { -- std::unique_ptr planner(new Planner); -- planner->AddStage(); -- return planner; -+ return 0; - } - - } // namespace android -diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h -similarity index 75% -rename from platform/platformminigbm.h -rename to bufferinfo/legacy/BufferInfoMinigbm.h -index 053b2aa..bff9d74 100644 ---- a/platform/platformminigbm.h -+++ b/bufferinfo/legacy/BufferInfoMinigbm.h -@@ -14,20 +14,18 @@ - * limitations under the License. - */ - --#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_ --#define ANDROID_PLATFORM_DRM_MINIGBM_H_ -- --#include "drmdevice.h" --#include "platform.h" --#include "platformdrmgeneric.h" -+#ifndef BUFFERINFOMINIGBM_H_ -+#define BUFFERINFOMINIGBM_H_ - - #include - -+#include "bufferinfo/BufferInfoGetter.h" -+ - namespace android { - --class DrmMinigbmImporter : public DrmGenericImporter { -+class BufferInfoMinigbm : public LegacyBufferInfoGetter { - public: -- using DrmGenericImporter::DrmGenericImporter; -+ using LegacyBufferInfoGetter::LegacyBufferInfoGetter; - int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; - }; - -diff --git a/compositor/drmdisplaycomposition.cpp b/compositor/DrmDisplayComposition.cpp -similarity index 98% -rename from compositor/drmdisplaycomposition.cpp -rename to compositor/DrmDisplayComposition.cpp -index b710fe1..4d2e19a 100644 ---- a/compositor/drmdisplaycomposition.cpp -+++ b/compositor/DrmDisplayComposition.cpp -@@ -16,21 +16,19 @@ - - #define LOG_TAG "hwc-drm-display-composition" - --#include "drmdisplaycomposition.h" --#include "drmcrtc.h" --#include "drmdevice.h" --#include "drmdisplaycompositor.h" --#include "drmplane.h" --#include "platform.h" -+#include "DrmDisplayComposition.h" - -+#include - #include -+#include -+#include - - #include - #include - --#include --#include --#include -+#include "DrmDisplayCompositor.h" -+#include "Planner.h" -+#include "drm/DrmDevice.h" - - namespace android { - -diff --git a/include/drmdisplaycomposition.h b/compositor/DrmDisplayComposition.h -similarity index 98% -rename from include/drmdisplaycomposition.h -rename to compositor/DrmDisplayComposition.h -index 2a5b1a4..73a9024 100644 ---- a/include/drmdisplaycomposition.h -+++ b/compositor/DrmDisplayComposition.h -@@ -17,15 +17,15 @@ - #ifndef ANDROID_DRM_DISPLAY_COMPOSITION_H_ - #define ANDROID_DRM_DISPLAY_COMPOSITION_H_ - --#include "drmcrtc.h" --#include "drmhwcomposer.h" --#include "drmplane.h" -+#include -+#include - - #include - #include - --#include --#include -+#include "drm/DrmCrtc.h" -+#include "drm/DrmPlane.h" -+#include "drmhwcomposer.h" - - namespace android { - -diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/DrmDisplayCompositor.cpp -similarity index 92% -rename from compositor/drmdisplaycompositor.cpp -rename to compositor/DrmDisplayCompositor.cpp -index 1519736..3ae42ef 100644 ---- a/compositor/drmdisplaycompositor.cpp -+++ b/compositor/DrmDisplayCompositor.cpp -@@ -17,25 +17,25 @@ - #define ATRACE_TAG ATRACE_TAG_GRAPHICS - #define LOG_TAG "hwc-drm-display-compositor" - --#include "drmdisplaycompositor.h" -+#include "DrmDisplayCompositor.h" - -+#include -+#include - #include - #include - #include -+#include - #include -+#include -+ - #include - #include - #include - --#include --#include --#include --#include -- --#include "autolock.h" --#include "drmcrtc.h" --#include "drmdevice.h" --#include "drmplane.h" -+#include "drm/DrmCrtc.h" -+#include "drm/DrmDevice.h" -+#include "drm/DrmPlane.h" -+#include "utils/autolock.h" - - static const uint32_t kWaitWritebackFence = 100; // ms - -@@ -342,6 +342,8 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, - uint64_t rotation = 0; - uint64_t alpha = 0xFFFF; - uint64_t blend; -+ uint64_t color_encoding = UINT64_MAX; -+ uint64_t color_range = UINT64_MAX; - - if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) { - if (source_layers.size() > 1) { -@@ -427,6 +429,45 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, - break; - } - } -+ -+ if (plane->color_encoding_propery().id()) { -+ switch (layer.dataspace & HAL_DATASPACE_STANDARD_MASK) { -+ case HAL_DATASPACE_STANDARD_BT709: -+ std::tie(color_encoding, -+ ret) = plane->color_encoding_propery() -+ .GetEnumValueWithName("ITU-R BT.709 YCbCr"); -+ 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: -+ std::tie(color_encoding, -+ ret) = plane->color_encoding_propery() -+ .GetEnumValueWithName("ITU-R BT.601 YCbCr"); -+ break; -+ case HAL_DATASPACE_STANDARD_BT2020: -+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE: -+ std::tie(color_encoding, -+ ret) = plane->color_encoding_propery() -+ .GetEnumValueWithName("ITU-R BT.2020 YCbCr"); -+ break; -+ } -+ } -+ -+ if (plane->color_range_property().id()) { -+ switch (layer.dataspace & HAL_DATASPACE_RANGE_MASK) { -+ case HAL_DATASPACE_RANGE_FULL: -+ std::tie(color_range, -+ ret) = plane->color_range_property() -+ .GetEnumValueWithName("YCbCr full range"); -+ break; -+ case HAL_DATASPACE_RANGE_LIMITED: -+ std::tie(color_range, -+ ret) = plane->color_range_property() -+ .GetEnumValueWithName("YCbCr limited range"); -+ break; -+ } -+ } - } - - // Disable the plane if there's no framebuffer -@@ -509,6 +550,28 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, - break; - } - } -+ -+ if (plane->color_encoding_propery().id() && color_encoding != UINT64_MAX) { -+ ret = drmModeAtomicAddProperty(pset, plane->id(), -+ plane->color_encoding_propery().id(), -+ color_encoding) < 0; -+ if (ret) { -+ ALOGE("Failed to add COLOR_ENCODING property %d to plane %d", -+ plane->color_encoding_propery().id(), plane->id()); -+ break; -+ } -+ } -+ -+ if (plane->color_range_property().id() && color_range != UINT64_MAX) { -+ ret = drmModeAtomicAddProperty(pset, plane->id(), -+ plane->color_range_property().id(), -+ color_range) < 0; -+ if (ret) { -+ ALOGE("Failed to add COLOR_RANGE property %d to plane %d", -+ plane->color_range_property().id(), plane->id()); -+ break; -+ } -+ } - } - - if (!ret) { -@@ -813,7 +876,9 @@ bool DrmDisplayCompositor::IsFlatteningNeeded() const { - } - - int DrmDisplayCompositor::FlattenOnClient() { -- if (refresh_display_cb_) { -+ const std::lock_guard lock(refresh_callback_lock); -+ -+ if (refresh_callback_hook_ && refresh_callback_data_) { - { - AutoLock lock(&lock_, __func__); - if (!IsFlatteningNeeded()) { -@@ -829,7 +894,7 @@ int DrmDisplayCompositor::FlattenOnClient() { - "No writeback connector available, " - "falling back to client composition"); - SetFlattening(FlatteningState::kClientRequested); -- refresh_display_cb_(display_); -+ refresh_callback_hook_(refresh_callback_data_, display_); - return 0; - } else { - ALOGV("No writeback connector available"); -diff --git a/include/drmdisplaycompositor.h b/compositor/DrmDisplayCompositor.h -similarity index 89% -rename from include/drmdisplaycompositor.h -rename to compositor/DrmDisplayCompositor.h -index 26e2572..ab3f867 100644 ---- a/include/drmdisplaycompositor.h -+++ b/compositor/DrmDisplayCompositor.h -@@ -17,19 +17,20 @@ - #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_ - #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_ - --#include "drmdisplaycomposition.h" --#include "drmframebuffer.h" --#include "drmhwcomposer.h" --#include "resourcemanager.h" --#include "vsyncworker.h" -- -+#include -+#include - #include -+ - #include - #include - #include - --#include --#include -+#include "DrmDisplayComposition.h" -+#include "DrmFramebuffer.h" -+#include "Planner.h" -+#include "drm/ResourceManager.h" -+#include "drm/VSyncWorker.h" -+#include "drmhwcomposer.h" - - // One for the front, one for the back, and one for cases where we need to - // squash a frame that the hw can't display with hw overlays. -@@ -59,9 +60,15 @@ class DrmDisplayCompositor { - - int Init(ResourceManager *resource_manager, int display); - -- template -- void SetRefreshCallback(Fn &&refresh_cb) { -- refresh_display_cb_ = std::forward(refresh_cb); -+ hwc2_callback_data_t refresh_callback_data_ = NULL; -+ HWC2_PFN_REFRESH refresh_callback_hook_ = NULL; -+ std::mutex refresh_callback_lock; -+ -+ void SetRefreshCallback(hwc2_callback_data_t data, -+ hwc2_function_pointer_t hook) { -+ const std::lock_guard lock(refresh_callback_lock); -+ refresh_callback_data_ = data; -+ refresh_callback_hook_ = reinterpret_cast(hook); - } - - std::unique_ptr CreateComposition() const; -diff --git a/platform/platform.cpp b/compositor/Planner.cpp -similarity index 91% -rename from platform/platform.cpp -rename to compositor/Planner.cpp -index b7a47c7..f4b5c51 100644 ---- a/platform/platform.cpp -+++ b/compositor/Planner.cpp -@@ -16,13 +16,20 @@ - - #define LOG_TAG "hwc-platform" - --#include "platform.h" --#include "drmdevice.h" -+#include "Planner.h" - - #include - -+#include "drm/DrmDevice.h" -+ - namespace android { - -+std::unique_ptr Planner::CreateInstance(DrmDevice *) { -+ std::unique_ptr planner(new Planner); -+ planner->AddStage(); -+ return planner; -+} -+ - std::vector Planner::GetUsablePlanes( - DrmCrtc *crtc, std::vector *primary_planes, - std::vector *overlay_planes) { -@@ -77,6 +84,13 @@ int Planner::PlanStage::ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer) { - ALOGE("Expected a valid blend mode on plane %d", plane->id()); - } - -+ uint32_t format = layer->buffer->format; -+ if (!plane->IsFormatSupported(format)) { -+ ALOGE("Plane %d does not supports %c%c%c%c format", plane->id(), format, -+ format >> 8, format >> 16, format >> 24); -+ return -EINVAL; -+ } -+ - return ret; - } - -diff --git a/include/platform.h b/compositor/Planner.h -similarity index 81% -rename from include/platform.h -rename to compositor/Planner.h -index 6775e29..09034ff 100644 ---- a/include/platform.h -+++ b/compositor/Planner.h -@@ -17,46 +17,19 @@ - #ifndef ANDROID_DRM_PLATFORM_H_ - #define ANDROID_DRM_PLATFORM_H_ - --#include "drmdisplaycomposition.h" --#include "drmhwcomposer.h" -- - #include - #include - - #include - #include - -+#include "compositor/DrmDisplayComposition.h" -+#include "drmhwcomposer.h" -+ - namespace android { - - class DrmDevice; - --class Importer { -- public: -- virtual ~Importer() { -- } -- -- // Creates a platform-specific importer instance -- static Importer *CreateInstance(DrmDevice *drm); -- -- // Imports the buffer referred to by handle into bo. -- // -- // Note: This can be called from a different thread than ReleaseBuffer. The -- // implementation is responsible for ensuring thread safety. -- virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; -- -- // Releases the buffer object (ie: does the inverse of ImportBuffer) -- // -- // Note: This can be called from a different thread than ImportBuffer. The -- // implementation is responsible for ensuring thread safety. -- virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; -- -- // Checks if importer can import the buffer. -- virtual bool CanImportBuffer(buffer_handle_t handle) = 0; -- -- // Convert platform-dependent buffer format to drm_hwc internal format. -- virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; --}; -- - class Planner { - public: - class PlanStage { -diff --git a/drm/drmconnector.cpp b/drm/DrmConnector.cpp -similarity index 92% -rename from drm/drmconnector.cpp -rename to drm/DrmConnector.cpp -index 81c2b98..f1b6c1b 100644 ---- a/drm/drmconnector.cpp -+++ b/drm/DrmConnector.cpp -@@ -16,17 +16,17 @@ - - #define LOG_TAG "hwc-drm-connector" - --#include "drmconnector.h" --#include "drmdevice.h" -+#include "DrmConnector.h" - - #include -+#include - #include -+#include - - #include - #include - --#include --#include -+#include "DrmDevice.h" - - namespace android { - -@@ -58,10 +58,7 @@ int DrmConnector::Init() { - ALOGE("Could not get CRTC_ID property\n"); - return ret; - } -- ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_); -- if (ret) { -- ALOGW("Could not get EDID property\n"); -- } -+ ret = UpdateEdidProperty(); - if (writeback()) { - ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS", - &writeback_pixel_formats_); -@@ -85,6 +82,30 @@ int DrmConnector::Init() { - return 0; - } - -+int DrmConnector::UpdateEdidProperty() { -+ int ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_); -+ if (ret) { -+ ALOGW("Could not get EDID property\n"); -+ } -+ return ret; -+} -+ -+int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) { -+ uint64_t blob_id; -+ int ret = UpdateEdidProperty(); -+ if (ret) { -+ return ret; -+ } -+ -+ std::tie(ret, blob_id) = edid_property().value(); -+ if (ret) { -+ return ret; -+ } -+ -+ blob = drmModeGetPropertyBlob(drm_->fd(), blob_id); -+ return !blob; -+} -+ - uint32_t DrmConnector::id() const { - return id_; - } -diff --git a/include/drmconnector.h b/drm/DrmConnector.h -similarity index 94% -rename from include/drmconnector.h -rename to drm/DrmConnector.h -index dc64b38..8533af8 100644 ---- a/include/drmconnector.h -+++ b/drm/DrmConnector.h -@@ -17,15 +17,16 @@ - #ifndef ANDROID_DRM_CONNECTOR_H_ - #define ANDROID_DRM_CONNECTOR_H_ - --#include "drmencoder.h" --#include "drmmode.h" --#include "drmproperty.h" -- - #include - #include -+ - #include - #include - -+#include "DrmEncoder.h" -+#include "DrmMode.h" -+#include "DrmProperty.h" -+ - namespace android { - - class DrmDevice; -@@ -39,6 +40,8 @@ class DrmConnector { - DrmConnector &operator=(const DrmProperty &) = delete; - - int Init(); -+ int UpdateEdidProperty(); -+ int GetEdidBlob(drmModePropertyBlobPtr &blob); - - uint32_t id() const; - -diff --git a/drm/drmcrtc.cpp b/drm/DrmCrtc.cpp -similarity index 97% -rename from drm/drmcrtc.cpp -rename to drm/DrmCrtc.cpp -index b627291..4ce8cfc 100644 ---- a/drm/drmcrtc.cpp -+++ b/drm/DrmCrtc.cpp -@@ -16,13 +16,13 @@ - - #define LOG_TAG "hwc-drm-crtc" - --#include "drmcrtc.h" --#include "drmdevice.h" -+#include "DrmCrtc.h" - -+#include - #include - #include - --#include -+#include "DrmDevice.h" - - namespace android { - -diff --git a/include/drmcrtc.h b/drm/DrmCrtc.h -similarity index 97% -rename from include/drmcrtc.h -rename to drm/DrmCrtc.h -index 3075f9b..7972bef 100644 ---- a/include/drmcrtc.h -+++ b/drm/DrmCrtc.h -@@ -17,12 +17,12 @@ - #ifndef ANDROID_DRM_CRTC_H_ - #define ANDROID_DRM_CRTC_H_ - --#include "drmmode.h" --#include "drmproperty.h" -- - #include - #include - -+#include "DrmMode.h" -+#include "DrmProperty.h" -+ - namespace android { - - class DrmDevice; -diff --git a/drm/drmdevice.cpp b/drm/DrmDevice.cpp -similarity index 96% -rename from drm/drmdevice.cpp -rename to drm/DrmDevice.cpp -index bef41d8..4e750f8 100644 ---- a/drm/drmdevice.cpp -+++ b/drm/DrmDevice.cpp -@@ -16,27 +16,22 @@ - - #define LOG_TAG "hwc-drm-device" - --#include "drmdevice.h" --#include "drmconnector.h" --#include "drmcrtc.h" --#include "drmencoder.h" --#include "drmeventlistener.h" --#include "drmplane.h" -+#include "DrmDevice.h" - -+#include - #include - #include -+#include - #include - #include - #include --#include - - #include - #include -+#include -+#include - #include - --#include --#include -- - static void trim_left(std::string &str) { - str.erase(std::begin(str), - std::find_if(std::begin(str), std::end(str), -@@ -59,7 +54,7 @@ namespace android { - - static std::vector read_primary_display_order_prop() { - std::array display_order_buf; -- property_get("hwc.drm.primary_display_order", display_order_buf.data(), -+ property_get("vendor.hwc.drm.primary_display_order", display_order_buf.data(), - "..."); - - std::vector display_order; -@@ -150,6 +145,12 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { - } - #endif - -+ drmSetMaster(fd()); -+ if (!drmIsMaster(fd())) { -+ ALOGE("DRM/KMS master access required"); -+ return std::make_tuple(-EACCES, 0); -+ } -+ - drmModeResPtr res = drmModeGetResources(fd()); - if (!res) { - ALOGE("Failed to get DrmDevice resources"); -@@ -254,7 +255,7 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { - } - - // Primary display priority: -- // 1) hwc.drm.primary_display_order property -+ // 1) vendor.hwc.drm.primary_display_order property - // 2) internal connectors - // 3) anything else - std::vector -@@ -267,8 +268,8 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { - found_primary = true; - } else { - ALOGE( -- "Failed to find primary display from \"hwc.drm.primary_display_order\" " -- "property"); -+ "Failed to find primary display from " -+ "\"vendor.hwc.drm.primary_display_order\" property"); - } - - // If no priority display were found then pick first available as primary and -@@ -570,4 +571,16 @@ int DrmDevice::GetConnectorProperty(const DrmConnector &connector, - return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name, - property); - } -+ -+const std::string DrmDevice::GetName() const { -+ auto ver = drmGetVersion(fd_.get()); -+ if (!ver) { -+ ALOGW("Failed to get drm version for fd=%d", fd_.get()); -+ return "generic"; -+ } -+ -+ std::string name(ver->name); -+ drmFreeVersion(ver); -+ return name; -+} - } // namespace android -diff --git a/include/drmdevice.h b/drm/DrmDevice.h -similarity index 94% -rename from include/drmdevice.h -rename to drm/DrmDevice.h -index 91dd38b..be68aa6 100644 ---- a/include/drmdevice.h -+++ b/drm/DrmDevice.h -@@ -17,16 +17,17 @@ - #ifndef ANDROID_DRM_H_ - #define ANDROID_DRM_H_ - --#include "drmconnector.h" --#include "drmcrtc.h" --#include "drmencoder.h" --#include "drmeventlistener.h" --#include "drmplane.h" --#include "platform.h" -- - #include -+ -+#include - #include - -+#include "DrmConnector.h" -+#include "DrmCrtc.h" -+#include "DrmEncoder.h" -+#include "DrmEventListener.h" -+#include "DrmPlane.h" -+ - namespace android { - - class DrmDevice { -@@ -70,6 +71,8 @@ class DrmDevice { - int GetConnectorProperty(const DrmConnector &connector, const char *prop_name, - DrmProperty *property); - -+ const std::string GetName() const; -+ - const std::vector> &crtcs() const; - uint32_t next_mode_id(); - -diff --git a/drm/drmencoder.cpp b/drm/DrmEncoder.cpp -similarity index 95% -rename from drm/drmencoder.cpp -rename to drm/DrmEncoder.cpp -index c36fca1..bcf0926 100644 ---- a/drm/drmencoder.cpp -+++ b/drm/DrmEncoder.cpp -@@ -14,13 +14,13 @@ - * limitations under the License. - */ - --#include "drmencoder.h" --#include "drmcrtc.h" --#include "drmdevice.h" -+#include "DrmEncoder.h" - - #include - #include - -+#include "DrmDevice.h" -+ - namespace android { - - DrmEncoder::DrmEncoder(drmModeEncoderPtr e, DrmCrtc *current_crtc, -diff --git a/include/drmencoder.h b/drm/DrmEncoder.h -similarity index 98% -rename from include/drmencoder.h -rename to drm/DrmEncoder.h -index 8a7f682..f4464d0 100644 ---- a/include/drmencoder.h -+++ b/drm/DrmEncoder.h -@@ -17,13 +17,14 @@ - #ifndef ANDROID_DRM_ENCODER_H_ - #define ANDROID_DRM_ENCODER_H_ - --#include "drmcrtc.h" -- - #include - #include -+ - #include - #include - -+#include "DrmCrtc.h" -+ - namespace android { - - class DrmEncoder { -diff --git a/drm/drmeventlistener.cpp b/drm/DrmEventListener.cpp -similarity index 98% -rename from drm/drmeventlistener.cpp -rename to drm/DrmEventListener.cpp -index ccee0d6..3d95e28 100644 ---- a/drm/drmeventlistener.cpp -+++ b/drm/DrmEventListener.cpp -@@ -16,19 +16,19 @@ - - #define LOG_TAG "hwc-drm-event-listener" - --#include "drmeventlistener.h" --#include "drmdevice.h" -+#include "DrmEventListener.h" - - #include - #include --#include --#include -- - #include - #include -+#include - #include -+#include - #include - -+#include "DrmDevice.h" -+ - namespace android { - - DrmEventListener::DrmEventListener(DrmDevice *drm) -diff --git a/include/drmeventlistener.h b/drm/DrmEventListener.h -similarity index 98% -rename from include/drmeventlistener.h -rename to drm/DrmEventListener.h -index 95672ee..9f9a4ba 100644 ---- a/include/drmeventlistener.h -+++ b/drm/DrmEventListener.h -@@ -18,7 +18,7 @@ - #define ANDROID_DRM_EVENT_LISTENER_H_ - - #include "autofd.h" --#include "worker.h" -+#include "utils/Worker.h" - - namespace android { - -diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp -new file mode 100644 -index 0000000..171d889 ---- /dev/null -+++ b/drm/DrmGenericImporter.cpp -@@ -0,0 +1,139 @@ -+/* -+ * Copyright (C) 2020 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 LOG_TAG "hwc-platform-drm-generic" -+ -+#include "DrmGenericImporter.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+namespace android { -+ -+DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) { -+ uint64_t cap_value = 0; -+ if (drmGetCap(drm_->fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) { -+ ALOGE("drmGetCap failed. Fallback to no modifier support."); -+ cap_value = 0; -+ } -+ has_modifier_support_ = cap_value; -+} -+ -+DrmGenericImporter::~DrmGenericImporter() { -+} -+ -+int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) { -+ int ret = 0; -+ -+ for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { -+ if (bo->prime_fds[i] > 0) { -+ if (i == 0 || bo->prime_fds[i] != bo->prime_fds[0]) { -+ ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[i], -+ &bo->gem_handles[i]); -+ if (ret) { -+ ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[i], ret); -+ return ret; -+ } -+ } else { -+ bo->gem_handles[i] = bo->gem_handles[0]; -+ } -+ } -+ } -+ -+ bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE && -+ bo->modifiers[0] != DRM_FORMAT_MOD_INVALID; -+ -+ if (!has_modifier_support_ && has_modifiers) { -+ ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64, -+ bo->modifiers[0]); -+ return -EINVAL; -+ } -+ -+ if (!has_modifiers) -+ ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, -+ bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, -+ 0); -+ else -+ ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, -+ bo->format, bo->gem_handles, bo->pitches, -+ bo->offsets, bo->modifiers, &bo->fb_id, -+ DRM_MODE_FB_MODIFIERS); -+ -+ if (ret) { -+ ALOGE("could not create drm fb %d", ret); -+ return ret; -+ } -+ -+ for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { -+ if (!bo->gem_handles[i]) -+ continue; -+ -+ ImportHandle(bo->gem_handles[i]); -+ } -+ -+ return ret; -+} -+ -+int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { -+ if (bo->fb_id) -+ if (drmModeRmFB(drm_->fd(), bo->fb_id)) -+ ALOGE("Failed to rm fb"); -+ -+ for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { -+ if (!bo->gem_handles[i]) -+ continue; -+ -+ if (ReleaseHandle(bo->gem_handles[i])) -+ ALOGE("Failed to release gem handle %d", bo->gem_handles[i]); -+ else -+ bo->gem_handles[i] = 0; -+ } -+ return 0; -+} -+ -+int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { -+ gem_refcount_[gem_handle]++; -+ -+ return 0; -+} -+ -+int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { -+ if (--gem_refcount_[gem_handle]) -+ return 0; -+ -+ gem_refcount_.erase(gem_handle); -+ -+ return CloseHandle(gem_handle); -+} -+ -+int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { -+ struct drm_gem_close gem_close; -+ -+ memset(&gem_close, 0, sizeof(gem_close)); -+ -+ gem_close.handle = gem_handle; -+ int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); -+ if (ret) -+ ALOGE("Failed to close gem handle %d %d", gem_handle, ret); -+ -+ return ret; -+} -+} // namespace android -diff --git a/platform/platformdrmgeneric.h b/drm/DrmGenericImporter.h -similarity index 61% -rename from platform/platformdrmgeneric.h -rename to drm/DrmGenericImporter.h -index f9d923f..ca53762 100644 ---- a/platform/platformdrmgeneric.h -+++ b/drm/DrmGenericImporter.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2015 The Android Open Source Project -+ * Copyright (C) 2020 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. -@@ -17,13 +17,13 @@ - #ifndef ANDROID_PLATFORM_DRM_GENERIC_H_ - #define ANDROID_PLATFORM_DRM_GENERIC_H_ - --#include "drmdevice.h" --#include "platform.h" -- -+#include - #include -+ - #include - --#include -+#include "drm/DrmDevice.h" -+#include "drmhwcgralloc.h" - - #ifndef DRM_FORMAT_INVALID - #define DRM_FORMAT_INVALID 0 -@@ -31,34 +31,43 @@ - - namespace android { - -+class Importer { -+ public: -+ virtual ~Importer() { -+ } -+ -+ // Imports the buffer referred to by handle into bo. -+ // -+ // Note: This can be called from a different thread than ReleaseBuffer. The -+ // implementation is responsible for ensuring thread safety. -+ virtual int ImportBuffer(hwc_drm_bo_t *bo) = 0; -+ -+ // Releases the buffer object (ie: does the inverse of ImportBuffer) -+ // -+ // Note: This can be called from a different thread than ImportBuffer. The -+ // implementation is responsible for ensuring thread safety. -+ virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; -+}; -+ - class DrmGenericImporter : public Importer { - public: - DrmGenericImporter(DrmDevice *drm); - ~DrmGenericImporter() override; - -- int Init(); -- -- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -+ int ImportBuffer(hwc_drm_bo_t *bo) override; - int ReleaseBuffer(hwc_drm_bo_t *bo) override; -- bool CanImportBuffer(buffer_handle_t handle) override; - int ImportHandle(uint32_t gem_handle); - int ReleaseHandle(uint32_t gem_handle); - -- int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; -- -- uint32_t ConvertHalFormatToDrm(uint32_t hal_format); -- uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format); -- - protected: - DrmDevice *drm_; - - private: -- const gralloc_module_t *gralloc_; -- bool exclude_non_hwfb_; -- - int CloseHandle(uint32_t gem_handle); - std::map gem_refcount_; -+ bool has_modifier_support_; - }; -+ - } // namespace android - - #endif -diff --git a/drm/drmmode.cpp b/drm/DrmMode.cpp -similarity index 96% -rename from drm/drmmode.cpp -rename to drm/DrmMode.cpp -index c3ab385..6de671a 100644 ---- a/drm/drmmode.cpp -+++ b/drm/DrmMode.cpp -@@ -14,12 +14,9 @@ - * limitations under the License. - */ - --#include "drmmode.h" --#include "drmdevice.h" -+#include "DrmMode.h" - --#include --#include --#include -+#include "DrmDevice.h" - - namespace android { - -diff --git a/include/drmmode.h b/drm/DrmMode.h -similarity index 99% -rename from include/drmmode.h -rename to drm/DrmMode.h -index 4cc06b1..313a8ea 100644 ---- a/include/drmmode.h -+++ b/drm/DrmMode.h -@@ -19,6 +19,7 @@ - - #include - #include -+ - #include - - namespace android { -diff --git a/drm/drmplane.cpp b/drm/DrmPlane.cpp -similarity index 80% -rename from drm/drmplane.cpp -rename to drm/DrmPlane.cpp -index 6f1bf9b..65bd8be 100644 ---- a/drm/drmplane.cpp -+++ b/drm/DrmPlane.cpp -@@ -16,20 +16,24 @@ - - #define LOG_TAG "hwc-drm-plane" - --#include "drmplane.h" --#include "drmdevice.h" -+#include "DrmPlane.h" -+#include "bufferinfo/BufferInfoGetter.h" - - #include -+#include - #include -+ - #include - --#include --#include -+#include "DrmDevice.h" - - namespace android { - - DrmPlane::DrmPlane(DrmDevice *drm, drmModePlanePtr p) -- : drm_(drm), id_(p->plane_id), possible_crtc_mask_(p->possible_crtcs) { -+ : drm_(drm), -+ id_(p->plane_id), -+ possible_crtc_mask_(p->possible_crtcs), -+ formats_(p->formats, p->formats + p->count_formats) { - } - - int DrmPlane::Init() { -@@ -138,6 +142,17 @@ int DrmPlane::Init() { - if (ret) - ALOGI("Could not get IN_FENCE_FD property"); - -+ if (HasNonRgbFormat()) { -+ ret = drm_->GetPlaneProperty(*this, "COLOR_ENCODING", -+ &color_encoding_propery_); -+ if (ret) -+ ALOGI("Could not get COLOR_ENCODING property"); -+ -+ ret = drm_->GetPlaneProperty(*this, "COLOR_RANGE", &color_range_property_); -+ if (ret) -+ ALOGI("Could not get COLOR_RANGE property"); -+ } -+ - return 0; - } - -@@ -153,6 +168,18 @@ uint32_t DrmPlane::type() const { - return type_; - } - -+bool DrmPlane::IsFormatSupported(uint32_t format) const { -+ return std::find(std::begin(formats_), std::end(formats_), format) != -+ std::end(formats_); -+} -+ -+bool DrmPlane::HasNonRgbFormat() const { -+ return std::find_if_not(std::begin(formats_), std::end(formats_), -+ [](uint32_t format) { -+ return BufferInfoGetter::IsDrmFormatRgb(format); -+ }) != std::end(formats_); -+} -+ - const DrmProperty &DrmPlane::crtc_property() const { - return crtc_property_; - } -@@ -212,4 +239,12 @@ const DrmProperty &DrmPlane::blend_property() const { - const DrmProperty &DrmPlane::in_fence_fd_property() const { - return in_fence_fd_property_; - } -+ -+const DrmProperty &DrmPlane::color_encoding_propery() const { -+ return color_encoding_propery_; -+} -+ -+const DrmProperty &DrmPlane::color_range_property() const { -+ return color_range_property_; -+} - } // namespace android -diff --git a/include/drmplane.h b/drm/DrmPlane.h -similarity index 87% -rename from include/drmplane.h -rename to drm/DrmPlane.h -index 43e0e8a..7a915cc 100644 ---- a/include/drmplane.h -+++ b/drm/DrmPlane.h -@@ -17,13 +17,14 @@ - #ifndef ANDROID_DRM_PLANE_H_ - #define ANDROID_DRM_PLANE_H_ - --#include "drmcrtc.h" --#include "drmproperty.h" -- - #include - #include -+ - #include - -+#include "DrmCrtc.h" -+#include "DrmProperty.h" -+ - namespace android { - - class DrmDevice; -@@ -42,6 +43,9 @@ class DrmPlane { - - uint32_t type() const; - -+ bool IsFormatSupported(uint32_t format) const; -+ bool HasNonRgbFormat() const; -+ - const DrmProperty &crtc_property() const; - const DrmProperty &fb_property() const; - const DrmProperty &crtc_x_property() const; -@@ -57,6 +61,8 @@ class DrmPlane { - const DrmProperty &alpha_property() const; - const DrmProperty &blend_property() const; - const DrmProperty &in_fence_fd_property() const; -+ const DrmProperty &color_encoding_propery() const; -+ const DrmProperty &color_range_property() const; - - private: - DrmDevice *drm_; -@@ -66,6 +72,8 @@ class DrmPlane { - - uint32_t type_; - -+ std::vector formats_; -+ - DrmProperty crtc_property_; - DrmProperty fb_property_; - DrmProperty crtc_x_property_; -@@ -81,6 +89,8 @@ class DrmPlane { - DrmProperty alpha_property_; - DrmProperty blend_property_; - DrmProperty in_fence_fd_property_; -+ DrmProperty color_encoding_propery_; -+ DrmProperty color_range_property_; - }; - } // namespace android - -diff --git a/drm/drmproperty.cpp b/drm/DrmProperty.cpp -similarity index 98% -rename from drm/drmproperty.cpp -rename to drm/DrmProperty.cpp -index 3aeed13..b60a76e 100644 ---- a/drm/drmproperty.cpp -+++ b/drm/DrmProperty.cpp -@@ -14,14 +14,15 @@ - * limitations under the License. - */ - --#include "drmproperty.h" --#include "drmdevice.h" -+#include "DrmProperty.h" - - #include - #include -+#include -+ - #include - --#include -+#include "DrmDevice.h" - - namespace android { - -diff --git a/include/drmproperty.h b/drm/DrmProperty.h -similarity index 99% -rename from include/drmproperty.h -rename to drm/DrmProperty.h -index 2d92ca1..d293da3 100644 ---- a/include/drmproperty.h -+++ b/drm/DrmProperty.h -@@ -19,6 +19,7 @@ - - #include - #include -+ - #include - #include - -diff --git a/drm/resourcemanager.cpp b/drm/ResourceManager.cpp -similarity index 75% -rename from drm/resourcemanager.cpp -rename to drm/ResourceManager.cpp -index da1a2db..fc24aea 100644 ---- a/drm/resourcemanager.cpp -+++ b/drm/ResourceManager.cpp -@@ -16,12 +16,15 @@ - - #define LOG_TAG "hwc-resource-manager" - --#include "resourcemanager.h" -+#include "ResourceManager.h" - - #include - #include -+#include -+ - #include --#include -+ -+#include "bufferinfo/BufferInfoGetter.h" - - namespace android { - -@@ -32,7 +35,8 @@ int ResourceManager::Init() { - char path_pattern[PROPERTY_VALUE_MAX]; - // Could be a valid path or it can have at the end of it the wildcard % - // which means that it will try open all devices until an error is met. -- int path_len = property_get("hwc.drm.device", path_pattern, "/dev/dri/card0"); -+ int path_len = property_get("vendor.hwc.drm.device", path_pattern, -+ "/dev/dri/card%"); - int ret = 0; - if (path_pattern[path_len - 1] != '%') { - ret = AddDrmDevice(std::string(path_pattern)); -@@ -41,7 +45,13 @@ int ResourceManager::Init() { - for (int idx = 0; !ret; ++idx) { - std::ostringstream path; - path << path_pattern << idx; -- ret = AddDrmDevice(path.str()); -+ -+ struct stat buf; -+ if (stat(path.str().c_str(), &buf)) { -+ break; -+ } else if (IsKMSDev(path.str().c_str())) { -+ ret = AddDrmDevice(path.str()); -+ } - } - } - -@@ -51,9 +61,14 @@ int ResourceManager::Init() { - } - - char scale_with_gpu[PROPERTY_VALUE_MAX]; -- property_get("hwc.drm.scale_with_gpu", scale_with_gpu, "0"); -+ property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0"); - scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1)); - -+ if (!BufferInfoGetter::GetInstance()) { -+ ALOGE("Failed to initialize BufferInfoGetter"); -+ return -EINVAL; -+ } -+ - return hw_get_module(GRALLOC_HARDWARE_MODULE_ID, - (const hw_module_t **)&gralloc_); - } -@@ -65,7 +80,7 @@ int ResourceManager::AddDrmDevice(std::string path) { - if (ret) - return ret; - std::shared_ptr importer; -- importer.reset(Importer::CreateInstance(drm.get())); -+ importer.reset(new DrmGenericImporter(drm.get())); - if (!importer) { - ALOGE("Failed to create importer instance"); - return -ENODEV; -@@ -94,6 +109,26 @@ DrmConnector *ResourceManager::AvailableWritebackConnector(int display) { - return writeback_conn; - } - -+bool ResourceManager::IsKMSDev(const char *path) { -+ int fd = open(path, O_RDWR | O_CLOEXEC); -+ if (fd < 0) -+ return false; -+ -+ auto res = drmModeGetResources(fd); -+ if (!res) { -+ close(fd); -+ return false; -+ } -+ -+ bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && -+ res->count_encoders > 0; -+ -+ drmModeFreeResources(res); -+ close(fd); -+ -+ return is_kms; -+} -+ - DrmDevice *ResourceManager::GetDrmDevice(int display) { - for (auto &drm : drms_) { - if (drm->HandlesDisplay(display)) -diff --git a/include/resourcemanager.h b/drm/ResourceManager.h -similarity index 94% -rename from include/resourcemanager.h -rename to drm/ResourceManager.h -index 7a86828..7102cea 100644 ---- a/include/resourcemanager.h -+++ b/drm/ResourceManager.h -@@ -17,11 +17,11 @@ - #ifndef RESOURCEMANAGER_H - #define RESOURCEMANAGER_H - --#include "drmdevice.h" --#include "platform.h" -- - #include - -+#include "DrmDevice.h" -+#include "DrmGenericImporter.h" -+ - namespace android { - - class ResourceManager { -@@ -46,6 +46,7 @@ class ResourceManager { - - private: - int AddDrmDevice(std::string path); -+ static bool IsKMSDev(const char *path); - - int num_displays_; - std::vector> drms_; -diff --git a/drm/vsyncworker.cpp b/drm/VSyncWorker.cpp -similarity index 75% -rename from drm/vsyncworker.cpp -rename to drm/VSyncWorker.cpp -index 08ab301..b2f7e5f 100644 ---- a/drm/vsyncworker.cpp -+++ b/drm/VSyncWorker.cpp -@@ -16,18 +16,13 @@ - - #define LOG_TAG "hwc-vsync-worker" - --#include "vsyncworker.h" --#include "drmdevice.h" --#include "worker.h" -+#include "VSyncWorker.h" - -+#include - #include - #include - #include - #include --#include -- --#include --#include - - namespace android { - -@@ -55,6 +50,14 @@ void VSyncWorker::RegisterCallback(std::shared_ptr callback) { - Unlock(); - } - -+void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data, -+ hwc2_function_pointer_t hook) { -+ Lock(); -+ vsync_callback_data_ = data; -+ vsync_callback_hook_ = reinterpret_cast(hook); -+ Unlock(); -+} -+ - void VSyncWorker::VSyncControl(bool enabled) { - Lock(); - enabled_ = enabled; -@@ -156,37 +159,17 @@ void VSyncWorker::Routine() { - (int64_t)vblank.reply.tval_usec * 1000; - } - -- /* -- * VSync could be disabled during routine execution so it could potentially -- * lead to crash since callback's inner hook could be invalid anymore. We have -- * no control over lifetime of this hook, therefore we can't rely that it'll -- * be valid after vsync disabling. -- * -- * Blocking VSyncControl to wait until routine -- * will finish execution is logically correct way to fix this issue, but it -- * creates visible lags and stutters, so we have to resort to other ways of -- * mitigating this issue. -- * -- * Doing check before attempt to invoke callback drastically shortens the -- * window when such situation could happen and that allows us to practically -- * avoid this issue. -- * -- * Please note that issue described below is different one and it is related -- * to RegisterCallback, not to disabling vsync via VSyncControl. -- */ - if (!enabled_) - return; -- /* -- * There's a race here where a change in callback_ will not take effect until -- * the next subsequent requested vsync. This is unavoidable since we can't -- * call the vsync hook while holding the thread lock. -- * -- * We could shorten the race window by caching callback_ right before calling -- * the hook. However, in practice, callback_ is only updated once, so it's not -- * worth the overhead. -- */ -+ - if (callback) - callback->Callback(display, timestamp); -+ -+ Lock(); -+ if (enabled_ && vsync_callback_hook_ && vsync_callback_data_) -+ vsync_callback_hook_(vsync_callback_data_, display, timestamp); -+ Unlock(); -+ - last_timestamp_ = timestamp; - } - } // namespace android -diff --git a/include/vsyncworker.h b/drm/VSyncWorker.h -similarity index 84% -rename from include/vsyncworker.h -rename to drm/VSyncWorker.h -index 96f7432..7454b51 100644 ---- a/include/vsyncworker.h -+++ b/drm/VSyncWorker.h -@@ -17,14 +17,15 @@ - #ifndef ANDROID_EVENT_WORKER_H_ - #define ANDROID_EVENT_WORKER_H_ - --#include "drmdevice.h" --#include "worker.h" -- -+#include -+#include -+#include - #include -+ - #include - --#include --#include -+#include "DrmDevice.h" -+#include "utils/Worker.h" - - namespace android { - -@@ -42,6 +43,8 @@ class VSyncWorker : public Worker { - - int Init(DrmDevice *drm, int display); - void RegisterCallback(std::shared_ptr callback); -+ void RegisterClientCallback(hwc2_callback_data_t data, -+ hwc2_function_pointer_t hook); - - void VSyncControl(bool enabled); - -@@ -62,6 +65,9 @@ class VSyncWorker : public Worker { - int display_; - std::atomic_bool enabled_; - int64_t last_timestamp_; -+ -+ hwc2_callback_data_t vsync_callback_data_ = NULL; -+ HWC2_PFN_VSYNC vsync_callback_hook_ = NULL; - }; - } // namespace android - -diff --git a/include/drmframebuffer.h b/include/DrmFramebuffer.h -similarity index 99% -rename from include/drmframebuffer.h -rename to include/DrmFramebuffer.h -index 9032d3a..33ca0db 100644 ---- a/include/drmframebuffer.h -+++ b/include/DrmFramebuffer.h -@@ -18,9 +18,7 @@ - #define ANDROID_DRM_FRAMEBUFFER_ - - #include -- - #include -- - #include - - namespace android { -diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h -index b959714..05b2cf0 100644 ---- a/include/drmhwcgralloc.h -+++ b/include/drmhwcgralloc.h -@@ -26,14 +26,12 @@ typedef struct hwc_drm_bo { - uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ - uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */ - uint32_t usage; -- uint32_t pixel_stride; - uint32_t pitches[HWC_DRM_BO_MAX_PLANES]; - uint32_t offsets[HWC_DRM_BO_MAX_PLANES]; - uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES]; - uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES]; - uint64_t modifiers[HWC_DRM_BO_MAX_PLANES]; - uint32_t fb_id; -- bool with_modifiers; - int acquire_fence_fd; - void *priv; - } hwc_drm_bo_t; -diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h -index 69313d9..1007144 100644 ---- a/include/drmhwcomposer.h -+++ b/include/drmhwcomposer.h -@@ -99,8 +99,7 @@ class DrmHwcNativeHandle { - return *this; - } - -- int CopyBufferHandle(buffer_handle_t handle, int width, int height, -- int layerCount, int format, int usage, int stride); -+ int CopyBufferHandle(buffer_handle_t handle); - - void Clear(); - -@@ -137,6 +136,7 @@ struct DrmHwcLayer { - uint16_t alpha = 0xffff; - hwc_frect_t source_crop; - hwc_rect_t display_frame; -+ android_dataspace_t dataspace; - - UniqueFd acquire_fence; - OutputFd release_fence; -diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp -deleted file mode 100644 -index 1aa8160..0000000 ---- a/platform/platformdrmgeneric.cpp -+++ /dev/null -@@ -1,252 +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. -- */ -- --#define LOG_TAG "hwc-platform-drm-generic" -- --#include "platformdrmgeneric.h" --#include "drmdevice.h" --#include "platform.h" -- --#include --#include -- --#include --#include --#include --#include -- --namespace android { -- --#ifdef USE_DRM_GENERIC_IMPORTER --// static --Importer *Importer::CreateInstance(DrmDevice *drm) { -- DrmGenericImporter *importer = new DrmGenericImporter(drm); -- if (!importer) -- return NULL; -- -- int ret = importer->Init(); -- if (ret) { -- ALOGE("Failed to initialize the nv importer %d", ret); -- delete importer; -- return NULL; -- } -- return importer; --} --#endif -- --DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) -- : drm_(drm), exclude_non_hwfb_(false) { --} -- --DrmGenericImporter::~DrmGenericImporter() { --} -- --int DrmGenericImporter::Init() { -- int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, -- (const hw_module_t **)&gralloc_); -- if (ret) { -- ALOGE("Failed to open gralloc module"); -- return ret; -- } -- -- ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name, -- gralloc_->common.author); -- -- char exclude_non_hwfb_prop[PROPERTY_VALUE_MAX]; -- property_get("hwc.drm.exclude_non_hwfb_imports", exclude_non_hwfb_prop, "0"); -- exclude_non_hwfb_ = static_cast(strncmp(exclude_non_hwfb_prop, "0", 1)); -- -- return 0; --} -- --uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) { -- switch (hal_format) { -- case HAL_PIXEL_FORMAT_RGB_888: -- return DRM_FORMAT_BGR888; -- case HAL_PIXEL_FORMAT_BGRA_8888: -- return DRM_FORMAT_ARGB8888; -- case HAL_PIXEL_FORMAT_RGBX_8888: -- return DRM_FORMAT_XBGR8888; -- case HAL_PIXEL_FORMAT_RGBA_8888: -- return DRM_FORMAT_ABGR8888; -- case HAL_PIXEL_FORMAT_RGB_565: -- return DRM_FORMAT_BGR565; -- case HAL_PIXEL_FORMAT_YV12: -- return DRM_FORMAT_YVU420; -- default: -- ALOGE("Cannot convert hal format to drm format %u", hal_format); -- return DRM_FORMAT_INVALID; -- } --} -- --uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) { -- switch (drm_format) { -- case DRM_FORMAT_ARGB8888: -- case DRM_FORMAT_XBGR8888: -- case DRM_FORMAT_ABGR8888: -- return 32; -- case DRM_FORMAT_BGR888: -- return 24; -- case DRM_FORMAT_BGR565: -- return 16; -- case DRM_FORMAT_YVU420: -- return 12; -- default: -- ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format); -- return 32; -- } --} -- --int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle, -- hwc_drm_bo_t *bo) { -- gralloc_handle_t *gr_handle = gralloc_handle(handle); -- if (!gr_handle) -- return -EINVAL; -- -- bo->width = gr_handle->width; -- bo->height = gr_handle->height; -- bo->hal_format = gr_handle->format; -- bo->format = ConvertHalFormatToDrm(gr_handle->format); -- if (bo->format == DRM_FORMAT_INVALID) -- return -EINVAL; -- bo->usage = gr_handle->usage; -- bo->pixel_stride = (gr_handle->stride * 8) / -- DrmFormatToBitsPerPixel(bo->format); -- bo->prime_fds[0] = gr_handle->prime_fd; -- bo->pitches[0] = gr_handle->stride; -- bo->offsets[0] = 0; -- -- return 0; --} -- --int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { -- memset(bo, 0, sizeof(hwc_drm_bo_t)); -- -- int ret = ConvertBoInfo(handle, bo); -- if (ret) -- return ret; -- -- ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]); -- if (ret) { -- ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret); -- return ret; -- } -- -- for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) { -- int fd = bo->prime_fds[i]; -- if (fd != 0) { -- if (fd != bo->prime_fds[0]) { -- ALOGE("Multiplanar FBs are not supported by this version of composer"); -- return -ENOTSUP; -- } -- bo->gem_handles[i] = bo->gem_handles[0]; -- } -- } -- -- if (!bo->with_modifiers) -- ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format, -- bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, -- 0); -- else -- ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height, -- bo->format, bo->gem_handles, bo->pitches, -- bo->offsets, bo->modifiers, &bo->fb_id, -- bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS -- : 0); -- -- if (ret) { -- ALOGE("could not create drm fb %d", ret); -- return ret; -- } -- -- ImportHandle(bo->gem_handles[0]); -- -- return ret; --} -- --int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) { -- if (bo->fb_id) -- if (drmModeRmFB(drm_->fd(), bo->fb_id)) -- ALOGE("Failed to rm fb"); -- -- for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) { -- if (!bo->gem_handles[i]) -- continue; -- -- if (ReleaseHandle(bo->gem_handles[i])) { -- ALOGE("Failed to release gem handle %d", bo->gem_handles[i]); -- } else { -- for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++) -- if (bo->gem_handles[j] == bo->gem_handles[i]) -- bo->gem_handles[j] = 0; -- bo->gem_handles[i] = 0; -- } -- } -- return 0; --} -- --bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) { -- hwc_drm_bo_t bo; -- -- int ret = ConvertBoInfo(handle, &bo); -- if (ret) -- return false; -- -- if (bo.prime_fds[0] == 0) -- return false; -- -- if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB)) -- return false; -- -- return true; --} -- --#ifdef USE_DRM_GENERIC_IMPORTER --std::unique_ptr Planner::CreateInstance(DrmDevice *) { -- std::unique_ptr planner(new Planner); -- planner->AddStage(); -- return planner; --} --#endif -- --int DrmGenericImporter::ImportHandle(uint32_t gem_handle) { -- gem_refcount_[gem_handle]++; -- -- return 0; --} -- --int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) { -- if (--gem_refcount_[gem_handle]) -- return 0; -- -- gem_refcount_.erase(gem_handle); -- -- return CloseHandle(gem_handle); --} -- --int DrmGenericImporter::CloseHandle(uint32_t gem_handle) { -- struct drm_gem_close gem_close; -- -- memset(&gem_close, 0, sizeof(gem_close)); -- -- gem_close.handle = gem_handle; -- int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close); -- if (ret) -- ALOGE("Failed to close gem handle %d %d", gem_handle, ret); -- -- return ret; --} --} -diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp -deleted file mode 100644 -index 1f1478f..0000000 ---- a/platform/platformhisi.cpp -+++ /dev/null -@@ -1,197 +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. -- */ -- --#define LOG_TAG "hwc-platform-hisi" -- --#include "platformhisi.h" --#include "drmdevice.h" --#include "platform.h" -- --#include --#include --#include --#include -- --#include --#include --#include "gralloc_priv.h" -- --#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1)) -- --namespace android { -- --Importer *Importer::CreateInstance(DrmDevice *drm) { -- HisiImporter *importer = new HisiImporter(drm); -- if (!importer) -- return NULL; -- -- int ret = importer->Init(); -- if (ret) { -- ALOGE("Failed to initialize the hisi importer %d", ret); -- delete importer; -- return NULL; -- } -- return importer; --} -- --#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \ -- defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) --uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags, -- bool is_rgb) { -- uint64_t features = 0UL; -- -- if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) -- features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16; -- -- if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) -- features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE); -- -- if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) -- features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8; -- -- if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) -- features |= AFBC_FORMAT_MOD_TILED; -- -- if (features) { -- if (is_rgb) -- features |= AFBC_FORMAT_MOD_YTR; -- -- return DRM_FORMAT_MOD_ARM_AFBC(features); -- } -- -- return 0; --} --#else --uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t /* flags */, -- bool /* is_rgb */) { -- return 0; --} --#endif -- --bool HisiImporter::IsDrmFormatRgb(uint32_t drm_format) { -- switch (drm_format) { -- case DRM_FORMAT_ARGB8888: -- case DRM_FORMAT_XBGR8888: -- case DRM_FORMAT_ABGR8888: -- case DRM_FORMAT_BGR888: -- case DRM_FORMAT_BGR565: -- return true; -- case DRM_FORMAT_YVU420: -- return false; -- default: -- ALOGV("Unsupported format %u assuming rgb?", drm_format); -- return true; -- } --} -- --int HisiImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) { -- bool is_rgb; -- -- private_handle_t const *hnd = reinterpret_cast( -- handle); -- if (!hnd) -- return -EINVAL; -- -- if (!(hnd->usage & GRALLOC_USAGE_HW_FB)) -- return -EINVAL; -- -- uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format); -- if (fmt == DRM_FORMAT_INVALID) -- return -EINVAL; -- -- is_rgb = HisiImporter::IsDrmFormatRgb(fmt); -- bo->modifiers[0] = HisiImporter:: -- 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->pixel_stride = hnd->stride; -- bo->pitches[0] = hnd->byte_stride; -- bo->prime_fds[0] = hnd->share_fd; -- bo->offsets[0] = 0; -- -- switch (fmt) { -- case DRM_FORMAT_YVU420: { -- int align = 128; -- if (hnd->usage & -- (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) -- align = 16; -- int adjusted_height = MALI_ALIGN(hnd->height, 2); -- int y_size = adjusted_height * hnd->byte_stride; -- int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align); -- 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; -- /* U plane */ -- bo->prime_fds[2] = hnd->share_fd; -- bo->pitches[2] = vu_stride; -- bo->offsets[2] = y_size + v_size; -- break; -- } -- default: -- break; -- } -- -- bo->with_modifiers = true; -- -- return 0; --} -- --class PlanStageHiSi : public Planner::PlanStage { -- public: -- int ProvisionPlanes(std::vector *composition, -- std::map &layers, DrmCrtc *crtc, -- std::vector *planes) { -- int layers_added = 0; -- // Fill up as many DRM planes as we can with buffers that have HW_FB usage. -- // Buffers without HW_FB should have been filtered out with -- // CanImportBuffer(), if we meet one here, just skip it. -- for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) { -- if (!(i->second->gralloc_buffer_usage & GRALLOC_USAGE_HW_FB)) -- continue; -- -- int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, -- crtc, std::make_pair(i->first, i->second)); -- layers_added++; -- // We don't have any planes left -- if (ret == -ENOENT) -- break; -- else if (ret) { -- ALOGE("Failed to emplace layer %zu, dropping it", i->first); -- return ret; -- } -- } -- // If we didn't emplace anything, return an error to ensure we force client -- // compositing. -- if (!layers_added) -- return -EINVAL; -- -- return 0; -- } --}; -- --std::unique_ptr Planner::CreateInstance(DrmDevice *) { -- std::unique_ptr planner(new Planner); -- planner->AddStage(); -- return planner; --} --} // namespace android -diff --git a/platform/platformimagination.h b/platform/platformimagination.h -deleted file mode 100644 -index f2a7cb7..0000000 ---- a/platform/platformimagination.h -+++ /dev/null -@@ -1,22 +0,0 @@ --#ifndef PLATFORMIMAGINATION_H --#define PLATFORMIMAGINATION_H -- --#include "drmdevice.h" --#include "platform.h" --#include "platformdrmgeneric.h" -- --#include -- --#include -- --namespace android { -- --class ImaginationImporter : public DrmGenericImporter { -- public: -- using DrmGenericImporter::DrmGenericImporter; -- -- int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override; --}; --} // namespace android -- --#endif // PLATFORMIMAGINATION_H -diff --git a/tests/Android.bp b/tests/Android.bp -index 7e550ff..282e71c 100644 ---- a/tests/Android.bp -+++ b/tests/Android.bp -@@ -9,5 +9,8 @@ cc_test { - header_libs: ["libhardware_headers"], - static_libs: ["libdrmhwc_utils"], - shared_libs: ["hwcomposer.drm"], -- include_dirs: ["external/drm_hwcomposer/include"], -+ include_dirs: [ -+ "external/drm_hwcomposer/include", -+ "external/drm_hwcomposer", -+ ], - } -diff --git a/tests/worker_test.cpp b/tests/worker_test.cpp -index 82523f0..cb6275e 100644 ---- a/tests/worker_test.cpp -+++ b/tests/worker_test.cpp -@@ -1,10 +1,10 @@ -+#include "utils/Worker.h" -+ - #include - #include - - #include - --#include "worker.h" -- - using android::Worker; - - struct TestWorker : public Worker { -diff --git a/utils/worker.cpp b/utils/Worker.cpp -similarity index 99% -rename from utils/worker.cpp -rename to utils/Worker.cpp -index 0dceb16..1f30588 100644 ---- a/utils/worker.cpp -+++ b/utils/Worker.cpp -@@ -14,7 +14,7 @@ - * limitations under the License. - */ - --#include "worker.h" -+#include "Worker.h" - - #include - #include -diff --git a/include/worker.h b/utils/Worker.h -similarity index 100% -rename from include/worker.h -rename to utils/Worker.h -index 7909038..73a80da 100644 ---- a/include/worker.h -+++ b/utils/Worker.h -@@ -19,10 +19,10 @@ - - #include - #include --#include - - #include - #include -+#include - #include - - namespace android { -diff --git a/include/autolock.h b/utils/autolock.h -similarity index 100% -rename from include/autolock.h -rename to utils/autolock.h -diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp -index 87e3c42..322efce 100644 ---- a/utils/hwcutils.cpp -+++ b/utils/hwcutils.cpp -@@ -17,12 +17,14 @@ - #define ATRACE_TAG ATRACE_TAG_GRAPHICS - #define LOG_TAG "hwc-drm-utils" - --#include "drmhwcomposer.h" --#include "platform.h" -- - #include -+#include - #include - -+#include "bufferinfo/BufferInfoGetter.h" -+#include "drm/DrmGenericImporter.h" -+#include "drmhwcomposer.h" -+ - #define UNUSED(x) (void)(x) - - namespace android { -@@ -44,11 +46,19 @@ void DrmHwcBuffer::Clear() { - } - - int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { -- hwc_drm_bo tmp_bo; -+ hwc_drm_bo tmp_bo{}; - -- int ret = importer->ImportBuffer(handle, &tmp_bo); -- if (ret) -+ int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo); -+ if (ret) { -+ ALOGE("Failed to convert buffer info %d", ret); - return ret; -+ } -+ -+ ret = importer->ImportBuffer(&tmp_bo); -+ if (ret) { -+ ALOGE("Failed to import buffer %d", ret); -+ return ret; -+ } - - if (importer_ != NULL) { - importer_->ReleaseBuffer(&bo_); -@@ -61,25 +71,15 @@ int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { - return 0; - } - --int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width, -- int height, int layerCount, int format, -- int usage, int stride) { -+int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle) { - native_handle_t *handle_copy; - GraphicBufferMapper &gm(GraphicBufferMapper::get()); - int ret; - --#ifdef HWC2_USE_OLD_GB_IMPORT -- UNUSED(width); -- UNUSED(height); -- UNUSED(layerCount); -- UNUSED(format); -- UNUSED(usage); -- UNUSED(stride); -- ret = gm.importBuffer(handle, const_cast(&handle_copy)); --#else -- ret = gm.importBuffer(handle, width, height, layerCount, format, usage, -- stride, const_cast(&handle_copy)); --#endif -+ ret = gm.getGrallocMapper().importBuffer(handle, -+ const_cast( -+ &handle_copy)); -+ - if (ret) { - ALOGE("Failed to import buffer handle %d", ret); - return ret; -@@ -114,13 +114,7 @@ int DrmHwcLayer::ImportBuffer(Importer *importer) { - - const hwc_drm_bo *bo = buffer.operator->(); - -- unsigned int layer_count; -- for (layer_count = 0; layer_count < HWC_DRM_BO_MAX_PLANES; ++layer_count) -- if (bo->gem_handles[layer_count] == 0) -- break; -- -- ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height, layer_count, -- bo->hal_format, bo->usage, bo->pixel_stride); -+ ret = handle.CopyBufferHandle(sf_handle); - if (ret) - return ret; - --- -2.29.0 - diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0002-Fix-issue-and-add-some-properties.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0002-Fix-issue-and-add-some-properties.patch new file mode 100644 index 0000000000..d53e3f1735 --- /dev/null +++ b/aosp_diff/preliminary/external/drm_hwcomposer/0002-Fix-issue-and-add-some-properties.patch @@ -0,0 +1,328 @@ +From 01f75270ce37ab07a7444a5d0b7088bbdfcfb8db Mon Sep 17 00:00:00 2001 +From: "Li, HaihongX" +Date: Thu, 26 Aug 2021 09:46:08 +0800 +Subject: [PATCH 2/3] Fix issue and add some properties + +1. Fix issue caused by crtc count and connector count doesn't match. +2. Multi-plane support + Multi-plane can be enabled by property + vendor.hwcomposer.planes.enabling. + By default, only one plane is used if the property is not set. + vendor.hwcomposer.planes.enabling=1 #support all planes + vendor.hwcomposer.planes.enabling=0 #only support PRIMARY by default +3. Select preferred mode + If the property 'vendor.hwcomposer.preferred.mode.limit' does not + exist, or set to '1' then only support preferred mode. + If the property 'vendor.hwcomposer.preferred.mode.limit' is set to + '0', support all modes. + vendor.hwcomposer.preferred.mode.limit=1#only support preferred mode + vendor.hwcomposer.preferred.mode.limit=0#support all modes +4. Select specific mode + This function is controlled by 2 properties. + vendor.hwcomposer.connector.id + vendor.hwcomposer.mode.id + If the properties 'vendor.hwcomposer.connector.id' and + 'vendor.hwcomposer.mode.id' are all set, then only support the + selected mode indicated by 'vendor.hwcomposer.mode.id'. + If any one of the properties 'vendor.hwcomposer.connector.id' and + 'vendor.hwcomposer.mode.id' is not set, then to check the property + 'vendor.hwcomposer.preferred.mode.limit'. + vendor.hwcomposer.connector.id=117 + vendor.hwcomposer.mode.id=2 +5. With these properties, hwc can provide flexibility for performance + tuning and bug triage. +6. Find mode id +cat /sys/kernel/debug/dri/0/i915_display_info.The output like below: +[CONNECTOR:117:DP-4]: status: connected +modes: +"1920x1080": 62 144500 1920 1968 2000 2080 1080 1083 1088 1112 0x48 0x9 +"1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0xa +"1680x1050": 60 146250 1680 1784 1960 2240 1050 1053 1059 1089 0x40 0x6 +"1680x945": 60 131481 1680 1784 1960 2240 945 946 949 978 0x0 0x6 +mode id starts from 1, and increases with a step of 1 in order. +mode id is 1: +"1920x1080": 62 144500 1920 1968 2000 2080 1080 1083 1088 1112 0x48 0x9 +mode id is 2: +"1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0xa +mode id is 3: +"1680x1050": 60 146250 1680 1784 1960 2240 1050 1053 1059 1089 0x40 0x6 +mode id is 4: +"1680x945": 60 131481 1680 1784 1960 2240 945 946 949 978 0x0 0x6 +7. The property can be set in /vendor/default.prop. +8. Support 'SetActiveConfigWithConstraints' interface needed by vts. +9. Fix multi-display issue. + +Tracked-On: OAM-99705 +Signed-off-by: Li, HaihongX +--- + DrmHwcTwo.cpp | 12 +++++-- + drm/DrmConnector.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++- + drm/DrmDevice.cpp | 55 ++++++++++++++++++++++++++++-- + drm/DrmDevice.h | 3 ++ + 4 files changed, 143 insertions(+), 6 deletions(-) + +diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp +index d141f16..2273303 100644 +--- a/DrmHwcTwo.cpp ++++ b/DrmHwcTwo.cpp +@@ -914,7 +914,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayVsyncPeriod( + } + + HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfigWithConstraints( +- hwc2_config_t /*config*/, ++ hwc2_config_t config, + hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints, + hwc_vsync_period_change_timeline_t *outTimeline) { + supported(__func__); +@@ -922,8 +922,14 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfigWithConstraints( + if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) { + return HWC2::Error::BadParameter; + } +- +- return HWC2::Error::BadConfig; ++ uint32_t num_configs; ++ HWC2::Error err = GetDisplayConfigs(&num_configs, NULL); ++ if (err != HWC2::Error::None || !num_configs) ++ return err; ++ if (num_configs < config) ++ return HWC2::Error::BadConfig; ++ else ++ return SetActiveConfig(config); + } + + HWC2::Error DrmHwcTwo::HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) { +diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp +index 0468527..972660c 100644 +--- a/drm/DrmConnector.cpp ++++ b/drm/DrmConnector.cpp +@@ -19,7 +19,7 @@ + #include "DrmConnector.h" + + #include +- ++#include + #include + #include + #include +@@ -170,14 +170,85 @@ int DrmConnector::UpdateModes() { + + state_ = c->connection; + ++ int32_t connector_id; ++ int32_t mode_id; ++ ++ char property[PROPERTY_VALUE_MAX]; ++ memset(property, 0 , PROPERTY_VALUE_MAX); ++ property_get("vendor.hwcomposer.connector.id", property, "-1"); ++ connector_id = atoi(property); ++ ALOGD("The property 'vendor.hwcomposer.connector.id' value is %d", connector_id); ++ ++ memset(property, 0 , PROPERTY_VALUE_MAX); ++ property_get("vendor.hwcomposer.mode.id", property, "-1"); ++ mode_id = atoi(property); ++ ALOGD("The property 'vendor.hwcomposer.mode.id' value is %d", mode_id); ++ + bool preferred_mode_found = false; + std::vector new_modes; ++ ++ if (mode_id <= 0 || mode_id > c->count_modes) ++ mode_id = -1; ++ ++ bool have_preferred_mode = false; ++ for (int i = 0; i < c->count_modes; ++i) { ++ if (c->modes[i].type & DRM_MODE_TYPE_PREFERRED) { ++ have_preferred_mode = true; ++ break; ++ } ++ } ++ + for (int i = 0; i < c->count_modes; ++i) { ++ if (drm_->preferred_mode_limit_ && connector_id == -1) { ++ if (have_preferred_mode) { ++ if (!(c->modes[i].type & DRM_MODE_TYPE_PREFERRED)) { ++ drm_->next_mode_id(); ++ continue; ++ } ++ } else { ++ have_preferred_mode = true; ++ } ++ } ++ if (c->connector_id == connector_id) { ++ if (mode_id == -1) { ++ if (drm_->preferred_mode_limit_) { ++ if (have_preferred_mode) { ++ if (!(c->modes[i].type & DRM_MODE_TYPE_PREFERRED)) { ++ drm_->next_mode_id(); ++ continue; ++ } ++ } else { ++ have_preferred_mode = true; ++ } ++ } ++ } else { ++ if (mode_id != (i + 1)) { ++ drm_->next_mode_id(); ++ continue; ++ } ++ } ++ } else { ++ if (connector_id != -1) { ++ if (drm_->preferred_mode_limit_) { ++ if (have_preferred_mode) { ++ if (!(c->modes[i].type & DRM_MODE_TYPE_PREFERRED)) { ++ drm_->next_mode_id(); ++ continue; ++ } ++ } else { ++ have_preferred_mode = true; ++ } ++ } ++ } ++ } ++ + bool exists = false; + for (const DrmMode &mode : modes_) { + if (mode == c->modes[i]) { + new_modes.push_back(mode); + exists = true; ++ ALOGD("CONNECTOR:%d select one mode, id = %d, name = %s, refresh = %f", ++ id_, mode.id(), mode.name().c_str(), mode.v_refresh()); + break; + } + } +@@ -185,17 +256,23 @@ int DrmConnector::UpdateModes() { + DrmMode m(&c->modes[i]); + m.set_id(drm_->next_mode_id()); + new_modes.push_back(m); ++ ALOGD("CONNECTOR:%d select one mode, id = %d, name = %s, refresh = %f", ++ id_, m.id(), m.name().c_str(), m.v_refresh()); + } + // Use only the first DRM_MODE_TYPE_PREFERRED mode found + if (!preferred_mode_found && + (new_modes.back().type() & DRM_MODE_TYPE_PREFERRED)) { + preferred_mode_id_ = new_modes.back().id(); + preferred_mode_found = true; ++ ALOGD("CONNECTOR:%d preferred mode found, set preferred mode id = %d, name = %s, refresh = %f", ++ id_, preferred_mode_id_, new_modes.back().name().c_str(), new_modes.back().v_refresh()); + } + } + modes_.swap(new_modes); + if (!preferred_mode_found && !modes_.empty()) { + preferred_mode_id_ = modes_[0].id(); ++ ALOGD("CONNECTOR:%d preferred mode not found, set preferred mode id = %d, name = %s, refresh = %f", ++ id_, preferred_mode_id_, modes_[0].name().c_str(), modes_[0].v_refresh()); + } + return 0; + } +diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp +index abc8edc..5abe2f4 100644 +--- a/drm/DrmDevice.cpp ++++ b/drm/DrmDevice.cpp +@@ -167,6 +167,18 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + return std::make_tuple(-ENODEV, 0); + } + ++ char property[PROPERTY_VALUE_MAX]; ++ memset(property, 0 , PROPERTY_VALUE_MAX); ++ property_get("vendor.hwcomposer.preferred.mode.limit", property, "1"); ++ preferred_mode_limit_ = atoi(property) != 0 ? true : false; ++ ALOGD("The property 'vendor.hwcomposer.preferred.mode.limit' value is %d", preferred_mode_limit_); ++ ++ memset(property, 0 , PROPERTY_VALUE_MAX); ++ property_get("vendor.hwcomposer.planes.enabling", property, "0"); ++ planes_enabling_ = atoi(property) != 0 ? true : false; ++ ALOGD("The property 'vendor.hwcomposer.planes.enabling' value is %d, %s", ++ planes_enabling_, planes_enabling_ ? "support all planes":"only support primary plane"); ++ + min_resolution_ = std::pair(res->min_width, + res->min_height); + max_resolution_ = std::pair(res->max_width, +@@ -282,6 +294,15 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + "\"vendor.hwc.drm.primary_display_order\" property"); + } + ++ for (auto &primary_conn : primary_candidates) { ++ if (primary_conn == *std::begin(primary_candidates)) ++ continue; ++ primary_conn->set_display(num_displays); ++ displays_[num_displays] = num_displays; ++ ++num_displays; ++ } ++ ++ int max_pipe_count = std::min(res->count_crtcs, res->count_connectors); + // If no priority display were found then pick first available as primary and + // for the others assign consecutive display_numbers. + for (auto &conn : connectors_) { +@@ -291,7 +312,7 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + displays_[num_displays] = num_displays; + found_primary = true; + ++num_displays; +- } else if (conn->display() < 0) { ++ } else if (conn->display() < 0 && num_displays < max_pipe_count) { + conn->set_display(num_displays); + displays_[num_displays] = num_displays; + ++num_displays; +@@ -330,7 +351,12 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + break; + } + +- planes_.emplace_back(std::move(plane)); ++ if (!planes_enabling_) { ++ if (plane->type() == DRM_PLANE_TYPE_PRIMARY) ++ planes_.emplace_back(std::move(plane)); ++ } else { ++ planes_.emplace_back(std::move(plane)); ++ } + } + drmModeFreePlaneResources(plane_res); + if (ret) +@@ -342,7 +368,32 @@ std::tuple DrmDevice::Init(const char *path, int num_displays) { + return std::make_tuple(ret, 0); + } + ++ for (auto conn : primary_candidates) { ++ if (max_pipe_count-- <= 0) ++ break; ++ ++ ret = CreateDisplayPipe(conn); ++ if (ret) { ++ ALOGE("Failed CreateDisplayPipe %d with %d", conn->id(), ret); ++ return std::make_tuple(ret, 0); ++ } ++ if (!AttachWriteback(conn)) { ++ ALOGI("Display %d has writeback attach to it", conn->display()); ++ } ++ } ++ + for (auto &conn : connectors_) { ++ auto it = std::find_if(std::begin(primary_candidates), ++ std::end(primary_candidates), ++ [&conn](const DrmConnector *conn_pri) { ++ return conn->id() == conn_pri->id(); ++ }); ++ if (it != std::end(primary_candidates)) ++ continue; ++ ++ if (max_pipe_count-- <= 0) ++ break; ++ + ret = CreateDisplayPipe(conn.get()); + if (ret) { + ALOGE("Failed CreateDisplayPipe %d with %d", conn->id(), ret); +diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h +index dfca263..cc35e6f 100644 +--- a/drm/DrmDevice.h ++++ b/drm/DrmDevice.h +@@ -123,6 +123,9 @@ class DrmDevice { + std::shared_ptr self; + + std::unique_ptr mDrmFbImporter; ++public: ++ bool preferred_mode_limit_; ++ bool planes_enabling_; + }; + } // namespace android + +-- +2.32.0 + diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0003-Fix-hotplug-issue-and-add-vsync2.4-callback.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0003-Fix-hotplug-issue-and-add-vsync2.4-callback.patch new file mode 100644 index 0000000000..70492c81eb --- /dev/null +++ b/aosp_diff/preliminary/external/drm_hwcomposer/0003-Fix-hotplug-issue-and-add-vsync2.4-callback.patch @@ -0,0 +1,246 @@ +From e2a49640c385500d9978a3b07901b14f976a7980 Mon Sep 17 00:00:00 2001 +From: "Li, HaihongX" +Date: Thu, 9 Sep 2021 15:04:23 +0800 +Subject: [PATCH 3/3] Fix hotplug issue and add vsync2.4 callback + +1. Once unplug event comes, display.ClearDisplay() will be invoked. + Then DrmDisplayCompositor::active_composition_ will be set to + nullptr, so in function DrmDisplayCompositor::IsFlatteningNeeded(), + should check active_composition_ is not nullptr. +2. For android can't delete primary display, so when unplug event comes + and belongs to primary display, don't invoke hotplug callback to + notify upper. +3. Add vsync2.4 callback. +4. Set connector dpms property with DRM_MODE_DPMS_OFF if unpluging, + DRM_MODE_DPMS_ON if pluging,to enable irq,fix type-c hotplug issue. +5. Set DrmDevice::mode_id_ with 0 at beginning of + DrmConnector::UpdateModes(). + +Tracked-On: OAM-99705 +Signed-off-by: Li, HaihongX +--- + DrmHwcTwo.cpp | 23 +++++++++++++++++++++-- + DrmHwcTwo.h | 3 +++ + compositor/DrmDisplayCompositor.cpp | 5 ++++- + drm/DrmConnector.cpp | 1 + + drm/DrmDevice.cpp | 4 ++++ + drm/DrmDevice.h | 1 + + drm/DrmEventListener.cpp | 4 ++-- + drm/VSyncWorker.cpp | 12 ++++++++++++ + drm/VSyncWorker.h | 5 +++++ + 9 files changed, 53 insertions(+), 5 deletions(-) + +diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp +index 2273303..0eadcd7 100644 +--- a/DrmHwcTwo.cpp ++++ b/DrmHwcTwo.cpp +@@ -203,6 +203,15 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, + d.second.RegisterVsyncCallback(data, function); + break; + } ++ case HWC2::Callback::Vsync_2_4: { ++ for (std::pair &d : ++ displays_) ++ d.second.RegisterVsync_2_4Callback(data, function); ++ break; ++ } ++ case HWC2::Callback::VsyncPeriodTimingChanged: { ++ break; ++ } + default: + break; + } +@@ -308,6 +317,12 @@ void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback( + compositor_.SetRefreshCallback(data, func); + } + ++void DrmHwcTwo::HwcDisplay::RegisterVsync_2_4Callback( ++ hwc2_callback_data_t data, hwc2_function_pointer_t func) { ++ supported(__func__); ++ vsync_worker_.RegisterClient_2_4Callback(data, func); ++} ++ + HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() { + supported(__func__); + for (std::pair &l : layers_) +@@ -1193,7 +1208,8 @@ void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) { + drmModeConnection cur_state = conn->UpdateModes() + ? DRM_MODE_UNKNOWNCONNECTION + : conn->state(); +- ++ if (conn->display() == -1) ++ continue; + if (cur_state == old_state) + continue; + +@@ -1205,12 +1221,15 @@ void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) { + if (cur_state == DRM_MODE_CONNECTED) { + auto &display = hwc2_->displays_.at(display_id); + display.ChosePreferredConfig(); ++ display.SetPowerMode(static_cast(HWC2::PowerMode::On)); + } else { + auto &display = hwc2_->displays_.at(display_id); + display.ClearDisplay(); ++ display.SetPowerMode(static_cast(HWC2::PowerMode::Off)); + } + +- hwc2_->HandleDisplayHotplug(display_id, cur_state); ++ if (display_id != 0 || (display_id == 0 && cur_state == DRM_MODE_CONNECTED)) ++ hwc2_->HandleDisplayHotplug(display_id, cur_state); + } + } + +diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h +index 111c664..0c2edef 100644 +--- a/DrmHwcTwo.h ++++ b/DrmHwcTwo.h +@@ -157,6 +157,9 @@ class DrmHwcTwo : public hwc2_device_t { + hwc2_function_pointer_t func); + void RegisterRefreshCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t func); ++ void RegisterVsync_2_4Callback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t func); ++ + HWC2::Error CreateComposition(bool test); + std::vector GetOrderLayersByZPos(); + +diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp +index a1fe50f..e332641 100644 +--- a/compositor/DrmDisplayCompositor.cpp ++++ b/compositor/DrmDisplayCompositor.cpp +@@ -685,7 +685,10 @@ void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) { + } + + bool DrmDisplayCompositor::IsFlatteningNeeded() const { +- return CountdownExpired() && active_composition_->layers().size() >= 2; ++ if (active_composition_) ++ return CountdownExpired() && active_composition_->layers().size() >= 2; ++ else ++ return false; + } + + int DrmDisplayCompositor::FlattenOnClient() { +diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp +index 972660c..3b0f8cb 100644 +--- a/drm/DrmConnector.cpp ++++ b/drm/DrmConnector.cpp +@@ -162,6 +162,7 @@ std::string DrmConnector::name() const { + int DrmConnector::UpdateModes() { + int fd = drm_->fd(); + ++ drm_->reset_mode_id(); + drmModeConnectorPtr c = drmModeGetConnector(fd, id_); + if (!c) { + ALOGE("Failed to get connector %d", id_); +diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp +index 5abe2f4..f47aa72 100644 +--- a/drm/DrmDevice.cpp ++++ b/drm/DrmDevice.cpp +@@ -475,6 +475,10 @@ uint32_t DrmDevice::next_mode_id() { + return ++mode_id_; + } + ++void DrmDevice::reset_mode_id() { ++ mode_id_ = 0; ++} ++ + int DrmDevice::TryEncoderForDisplay(int display, DrmEncoder *enc) { + /* First try to use the currently-bound crtc */ + DrmCrtc *crtc = enc->crtc(); +diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h +index cc35e6f..a84d1f9 100644 +--- a/drm/DrmDevice.h ++++ b/drm/DrmDevice.h +@@ -81,6 +81,7 @@ class DrmDevice { + const std::vector> &crtcs() const; + uint32_t next_mode_id(); + ++ void reset_mode_id(); + int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id) const; + int DestroyPropertyBlob(uint32_t blob_id) const; + bool HandlesDisplay(int display) const; +diff --git a/drm/DrmEventListener.cpp b/drm/DrmEventListener.cpp +index b303653..d59bd07 100644 +--- a/drm/DrmEventListener.cpp ++++ b/drm/DrmEventListener.cpp +@@ -83,7 +83,7 @@ void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */, + } + + void DrmEventListener::UEventHandler() { +- char buffer[1024]; ++ char buffer[1024]= {0}; + int ret = 0; + + struct timespec ts {}; +@@ -96,7 +96,7 @@ void DrmEventListener::UEventHandler() { + ALOGE("Failed to get monotonic clock on hotplug %d", ret); + + while (true) { +- ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer)); ++ ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer) - 1); + if (ret == 0) + return; + +diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp +index 25eeeab..b7ceb4c 100644 +--- a/drm/VSyncWorker.cpp ++++ b/drm/VSyncWorker.cpp +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include "utils/log.h" + +@@ -58,6 +59,14 @@ void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data, + Unlock(); + } + ++void VSyncWorker::RegisterClient_2_4Callback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook) { ++ Lock(); ++ vsync_2_4_callback_data_ = data; ++ vsync_2_4_callback_hook_ = (HWC2_PFN_VSYNC_2_4)hook; ++ Unlock(); ++} ++ + void VSyncWorker::VSyncControl(bool enabled) { + Lock(); + enabled_ = enabled; +@@ -171,6 +180,9 @@ void VSyncWorker::Routine() { + Lock(); + if (enabled_ && vsync_callback_hook_ && vsync_callback_data_) + vsync_callback_hook_(vsync_callback_data_, display, timestamp); ++ ++ if (enabled_ && vsync_2_4_callback_hook_ && vsync_2_4_callback_data_) ++ vsync_2_4_callback_hook_(vsync_2_4_callback_data_, display, timestamp, 0); + Unlock(); + + last_timestamp_ = timestamp; +diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h +index b43918c..09ebfda 100644 +--- a/drm/VSyncWorker.h ++++ b/drm/VSyncWorker.h +@@ -45,6 +45,8 @@ class VSyncWorker : public Worker { + void RegisterCallback(std::shared_ptr callback); + void RegisterClientCallback(hwc2_callback_data_t data, + hwc2_function_pointer_t hook); ++ void RegisterClient_2_4Callback(hwc2_callback_data_t data, ++ hwc2_function_pointer_t hook); + + void VSyncControl(bool enabled); + +@@ -68,6 +70,9 @@ class VSyncWorker : public Worker { + + hwc2_callback_data_t vsync_callback_data_ = NULL; + HWC2_PFN_VSYNC vsync_callback_hook_ = NULL; ++ ++ hwc2_callback_data_t vsync_2_4_callback_data_ = NULL; ++ HWC2_PFN_VSYNC_2_4 vsync_2_4_callback_hook_ = NULL; + }; + } // namespace android + +-- +2.32.0 + diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0004-Set-the-primary-display-as-internal-display.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0004-Set-the-primary-display-as-internal-display.patch new file mode 100644 index 0000000000..3052c18245 --- /dev/null +++ b/aosp_diff/preliminary/external/drm_hwcomposer/0004-Set-the-primary-display-as-internal-display.patch @@ -0,0 +1,32 @@ +From 7634fb36fc53913b962b5257b916f25ebf68f670 Mon Sep 17 00:00:00 2001 +From: "Li, HaihongX" +Date: Wed, 13 Oct 2021 10:01:58 +0800 +Subject: [PATCH] Set the primary display as internal display + +Celadon connect monitor with HDMI/DP/Type-C port, which is +regarded as external display, but android by default assume +there is one internal display, so need to set the primary +display as internal display. + +Tracked-On: OAM-99705 +Signed-off-by: Li, HaihongX +--- + DrmHwcTwo.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp +index 0eadcd7..194b11e 100644 +--- a/DrmHwcTwo.cpp ++++ b/DrmHwcTwo.cpp +@@ -907,7 +907,7 @@ DrmHwcTwo::HwcDisplay::GetOrderLayersByZPos() { + + #if PLATFORM_SDK_VERSION > 29 + HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConnectionType(uint32_t *outType) { +- if (connector_->internal()) ++ if (connector_->internal() || connector_->display() == 0) + *outType = static_cast(HWC2::DisplayConnectionType::Internal); + else if (connector_->external()) + *outType = static_cast(HWC2::DisplayConnectionType::External); +-- +2.32.0 +