mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-01 13:49:58 +00:00
vkwindow/swapper: implement redraw handling
only xcb has been implemented
This commit is contained in:
parent
216a321319
commit
a4476fa24b
6 changed files with 105 additions and 30 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -71,9 +71,13 @@ struct _GstVulkanSwapper
|
|||
/* <private> */
|
||||
/* runtime variables */
|
||||
gint to_quit;
|
||||
GstBuffer *current_buffer;
|
||||
|
||||
/* signal handlers */
|
||||
gulong close_id;
|
||||
gulong draw_id;
|
||||
|
||||
GstVulkanSwapperPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GstVulkanSwapperClass
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue