vkwindow/swapper: implement redraw handling
authorMatthew Waters <matthew@centricular.com>
Tue, 1 Dec 2015 07:37:34 +0000 (18:37 +1100)
committerMatthew Waters <matthew@centricular.com>
Tue, 16 Feb 2016 14:13:43 +0000 (01:13 +1100)
only xcb has been implemented

ext/vulkan/vk_fwd.h
ext/vulkan/vkswapper.c
ext/vulkan/vkswapper.h
ext/vulkan/vkwindow.c
ext/vulkan/vkwindow.h
ext/vulkan/xcb/xcb_event_source.c

index 59b307d..dd52283 100644 (file)
@@ -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;
index 7d8bf44..21cf50f 100644 (file)
@@ -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);
+}
index e090b4b..043c0a2 100644 (file)
@@ -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
index d62e79d..83e3b4d 100644 (file)
@@ -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);
index 65eb40b..8dd7c4e 100644 (file)
@@ -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
 
index b11bc12..3368f19 100644 (file)
@@ -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:
@@ -184,7 +178,6 @@ _xcb_handle_event (GstVulkanDisplayXCB * display_xcb)
             gst_vulkan_window_mouse_event_cb, mouse_data);
         break;
 #endif
-#endif
       default:
         GST_DEBUG ("unhandled XCB type: %u", event_code);
         break;