diff options
author | Seungha Yang <seungha@centricular.com> | 2021-06-07 01:49:26 +0900 |
---|---|---|
committer | Seungha Yang <seungha@centricular.com> | 2021-06-10 01:20:32 +0900 |
commit | f90506e33b515377b29e654bfa8d457766063ec0 (patch) | |
tree | d2443fa844c634835677b8774f0a0508296820b2 /gst-libs/gst/d3d11 | |
parent | b7abd34285bf47f5b49a6541936d274f841de8fc (diff) | |
download | gstreamer-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.h | 1 | ||||
-rw-r--r-- | gst-libs/gst/d3d11/gstd3d11memory.c | 103 | ||||
-rw-r--r-- | gst-libs/gst/d3d11/gstd3d11memory.h | 2 |
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]; }; |