diff options
author | Andreas Grois <andi@grois.info> | 2018-03-09 21:36:10 +0100 |
---|---|---|
committer | Andreas Grois <andi@grois.info> | 2018-03-09 21:36:10 +0100 |
commit | 3b734f0d6b9e28c1f2c4ae54e3f46e573e02f4a5 (patch) | |
tree | 444542870666e41594e7b493f625ade81d64f885 /glfw-3.2.1/src/mir_window.c |
Initial Commit
Diffstat (limited to 'glfw-3.2.1/src/mir_window.c')
-rw-r--r-- | glfw-3.2.1/src/mir_window.c | 848 |
1 files changed, 848 insertions, 0 deletions
diff --git a/glfw-3.2.1/src/mir_window.c b/glfw-3.2.1/src/mir_window.c new file mode 100644 index 0000000..411f906 --- /dev/null +++ b/glfw-3.2.1/src/mir_window.c @@ -0,0 +1,848 @@ +//======================================================================== +// GLFW 3.2 Mir - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include <linux/input.h> +#include <stdlib.h> +#include <string.h> + + +typedef struct EventNode +{ + TAILQ_ENTRY(EventNode) entries; + const MirEvent* event; + _GLFWwindow* window; +} EventNode; + +static void deleteNode(EventQueue* queue, EventNode* node) +{ + mir_event_unref(node->event); + free(node); +} + +static GLFWbool emptyEventQueue(EventQueue* queue) +{ + return queue->head.tqh_first == NULL; +} + +// TODO The mir_event_ref is not supposed to be used but ... its needed +// in this case. Need to wait until we can read from an FD set up by mir +// for single threaded event handling. +static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context) +{ + EventNode* new_node = calloc(1, sizeof(EventNode)); + new_node->event = mir_event_ref(event); + new_node->window = context; + + return new_node; +} + +static void enqueueEvent(const MirEvent* 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; +} + +/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out + the best pixel format! +*/ +static MirPixelFormat findValidPixelFormat(void) +{ + unsigned int i, validFormats, mirPixelFormats = 32; + MirPixelFormat formats[mir_pixel_formats]; + + mir_connection_get_available_surface_formats(_glfw.mir.connection, formats, + mirPixelFormats, &validFormats); + + for (i = 0; i < validFormats; i++) + { + if (formats[i] == mir_pixel_format_abgr_8888 || + formats[i] == mir_pixel_format_xbgr_8888 || + formats[i] == mir_pixel_format_argb_8888 || + formats[i] == mir_pixel_format_xrgb_8888) + { + return formats[i]; + } + } + + return mir_pixel_format_invalid; +} + +static int mirModToGLFWMod(uint32_t mods) +{ + int publicMods = 0x0; + + if (mods & mir_input_event_modifier_alt) + publicMods |= GLFW_MOD_ALT; + else if (mods & mir_input_event_modifier_shift) + publicMods |= GLFW_MOD_SHIFT; + else if (mods & mir_input_event_modifier_ctrl) + publicMods |= GLFW_MOD_CONTROL; + else if (mods & mir_input_event_modifier_meta) + publicMods |= GLFW_MOD_SUPER; + + return publicMods; +} + +static int toGLFWKeyCode(uint32_t key) +{ + if (key < sizeof(_glfw.mir.publicKeys) / sizeof(_glfw.mir.publicKeys[0])) + return _glfw.mir.publicKeys[key]; + + return GLFW_KEY_UNKNOWN; +} + +static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window) +{ + const int action = mir_keyboard_event_action (key_event); + const int scan_code = mir_keyboard_event_scan_code(key_event); + const int key_code = mir_keyboard_event_key_code (key_event); + const int modifiers = mir_keyboard_event_modifiers(key_event); + + const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS; + const int mods = mirModToGLFWMod(modifiers); + const long text = _glfwKeySym2Unicode(key_code); + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + + _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods); + + if (text != -1) + _glfwInputChar(window, text, mods, plain); +} + +static void handlePointerButton(_GLFWwindow* window, + int pressed, + const MirPointerEvent* pointer_event) +{ + int mods = mir_pointer_event_modifiers(pointer_event); + const int publicMods = mirModToGLFWMod(mods); + MirPointerButton button = mir_pointer_button_primary; + static uint32_t oldButtonStates = 0; + uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); + int publicButton = GLFW_MOUSE_BUTTON_LEFT; + + // XOR our old button states our new states to figure out what was added or removed + button = newButtonStates ^ oldButtonStates; + + switch (button) + { + case mir_pointer_button_primary: + publicButton = GLFW_MOUSE_BUTTON_LEFT; + break; + case mir_pointer_button_secondary: + publicButton = GLFW_MOUSE_BUTTON_RIGHT; + break; + case mir_pointer_button_tertiary: + publicButton = GLFW_MOUSE_BUTTON_MIDDLE; + break; + case mir_pointer_button_forward: + // FIXME What is the forward button? + publicButton = GLFW_MOUSE_BUTTON_4; + break; + case mir_pointer_button_back: + // FIXME What is the back button? + publicButton = GLFW_MOUSE_BUTTON_5; + break; + default: + break; + } + + oldButtonStates = newButtonStates; + + _glfwInputMouseClick(window, publicButton, pressed, publicMods); +} + +static void handlePointerMotion(_GLFWwindow* window, + const MirPointerEvent* pointer_event) +{ + int current_x = window->virtualCursorPosX; + int current_y = window->virtualCursorPosY; + int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x); + int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y); + int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll); + int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); + + _glfwInputCursorPos(window, x, y); + if (dx != 0 || dy != 0) + _glfwInputScroll(window, dx, dy); +} + +static void handlePointerEvent(const MirPointerEvent* pointer_event, + _GLFWwindow* window) +{ + int action = mir_pointer_event_action(pointer_event); + + switch (action) + { + case mir_pointer_action_button_down: + handlePointerButton(window, GLFW_PRESS, pointer_event); + break; + case mir_pointer_action_button_up: + handlePointerButton(window, GLFW_RELEASE, pointer_event); + break; + case mir_pointer_action_motion: + handlePointerMotion(window, pointer_event); + break; + case mir_pointer_action_enter: + case mir_pointer_action_leave: + break; + default: + break; + + } +} + +static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window) +{ + int type = mir_input_event_get_type(input_event); + + switch (type) + { + case mir_input_event_type_key: + handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window); + break; + case mir_input_event_type_pointer: + handlePointerEvent(mir_input_event_get_pointer_event(input_event), window); + break; + default: + break; + } +} + +static void handleEvent(const MirEvent* event, _GLFWwindow* window) +{ + int type = mir_event_get_type(event); + + switch (type) + { + case mir_event_type_input: + handleInput(mir_event_get_input_event(event), window); + break; + default: + break; + } +} + +static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context) +{ + enqueueEvent(event, context); +} + +static GLFWbool createSurface(_GLFWwindow* window) +{ + MirSurfaceSpec* spec; + MirBufferUsage buffer_usage = mir_buffer_usage_hardware; + MirPixelFormat pixel_format = findValidPixelFormat(); + + if (pixel_format == mir_pixel_format_invalid) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to find a correct pixel format"); + return GLFW_FALSE; + } + + spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection, + window->mir.width, + window->mir.height, + pixel_format); + + mir_surface_spec_set_buffer_usage(spec, buffer_usage); + mir_surface_spec_set_name(spec, "MirSurface"); + + window->mir.surface = mir_surface_create_sync(spec); + mir_surface_spec_release(spec); + + if (!mir_surface_is_valid(window->mir.surface)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to create surface: %s", + mir_surface_get_error_message(window->mir.surface)); + + return GLFW_FALSE; + } + + mir_surface_set_event_handler(window->mir.surface, addNewEvent, window); + + return GLFW_TRUE; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +void _glfwInitEventQueueMir(EventQueue* queue) +{ + TAILQ_INIT(&queue->head); +} + +void _glfwDeleteEventQueueMir(EventQueue* queue) +{ + if (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; + } + + free(queue); + } +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwPlatformCreateWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) +{ + if (window->monitor) + { + GLFWvidmode mode; + _glfwPlatformGetVideoMode(window->monitor, &mode); + + mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen); + + if (wndconfig->width > mode.width || wndconfig->height > mode.height) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Requested surface size too large: %ix%i", + wndconfig->width, wndconfig->height); + + return GLFW_FALSE; + } + } + + window->mir.width = wndconfig->width; + window->mir.height = wndconfig->height; + + if (!createSurface(window)) + return GLFW_FALSE; + + window->mir.window = mir_buffer_stream_get_egl_native_window( + mir_surface_get_buffer_stream(window->mir.surface)); + + if (ctxconfig->client != GLFW_NO_API) + { + if (!_glfwInitEGL()) + return GLFW_FALSE; + if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + +void _glfwPlatformDestroyWindow(_GLFWwindow* window) +{ + if (mir_surface_is_valid(window->mir.surface)) + { + mir_surface_release_sync(window->mir.surface); + window->mir.surface = NULL; + } + + if (window->context.destroy) + window->context.destroy(window); +} + +void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) +{ + MirSurfaceSpec* spec; + const char* e_title = title ? title : ""; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_name(spec, e_title); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); +} + +void _glfwPlatformSetWindowIcon(_GLFWwindow* window, + int count, const GLFWimage* images) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) +{ + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_width (spec, width); + mir_surface_spec_set_height(spec, height); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); +} + +void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->mir.width; + if (height) + *height = window->mir.height; +} + +void _glfwPlatformIconifyWindow(_GLFWwindow* window) +{ + mir_surface_set_state(window->mir.surface, mir_surface_state_minimized); +} + +void _glfwPlatformRestoreWindow(_GLFWwindow* window) +{ + mir_surface_set_state(window->mir.surface, mir_surface_state_restored); +} + +void _glfwPlatformMaximizeWindow(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformHideWindow(_GLFWwindow* window) +{ + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_state(spec, mir_surface_state_hidden); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); +} + +void _glfwPlatformShowWindow(_GLFWwindow* window) +{ + MirSurfaceSpec* spec; + + spec = mir_connection_create_spec_for_changes(_glfw.mir.connection); + mir_surface_spec_set_state(spec, mir_surface_state_restored); + + mir_surface_apply_spec(window->mir.surface, spec); + mir_surface_spec_release(spec); +} + +void _glfwPlatformFocusWindow(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + return GLFW_FALSE; +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + return GLFW_FALSE; +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed; +} + +int _glfwPlatformWindowMaximized(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + return GLFW_FALSE; +} + +void _glfwPlatformPollEvents(void) +{ + EventNode* node = NULL; + + while ((node = dequeueEvent(_glfw.mir.event_queue))) + { + handleEvent(node->event, node->window); + deleteNode(_glfw.mir.event_queue, node); + } +} + +void _glfwPlatformWaitEvents(void) +{ + 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 _glfwPlatformWaitEventsTimeout(double timeout) +{ + pthread_mutex_lock(&_glfw.mir.event_mutex); + + if (emptyEventQueue(_glfw.mir.event_queue)) + { + struct timespec time; + clock_gettime(CLOCK_REALTIME, &time); + time.tv_sec += (long) timeout; + time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9); + pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time); + } + + pthread_mutex_unlock(&_glfw.mir.event_mutex); + + _glfwPlatformPollEvents(); +} + +void _glfwPlatformPostEmptyEvent(void) +{ +} + +void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->mir.width; + if (height) + *height = window->mir.height; +} + +// FIXME implement +int _glfwPlatformCreateCursor(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) +{ + MirBufferStream* stream; + MirPixelFormat pixel_format = findValidPixelFormat(); + + int i_w = image->width; + int i_h = image->height; + + if (pixel_format == mir_pixel_format_invalid) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unable to find a correct pixel format"); + return GLFW_FALSE; + } + + stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection, + i_w, i_h, + pixel_format, + mir_buffer_usage_software); + + cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot); + + char* dest; + unsigned char *pixels; + int i, r_stride, bytes_per_pixel, bytes_per_row; + + MirGraphicsRegion region; + mir_buffer_stream_get_graphics_region(stream, ®ion); + + // FIXME Figure this out based on the current_pf + bytes_per_pixel = 4; + bytes_per_row = bytes_per_pixel * i_w; + + dest = region.vaddr; + pixels = image->pixels; + + r_stride = region.stride; + + for (i = 0; i < i_h; i++) + { + memcpy(dest, pixels, bytes_per_row); + dest += r_stride; + pixels += r_stride; + } + + cursor->mir.custom_cursor = stream; + + return GLFW_TRUE; +} + +const char* getSystemCursorName(int shape) +{ + switch (shape) + { + case GLFW_ARROW_CURSOR: + return mir_arrow_cursor_name; + case GLFW_IBEAM_CURSOR: + return mir_caret_cursor_name; + case GLFW_CROSSHAIR_CURSOR: + return mir_crosshair_cursor_name; + case GLFW_HAND_CURSOR: + return mir_open_hand_cursor_name; + case GLFW_HRESIZE_CURSOR: + return mir_horizontal_resize_cursor_name; + case GLFW_VRESIZE_CURSOR: + return mir_vertical_resize_cursor_name; + } + + return NULL; +} + +int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) +{ + const char* cursor_name = getSystemCursorName(shape); + + if (cursor_name) + { + cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name); + cursor->mir.custom_cursor = NULL; + + return GLFW_TRUE; + } + + return GLFW_FALSE; +} + +void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) +{ + if (cursor->mir.conf) + mir_cursor_configuration_destroy(cursor->mir.conf); + if (cursor->mir.custom_cursor) + mir_buffer_stream_release_sync(cursor->mir.custom_cursor); +} + +void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) +{ + if (cursor && cursor->mir.conf) + { + mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf)); + if (cursor->mir.custom_cursor) + { + mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor); + } + } + else + { + mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf)); + } +} + +void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +const char* _glfwPlatformGetKeyName(int key, int scancode) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + return NULL; +} + +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); +} + +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported function %s", __PRETTY_FUNCTION__); + + return NULL; +} + +char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count) +{ + char** extensions; + + *count = 0; + + if (!_glfw.vk.KHR_mir_surface) + return NULL; + + extensions = calloc(2, sizeof(char*)); + extensions[0] = strdup("VK_KHR_surface"); + extensions[1] = strdup("VK_KHR_mir_surface"); + + *count = 2; + return extensions; +} + +int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) +{ + PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR = + (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR) + vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR"); + if (!vkGetPhysicalDeviceMirPresentationSupportKHR) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Mir: Vulkan instance missing VK_KHR_mir_surface extension"); + return GLFW_FALSE; + } + + return vkGetPhysicalDeviceMirPresentationSupportKHR(device, + queuefamily, + _glfw.mir.connection); +} + +VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) +{ + VkResult err; + VkMirSurfaceCreateInfoKHR sci; + PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR; + + vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR) + vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR"); + if (!vkCreateMirSurfaceKHR) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Mir: Vulkan instance missing VK_KHR_mir_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + memset(&sci, 0, sizeof(sci)); + sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR; + sci.connection = _glfw.mir.connection; + sci.mirSurface = window->mir.surface; + + err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface); + if (err) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Failed to create Vulkan surface: %s", + _glfwGetVulkanResultString(err)); + } + + return err; +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW native API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWAPI MirConnection* glfwGetMirDisplay(void) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + return _glfw.mir.connection; +} + +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + return window->mir.surface; +} + |