diff options
author | Bill Rassieur <rassb@google.com> | 2019-03-29 04:14:51 +0000 |
---|---|---|
committer | Bill Rassieur <rassb@google.com> | 2019-03-29 04:14:51 +0000 |
commit | c8f5bbabed254bb73306b247d10b988df58087e3 (patch) | |
tree | d7b95489ab5d2dce3904772e2f514faf1a2e7959 | |
parent | 92703b21b73f37369b3eb03aa09deeda32a0bee7 (diff) | |
parent | cdc57d4d7255f78072155d8a88bfc028d69616b8 (diff) | |
download | drm_hwcomposer-c8f5bbabed254bb73306b247d10b988df58087e3.tar.gz |
Merge master@5406228 into git_qt-dev-plus-aosp.
Change-Id: Ibaeaf918de950d67dcd5eb3a0633a85dbdccb460
BUG: 129345239
-rwxr-xr-x | .gitlab-ci-checkcommit.sh | 4 | ||||
-rw-r--r-- | drmconnector.cpp | 19 | ||||
-rw-r--r-- | drmconnector.h | 6 | ||||
-rw-r--r-- | drmdevice.h | 3 | ||||
-rw-r--r-- | drmdisplaycompositor.cpp | 10 | ||||
-rw-r--r-- | drmdisplaycompositor.h | 2 | ||||
-rw-r--r-- | drmeventlistener.cpp | 2 | ||||
-rw-r--r-- | drmeventlistener.h | 2 | ||||
-rw-r--r-- | drmhwctwo.cpp | 143 | ||||
-rw-r--r-- | drmhwctwo.h | 17 | ||||
-rw-r--r-- | drmplane.cpp | 2 | ||||
-rw-r--r-- | drmproperty.cpp | 47 | ||||
-rw-r--r-- | drmproperty.h | 8 | ||||
-rw-r--r-- | platform.h | 2 | ||||
-rw-r--r-- | resourcemanager.h | 6 |
15 files changed, 203 insertions, 70 deletions
diff --git a/.gitlab-ci-checkcommit.sh b/.gitlab-ci-checkcommit.sh index d76baf7..c1c524d 100755 --- a/.gitlab-ci-checkcommit.sh +++ b/.gitlab-ci-checkcommit.sh @@ -38,13 +38,13 @@ git log --pretty='%h' FETCH_HEAD..HEAD | while read h; do commit_body=$(git show -s --pretty=%b "$h") - author=$(git show -s --format='%an <%ae>') + author=$(git show -s --format='%an <%ae>' "$h") if findtag "$commit_body" "Signed-off-by" "$author"; then echoerr "Author SoB tag is missing from commit $h" exit 1 fi - committer=$(git show -s --format='%cn <%ce>') + committer=$(git show -s --format='%cn <%ce>' "$h") if findtag "$commit_body" "Signed-off-by" "$committer"; then echoerr "Committer SoB tag is missing from commit $h" exit 1 diff --git a/drmconnector.cpp b/drmconnector.cpp index 756791f..f272024 100644 --- a/drmconnector.cpp +++ b/drmconnector.cpp @@ -122,6 +122,7 @@ int DrmConnector::UpdateModes() { state_ = c->connection; + bool preferred_mode_found = false; std::vector<DrmMode> new_modes; for (int i = 0; i < c->count_modes; ++i) { bool exists = false; @@ -132,14 +133,20 @@ int DrmConnector::UpdateModes() { break; } } - if (exists) - continue; - - DrmMode m(&c->modes[i]); - m.set_id(drm_->next_mode_id()); - new_modes.push_back(m); + if (!exists) { + DrmMode m(&c->modes[i]); + m.set_id(drm_->next_mode_id()); + new_modes.push_back(m); + } + if (new_modes.back().type() & DRM_MODE_TYPE_PREFERRED) { + preferred_mode_id_ = new_modes.back().id(); + preferred_mode_found = true; + } } modes_.swap(new_modes); + if ((!preferred_mode_found) && (modes_.size() != 0)) { + preferred_mode_id_ = modes_[0].id(); + } return 0; } diff --git a/drmconnector.h b/drmconnector.h index 4f7f6a8..9c526c8 100644 --- a/drmconnector.h +++ b/drmconnector.h @@ -74,6 +74,10 @@ class DrmConnector { uint32_t mm_width() const; uint32_t mm_height() const; + uint32_t get_preferred_mode_id() const { + return preferred_mode_id_; + } + private: DrmDevice *drm_; @@ -97,6 +101,8 @@ class DrmConnector { DrmProperty writeback_out_fence_; std::vector<DrmEncoder *> possible_encoders_; + + uint32_t preferred_mode_id_; }; } // namespace android diff --git a/drmdevice.h b/drmdevice.h index da1b961..91dd38b 100644 --- a/drmdevice.h +++ b/drmdevice.h @@ -76,6 +76,9 @@ class DrmDevice { int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id); int DestroyPropertyBlob(uint32_t blob_id); bool HandlesDisplay(int display) const; + void RegisterHotplugHandler(DrmEventHandler *handler) { + event_listener_.RegisterHotplugHandler(handler); + } private: int TryEncoderForDisplay(int display, DrmEncoder *enc); diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp index a1ccdc7..e6f6922 100644 --- a/drmdisplaycompositor.cpp +++ b/drmdisplaycompositor.cpp @@ -359,10 +359,16 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, } } - if (plane->zpos_property().id() && !plane->zpos_property().immutable()) { + if (plane->zpos_property().id() && + !plane->zpos_property().is_immutable()) { + uint64_t min_zpos = 0; + + // Ignore ret and use min_zpos as 0 by default + std::tie(std::ignore, min_zpos) = plane->zpos_property().range_min(); + ret = drmModeAtomicAddProperty(pset, plane->id(), plane->zpos_property().id(), - source_layers.front()) < 0; + source_layers.front() + min_zpos) < 0; if (ret) { ALOGE("Failed to add zpos property %d to plane %d", plane->zpos_property().id(), plane->id()); diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h index 67f6334..1005598 100644 --- a/drmdisplaycompositor.h +++ b/drmdisplaycompositor.h @@ -55,6 +55,7 @@ class DrmDisplayCompositor { int Composite(); void Dump(std::ostringstream *out) const; void Vsync(int display, int64_t timestamp); + void ClearDisplay(); std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution(); @@ -82,7 +83,6 @@ class DrmDisplayCompositor { int ApplyDpms(DrmDisplayComposition *display_comp); int DisablePlanes(DrmDisplayComposition *display_comp); - void ClearDisplay(); void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition, int status, bool writeback = false); int FlattenActiveComposition(); diff --git a/drmeventlistener.cpp b/drmeventlistener.cpp index 6aab6fb..8f655a7 100644 --- a/drmeventlistener.cpp +++ b/drmeventlistener.cpp @@ -64,7 +64,7 @@ int DrmEventListener::Init() { void DrmEventListener::RegisterHotplugHandler(DrmEventHandler *handler) { assert(!hotplug_handler_); - hotplug_handler_ = handler; + hotplug_handler_.reset(handler); } void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */, diff --git a/drmeventlistener.h b/drmeventlistener.h index d8a61a5..95672ee 100644 --- a/drmeventlistener.h +++ b/drmeventlistener.h @@ -58,7 +58,7 @@ class DrmEventListener : public Worker { int max_fd_ = -1; DrmDevice *drm_; - DrmEventHandler *hotplug_handler_ = NULL; + std::unique_ptr<DrmEventHandler> hotplug_handler_; }; } // namespace android diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp index cf4ec11..3123b29 100644 --- a/drmhwctwo.cpp +++ b/drmhwctwo.cpp @@ -57,43 +57,55 @@ DrmHwcTwo::DrmHwcTwo() { getFunction = HookDevGetFunction; } -HWC2::Error DrmHwcTwo::Init() { - int ret = resource_manager_.Init(); - if (ret) { - ALOGE("Can't initialize the resource manager %d", ret); - return HWC2::Error::NoResources; - } - - DrmDevice *drm = resource_manager_.GetDrmDevice(HWC_DISPLAY_PRIMARY); - std::shared_ptr<Importer> importer = resource_manager_.GetImporter( - HWC_DISPLAY_PRIMARY); +HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ, + HWC2::DisplayType type) { + DrmDevice *drm = resource_manager_.GetDrmDevice(displ); + std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ); if (!drm || !importer) { ALOGE("Failed to get a valid drmresource and importer"); return HWC2::Error::NoResources; } - - displays_.emplace(std::piecewise_construct, - std::forward_as_tuple(HWC_DISPLAY_PRIMARY), + displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ), std::forward_as_tuple(&resource_manager_, drm, importer, - HWC_DISPLAY_PRIMARY, - HWC2::DisplayType::Physical)); + displ, type)); - DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(HWC_DISPLAY_PRIMARY)); + DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ)); if (!crtc) { - ALOGE("Failed to get crtc for display %d", - static_cast<int>(HWC_DISPLAY_PRIMARY)); + ALOGE("Failed to get crtc for display %d", static_cast<int>(displ)); return HWC2::Error::BadDisplay; } - std::vector<DrmPlane *> display_planes; for (auto &plane : drm->planes()) { if (plane->GetCrtcSupported(*crtc)) display_planes.push_back(plane.get()); } - displays_.at(HWC_DISPLAY_PRIMARY).Init(&display_planes); + displays_.at(displ).Init(&display_planes); return HWC2::Error::None; } +HWC2::Error DrmHwcTwo::Init() { + int rv = resource_manager_.Init(); + if (rv) { + ALOGE("Can't initialize the resource manager %d", rv); + return HWC2::Error::NoResources; + } + + HWC2::Error ret = HWC2::Error::None; + for (int i = 0; i < resource_manager_.getDisplayCount(); i++) { + ret = CreateDisplay(i, HWC2::DisplayType::Physical); + if (ret != HWC2::Error::None) { + ALOGE("Failed to create display %d with error %d", i, ret); + return ret; + } + } + + auto &drmDevices = resource_manager_.getDrmDevices(); + for (auto &device : drmDevices) { + device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get())); + } + return ret; +} + template <typename... Args> static inline HWC2::Error unsupported(char const *func, Args... /*args*/) { ALOGV("Unsupported function: %s", func); @@ -132,6 +144,12 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, hwc2_function_pointer_t function) { supported(__func__); auto callback = static_cast<HWC2::Callback>(descriptor); + + if (!function) { + callbacks_.erase(callback); + return HWC2::Error::None; + } + callbacks_.emplace(callback, HwcCallback(data, function)); switch (callback) { @@ -139,6 +157,9 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(function); hotplug(data, HWC_DISPLAY_PRIMARY, static_cast<int32_t>(HWC2::Connection::Connected)); + auto &drmDevices = resource_manager_.getDrmDevices(); + for (auto &device : drmDevices) + HandleInitialHotplugState(device.get()); break; } case HWC2::Callback::Vsync: { @@ -165,6 +186,10 @@ DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager, supported(__func__); } +void DrmHwcTwo::HwcDisplay::ClearDisplay() { + compositor_.ClearDisplay(); +} + HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { supported(__func__); planner_ = Planner::CreateInstance(drm_); @@ -204,27 +229,23 @@ HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) { return HWC2::Error::BadDisplay; } - // Fetch the number of modes from the display - uint32_t num_configs; - HWC2::Error err = GetDisplayConfigs(&num_configs, NULL); - if (err != HWC2::Error::None || !num_configs) - return err; - - // Grab the first mode, we'll choose this as the active mode - // TODO: Should choose the preferred mode here - hwc2_config_t default_config; - num_configs = 1; - err = GetDisplayConfigs(&num_configs, &default_config); - if (err != HWC2::Error::None) - return err; - ret = vsync_worker_.Init(drm_, display); if (ret) { ALOGE("Failed to create event worker for d=%d %d\n", display, ret); return HWC2::Error::BadDisplay; } - return SetActiveConfig(default_config); + 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); + if (err != HWC2::Error::None || !num_configs) + return err; + + return SetActiveConfig(connector_->get_preferred_mode_id()); } HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback( @@ -617,8 +638,8 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { ALOGE("Failed to queue dpms composition on %d", ret); return HWC2::Error::BadConfig; } - if (connector_->active_mode().id() == 0) - connector_->set_active_mode(*mode); + + connector_->set_active_mode(*mode); // Setup the client layer's dimensions hwc_rect_t display_frame = {.left = 0, @@ -702,7 +723,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) { HWC2::Error DrmHwcTwo::HwcDisplay::SetVsyncEnabled(int32_t enabled) { supported(__func__); - vsync_worker_.VSyncControl(enabled); + vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled); return HWC2::Error::None; } @@ -880,6 +901,52 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { layer->SetTransform(static_cast<int32_t>(transform_)); } +void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { + auto cb = callbacks_.find(HWC2::Callback::Hotplug); + if (cb == callbacks_.end()) + return; + + auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(cb->second.func); + hotplug(cb->second.data, displayid, + (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED + : HWC2_CONNECTION_DISCONNECTED)); +} + +void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) { + for (auto &conn : drmDevice->connectors()) { + if (conn->state() != DRM_MODE_CONNECTED) + continue; + HandleDisplayHotplug(conn->display(), conn->state()); + } +} + +void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) { + for (auto &conn : drm_->connectors()) { + drmModeConnection old_state = conn->state(); + drmModeConnection cur_state = conn->UpdateModes() + ? DRM_MODE_UNKNOWNCONNECTION + : conn->state(); + + if (cur_state == old_state) + continue; + + ALOGI("%s event @%" PRIu64 " for connector %u on display %d", + cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us, + conn->id(), conn->display()); + + int display_id = conn->display(); + if (cur_state == DRM_MODE_CONNECTED) { + auto &display = hwc2_->displays_.at(display_id); + display.ChosePreferredConfig(); + } else { + auto &display = hwc2_->displays_.at(display_id); + display.ClearDisplay(); + } + + hwc2_->HandleDisplayHotplug(display_id, cur_state); + } +} + // static int DrmHwcTwo::HookDevClose(hw_device_t * /*dev*/) { unsupported(__func__); diff --git a/drmhwctwo.h b/drmhwctwo.h index d9ced9b..a71d7cc 100644 --- a/drmhwctwo.h +++ b/drmhwctwo.h @@ -143,6 +143,7 @@ class DrmHwcTwo : public hwc2_device_t { HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t func); + void ClearDisplay(); // HWC Hooks HWC2::Error AcceptDisplayChanges(); @@ -173,6 +174,7 @@ class DrmHwcTwo : public hwc2_device_t { int32_t *fences); HWC2::Error PresentDisplay(int32_t *retire_fence); HWC2::Error SetActiveConfig(hwc2_config_t config); + HWC2::Error ChosePreferredConfig(); HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence, int32_t dataspace, hwc_region_t damage); HWC2::Error SetColorMode(int32_t mode); @@ -213,6 +215,18 @@ class DrmHwcTwo : public hwc2_device_t { uint32_t frame_no_ = 0; }; + class DrmHotplugHandler : public DrmEventHandler { + public: + DrmHotplugHandler(DrmHwcTwo *hwc2, DrmDevice *drm) + : hwc2_(hwc2), drm_(drm) { + } + void HandleEvent(uint64_t timestamp_us); + + private: + DrmHwcTwo *hwc2_; + DrmDevice *drm_; + }; + static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) { return static_cast<DrmHwcTwo *>(dev); } @@ -261,6 +275,9 @@ class DrmHwcTwo : public hwc2_device_t { uint32_t GetMaxVirtualDisplayCount(); HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data, hwc2_function_pointer_t function); + HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type); + void HandleDisplayHotplug(hwc2_display_t displayid, int state); + void HandleInitialHotplugState(DrmDevice *drmDevice); ResourceManager resource_manager_; std::map<hwc2_display_t, HwcDisplay> displays_; diff --git a/drmplane.cpp b/drmplane.cpp index 35f91b4..6f1bf9b 100644 --- a/drmplane.cpp +++ b/drmplane.cpp @@ -42,7 +42,7 @@ int DrmPlane::Init() { } uint64_t type; - ret = p.value(&type); + std::tie(ret, type) = p.value(); if (ret) { ALOGE("Failed to get plane type property value"); return ret; diff --git a/drmproperty.cpp b/drmproperty.cpp index 9faa37e..3aeed13 100644 --- a/drmproperty.cpp +++ b/drmproperty.cpp @@ -70,40 +70,57 @@ std::string DrmProperty::name() const { return name_; } -int DrmProperty::value(uint64_t *value) const { - if (type_ == DRM_PROPERTY_TYPE_BLOB) { - *value = value_; - return 0; - } +std::tuple<int, uint64_t> DrmProperty::value() const { + if (type_ == DRM_PROPERTY_TYPE_BLOB) + return std::make_tuple(0, value_); if (values_.size() == 0) - return -ENOENT; + return std::make_tuple(-ENOENT, 0); switch (type_) { case DRM_PROPERTY_TYPE_INT: - *value = value_; - return 0; + return std::make_tuple(0, value_); case DRM_PROPERTY_TYPE_ENUM: if (value_ >= enums_.size()) - return -ENOENT; + return std::make_tuple(-ENOENT, 0); - *value = enums_[value_].value_; - return 0; + return std::make_tuple(0, enums_[value_].value_); case DRM_PROPERTY_TYPE_OBJECT: - *value = value_; - return 0; + return std::make_tuple(0, value_); default: - return -EINVAL; + return std::make_tuple(-EINVAL, 0); } } -bool DrmProperty::immutable() const { +bool DrmProperty::is_immutable() const { return id_ && (flags_ & DRM_MODE_PROP_IMMUTABLE); } +bool DrmProperty::is_range() const { + return id_ && (flags_ & DRM_MODE_PROP_RANGE); +} + +std::tuple<int, uint64_t> DrmProperty::range_min() const { + if (!is_range()) + return std::make_tuple(-EINVAL, 0); + if (values_.size() < 1) + return std::make_tuple(-ENOENT, 0); + + return std::make_tuple(0, values_[0]); +} + +std::tuple<int, uint64_t> DrmProperty::range_max() const { + if (!is_range()) + return std::make_tuple(-EINVAL, 0); + if (values_.size() < 2) + return std::make_tuple(-ENOENT, 0); + + return std::make_tuple(0, values_[1]); +} + std::tuple<uint64_t, int> DrmProperty::GetEnumValueWithName( std::string name) const { for (auto it : enums_) { diff --git a/drmproperty.h b/drmproperty.h index f1328fe..2d92ca1 100644 --- a/drmproperty.h +++ b/drmproperty.h @@ -45,8 +45,12 @@ class DrmProperty { uint32_t id() const; std::string name() const; - int value(uint64_t *value) const; - bool immutable() const; + std::tuple<int, uint64_t> value() const; + bool is_immutable() const; + + bool is_range() const; + std::tuple<int, uint64_t> range_min() const; + std::tuple<int, uint64_t> range_max() const; private: class DrmPropertyEnum { @@ -90,7 +90,7 @@ class Planner { ret = ValidatePlane(plane, layer.second); if (!ret) break; - if (!plane->zpos_property().immutable()) + if (!plane->zpos_property().is_immutable()) unused_planes.push_back(plane); plane = PopPlane(planes); } diff --git a/resourcemanager.h b/resourcemanager.h index 463739b..f10af45 100644 --- a/resourcemanager.h +++ b/resourcemanager.h @@ -34,6 +34,12 @@ class ResourceManager { std::shared_ptr<Importer> GetImporter(int display); const gralloc_module_t *gralloc(); DrmConnector *AvailableWritebackConnector(int display); + const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const { + return drms_; + } + int getDisplayCount() const { + return num_displays_; + } private: int AddDrmDevice(std::string path); |