diff --git a/ext/vulkan/vk_fwd.h b/ext/vulkan/vk_fwd.h index 59b307d492..dd5228378b 100644 --- a/ext/vulkan/vk_fwd.h +++ b/ext/vulkan/vk_fwd.h @@ -44,6 +44,7 @@ typedef struct _GstVulkanWindowPrivate GstVulkanWindowPrivate; typedef struct _GstVulkanSwapper GstVulkanSwapper; typedef struct _GstVulkanSwapperClass GstVulkanSwapperClass; +typedef struct _GstVulkanSwapperPrivate GstVulkanSwapperPrivate; typedef struct _GstVulkanMemory GstVulkanMemory; typedef struct _GstVulkanMemoryAllocator GstVulkanMemoryAllocator; diff --git a/ext/vulkan/vkswapper.c b/ext/vulkan/vkswapper.c index 7d8bf44000..21cf50ff27 100644 --- a/ext/vulkan/vkswapper.c +++ b/ext/vulkan/vkswapper.c @@ -34,6 +34,18 @@ G_DEFINE_TYPE_WITH_CODE (GstVulkanSwapper, gst_vulkan_swapper, GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkanswapper", 0, "Vulkan Swapper")); +#define RENDER_GET_LOCK(o) &(GST_VULKAN_SWAPPER (o)->priv->render_lock) +#define RENDER_LOCK(o) g_mutex_lock (RENDER_GET_LOCK(o)); +#define RENDER_UNLOCK(o) g_mutex_unlock (RENDER_GET_LOCK(o)); + +struct _GstVulkanSwapperPrivate +{ + GMutex render_lock; +}; + +static void _on_window_draw (GstVulkanWindow * window, + GstVulkanSwapper * swapper); + static gboolean _get_function_table (GstVulkanSwapper * swapper) { @@ -210,8 +222,8 @@ _vulkan_swapper_retrieve_surface_properties (GstVulkanSwapper * swapper, swapper->GetPhysicalDeviceSurfaceSupportKHR (gpu, i, (VkSurfaceDescriptionKHR *) & surface_desc, &supports_present); - if ((swapper->device->queue_family_props[i]. - queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { + if ((swapper->device-> + queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { if (supports_present) { /* found one that supports both */ graphics_queue = present_queue = i; @@ -313,6 +325,9 @@ gst_vulkan_swapper_finalize (GObject * object) gst_object_unref (swapper->device); swapper->device = NULL; + g_signal_handler_disconnect (swapper->window, swapper->draw_id); + swapper->draw_id = 0; + g_signal_handler_disconnect (swapper->window, swapper->close_id); swapper->close_id = 0; @@ -326,17 +341,27 @@ gst_vulkan_swapper_finalize (GObject * object) g_free (swapper->surf_formats); swapper->surf_formats = NULL; + gst_buffer_replace (&swapper->current_buffer, NULL); gst_caps_replace (&swapper->caps, NULL); + + g_mutex_clear (&swapper->priv->render_lock); } static void gst_vulkan_swapper_init (GstVulkanSwapper * swapper) { + swapper->priv = + G_TYPE_INSTANCE_GET_PRIVATE (swapper, GST_TYPE_VULKAN_SWAPPER, + GstVulkanSwapperPrivate); + + g_mutex_init (&swapper->priv->render_lock); } static void gst_vulkan_swapper_class_init (GstVulkanSwapperClass * klass) { + g_type_class_add_private (klass, sizeof (GstVulkanSwapperPrivate)); + G_OBJECT_CLASS (klass)->finalize = gst_vulkan_swapper_finalize; } @@ -356,6 +381,8 @@ gst_vulkan_swapper_new (GstVulkanDevice * device, GstVulkanWindow * window) swapper->close_id = g_signal_connect (swapper->window, "close", (GCallback) _on_window_close, swapper); + swapper->draw_id = g_signal_connect (swapper->window, "draw", + (GCallback) _on_window_draw, swapper); return swapper; } @@ -563,8 +590,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps, n_images_wanted = swapper->surf_props.maxImageCount; } - if (swapper-> - surf_props.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) { + if (swapper->surf_props. + supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_NONE_KHR; } else { preTransform = swapper->surf_props.currentTransform; @@ -583,8 +610,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps, "Incorrect usage flags available for the swap images"); return FALSE; } - if ((swapper->surf_props. - supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + if ((swapper-> + surf_props.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) { usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } else { @@ -900,8 +927,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx, return TRUE; } -gboolean -gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper, +static gboolean +_render_buffer_unlocked (GstVulkanSwapper * swapper, GstBuffer * buffer, GError ** error) { VkSemaphore semaphore = { 0, }; @@ -915,12 +942,20 @@ gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper, guint32 swap_idx; VkResult err; + if (!buffer) { + g_set_error (error, GST_VULKAN_ERROR, + GST_VULKAN_ERROR_INITIALIZATION_FAILED, "Invalid buffer"); + goto error; + } + if (g_atomic_int_get (&swapper->to_quit)) { g_set_error (error, GST_VULKAN_ERROR, GST_VULKAN_ERROR_DEVICE_LOST, "Output window was closed"); - return FALSE; + goto error; } + gst_buffer_replace (&swapper->current_buffer, buffer); + reacquire: err = vkCreateSemaphore (swapper->device->device, &semaphore_info, &semaphore); @@ -936,7 +971,7 @@ reacquire: vkDestroySemaphore (swapper->device->device, semaphore); if (!_swapchain_resize (swapper, error)) - return FALSE; + goto error; goto reacquire; } else if (gst_vulkan_error_to_g_error (err, error, "vkAcquireNextImageKHR") < 0) { @@ -958,11 +993,10 @@ reacquire: if (err == VK_ERROR_OUT_OF_DATE_KHR) { GST_DEBUG_OBJECT (swapper, "out of date frame submitted"); - vkDestroySemaphore (swapper->device->device, semaphore); - if (!_swapchain_resize (swapper, error)) - return FALSE; + goto error; + vkDestroySemaphore (swapper->device->device, semaphore); if (cmd_data.cmd) vkDestroyCommandBuffer (swapper->device->device, cmd_data.cmd); cmd_data.cmd = NULL; @@ -1004,3 +1038,32 @@ error: return FALSE; } } + +gboolean +gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper, + GstBuffer * buffer, GError ** error) +{ + gboolean ret; + + RENDER_LOCK (swapper); + ret = _render_buffer_unlocked (swapper, buffer, error); + RENDER_UNLOCK (swapper); + + return ret; +} + +static void +_on_window_draw (GstVulkanWindow * window, GstVulkanSwapper * swapper) +{ + GError *error = NULL; + + RENDER_LOCK (swapper); + if (!swapper->current_buffer) + return; + + /* TODO: perform some rate limiting of the number of redraw events */ + if (!_render_buffer_unlocked (swapper, swapper->current_buffer, &error)) + GST_ERROR_OBJECT (swapper, "Failed to redraw buffer %p %s", + swapper->current_buffer, error->message); + RENDER_UNLOCK (swapper); +} diff --git a/ext/vulkan/vkswapper.h b/ext/vulkan/vkswapper.h index e090b4b46a..043c0a2c0c 100644 --- a/ext/vulkan/vkswapper.h +++ b/ext/vulkan/vkswapper.h @@ -71,9 +71,13 @@ struct _GstVulkanSwapper /* */ /* runtime variables */ gint to_quit; + GstBuffer *current_buffer; /* signal handlers */ gulong close_id; + gulong draw_id; + + GstVulkanSwapperPrivate *priv; }; struct _GstVulkanSwapperClass diff --git a/ext/vulkan/vkwindow.c b/ext/vulkan/vkwindow.c index d62e79dc82..83e3b4d5d9 100644 --- a/ext/vulkan/vkwindow.c +++ b/ext/vulkan/vkwindow.c @@ -79,6 +79,7 @@ enum { SIGNAL_0, SIGNAL_CLOSE, + SIGNAL_DRAW, LAST_SIGNAL }; @@ -145,6 +146,10 @@ gst_vulkan_window_class_init (GstVulkanWindowClass * klass) g_signal_new ("close", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, (GSignalAccumulator) _accum_logical_and, NULL, NULL, G_TYPE_BOOLEAN, 0); + gst_vulkan_window_signals[SIGNAL_DRAW] = + g_signal_new ("draw", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, + NULL, NULL, NULL, G_TYPE_NONE, 0); + G_OBJECT_CLASS (klass)->finalize = gst_vulkan_window_finalize; _init_debug (); @@ -260,6 +265,14 @@ gst_vulkan_window_resize (GstVulkanWindow * window, gint width, gint height) /* XXX: possibly queue a resize/redraw */ } +void +gst_vulkan_window_redraw (GstVulkanWindow * window) +{ + g_return_if_fail (GST_IS_VULKAN_WINDOW (window)); + + g_signal_emit (window, gst_vulkan_window_signals[SIGNAL_DRAW], 0); +} + GType gst_vulkan_dummy_window_get_type (void); G_DEFINE_TYPE (GstVulkanDummyWindow, gst_vulkan_dummy_window, GST_TYPE_VULKAN_WINDOW); diff --git a/ext/vulkan/vkwindow.h b/ext/vulkan/vkwindow.h index 65eb40badb..8dd7c4e227 100644 --- a/ext/vulkan/vkwindow.h +++ b/ext/vulkan/vkwindow.h @@ -96,6 +96,7 @@ gboolean gst_vulkan_window_open (GstVulkanWindow * w void gst_vulkan_window_close (GstVulkanWindow * window); void gst_vulkan_window_resize (GstVulkanWindow * window, gint width, gint height); +void gst_vulkan_window_redraw (GstVulkanWindow * window); G_END_DECLS diff --git a/ext/vulkan/xcb/xcb_event_source.c b/ext/vulkan/xcb/xcb_event_source.c index b11bc12751..3368f19626 100644 --- a/ext/vulkan/xcb/xcb_event_source.c +++ b/ext/vulkan/xcb/xcb_event_source.c @@ -112,32 +112,26 @@ _xcb_handle_event (GstVulkanDisplayXCB * display_xcb) } break; } + case XCB_EXPOSE:{ + xcb_expose_event_t *expose_event = (xcb_expose_event_t *) event; + GstVulkanWindowXCB *window_xcb; -#if 0 - case Expose: /* non-zero means that other Expose follows * so just wait for the last one * in theory we should not receive non-zero because * we have no sub areas here but just in case */ - if (event.xexpose.count != 0) { + if (expose_event->count != 0) break; - } -#if 0 - /* We need to redraw on expose */ - if (window->draw) { - context = gst_vulkan_window_get_context (window); - context_class = GST_VULKAN_CONTEXT_GET_CLASS (context); - window->draw (window->draw_data); - context_class->swap_buffers (context); + window_xcb = + _find_window_from_xcb_window (display_xcb, expose_event->window); - gst_object_unref (context); + if (window_xcb) { + gst_vulkan_window_redraw (GST_VULKAN_WINDOW (window_xcb)); + gst_object_unref (window_xcb); } -#endif - break; - case VisibilityNotify: - /* actually nothing to do here */ break; + } #if 0 case KeyPress: case KeyRelease: @@ -183,7 +177,6 @@ _xcb_handle_event (GstVulkanDisplayXCB * display_xcb) g_main_context_invoke (window->navigation_context, (GSourceFunc) gst_vulkan_window_mouse_event_cb, mouse_data); break; -#endif #endif default: GST_DEBUG ("unhandled XCB type: %u", event_code);