win32: Add GdkD3d12Texture and builder

This is a simple implementation of a GdkTexture that is backed by
a ID3D12Resource.

The only functionality implemented so far is GdkTexture::download(),
but that is enough to make it work - albeit slowly - in all renderers.

It also doesn't support any fancy formats yet; in particular: no YUV.
This commit is contained in:
Benjamin Otte
2024-10-30 05:22:10 +01:00
parent b5af96c21f
commit 8b99f14706
7 changed files with 1055 additions and 0 deletions

347
gdk/win32/gdkd3d12texture.c Normal file
View File

@@ -0,0 +1,347 @@
/* 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 "gdkmemoryformatprivate.h"
#include "gdkprivate-win32.h"
#include "gdktextureprivate.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;
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);
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));
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;
D3D12_RESOURCE_DESC desc;
gboolean premultiplied;
resource = gdk_d3d12_texture_builder_get_resource (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;
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
}

View 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

View File

@@ -0,0 +1,542 @@
/*
* 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;
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_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);
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_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_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: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_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);
}

View File

@@ -0,0 +1,78 @@
/*
* 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
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

View File

@@ -0,0 +1,15 @@
#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);
G_END_DECLS

View File

@@ -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>

View File

@@ -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',
@@ -39,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',