vkwindow/swapper: implement redraw handling

only xcb has been implemented
This commit is contained in:
Matthew Waters 2015-12-01 18:37:34 +11:00
parent 216a321319
commit a4476fa24b
6 changed files with 105 additions and 30 deletions

View File

@ -44,6 +44,7 @@ typedef struct _GstVulkanWindowPrivate GstVulkanWindowPrivate;
typedef struct _GstVulkanSwapper GstVulkanSwapper; typedef struct _GstVulkanSwapper GstVulkanSwapper;
typedef struct _GstVulkanSwapperClass GstVulkanSwapperClass; typedef struct _GstVulkanSwapperClass GstVulkanSwapperClass;
typedef struct _GstVulkanSwapperPrivate GstVulkanSwapperPrivate;
typedef struct _GstVulkanMemory GstVulkanMemory; typedef struct _GstVulkanMemory GstVulkanMemory;
typedef struct _GstVulkanMemoryAllocator GstVulkanMemoryAllocator; typedef struct _GstVulkanMemoryAllocator GstVulkanMemoryAllocator;

View File

@ -34,6 +34,18 @@ G_DEFINE_TYPE_WITH_CODE (GstVulkanSwapper, gst_vulkan_swapper,
GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
"vulkanswapper", 0, "Vulkan Swapper")); "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 static gboolean
_get_function_table (GstVulkanSwapper * swapper) _get_function_table (GstVulkanSwapper * swapper)
{ {
@ -210,8 +222,8 @@ _vulkan_swapper_retrieve_surface_properties (GstVulkanSwapper * swapper,
swapper->GetPhysicalDeviceSurfaceSupportKHR (gpu, i, swapper->GetPhysicalDeviceSurfaceSupportKHR (gpu, i,
(VkSurfaceDescriptionKHR *) & surface_desc, &supports_present); (VkSurfaceDescriptionKHR *) & surface_desc, &supports_present);
if ((swapper->device->queue_family_props[i]. if ((swapper->device->
queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { queue_family_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
if (supports_present) { if (supports_present) {
/* found one that supports both */ /* found one that supports both */
graphics_queue = present_queue = i; graphics_queue = present_queue = i;
@ -313,6 +325,9 @@ gst_vulkan_swapper_finalize (GObject * object)
gst_object_unref (swapper->device); gst_object_unref (swapper->device);
swapper->device = NULL; 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); g_signal_handler_disconnect (swapper->window, swapper->close_id);
swapper->close_id = 0; swapper->close_id = 0;
@ -326,17 +341,27 @@ gst_vulkan_swapper_finalize (GObject * object)
g_free (swapper->surf_formats); g_free (swapper->surf_formats);
swapper->surf_formats = NULL; swapper->surf_formats = NULL;
gst_buffer_replace (&swapper->current_buffer, NULL);
gst_caps_replace (&swapper->caps, NULL); gst_caps_replace (&swapper->caps, NULL);
g_mutex_clear (&swapper->priv->render_lock);
} }
static void static void
gst_vulkan_swapper_init (GstVulkanSwapper * swapper) 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 static void
gst_vulkan_swapper_class_init (GstVulkanSwapperClass * klass) gst_vulkan_swapper_class_init (GstVulkanSwapperClass * klass)
{ {
g_type_class_add_private (klass, sizeof (GstVulkanSwapperPrivate));
G_OBJECT_CLASS (klass)->finalize = gst_vulkan_swapper_finalize; 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", swapper->close_id = g_signal_connect (swapper->window, "close",
(GCallback) _on_window_close, swapper); (GCallback) _on_window_close, swapper);
swapper->draw_id = g_signal_connect (swapper->window, "draw",
(GCallback) _on_window_draw, swapper);
return swapper; return swapper;
} }
@ -563,8 +590,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps,
n_images_wanted = swapper->surf_props.maxImageCount; n_images_wanted = swapper->surf_props.maxImageCount;
} }
if (swapper-> if (swapper->surf_props.
surf_props.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) { supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
preTransform = VK_SURFACE_TRANSFORM_NONE_KHR; preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
} else { } else {
preTransform = swapper->surf_props.currentTransform; preTransform = swapper->surf_props.currentTransform;
@ -583,8 +610,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps,
"Incorrect usage flags available for the swap images"); "Incorrect usage flags available for the swap images");
return FALSE; return FALSE;
} }
if ((swapper->surf_props. if ((swapper->
supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) surf_props.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
!= 0) { != 0) {
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
} else { } else {
@ -900,8 +927,8 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
return TRUE; return TRUE;
} }
gboolean static gboolean
gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper, _render_buffer_unlocked (GstVulkanSwapper * swapper,
GstBuffer * buffer, GError ** error) GstBuffer * buffer, GError ** error)
{ {
VkSemaphore semaphore = { 0, }; VkSemaphore semaphore = { 0, };
@ -915,12 +942,20 @@ gst_vulkan_swapper_render_buffer (GstVulkanSwapper * swapper,
guint32 swap_idx; guint32 swap_idx;
VkResult err; 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)) { if (g_atomic_int_get (&swapper->to_quit)) {
g_set_error (error, GST_VULKAN_ERROR, GST_VULKAN_ERROR_DEVICE_LOST, g_set_error (error, GST_VULKAN_ERROR, GST_VULKAN_ERROR_DEVICE_LOST,
"Output window was closed"); "Output window was closed");
return FALSE; goto error;
} }
gst_buffer_replace (&swapper->current_buffer, buffer);
reacquire: reacquire:
err = vkCreateSemaphore (swapper->device->device, &semaphore_info, err = vkCreateSemaphore (swapper->device->device, &semaphore_info,
&semaphore); &semaphore);
@ -936,7 +971,7 @@ reacquire:
vkDestroySemaphore (swapper->device->device, semaphore); vkDestroySemaphore (swapper->device->device, semaphore);
if (!_swapchain_resize (swapper, error)) if (!_swapchain_resize (swapper, error))
return FALSE; goto error;
goto reacquire; goto reacquire;
} else if (gst_vulkan_error_to_g_error (err, error, } else if (gst_vulkan_error_to_g_error (err, error,
"vkAcquireNextImageKHR") < 0) { "vkAcquireNextImageKHR") < 0) {
@ -958,11 +993,10 @@ reacquire:
if (err == VK_ERROR_OUT_OF_DATE_KHR) { if (err == VK_ERROR_OUT_OF_DATE_KHR) {
GST_DEBUG_OBJECT (swapper, "out of date frame submitted"); GST_DEBUG_OBJECT (swapper, "out of date frame submitted");
vkDestroySemaphore (swapper->device->device, semaphore);
if (!_swapchain_resize (swapper, error)) if (!_swapchain_resize (swapper, error))
return FALSE; goto error;
vkDestroySemaphore (swapper->device->device, semaphore);
if (cmd_data.cmd) if (cmd_data.cmd)
vkDestroyCommandBuffer (swapper->device->device, cmd_data.cmd); vkDestroyCommandBuffer (swapper->device->device, cmd_data.cmd);
cmd_data.cmd = NULL; cmd_data.cmd = NULL;
@ -1004,3 +1038,32 @@ error:
return FALSE; 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);
}

View File

@ -71,9 +71,13 @@ struct _GstVulkanSwapper
/* <private> */ /* <private> */
/* runtime variables */ /* runtime variables */
gint to_quit; gint to_quit;
GstBuffer *current_buffer;
/* signal handlers */ /* signal handlers */
gulong close_id; gulong close_id;
gulong draw_id;
GstVulkanSwapperPrivate *priv;
}; };
struct _GstVulkanSwapperClass struct _GstVulkanSwapperClass

