forked from AuroraMiddleware/gtk
vulkan: 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.
This commit is contained in:
parent
cca547e5bc
commit
6d1d6e6792
@ -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);
|
||||
|
@ -489,6 +489,21 @@ typedef enum {
|
||||
GDK_GL_ERROR_LINK_FAILED
|
||||
} 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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -2682,6 +2682,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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 "gdkconfig.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_VULKAN
|
||||
|
||||
#include "gdkvulkancontext-x11.h"
|
||||
|
||||
#include <vulkan/vulkan.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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user