summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarissa Wall <marissaw@google.com>2017-03-02 22:09:00 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-03-02 22:09:00 +0000
commitaf55de08768da96f0f356366e400382b6869f929 (patch)
tree8843218408499d52b0b23d8dcdef572d3b9ee0c2
parent7534f7f3398d643ed8a755a231878aad9667185c (diff)
parent954c3776e61ebe04e6b98cd12045cec9700e8452 (diff)
downloadflounder-af55de08768da96f0f356366e400382b6869f929.tar.gz
hwc2: call hotplug on physical displays
am: 954c3776e6 Change-Id: Ifda38c0296459b4d6d8532875c82145b2ed73d91
-rw-r--r--hwc2/hwc2.h20
-rw-r--r--hwc2/hwc2_callback.cpp25
-rw-r--r--hwc2/hwc2_dev.cpp31
-rw-r--r--hwc2/hwc2_display.cpp14
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;