[gtk+/wip/otte/vulkan: 19/36] gdk: Add more infrastructure
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/vulkan: 19/36] gdk: Add more infrastructure
- Date: Wed, 30 Nov 2016 23:11:08 +0000 (UTC)
commit d56e4cb1692f3af747cd1f577d3993f3cc108613
Author: Benjamin Otte <otte redhat com>
Date: Mon Nov 28 16:34:01 2016 +0100
gdk: Add more infrastructure
gdk_window_create_vulkan_context() now exists and will return a Vulkan
context for the given window. It even initializes the surface. But it
doesn't do anything useful yet.
gdk/gdkdisplayprivate.h | 2 +
gdk/gdktypes.h | 15 ++++++
gdk/gdkvulkancontext.c | 103 +++++++++++++++++++++++++++++++++-------
gdk/gdkvulkancontext.h | 11 ++++
gdk/gdkvulkancontextprivate.h | 12 ++++-
gdk/gdkwindow.c | 39 +++++++++++++++
gdk/gdkwindow.h | 4 ++
gdk/x11/gdkdisplay-x11.c | 7 +++
gdk/x11/gdkvulkancontext-x11.c | 44 +++++++++++++++--
gdk/x11/gdkvulkancontext-x11.h | 10 ++++
10 files changed, 223 insertions(+), 24 deletions(-)
---
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index c90c611..4164b9c 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -145,6 +145,8 @@ struct _GdkDisplayClass
GObjectClass parent_class;
GType window_type; /* type for native windows for this display, set in class_init */
+ GType vk_context_type; /* type for GdkVulkanContext, must be set if vk_extension_name != NULL */
+ const char *vk_extension_name; /* Name of required windowing vulkan extension or %NULL (default) if Vulkan
isn't supported */
const gchar * (*get_name) (GdkDisplay *display);
GdkScreen * (*get_default_screen) (GdkDisplay *display);
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
index 2faa907..e2ad6f7 100644
--- a/gdk/gdktypes.h
+++ b/gdk/gdktypes.h
@@ -489,6 +489,21 @@ typedef enum {
} GdkGLError;
/**
+ * GdkVulkanError:
+ * @GDK_VULKAN_ERROR_UNSUPPORTED: Vulkan is not supported on this backend or has not been
+ * compiled in.
+ * @GDK_VULKAN_ERROR_NOT_AVAILABLE: Vulkan support is not available on this Window
+ *
+ * Error enumeration for #GdkVulkanContext.
+ *
+ * Since: 3.90
+ */
+typedef enum {
+ GDK_VULKAN_ERROR_UNSUPPORTED,
+ GDK_VULKAN_ERROR_NOT_AVAILABLE,
+} GdkVulkanError;
+
+/**
* GdkWindowTypeHint:
* @GDK_WINDOW_TYPE_HINT_NORMAL: Normal toplevel window.
* @GDK_WINDOW_TYPE_HINT_DIALOG: Dialog window.
diff --git a/gdk/gdkvulkancontext.c b/gdk/gdkvulkancontext.c
index c392d21..df6a30f 100644
--- a/gdk/gdkvulkancontext.c
+++ b/gdk/gdkvulkancontext.c
@@ -32,6 +32,8 @@ typedef struct _GdkVulkanContextPrivate GdkVulkanContextPrivate;
struct _GdkVulkanContextPrivate {
GdkWindow *window;
+
+ VkSurfaceKHR surface;
};
enum {
@@ -47,7 +49,11 @@ static GParamSpec *pspecs[LAST_PROP] = { NULL, };
G_DEFINE_QUARK (gdk-vulkan-error-quark, gdk_vulkan_error)
-G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkVulkanContext, gdk_vulkan_context, G_TYPE_OBJECT)
+static void gdk_vulkan_context_initable_init (GInitableIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkVulkanContext, gdk_vulkan_context, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gdk_vulkan_context_initable_init)
+ G_ADD_PRIVATE (GdkVulkanContext))
static void
gdk_vulkan_context_dispose (GObject *gobject)
@@ -55,6 +61,8 @@ gdk_vulkan_context_dispose (GObject *gobject)
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (gobject);
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
+ gdk_display_unref_vulkan (gdk_vulkan_context_get_display (context));
+
g_clear_object (&priv->window);
G_OBJECT_CLASS (gdk_vulkan_context_parent_class)->dispose (gobject);
@@ -153,6 +161,33 @@ gdk_vulkan_context_init (GdkVulkanContext *self)
{
}
+static gboolean
+gdk_vulkan_context_real_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GdkVulkanContext *context = GDK_VULKAN_CONTEXT (initable);
+ GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
+
+ if (!gdk_display_ref_vulkan (gdk_vulkan_context_get_display (context), error))
+ return FALSE;
+
+ if (GDK_VULKAN_CONTEXT_GET_CLASS (context)->create_surface (context, &priv->surface) != VK_SUCCESS)
+ {
+ g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
+ "Vulkan support not available for this window.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+gdk_vulkan_context_initable_init (GInitableIface *iface)
+{
+ iface->init = gdk_vulkan_context_real_init;
+}
+
/**
* gdk_vulkan_context_get_display:
* @context: a #GdkVulkanContext
@@ -195,8 +230,17 @@ gdk_vulkan_context_get_window (GdkVulkanContext *context)
#ifdef GDK_WINDOWING_VULKAN
+VkInstance
+gdk_vulkan_context_get_instance (GdkVulkanContext *context)
+{
+ g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), NULL);
+
+ return gdk_vulkan_context_get_display (context)->vk_instance;
+}
+
static gboolean
-gdk_display_create_vulkan_device (GdkDisplay *display)
+gdk_display_create_vulkan_device (GdkDisplay *display,
+ GError **error)
{
uint32_t i, j;
@@ -205,6 +249,14 @@ gdk_display_create_vulkan_device (GdkDisplay *display)
VkPhysicalDevice devices[n_devices];
GDK_VK_CHECK(vkEnumeratePhysicalDevices, display->vk_instance, &n_devices, devices);
+ if (n_devices == 0)
+ {
+ /* Give a different error for 0 devices so people know their drivers suck. */
+ g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
+ "No Vulkan devices available.");
+ return FALSE;
+ }
+
for (i = 0; i < n_devices; i++)
{
VkPhysicalDeviceProperties props;
@@ -265,15 +317,24 @@ gdk_display_create_vulkan_device (GdkDisplay *display)
}
}
+ g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
+ "Could not find a Vulkan device with the required features.");
return FALSE;
}
static gboolean
-gdk_display_create_vulkan_instance (GdkDisplay *display,
- const char *wsi_extension_name)
+gdk_display_create_vulkan_instance (GdkDisplay *display,
+ GError **error)
{
uint32_t i;
+ if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
+ {
+ g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+ "The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (display));
+ return FALSE;
+ }
+
uint32_t n_extensions;
GDK_VK_CHECK (vkEnumerateInstanceExtensionProperties, NULL, &n_extensions, NULL);
VkExtensionProperties extensions[n_extensions];
@@ -308,31 +369,39 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
NULL,
0,
&(VkApplicationInfo) {
- VK_STRUCTURE_TYPE_APPLICATION_INFO,
- NULL,
- g_get_application_name (),
- 0,
- "GTK+",
- VK_MAKE_VERSION (GDK_MAJOR_VERSION, GDK_MINOR_VERSION,
GDK_MICRO_VERSION),
- VK_API_VERSION_1_0 },
+ VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ NULL,
+ g_get_application_name (),
+ 0,
+ "GTK+",
+ VK_MAKE_VERSION (GDK_MAJOR_VERSION, GDK_MINOR_VERSION,
GDK_MICRO_VERSION),
+ VK_API_VERSION_1_0 },
0,
NULL,
- 1,
- &wsi_extension_name },
+ 2,
+ (const char *const *) &(const char *[2]) {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ GDK_DISPLAY_GET_CLASS (display)->vk_extension_name
+ },
+ },
NULL,
&display->vk_instance) != VK_SUCCESS)
- return FALSE;
+ {
+ g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+ "Could not create a Vulkan instance.");
+ return FALSE;
+ }
- return gdk_display_create_vulkan_device (display);
+ return gdk_display_create_vulkan_device (display, error);
}
gboolean
gdk_display_ref_vulkan (GdkDisplay *display,
- const char *wsi_extension_name)
+ GError **error)
{
if (display->vulkan_refcount == 0)
{
- if (!gdk_display_create_vulkan_instance (display, wsi_extension_name))
+ if (!gdk_display_create_vulkan_instance (display, error))
return FALSE;
}
diff --git a/gdk/gdkvulkancontext.h b/gdk/gdkvulkancontext.h
index 7a042f0..ce85903 100644
--- a/gdk/gdkvulkancontext.h
+++ b/gdk/gdkvulkancontext.h
@@ -28,6 +28,10 @@
#include <gdk/gdkversionmacros.h>
#include <gdk/gdktypes.h>
+#ifdef GDK_WINDOWING_VULKAN
+#include <vulkan/vulkan.h>
+#endif
+
G_BEGIN_DECLS
#define GDK_TYPE_VULKAN_CONTEXT (gdk_vulkan_context_get_type ())
@@ -47,6 +51,13 @@ GdkDisplay * gdk_vulkan_context_get_display (GdkVulkanCo
GDK_AVAILABLE_IN_3_90
GdkWindow * gdk_vulkan_context_get_window (GdkVulkanContext *context);
+#ifdef GDK_WINDOWING_VULKAN
+
+GDK_AVAILABLE_IN_3_90
+VkInstance gdk_vulkan_context_get_instance (GdkVulkanContext *context);
+
+#endif /* GDK_WINDOWING_VULKAN */
+
G_END_DECLS
#endif /* __GDK_VULKAN_CONTEXT__ */
diff --git a/gdk/gdkvulkancontextprivate.h b/gdk/gdkvulkancontextprivate.h
index 7bed0d9..de4ba2f 100644
--- a/gdk/gdkvulkancontextprivate.h
+++ b/gdk/gdkvulkancontextprivate.h
@@ -43,6 +43,9 @@ struct _GdkVulkanContext
struct _GdkVulkanContextClass
{
GObjectClass parent_class;
+
+ VkResult (* create_surface) (GdkVulkanContext *context,
+ VkSurfaceKHR *surface);
};
#ifdef GDK_WINDOWING_VULKAN
@@ -61,17 +64,20 @@ gdk_vulkan_handle_result (VkResult res,
#define GDK_VK_CHECK(func, ...) gdk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
gboolean gdk_display_ref_vulkan (GdkDisplay *display,
- const char *wsi_extension_name);
+ GError **error);
void gdk_display_unref_vulkan (GdkDisplay *display);
#else /* !GDK_WINDOWING_VULKAN */
static inline gboolean
-gdk_display_init_vulkan (GdkDisplay *display,
- const char *wsi_extension_name)
+gdk_display_ref_vulkan (GdkDisplay *display,
+ GError **error)
{
GDK_NOTE (VULKAN, g_print ("Support for Vulkan disabled at compile-time"));
+ g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+ "Vulkan support was not enabled at compie time.");
+
return FALSE;
}
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index fd74eb8..22307a2 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -2681,6 +2681,45 @@ gdk_window_create_gl_context (GdkWindow *window,
error);
}
+/**
+ * gdk_window_create_vulkan_context:
+ * @window: a #GdkWindow
+ * @error: return location for an error
+ *
+ * Creates a new #GdkVulkanContext for rendering on @window.
+ *
+ * If the creation of the #GdkVulkanContext failed, @error will be set.
+ *
+ * Returns: (transfer full): the newly created #GdkVulkanContext, or
+ * %NULL on error
+ *
+ * Since: 3.90
+ **/
+GdkVulkanContext *
+gdk_window_create_vulkan_context (GdkWindow *window,
+ GError **error)
+{
+ GdkDisplay *display;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ display = gdk_window_get_display (window);
+
+ if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
+ {
+ g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
+ "The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (display));
+ return FALSE;
+ }
+
+ return g_initable_new (GDK_DISPLAY_GET_CLASS (display)->vk_context_type,
+ NULL,
+ error,
+ "window", window,
+ NULL);
+}
+
static void
gdk_window_begin_paint_internal (GdkWindow *window,
const cairo_region_t *region)
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 96d326c..e6c60c7 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -946,6 +946,10 @@ gboolean gdk_window_show_window_menu (GdkWindow *window,
GDK_AVAILABLE_IN_3_16
GdkGLContext * gdk_window_create_gl_context (GdkWindow *window,
GError **error);
+GDK_AVAILABLE_IN_3_90
+GdkVulkanContext *
+ gdk_window_create_vulkan_context(GdkWindow *window,
+ GError **error);
G_END_DECLS
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 843cdc8..9efe829 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -22,6 +22,8 @@
#include "config.h"
+#define VK_USE_PLATFORM_XLIB_KHR
+
#include "gdkasync.h"
#include "gdkdisplay.h"
#include "gdkeventsource.h"
@@ -38,6 +40,7 @@
#include "gdkprivate-x11.h"
#include "gdkscreen-x11.h"
#include "gdkglcontext-x11.h"
+#include "gdkvulkancontext-x11.h"
#include "gdk-private.h"
#include <glib.h>
@@ -2951,6 +2954,10 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
object_class->finalize = gdk_x11_display_finalize;
display_class->window_type = GDK_TYPE_X11_WINDOW;
+#ifdef GDK_WINDOWING_VULKAN
+ display_class->vk_context_type = GDK_TYPE_X11_VULKAN_CONTEXT;
+ display_class->vk_extension_name = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
+#endif
display_class->get_name = gdk_x11_display_get_name;
display_class->get_default_screen = gdk_x11_display_get_default_screen;
diff --git a/gdk/x11/gdkvulkancontext-x11.c b/gdk/x11/gdkvulkancontext-x11.c
index cb0bda2..dc42306 100644
--- a/gdk/x11/gdkvulkancontext-x11.c
+++ b/gdk/x11/gdkvulkancontext-x11.c
@@ -18,15 +18,51 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifdef GDK_WINDOWING_VULKAN
-
#include "config.h"
-#include "gdkvulkancontext-x11.h"
+#include "gdkconfig.h"
-#include <vulkan/vulkan.h>
+#ifdef GDK_WINDOWING_VULKAN
+
+#include "gdkvulkancontext-x11.h"
#include "gdkinternals.h"
+#include "gdkdisplay-x11.h"
+#include "gdkwindow-x11.h"
+
+G_DEFINE_TYPE (GdkX11VulkanContext, gdk_x11_vulkan_context, GDK_TYPE_VULKAN_CONTEXT)
+
+static VkResult
+gdk_x11_vulkan_context_create_surface (GdkVulkanContext *context,
+ VkSurfaceKHR *surface)
+{
+ GdkWindow *window = gdk_vulkan_context_get_window (context);
+ GdkDisplay *display = gdk_vulkan_context_get_display (context);
+
+ return GDK_VK_CHECK (vkCreateXlibSurfaceKHR, gdk_vulkan_context_get_instance (context),
+ &(VkXlibSurfaceCreateInfoKHR) {
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ gdk_x11_display_get_xdisplay (display),
+ gdk_x11_window_get_xid (window)
+ },
+ NULL,
+ surface);
+}
+
+static void
+gdk_x11_vulkan_context_class_init (GdkX11VulkanContextClass *klass)
+{
+ GdkVulkanContextClass *context_class = GDK_VULKAN_CONTEXT_CLASS (klass);
+
+ context_class->create_surface = gdk_x11_vulkan_context_create_surface;
+}
+
+static void
+gdk_x11_vulkan_context_init (GdkX11VulkanContext *self)
+{
+}
#endif /* GDK_WINDOWING_VULKAN */
diff --git a/gdk/x11/gdkvulkancontext-x11.h b/gdk/x11/gdkvulkancontext-x11.h
index d4268df..8c3dab1 100644
--- a/gdk/x11/gdkvulkancontext-x11.h
+++ b/gdk/x11/gdkvulkancontext-x11.h
@@ -21,8 +21,12 @@
#ifndef __GDK_X11_VULKAN_CONTEXT__
#define __GDK_X11_VULKAN_CONTEXT__
+#include "gdkconfig.h"
+
#ifdef GDK_WINDOWING_VULKAN
+#define VK_USE_PLATFORM_XLIB_KHR
+
#include "gdkvulkancontextprivate.h"
G_BEGIN_DECLS
@@ -34,6 +38,9 @@ G_BEGIN_DECLS
#define GDK_IS_X11_VULKAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GDK_TYPE_X11_VULKAN_CONTEXT))
#define GDK_X11_VULKAN_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GDK_TYPE_X11_VULKAN_CONTEXT, GdkX11VulkanContextClass))
+typedef struct _GdkX11VulkanContext GdkX11VulkanContext;
+typedef struct _GdkX11VulkanContextClass GdkX11VulkanContextClass;
+
struct _GdkX11VulkanContext
{
GdkVulkanContext parent_instance;
@@ -44,6 +51,9 @@ struct _GdkX11VulkanContextClass
GdkVulkanContextClass parent_class;
};
+GDK_AVAILABLE_IN_3_90
+GType gdk_x11_vulkan_context_get_type (void) G_GNUC_CONST;
+
G_END_DECLS
#endif /* !GDK_WINDOWING_VULKAN */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]