From bc55f587da4ed3b22f76479a327b7d3119914c38 Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Mon, 10 Nov 2014 09:26:20 -0800 Subject: [PATCH 1/6] * Fix realloc, should be monitors, not monitors[found]; * Move found to the end of the loop, otherwise found = 1 causing index 0 to crash. * Find the modes for the monitor->modes. --- src/mir_monitor.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mir_monitor.c b/src/mir_monitor.c index 5fb73ef5d..286975d3e 100644 --- a/src/mir_monitor.c +++ b/src/mir_monitor.c @@ -51,9 +51,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) out->num_modes && out->current_mode < out->num_modes) { - found++; - - monitors[found] = realloc(monitors, sizeof(_GLFWmonitor*) * found); + monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found); monitors[found] = _glfwAllocMonitor("Unknown", out->physical_width_mm, out->physical_height_mm); @@ -62,6 +60,11 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) monitors[found]->mir.y = out->position_y; monitors[found]->mir.output_id = out->output_id; monitors[found]->mir.cur_mode = out->current_mode; + + monitors[found]->modes = _glfwPlatformGetVideoModes(monitors[found], + &monitors[found]->modeCount); + + found++; } } From 3893c693ac864f1fa6328d0553168ac02fe9366b Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Mon, 10 Nov 2014 09:42:41 -0800 Subject: [PATCH 2/6] * Create a EventQueue to store all MirEvents so we can ensure all Events come out of the same thread. As well as ensuring the threads sync up correctly when touching the Event Queue. --- src/mir_init.c | 18 +++++++ src/mir_platform.h | 18 +++++++ src/mir_window.c | 114 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 142 insertions(+), 8 deletions(-) diff --git a/src/mir_init.c b/src/mir_init.c index ab16861d7..fe02e6279 100644 --- a/src/mir_init.c +++ b/src/mir_init.c @@ -26,6 +26,7 @@ #include "internal.h" +#include ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -33,6 +34,8 @@ int _glfwPlatformInit(void) { + int error; + _glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__); if (!mir_connection_is_valid(_glfw.mir.connection)) @@ -51,6 +54,17 @@ int _glfwPlatformInit(void) _glfwInitTimer(); _glfwInitJoysticks(); + _glfw.mir.event_queue = calloc(1, sizeof(EventQueue)); + _glfwInitEventQueue(_glfw.mir.event_queue); + + error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL); + if (error) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Failed to create Event Mutex Error: %i\n", error); + return GL_FALSE; + } + return GL_TRUE; } @@ -59,6 +73,10 @@ void _glfwPlatformTerminate(void) _glfwTerminateContextAPI(); _glfwTerminateJoysticks(); + _glfwDeleteEventQueue(_glfw.mir.event_queue); + + pthread_mutex_destroy(&_glfw.mir.event_mutex); + mir_connection_release(_glfw.mir.connection); } diff --git a/src/mir_platform.h b/src/mir_platform.h index 4a3ebfb8a..60fde476e 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -33,6 +33,10 @@ #include "posix_time.h" #include "linux_joystick.h" +#include + +#include + #if defined(_GLFW_EGL) #include "egl_context.h" #else @@ -47,6 +51,12 @@ #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir +// Mir-specific Event Queue +// +typedef struct EventQueue +{ + TAILQ_HEAD(, EventNode) head; +} EventQueue; // Mir-specific per-window data // @@ -78,6 +88,10 @@ typedef struct _GLFWlibraryMir { MirConnection* connection; MirEGLNativeDisplayType display; + EventQueue* event_queue; + + pthread_mutex_t event_mutex; + pthread_cond_t event_cond; } _GLFWlibraryMir; @@ -89,4 +103,8 @@ typedef struct _GLFWcursorMir { } _GLFWcursorMir; + +extern void _glfwInitEventQueue(EventQueue* queue); +extern void _glfwDeleteEventQueue(EventQueue* queue); + #endif // _mir_platform_h_ diff --git a/src/mir_window.c b/src/mir_window.c index 0a637453f..8dd033b5b 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -28,8 +28,66 @@ #include "xkb_unicode.h" #include +#include +#include +typedef struct EventNode +{ + TAILQ_ENTRY(EventNode) entries; + MirEvent* event; + _GLFWwindow* window; +} EventNode; + +static void deleteNode(EventQueue* queue, EventNode* node) +{ + free(node->event); + free(node); +} + +static int emptyEventQueue(EventQueue* queue) +{ + return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE; +} + +static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context) +{ + EventNode* new_node = calloc(1, sizeof(EventNode)); + new_node->event = calloc(1, sizeof(MirEvent)); + new_node->window = context; + + memcpy(new_node->event, event, sizeof(MirEvent)); + return new_node; +} + +static void enqueueEvent(MirEvent const* event, _GLFWwindow* context) +{ + pthread_mutex_lock(&_glfw.mir.event_mutex); + + EventNode* new_node = newEventNode(event, context); + TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries); + + pthread_cond_signal(&_glfw.mir.event_cond); + + pthread_mutex_unlock(&_glfw.mir.event_mutex); +} + +static EventNode* dequeueEvent(EventQueue* queue) +{ + EventNode* node = NULL; + + pthread_mutex_lock(&_glfw.mir.event_mutex); + + node = queue->head.tqh_first; + + if (node) + TAILQ_REMOVE(&queue->head, node, entries); + + pthread_mutex_unlock(&_glfw.mir.event_mutex); + + return node; +} + static MirPixelFormat findValidPixelFormat(void) { unsigned int i, validFormats, size = 32; @@ -298,21 +356,26 @@ static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window) handleMouseEvent(motion, i, window); } -static void handleInput(MirSurface* surface, const MirEvent* event, void* context) +static void handleInput(MirEvent const* event, _GLFWwindow* window) { switch (event->type) { case mir_event_type_key: - handleKeyEvent(event->key, (_GLFWwindow*) context); + handleKeyEvent(event->key, window); break; case mir_event_type_motion: - handleMotionEvent(event->motion, (_GLFWwindow*) context); + handleMotionEvent(event->motion, window); break; default: break; } } +static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context) +{ + enqueueEvent(event, context); +} + static int createSurface(_GLFWwindow* window) { MirSurfaceParameters params = @@ -327,7 +390,7 @@ static int createSurface(_GLFWwindow* window) MirEventDelegate delegate = { - handleInput, + addNewEvent, window }; @@ -353,6 +416,30 @@ static int createSurface(_GLFWwindow* window) return GL_TRUE; } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +void _glfwInitEventQueue(EventQueue* queue) +{ + TAILQ_INIT(&queue->head); +} + +void _glfwDeleteEventQueue(EventQueue* queue) +{ + EventNode* node, *node_next; + node = queue->head.tqh_first; + + while (node != NULL) + { + node_next = node->entries.tqe_next; + + TAILQ_REMOVE(&queue->head, node, entries); + deleteNode(queue, node); + + node = node_next; + } +} ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -475,14 +562,25 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window) void _glfwPlatformPollEvents(void) { - // Mir does event handling in a different thread, so windows get events - // directly as they happen + EventNode* node = NULL; + + while ((node = dequeueEvent(_glfw.mir.event_queue))) + { + handleInput(node->event, node->window); + deleteNode(_glfw.mir.event_queue, node); + } } void _glfwPlatformWaitEvents(void) { - // Mir does event handling in a different thread, so windows get events - // directly as they happen + pthread_mutex_lock(&_glfw.mir.event_mutex); + + if (emptyEventQueue(_glfw.mir.event_queue)) + pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex); + + pthread_mutex_unlock(&_glfw.mir.event_mutex); + + _glfwPlatformPollEvents(); } void _glfwPlatformPostEmptyEvent(void) From cf244380bf5f118a3440d80e62e55bd26ccd30f8 Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Mon, 10 Nov 2014 09:45:29 -0800 Subject: [PATCH 3/6] * Missed two spaces ... --- src/mir_platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mir_platform.h b/src/mir_platform.h index 60fde476e..7d477e90b 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h @@ -90,8 +90,8 @@ typedef struct _GLFWlibraryMir MirEGLNativeDisplayType display; EventQueue* event_queue; - pthread_mutex_t event_mutex; - pthread_cond_t event_cond; + pthread_mutex_t event_mutex; + pthread_cond_t event_cond; } _GLFWlibraryMir; From 4ed4e06c570fdc579b8ec17cce6d8410a1fd38c6 Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Mon, 10 Nov 2014 12:12:03 -0800 Subject: [PATCH 4/6] * Fix the found issue. Found needs to be 1 for the realloc, while index should be 0. So using i for the index, and found for the count. --- src/mir_monitor.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/mir_monitor.c b/src/mir_monitor.c index 286975d3e..bdf47bdc6 100644 --- a/src/mir_monitor.c +++ b/src/mir_monitor.c @@ -51,20 +51,19 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) out->num_modes && out->current_mode < out->num_modes) { + found++; monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found); - monitors[found] = _glfwAllocMonitor("Unknown", + monitors[i] = _glfwAllocMonitor("Unknown", out->physical_width_mm, out->physical_height_mm); - monitors[found]->mir.x = out->position_x; - monitors[found]->mir.y = out->position_y; - monitors[found]->mir.output_id = out->output_id; - monitors[found]->mir.cur_mode = out->current_mode; + monitors[i]->mir.x = out->position_x; + monitors[i]->mir.y = out->position_y; + monitors[i]->mir.output_id = out->output_id; + monitors[i]->mir.cur_mode = out->current_mode; - monitors[found]->modes = _glfwPlatformGetVideoModes(monitors[found], - &monitors[found]->modeCount); - - found++; + monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i], + &monitors[i]->modeCount); } } From ab27dd2bdedae6003f88be5f2dd739c55ba5b63b Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Mon, 10 Nov 2014 12:17:21 -0800 Subject: [PATCH 5/6] * If we can't connect to the mir server make sure we check queue == NULL --- src/mir_window.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/mir_window.c b/src/mir_window.c index 8dd033b5b..530d38dec 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -427,18 +427,23 @@ void _glfwInitEventQueue(EventQueue* queue) void _glfwDeleteEventQueue(EventQueue* queue) { - EventNode* node, *node_next; - node = queue->head.tqh_first; - - while (node != NULL) + if (queue) { - node_next = node->entries.tqe_next; + EventNode* node, *node_next; + node = queue->head.tqh_first; - TAILQ_REMOVE(&queue->head, node, entries); - deleteNode(queue, node); + while (node != NULL) + { + node_next = node->entries.tqe_next; - node = node_next; + TAILQ_REMOVE(&queue->head, node, entries); + deleteNode(queue, node); + + node = node_next; + } } + + free(queue); } ////////////////////////////////////////////////////////////////////////// From e323dade6eb475e49a27e6356ee343bd452d78b8 Mon Sep 17 00:00:00 2001 From: BrandonSchaefer Date: Wed, 12 Nov 2014 09:41:12 -0800 Subject: [PATCH 6/6] * Move redundant free, to where its no longer redundant :) --- src/mir_window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mir_window.c b/src/mir_window.c index 530d38dec..9896d3ad1 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -441,9 +441,9 @@ void _glfwDeleteEventQueue(EventQueue* queue) node = node_next; } - } - free(queue); + free(queue); + } } //////////////////////////////////////////////////////////////////////////