Snap for 8120673 from f1ac4dacd2e09aa787e85fe948f679d78d534a35 to tm-release
Change-Id: I21180958365a39192d96e9422d14e8c37bb71fa0
diff --git a/minui/events.cpp b/minui/events.cpp
index 863ac74..b307a49 100644
--- a/minui/events.cpp
+++ b/minui/events.cpp
@@ -267,6 +267,35 @@
return -1;
}
+int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb) {
+ // Use unsigned long to match ioctl's parameter type.
+ unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
+ unsigned long sw_bits[BITS_TO_LONGS(SW_MAX)]; // NOLINT
+
+ for (size_t i = 0; i < g_ev_dev_count; ++i) {
+ memset(ev_bits, 0, sizeof(ev_bits));
+ memset(sw_bits, 0, sizeof(sw_bits));
+
+ if (ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1) {
+ continue;
+ }
+ if (!test_bit(EV_SW, ev_bits)) {
+ continue;
+ }
+ if (ioctl(ev_fdinfo[i].fd, EVIOCGSW(sizeof(sw_bits)), sw_bits) == -1) {
+ continue;
+ }
+
+ for (int code = 0; code <= SW_MAX; code++) {
+ if (test_bit(code, sw_bits)) {
+ set_sw_cb(code, 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
int ev_sync_key_state(const ev_set_key_callback& set_key_cb) {
// Use unsigned long to match ioctl's parameter type.
unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)]; // NOLINT
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index 370b4cf..b24c2b1 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -495,6 +495,10 @@
gr_backend->Blank(blank);
}
+void gr_fb_blank(bool blank, int index) {
+ gr_backend->Blank(blank, static_cast<MinuiBackend::DrmConnector>(index));
+}
+
void gr_rotate(GRRotation rot) {
rotation = rot;
}
diff --git a/minui/graphics.h b/minui/graphics.h
index 3c45a40..5408c93 100644
--- a/minui/graphics.h
+++ b/minui/graphics.h
@@ -21,6 +21,12 @@
class MinuiBackend {
public:
+ enum DrmConnector {
+ DRM_MAIN = 0,
+ DRM_SEC,
+ DRM_MAX,
+ };
+
// Initializes the backend and returns a GRSurface* to draw into.
virtual GRSurface* Init() = 0;
@@ -28,9 +34,12 @@
// be displayed, and returns a new drawing surface.
virtual GRSurface* Flip() = 0;
- // Blank (or unblank) the screen.
+ // Blank (or unblank) the default screen.
virtual void Blank(bool) = 0;
+ // Blank (or unblank) the specific screen.
+ virtual void Blank(bool blank, DrmConnector index) = 0;
+
// Device cleanup when drawing is done.
virtual ~MinuiBackend() {};
};
diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp
index 9d31ff7..c557022 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -153,22 +153,50 @@
}
bool MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc,
- const std::unique_ptr<GRSurfaceDrm>& surface) {
+ const std::unique_ptr<GRSurfaceDrm>& surface,
+ uint32_t* connector_id) {
if (drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y
- &main_monitor_connector->connector_id,
- 1, // connector_count
- &main_monitor_crtc->mode) != 0) {
- perror("Failed to drmModeSetCrtc");
+ connector_id, 1, // connector_count
+ &crtc->mode) != 0) {
+ fprintf(stderr, "Failed to drmModeSetCrtc(%d)\n", *connector_id);
return false;
}
+
return true;
}
void MinuiBackendDrm::Blank(bool blank) {
+ Blank(blank, DRM_MAIN);
+}
+
+void MinuiBackendDrm::Blank(bool blank, DrmConnector index) {
+ const auto* drmInterface = &drm[DRM_MAIN];
+
+ switch (index) {
+ case DRM_MAIN:
+ drmInterface = &drm[DRM_MAIN];
+ break;
+ case DRM_SEC:
+ drmInterface = &drm[DRM_SEC];
+ break;
+ default:
+ fprintf(stderr, "Invalid index: %d\n", index);
+ return;
+ }
+
+ if (!drmInterface->monitor_connector) {
+ fprintf(stderr, "Unsupported. index = %d\n", index);
+ return;
+ }
+
if (blank) {
- DrmDisableCrtc(drm_fd, main_monitor_crtc);
+ DrmDisableCrtc(drm_fd, drmInterface->monitor_crtc);
} else {
- DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]);
+ DrmEnableCrtc(drm_fd, drmInterface->monitor_crtc,
+ drmInterface->GRSurfaceDrms[drmInterface->current_buffer],
+ &drmInterface->monitor_connector->connector_id);
+
+ active_display = index;
}
}
@@ -210,18 +238,21 @@
return nullptr;
}
-static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) {
+std::vector<drmModeConnector*> find_used_connector_by_type(int fd, drmModeRes* resources,
+ unsigned type) {
+ std::vector<drmModeConnector*> drmConnectors;
for (int i = 0; i < resources->count_connectors; i++) {
drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
if (connector) {
if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) &&
(connector->count_modes > 0)) {
- return connector;
+ drmConnectors.push_back(connector);
+ } else {
+ drmModeFreeConnector(connector);
}
- drmModeFreeConnector(connector);
}
}
- return nullptr;
+ return drmConnectors;
}
static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) {
@@ -239,8 +270,7 @@
return nullptr;
}
-drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources,
- uint32_t* mode_index) {
+bool MinuiBackendDrm::FindAndSetMonitor(int fd, drmModeRes* resources) {
/* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
static constexpr unsigned kConnectorPriority[] = {
DRM_MODE_CONNECTOR_LVDS,
@@ -248,37 +278,41 @@
DRM_MODE_CONNECTOR_DSI,
};
- drmModeConnector* main_monitor_connector = nullptr;
- unsigned i = 0;
- do {
- main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
- i++;
- } while (!main_monitor_connector && i < arraysize(kConnectorPriority));
-
- /* If we didn't find a connector, grab the first one that is connected. */
- if (!main_monitor_connector) {
- main_monitor_connector = find_first_connected_connector(fd, resources);
- }
-
- /* If we still didn't find a connector, give up and return. */
- if (!main_monitor_connector) return nullptr;
-
- for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
- printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes,
- main_monitor_connector->modes[modes].hdisplay,
- main_monitor_connector->modes[modes].vdisplay,
- main_monitor_connector->modes[modes].vrefresh);
- }
- *mode_index = 0;
- for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
- if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
- printf("Choosing display mode #%d\n", modes);
- *mode_index = modes;
- break;
+ std::vector<drmModeConnector*> drmConnectors;
+ for (int i = 0; i < arraysize(kConnectorPriority) && drmConnectors.size() < DRM_MAX; i++) {
+ auto connectors = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
+ for (auto connector : connectors) {
+ drmConnectors.push_back(connector);
+ if (drmConnectors.size() >= DRM_MAX) break;
}
}
- return main_monitor_connector;
+ /* If we didn't find a connector, grab the first one that is connected. */
+ if (drmConnectors.empty()) {
+ drmModeConnector* connector = find_first_connected_connector(fd, resources);
+ if (connector) {
+ drmConnectors.push_back(connector);
+ }
+ }
+
+ for (int drm_index = 0; drm_index < drmConnectors.size(); drm_index++) {
+ drm[drm_index].monitor_connector = drmConnectors[drm_index];
+
+ drm[drm_index].selected_mode = 0;
+ for (int modes = 0; modes < drmConnectors[drm_index]->count_modes; modes++) {
+ printf("Display Mode %d resolution: %d x %d @ %d FPS\n", modes,
+ drmConnectors[drm_index]->modes[modes].hdisplay,
+ drmConnectors[drm_index]->modes[modes].vdisplay,
+ drmConnectors[drm_index]->modes[modes].vrefresh);
+ if (drmConnectors[drm_index]->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
+ printf("Choosing display mode #%d\n", modes);
+ drm[drm_index].selected_mode = modes;
+ break;
+ }
+ }
+ }
+
+ return drmConnectors.size() > 0;
}
void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
@@ -329,46 +363,49 @@
return nullptr;
}
- uint32_t selected_mode;
- main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode);
- if (!main_monitor_connector) {
- fprintf(stderr, "Failed to find main_monitor_connector\n");
+ if (!FindAndSetMonitor(drm_fd, res)) {
+ fprintf(stderr, "Failed to find main monitor_connector\n");
drmModeFreeResources(res);
- close(drm_fd);
return nullptr;
}
- main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
- if (!main_monitor_crtc) {
- fprintf(stderr, "Failed to find main_monitor_crtc\n");
- drmModeFreeResources(res);
- close(drm_fd);
- return nullptr;
+ for (int i = 0; i < DRM_MAX; i++) {
+ if (drm[i].monitor_connector) {
+ drm[i].monitor_crtc = find_crtc_for_connector(drm_fd, res, drm[i].monitor_connector);
+ if (!drm[i].monitor_crtc) {
+ fprintf(stderr, "Failed to find monitor_crtc, drm index=%d\n", i);
+ drmModeFreeResources(res);
+ return nullptr;
+ }
+
+ drm[i].monitor_crtc->mode = drm[i].monitor_connector->modes[drm[i].selected_mode];
+
+ int width = drm[i].monitor_crtc->mode.hdisplay;
+ int height = drm[i].monitor_crtc->mode.vdisplay;
+
+ drm[i].GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height);
+ drm[i].GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height);
+ if (!drm[i].GRSurfaceDrms[0] || !drm[i].GRSurfaceDrms[1]) {
+ fprintf(stderr, "Failed to create GRSurfaceDrm, drm index=%d\n", i);
+ drmModeFreeResources(res);
+ return nullptr;
+ }
+
+ drm[i].current_buffer = 0;
+ }
}
- DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
-
- main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
-
- int width = main_monitor_crtc->mode.hdisplay;
- int height = main_monitor_crtc->mode.vdisplay;
+ DisableNonMainCrtcs(drm_fd, res, drm[DRM_MAIN].monitor_crtc);
drmModeFreeResources(res);
- GRSurfaceDrms[0] = GRSurfaceDrm::Create(drm_fd, width, height);
- GRSurfaceDrms[1] = GRSurfaceDrm::Create(drm_fd, width, height);
- if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
- return nullptr;
- }
-
- current_buffer = 0;
-
// We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
- if (!DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1])) {
+ if (!DrmEnableCrtc(drm_fd, drm[DRM_MAIN].monitor_crtc, drm[DRM_MAIN].GRSurfaceDrms[1],
+ &drm[DRM_MAIN].monitor_connector->connector_id)) {
return nullptr;
}
- return GRSurfaceDrms[0].get();
+ return drm[DRM_MAIN].GRSurfaceDrms[0].get();
}
static void page_flip_complete(__unused int fd,
@@ -380,10 +417,19 @@
}
GRSurface* MinuiBackendDrm::Flip() {
+ GRSurface* surface = NULL;
+ DrmInterface* current_drm = &drm[active_display];
bool ongoing_flip = true;
- if (drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, GRSurfaceDrms[current_buffer]->fb_id,
+
+ if (!current_drm->monitor_connector) {
+ fprintf(stderr, "Unsupported. active_display = %d\n", active_display);
+ return nullptr;
+ }
+
+ if (drmModePageFlip(drm_fd, current_drm->monitor_crtc->crtc_id,
+ current_drm->GRSurfaceDrms[current_drm->current_buffer]->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip) != 0) {
- perror("Failed to drmModePageFlip");
+ fprintf(stderr, "Failed to drmModePageFlip, active_display=%d", active_display);
return nullptr;
}
@@ -409,14 +455,19 @@
}
}
- current_buffer = 1 - current_buffer;
- return GRSurfaceDrms[current_buffer].get();
+ current_drm->current_buffer = 1 - current_drm->current_buffer;
+ surface = current_drm->GRSurfaceDrms[current_drm->current_buffer].get();
+ return surface;
}
MinuiBackendDrm::~MinuiBackendDrm() {
- DrmDisableCrtc(drm_fd, main_monitor_crtc);
- drmModeFreeCrtc(main_monitor_crtc);
- drmModeFreeConnector(main_monitor_connector);
+ for (int i = 0; i < DRM_MAX; i++) {
+ if (drm[i].monitor_connector) {
+ DrmDisableCrtc(drm_fd, drm[i].monitor_crtc);
+ drmModeFreeCrtc(drm[i].monitor_crtc);
+ drmModeFreeConnector(drm[i].monitor_connector);
+ }
+ }
close(drm_fd);
drm_fd = -1;
}
diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h
index 57ba39b..fe3beaf 100644
--- a/minui/graphics_drm.h
+++ b/minui/graphics_drm.h
@@ -59,16 +59,23 @@
GRSurface* Init() override;
GRSurface* Flip() override;
void Blank(bool) override;
+ void Blank(bool blank, DrmConnector index) override;
private:
void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc);
- bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface);
+ bool DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, const std::unique_ptr<GRSurfaceDrm>& surface,
+ uint32_t* conntcors);
void DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc);
- drmModeConnector* FindMainMonitor(int fd, drmModeRes* resources, uint32_t* mode_index);
+ bool FindAndSetMonitor(int fd, drmModeRes* resources);
- std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
- int current_buffer{ 0 };
- drmModeCrtc* main_monitor_crtc{ nullptr };
- drmModeConnector* main_monitor_connector{ nullptr };
+ struct DrmInterface {
+ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrms[2];
+ int current_buffer{ 0 };
+ drmModeCrtc* monitor_crtc{ nullptr };
+ drmModeConnector* monitor_connector{ nullptr };
+ uint32_t selected_mode{ 0 };
+ } drm[DRM_MAX];
+
int drm_fd{ -1 };
+ DrmConnector active_display = DRM_MAIN;
};
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 0d0fabc..1cb0c0a 100644
--- a/minui/graphics_fbdev.cpp
+++ b/minui/graphics_fbdev.cpp
@@ -43,6 +43,10 @@
if (ret < 0) perror("ioctl(): blank");
}
+void MinuiBackendFbdev::Blank(bool blank, DrmConnector index) {
+ fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index);
+}
+
void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) {
if (n > 1 || !double_buffered) return;
diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h
index 596ba74..7e193c4 100644
--- a/minui/graphics_fbdev.h
+++ b/minui/graphics_fbdev.h
@@ -56,6 +56,7 @@
GRSurface* Init() override;
GRSurface* Flip() override;
void Blank(bool) override;
+ void Blank(bool blank, DrmConnector index) override;
private:
void SetDisplayedFramebuffer(size_t n);
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index b9992c8..f9be82f 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -128,6 +128,7 @@
void gr_flip();
void gr_fb_blank(bool blank);
+void gr_fb_blank(bool blank, int index);
// Clears entire surface to current color.
void gr_clear();
@@ -162,6 +163,7 @@
using ev_callback = std::function<int(int fd, uint32_t epevents)>;
using ev_set_key_callback = std::function<int(int code, int value)>;
+using ev_set_sw_callback = std::function<int(int code, int value)>;
int ev_init(ev_callback input_cb, bool allow_touch_inputs = false);
void ev_exit();
@@ -169,6 +171,7 @@
void ev_iterate_available_keys(const std::function<void(int)>& f);
void ev_iterate_touch_inputs(const std::function<void(int)>& action);
int ev_sync_key_state(const ev_set_key_callback& set_key_cb);
+int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb);
// 'timeout' has the same semantics as poll(2).
// 0 : don't block