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)
{
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;
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;
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;
}
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;
}
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;
"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 {
return TRUE;
}
-gboolean
-gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper,
+static gboolean
+_render_buffer_unlocked (GstVulkanSwapper * swapper,
GstBuffer * buffer, GError ** error)
{
VkSemaphore semaphore = { 0, };
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);
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) {
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;
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);
+}
{
SIGNAL_0,
SIGNAL_CLOSE,
+ SIGNAL_DRAW,
LAST_SIGNAL
};
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 ();
/* 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);
}
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:
gst_vulkan_window_mouse_event_cb, mouse_data);
break;
#endif
-#endif
default:
GST_DEBUG ("unhandled XCB type: %u", event_code);
break;