Compare commits
26 Commits
main
...
wip/otte/d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
847c7e2315 | ||
|
|
3e9b6abdec | ||
|
|
e48dc89daa | ||
|
|
ac066e1807 | ||
|
|
b5c0dc1ced | ||
|
|
ca4915962e | ||
|
|
90d09a1180 | ||
|
|
9ae76f6e69 | ||
|
|
641b8c9cd0 | ||
|
|
a6d30b1694 | ||
|
|
9f9d8f59bd | ||
|
|
d22cfef06e | ||
|
|
577176b0f2 | ||
|
|
595294b8f4 | ||
|
|
80c04eb223 | ||
|
|
c9d58ee54e | ||
|
|
768fcfb718 | ||
|
|
35904b793a | ||
|
|
8b99f14706 | ||
|
|
b5af96c21f | ||
|
|
d1e903203b | ||
|
|
d859b8a8e4 | ||
|
|
c3eb4ff025 | ||
|
|
2a411b895a | ||
|
|
fe6b9d61f5 | ||
|
|
7b6a7671cf |
@@ -17,6 +17,7 @@ pacman --noconfirm -S --needed \
|
||||
${MINGW_PACKAGE_PREFIX}-adwaita-icon-theme \
|
||||
${MINGW_PACKAGE_PREFIX}-atk \
|
||||
${MINGW_PACKAGE_PREFIX}-cairo \
|
||||
${MINGW_PACKAGE_PREFIX}-directx-headers \
|
||||
${MINGW_PACKAGE_PREFIX}-gdk-pixbuf2 \
|
||||
${MINGW_PACKAGE_PREFIX}-glib2 \
|
||||
${MINGW_PACKAGE_PREFIX}-graphene \
|
||||
|
||||
@@ -206,6 +206,9 @@ print out different types of debugging information.
|
||||
`dmabuf`
|
||||
: Information about dmabuf handling (Linux-only)
|
||||
|
||||
`d3d12`
|
||||
: Information about Direct3D12 (Windows-only)
|
||||
|
||||
`offload`
|
||||
: Information about subsurfaces and graphics offload (Wayland-only)
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "selection", GDK_DEBUG_SELECTION, "Information about selections" },
|
||||
{ "clipboard", GDK_DEBUG_CLIPBOARD, "Information about clipboards" },
|
||||
{ "dmabuf", GDK_DEBUG_DMABUF, "Information about dmabuf buffers" },
|
||||
{ "d3d12", GDK_DEBUG_D3D12, "Information about Direct3D12" },
|
||||
{ "offload", GDK_DEBUG_OFFLOAD, "Information about subsurfaces and graphics offload" },
|
||||
|
||||
{ "linear", GDK_DEBUG_LINEAR, "Enable linear rendering" },
|
||||
|
||||
@@ -37,20 +37,21 @@ typedef enum {
|
||||
GDK_DEBUG_SELECTION = 1 << 9,
|
||||
GDK_DEBUG_CLIPBOARD = 1 << 10,
|
||||
GDK_DEBUG_DMABUF = 1 << 11,
|
||||
GDK_DEBUG_OFFLOAD = 1 << 12,
|
||||
GDK_DEBUG_D3D12 = 1 << 12,
|
||||
GDK_DEBUG_OFFLOAD = 1 << 13,
|
||||
|
||||
/* flags below are influencing behavior */
|
||||
GDK_DEBUG_LINEAR = 1 << 13,
|
||||
GDK_DEBUG_HDR = 1 << 14,
|
||||
GDK_DEBUG_PORTALS = 1 << 15,
|
||||
GDK_DEBUG_NO_PORTALS = 1 << 16,
|
||||
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 17,
|
||||
GDK_DEBUG_FORCE_OFFLOAD = 1 << 18,
|
||||
GDK_DEBUG_GL_PREFER_GL = 1 << 19,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 20,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21,
|
||||
GDK_DEBUG_HIGH_DEPTH = 1 << 22,
|
||||
GDK_DEBUG_NO_VSYNC = 1 << 23,
|
||||
GDK_DEBUG_LINEAR = 1 << 14,
|
||||
GDK_DEBUG_HDR = 1 << 15,
|
||||
GDK_DEBUG_PORTALS = 1 << 16,
|
||||
GDK_DEBUG_NO_PORTALS = 1 << 17,
|
||||
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 18,
|
||||
GDK_DEBUG_FORCE_OFFLOAD = 1 << 19,
|
||||
GDK_DEBUG_GL_PREFER_GL = 1 << 20,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 21,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 22,
|
||||
GDK_DEBUG_HIGH_DEPTH = 1 << 23,
|
||||
GDK_DEBUG_NO_VSYNC = 1 << 24,
|
||||
} GdkDebugFlags;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -44,11 +47,14 @@ typedef struct _GdkDisplayClass GdkDisplayClass;
|
||||
|
||||
typedef enum {
|
||||
GDK_VULKAN_FEATURE_DMABUF = 1 << 0,
|
||||
GDK_VULKAN_FEATURE_YCBCR = 1 << 1,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_WIN32 = 1 << 1,
|
||||
GDK_VULKAN_FEATURE_YCBCR = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_WIN32_SEMAPHORE = 1 << 6,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 7,
|
||||
GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 8,
|
||||
} GdkVulkanFeatures;
|
||||
|
||||
#define GDK_VULKAN_N_FEATURES 6
|
||||
|
||||
@@ -107,6 +107,8 @@ const GdkDebugKey gdk_gl_feature_keys[] = {
|
||||
{ "debug", GDK_GL_FEATURE_DEBUG, "GL_KHR_debug" },
|
||||
{ "base-instance", GDK_GL_FEATURE_BASE_INSTANCE, "GL_ARB_base_instance" },
|
||||
{ "buffer-storage", GDK_GL_FEATURE_BUFFER_STORAGE, "GL_EXT_buffer_storage" },
|
||||
{ "external-objects", GDK_GL_FEATURE_EXTERNAL_OBJECTS, "GL_EXT_memory_object and GL_EXT_semaphore"},
|
||||
{ "external-objects-win32", GDK_GL_FEATURE_EXTERNAL_OBJECTS_WIN32, "GL_EXT_memory_object_win32 and GL_EXT_semaphore_win32" },
|
||||
};
|
||||
|
||||
typedef struct _GdkGLContextPrivate GdkGLContextPrivate;
|
||||
@@ -1694,6 +1696,16 @@ gdk_gl_context_check_features (GdkGLContext *context)
|
||||
epoxy_has_gl_extension ("GL_ARB_buffer_storage"))
|
||||
features |= GDK_GL_FEATURE_BUFFER_STORAGE;
|
||||
|
||||
if (epoxy_has_gl_extension ("GL_EXT_memory_object") &&
|
||||
epoxy_has_gl_extension ("GL_EXT_semaphore"))
|
||||
{
|
||||
features |= GDK_GL_FEATURE_EXTERNAL_OBJECTS;
|
||||
|
||||
if (epoxy_has_gl_extension ("GL_EXT_memory_object_win32") &&
|
||||
epoxy_has_gl_extension ("GL_EXT_semaphore_win32"))
|
||||
features |= GDK_GL_FEATURE_EXTERNAL_OBJECTS_WIN32;
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
@@ -1736,6 +1748,10 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
gdk_gl_feature_keys,
|
||||
G_N_ELEMENTS (gdk_gl_feature_keys));
|
||||
|
||||
/* handle feature dependencies */
|
||||
if (disabled_features & GDK_GL_FEATURE_EXTERNAL_OBJECTS)
|
||||
disabled_features |= GDK_GL_FEATURE_EXTERNAL_OBJECTS_WIN32;
|
||||
|
||||
priv->features = supported_features & ~disabled_features;
|
||||
|
||||
gdk_gl_context_init_memory_flags (context);
|
||||
|
||||
@@ -32,6 +32,8 @@ typedef enum {
|
||||
GDK_GL_FEATURE_DEBUG = 1 << 0,
|
||||
GDK_GL_FEATURE_BASE_INSTANCE = 1 << 1,
|
||||
GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 2,
|
||||
GDK_GL_FEATURE_EXTERNAL_OBJECTS = 1 << 3,
|
||||
GDK_GL_FEATURE_EXTERNAL_OBJECTS_WIN32 = 1 << 4,
|
||||
} GdkGLFeatures;
|
||||
|
||||
#define GDK_GL_N_FEATURES 3
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <directx/d3d12.h>
|
||||
#endif
|
||||
|
||||
/* Don't report quick (< 0.5 msec) runs */
|
||||
#define MIN_MARK_DURATION 500000
|
||||
|
||||
@@ -454,6 +458,10 @@ struct _GdkMemoryFormatDescription
|
||||
VkFormat vk_format;
|
||||
VkFormat vk_srgb_format;
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
DXGI_FORMAT dxgi_format;
|
||||
DXGI_FORMAT dxgi_srgb_format;
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
guint32 dmabuf_fourcc;
|
||||
#endif
|
||||
@@ -498,6 +506,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_B8G8R8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ARGB8888,
|
||||
#endif
|
||||
@@ -531,6 +543,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_BGRA8888,
|
||||
#endif
|
||||
@@ -563,6 +579,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_R8G8B8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR8888,
|
||||
#endif
|
||||
@@ -596,6 +616,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_RGBA8888,
|
||||
#endif
|
||||
@@ -629,6 +653,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_B8G8R8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ARGB8888,
|
||||
#endif
|
||||
@@ -662,6 +690,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_BGRA8888,
|
||||
#endif
|
||||
@@ -694,6 +726,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_R8G8B8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR8888,
|
||||
#endif
|
||||
@@ -727,6 +763,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_RGBA8888,
|
||||
#endif
|
||||
@@ -761,6 +801,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_B8G8R8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_XRGB8888,
|
||||
#endif
|
||||
@@ -795,6 +839,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_BGRX8888,
|
||||
#endif
|
||||
@@ -828,6 +876,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_R8G8B8A8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_XBGR8888,
|
||||
#endif
|
||||
@@ -862,6 +914,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_UNDEFINED,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_RGBX8888,
|
||||
#endif
|
||||
@@ -895,6 +951,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8B8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_R8G8B8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_BGR888,
|
||||
#endif
|
||||
@@ -929,6 +989,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_B8G8R8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_B8G8R8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_RGB888,
|
||||
#endif
|
||||
@@ -965,6 +1029,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1000,6 +1068,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16A16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR16161616,
|
||||
#endif
|
||||
@@ -1035,6 +1107,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16A16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR16161616,
|
||||
#endif
|
||||
@@ -1070,6 +1146,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_UNKNOWN,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1104,6 +1184,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR16161616F,
|
||||
#endif
|
||||
@@ -1138,6 +1222,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_ABGR16161616F,
|
||||
#endif
|
||||
@@ -1173,6 +1261,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R32G32B32_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1207,6 +1299,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1241,6 +1337,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1274,6 +1374,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8G8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1307,6 +1411,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8G8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8G8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1340,6 +1448,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_R8_SRGB,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_R8,
|
||||
#endif
|
||||
@@ -1376,6 +1488,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1412,6 +1528,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16G16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16G16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1448,6 +1568,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = DRM_FORMAT_R16,
|
||||
#endif
|
||||
@@ -1481,6 +1605,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R8_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_A8_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1517,6 +1645,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16_UNORM,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16_UNORM,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1552,6 +1684,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R16_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R16_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1587,6 +1723,10 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.vk_format = VK_FORMAT_R32_SFLOAT,
|
||||
.vk_srgb_format = VK_FORMAT_UNDEFINED,
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
.dxgi_format = DXGI_FORMAT_R32_FLOAT,
|
||||
.dxgi_srgb_format = DXGI_FORMAT_UNKNOWN,
|
||||
#endif
|
||||
#ifdef HAVE_DMABUF
|
||||
.dmabuf_fourcc = 0,
|
||||
#endif
|
||||
@@ -1971,6 +2111,80 @@ gdk_memory_format_vk_rgba_format (GdkMemoryFormat format,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
static D3D12_SHADER_COMPONENT_MAPPING
|
||||
dxgi_swizzle_from_gl_swizzle_one (GLint swizzle)
|
||||
{
|
||||
switch (swizzle)
|
||||
{
|
||||
case GL_RED:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0;
|
||||
case GL_GREEN:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1;
|
||||
case GL_BLUE:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2;
|
||||
case GL_ALPHA:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_3;
|
||||
case GL_ZERO:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0;
|
||||
case GL_ONE:
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static UINT
|
||||
dxgi_swizzle_from_gl_swizzle (const GLint gl_swizzle[4])
|
||||
{
|
||||
return D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING (
|
||||
dxgi_swizzle_from_gl_swizzle_one (gl_swizzle[0]),
|
||||
dxgi_swizzle_from_gl_swizzle_one (gl_swizzle[1]),
|
||||
dxgi_swizzle_from_gl_swizzle_one (gl_swizzle[2]),
|
||||
dxgi_swizzle_from_gl_swizzle_one (gl_swizzle[3]));
|
||||
}
|
||||
|
||||
/* DXGI version of gdk_memory_format_gl_format()
|
||||
* Returns DXGI_FORMAT_UNKNOWN on failure */
|
||||
DXGI_FORMAT
|
||||
gdk_memory_format_dxgi_format (GdkMemoryFormat format,
|
||||
UINT *out_shader_4_component_mapping)
|
||||
{
|
||||
if (out_shader_4_component_mapping)
|
||||
*out_shader_4_component_mapping = dxgi_swizzle_from_gl_swizzle (memory_formats[format].gl.swizzle);
|
||||
return memory_formats[format].dxgi_format;
|
||||
}
|
||||
|
||||
/* Gets the matching SRGB version of a DXGI_FORMAT
|
||||
* Returns DXGI_FORMAT_UNKNOWN if none exists */
|
||||
DXGI_FORMAT
|
||||
gdk_memory_format_dxgi_srgb_format (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].dxgi_srgb_format;
|
||||
}
|
||||
|
||||
/* DXGI version of gdk_memory_format_gl_rgba_format()
|
||||
* Returns DXGI_FORMAT_UNKNOWN on failure */
|
||||
DXGI_FORMAT
|
||||
gdk_memory_format_dxgi_rgba_format (GdkMemoryFormat format,
|
||||
GdkMemoryFormat *out_rgba_format,
|
||||
UINT *out_shader_4_component_mapping)
|
||||
{
|
||||
GdkMemoryFormat actual = memory_formats[format].gl.rgba_format;
|
||||
|
||||
if (actual == -1)
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
if (out_rgba_format)
|
||||
*out_rgba_format = actual;
|
||||
if (out_shader_4_component_mapping)
|
||||
*out_shader_4_component_mapping = dxgi_swizzle_from_gl_swizzle (memory_formats[format].gl.swizzle);
|
||||
return memory_formats[actual].dxgi_format;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* gdk_memory_format_get_dmabuf_fourcc:
|
||||
* @format: The memory format
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
/* epoxy needs this, see https://github.com/anholt/libepoxy/issues/299 */
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <windows.h>
|
||||
#include <dxgiformat.h>
|
||||
#endif
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@@ -95,6 +96,14 @@ VkFormat gdk_memory_format_vk_rgba_format (GdkMemoryFormat
|
||||
GdkMemoryFormat *out_rgba_format,
|
||||
VkComponentMapping *out_swizzle);
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
DXGI_FORMAT gdk_memory_format_dxgi_format (GdkMemoryFormat format,
|
||||
UINT *out_shader_4_component_mapping);
|
||||
DXGI_FORMAT gdk_memory_format_dxgi_srgb_format (GdkMemoryFormat format);
|
||||
DXGI_FORMAT gdk_memory_format_dxgi_rgba_format (GdkMemoryFormat format,
|
||||
GdkMemoryFormat *out_rgba_format,
|
||||
UINT *out_shader_4_component_mapping);
|
||||
#endif
|
||||
guint32 gdk_memory_format_get_dmabuf_fourcc (GdkMemoryFormat format);
|
||||
const char * gdk_memory_format_get_name (GdkMemoryFormat format);
|
||||
|
||||
|
||||
@@ -37,9 +37,12 @@
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
const GdkDebugKey gdk_vulkan_feature_keys[] = {
|
||||
{ "dmabuf", GDK_VULKAN_FEATURE_DMABUF, "Never import Dmabufs" },
|
||||
{ "win32", GDK_VULKAN_FEATURE_WIN32, "Never import Windows resources" },
|
||||
{ "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures (also disables dmabufs)" },
|
||||
{ "timeline-semaphore", GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE, "Disable timeline semaphore support (disables Windows sync)"},
|
||||
{ "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" },
|
||||
{ "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" },
|
||||
{ "win32-semaphore", GDK_VULKAN_FEATURE_WIN32_SEMAPHORE, "Disable Windows sync support" },
|
||||
{ "incremental-present", GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT, "Do not send damage regions" },
|
||||
{ "swapchain-maintenance", GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE, "Do not use advanced swapchain features" },
|
||||
};
|
||||
@@ -631,6 +634,18 @@ physical_device_check_features (VkPhysicalDevice device)
|
||||
physical_device_supports_extension (device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_DMABUF;
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE;
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_WIN32;
|
||||
|
||||
if ((features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE) &&
|
||||
physical_device_supports_extension (device, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_WIN32_SEMAPHORE;
|
||||
#endif
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME))
|
||||
{
|
||||
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT)
|
||||
@@ -1478,6 +1493,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
G_N_ELEMENTS (gdk_vulkan_feature_keys));
|
||||
if (skip_features & GDK_VULKAN_FEATURE_YCBCR)
|
||||
skip_features |= GDK_VULKAN_FEATURE_DMABUF;
|
||||
if (skip_features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE)
|
||||
skip_features |= GDK_VULKAN_FEATURE_WIN32_SEMAPHORE;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, VULKAN))
|
||||
{
|
||||
@@ -1573,8 +1590,27 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
|
||||
}
|
||||
if (features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE)
|
||||
{
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
|
||||
}
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (features & GDK_VULKAN_FEATURE_WIN32)
|
||||
{
|
||||
if (!(features & GDK_VULKAN_FEATURE_DMABUF))
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
|
||||
}
|
||||
if (features & GDK_VULKAN_FEATURE_WIN32_SEMAPHORE)
|
||||
{
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
|
||||
}
|
||||
#endif
|
||||
if (features & (GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT | GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT))
|
||||
{
|
||||
if (!(features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE))
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
|
||||
}
|
||||
if (features & GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT)
|
||||
|
||||
591
gdk/win32/gdkd3d12texture.c
Normal file
591
gdk/win32/gdkd3d12texture.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/* gdkd3d12texture.c
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkd3d12textureprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkd3d12texturebuilder.h"
|
||||
#include "gdkdxgiformatprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
/**
|
||||
* GdkD3D12Texture:
|
||||
*
|
||||
* A `GdkTexture` representing a [ID3D12Resource](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12resource).
|
||||
*
|
||||
* To create a `GdkD3D12Texture`, use the auxiliary
|
||||
* [class@Gdk.D3d12TextureBuilder] object.
|
||||
*
|
||||
* D3D12 textures can only be created on Windows.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
|
||||
struct _GdkD3D12Texture
|
||||
{
|
||||
GdkTexture parent_instance;
|
||||
|
||||
ID3D12Resource *resource;
|
||||
HANDLE resource_handle;
|
||||
ID3D12Fence *fence;
|
||||
HANDLE fence_handle;
|
||||
guint64 fence_wait;
|
||||
|
||||
GDestroyNotify destroy;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
struct _GdkD3D12TextureClass
|
||||
{
|
||||
GdkTextureClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* gdk_d3d12_error_quark:
|
||||
*
|
||||
* Registers an error quark for [class@Gdk.D3d12Texture] errors.
|
||||
*
|
||||
* Returns: the error quark
|
||||
**/
|
||||
G_DEFINE_QUARK (gdk-d3d12-error-quark, gdk_d3d12_error)
|
||||
|
||||
G_DEFINE_TYPE (GdkD3D12Texture, gdk_d3d12_texture, GDK_TYPE_TEXTURE)
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_dispose (GObject *object)
|
||||
{
|
||||
GdkD3D12Texture *self = GDK_D3D12_TEXTURE (object);
|
||||
|
||||
if (self->fence_handle)
|
||||
{
|
||||
if (G_UNLIKELY (!CloseHandle (self->fence_handle)))
|
||||
{
|
||||
g_warning ("Failed to fence handle: %s", g_win32_error_message (GetLastError ()));
|
||||
}
|
||||
self->fence_handle = NULL;
|
||||
}
|
||||
if (self->resource_handle)
|
||||
{
|
||||
if (G_UNLIKELY (!CloseHandle (self->resource_handle)))
|
||||
{
|
||||
g_warning ("Failed to close resource handle: %s", g_win32_error_message (GetLastError ()));
|
||||
}
|
||||
self->resource_handle = NULL;
|
||||
}
|
||||
|
||||
gdk_win32_com_clear (&self->fence);
|
||||
gdk_win32_com_clear (&self->resource);
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
self->destroy (self->data);
|
||||
self->destroy = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_d3d12_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supports_nonzero (ID3D12Device *device)
|
||||
{
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ID3D12Device_CheckFeatureSupport (device,
|
||||
D3D12_FEATURE_D3D12_OPTIONS7,
|
||||
&options,
|
||||
sizeof (options));
|
||||
return SUCCEEDED (hr);
|
||||
}
|
||||
|
||||
#define hr_return_if_fail(expr) G_STMT_START {\
|
||||
HRESULT _hr = (expr); \
|
||||
if (!SUCCEEDED (_hr)) \
|
||||
{ \
|
||||
g_log (G_LOG_DOMAIN, \
|
||||
G_LOG_LEVEL_CRITICAL, \
|
||||
"file %s: line %d (%s): %s returned %ld (%s)", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
G_STRFUNC, \
|
||||
#expr, \
|
||||
_hr, \
|
||||
g_win32_error_message (_hr)); \
|
||||
return; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkD3D12Texture *self = GDK_D3D12_TEXTURE (texture);
|
||||
UINT64 buffer_size;
|
||||
ID3D12Device *device;
|
||||
ID3D12CommandAllocator *allocator;
|
||||
ID3D12GraphicsCommandList *commands;
|
||||
ID3D12CommandQueue *queue;
|
||||
ID3D12Fence *fence;
|
||||
ID3D12Resource *buffer;
|
||||
D3D12_RESOURCE_DESC resource_desc;
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
||||
void *buffer_data;
|
||||
|
||||
hr_return_if_fail (ID3D12Resource_GetDevice (self->resource,
|
||||
&IID_ID3D12Device,
|
||||
(void **) &device));
|
||||
ID3D12Resource_GetDesc (self->resource, &resource_desc);
|
||||
ID3D12Device_GetCopyableFootprints (device,
|
||||
&resource_desc,
|
||||
0, 1, 0,
|
||||
&footprint,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
buffer_size = footprint.Footprint.RowPitch * footprint.Footprint.Height;
|
||||
|
||||
hr_return_if_fail (ID3D12Device_CreateCommittedResource (device,
|
||||
(&(D3D12_HEAP_PROPERTIES) {
|
||||
.Type = D3D12_HEAP_TYPE_READBACK,
|
||||
.CreationNodeMask = 1,
|
||||
.VisibleNodeMask = 1,
|
||||
}),
|
||||
supports_nonzero (device) ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED
|
||||
: D3D12_HEAP_FLAG_NONE,
|
||||
(&(D3D12_RESOURCE_DESC) {
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = buffer_size,
|
||||
.Height = 1,
|
||||
.DepthOrArraySize = 1,
|
||||
.MipLevels = 1,
|
||||
.SampleDesc = {
|
||||
.Count = 1,
|
||||
.Quality = 0,
|
||||
},
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
}),
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
NULL,
|
||||
&IID_ID3D12Resource,
|
||||
(void **) &buffer));
|
||||
|
||||
hr_return_if_fail (ID3D12Device_CreateFence (device,
|
||||
0,
|
||||
D3D12_FENCE_FLAG_NONE,
|
||||
&IID_ID3D12Fence,
|
||||
(void **) &fence));
|
||||
|
||||
hr_return_if_fail (ID3D12Device_CreateCommandQueue (device,
|
||||
(&(D3D12_COMMAND_QUEUE_DESC) {
|
||||
.Type = D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
||||
.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||
}),
|
||||
&IID_ID3D12CommandQueue,
|
||||
(void **) &queue));
|
||||
hr_return_if_fail (ID3D12Device_CreateCommandAllocator (device,
|
||||
D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
&IID_ID3D12CommandAllocator,
|
||||
(void **) &allocator));
|
||||
hr_return_if_fail (ID3D12Device_CreateCommandList (device,
|
||||
0,
|
||||
D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
allocator,
|
||||
NULL,
|
||||
&IID_ID3D12GraphicsCommandList,
|
||||
(void **) &commands));
|
||||
|
||||
ID3D12GraphicsCommandList_CopyTextureRegion (commands,
|
||||
(&(D3D12_TEXTURE_COPY_LOCATION) {
|
||||
.pResource = buffer,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
.PlacedFootprint = footprint,
|
||||
}),
|
||||
0, 0, 0,
|
||||
(&(D3D12_TEXTURE_COPY_LOCATION) {
|
||||
.pResource = self->resource,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
.SubresourceIndex = 0,
|
||||
}),
|
||||
NULL);
|
||||
hr_return_if_fail (ID3D12GraphicsCommandList_Close (commands));
|
||||
|
||||
if (self->fence)
|
||||
ID3D12CommandQueue_Wait (queue, self->fence, self->fence_wait);
|
||||
|
||||
ID3D12CommandQueue_ExecuteCommandLists (queue, 1, (ID3D12CommandList **) &commands);
|
||||
|
||||
#define FENCE_SIGNAL 1
|
||||
hr_return_if_fail (ID3D12CommandQueue_Signal (queue, fence, FENCE_SIGNAL));
|
||||
hr_return_if_fail (ID3D12Fence_SetEventOnCompletion (fence, FENCE_SIGNAL, NULL));
|
||||
|
||||
hr_return_if_fail (ID3D12Resource_Map (buffer,
|
||||
0,
|
||||
(&(D3D12_RANGE) {
|
||||
.Begin = 0,
|
||||
.End = buffer_size,
|
||||
}),
|
||||
&buffer_data));
|
||||
|
||||
gdk_dxgi_format_convert (resource_desc.Format,
|
||||
gdk_memory_format_alpha (texture->format) != GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
buffer_data,
|
||||
footprint.Footprint.RowPitch,
|
||||
texture->color_state,
|
||||
format,
|
||||
data,
|
||||
stride,
|
||||
color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
ID3D12Resource_Unmap (buffer, 0, (&(D3D12_RANGE) { 0, 0 }));
|
||||
|
||||
gdk_win32_com_clear (&buffer);
|
||||
gdk_win32_com_clear (&commands);
|
||||
gdk_win32_com_clear (&allocator);
|
||||
gdk_win32_com_clear (&queue);
|
||||
gdk_win32_com_clear (&fence);
|
||||
gdk_win32_com_clear (&device);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_class_init (GdkD3D12TextureClass *klass)
|
||||
{
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download = gdk_d3d12_texture_download;
|
||||
|
||||
gobject_class->dispose = gdk_d3d12_texture_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_init (GdkD3D12Texture *self)
|
||||
{
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_d3d12_texture_new_from_builder (GdkD3D12TextureBuilder *builder,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
GdkD3D12Texture *self;
|
||||
GdkTexture *update_texture;
|
||||
GdkColorState *color_state;
|
||||
GdkMemoryFormat format;
|
||||
ID3D12Resource *resource;
|
||||
ID3D12Fence *fence;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
gboolean premultiplied;
|
||||
|
||||
resource = gdk_d3d12_texture_builder_get_resource (builder);
|
||||
fence = gdk_d3d12_texture_builder_get_fence (builder);
|
||||
premultiplied = gdk_d3d12_texture_builder_get_premultiplied (builder);
|
||||
ID3D12Resource_GetDesc (resource, &desc);
|
||||
|
||||
if (desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_D3D12_ERROR, GDK_D3D12_ERROR_UNSUPPORTED_FORMAT,
|
||||
"Resource must be 2D texture");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!gdk_dxgi_format_is_supported (desc.Format))
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_D3D12_ERROR, GDK_D3D12_ERROR_UNSUPPORTED_FORMAT,
|
||||
"Unsupported DXGI format %u", desc.Format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
format = gdk_dxgi_format_get_memory_format (desc.Format, premultiplied);
|
||||
|
||||
/* FIXME: Do we need to validate the desc.SampleDesc? */
|
||||
|
||||
color_state = gdk_d3d12_texture_builder_get_color_state (builder);
|
||||
if (color_state == NULL)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
self = (GdkD3D12Texture *) g_object_new (GDK_TYPE_D3D12_TEXTURE,
|
||||
"width", (int) desc.Width,
|
||||
"height", (int) desc.Height,
|
||||
"color-state", color_state,
|
||||
NULL);
|
||||
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
ID3D12Resource_AddRef (resource);
|
||||
self->resource = resource;
|
||||
if (fence)
|
||||
{
|
||||
ID3D12Fence_AddRef (fence);
|
||||
self->fence = fence;
|
||||
self->fence_wait = gdk_d3d12_texture_builder_get_fence_wait (builder);
|
||||
}
|
||||
|
||||
GDK_DEBUG (D3D12,
|
||||
"Creating %ux%u D3D12 texture, format %u",
|
||||
(UINT) desc.Width, desc.Height,
|
||||
desc.Format);
|
||||
|
||||
/* Set this only once we know that the texture will be created.
|
||||
* Otherwise dispose() will run the callback */
|
||||
self->destroy = destroy;
|
||||
self->data = data;
|
||||
|
||||
update_texture = gdk_d3d12_texture_builder_get_update_texture (builder);
|
||||
if (update_texture)
|
||||
{
|
||||
cairo_region_t *update_region = gdk_d3d12_texture_builder_get_update_region (builder);
|
||||
if (update_region)
|
||||
{
|
||||
cairo_rectangle_int_t tex_rect = { 0, 0,
|
||||
update_texture->width, update_texture->height };
|
||||
update_region = cairo_region_copy (update_region);
|
||||
cairo_region_intersect_rectangle (update_region, &tex_rect);
|
||||
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
|
||||
#if 0
|
||||
g_set_error_literal (error, GDK_D3D12_ERROR, GDK_D3D12_ERROR_NOT_AVAILABLE,
|
||||
"d3d12 support disabled at compile-time.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ID3D12Resource *
|
||||
gdk_d3d12_texture_get_resource (GdkD3D12Texture *self)
|
||||
{
|
||||
return self->resource;
|
||||
}
|
||||
|
||||
G_LOCK_DEFINE_STATIC(handle_creation);
|
||||
|
||||
HANDLE
|
||||
gdk_d3d12_texture_get_resource_handle (GdkD3D12Texture *self)
|
||||
{
|
||||
ID3D12Device *device = NULL;
|
||||
D3D12_HEAP_FLAGS heap_flags;
|
||||
HANDLE result;
|
||||
HRESULT hr;
|
||||
|
||||
result = g_atomic_pointer_get (&self->resource_handle);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
G_LOCK (handle_creation);
|
||||
|
||||
result = g_atomic_pointer_get (&self->resource_handle);
|
||||
if (result)
|
||||
goto out;
|
||||
|
||||
if (FAILED (ID3D12Resource_GetHeapProperties (self->resource, NULL, &heap_flags)) ||
|
||||
(heap_flags & D3D12_HEAP_FLAG_SHARED == 0))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Cannot export handle, heap is not shared");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (FAILED (ID3D12Resource_GetDevice (self->resource,
|
||||
&IID_ID3D12Device,
|
||||
(void **) &device)))
|
||||
goto out;
|
||||
|
||||
hr = ID3D12Device_CreateSharedHandle (device,
|
||||
(ID3D12DeviceChild *)self->resource,
|
||||
NULL,
|
||||
GENERIC_ALL,
|
||||
NULL,
|
||||
&result);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Failed to create shared handle for texture: %s",
|
||||
g_win32_error_message (hr));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_atomic_pointer_set (&self->resource_handle, result);
|
||||
|
||||
out:
|
||||
gdk_win32_com_clear (&device);
|
||||
|
||||
G_UNLOCK (handle_creation);
|
||||
return result;
|
||||
}
|
||||
|
||||
ID3D12Fence *
|
||||
gdk_d3d12_texture_get_fence (GdkD3D12Texture *self)
|
||||
{
|
||||
return self->fence;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
gdk_d3d12_texture_get_fence_handle (GdkD3D12Texture *self)
|
||||
{
|
||||
ID3D12Device *device = NULL;
|
||||
D3D12_HEAP_FLAGS heap_flags;
|
||||
HANDLE result;
|
||||
HRESULT hr;
|
||||
|
||||
if (self->fence == NULL)
|
||||
return NULL;
|
||||
|
||||
result = g_atomic_pointer_get (&self->fence_handle);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
G_LOCK (handle_creation);
|
||||
|
||||
result = g_atomic_pointer_get (&self->fence_handle);
|
||||
if (result)
|
||||
goto out;
|
||||
|
||||
if (FAILED (ID3D12Fence_GetDevice (self->fence,
|
||||
&IID_ID3D12Device,
|
||||
(void **) &device)))
|
||||
goto out;
|
||||
|
||||
hr = ID3D12Device_CreateSharedHandle (device,
|
||||
(ID3D12DeviceChild *) self->fence,
|
||||
NULL,
|
||||
GENERIC_ALL,
|
||||
NULL,
|
||||
&result);
|
||||
if (FAILED (hr))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Failed to create shared handle for fence: %s",
|
||||
g_win32_error_message (hr));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_atomic_pointer_set (&self->fence_handle, result);
|
||||
|
||||
out:
|
||||
gdk_win32_com_clear (&device);
|
||||
|
||||
G_UNLOCK (handle_creation);
|
||||
return result;
|
||||
}
|
||||
|
||||
guint64
|
||||
gdk_d3d12_texture_get_fence_wait (GdkD3D12Texture *self)
|
||||
{
|
||||
return self->fence_wait;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_d3d12_texture_import_gl:
|
||||
* @self: texture to import into GL
|
||||
* @context: GL context to use for the import. The context
|
||||
* must be the current context.
|
||||
* @out_mem_id: (out): out result for the memory object
|
||||
* created during the import. See GL_EXT_memory_object_win32
|
||||
* for details.
|
||||
*
|
||||
* Imports the given D3D12 texture into the given OpenGL
|
||||
* context.
|
||||
*
|
||||
* This function binds `GL_TEXTURE_2D` during the import.
|
||||
*
|
||||
* Returns: The newly created texture or 0 on failure.
|
||||
*/
|
||||
guint
|
||||
gdk_d3d12_texture_import_gl (GdkD3D12Texture *self,
|
||||
GdkGLContext *context,
|
||||
guint *out_mem_id)
|
||||
{
|
||||
GdkTexture *texture = GDK_TEXTURE (self);
|
||||
GLuint tex_id, mem_id;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
HANDLE handle;
|
||||
GLenum gl_internal_format;
|
||||
GLenum gl_error;
|
||||
|
||||
/* We assume that the context is current, the caller needs to juggle that */
|
||||
g_assert (gdk_gl_context_get_current () == context);
|
||||
|
||||
if (!gdk_gl_context_has_feature (context, GDK_GL_FEATURE_EXTERNAL_OBJECTS_WIN32))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Not importing %ux%u texture, EXT_external_objects_win32 is not supported",
|
||||
texture->width, texture->height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ID3D12Resource_GetDesc (self->resource, &desc);
|
||||
|
||||
gl_internal_format = gdk_dxgi_format_get_gl_format (desc.Format);
|
||||
if (gl_internal_format == 0)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Not importing %ux%u texture, no matching GL format for DGI format %u",
|
||||
texture->width, texture->height,
|
||||
desc.Format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle = gdk_d3d12_texture_get_resource_handle (self);
|
||||
if (!handle)
|
||||
return 0;
|
||||
|
||||
GDK_DEBUG (D3D12, "Attempting to import %ux%u texture",
|
||||
texture->width, texture->height);
|
||||
|
||||
glCreateMemoryObjectsEXT (1, &mem_id);
|
||||
glImportMemoryWin32HandleEXT (mem_id,
|
||||
0,
|
||||
GL_HANDLE_TYPE_D3D12_RESOURCE_EXT,
|
||||
handle);
|
||||
|
||||
glGenTextures (1, &tex_id);
|
||||
glBindTexture (GL_TEXTURE_2D, tex_id);
|
||||
glTexStorageMem2DEXT (GL_TEXTURE_2D,
|
||||
desc.MipLevels,
|
||||
gl_internal_format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mem_id,
|
||||
0);
|
||||
|
||||
gl_error = glGetError ();
|
||||
if (gl_error != GL_NO_ERROR)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Failed to import %ux%u texture, got GL error %u",
|
||||
texture->width, texture->height,
|
||||
gl_error);
|
||||
glDeleteTextures (1, &tex_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_mem_id = mem_id;
|
||||
|
||||
return tex_id;
|
||||
}
|
||||
67
gdk/win32/gdkd3d12texture.h
Normal file
67
gdk/win32/gdkd3d12texture.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* gdkd3d12texture.h
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDKWIN32_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdktexture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_D3D12_TEXTURE (gdk_d3d12_texture_get_type ())
|
||||
|
||||
#define GDK_D3D12_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_D3D12_TEXTURE, GdkD3D12Texture))
|
||||
#define GDK_IS_D3D12_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_D3D12_TEXTURE))
|
||||
|
||||
#define GDK_D3D12_ERROR (gdk_d3d12_error_quark ())
|
||||
|
||||
typedef struct _GdkD3D12Texture GdkD3D12Texture;
|
||||
typedef struct _GdkD3D12TextureClass GdkD3D12TextureClass;
|
||||
|
||||
/**
|
||||
* GdkD3D12Error:
|
||||
* @GDK_D3D12_ERROR_NOT_AVAILABLE: D3D12 support is not available, because the OS
|
||||
* is not Windows, the Windows version is not recent enough, or it was explicitly
|
||||
* disabled at compile- or runtime
|
||||
* @GDK_D3D12_ERROR_UNSUPPORTED_FORMAT: The requested format is not supported
|
||||
* @GDK_D3D12_ERROR_CREATION_FAILED: GTK failed to create the resource for other
|
||||
* reasons
|
||||
*
|
||||
* Error enumeration for `GdkD3D12Texture`.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_D3D12_ERROR_NOT_AVAILABLE,
|
||||
GDK_D3D12_ERROR_UNSUPPORTED_FORMAT,
|
||||
GDK_D3D12_ERROR_CREATION_FAILED,
|
||||
} GdkD3D12Error;
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GType gdk_d3d12_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GQuark gdk_d3d12_error_quark (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkD3D12Texture, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
677
gdk/win32/gdkd3d12texturebuilder.c
Normal file
677
gdk/win32/gdkd3d12texturebuilder.c
Normal file
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* Copyright © 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkd3d12texturebuilder.h"
|
||||
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkd3d12textureprivate.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
struct _GdkD3D12TextureBuilder
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
ID3D12Resource *resource;
|
||||
ID3D12Fence *fence;
|
||||
guint64 fence_wait;
|
||||
|
||||
GdkColorState *color_state;
|
||||
gboolean premultiplied;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
};
|
||||
|
||||
struct _GdkD3D12TextureBuilderClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:
|
||||
*
|
||||
* `GdkD3D12TextureBuilder` is a builder used to construct [class@Gdk.Texture]
|
||||
* objects from [ID3D12Resources](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12resource).
|
||||
*
|
||||
* The operation of `GdkD3D12TextureBuilder` is quite simple: Create a texture builder,
|
||||
* set all the necessary properties, and then call [method@Gdk.D3d12TextureBuilder.build]
|
||||
* to create the new texture.
|
||||
*
|
||||
* Not all `D3D12Resources` can be used. You have to use a texture resource for a `GdkTexture`.
|
||||
* GDK will attempt to detect invalid resources and fail to create the texture in that case.
|
||||
|
||||
* `GdkD3D12TextureBuilder` can be used for quick one-shot construction of
|
||||
* textures as well as kept around and reused to construct multiple textures.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_FENCE,
|
||||
PROP_FENCE_WAIT,
|
||||
PROP_RESOURCE,
|
||||
PROP_PREMULTIPLIED,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkD3D12TextureBuilder, gdk_d3d12_texture_builder, G_TYPE_OBJECT)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_builder_dispose (GObject *object)
|
||||
{
|
||||
GdkD3D12TextureBuilder *self = GDK_D3D12_TEXTURE_BUILDER (object);
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
gdk_win32_com_clear (&self->resource);
|
||||
gdk_win32_com_clear (&self->fence);
|
||||
|
||||
G_OBJECT_CLASS (gdk_d3d12_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_builder_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkD3D12TextureBuilder *self = GDK_D3D12_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_FENCE:
|
||||
g_value_set_pointer (value, self->fence);
|
||||
break;
|
||||
|
||||
case PROP_FENCE_WAIT:
|
||||
g_value_set_uint64 (value, self->fence_wait);
|
||||
break;
|
||||
|
||||
case PROP_PREMULTIPLIED:
|
||||
g_value_set_boolean (value, self->premultiplied);
|
||||
break;
|
||||
|
||||
case PROP_RESOURCE:
|
||||
g_value_set_pointer (value, self->resource);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
g_value_set_object (value, self->update_texture);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_builder_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkD3D12TextureBuilder *self = GDK_D3D12_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_d3d12_texture_builder_set_color_state (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_FENCE:
|
||||
gdk_d3d12_texture_builder_set_fence (self, g_value_get_pointer (value));
|
||||
break;
|
||||
|
||||
case PROP_FENCE_WAIT:
|
||||
gdk_d3d12_texture_builder_set_fence_wait (self, g_value_get_uint64 (value));
|
||||
break;
|
||||
|
||||
case PROP_PREMULTIPLIED:
|
||||
gdk_d3d12_texture_builder_set_premultiplied (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_RESOURCE:
|
||||
gdk_d3d12_texture_builder_set_resource (self, g_value_get_pointer (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_d3d12_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
gdk_d3d12_texture_builder_set_update_texture (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_builder_class_init (GdkD3D12TextureBuilderClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gdk_d3d12_texture_builder_dispose;
|
||||
gobject_class->get_property = gdk_d3d12_texture_builder_get_property;
|
||||
gobject_class->set_property = gdk_d3d12_texture_builder_set_property;
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:color-state:
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:fence:
|
||||
*
|
||||
* The optional `ID3D12Fence` to wait on before using the resource.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_FENCE] =
|
||||
g_param_spec_pointer ("fence", NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:fence-wait:
|
||||
*
|
||||
* The value the fence should wait on
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_FENCE_WAIT] =
|
||||
g_param_spec_uint64 ("fence-wait", NULL, NULL,
|
||||
0, G_MAXUINT64, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:premultiplied:
|
||||
*
|
||||
* Whether the alpha channel is premultiplied into the others.
|
||||
*
|
||||
* Only relevant if the format has alpha.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_PREMULTIPLIED] =
|
||||
g_param_spec_boolean ("premultiplied", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:resource:
|
||||
*
|
||||
* The `ID3D12Resource`
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_RESOURCE] =
|
||||
g_param_spec_pointer ("resource", NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:update-region:
|
||||
*
|
||||
* The update region for [property@Gdk.D3d12TextureBuilder:update-texture].
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_UPDATE_REGION] =
|
||||
g_param_spec_boxed ("update-region", NULL, NULL,
|
||||
CAIRO_GOBJECT_TYPE_REGION,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkD3D12TextureBuilder:update-texture:
|
||||
*
|
||||
* The texture [property@Gdk.D3d12TextureBuilder:update-region] is an update for.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
properties[PROP_UPDATE_TEXTURE] =
|
||||
g_param_spec_object ("update-texture", NULL, NULL,
|
||||
GDK_TYPE_TEXTURE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_d3d12_texture_builder_init (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
self->premultiplied = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_new: (constructor):
|
||||
*
|
||||
* Creates a new texture builder.
|
||||
*
|
||||
* Returns: the new `GdkTextureBuilder`
|
||||
*
|
||||
* Since: 4.18
|
||||
**/
|
||||
GdkD3D12TextureBuilder *
|
||||
gdk_d3d12_texture_builder_new (void)
|
||||
{
|
||||
return (GdkD3D12TextureBuilder *) g_object_new (GDK_TYPE_D3D12_TEXTURE_BUILDER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_resource:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Returns the resource that this texture builder is
|
||||
* associated with.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the resource
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
ID3D12Resource *
|
||||
gdk_d3d12_texture_builder_get_resource (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_resource:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @resource: the resource
|
||||
*
|
||||
* Sets the resource that this texture builder is going to construct
|
||||
* a texture for.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_resource (GdkD3D12TextureBuilder *self,
|
||||
ID3D12Resource *resource)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->resource == resource)
|
||||
return;
|
||||
|
||||
if (resource)
|
||||
ID3D12Resource_AddRef (resource);
|
||||
if (self->resource)
|
||||
ID3D12Resource_Release (self->resource);
|
||||
self->resource = resource;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RESOURCE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_fence:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Returns the fence that this texture builder is
|
||||
* associated with.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the fence
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
ID3D12Fence *
|
||||
gdk_d3d12_texture_builder_get_fence (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->fence;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_fence:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @fence: the fence
|
||||
*
|
||||
* Sets the fence that this texture builder is going to construct
|
||||
* a texture for.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_fence (GdkD3D12TextureBuilder *self,
|
||||
ID3D12Fence *fence)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->fence == fence)
|
||||
return;
|
||||
|
||||
if (fence)
|
||||
ID3D12Fence_AddRef (fence);
|
||||
gdk_win32_com_clear (&self->fence);
|
||||
self->fence = fence;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FENCE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_fence_wait:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Returns the value that GTK should wait for on the fence
|
||||
* before using the resource.
|
||||
*
|
||||
* Returns: the fence wait value
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
guint64
|
||||
gdk_d3d12_texture_builder_get_fence_wait (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->fence_wait;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_fence_wait:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @fence_wait: the value to wait on
|
||||
*
|
||||
* Sets the value that GTK should wait on on the given fence before using the
|
||||
* resource.
|
||||
*
|
||||
* When no fence is set, this value has no effect.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_fence_wait (GdkD3D12TextureBuilder *self,
|
||||
guint64 fence_wait)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->fence_wait == fence_wait)
|
||||
return;
|
||||
|
||||
self->fence_wait = fence_wait;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FENCE_WAIT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_premultiplied:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Whether the data is premultiplied.
|
||||
*
|
||||
* Returns: whether the data is premultiplied
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
gboolean
|
||||
gdk_d3d12_texture_builder_get_premultiplied (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), TRUE);
|
||||
|
||||
return self->premultiplied;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_premultiplied:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @premultiplied: whether the data is premultiplied
|
||||
*
|
||||
* Sets whether the data is premultiplied.
|
||||
*
|
||||
* Unless otherwise specified, all formats including alpha channels are assumed
|
||||
* to be premultiplied.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_premultiplied (GdkD3D12TextureBuilder *self,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->premultiplied == premultiplied)
|
||||
return;
|
||||
|
||||
self->premultiplied = premultiplied;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PREMULTIPLIED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_color_state:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Gets the color state previously set via gdk_d3d12_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: (nullable) (transfer none): the color state
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_d3d12_texture_builder_get_color_state (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_color_state:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @color_state: (nullable): a `GdkColorState` or `NULL` to unset the colorstate.
|
||||
*
|
||||
* Sets the color state for the texture.
|
||||
*
|
||||
* By default, the colorstate is `NULL`. In that case, GTK will choose the
|
||||
* correct colorstate based on the format.
|
||||
* If you don't know what colorstates are, this is probably the right thing.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_color_state (GdkD3D12TextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->color_state == color_state ||
|
||||
(self->color_state != NULL && color_state != NULL && gdk_color_state_equal (self->color_state, color_state)))
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = color_state;
|
||||
if (color_state)
|
||||
gdk_color_state_ref (color_state);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_update_texture:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Gets the texture previously set via gdk_d3d12_texture_builder_set_update_texture() or
|
||||
* %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The texture
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_d3d12_texture_builder_get_update_texture (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_update_texture:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @texture: (nullable): the texture to update
|
||||
*
|
||||
* Sets the texture to be updated by this texture. See
|
||||
* [method@Gdk.D3d12TextureBuilder.set_update_region] for an explanation.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_update_texture (GdkD3D12TextureBuilder *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
|
||||
|
||||
if (!g_set_object (&self->update_texture, texture))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_get_update_region:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
*
|
||||
* Gets the region previously set via gdk_d3d12_texture_builder_set_update_region() or
|
||||
* %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The region
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
cairo_region_t *
|
||||
gdk_d3d12_texture_builder_get_update_region (GdkD3D12TextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_set_update_region:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @region: (nullable): the region to update
|
||||
*
|
||||
* Sets the region to be updated by this texture. Together with
|
||||
* [property@Gdk.D3d12TextureBuilder:update-texture] this describes an
|
||||
* update of a previous texture.
|
||||
*
|
||||
* When rendering animations of large textures, it is possible that
|
||||
* consecutive textures are only updating contents in parts of the texture.
|
||||
* It is then possible to describe this update via these two properties,
|
||||
* so that GTK can avoid rerendering parts that did not change.
|
||||
*
|
||||
* An example would be a screen recording where only the mouse pointer moves.
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
void
|
||||
gdk_d3d12_texture_builder_set_update_region (GdkD3D12TextureBuilder *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->update_region == region)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
|
||||
if (region)
|
||||
self->update_region = cairo_region_reference (region);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_d3d12_texture_builder_build:
|
||||
* @self: a `GdkD3D12TextureBuilder`
|
||||
* @destroy: (nullable): destroy function to be called when the texture is
|
||||
* released
|
||||
* @data: user data to pass to the destroy function
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Builds a new `GdkTexture` with the values set up in the builder.
|
||||
*
|
||||
* It is a programming error to call this function if any mandatory property has not been set.
|
||||
*
|
||||
* Not all formats defined in the `drm_fourcc.h` header are supported. You can use
|
||||
* [method@Gdk.Display.get_d3d12_formats] to get a list of supported formats. If the
|
||||
* format is not supported by GTK, %NULL will be returned and @error will be set.
|
||||
*
|
||||
* The `destroy` function gets called when the returned texture gets released.
|
||||
*
|
||||
* It is the responsibility of the caller to keep the file descriptors for the planes
|
||||
* open until the created texture is no longer used, and close them afterwards (possibly
|
||||
* using the @destroy notify).
|
||||
*
|
||||
* It is possible to call this function multiple times to create multiple textures,
|
||||
* possibly with changing properties in between.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): a newly built `GdkTexture` or `NULL`
|
||||
* if the format is not supported
|
||||
*
|
||||
* Since: 4.18
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_d3d12_texture_builder_build (GdkD3D12TextureBuilder *self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
|
||||
g_return_val_if_fail (destroy == NULL || data != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
g_return_val_if_fail (self->resource, NULL);
|
||||
|
||||
return gdk_d3d12_texture_new_from_builder (self, destroy, data, error);
|
||||
}
|
||||
90
gdk/win32/gdkd3d12texturebuilder.h
Normal file
90
gdk/win32/gdkd3d12texturebuilder.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright © 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDKWIN32_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
#include <directx/d3d12.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_D3D12_TEXTURE_BUILDER (gdk_d3d12_texture_builder_get_type ())
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GDK_DECLARE_INTERNAL_TYPE (GdkD3D12TextureBuilder, gdk_d3d12_texture_builder, GDK, D3D12_TEXTURE_BUILDER, GObject)
|
||||
|
||||
typedef struct _GdkD3D12TextureBuilder GdkD3D12TextureBuilder;
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GdkD3D12TextureBuilder * gdk_d3d12_texture_builder_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
ID3D12Resource * gdk_d3d12_texture_builder_get_resource (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_resource (GdkD3D12TextureBuilder *self,
|
||||
ID3D12Resource *resource);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
ID3D12Fence * gdk_d3d12_texture_builder_get_fence (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_fence (GdkD3D12TextureBuilder *self,
|
||||
ID3D12Fence *fence);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
guint64 gdk_d3d12_texture_builder_get_fence_wait (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_fence_wait (GdkD3D12TextureBuilder *self,
|
||||
guint64 fence_wait);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
gboolean gdk_d3d12_texture_builder_get_premultiplied (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_premultiplied (GdkD3D12TextureBuilder *self,
|
||||
gboolean premultiplied);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GdkColorState * gdk_d3d12_texture_builder_get_color_state (GdkD3D12TextureBuilder *self);
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_color_state (GdkD3D12TextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GdkTexture * gdk_d3d12_texture_builder_get_update_texture (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_update_texture (GdkD3D12TextureBuilder *self,
|
||||
GdkTexture *texture);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
cairo_region_t * gdk_d3d12_texture_builder_get_update_region (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
void gdk_d3d12_texture_builder_set_update_region (GdkD3D12TextureBuilder *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
GDK_AVAILABLE_IN_4_18
|
||||
GdkTexture * gdk_d3d12_texture_builder_build (GdkD3D12TextureBuilder *self,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
25
gdk/win32/gdkd3d12textureprivate.h
Normal file
25
gdk/win32/gdkd3d12textureprivate.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkd3d12texture.h"
|
||||
|
||||
#include "gdkd3d12texturebuilder.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GdkTexture * gdk_d3d12_texture_new_from_builder (GdkD3D12TextureBuilder *builder,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data,
|
||||
GError **error);
|
||||
|
||||
ID3D12Resource * gdk_d3d12_texture_get_resource (GdkD3D12Texture *self);
|
||||
HANDLE gdk_d3d12_texture_get_resource_handle (GdkD3D12Texture *self);
|
||||
ID3D12Fence * gdk_d3d12_texture_get_fence (GdkD3D12Texture *self);
|
||||
HANDLE gdk_d3d12_texture_get_fence_handle (GdkD3D12Texture *self);
|
||||
guint64 gdk_d3d12_texture_get_fence_wait (GdkD3D12Texture *self);
|
||||
|
||||
guint gdk_d3d12_texture_import_gl (GdkD3D12Texture *self,
|
||||
GdkGLContext *context,
|
||||
guint *out_mem_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
1338
gdk/win32/gdkdxgiformat.c
Normal file
1338
gdk/win32/gdkdxgiformat.c
Normal file
File diff suppressed because it is too large
Load Diff
32
gdk/win32/gdkdxgiformatprivate.h
Normal file
32
gdk/win32/gdkdxgiformatprivate.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdkenums.h>
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
#include <directx/d3d12.h>
|
||||
#include <epoxy/gl.h>
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
gboolean gdk_dxgi_format_is_supported (DXGI_FORMAT dxgi_format);
|
||||
GdkMemoryFormat gdk_dxgi_format_get_memory_format (DXGI_FORMAT dxgi_format,
|
||||
gboolean premultiplied);
|
||||
gboolean gdk_dxgi_format_is_yuv (DXGI_FORMAT dxgi_format);
|
||||
|
||||
GLenum gdk_dxgi_format_get_gl_format (DXGI_FORMAT dxgi_format);
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkFormat gdk_dxgi_format_get_vk_format (DXGI_FORMAT dxgi_format,
|
||||
VkComponentMapping *out_swizzle);
|
||||
#endif
|
||||
void gdk_dxgi_format_convert (DXGI_FORMAT src_format,
|
||||
gboolean src_premultiplied,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkColorState *src_color_state,
|
||||
GdkMemoryFormat dest_format,
|
||||
guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkColorState *dest_color_state,
|
||||
gsize width,
|
||||
gsize height);
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#define __GDKWIN32_H_INSIDE__
|
||||
|
||||
#include <gdk/win32/gdkd3d12texture.h>
|
||||
#include <gdk/win32/gdkd3d12texturebuilder.h>
|
||||
#include <gdk/win32/gdkwin32cursor.h>
|
||||
#include <gdk/win32/gdkwin32display.h>
|
||||
#include <gdk/win32/gdkwin32displaymanager.h>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
gdk_win32_public_sources = files([
|
||||
'gdkcursor-win32.c',
|
||||
'gdkd3d12texture.c',
|
||||
'gdkd3d12texturebuilder.c',
|
||||
'gdkdisplay-win32.c',
|
||||
'gdkdisplaymanager-win32.c',
|
||||
'gdkdrag-win32.c',
|
||||
@@ -21,6 +23,7 @@ gdk_win32_sources = gdk_win32_public_sources + files([
|
||||
'gdkdevice-win32.c',
|
||||
'gdkdevice-winpointer.c',
|
||||
'gdkdevice-wintab.c',
|
||||
'gdkdxgiformat.c',
|
||||
'gdkdrop-win32.c',
|
||||
'gdkglcontext-win32-wgl-private.c',
|
||||
'gdkhdataoutputstream-win32.c',
|
||||
@@ -38,6 +41,8 @@ gdk_win32_sources = gdk_win32_public_sources + files([
|
||||
])
|
||||
|
||||
gdk_win32_public_headers = files([
|
||||
'gdkd3d12texture.h',
|
||||
'gdkd3d12texturebuilder.h',
|
||||
'gdkwin32cursor.h',
|
||||
'gdkwin32display.h',
|
||||
'gdkwin32displaymanager.h',
|
||||
@@ -55,10 +60,17 @@ if have_egl
|
||||
gdk_win32_sources += ['gdkglcontext-win32-egl.c']
|
||||
endif
|
||||
|
||||
d3d12_dep = [
|
||||
cc.find_library('d3d12'),
|
||||
cc.find_library('dxgi'),
|
||||
dependency('DirectX-Headers', version: '>= 1.611'),
|
||||
]
|
||||
|
||||
gdk_win32_deps = [
|
||||
pangowin32_dep, # FIXME
|
||||
cc.find_library('hid'),
|
||||
cc.find_library('opengl32'),
|
||||
d3d12_dep,
|
||||
]
|
||||
|
||||
libgdk_win32 = static_library('gdk-win32',
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include "win32/gdkd3d12textureprivate.h"
|
||||
#endif
|
||||
struct _GskGLFrame
|
||||
{
|
||||
GskGpuFrame parent_instance;
|
||||
@@ -89,6 +92,7 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
|
||||
image = gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
gdk_gl_texture_get_id (gl_texture),
|
||||
0,
|
||||
FALSE,
|
||||
gdk_gl_texture_has_mipmap (gl_texture) ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP) : 0);
|
||||
|
||||
@@ -115,10 +119,30 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
|
||||
return gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
tex_id,
|
||||
0,
|
||||
TRUE,
|
||||
(external ? GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT : 0));
|
||||
}
|
||||
}
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
else if (GDK_IS_D3D12_TEXTURE (texture))
|
||||
{
|
||||
guint tex_id, mem_id;
|
||||
|
||||
tex_id = gdk_d3d12_texture_import_gl (GDK_D3D12_TEXTURE (texture),
|
||||
GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
||||
&mem_id);
|
||||
if (tex_id)
|
||||
{
|
||||
return gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
tex_id,
|
||||
mem_id,
|
||||
TRUE,
|
||||
0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->upload_texture (frame, with_mipmap, texture);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ struct _GskGLImage
|
||||
GskGpuImage parent_instance;
|
||||
|
||||
guint texture_id;
|
||||
guint memory_id;
|
||||
guint framebuffer_id;
|
||||
|
||||
GLint gl_internal_format;
|
||||
@@ -49,6 +50,9 @@ gsk_gl_image_finalize (GObject *object)
|
||||
if (self->owns_texture)
|
||||
glDeleteTextures (1, &self->texture_id);
|
||||
|
||||
if (self->memory_id)
|
||||
glDeleteMemoryObjectsEXT (1, &self->memory_id);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -216,6 +220,7 @@ GskGpuImage *
|
||||
gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
GdkTexture *owner,
|
||||
GLuint tex_id,
|
||||
GLuint mem_id,
|
||||
gboolean take_ownership,
|
||||
GskGpuImageFlags extra_flags)
|
||||
{
|
||||
@@ -258,6 +263,7 @@ gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
gsk_gpu_image_toggle_ref_texture (GSK_GPU_IMAGE (self), owner);
|
||||
|
||||
self->texture_id = tex_id;
|
||||
self->memory_id = mem_id;
|
||||
self->owns_texture = take_ownership;
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
|
||||
@@ -25,6 +25,7 @@ GskGpuImage * gsk_gl_image_new (GskGLDe
|
||||
GskGpuImage * gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
GdkTexture *owner,
|
||||
GLuint tex_id,
|
||||
GLuint mem_id,
|
||||
gboolean take_ownership,
|
||||
GskGpuImageFlags extra_flags);
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ gsk_vulkan_buffer_new_internal (GskVulkanDevice *device,
|
||||
{
|
||||
VkMemoryRequirements requirements;
|
||||
GskVulkanBuffer *self;
|
||||
gsize memory_index;
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_BUFFER, NULL);
|
||||
|
||||
@@ -94,11 +95,14 @@ gsk_vulkan_buffer_new_internal (GskVulkanDevice *device,
|
||||
self->vk_buffer,
|
||||
&requirements);
|
||||
|
||||
self->allocator = gsk_vulkan_device_find_allocator (device,
|
||||
requirements.memoryTypeBits,
|
||||
GSK_VULKAN_MEMORY_MAPPABLE,
|
||||
GSK_VULKAN_MEMORY_MAPPABLE |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
requirements.memoryTypeBits,
|
||||
GSK_VULKAN_MEMORY_MAPPABLE,
|
||||
GSK_VULKAN_MEMORY_MAPPABLE |
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
|
||||
self->allocator = gsk_vulkan_device_get_allocator (device, memory_index);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
||||
gsk_vulkan_alloc (self->allocator,
|
||||
requirements.size,
|
||||
requirements.alignment,
|
||||
|
||||
@@ -1033,16 +1033,20 @@ gsk_vulkan_device_get_vk_pipeline (GskVulkanDevice *self,
|
||||
return vk_pipeline;
|
||||
}
|
||||
|
||||
static GskVulkanAllocator *
|
||||
GskVulkanAllocator *
|
||||
gsk_vulkan_device_get_allocator (GskVulkanDevice *self,
|
||||
gsize index,
|
||||
const VkMemoryType *type)
|
||||
gsize index)
|
||||
{
|
||||
if (self->allocators[index] == NULL)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties properties;
|
||||
|
||||
vkGetPhysicalDeviceMemoryProperties (gsk_vulkan_device_get_vk_physical_device (self),
|
||||
&properties);
|
||||
|
||||
self->allocators[index] = gsk_vulkan_direct_allocator_new (gsk_vulkan_device_get_vk_device (self),
|
||||
index,
|
||||
type);
|
||||
&properties.memoryTypes[index]);
|
||||
self->allocators[index] = gsk_vulkan_buddy_allocator_new (self->allocators[index],
|
||||
1024 * 1024);
|
||||
//allocators[index] = gsk_vulkan_stats_allocator_new (allocators[index]);
|
||||
@@ -1053,11 +1057,11 @@ gsk_vulkan_device_get_allocator (GskVulkanDevice *self,
|
||||
|
||||
/* following code found in
|
||||
* https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceMemoryProperties.html */
|
||||
GskVulkanAllocator *
|
||||
gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
|
||||
uint32_t allowed_types,
|
||||
VkMemoryPropertyFlags required_flags,
|
||||
VkMemoryPropertyFlags desired_flags)
|
||||
gsize
|
||||
gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
|
||||
uint32_t allowed_types,
|
||||
VkMemoryPropertyFlags required_flags,
|
||||
VkMemoryPropertyFlags desired_flags)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties properties;
|
||||
uint32_t i, found;
|
||||
@@ -1085,7 +1089,7 @@ gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
|
||||
|
||||
g_assert (found < properties.memoryTypeCount);
|
||||
|
||||
return gsk_vulkan_allocator_ref (gsk_vulkan_device_get_allocator (self, found, &properties.memoryTypes[found]));
|
||||
return found;
|
||||
}
|
||||
|
||||
GskVulkanAllocator *
|
||||
|
||||
@@ -67,10 +67,14 @@ VkPipeline gsk_vulkan_device_get_vk_pipeline (GskVulk
|
||||
VkRenderPass render_pass);
|
||||
|
||||
GskVulkanAllocator * gsk_vulkan_device_get_external_allocator (GskVulkanDevice *self);
|
||||
GskVulkanAllocator * gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
|
||||
GskVulkanAllocator * gsk_vulkan_device_get_allocator (GskVulkanDevice *self,
|
||||
gsize index);
|
||||
|
||||
gsize gsk_vulkan_device_find_allocator (GskVulkanDevice *self,
|
||||
uint32_t allowed_types,
|
||||
VkMemoryPropertyFlags required_flags,
|
||||
VkMemoryPropertyFlags desired_flags);
|
||||
|
||||
static inline VkResult
|
||||
gsk_vulkan_handle_result (VkResult res,
|
||||
const char *called_function)
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkgltextureprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include "gdk/win32/gdkd3d12textureprivate.h"
|
||||
#endif
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_semaphores
|
||||
#define GDK_ARRAY_TYPE_NAME GskSemaphores
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkSemaphore
|
||||
@@ -18,6 +22,13 @@
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_semaphore_values
|
||||
#define GDK_ARRAY_TYPE_NAME GskSemaphoreValues
|
||||
#define GDK_ARRAY_ELEMENT_TYPE uint64_t
|
||||
#define GDK_ARRAY_PREALLOC 16
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_pipeline_stages
|
||||
#define GDK_ARRAY_TYPE_NAME GskPipelineStages
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkPipelineStageFlags
|
||||
@@ -28,6 +39,7 @@
|
||||
struct _GskVulkanSemaphores
|
||||
{
|
||||
GskSemaphores wait_semaphores;
|
||||
GskSemaphoreValues wait_semaphore_values;
|
||||
GskPipelineStages wait_stages;
|
||||
GskSemaphores signal_semaphores;
|
||||
};
|
||||
@@ -218,6 +230,26 @@ gsk_vulkan_frame_upload_texture (GskGpuFrame *frame,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_D3D12_TEXTURE (texture))
|
||||
{
|
||||
GdkD3D12Texture *d3d_texture = GDK_D3D12_TEXTURE (texture);
|
||||
GskGpuImage *image;
|
||||
|
||||
image = gsk_vulkan_image_new_for_d3d12resource (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
gdk_d3d12_texture_get_resource (d3d_texture),
|
||||
gdk_d3d12_texture_get_resource_handle (d3d_texture),
|
||||
gdk_d3d12_texture_get_fence (d3d_texture),
|
||||
gdk_d3d12_texture_get_fence_handle (d3d_texture),
|
||||
gdk_d3d12_texture_get_fence_wait (d3d_texture),
|
||||
gdk_memory_format_alpha (gdk_texture_get_format (texture)) != GDK_MEMORY_ALPHA_STRAIGHT);
|
||||
if (image)
|
||||
{
|
||||
gsk_gpu_image_toggle_ref_texture (image, texture);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GSK_GPU_FRAME_CLASS (gsk_vulkan_frame_parent_class)->upload_texture (frame, with_mipmap, texture);
|
||||
}
|
||||
@@ -260,9 +292,12 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
GskGpuOp *op)
|
||||
{
|
||||
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
|
||||
GskVulkanDevice *device;
|
||||
GskVulkanSemaphores semaphores;
|
||||
GskVulkanCommandState state = { 0, };
|
||||
|
||||
device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame));
|
||||
|
||||
GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer,
|
||||
&(VkCommandBufferBeginInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
@@ -279,6 +314,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
(VkDeviceSize[1]) { 0 });
|
||||
|
||||
gsk_semaphores_init (&semaphores.wait_semaphores);
|
||||
gsk_semaphore_values_init (&semaphores.wait_semaphore_values);
|
||||
gsk_pipeline_stages_init (&semaphores.wait_stages);
|
||||
gsk_semaphores_init (&semaphores.signal_semaphores);
|
||||
|
||||
@@ -286,6 +322,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
{
|
||||
gsk_vulkan_semaphores_add_wait (&semaphores,
|
||||
self->vk_acquire_semaphore,
|
||||
0,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||
}
|
||||
|
||||
@@ -302,7 +339,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
|
||||
GSK_VK_CHECK (vkEndCommandBuffer, self->vk_command_buffer);
|
||||
|
||||
GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame))),
|
||||
GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (device),
|
||||
1,
|
||||
&(VkSubmitInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
@@ -313,10 +350,16 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
.waitSemaphoreCount = gsk_semaphores_get_size (&semaphores.wait_semaphores),
|
||||
.pSignalSemaphores = gsk_semaphores_get_data (&semaphores.signal_semaphores),
|
||||
.signalSemaphoreCount = gsk_semaphores_get_size (&semaphores.signal_semaphores),
|
||||
.pNext = gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE) ? &(VkTimelineSemaphoreSubmitInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
|
||||
.waitSemaphoreValueCount = gsk_semaphore_values_get_size (&semaphores.wait_semaphore_values),
|
||||
.pWaitSemaphoreValues = gsk_semaphore_values_get_data (&semaphores.wait_semaphore_values),
|
||||
} : NULL,
|
||||
},
|
||||
self->vk_fence);
|
||||
|
||||
gsk_semaphores_clear (&semaphores.wait_semaphores);
|
||||
gsk_semaphore_values_clear (&semaphores.wait_semaphore_values);
|
||||
gsk_pipeline_stages_clear (&semaphores.wait_stages);
|
||||
gsk_semaphores_clear (&semaphores.signal_semaphores);
|
||||
}
|
||||
@@ -384,9 +427,11 @@ gsk_vulkan_frame_get_vk_fence (GskVulkanFrame *self)
|
||||
void
|
||||
gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore,
|
||||
guint64 semaphore_wait,
|
||||
VkPipelineStageFlags stage)
|
||||
{
|
||||
gsk_semaphores_append (&self->wait_semaphores, semaphore);
|
||||
gsk_semaphore_values_append (&self->wait_semaphore_values, semaphore_wait);
|
||||
gsk_pipeline_stages_append (&self->wait_stages, stage);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ VkFence gsk_vulkan_frame_get_vk_fence (GskVulk
|
||||
|
||||
void gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore,
|
||||
uint64_t semaphore_wait,
|
||||
VkPipelineStageFlags stage);
|
||||
void gsk_vulkan_semaphores_add_signal (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore);
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <linux/dma-buf.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkdxgiformatprivate.h>
|
||||
#endif
|
||||
|
||||
struct _GskVulkanImage
|
||||
{
|
||||
@@ -34,6 +37,7 @@ struct _GskVulkanImage
|
||||
VkImageView vk_framebuffer_image_view;
|
||||
GskVulkanYcbcr *ycbcr;
|
||||
VkSemaphore vk_semaphore;
|
||||
uint64_t vk_semaphore_wait;
|
||||
struct {
|
||||
VkDescriptorSet vk_descriptor_set;
|
||||
gsize pool_id;
|
||||
@@ -265,6 +269,7 @@ gsk_vulkan_image_new (GskVulkanDevice *device,
|
||||
GskGpuImageFlags flags;
|
||||
VkFormat vk_format, vk_srgb_format;
|
||||
VkComponentMapping vk_components;
|
||||
gsize memory_index;
|
||||
|
||||
g_assert (width > 0 && height > 0);
|
||||
|
||||
@@ -386,10 +391,13 @@ gsk_vulkan_image_new (GskVulkanDevice *device,
|
||||
self->vk_image,
|
||||
&requirements);
|
||||
|
||||
self->allocator = gsk_vulkan_device_find_allocator (device,
|
||||
requirements.memoryTypeBits,
|
||||
0,
|
||||
tiling == VK_IMAGE_TILING_LINEAR ? GSK_VULKAN_MEMORY_MAPPABLE : 0);
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
requirements.memoryTypeBits,
|
||||
0,
|
||||
tiling == VK_IMAGE_TILING_LINEAR ? GSK_VULKAN_MEMORY_MAPPABLE : 0);
|
||||
self->allocator = gsk_vulkan_device_get_allocator (device, memory_index);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
||||
gsk_vulkan_alloc (self->allocator,
|
||||
requirements.size,
|
||||
requirements.alignment,
|
||||
@@ -676,6 +684,7 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
|
||||
VkFormat vk_format, vk_srgb_format;
|
||||
VkComponentMapping vk_components;
|
||||
VkMemoryRequirements requirements;
|
||||
gsize memory_index;
|
||||
GskVulkanImage *self;
|
||||
VkResult res;
|
||||
gsize n_modifiers;
|
||||
@@ -809,6 +818,10 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
|
||||
self->vk_image,
|
||||
&requirements);
|
||||
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
requirements.memoryTypeBits,
|
||||
0,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
self->allocator = gsk_vulkan_device_get_external_allocator (device);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
||||
@@ -821,7 +834,7 @@ gsk_vulkan_image_new_dmabuf (GskVulkanDevice *device,
|
||||
&(VkMemoryAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = requirements.size,
|
||||
.memoryTypeIndex = g_bit_nth_lsf (requirements.memoryTypeBits, -1),
|
||||
.memoryTypeIndex = memory_index,
|
||||
.pNext = &(VkExportMemoryAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
||||
@@ -994,6 +1007,7 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
VkMemoryRequirements2 requirements = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
};
|
||||
gsize memory_index;
|
||||
|
||||
GSK_VK_CHECK (func_vkGetMemoryFdPropertiesKHR, vk_device,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
||||
@@ -1037,6 +1051,10 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
}
|
||||
}
|
||||
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
fd_props.memoryTypeBits,
|
||||
0,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
gsk_vulkan_alloc (self->allocator,
|
||||
requirements.memoryRequirements.size,
|
||||
requirements.memoryRequirements.alignment,
|
||||
@@ -1045,7 +1063,7 @@ gsk_vulkan_image_new_for_dmabuf (GskVulkanDevice *device,
|
||||
&(VkMemoryAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = requirements.memoryRequirements.size,
|
||||
.memoryTypeIndex = g_bit_nth_lsf (fd_props.memoryTypeBits, -1),
|
||||
.memoryTypeIndex = memory_index,
|
||||
.pNext = &(VkImportMemoryFdInfoKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
|
||||
@@ -1269,6 +1287,236 @@ gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
static gboolean
|
||||
gsk_vulkan_is_same_device (VkDevice vk_device,
|
||||
ID3D12DeviceChild *child)
|
||||
{
|
||||
/* FIXME: implement */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_vulkan_image_new_for_d3d12resource (GskVulkanDevice *device,
|
||||
ID3D12Resource *resource,
|
||||
HANDLE resource_handle,
|
||||
ID3D12Fence *fence,
|
||||
HANDLE fence_handle,
|
||||
guint64 fence_wait,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
VkDevice vk_device;
|
||||
VkFormat vk_format;
|
||||
VkComponentMapping vk_components;
|
||||
VkSamplerYcbcrConversion vk_conversion;
|
||||
PFN_vkGetMemoryWin32HandlePropertiesKHR func_vkGetMemoryWin32HandlePropertiesKHR;
|
||||
VkResult res;
|
||||
GdkMemoryFormat format;
|
||||
GskGpuImageFlags flags;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
gsize memory_index;
|
||||
gboolean is_yuv;
|
||||
VkMemoryRequirements2 requirements = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
};
|
||||
VkMemoryWin32HandlePropertiesKHR handle_properties = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR,
|
||||
};
|
||||
|
||||
if (!gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_WIN32))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Vulkan does not support D3D12Resource import");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (device);
|
||||
func_vkGetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR) vkGetDeviceProcAddr (vk_device, "vkGetMemoryWin32HandlePropertiesKHR");
|
||||
ID3D12Resource_GetDesc (resource, &desc);
|
||||
|
||||
if (!gsk_vulkan_is_same_device (vk_device, (ID3D12DeviceChild *) resource))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Resource is from a different device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vk_format = gdk_dxgi_format_get_vk_format (desc.Format, &vk_components);
|
||||
if (vk_format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "GTK's Vulkan doesn't support DXGI format %u", desc.Format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_yuv = gdk_dxgi_format_is_yuv (desc.Format);
|
||||
if (is_yuv && !gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_YCBCR))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Vulkan driver cannot import DXGI format %u because it is YUV", desc.Format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!gsk_vulkan_device_supports_format (device,
|
||||
vk_format,
|
||||
dmabuf->modifier,
|
||||
dmabuf->n_planes,
|
||||
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
width, height,
|
||||
&flags))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Vulkan driver does not support format %.4s::%016llx with %u planes",
|
||||
(char *) &dmabuf->fourcc, (unsigned long long) dmabuf->modifier, dmabuf->n_planes);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
|
||||
|
||||
self->device = g_object_ref (device);
|
||||
self->vk_tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
self->vk_format = vk_format;
|
||||
self->vk_pipeline_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
self->vk_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
self->vk_access = 0;
|
||||
|
||||
res = vkCreateImage (vk_device,
|
||||
&(VkImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = vk_format,
|
||||
.extent = { desc.Width, desc.Height, 1 },
|
||||
.mipLevels = desc.MipLevels,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = self->vk_tiling,
|
||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
(flags & GSK_GPU_IMAGE_NO_BLIT ? 0 : VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.initialLayout = self->vk_image_layout,
|
||||
.pNext = &(VkExternalMemoryImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&self->vk_image);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "vkCreateImage() failed: %s", gdk_vulkan_strerror (res));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags |
|
||||
(!premultiplied ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0) |
|
||||
(is_yuv ? (GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT) : 0) |
|
||||
(desc.MipLevels > 1 ? GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP : 0),
|
||||
gdk_dxgi_format_get_memory_format (desc.Format, premultiplied),
|
||||
desc.Width, desc.Height);
|
||||
|
||||
vkGetImageMemoryRequirements2 (vk_device,
|
||||
&(VkImageMemoryRequirementsInfo2) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.image = self->vk_image,
|
||||
},
|
||||
&requirements);
|
||||
// Vulkan memory import
|
||||
GSK_VK_CHECK (func_vkGetMemoryWin32HandlePropertiesKHR, vk_device,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
resource_handle,
|
||||
&handle_properties);
|
||||
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
handle_properties.memoryTypeBits,
|
||||
0,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
self->allocator = gsk_vulkan_device_get_external_allocator (device);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
||||
gsk_vulkan_alloc (self->allocator,
|
||||
requirements.memoryRequirements.size,
|
||||
requirements.memoryRequirements.alignment,
|
||||
&self->allocation);
|
||||
|
||||
GSK_VK_CHECK (vkAllocateMemory, vk_device,
|
||||
&(VkMemoryAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = requirements.memoryRequirements.size,
|
||||
.memoryTypeIndex = memory_index,
|
||||
.pNext = &(VkImportMemoryWin32HandleInfoKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
.handle = resource_handle,
|
||||
.pNext = &(VkMemoryDedicatedAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||
.image = self->vk_image,
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&self->allocation.vk_memory);
|
||||
|
||||
GSK_VK_CHECK (vkBindImageMemory2, gsk_vulkan_device_get_vk_device (self->device),
|
||||
1,
|
||||
&(VkBindImageMemoryInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
||||
.image = self->vk_image,
|
||||
.memory = self->allocation.vk_memory,
|
||||
.memoryOffset = self->allocation.offset,
|
||||
});
|
||||
|
||||
if (gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_WIN32_SEMAPHORE) && fence)
|
||||
{
|
||||
PFN_vkImportSemaphoreWin32HandleKHR func_vkImportSemaphoreWin32HandleKHR;
|
||||
func_vkImportSemaphoreWin32HandleKHR = (PFN_vkImportSemaphoreWin32HandleKHR) vkGetDeviceProcAddr (vk_device, "vkImportSemaphoreWin32HandleKHR");
|
||||
|
||||
GSK_VK_CHECK (vkCreateSemaphore, vk_device,
|
||||
&(VkSemaphoreCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = &(VkSemaphoreTypeCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
|
||||
.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&self->vk_semaphore);
|
||||
|
||||
GSK_VK_CHECK (func_vkImportSemaphoreWin32HandleKHR, vk_device,
|
||||
&(VkImportSemaphoreWin32HandleInfoKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,
|
||||
.semaphore = self->vk_semaphore,
|
||||
.handle = fence_handle,
|
||||
});
|
||||
self->vk_semaphore_wait = fence_wait;
|
||||
}
|
||||
|
||||
if (is_yuv)
|
||||
{
|
||||
self->ycbcr = gsk_vulkan_device_get_ycbcr (device, vk_format);
|
||||
gsk_vulkan_ycbcr_ref (self->ycbcr);
|
||||
vk_conversion = gsk_vulkan_ycbcr_get_vk_conversion (self->ycbcr);
|
||||
}
|
||||
else
|
||||
vk_conversion = VK_NULL_HANDLE;
|
||||
|
||||
gsk_vulkan_image_create_view (self,
|
||||
vk_format,
|
||||
&vk_components,
|
||||
vk_conversion);
|
||||
|
||||
GDK_DEBUG (D3D12, "Vulkan uploaded %ux%u resource of %sformat %u",
|
||||
(guint) desc.Width, (guint) desc.Height,
|
||||
is_yuv ? "YUV " : "",
|
||||
desc.Format);
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gsk_vulkan_image_get_projection_matrix (GskGpuImage *image,
|
||||
graphene_matrix_t *out_projection)
|
||||
@@ -1501,7 +1749,10 @@ gsk_vulkan_image_transition (GskVulkanImage *self,
|
||||
if (self->vk_pipeline_stage == VK_IMAGE_LAYOUT_GENERAL &&
|
||||
self->vk_semaphore)
|
||||
{
|
||||
gsk_vulkan_semaphores_add_wait (semaphores, self->vk_semaphore, stage);
|
||||
gsk_vulkan_semaphores_add_wait (semaphores,
|
||||
self->vk_semaphore,
|
||||
self->vk_semaphore_wait,
|
||||
stage);
|
||||
}
|
||||
|
||||
vkCmdPipelineBarrier (command_buffer,
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#include "gdk/gdkdmabufprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkwin32.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
|
||||
@@ -47,6 +51,15 @@ GskGpuImage * gsk_vulkan_image_new_for_dmabuf (GskVulk
|
||||
GdkTexture * gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
|
||||
GdkColorState *color_state);
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
GskGpuImage * gsk_vulkan_image_new_for_d3d12resource (GskVulkanDevice *device,
|
||||
ID3D12Resource *resource,
|
||||
HANDLE resource_handle,
|
||||
ID3D12Fence *fence,
|
||||
HANDLE fence_handle,
|
||||
guint64 fence_wait,
|
||||
gboolean premultiplied);
|
||||
#endif
|
||||
|
||||
guchar * gsk_vulkan_image_get_data (GskVulkanImage *self,
|
||||
gsize *out_stride);
|
||||
|
||||
@@ -458,6 +458,13 @@ gstgl_dep = dependency('gstreamer-gl-1.0', version: gstreamer_req,
|
||||
required: get_option('media-gstreamer'))
|
||||
gstallocators_dep = dependency('gstreamer-allocators-1.0', version: gstreamer_req,
|
||||
required: get_option('media-gstreamer'))
|
||||
if os_win32
|
||||
gstd3d12_dep = dependency('gstreamer-d3d12-1.0', version: gstreamer_req,
|
||||
required: get_option('media-gstreamer'))
|
||||
else
|
||||
gstd3d12_dep = dependency('', required: false)
|
||||
endif
|
||||
|
||||
|
||||
fontconfig_dep = [] # only used in x11 backend
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkwin32.h>
|
||||
#endif
|
||||
|
||||
struct _GtkGstPaintable
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -164,6 +168,30 @@ gtk_gst_paintable_video_renderer_create_video_sink (GstPlayerVideoRenderer *rend
|
||||
|
||||
g_object_get (GTK_GST_SINK (sink), "uses-gl", &uses_gl, NULL);
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_WIN32_DISPLAY (display))
|
||||
{
|
||||
GstElement *bin, *convert;
|
||||
GstPad *pad, *ghostpad;
|
||||
gboolean res = TRUE;
|
||||
|
||||
convert = gst_element_factory_make ("d3d12convert", NULL);
|
||||
if (convert)
|
||||
{
|
||||
bin = gst_bin_new ("d3d12sinkbin");
|
||||
res &= gst_bin_add (GST_BIN (bin), convert);
|
||||
res &= gst_bin_add (GST_BIN (bin), sink);
|
||||
res &= gst_element_link_pads (convert, "src", sink, "sink");
|
||||
pad = gst_element_get_static_pad (convert, "sink");
|
||||
ghostpad = gst_ghost_pad_new ("sink", pad);
|
||||
gst_element_add_pad (bin, ghostpad);
|
||||
gst_object_unref (pad);
|
||||
g_assert (res);
|
||||
sink = bin;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (uses_gl)
|
||||
{
|
||||
GstElement *glsinkbin;
|
||||
|
||||
@@ -38,8 +38,9 @@
|
||||
#include <gst/gl/wayland/gstgldisplay_wayland.h>
|
||||
#endif
|
||||
|
||||
#if GST_GL_HAVE_WINDOW_WIN32 && (GST_GL_HAVE_PLATFORM_WGL || GST_GL_HAVE_PLATFORM_EGL) && defined (GDK_WINDOWING_WIN32)
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkwin32.h>
|
||||
#include <gst/d3d12/gstd3d12.h>
|
||||
#endif
|
||||
|
||||
#if GST_GL_HAVE_PLATFORM_EGL && (GST_GL_HAVE_WINDOW_WIN32 || GST_GL_HAVE_WINDOW_X11)
|
||||
@@ -72,6 +73,16 @@ GST_DEBUG_CATEGORY (gtk_debug_gst_sink);
|
||||
|
||||
#define MEMORY_TEXTURE_CAPS GST_VIDEO_CAPS_MAKE (FORMATS)
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#define D3D12_TEXTURE_CAPS \
|
||||
"video/x-raw(" GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY "), " \
|
||||
"width = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"height = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"framerate = " GST_VIDEO_FPS_RANGE ", "
|
||||
#else
|
||||
#define D3D12_TEXTURE_CAPS ""
|
||||
#endif
|
||||
|
||||
#define GL_TEXTURE_CAPS \
|
||||
"video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " \
|
||||
"format = (string) RGBA, " \
|
||||
@@ -87,6 +98,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS(DMABUF_TEXTURE_CAPS "; "
|
||||
D3D12_TEXTURE_CAPS "; "
|
||||
GL_TEXTURE_CAPS "; "
|
||||
MEMORY_TEXTURE_CAPS)
|
||||
);
|
||||
@@ -215,6 +227,11 @@ gtk_gst_sink_get_caps (GstBaseSink *bsink,
|
||||
|
||||
unfiltered = gst_caps_new_empty ();
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
tmp = gst_caps_from_string (D3D12_TEXTURE_CAPS);
|
||||
gst_caps_append (unfiltered, tmp);
|
||||
#endif
|
||||
|
||||
if (self->gdk_display)
|
||||
{
|
||||
GdkDmabufFormats *formats = gdk_display_get_dmabuf_formats (self->gdk_display);
|
||||
@@ -263,6 +280,18 @@ gtk_gst_sink_set_caps (GstBaseSink *bsink,
|
||||
|
||||
GST_DEBUG_OBJECT (self, "set caps with %" GST_PTR_FORMAT, caps);
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (gst_caps_features_contains (gst_caps_get_features (caps, 0), GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY))
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "using D3D12");
|
||||
|
||||
gst_video_info_dma_drm_init (&self->drm_info);
|
||||
|
||||
if (!gst_video_info_from_caps (&self->v_info, caps))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gst_video_is_dma_drm_caps (caps))
|
||||
{
|
||||
if (!gst_video_info_dma_drm_from_caps (&self->drm_info, caps))
|
||||
@@ -323,6 +352,50 @@ gtk_gst_sink_propose_allocation (GstBaseSink *bsink,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (gst_caps_features_contains (gst_caps_get_features (caps, 0), GST_CAPS_FEATURE_MEMORY_D3D12_MEMORY))
|
||||
{
|
||||
GstD3D12Device *device;
|
||||
|
||||
if (!gst_video_info_from_caps (&info, caps))
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "invalid caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* the normal size of a frame */
|
||||
size = info.size;
|
||||
|
||||
if (need_pool &&
|
||||
(device = gst_d3d12_device_new (0)))
|
||||
{
|
||||
pool = gst_d3d12_buffer_pool_new (device);
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
g_clear_object (&device);
|
||||
|
||||
if (!gst_buffer_pool_set_config (pool, config))
|
||||
{
|
||||
GST_DEBUG_OBJECT (bsink, "failed setting config");
|
||||
gst_object_unref (pool);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_query_add_allocation_pool (query, pool, size, 2, 0);
|
||||
g_clear_object (&pool);
|
||||
|
||||
/* we also support various metadata */
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gst_caps_features_contains (gst_caps_get_features (caps, 0), GST_CAPS_FEATURE_MEMORY_DMABUF))
|
||||
{
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
||||
@@ -359,8 +432,7 @@ gtk_gst_sink_propose_allocation (GstBaseSink *bsink,
|
||||
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
gst_query_add_allocation_pool (query, pool, size, 2, 0);
|
||||
if (pool)
|
||||
gst_object_unref (pool);
|
||||
g_clear_object (&pool);
|
||||
|
||||
/* we also support various metadata */
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
||||
@@ -425,6 +497,44 @@ gtk_gst_sink_texture_from_buffer (GtkGstSink *self,
|
||||
|
||||
mem = gst_buffer_peek_memory (buffer, 0);
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (gst_is_d3d12_memory (mem) &&
|
||||
gst_video_frame_map (frame, &self->v_info, buffer, GST_MAP_READ_D3D12))
|
||||
{
|
||||
GstD3D12Memory *dmem = GST_D3D12_MEMORY_CAST (mem);
|
||||
GdkD3D12TextureBuilder *builder;
|
||||
ID3D12Fence *fence;
|
||||
guint64 fence_wait;
|
||||
GError *error = NULL;
|
||||
int i;
|
||||
|
||||
builder = gdk_d3d12_texture_builder_new ();
|
||||
gdk_d3d12_texture_builder_set_resource (builder, gst_d3d12_memory_get_resource_handle (dmem));
|
||||
if (gst_d3d12_memory_get_fence (dmem, &fence, &fence_wait))
|
||||
{
|
||||
gdk_d3d12_texture_builder_set_fence (builder, fence);
|
||||
ID3D12Fence_Release (fence);
|
||||
gdk_d3d12_texture_builder_set_fence_wait (builder, fence_wait);
|
||||
}
|
||||
gdk_d3d12_texture_builder_set_color_state (builder, self->color_state);
|
||||
|
||||
texture = gdk_d3d12_texture_builder_build (builder,
|
||||
(GDestroyNotify) video_frame_free,
|
||||
frame,
|
||||
&error);
|
||||
g_object_unref (builder);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
GST_ERROR_OBJECT (self, "Failed to create d3d12 texture: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
*pixel_aspect_ratio = ((double) GST_VIDEO_INFO_PAR_N (&self->v_info) /
|
||||
(double) GST_VIDEO_INFO_PAR_D (&self->v_info));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gst_is_dmabuf_memory (mem))
|
||||
{
|
||||
GdkDmabufTextureBuilder *builder = NULL;
|
||||
|
||||
@@ -8,7 +8,7 @@ extra_c_args += common_cflags
|
||||
if gstplayer_dep.found() and gstgl_dep.found() and gstallocators_dep.found()
|
||||
media_backends += 'gstreamer'
|
||||
cdata.set('HAVE_GSTREAMER', 1)
|
||||
media_gst_deps = [ libm, libgtk_dep, gstplayer_dep, gstgl_dep, gstallocators_dep ]
|
||||
media_gst_deps = [ libm, libgtk_dep, gstplayer_dep, gstgl_dep, gstallocators_dep, gstd3d12_dep ]
|
||||
|
||||
shared_module('media-gstreamer',
|
||||
sources: [
|
||||
|
||||
5
subprojects/DirectX-Headers.wrap
Normal file
5
subprojects/DirectX-Headers.wrap
Normal file
@@ -0,0 +1,5 @@
|
||||
[wrap-git]
|
||||
directory = DirectX-Headers-1.0
|
||||
|
||||
url = https://github.com/microsoft/DirectX-Headers.git
|
||||
revision = v1.611.0
|
||||
@@ -1,7 +1,7 @@
|
||||
[wrap-git]
|
||||
directory=gstreamer
|
||||
url=https://gitlab.freedesktop.org/gstreamer/gstreamer.git
|
||||
revision=1.24
|
||||
revision=main
|
||||
depth=1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -137,6 +137,12 @@ if os_linux
|
||||
]
|
||||
endif
|
||||
|
||||
if os_win32
|
||||
gtk_tests += [
|
||||
['testd3d12', ['testd3d12.c', 'gtkclipper.c']],
|
||||
]
|
||||
endif
|
||||
|
||||
if x11_enabled
|
||||
gtk_tests += [['testerrors']]
|
||||
endif
|
||||
@@ -153,5 +159,5 @@ foreach t: gtk_tests
|
||||
include_directories: [confinc, gdkinc],
|
||||
c_args: test_args + common_cflags,
|
||||
dependencies: [libgtk_dep, libm],
|
||||
)
|
||||
)
|
||||
endforeach
|
||||
|
||||
432
tests/testd3d12.c
Normal file
432
tests/testd3d12.c
Normal file
@@ -0,0 +1,432 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <gdk/win32/gdkwin32.h>
|
||||
|
||||
#include "gtkclipperprivate.h"
|
||||
|
||||
static char *
|
||||
supported_formats_to_string (void)
|
||||
{
|
||||
return g_strdup ("whatever");
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
make_d3d12_texture (ID3D12Device *device,
|
||||
GdkTexture *texture,
|
||||
guint32 format,
|
||||
gboolean disjoint,
|
||||
gboolean premultiplied,
|
||||
gboolean flip)
|
||||
{
|
||||
GdkTextureDownloader *downloader;
|
||||
UINT64 buffer_size;
|
||||
GdkD3D12TextureBuilder *builder;
|
||||
GError *error = NULL;
|
||||
HRESULT hr;
|
||||
ID3D12CommandAllocator *allocator;
|
||||
ID3D12GraphicsCommandList *commands;
|
||||
ID3D12CommandQueue *queue;
|
||||
ID3D12Resource *buffer, *resource;
|
||||
D3D12_RESOURCE_DESC resource_desc;
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint;
|
||||
void *buffer_data;
|
||||
|
||||
hr = ID3D12Device_CreateCommittedResource (device,
|
||||
(&(D3D12_HEAP_PROPERTIES) {
|
||||
.Type = D3D12_HEAP_TYPE_DEFAULT,
|
||||
.CreationNodeMask = 1,
|
||||
.VisibleNodeMask = 1,
|
||||
}),
|
||||
D3D12_HEAP_FLAG_SHARED,
|
||||
(&(D3D12_RESOURCE_DESC) {
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
|
||||
.Width = gdk_texture_get_width (texture),
|
||||
.Height = gdk_texture_get_height (texture),
|
||||
.DepthOrArraySize = 1,
|
||||
.MipLevels = 0,
|
||||
.Format = DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
.SampleDesc = {
|
||||
.Count = 1,
|
||||
.Quality = 0,
|
||||
},
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
|
||||
.Flags = D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS,
|
||||
}),
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
&IID_ID3D12Resource,
|
||||
(void **) &resource);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
ID3D12Resource_GetDesc (resource, &resource_desc);
|
||||
ID3D12Device_GetCopyableFootprints (device,
|
||||
&resource_desc,
|
||||
0, 1, 0,
|
||||
&footprint,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
buffer_size = footprint.Footprint.RowPitch * footprint.Footprint.Height;
|
||||
|
||||
hr = ID3D12Device_CreateCommittedResource (device,
|
||||
(&(D3D12_HEAP_PROPERTIES) {
|
||||
.Type = D3D12_HEAP_TYPE_UPLOAD,
|
||||
.CreationNodeMask = 1,
|
||||
.VisibleNodeMask = 1,
|
||||
}),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
(&(D3D12_RESOURCE_DESC) {
|
||||
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
||||
.Width = buffer_size,
|
||||
.Height = 1,
|
||||
.DepthOrArraySize = 1,
|
||||
.MipLevels = 1,
|
||||
.SampleDesc = {
|
||||
.Count = 1,
|
||||
.Quality = 0,
|
||||
},
|
||||
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
}),
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
NULL,
|
||||
&IID_ID3D12Resource,
|
||||
(void **) &buffer);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
ID3D12Resource_Map (buffer, 0, (&(D3D12_RANGE) { 0, buffer_size }), &buffer_data );
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
if (premultiplied)
|
||||
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
|
||||
else
|
||||
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R8G8B8A8);
|
||||
gdk_texture_downloader_download_into (downloader, buffer_data, footprint.Footprint.RowPitch);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
if (flip)
|
||||
{
|
||||
int x, y, width, height, stride;
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
stride = footprint.Footprint.RowPitch;
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
guint32 *row = (guint32 *) ((guint8 *) buffer_data + y * stride);
|
||||
for (x = 0; x < width / 2; x++)
|
||||
{
|
||||
guint32 p = row[x];
|
||||
row[x] = row[width - 1 - x];
|
||||
row[width - 1 - x] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ID3D12Resource_Unmap (buffer, 0, (&(D3D12_RANGE) { 0, buffer_size }));
|
||||
|
||||
hr = ID3D12Device_CreateCommandAllocator (device,
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
&IID_ID3D12CommandAllocator,
|
||||
(void **) &allocator);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
hr = ID3D12Device_CreateCommandList (device,
|
||||
0,
|
||||
D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
allocator,
|
||||
NULL,
|
||||
&IID_ID3D12GraphicsCommandList,
|
||||
(void **) &commands);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
ID3D12GraphicsCommandList_CopyTextureRegion (commands,
|
||||
(&(D3D12_TEXTURE_COPY_LOCATION) {
|
||||
.pResource = resource,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||
.SubresourceIndex = 0,
|
||||
}),
|
||||
0, 0, 0,
|
||||
(&(D3D12_TEXTURE_COPY_LOCATION) {
|
||||
.pResource = buffer,
|
||||
.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
|
||||
.PlacedFootprint = footprint,
|
||||
}),
|
||||
NULL);
|
||||
hr = ID3D12GraphicsCommandList_Close (commands);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
hr = ID3D12Device_CreateCommandQueue (device,
|
||||
(&(D3D12_COMMAND_QUEUE_DESC) {
|
||||
.Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
||||
.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||
}),
|
||||
&IID_ID3D12CommandQueue,
|
||||
(void **) &queue);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
ID3D12CommandQueue_ExecuteCommandLists (queue, 1, (ID3D12CommandList **) &commands);
|
||||
|
||||
builder = gdk_d3d12_texture_builder_new ();
|
||||
|
||||
gdk_d3d12_texture_builder_set_resource (builder, resource);
|
||||
gdk_d3d12_texture_builder_set_premultiplied (builder, premultiplied);
|
||||
|
||||
texture = gdk_d3d12_texture_builder_build (builder, NULL, NULL, &error);
|
||||
if (!texture)
|
||||
g_error ("Failed to create d3d12 texture: %s", error->message);
|
||||
|
||||
g_object_unref (builder);
|
||||
ID3D12Resource_Release (buffer);
|
||||
ID3D12Resource_Release (resource);
|
||||
ID3D12GraphicsCommandList_Release (commands);
|
||||
ID3D12CommandAllocator_Release (allocator);
|
||||
ID3D12CommandQueue_Release (queue);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
G_GNUC_NORETURN
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
char *formats = supported_formats_to_string ();
|
||||
g_print ("Usage: testdmabuf [--undecorated][--disjoint][--download-to FILE][--padding PADDING] FORMAT FILE\n"
|
||||
"Supported formats: %s\n", formats);
|
||||
g_free (formats);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
toggle_fullscreen (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
|
||||
if (gtk_window_is_fullscreen (window))
|
||||
gtk_window_unfullscreen (window);
|
||||
else
|
||||
gtk_window_fullscreen (window);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
toggle_overlay (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer data)
|
||||
{
|
||||
static GtkWidget *child = NULL;
|
||||
GtkOverlay *overlay = (GtkOverlay *) data;
|
||||
|
||||
if (child)
|
||||
{
|
||||
gtk_overlay_remove_overlay (overlay, child);
|
||||
child = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget *spinner;
|
||||
spinner = gtk_spinner_new ();
|
||||
gtk_spinner_start (GTK_SPINNER (spinner));
|
||||
child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
|
||||
gtk_box_append (GTK_BOX (child), spinner);
|
||||
gtk_box_append (GTK_BOX (child), gtk_image_new_from_icon_name ("media-playback-start-symbolic"));
|
||||
gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
|
||||
gtk_overlay_add_overlay (overlay, child);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkTexture *texture;
|
||||
static GdkTexture *texture_flipped;
|
||||
|
||||
static gboolean
|
||||
toggle_flip (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPicture *picture = (GtkPicture *) data;
|
||||
|
||||
if (!texture_flipped)
|
||||
return FALSE;
|
||||
|
||||
if (gtk_picture_get_paintable (picture) == GDK_PAINTABLE (texture))
|
||||
gtk_picture_set_paintable (picture, GDK_PAINTABLE (texture_flipped));
|
||||
else
|
||||
gtk_picture_set_paintable (picture, GDK_PAINTABLE (texture));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
toggle_start (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *offload = (GtkWidget *) data;
|
||||
|
||||
if (gtk_widget_get_halign (offload) == GTK_ALIGN_CENTER)
|
||||
gtk_widget_set_halign (offload, GTK_ALIGN_START);
|
||||
else
|
||||
gtk_widget_set_halign (offload, GTK_ALIGN_CENTER);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window, *offload, *picture, *overlay;
|
||||
char *filename;
|
||||
guint32 format;
|
||||
gboolean disjoint = FALSE;
|
||||
gboolean premultiplied = TRUE;
|
||||
gboolean decorated = TRUE;
|
||||
gboolean fullscreen = FALSE;
|
||||
unsigned int i;
|
||||
const char *save_filename = NULL;
|
||||
GtkEventController *controller;
|
||||
GtkShortcutTrigger *trigger;
|
||||
GtkShortcutAction *action;
|
||||
GtkShortcut *shortcut;
|
||||
GdkPaintable *paintable;
|
||||
GdkTexture *orig;
|
||||
ID3D12Device *device;
|
||||
HRESULT hr;
|
||||
int padding[4] = { 0, }; /* left, right, top, bottom */
|
||||
int padding_set = 0;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (g_str_equal (argv[i], "--disjoint"))
|
||||
disjoint = TRUE;
|
||||
else if (g_str_equal (argv[i], "--undecorated"))
|
||||
decorated = FALSE;
|
||||
else if (g_str_equal (argv[i], "--fullscreen"))
|
||||
fullscreen = TRUE;
|
||||
else if (g_str_equal (argv[i], "--unpremultiplied"))
|
||||
premultiplied = FALSE;
|
||||
else if (g_str_equal (argv[i], "--download-to"))
|
||||
{
|
||||
i++;
|
||||
if (i == argc)
|
||||
usage ();
|
||||
|
||||
save_filename = argv[i];
|
||||
}
|
||||
else if (g_str_equal (argv[i], "--padding"))
|
||||
{
|
||||
if (padding_set < 4)
|
||||
{
|
||||
char **strv;
|
||||
|
||||
i++;
|
||||
if (i == argc)
|
||||
usage ();
|
||||
|
||||
strv = g_strsplit (argv[i], ",", 0);
|
||||
if (g_strv_length (strv) > 4)
|
||||
g_error ("Too much padding");
|
||||
|
||||
for (padding_set = 0; padding_set < 4; padding_set++)
|
||||
{
|
||||
guint64 num;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!strv[padding_set])
|
||||
break;
|
||||
|
||||
if (!g_ascii_string_to_unsigned (strv[padding_set], 10, 0, 100, &num, &error))
|
||||
g_error ("%s", error->message);
|
||||
|
||||
padding[padding_set] = (int) num;
|
||||
}
|
||||
}
|
||||
else
|
||||
g_error ("Too much padding");
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (argc - i != 2)
|
||||
{
|
||||
usage ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[argc - 1];
|
||||
|
||||
gtk_init ();
|
||||
|
||||
hr = D3D12CreateDevice (NULL, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device, (void **) &device);
|
||||
g_assert (SUCCEEDED (hr));
|
||||
|
||||
orig = gdk_texture_new_from_filename (filename, NULL);
|
||||
format = strtoul (argv[argc-2], NULL, 10);
|
||||
texture = make_d3d12_texture (device, orig, format, disjoint, premultiplied, FALSE);
|
||||
texture_flipped = make_d3d12_texture (device, orig, format, disjoint, premultiplied, TRUE);
|
||||
g_object_unref (orig);
|
||||
|
||||
if (padding_set > 0)
|
||||
{
|
||||
paintable = gtk_clipper_new (GDK_PAINTABLE (texture),
|
||||
&GRAPHENE_RECT_INIT (padding[0],
|
||||
padding[2],
|
||||
gdk_texture_get_width (texture) - padding[0] - padding[1],
|
||||
gdk_texture_get_height (texture) - padding[2] - padding[3]));
|
||||
}
|
||||
else
|
||||
paintable = GDK_PAINTABLE (texture);
|
||||
|
||||
if (save_filename)
|
||||
gdk_texture_save_to_png (texture, save_filename);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_decorated (GTK_WINDOW (window), decorated);
|
||||
if (fullscreen)
|
||||
gtk_window_fullscreen (GTK_WINDOW (window));
|
||||
|
||||
picture = gtk_picture_new_for_paintable (paintable);
|
||||
offload = gtk_graphics_offload_new (picture);
|
||||
gtk_widget_set_halign (offload, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (offload, GTK_ALIGN_CENTER);
|
||||
overlay = gtk_overlay_new ();
|
||||
|
||||
gtk_overlay_set_child (GTK_OVERLAY (overlay), offload);
|
||||
gtk_window_set_child (GTK_WINDOW (window), overlay);
|
||||
|
||||
controller = gtk_shortcut_controller_new ();
|
||||
|
||||
trigger = gtk_keyval_trigger_new (GDK_KEY_F11, GDK_NO_MODIFIER_MASK);
|
||||
action = gtk_callback_action_new (toggle_fullscreen, NULL, NULL);
|
||||
shortcut = gtk_shortcut_new (trigger, action);
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
|
||||
|
||||
trigger = gtk_keyval_trigger_new (GDK_KEY_O, GDK_CONTROL_MASK);
|
||||
action = gtk_callback_action_new (toggle_overlay, overlay, NULL);
|
||||
shortcut = gtk_shortcut_new (trigger, action);
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
|
||||
|
||||
trigger = gtk_keyval_trigger_new (GDK_KEY_F, GDK_CONTROL_MASK);
|
||||
action = gtk_callback_action_new (toggle_flip, picture, NULL);
|
||||
shortcut = gtk_shortcut_new (trigger, action);
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
|
||||
|
||||
trigger = gtk_keyval_trigger_new (GDK_KEY_S, GDK_CONTROL_MASK);
|
||||
action = gtk_callback_action_new (toggle_start, offload, NULL);
|
||||
shortcut = gtk_shortcut_new (trigger, action);
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
|
||||
|
||||
gtk_widget_add_controller (window, controller);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
|
||||
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user