diff options
author | Marissa Wall <marissaw@google.com> | 2017-03-02 22:09:00 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-03-02 22:09:00 +0000 |
commit | af55de08768da96f0f356366e400382b6869f929 (patch) | |
tree | 8843218408499d52b0b23d8dcdef572d3b9ee0c2 | |
parent | 7534f7f3398d643ed8a755a231878aad9667185c (diff) | |
parent | 954c3776e61ebe04e6b98cd12045cec9700e8452 (diff) | |
download | flounder-af55de08768da96f0f356366e400382b6869f929.tar.gz |
hwc2: call hotplug on physical displays
am: 954c3776e6
Change-Id: Ifda38c0296459b4d6d8532875c82145b2ed73d91
-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; |