View File

@ -79,6 +79,7 @@ enum
{ {
SIGNAL_0, SIGNAL_0,
SIGNAL_CLOSE, SIGNAL_CLOSE,
SIGNAL_DRAW,
LAST_SIGNAL 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, g_signal_new ("close", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0,
(GSignalAccumulator) _accum_logical_and, NULL, NULL, G_TYPE_BOOLEAN, 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; G_OBJECT_CLASS (klass)->finalize = gst_vulkan_window_finalize;
_init_debug (); _init_debug ();
@ -260,6 +265,14 @@ gst_vulkan_window_resize (GstVulkanWindow * window, gint width, gint height)
/* XXX: possibly queue a resize/redraw */ /* 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); GType gst_vulkan_dummy_window_get_type (void);
G_DEFINE_TYPE (GstVulkanDummyWindow, gst_vulkan_dummy_window, G_DEFINE_TYPE (GstVulkanDummyWindow, gst_vulkan_dummy_window,
GST_TYPE_VULKAN_WINDOW); GST_TYPE_VULKAN_WINDOW);

View File

@ -96,6 +96,7 @@ gboolean gst_vulkan_window_open (GstVulkanWindow * w
void gst_vulkan_window_close (GstVulkanWindow * window); void gst_vulkan_window_close (GstVulkanWindow * window);
void gst_vulkan_window_resize (GstVulkanWindow * window, gint width, gint height); void gst_vulkan_window_resize (GstVulkanWindow * window, gint width, gint height);
void gst_vulkan_window_redraw (GstVulkanWindow * window);
G_END_DECLS G_END_DECLS

View File

@ -112,32 +112,26 @@ _xcb_handle_event (GstVulkanDisplayXCB * display_xcb)
} }
break; 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 /* non-zero means that other Expose follows
* so just wait for the last one * so just wait for the last one
* in theory we should not receive non-zero because * in theory we should not receive non-zero because
* we have no sub areas here but just in case */ * we have no sub areas here but just in case */
if (event.xexpose.count != 0) { if (expose_event->count != 0)
break; 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); window_xcb =
context_class->swap_buffers (context); _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; break;
}
#if 0 #if 0
case KeyPress: case KeyPress:
case KeyRelease: case KeyRelease:
@ -183,7 +177,6 @@ _xcb_handle_event (GstVulkanDisplayXCB * display_xcb)
g_main_context_invoke (window->navigation_context, (GSourceFunc) g_main_context_invoke (window->navigation_context, (GSourceFunc)
gst_vulkan_window_mouse_event_cb, mouse_data); gst_vulkan_window_mouse_event_cb, mouse_data);
break; break;
#endif
#endif #endif
default: default:
GST_DEBUG ("unhandled XCB type: %u", event_code); GST_DEBUG ("unhandled XCB type: %u", event_code);