gpu: Add D3D12 texture support to GL renderer

Add a gdk_d3d12_texture_import_gl() function to match the EGL import
behavior.

And then use it in the import code.

What makes this a bit awkward is that we need to not just shuffle a
tex_id but also a mem_id around, but oh well...
This commit is contained in:
Benjamin Otte
2024-10-31 14:51:13 +01:00
parent 80c04eb223
commit 595294b8f4
3 changed files with 116 additions and 0 deletions

View File

@@ -23,10 +23,13 @@
#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:
*
@@ -409,3 +412,90 @@ out:
G_UNLOCK (handle_creation);
return result;
}
/*
* 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;
}

View File

@@ -13,5 +13,9 @@ GdkTexture * gdk_d3d12_texture_new_from_builder (GdkD3D1
HANDLE gdk_d3d12_texture_get_resource_handle (GdkD3D12Texture *self);
guint gdk_d3d12_texture_import_gl (GdkD3D12Texture *self,
GdkGLContext *context,
guint *out_mem_id);
G_END_DECLS

View File

@@ -13,6 +13,9 @@
#include "gdkglcontextprivate.h"
#include "gdkgltextureprivate.h"
#ifdef GDK_WINDOWING_WIN32
#include "win32/gdkd3d12textureprivate.h"
#endif
struct _GskGLFrame
{
GskGpuFrame parent_instance;
@@ -121,6 +124,25 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
(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);
}