summaryrefslogtreecommitdiff
path: root/gst-libs/gst/d3d11
diff options
context:
space:
mode:
authorSeungha Yang <seungha@centricular.com>2021-06-07 01:49:26 +0900
committerSeungha Yang <seungha@centricular.com>2021-06-10 01:20:32 +0900
commitf90506e33b515377b29e654bfa8d457766063ec0 (patch)
treed2443fa844c634835677b8774f0a0508296820b2 /gst-libs/gst/d3d11
parentb7abd34285bf47f5b49a6541936d274f841de8fc (diff)
downloadgstreamer-plugins-bad-f90506e33b515377b29e654bfa8d457766063ec0.tar.gz
d3d11memory: Implement GstAllocator::mem_copy method
There are a few places which require deep copy (basesink on drain for example). Also this implementation can be useful for future use case. One probable future use case is that copying DPB texture to another texture for in-place transform since our DPB texture is never writable, and therefore copying is unavoidable. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2308>
Diffstat (limited to 'gst-libs/gst/d3d11')
-rw-r--r--gst-libs/gst/d3d11/gstd3d11_fwd.h1
-rw-r--r--gst-libs/gst/d3d11/gstd3d11memory.c103
-rw-r--r--gst-libs/gst/d3d11/gstd3d11memory.h2
3 files changed, 104 insertions, 2 deletions
diff --git a/gst-libs/gst/d3d11/gstd3d11_fwd.h b/gst-libs/gst/d3d11/gstd3d11_fwd.h
index 8b455d1aa..e4c6265f6 100644
--- a/gst-libs/gst/d3d11/gstd3d11_fwd.h
+++ b/gst-libs/gst/d3d11/gstd3d11_fwd.h
@@ -67,6 +67,7 @@ typedef struct _GstD3D11MemoryPrivate GstD3D11MemoryPrivate;
typedef struct _GstD3D11Allocator GstD3D11Allocator;
typedef struct _GstD3D11AllocatorClass GstD3D11AllocatorClass;
+typedef struct _GstD3D11AllocatorPrivate GstD3D11AllocatorPrivate;
typedef struct _GstD3D11PoolAllocator GstD3D11PoolAllocator;
typedef struct _GstD3D11PoolAllocatorClass GstD3D11PoolAllocatorClass;
diff --git a/gst-libs/gst/d3d11/gstd3d11memory.c b/gst-libs/gst/d3d11/gstd3d11memory.c
index 74137dd6a..8627d0930 100644
--- a/gst-libs/gst/d3d11/gstd3d11memory.c
+++ b/gst-libs/gst/d3d11/gstd3d11memory.c
@@ -1217,11 +1217,19 @@ gst_d3d11_memory_get_processor_output_view (GstD3D11Memory * mem,
}
/* GstD3D11Allocator */
+struct _GstD3D11AllocatorPrivate
+{
+ GstMemoryCopyFunction fallback_copy;
+};
+
#define gst_d3d11_allocator_parent_class alloc_parent_class
-G_DEFINE_TYPE (GstD3D11Allocator, gst_d3d11_allocator, GST_TYPE_ALLOCATOR);
+G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Allocator,
+ gst_d3d11_allocator, GST_TYPE_ALLOCATOR);
static GstMemory *gst_d3d11_allocator_dummy_alloc (GstAllocator * allocator,
gsize size, GstAllocationParams * params);
+static GstMemory *gst_d3d11_allocator_alloc_internal (GstD3D11Allocator * self,
+ GstD3D11Device * device, const D3D11_TEXTURE2D_DESC * desc);
static void gst_d3d11_allocator_free (GstAllocator * allocator,
GstMemory * mem);
@@ -1234,16 +1242,107 @@ gst_d3d11_allocator_class_init (GstD3D11AllocatorClass * klass)
allocator_class->free = gst_d3d11_allocator_free;
}
+static GstMemory *
+gst_d3d11_memory_copy (GstMemory * mem, gssize offset, gssize size)
+{
+ GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (mem->allocator);
+ GstD3D11AllocatorPrivate *priv = alloc->priv;
+ GstD3D11Memory *dmem = GST_D3D11_MEMORY_CAST (mem);
+ GstD3D11Memory *copy_dmem;
+ GstD3D11Device *device = dmem->device;
+ ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (device);
+ ID3D11DeviceContext *device_context =
+ gst_d3d11_device_get_device_context_handle (device);
+ D3D11_TEXTURE2D_DESC dst_desc = { 0, };
+ D3D11_TEXTURE2D_DESC src_desc = { 0, };
+ GstMemory *copy = NULL;
+ GstMapInfo info;
+ HRESULT hr;
+ UINT bind_flags = 0;
+ UINT supported_flags = 0;
+
+ /* non-zero offset or different size is not supported */
+ if (offset != 0 || (size != -1 && size != mem->size)) {
+ GST_DEBUG_OBJECT (alloc, "Different size/offset, try fallback copy");
+ return priv->fallback_copy (mem, offset, size);
+ }
+
+ gst_d3d11_device_lock (device);
+ if (!gst_memory_map (mem, &info, GST_MAP_READ | GST_MAP_D3D11)) {
+ gst_d3d11_device_unlock (device);
+
+ GST_WARNING_OBJECT (alloc, "Failed to map memory, try fallback copy");
+
+ return priv->fallback_copy (mem, offset, size);
+ }
+
+ ID3D11Texture2D_GetDesc (dmem->priv->texture, &src_desc);
+ dst_desc.Width = src_desc.Width;
+ dst_desc.Height = src_desc.Height;
+ dst_desc.MipLevels = 1;
+ dst_desc.Format = src_desc.Format;
+ dst_desc.SampleDesc.Count = 1;
+ dst_desc.ArraySize = 1;
+ dst_desc.Usage = D3D11_USAGE_DEFAULT;
+
+ /* If supported, use bind flags for SRV/RTV */
+ hr = ID3D11Device_CheckFormatSupport (device_handle,
+ src_desc.Format, &supported_flags);
+ if (gst_d3d11_result (hr, device)) {
+ if ((supported_flags & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) ==
+ D3D11_FORMAT_SUPPORT_SHADER_SAMPLE) {
+ bind_flags |= D3D11_BIND_SHADER_RESOURCE;
+ }
+
+ if ((supported_flags & D3D11_FORMAT_SUPPORT_RENDER_TARGET) ==
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET) {
+ bind_flags |= D3D11_BIND_RENDER_TARGET;
+ }
+ }
+
+ copy = gst_d3d11_allocator_alloc_internal (alloc, device, &dst_desc);
+ if (!copy) {
+ gst_memory_unmap (mem, &info);
+ gst_d3d11_device_unlock (device);
+
+ GST_WARNING_OBJECT (alloc,
+ "Failed to allocate new d3d11 map memory, try fallback copy");
+
+ return priv->fallback_copy (mem, offset, size);
+ }
+
+ copy_dmem = GST_D3D11_MEMORY_CAST (copy);
+ ID3D11DeviceContext_CopySubresourceRegion (device_context,
+ (ID3D11Resource *) copy_dmem->priv->texture, 0, 0, 0, 0,
+ (ID3D11Resource *) dmem->priv->texture, dmem->priv->subresource_index,
+ NULL);
+ copy->maxsize = copy->size = mem->maxsize;
+ gst_memory_unmap (mem, &info);
+ gst_d3d11_device_unlock (device);
+
+ /* newly allocated memory holds valid image data. We need download this
+ * pixel data into staging memory for CPU access */
+ GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
+
+ return copy;
+}
+
static void
gst_d3d11_allocator_init (GstD3D11Allocator * allocator)
{
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
+ GstD3D11AllocatorPrivate *priv;
+
+ priv = allocator->priv = gst_d3d11_allocator_get_instance_private (allocator);
alloc->mem_type = GST_D3D11_MEMORY_NAME;
alloc->mem_map_full = gst_d3d11_memory_map_full;
alloc->mem_unmap_full = gst_d3d11_memory_unmap_full;
alloc->mem_share = gst_d3d11_memory_share;
- /* fallback copy */
+
+ /* Store pointer to default mem_copy method for fallback copy */
+ priv->fallback_copy = alloc->mem_copy;
+ alloc->mem_copy = gst_d3d11_memory_copy;
GST_OBJECT_FLAG_SET (alloc, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
}
diff --git a/gst-libs/gst/d3d11/gstd3d11memory.h b/gst-libs/gst/d3d11/gstd3d11memory.h
index abfb0cd6a..a80bf7b10 100644
--- a/gst-libs/gst/d3d11/gstd3d11memory.h
+++ b/gst-libs/gst/d3d11/gstd3d11memory.h
@@ -209,6 +209,8 @@ struct _GstD3D11Allocator
GstAllocator allocator;
/*< private >*/
+ GstD3D11AllocatorPrivate *priv;
+
gpointer _gst_reserved[GST_PADDING];
};