diff options
author | Marissa Wall <marissaw@google.com> | 2016-09-01 14:38:04 -0700 |
---|---|---|
committer | Marissa Wall <marissaw@google.com> | 2017-03-02 12:35:01 -0800 |
commit | 954c3776e61ebe04e6b98cd12045cec9700e8452 (patch) | |
tree | 8fb0528d21c915addb81b58b67651c972a3d7073 | |
parent | 7384507cad45dc3c1deb4b4f9d41a69362f664dc (diff) | |
download | flounder-954c3776e61ebe04e6b98cd12045cec9700e8452.tar.gz |
hwc2: call hotplug on physical displays
Call the hotplug callback on all physical displays. If the hotplug callback
has not been registered, store the information for when the callback has been
registered. Keep track of connection status and update it with each hotplug
event.
Test: Add "TARGET_USES_HWC2 := true" to BoardConfig.mk.
Recompile.
Run testcases: https://android-review.googlesource.com/#/q/project:
platform/frameworks/native+branch:master+topic:test-hwc2
Change-Id: I56af90482e0323e64fc86909d70f66a92c600c1d
-rw-r--r-- | hwc2/hwc2.h | 20 | ||||
-rw-r--r-- | hwc2/hwc2_callback.cpp | 25 | ||||
-rw-r--r-- | hwc2/hwc2_dev.cpp | 31 | ||||
-rw-r--r-- | hwc2/hwc2_display.cpp | 14 |
4 files changed, 84 insertions, 6 deletions
diff --git a/hwc2/hwc2.h b/hwc2/hwc2.h index 6bb500c..9bf84b6 100644 --- a/hwc2/hwc2.h +++ b/hwc2/hwc2.h @@ -20,6 +20,8 @@ #include <hardware/hwcomposer2.h> #include <unordered_map> +#include <queue> +#include <mutex> #include <adf/adf.h> #include <adfhwc/adfhwc.h> @@ -51,7 +53,15 @@ public: hwc2_callback_data_t callback_data, hwc2_function_pointer_t pointer); + void call_hotplug(hwc2_display_t dpy_id, hwc2_connection_t connection); + private: + std::mutex state_mutex; + + /* A queue of all the hotplug notifications that were called before the + * callback was registered */ + std::queue<std::pair<hwc2_display_t, hwc2_connection_t>> hotplug_pending; + /* All of the client callback functions and their data */ hwc2_callback_data_t hotplug_data; HWC2_PFN_HOTPLUG hotplug; @@ -66,10 +76,13 @@ private: class hwc2_display { public: hwc2_display(hwc2_display_t id, int adf_intf_fd, - const struct adf_device &adf_dev); + const struct adf_device &adf_dev, hwc2_connection_t connection); ~hwc2_display(); hwc2_display_t get_id() const { return id; } + hwc2_connection_t get_connection() const { return connection; } + + hwc2_error_t set_connection(hwc2_connection_t connection); int retrieve_display_configs(struct adf_hwc_helper *adf_helper); @@ -81,6 +94,9 @@ private: /* Identifies the display to the client */ hwc2_display_t id; + /* The display is connected to an output */ + hwc2_connection_t connection; + /* All the valid configurations for the display */ std::unordered_map<hwc2_config_t, hwc2_config> configs; @@ -103,6 +119,8 @@ public: hwc2_dev(); ~hwc2_dev(); + void hotplug(hwc2_display_t dpy_id, hwc2_connection_t connection); + hwc2_error_t register_callback(hwc2_callback_descriptor_t descriptor, hwc2_callback_data_t callback_data, hwc2_function_pointer_t pointer); diff --git a/hwc2/hwc2_callback.cpp b/hwc2/hwc2_callback.cpp index 1900b1e..041bc86 100644 --- a/hwc2/hwc2_callback.cpp +++ b/hwc2/hwc2_callback.cpp @@ -19,7 +19,9 @@ #include "hwc2.h" hwc2_callback::hwc2_callback() - : hotplug_data(nullptr), + : state_mutex(), + hotplug_pending(), + hotplug_data(nullptr), hotplug(nullptr), refresh_data(nullptr), refresh(nullptr), @@ -30,6 +32,8 @@ hwc2_error_t hwc2_callback::register_callback( hwc2_callback_descriptor_t descriptor, hwc2_callback_data_t callback_data, hwc2_function_pointer_t pointer) { + std::lock_guard<std::mutex> lock(state_mutex); + switch (descriptor) { case HWC2_CALLBACK_HOTPLUG: hotplug = (HWC2_PFN_HOTPLUG) pointer; @@ -48,5 +52,24 @@ hwc2_error_t hwc2_callback::register_callback( return HWC2_ERROR_BAD_PARAMETER; } + if (descriptor == HWC2_CALLBACK_HOTPLUG && hotplug) { + while (!hotplug_pending.empty()) { + hotplug(hotplug_data, std::get<0>(hotplug_pending.front()), + std::get<1>(hotplug_pending.front())); + hotplug_pending.pop(); + } + } + return HWC2_ERROR_NONE; } + +void hwc2_callback::call_hotplug(hwc2_display_t dpy_id, + hwc2_connection_t connection) +{ + std::lock_guard<std::mutex> lock(state_mutex); + + if (hotplug) + hotplug(hotplug_data, dpy_id, connection); + else + hotplug_pending.push(std::make_pair(dpy_id, connection)); +} diff --git a/hwc2/hwc2_dev.cpp b/hwc2/hwc2_dev.cpp index 6754087..3123679 100644 --- a/hwc2/hwc2_dev.cpp +++ b/hwc2/hwc2_dev.cpp @@ -27,9 +27,12 @@ static void hwc2_vsync(void* /*data*/, int /*dpy_id*/, uint64_t /*timestamp*/) return; } -static void hwc2_hotplug(void* /*data*/, int /*dpy_id*/, bool /*connected*/) +static void hwc2_hotplug(void *data, int dpy_id, bool connected) { - return; + hwc2_dev *dev = static_cast<hwc2_dev *>(data); + dev->hotplug(static_cast<hwc2_display_t>(dpy_id), + (connected)? HWC2_CONNECTION_CONNECTED: + HWC2_CONNECTION_DISCONNECTED); } static void hwc2_custom_event(void* /*data*/, int /*dpy_id*/, @@ -56,6 +59,22 @@ hwc2_dev::~hwc2_dev() hwc2_display::reset_ids(); } +void hwc2_dev::hotplug(hwc2_display_t dpy_id, hwc2_connection_t connection) +{ + auto it = displays.find(dpy_id); + if (it == displays.end()) { + ALOGW("dpy %" PRIu64 ": invalid display handle preventing hotplug" + " callback", dpy_id); + return; + } + + hwc2_error_t ret = it->second.set_connection(connection); + if (ret != HWC2_ERROR_NONE) + return; + + callback_handler.call_hotplug(dpy_id, connection); +} + hwc2_error_t hwc2_dev::register_callback(hwc2_callback_descriptor_t descriptor, hwc2_callback_data_t callback_data, hwc2_function_pointer_t pointer) { @@ -109,6 +128,10 @@ int hwc2_dev::open_adf_device() } } + for (auto &dpy: displays) + callback_handler.call_hotplug(dpy.second.get_id(), + dpy.second.get_connection()); + free(dev_ids); return 0; @@ -148,7 +171,9 @@ int hwc2_dev::open_adf_display(adf_id_t adf_id) { hwc2_display_t dpy_id = hwc2_display::get_next_id(); displays.emplace(std::piecewise_construct, std::forward_as_tuple(dpy_id), - std::forward_as_tuple(dpy_id, intf_fd, adf_dev)); + std::forward_as_tuple(dpy_id, intf_fd, adf_dev, + (intf.hotplug_detect)? HWC2_CONNECTION_CONNECTED: + HWC2_CONNECTION_DISCONNECTED)); adf_free_interface_data(&intf); diff --git a/hwc2/hwc2_display.cpp b/hwc2/hwc2_display.cpp index e25eded..b68d251 100644 --- a/hwc2/hwc2_display.cpp +++ b/hwc2/hwc2_display.cpp @@ -25,8 +25,9 @@ uint64_t hwc2_display::display_cnt = 0; hwc2_display::hwc2_display(hwc2_display_t id, int adf_intf_fd, - const struct adf_device &adf_dev) + const struct adf_device &adf_dev, hwc2_connection_t connection) : id(id), + connection(connection), configs(), active_config(0), adf_intf_fd(adf_intf_fd), @@ -38,6 +39,17 @@ hwc2_display::~hwc2_display() adf_device_close(&adf_dev); } +hwc2_error_t hwc2_display::set_connection(hwc2_connection_t connection) +{ + if (connection == HWC2_CONNECTION_INVALID) { + ALOGE("dpy %" PRIu64 ": invalid connection", id); + return HWC2_ERROR_BAD_PARAMETER; + } + + this->connection = connection; + return HWC2_ERROR_NONE; +} + int hwc2_display::retrieve_display_configs(struct adf_hwc_helper *adf_helper) { size_t num_configs = 0; |