aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2019-03-22 11:44:51 -0700
committerJohn Stultz <john.stultz@linaro.org>2019-03-22 11:47:04 -0700
commit077ac9bc3856cf7a775e5daa1e41ca60517c3ae1 (patch)
treed7b95489ab5d2dce3904772e2f514faf1a2e7959
parentbea3b4ca9bd3b4bc4bc920b492c401d7b55cacbc (diff)
parent2d8341e8a6e9f6dde388951c06f173aa0c18d75b (diff)
downloaddrm_hwcomposer-077ac9bc3856cf7a775e5daa1e41ca60517c3ae1.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into HEAD
Merge in freedesktop upstream changes * aosp/upstream-master: Revert "drm_hwcomposer: platformgeneric: Fix build" drm_hwcomposer: Set zpos relative to the minimum possible value drm_hwcomposer: Rename DrmProperty::immutable() drm_hwcomposer: Change return type of DrmProperty::value() to tuple drm_hwcomposer: Use proper commit for author/committer check drm_hwcomposer: platformgeneric: Fix build drm_hwcomposer: Chose preferred mode with type DRM_MODE_TYPE_PREFERRED drm_hwcomposer: Added hotplug support of the external display drm_hwcomposer: Fix VSYNC control Change-Id: Ib66a89d151ff47cb490ba82f0dae0ef3ffcfa51c Signed-off-by: John Stultz <john.stultz@linaro.org>
-rwxr-xr-x.gitlab-ci-checkcommit.sh4
-rw-r--r--drmconnector.cpp19
-rw-r--r--drmconnector.h6
-rw-r--r--drmdevice.h3
-rw-r--r--drmdisplaycompositor.cpp10
-rw-r--r--drmdisplaycompositor.h2
-rw-r--r--drmeventlistener.cpp2
-rw-r--r--drmeventlistener.h2
-rw-r--r--drmhwctwo.cpp143
-rw-r--r--drmhwctwo.h17
-rw-r--r--drmplane.cpp2
-rw-r--r--drmproperty.cpp47
-rw-r--r--drmproperty.h8
-rw-r--r--platform.h2
-rw-r--r--resourcemanager.h6
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 {
diff --git a/platform.h b/platform.h
index a58d62e..6fdece2 100644
--- a/platform.h
+++ b/platform.h
@@ -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);