From 0788492461e1b559230cc5c3a354fe5f48f95f8b Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 20 Dec 2019 00:17:33 +0900 Subject: [PATCH] d3d11: Use GRecMutex to protect immediate context and dxgi API call In some cases, rendering and dxgi (e.g., swapchain) APIs should be called from window message pump thread, but current design (dedicated d3d11 thread) make it impossible. To solve it, change concurrency model to locking based one from single-thread model. --- sys/d3d11/gstd3d11colorconvert.c | 90 +++------ sys/d3d11/gstd3d11colorconverter.c | 48 +---- sys/d3d11/gstd3d11device.c | 378 +++++++------------------------------ sys/d3d11/gstd3d11device.h | 14 +- sys/d3d11/gstd3d11download.c | 56 +----- sys/d3d11/gstd3d11format.c | 55 ++---- sys/d3d11/gstd3d11memory.c | 187 ++++++++---------- sys/d3d11/gstd3d11shader.c | 230 ++++++++-------------- sys/d3d11/gstd3d11shader.h | 8 + sys/d3d11/gstd3d11upload.c | 79 +++----- sys/d3d11/gstd3d11window.c | 207 +++++++------------- sys/d3d11/gstd3d11window.h | 4 - 12 files changed, 400 insertions(+), 956 deletions(-) diff --git a/sys/d3d11/gstd3d11colorconvert.c b/sys/d3d11/gstd3d11colorconvert.c index 48f6641..c753fe2 100644 --- a/sys/d3d11/gstd3d11colorconvert.c +++ b/sys/d3d11/gstd3d11colorconvert.c @@ -179,7 +179,7 @@ gst_d3d11_color_convert_init (GstD3D11ColorConvert * self) } static void -clear_shader_resource (GstD3D11Device * device, GstD3D11ColorConvert * self) +gst_d3d11_color_convert_clear_shader_resource (GstD3D11ColorConvert * self) { gint i; @@ -216,17 +216,6 @@ clear_shader_resource (GstD3D11Device * device, GstD3D11ColorConvert * self) } static void -gst_d3d11_color_convert_clear_shader_resource (GstD3D11ColorConvert * self) -{ - GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self); - - if (filter->device) { - gst_d3d11_device_thread_add (filter->device, - (GstD3D11DeviceThreadFunc) clear_shader_resource, self); - } -} - -static void gst_d3d11_color_convert_dispose (GObject * object) { GstD3D11ColorConvert *self = GST_D3D11_COLOR_CONVERT (object); @@ -781,32 +770,25 @@ format_unknown: } } -typedef struct -{ - GstD3D11ColorConvert *self; - GstBuffer *in_buf; - GstBuffer *out_buf; - - gboolean ret; -} DoConvertData; - -static void -do_convert (GstD3D11Device * device, DoConvertData * data) +static GstFlowReturn +gst_d3d11_color_convert_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf) { - GstD3D11ColorConvert *self = data->self; - GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (self); + GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); + GstD3D11ColorConvert *self = GST_D3D11_COLOR_CONVERT (trans); ID3D11DeviceContext *context_handle; ID3D11ShaderResourceView *resource_view[GST_VIDEO_MAX_PLANES] = { NULL, }; ID3D11RenderTargetView *render_view[GST_VIDEO_MAX_PLANES] = { NULL, }; gint i, j, view_index; gboolean copy_input = FALSE; gboolean copy_output = FALSE; + GstD3D11Device *device = filter->device; context_handle = gst_d3d11_device_get_device_context_handle (device); view_index = 0; - for (i = 0; i < gst_buffer_n_memory (data->in_buf); i++) { - GstMemory *mem = gst_buffer_peek_memory (data->in_buf, i); + for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { + GstMemory *mem = gst_buffer_peek_memory (inbuf, i); GstD3D11Memory *d3d11_mem; GstMapInfo info; @@ -833,8 +815,7 @@ do_convert (GstD3D11Device * device, DoConvertData * data) if (!create_shader_input_resource (self, device, self->in_d3d11_format, &filter->in_info)) { GST_ERROR_OBJECT (self, "Failed to configure fallback input texture"); - data->ret = FALSE; - return; + return GST_FLOW_ERROR; } break; } @@ -843,8 +824,9 @@ do_convert (GstD3D11Device * device, DoConvertData * data) /* if input memory has no resource view, * copy texture into our fallback texture */ if (copy_input) { - for (i = 0; i < gst_buffer_n_memory (data->in_buf); i++) { - GstMemory *mem = gst_buffer_peek_memory (data->in_buf, i); + gst_d3d11_device_lock (device); + for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { + GstMemory *mem = gst_buffer_peek_memory (inbuf, i); GstD3D11Memory *d3d11_mem; g_assert (gst_is_d3d11_memory (mem)); @@ -855,11 +837,12 @@ do_convert (GstD3D11Device * device, DoConvertData * data) (ID3D11Resource *) self->in_texture[i], 0, 0, 0, 0, (ID3D11Resource *) d3d11_mem->texture, 0, NULL); } + gst_d3d11_device_unlock (device); } view_index = 0; - for (i = 0; i < gst_buffer_n_memory (data->out_buf); i++) { - GstMemory *mem = gst_buffer_peek_memory (data->out_buf, i); + for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { + GstMemory *mem = gst_buffer_peek_memory (outbuf, i); GstD3D11Memory *d3d11_mem; g_assert (gst_is_d3d11_memory (mem)); @@ -880,20 +863,24 @@ do_convert (GstD3D11Device * device, DoConvertData * data) if (!create_shader_output_resource (self, device, self->out_d3d11_format, &filter->out_info)) { GST_ERROR_OBJECT (self, "Failed to configure fallback output texture"); - data->ret = FALSE; - return; + return GST_FLOW_ERROR; } break; } } - data->ret = gst_d3d11_color_converter_convert (self->converter, - copy_input ? self->shader_resource_view : resource_view, - copy_output ? self->render_target_view : render_view); + if (!gst_d3d11_color_converter_convert (self->converter, + copy_input ? self->shader_resource_view : resource_view, + copy_output ? self->render_target_view : render_view)) { + GST_ERROR_OBJECT (self, "Failed to convert"); + + return GST_FLOW_ERROR; + } - if (data->ret && copy_output) { - for (i = 0; i < gst_buffer_n_memory (data->out_buf); i++) { - GstMemory *mem = gst_buffer_peek_memory (data->out_buf, i); + if (copy_output) { + gst_d3d11_device_lock (device); + for (i = 0; i < gst_buffer_n_memory (outbuf); i++) { + GstMemory *mem = gst_buffer_peek_memory (outbuf, i); GstD3D11Memory *d3d11_mem; g_assert (gst_is_d3d11_memory (mem)); @@ -904,27 +891,8 @@ do_convert (GstD3D11Device * device, DoConvertData * data) (ID3D11Resource *) d3d11_mem->texture, 0, 0, 0, 0, (ID3D11Resource *) self->out_texture[i], 0, NULL); } + gst_d3d11_device_unlock (device); } -} - -static GstFlowReturn -gst_d3d11_color_convert_transform (GstBaseTransform * trans, - GstBuffer * inbuf, GstBuffer * outbuf) -{ - GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); - GstD3D11ColorConvert *self = GST_D3D11_COLOR_CONVERT (trans); - DoConvertData data; - - data.self = self; - data.in_buf = inbuf; - data.out_buf = outbuf; - data.ret = TRUE; - - gst_d3d11_device_thread_add (filter->device, - (GstD3D11DeviceThreadFunc) do_convert, &data); - - if (!data.ret) - return GST_FLOW_ERROR; return GST_FLOW_OK; } diff --git a/sys/d3d11/gstd3d11colorconverter.c b/sys/d3d11/gstd3d11colorconverter.c index 90b9448..9897e78 100644 --- a/sys/d3d11/gstd3d11colorconverter.c +++ b/sys/d3d11/gstd3d11colorconverter.c @@ -610,12 +610,14 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device, goto clear; } + gst_d3d11_device_lock (device); hr = ID3D11DeviceContext_Map (context_handle, (ID3D11Resource *) const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr)) { GST_ERROR ("Couldn't map constant buffer, hr: 0x%x", (guint) hr); data->ret = FALSE; + gst_d3d11_device_unlock (device); goto clear; } @@ -624,6 +626,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device, ID3D11DeviceContext_Unmap (context_handle, (ID3D11Resource *) const_buffer, 0); + gst_d3d11_device_unlock (device); } input_desc[0].SemanticName = "POSITION"; @@ -678,12 +681,14 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device, goto clear; } + gst_d3d11_device_lock (device); hr = ID3D11DeviceContext_Map (context_handle, (ID3D11Resource *) vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (!gst_d3d11_result (hr)) { GST_ERROR ("Couldn't map vertex buffer, hr: 0x%x", (guint) hr); data->ret = FALSE; + gst_d3d11_device_unlock (device); goto clear; } @@ -696,6 +701,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device, GST_ERROR ("Couldn't map index buffer, hr: 0x%x", (guint) hr); ID3D11DeviceContext_Unmap (context_handle, (ID3D11Resource *) vertex_buffer, 0); + gst_d3d11_device_unlock (device); data->ret = FALSE; goto clear; } @@ -743,6 +749,7 @@ gst_d3d11_color_convert_setup_shader (GstD3D11Device * device, (ID3D11Resource *) vertex_buffer, 0); ID3D11DeviceContext_Unmap (context_handle, (ID3D11Resource *) index_buffer, 0); + gst_d3d11_device_unlock (device); self->quad = gst_d3d11_quad_new (device, ps, vs, layout, sampler, const_buffer, vertex_buffer, sizeof (VertexData), @@ -856,8 +863,7 @@ gst_d3d11_color_converter_new (GstD3D11Device * device, data.self = converter; data.in_info = in_info; data.out_info = out_info; - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) gst_d3d11_color_convert_setup_shader, &data); + gst_d3d11_color_convert_setup_shader (device, &data); if (!data.ret || !converter->quad) { GST_ERROR ("Couldn't setup shader"); @@ -897,51 +903,17 @@ gst_d3d11_color_converter_free (GstD3D11ColorConverter * converter) g_free (converter); } -typedef struct -{ - GstD3D11ColorConverter *self; - ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES]; - ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES]; - - gboolean ret; -} DoConvertData; - -static void -do_convert (GstD3D11Device * device, DoConvertData * data) -{ - GstD3D11ColorConverter *self = data->self; - - data->ret = - gst_d3d11_draw_quad (self->quad, &self->viewport, 1, - data->srv, self->num_input_view, data->rtv, self->num_output_view); -} - gboolean gst_d3d11_color_converter_convert (GstD3D11ColorConverter * converter, ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES]) { - DoConvertData data = { 0, }; - gint i; - g_return_val_if_fail (converter != NULL, FALSE); g_return_val_if_fail (srv != NULL, FALSE); g_return_val_if_fail (rtv != NULL, FALSE); - data.self = converter; - - for (i = 0; i < converter->num_input_view; i++) - data.srv[i] = srv[i]; - - for (i = 0; i < converter->num_output_view; i++) - data.rtv[i] = rtv[i]; - - data.ret = TRUE; - - gst_d3d11_device_thread_add (converter->device, - (GstD3D11DeviceThreadFunc) do_convert, &data); - - return data.ret; + return gst_d3d11_draw_quad (converter->quad, &converter->viewport, 1, + srv, converter->num_input_view, rtv, converter->num_output_view); } gboolean diff --git a/sys/d3d11/gstd3d11device.c b/sys/d3d11/gstd3d11device.c index 02f0cc3..d18e3f0 100644 --- a/sys/d3d11/gstd3d11device.c +++ b/sys/d3d11/gstd3d11device.c @@ -75,15 +75,7 @@ struct _GstD3D11DevicePrivate GstD3D11DXGIFactoryVersion factory_ver; D3D_FEATURE_LEVEL feature_level; - ID3D11VideoDevice *video_device; - ID3D11VideoContext *video_context; - - GMutex lock; - GCond cond; - GThread *thread; - GThread *active_thread; - GMainLoop *loop; - GMainContext *main_context; + GRecMutex extern_lock; #ifdef HAVE_D3D11SDKLAYER_H ID3D11Debug *debug; @@ -102,8 +94,6 @@ static void gst_d3d11_device_constructed (GObject * object); static void gst_d3d11_device_dispose (GObject * object); static void gst_d3d11_device_finalize (GObject * object); -static gpointer gst_d3d11_device_thread_func (gpointer data); - #ifdef HAVE_D3D11SDKLAYER_H static gboolean gst_d3d11_device_enable_debug_layer (void) @@ -206,11 +196,7 @@ gst_d3d11_device_init (GstD3D11Device * self) priv = gst_d3d11_device_get_instance_private (self); priv->adapter = DEFAULT_ADAPTER; - g_mutex_init (&priv->lock); - g_cond_init (&priv->cond); - - priv->main_context = g_main_context_new (); - priv->loop = g_main_loop_new (priv->main_context, FALSE); + g_rec_mutex_init (&priv->extern_lock); self->priv = priv; } @@ -332,7 +318,6 @@ gst_d3d11_device_constructed (GObject * object) priv->factory = factory; - #ifdef HAVE_D3D11SDKLAYER_H if ((d3d11_flags & D3D11_CREATE_DEVICE_DEBUG) == D3D11_CREATE_DEVICE_DEBUG) { ID3D11Debug *debug; @@ -351,30 +336,14 @@ gst_d3d11_device_constructed (GObject * object) hr = ID3D11Device_QueryInterface (priv->device, &IID_ID3D11InfoQueue, (void **) &info_queue); if (SUCCEEDED (hr)) { - GSource *source; - GST_DEBUG_OBJECT (self, "D3D11InfoQueue interface available"); priv->info_queue = info_queue; - - source = g_idle_source_new (); - g_source_set_callback (source, (GSourceFunc) gst_d3d11_device_get_message, - self, NULL); - - g_source_attach (source, priv->main_context); - g_source_unref (source); } } #endif IDXGIAdapter1_Release (adapter); - g_mutex_lock (&priv->lock); - priv->thread = g_thread_new ("GstD3D11Device", - (GThreadFunc) gst_d3d11_device_thread_func, self); - while (!g_main_loop_is_running (priv->loop)) - g_cond_wait (&priv->cond, &priv->lock); - g_mutex_unlock (&priv->lock); - G_OBJECT_CLASS (parent_class)->constructed (object); return; @@ -458,39 +427,10 @@ gst_d3d11_device_dispose (GObject * object) priv->device_context = NULL; } - if (priv->video_device) { - ID3D11VideoDevice_Release (priv->video_device); - priv->video_device = NULL; - } - - if (priv->video_context) { - ID3D11VideoContext_Release (priv->video_context); - priv->video_context = NULL; - } - if (priv->factory) { IDXGIFactory1_Release (priv->factory); priv->factory = NULL; } - - if (priv->loop) { - g_main_loop_quit (priv->loop); - } - - if (priv->thread) { - g_thread_join (priv->thread); - priv->thread = NULL; - } - - if (priv->loop) { - g_main_loop_unref (priv->loop); - priv->loop = NULL; - } - - if (priv->main_context) { - g_main_context_unref (priv->main_context); - priv->main_context = NULL; - } #ifdef HAVE_D3D11SDKLAYER_H if (priv->debug) { ID3D11Debug_ReportLiveDeviceObjects (priv->debug, @@ -518,53 +458,12 @@ gst_d3d11_device_finalize (GObject * object) GST_LOG_OBJECT (self, "finalize"); - g_mutex_clear (&priv->lock); - g_cond_clear (&priv->cond); + g_rec_mutex_clear (&priv->extern_lock); g_free (priv->description); G_OBJECT_CLASS (parent_class)->finalize (object); } -static gboolean -running_cb (gpointer user_data) -{ - GstD3D11Device *self = GST_D3D11_DEVICE (user_data); - GstD3D11DevicePrivate *priv = self->priv; - - GST_TRACE_OBJECT (self, "Main loop running now"); - - g_mutex_lock (&priv->lock); - g_cond_signal (&priv->cond); - g_mutex_unlock (&priv->lock); - - return G_SOURCE_REMOVE; -} - -static gpointer -gst_d3d11_device_thread_func (gpointer data) -{ - GstD3D11Device *self = GST_D3D11_DEVICE (data); - GstD3D11DevicePrivate *priv = self->priv; - GSource *source; - - GST_DEBUG_OBJECT (self, "Enter loop"); - g_main_context_push_thread_default (priv->main_context); - - source = g_idle_source_new (); - g_source_set_callback (source, (GSourceFunc) running_cb, self, NULL); - g_source_attach (source, priv->main_context); - g_source_unref (source); - - priv->active_thread = g_thread_self (); - g_main_loop_run (priv->loop); - - g_main_context_pop_thread_default (priv->main_context); - - GST_DEBUG_OBJECT (self, "Exit loop"); - - return NULL; -} - /** * gst_d3d11_device_new: * @adapter: the index of adapter for creating d3d11 device @@ -642,119 +541,6 @@ gst_d3d11_device_get_chosen_feature_level (GstD3D11Device * device) return device->priv->feature_level; } -typedef struct -{ - GstD3D11Device *device; - GstD3D11DeviceThreadFunc func; - - gpointer data; - gboolean fired; -} MessageData; - -static gboolean -gst_d3d11_device_message_callback (MessageData * msg) -{ - GstD3D11Device *self = msg->device; - GstD3D11DevicePrivate *priv = self->priv; - - msg->func (self, msg->data); - - g_mutex_lock (&priv->lock); - msg->fired = TRUE; - g_cond_broadcast (&priv->cond); - g_mutex_unlock (&priv->lock); - - return G_SOURCE_REMOVE; -} - -/** - * gst_d3d11_device_thread_add: - * @device: a #GstD3D11Device - * @func: (scope call): a #GstD3D11DeviceThreadFunc - * @data: (closure): user data to call @func with - * - * Execute @func in the D3DDevice thread of @device with @data - * - * MT-safe - */ -void -gst_d3d11_device_thread_add (GstD3D11Device * device, - GstD3D11DeviceThreadFunc func, gpointer data) -{ - gst_d3d11_device_thread_add_full (device, - G_PRIORITY_DEFAULT, func, data, NULL); -} - -/** - * gst_d3d11_device_thread_add_full: - * @device: a #GstD3D11Device - * @priority: the priority at which to run @func - * @func: (scope call): a #GstD3D11DeviceThreadFunc - * @data: (closure): user data to call @func with - * @notify: (nullable): a function to call when @data is no longer in use, or %NULL. - * - * Execute @func in the D3DDevice thread of @device with @data with specified - * @priority - * - * MT-safe - */ -void -gst_d3d11_device_thread_add_full (GstD3D11Device * device, - gint priority, GstD3D11DeviceThreadFunc func, gpointer data, - GDestroyNotify notify) -{ - GstD3D11DevicePrivate *priv; - MessageData msg = { 0, }; - - g_return_if_fail (GST_IS_D3D11_DEVICE (device)); - g_return_if_fail (func != NULL); - - priv = device->priv; - - if (priv->active_thread == g_thread_self ()) { - func (device, data); - return; - } - - msg.device = gst_object_ref (device); - msg.func = func; - msg.data = data; - msg.fired = FALSE; - - g_main_context_invoke_full (priv->main_context, priority, - (GSourceFunc) gst_d3d11_device_message_callback, &msg, notify); - - g_mutex_lock (&priv->lock); - while (!msg.fired) - g_cond_wait (&priv->cond, &priv->lock); - g_mutex_unlock (&priv->lock); - - gst_object_unref (device); -} - -typedef struct -{ - IDXGISwapChain *swap_chain; - const DXGI_SWAP_CHAIN_DESC *desc; -} CreateSwapChainData; - -static void -gst_d3d11_device_create_swap_chain_internal (GstD3D11Device * device, - CreateSwapChainData * data) -{ - GstD3D11DevicePrivate *priv = device->priv; - HRESULT hr; - - hr = IDXGIFactory1_CreateSwapChain (priv->factory, (IUnknown *) priv->device, - (DXGI_SWAP_CHAIN_DESC *) data->desc, &data->swap_chain); - - if (!gst_d3d11_result (hr)) { - GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x", - (guint) hr); - data->swap_chain = NULL; - } -} - /** * gst_d3d11_device_create_swap_chain: * @device: a #GstD3D11Device @@ -770,47 +556,29 @@ IDXGISwapChain * gst_d3d11_device_create_swap_chain (GstD3D11Device * device, const DXGI_SWAP_CHAIN_DESC * desc) { - CreateSwapChainData data = { 0, }; + GstD3D11DevicePrivate *priv; + HRESULT hr; + IDXGISwapChain *swap_chain = NULL; g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); - data.swap_chain = NULL; - data.desc = desc; - - gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc) - gst_d3d11_device_create_swap_chain_internal, &data); - - return data.swap_chain; -} - -#if (DXGI_HEADER_VERSION >= 2) -typedef struct -{ - IDXGISwapChain1 *swap_chain; - HWND hwnd; - const DXGI_SWAP_CHAIN_DESC1 *desc; - const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc; - IDXGIOutput *output; -} CreateSwapChainForHwndData; - -static void -gst_d3d11_device_create_swap_chain_for_hwnd_internal (GstD3D11Device * device, - CreateSwapChainForHwndData * data) -{ - GstD3D11DevicePrivate *priv = device->priv; - HRESULT hr; + priv = device->priv; - hr = IDXGIFactory2_CreateSwapChainForHwnd ((IDXGIFactory2 *) priv->factory, - (IUnknown *) priv->device, data->hwnd, data->desc, data->fullscreen_desc, - data->output, &data->swap_chain); + gst_d3d11_device_lock (device); + hr = IDXGIFactory1_CreateSwapChain (priv->factory, (IUnknown *) priv->device, + (DXGI_SWAP_CHAIN_DESC *) desc, &swap_chain); + gst_d3d11_device_unlock (device); if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x", (guint) hr); - data->swap_chain = NULL; + swap_chain = NULL; } + + return swap_chain; } +#if (DXGI_HEADER_VERSION >= 2) /** * gst_d3d11_device_create_swap_chain_for_hwnd: * @device: a #GstD3D11Device @@ -832,29 +600,29 @@ gst_d3d11_device_create_swap_chain_for_hwnd (GstD3D11Device * device, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC * fullscreen_desc, IDXGIOutput * output) { - CreateSwapChainForHwndData data = { 0, }; + GstD3D11DevicePrivate *priv; + IDXGISwapChain1 *swap_chain = NULL; + HRESULT hr; g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); - data.swap_chain = NULL; - data.hwnd = hwnd; - data.desc = desc; - data.fullscreen_desc = fullscreen_desc; - data.output = output; + priv = device->priv; - gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc) - gst_d3d11_device_create_swap_chain_for_hwnd_internal, &data); + gst_d3d11_device_lock (device); + hr = IDXGIFactory2_CreateSwapChainForHwnd ((IDXGIFactory2 *) priv->factory, + (IUnknown *) priv->device, hwnd, desc, fullscreen_desc, + output, &swap_chain); + gst_d3d11_device_unlock (device); - return data.swap_chain; -} -#endif + if (!gst_d3d11_result (hr)) { + GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x", + (guint) hr); + swap_chain = NULL; + } -static void -gst_d3d11_device_release_swap_chain_internal (GstD3D11Device * device, - IDXGISwapChain * swap_chain) -{ - IDXGISwapChain_Release (swap_chain); + return swap_chain; } +#endif /** * gst_d3d11_device_release_swap_chain: @@ -862,38 +630,35 @@ gst_d3d11_device_release_swap_chain_internal (GstD3D11Device * device, * @swap_chain: a IDXGISwapChain * * Release a @swap_chain from device thread - * */ void gst_d3d11_device_release_swap_chain (GstD3D11Device * device, IDXGISwapChain * swap_chain) { g_return_if_fail (GST_IS_D3D11_DEVICE (device)); + g_return_if_fail (swap_chain != NULL); - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) gst_d3d11_device_release_swap_chain_internal, - swap_chain); + gst_d3d11_device_lock (device); + IDXGISwapChain_Release (swap_chain); + gst_d3d11_device_unlock (device); } -typedef struct +ID3D11Texture2D * +gst_d3d11_device_create_texture (GstD3D11Device * device, + const D3D11_TEXTURE2D_DESC * desc, + const D3D11_SUBRESOURCE_DATA * inital_data) { + GstD3D11DevicePrivate *priv; + HRESULT hr; ID3D11Texture2D *texture; - const D3D11_TEXTURE2D_DESC *desc; - const D3D11_SUBRESOURCE_DATA *inital_data; -} CreateTextureData; -static void -gst_d3d11_device_create_texture_internal (GstD3D11Device * device, - CreateTextureData * data) -{ - GstD3D11DevicePrivate *priv = device->priv; - HRESULT hr; + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); + g_return_val_if_fail (desc != NULL, NULL); - hr = ID3D11Device_CreateTexture2D (priv->device, data->desc, - data->inital_data, &data->texture); - if (!gst_d3d11_result (hr)) { - const D3D11_TEXTURE2D_DESC *desc = data->desc; + priv = device->priv; + hr = ID3D11Device_CreateTexture2D (priv->device, desc, inital_data, &texture); + if (!gst_d3d11_result (hr)) { GST_ERROR ("Failed to create texture (0x%x)", (guint) hr); GST_WARNING ("Direct3D11 Allocation params"); @@ -907,44 +672,45 @@ gst_d3d11_device_create_texture_internal (GstD3D11Device * device, GST_WARNING ("\tBindFlags 0x%x", desc->BindFlags); GST_WARNING ("\tCPUAccessFlags 0x%x", desc->CPUAccessFlags); GST_WARNING ("\tMiscFlags 0x%x", desc->MiscFlags); - data->texture = NULL; + texture = NULL; } + + return texture; } -ID3D11Texture2D * -gst_d3d11_device_create_texture (GstD3D11Device * device, - const D3D11_TEXTURE2D_DESC * desc, - const D3D11_SUBRESOURCE_DATA * inital_data) +void +gst_d3d11_device_release_texture (GstD3D11Device * device, + ID3D11Texture2D * texture) { - CreateTextureData data; + g_return_if_fail (GST_IS_D3D11_DEVICE (device)); + g_return_if_fail (texture != NULL); - g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); - g_return_val_if_fail (desc != NULL, NULL); + ID3D11Texture2D_Release (texture); +} - data.texture = NULL; - data.desc = desc; - data.inital_data = inital_data; +void +gst_d3d11_device_lock (GstD3D11Device * device) +{ + GstD3D11DevicePrivate *priv; - gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc) - gst_d3d11_device_create_texture_internal, &data); + g_return_if_fail (GST_IS_D3D11_DEVICE (device)); - return data.texture; -} + priv = device->priv; -static void -gst_d3d11_device_release_texture_internal (GstD3D11Device * device, - ID3D11Texture2D * texture) -{ - ID3D11Texture2D_Release (texture); + GST_TRACE_OBJECT (device, "device locking"); + g_rec_mutex_lock (&priv->extern_lock); + GST_TRACE_OBJECT (device, "device locked"); } void -gst_d3d11_device_release_texture (GstD3D11Device * device, - ID3D11Texture2D * texture) +gst_d3d11_device_unlock (GstD3D11Device * device) { + GstD3D11DevicePrivate *priv; + g_return_if_fail (GST_IS_D3D11_DEVICE (device)); - g_return_if_fail (texture != NULL); - gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc) - gst_d3d11_device_release_texture_internal, texture); + priv = device->priv; + + g_rec_mutex_unlock (&priv->extern_lock); + GST_TRACE_OBJECT (device, "device unlocked"); } diff --git a/sys/d3d11/gstd3d11device.h b/sys/d3d11/gstd3d11device.h index 59cb647..08ccdfb 100644 --- a/sys/d3d11/gstd3d11device.h +++ b/sys/d3d11/gstd3d11device.h @@ -101,16 +101,6 @@ IDXGISwapChain1 * gst_d3d11_device_create_swap_chain_for_hwnd (GstD3D11Devic void gst_d3d11_device_release_swap_chain (GstD3D11Device * device, IDXGISwapChain * swap_chain); -void gst_d3d11_device_thread_add (GstD3D11Device * device, - GstD3D11DeviceThreadFunc func, - gpointer data); - -void gst_d3d11_device_thread_add_full (GstD3D11Device * device, - gint priority, - GstD3D11DeviceThreadFunc func, - gpointer data, - GDestroyNotify notify); - ID3D11Texture2D * gst_d3d11_device_create_texture (GstD3D11Device * device, const D3D11_TEXTURE2D_DESC * desc, const D3D11_SUBRESOURCE_DATA *inital_data); @@ -118,6 +108,10 @@ ID3D11Texture2D * gst_d3d11_device_create_texture (GstD3D11Device * devi void gst_d3d11_device_release_texture (GstD3D11Device * device, ID3D11Texture2D * texture); +void gst_d3d11_device_lock (GstD3D11Device * device); + +void gst_d3d11_device_unlock (GstD3D11Device * device); + G_END_DECLS #endif /* __GST_D3D11_DEVICE_H__ */ diff --git a/sys/d3d11/gstd3d11download.c b/sys/d3d11/gstd3d11download.c index 31ad807..1f612cb 100644 --- a/sys/d3d11/gstd3d11download.c +++ b/sys/d3d11/gstd3d11download.c @@ -265,26 +265,19 @@ gst_d3d11_download_decide_allocation (GstBaseTransform * trans, query); } -typedef struct -{ - GstD3D11BaseFilter *filter; - GstBuffer *inbuf; - GstBuffer *outbuf; - GstFlowReturn ret; -} UploadTransformData; - -static void -download_transform (GstD3D11Device * device, UploadTransformData * data) +static GstFlowReturn +gst_d3d11_download_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) { + GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); GstVideoFrame in_frame, out_frame; - GstD3D11BaseFilter *filter = data->filter; gint i; - if (!gst_video_frame_map (&in_frame, &filter->in_info, data->inbuf, + if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf, GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) goto invalid_buffer; - if (!gst_video_frame_map (&out_frame, &filter->out_info, data->outbuf, + if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf, GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) { gst_video_frame_unmap (&in_frame); goto invalid_buffer; @@ -293,51 +286,20 @@ download_transform (GstD3D11Device * device, UploadTransformData * data) for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&in_frame); i++) { if (!gst_video_frame_copy_plane (&out_frame, &in_frame, i)) { GST_ERROR_OBJECT (filter, "Couldn't copy %dth plane", i); - data->ret = GST_FLOW_ERROR; - return; + return GST_FLOW_ERROR; } } gst_video_frame_unmap (&out_frame); gst_video_frame_unmap (&in_frame); - data->ret = GST_FLOW_OK; - return; + return GST_FLOW_OK; /* ERRORS */ invalid_buffer: { GST_ELEMENT_WARNING (filter, CORE, NOT_IMPLEMENTED, (NULL), ("invalid video buffer received")); - data->ret = GST_FLOW_ERROR; - return; + return GST_FLOW_ERROR; } } - -static GstFlowReturn -gst_d3d11_download_transform (GstBaseTransform * trans, GstBuffer * inbuf, - GstBuffer * outbuf) -{ - GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); - GstMemory *mem; - GstD3D11Device *device; - UploadTransformData data; - - mem = gst_buffer_peek_memory (inbuf, 0); - if (gst_is_d3d11_memory (mem)) { - GstD3D11Memory *dmem = (GstD3D11Memory *) mem; - device = dmem->device; - } else { - device = filter->device; - } - - data.filter = filter; - data.inbuf = inbuf; - data.outbuf = outbuf; - data.ret = GST_FLOW_OK; - - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) download_transform, &data); - - return data.ret; -} diff --git a/sys/d3d11/gstd3d11format.c b/sys/d3d11/gstd3d11format.c index 8c0fd2d..4bfc23a 100644 --- a/sys/d3d11/gstd3d11format.c +++ b/sys/d3d11/gstd3d11format.c @@ -208,15 +208,18 @@ gst_d3d11_format_from_gst (GstVideoFormat format) return NULL; } -typedef struct -{ - GstCaps *caps; - D3D11_FORMAT_SUPPORT flags; -} SupportCapsData; - -static void -gst_d3d11_device_get_supported_caps_internal (GstD3D11Device * device, - SupportCapsData * data) +/** + * gst_d3d11_device_get_supported_caps: + * @device: a #GstD3DDevice + * @flags: D3D11_FORMAT_SUPPORT flags + * + * Check supported format with given flags + * + * Returns: a #GstCaps representing supported format + */ +GstCaps * +gst_d3d11_device_get_supported_caps (GstD3D11Device * device, + D3D11_FORMAT_SUPPORT flags) { ID3D11Device *d3d11_device; HRESULT hr; @@ -225,6 +228,8 @@ gst_d3d11_device_get_supported_caps_internal (GstD3D11Device * device, GstCaps *supported_caps; GstD3D11Format *format_list; + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); + d3d11_device = gst_d3d11_device_get_device_handle (device); g_value_init (&v_list, GST_TYPE_LIST); @@ -241,12 +246,12 @@ gst_d3d11_device_get_supported_caps_internal (GstD3D11Device * device, hr = ID3D11Device_CheckFormatSupport (d3d11_device, format_list[i].dxgi_format, &format_support); - if (SUCCEEDED (hr) && ((format_support & data->flags) == data->flags)) { + if (SUCCEEDED (hr) && ((format_support & flags) == flags)) { GValue v_str = G_VALUE_INIT; g_value_init (&v_str, G_TYPE_STRING); GST_LOG_OBJECT (device, "d3d11 device can support %s with flags 0x%x", - gst_video_format_to_string (format), data->flags); + gst_video_format_to_string (format), flags); g_value_set_string (&v_str, gst_video_format_to_string (format)); gst_value_list_append_and_take_value (&v_list, &v_str); } @@ -262,31 +267,5 @@ gst_d3d11_device_get_supported_caps_internal (GstD3D11Device * device, gst_caps_set_features_simple (supported_caps, gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)); - data->caps = supported_caps; -} - -/** - * gst_d3d11_device_get_supported_caps: - * @device: a #GstD3DDevice - * @flags: D3D11_FORMAT_SUPPORT flags - * - * Check supported format with given flags - * - * Returns: a #GstCaps representing supported format - */ -GstCaps * -gst_d3d11_device_get_supported_caps (GstD3D11Device * device, - D3D11_FORMAT_SUPPORT flags) -{ - SupportCapsData data; - - g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL); - - data.caps = NULL; - data.flags = flags; - - gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc) - gst_d3d11_device_get_supported_caps_internal, &data); - - return data.caps; + return supported_caps; } diff --git a/sys/d3d11/gstd3d11memory.c b/sys/d3d11/gstd3d11memory.c index 1cf6eb9..5e17d71 100644 --- a/sys/d3d11/gstd3d11memory.c +++ b/sys/d3d11/gstd3d11memory.c @@ -199,55 +199,34 @@ create_staging_texture (GstD3D11Device * device, return gst_d3d11_device_create_texture (device, &desc, NULL); } -typedef struct +static gboolean +map_cpu_access_data (GstD3D11Memory * dmem, D3D11_MAP map_type) { - ID3D11Resource *dst; - ID3D11Resource *src; -} D3D11CopyTextureData; - -static void -copy_texture (GstD3D11Device * device, D3D11CopyTextureData * data) -{ - ID3D11DeviceContext *device_context = - gst_d3d11_device_get_device_context_handle (device); - - ID3D11DeviceContext_CopySubresourceRegion (device_context, - data->dst, 0, 0, 0, 0, data->src, 0, NULL); -} - -typedef struct -{ - GstD3D11Memory *mem; - D3D11_MAP map_type; - - gboolean ret; -} D3D11MapData; - -static void -map_cpu_access_data (GstD3D11Device * device, D3D11MapData * map_data) -{ - GstD3D11Memory *dmem = map_data->mem; HRESULT hr; + gboolean ret = TRUE; ID3D11Resource *texture = (ID3D11Resource *) dmem->texture; ID3D11Resource *staging = (ID3D11Resource *) dmem->staging; ID3D11DeviceContext *device_context = - gst_d3d11_device_get_device_context_handle (device); + gst_d3d11_device_get_device_context_handle (dmem->device); + gst_d3d11_device_lock (dmem->device); if (GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD)) { ID3D11DeviceContext_CopySubresourceRegion (device_context, staging, 0, 0, 0, 0, texture, 0, NULL); } hr = ID3D11DeviceContext_Map (device_context, - staging, 0, map_data->map_type, 0, &dmem->map); + staging, 0, map_type, 0, &dmem->map); if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (GST_MEMORY_CAST (dmem)->allocator, "Failed to map staging texture (0x%x)", (guint) hr); - map_data->ret = FALSE; + ret = FALSE; } - map_data->ret = TRUE; + gst_d3d11_device_unlock (dmem->device); + + return ret; } static gpointer @@ -265,13 +244,14 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) if ((flags & GST_MAP_D3D11) == GST_MAP_D3D11) { if (dmem->staging && GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD)) { - D3D11CopyTextureData data; - - data.dst = (ID3D11Resource *) dmem->texture; - data.src = (ID3D11Resource *) dmem->staging; - - gst_d3d11_device_thread_add (dmem->device, - (GstD3D11DeviceThreadFunc) copy_texture, &data); + ID3D11DeviceContext *device_context = + gst_d3d11_device_get_device_context_handle (dmem->device); + + gst_d3d11_device_lock (dmem->device); + ID3D11DeviceContext_CopySubresourceRegion (device_context, + (ID3D11Resource *) dmem->texture, 0, 0, 0, 0, + (ID3D11Resource *) dmem->staging, 0, NULL); + gst_d3d11_device_unlock (dmem->device); } GST_MEMORY_FLAG_UNSET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD); @@ -286,7 +266,7 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) } if (dmem->cpu_map_count == 0) { - D3D11MapData map_data; + D3D11_MAP map_type; /* Allocate staging texture for CPU access */ if (!dmem->staging) { @@ -302,13 +282,9 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); } - map_data.mem = dmem; - map_data.map_type = gst_map_flags_to_d3d11 (flags); - - gst_d3d11_device_thread_add (dmem->device, (GstD3D11DeviceThreadFunc) - map_cpu_access_data, &map_data); + map_type = gst_map_flags_to_d3d11 (flags); - if (!map_data.ret) { + if (!map_cpu_access_data (dmem, map_type)) { GST_ERROR_OBJECT (mem->allocator, "Couldn't map staging texture"); g_mutex_unlock (&dmem->lock); @@ -328,14 +304,15 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) } static void -unmap_cpu_access_data (GstD3D11Device * device, gpointer data) +unmap_cpu_access_data (GstD3D11Memory * dmem) { - GstD3D11Memory *dmem = (GstD3D11Memory *) data; ID3D11Resource *staging = (ID3D11Resource *) dmem->staging; ID3D11DeviceContext *device_context = - gst_d3d11_device_get_device_context_handle (device); + gst_d3d11_device_get_device_context_handle (dmem->device); + gst_d3d11_device_lock (dmem->device); ID3D11DeviceContext_Unmap (device_context, staging, 0); + gst_d3d11_device_unlock (dmem->device); } static void @@ -367,8 +344,7 @@ gst_d3d11_memory_unmap_full (GstMemory * mem, GstMapInfo * info) return; } - gst_d3d11_device_thread_add (dmem->device, (GstD3D11DeviceThreadFunc) - unmap_cpu_access_data, dmem); + unmap_cpu_access_data (dmem); g_mutex_unlock (&dmem->lock); } @@ -388,37 +364,28 @@ gst_d3d11_allocator_dummy_alloc (GstAllocator * allocator, gsize size, } static void -release_texture (GstD3D11Device * device, GstD3D11Memory * mem) +gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem) { + GstD3D11Memory *dmem = (GstD3D11Memory *) mem; gint i; for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) { - if (mem->render_target_view[i]) - ID3D11RenderTargetView_Release (mem->render_target_view[i]); - mem->render_target_view[i] = NULL; + if (dmem->render_target_view[i]) + ID3D11RenderTargetView_Release (dmem->render_target_view[i]); + dmem->render_target_view[i] = NULL; - if (mem->shader_resource_view[i]) - ID3D11ShaderResourceView_Release (mem->shader_resource_view[i]); - mem->shader_resource_view[i] = NULL; + if (dmem->shader_resource_view[i]) + ID3D11ShaderResourceView_Release (dmem->shader_resource_view[i]); + dmem->shader_resource_view[i] = NULL; } - if (mem->texture) - ID3D11Texture2D_Release (mem->texture); + if (dmem->texture) + ID3D11Texture2D_Release (dmem->texture); - if (mem->staging) - ID3D11Texture2D_Release (mem->staging); -} - -static void -gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem) -{ - GstD3D11Memory *dmem = (GstD3D11Memory *) mem; - GstD3D11Device *device = dmem->device; + if (dmem->staging) + ID3D11Texture2D_Release (dmem->staging); - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) release_texture, dmem); - - gst_object_unref (device); + gst_clear_object (&dmem->device); g_mutex_clear (&dmem->lock); g_free (dmem); @@ -476,44 +443,39 @@ gst_d3d11_allocator_new (GstD3D11Device * device) return allocator; } -typedef struct -{ - ID3D11Resource *texture; - D3D11_TEXTURE2D_DESC *desc; - D3D11_MAP map_mode; - - gint stride[GST_VIDEO_MAX_PLANES]; - gsize size; - - gboolean ret; -} CalSizeData; - -static void -calculate_mem_size (GstD3D11Device * device, CalSizeData * data) +static gboolean +calculate_mem_size (GstD3D11Device * device, ID3D11Texture2D * texture, + D3D11_TEXTURE2D_DESC * desc, D3D11_MAP map_type, + gint stride[GST_VIDEO_MAX_PLANES], gsize * size) { HRESULT hr; + gboolean ret = TRUE; D3D11_MAPPED_SUBRESOURCE map; gsize offset[GST_VIDEO_MAX_PLANES]; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (device); + gst_d3d11_device_lock (device); hr = ID3D11DeviceContext_Map (device_context, - data->texture, 0, data->map_mode, 0, &map); + (ID3D11Resource *) texture, 0, map_type, 0, &map); if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (device, "Failed to map texture (0x%x)", (guint) hr); - data->ret = FALSE; + gst_d3d11_device_unlock (device); + return FALSE; } - data->ret = gst_d3d11_dxgi_format_get_size (data->desc->Format, - data->desc->Width, data->desc->Height, map.RowPitch, - offset, data->stride, &data->size); + ret = gst_d3d11_dxgi_format_get_size (desc->Format, + desc->Width, desc->Height, map.RowPitch, offset, stride, size); + + ID3D11DeviceContext_Unmap (device_context, (ID3D11Resource *) texture, 0); + gst_d3d11_device_unlock (device); - ID3D11DeviceContext_Unmap (device_context, data->texture, 0); + return ret; } static void -create_shader_resource_views (GstD3D11Device * device, GstD3D11Memory * mem) +create_shader_resource_views (GstD3D11Memory * mem) { gint i; HRESULT hr; @@ -522,7 +484,7 @@ create_shader_resource_views (GstD3D11Device * device, GstD3D11Memory * mem) D3D11_SHADER_RESOURCE_VIEW_DESC resource_desc = { 0, }; DXGI_FORMAT formats[GST_VIDEO_MAX_PLANES] = { DXGI_FORMAT_UNKNOWN, }; - device_handle = gst_d3d11_device_get_device_handle (device); + device_handle = gst_d3d11_device_get_device_handle (mem->device); switch (mem->desc.Format) { case DXGI_FORMAT_B8G8R8A8_UNORM: @@ -566,7 +528,7 @@ create_shader_resource_views (GstD3D11Device * device, GstD3D11Memory * mem) &mem->shader_resource_view[i]); if (!gst_d3d11_result (hr)) { - GST_ERROR_OBJECT (device, + GST_ERROR_OBJECT (GST_MEMORY_CAST (mem)->allocator, "Failed to create %dth resource view (0x%x)", i, (guint) hr); goto error; } @@ -588,7 +550,7 @@ error: } static void -create_render_target_views (GstD3D11Device * device, GstD3D11Memory * mem) +create_render_target_views (GstD3D11Memory * mem) { gint i; HRESULT hr; @@ -597,7 +559,7 @@ create_render_target_views (GstD3D11Device * device, GstD3D11Memory * mem) D3D11_RENDER_TARGET_VIEW_DESC render_desc = { 0, }; DXGI_FORMAT formats[GST_VIDEO_MAX_PLANES] = { DXGI_FORMAT_UNKNOWN, }; - device_handle = gst_d3d11_device_get_device_handle (device); + device_handle = gst_d3d11_device_get_device_handle (mem->device); switch (mem->desc.Format) { case DXGI_FORMAT_B8G8R8A8_UNORM: @@ -641,7 +603,7 @@ create_render_target_views (GstD3D11Device * device, GstD3D11Memory * mem) (ID3D11Resource *) mem->texture, &render_desc, &mem->render_target_view[i]); if (!gst_d3d11_result (hr)) { - GST_ERROR_OBJECT (device, + GST_ERROR_OBJECT (GST_MEMORY_CAST (mem)->allocator, "Failed to create %dth render target view (0x%x)", i, (guint) hr); goto error; } @@ -704,8 +666,11 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, /* per plane, allocated staging texture to calculate actual size, * stride, and offset */ if (is_first) { - CalSizeData data; + ID3D11Texture2D *target; + D3D11_MAP map_type; gint num_plane; + gint stride[GST_VIDEO_MAX_PLANES]; + gsize mem_size; gint i; if (desc->Usage == D3D11_USAGE_DEFAULT) { @@ -715,27 +680,25 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator, goto error; } - data.texture = (ID3D11Resource *) staging; - data.map_mode = D3D11_MAP_READ; + target = staging; + map_type = D3D11_MAP_READ; } else if (desc->Usage == D3D11_USAGE_DYNAMIC) { - data.texture = (ID3D11Resource *) texture; - data.map_mode = D3D11_MAP_WRITE_DISCARD; + target = texture; + map_type = D3D11_MAP_WRITE_DISCARD; } else { g_assert_not_reached (); } - data.desc = desc; - - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) calculate_mem_size, &data); + if (!calculate_mem_size (device, target, desc, map_type, stride, &mem_size)) + goto error; num_plane = gst_d3d11_dxgi_format_n_planes (desc->Format); for (i = 0; i < num_plane; i++) { - params->stride[params->plane + i] = data.stride[i]; + params->stride[params->plane + i] = stride[i]; } - *size = data.size; + *size = mem_size; } mem = g_new0 (GstD3D11Memory, 1); @@ -788,8 +751,7 @@ gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem) return FALSE; } - gst_d3d11_device_thread_add (mem->device, - (GstD3D11DeviceThreadFunc) create_shader_resource_views, mem); + create_shader_resource_views (mem); return ! !mem->num_shader_resource_views; } @@ -809,8 +771,7 @@ gst_d3d11_memory_ensure_render_target_view (GstD3D11Memory * mem) return FALSE; } - gst_d3d11_device_thread_add (mem->device, - (GstD3D11DeviceThreadFunc) create_render_target_views, mem); + create_render_target_views (mem); return ! !mem->num_render_target_views; } diff --git a/sys/d3d11/gstd3d11shader.c b/sys/d3d11/gstd3d11shader.c index 81d2a0c..cdd424e 100644 --- a/sys/d3d11/gstd3d11shader.c +++ b/sys/d3d11/gstd3d11shader.c @@ -73,88 +73,68 @@ compile_shader (GstD3D11Device * device, const gchar * shader_source, return ret; } -typedef struct -{ - const gchar *source; - ID3D11PixelShader *shader; - gboolean ret; -} CreatePSData; - -static void -create_pixel_shader (GstD3D11Device * device, CreatePSData * data) +gboolean +gst_d3d11_create_pixel_shader (GstD3D11Device * device, + const gchar * source, ID3D11PixelShader ** shader) { ID3DBlob *ps_blob; ID3D11Device *device_handle; HRESULT hr; - data->ret = TRUE; + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE); + g_return_val_if_fail (source != NULL, FALSE); + g_return_val_if_fail (shader != NULL, FALSE); - ps_blob = compile_shader (device, data->source, TRUE); + gst_d3d11_device_lock (device); + ps_blob = compile_shader (device, source, TRUE); if (!ps_blob) { GST_ERROR ("Failed to compile pixel shader"); - data->ret = FALSE; - return; + gst_d3d11_device_unlock (device); + return FALSE; } device_handle = gst_d3d11_device_get_device_handle (device); hr = ID3D11Device_CreatePixelShader (device_handle, (gpointer) ID3D10Blob_GetBufferPointer (ps_blob), - ID3D10Blob_GetBufferSize (ps_blob), NULL, &data->shader); + ID3D10Blob_GetBufferSize (ps_blob), NULL, shader); if (!gst_d3d11_result (hr)) { GST_ERROR ("could not create pixel shader, hr: 0x%x", (guint) hr); - data->ret = FALSE; + gst_d3d11_device_unlock (device); + return FALSE; } ID3D10Blob_Release (ps_blob); -} - -gboolean -gst_d3d11_create_pixel_shader (GstD3D11Device * device, - const gchar * source, ID3D11PixelShader ** shader) -{ - CreatePSData data = { 0, }; + gst_d3d11_device_unlock (device); - g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE); - g_return_val_if_fail (source != NULL, FALSE); - g_return_val_if_fail (shader != NULL, FALSE); - - data.source = source; - - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) create_pixel_shader, &data); - - *shader = data.shader; - return data.ret; + return TRUE; } -typedef struct -{ - const gchar *source; - const D3D11_INPUT_ELEMENT_DESC *input_desc; - guint desc_len; - ID3D11VertexShader *shader; - ID3D11InputLayout *layout; - gboolean ret; -} CreateVSData; - -static void -create_vertex_shader (GstD3D11Device * device, CreateVSData * data) +gboolean +gst_d3d11_create_vertex_shader (GstD3D11Device * device, const gchar * source, + const D3D11_INPUT_ELEMENT_DESC * input_desc, guint desc_len, + ID3D11VertexShader ** shader, ID3D11InputLayout ** layout) { ID3DBlob *vs_blob; ID3D11Device *device_handle; HRESULT hr; ID3D11VertexShader *vshader = NULL; ID3D11InputLayout *in_layout = NULL; + gboolean ret = FALSE; - data->ret = TRUE; + g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE); + g_return_val_if_fail (source != NULL, FALSE); + g_return_val_if_fail (input_desc != NULL, FALSE); + g_return_val_if_fail (desc_len > 0, FALSE); + g_return_val_if_fail (shader != NULL, FALSE); + g_return_val_if_fail (layout != NULL, FALSE); - vs_blob = compile_shader (device, data->source, FALSE); + gst_d3d11_device_lock (device); + vs_blob = compile_shader (device, source, FALSE); if (!vs_blob) { GST_ERROR ("Failed to compile shader code"); - data->ret = FALSE; - return; + goto done; } device_handle = gst_d3d11_device_get_device_handle (device); @@ -166,52 +146,31 @@ create_vertex_shader (GstD3D11Device * device, CreateVSData * data) if (!gst_d3d11_result (hr)) { GST_ERROR ("could not create vertex shader, hr: 0x%x", (guint) hr); ID3D10Blob_Release (vs_blob); - data->ret = FALSE; - return; + goto done; } - hr = ID3D11Device_CreateInputLayout (device_handle, data->input_desc, - data->desc_len, (gpointer) ID3D10Blob_GetBufferPointer (vs_blob), + hr = ID3D11Device_CreateInputLayout (device_handle, input_desc, + desc_len, (gpointer) ID3D10Blob_GetBufferPointer (vs_blob), ID3D10Blob_GetBufferSize (vs_blob), &in_layout); if (!gst_d3d11_result (hr)) { GST_ERROR ("could not create input layout shader, hr: 0x%x", (guint) hr); ID3D10Blob_Release (vs_blob); ID3D11VertexShader_Release (vshader); - data->ret = FALSE; - return; + goto done; } ID3D10Blob_Release (vs_blob); - data->shader = vshader; - data->layout = in_layout; -} - -gboolean -gst_d3d11_create_vertex_shader (GstD3D11Device * device, const gchar * source, - const D3D11_INPUT_ELEMENT_DESC * input_desc, guint desc_len, - ID3D11VertexShader ** shader, ID3D11InputLayout ** layout) -{ - CreateVSData data = { 0, }; - - g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE); - g_return_val_if_fail (source != NULL, FALSE); - g_return_val_if_fail (input_desc != NULL, FALSE); - g_return_val_if_fail (desc_len > 0, FALSE); - g_return_val_if_fail (shader != NULL, FALSE); - g_return_val_if_fail (layout != NULL, FALSE); + *shader = vshader; + *layout = in_layout; - data.source = source; - data.input_desc = input_desc; - data.desc_len = desc_len; + ret = TRUE; - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) create_vertex_shader, &data); +done: + gst_d3d11_device_unlock (device); - *shader = data.shader; - *layout = data.layout; - return data.ret; + return ret; } struct _GstD3D11Quad @@ -281,9 +240,11 @@ gst_d3d11_quad_new (GstD3D11Device * device, ID3D11PixelShader * pixel_shader, return quad; } -static void -quad_free (GstD3D11Device * device, GstD3D11Quad * quad) +void +gst_d3d11_quad_free (GstD3D11Quad * quad) { + g_return_if_fail (quad != NULL); + if (quad->ps) ID3D11PixelShader_Release (quad->ps); if (quad->vs) @@ -298,43 +259,46 @@ quad_free (GstD3D11Device * device, GstD3D11Quad * quad) ID3D11Buffer_Release (quad->vertex_buffer); if (quad->index_buffer) ID3D11Buffer_Release (quad->index_buffer); + + gst_clear_object (&quad->device); + g_free (quad); } -void -gst_d3d11_quad_free (GstD3D11Quad * quad) +gboolean +gst_d3d11_draw_quad (GstD3D11Quad * quad, + D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES], guint num_viewport, + ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], guint num_srv, + ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], guint num_rtv) { - g_return_if_fail (quad != NULL); + gboolean ret; - if (quad->device) { - gst_d3d11_device_thread_add (quad->device, - (GstD3D11DeviceThreadFunc) quad_free, quad); + g_return_val_if_fail (quad != NULL, FALSE); - gst_object_unref (quad->device); - } + gst_d3d11_device_lock (quad->device); + ret = gst_d3d11_draw_quad_unlocked (quad, viewport, num_viewport, + srv, num_srv, rtv, num_viewport); + gst_d3d11_device_unlock (quad->device); - g_free (quad); + return ret; } -typedef struct -{ - GstD3D11Quad *quad; - D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES]; - guint num_viewport; - ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES]; - guint num_srv; - ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES]; - guint num_rtv; - - gboolean ret; -} DrawQuadData; - -static void -gst_d3d11_draw_quad_internal (GstD3D11Device * device, DrawQuadData * data) +gboolean +gst_d3d11_draw_quad_unlocked (GstD3D11Quad * quad, + D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES], guint num_viewport, + ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], guint num_srv, + ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], guint num_rtv) { ID3D11DeviceContext *context_handle; UINT offsets = 0; ID3D11ShaderResourceView *clear_view[GST_VIDEO_MAX_PLANES] = { NULL, }; - GstD3D11Quad *quad = data->quad; + + g_return_val_if_fail (quad != NULL, FALSE); + g_return_val_if_fail (viewport != NULL, FALSE); + g_return_val_if_fail (num_viewport <= GST_VIDEO_MAX_PLANES, FALSE); + g_return_val_if_fail (srv != NULL, FALSE); + g_return_val_if_fail (num_srv <= GST_VIDEO_MAX_PLANES, FALSE); + g_return_val_if_fail (rtv != NULL, FALSE); + g_return_val_if_fail (num_rtv <= GST_VIDEO_MAX_PLANES, FALSE); context_handle = gst_d3d11_device_get_device_context_handle (quad->device); @@ -349,60 +313,20 @@ gst_d3d11_draw_quad_internal (GstD3D11Device * device, DrawQuadData * data) ID3D11DeviceContext_PSSetSamplers (context_handle, 0, 1, &quad->sampler); ID3D11DeviceContext_VSSetShader (context_handle, quad->vs, NULL, 0); ID3D11DeviceContext_PSSetShader (context_handle, quad->ps, NULL, 0); - ID3D11DeviceContext_RSSetViewports (context_handle, - data->num_viewport, data->viewport); + ID3D11DeviceContext_RSSetViewports (context_handle, num_viewport, viewport); if (quad->const_buffer) ID3D11DeviceContext_PSSetConstantBuffers (context_handle, 0, 1, &quad->const_buffer); - ID3D11DeviceContext_PSSetShaderResources (context_handle, - 0, data->num_srv, data->srv); - ID3D11DeviceContext_OMSetRenderTargets (context_handle, - data->num_rtv, data->rtv, NULL); + ID3D11DeviceContext_PSSetShaderResources (context_handle, 0, num_srv, srv); + ID3D11DeviceContext_OMSetRenderTargets (context_handle, num_rtv, rtv, NULL); ID3D11DeviceContext_DrawIndexed (context_handle, quad->index_count, 0, 0); ID3D11DeviceContext_PSSetShaderResources (context_handle, - 0, data->num_srv, clear_view); - - data->ret = TRUE; -} - -gboolean -gst_d3d11_draw_quad (GstD3D11Quad * quad, - D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES], guint num_viewport, - ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES], guint num_srv, - ID3D11RenderTargetView * rtv[GST_VIDEO_MAX_PLANES], guint num_rtv) -{ - DrawQuadData data = { 0, }; - gint i; - - g_return_val_if_fail (quad != NULL, FALSE); - g_return_val_if_fail (viewport != NULL, FALSE); - g_return_val_if_fail (num_viewport <= GST_VIDEO_MAX_PLANES, FALSE); - g_return_val_if_fail (srv != NULL, FALSE); - g_return_val_if_fail (num_srv <= GST_VIDEO_MAX_PLANES, FALSE); - g_return_val_if_fail (rtv != NULL, FALSE); - g_return_val_if_fail (num_rtv <= GST_VIDEO_MAX_PLANES, FALSE); - - data.quad = quad; - for (i = 0; i < num_viewport; i++) - data.viewport[i] = viewport[i]; - data.num_viewport = num_viewport; - - for (i = 0; i < num_srv; i++) - data.srv[i] = srv[i]; - data.num_srv = num_srv; - - for (i = 0; i < num_rtv; i++) - data.rtv[i] = rtv[i]; - data.num_rtv = num_rtv; - - data.ret = TRUE; - - gst_d3d11_device_thread_add (quad->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_draw_quad_internal, &data); + 0, num_srv, clear_view); + ID3D11DeviceContext_OMSetRenderTargets (context_handle, 0, NULL, NULL); - return data.ret; + return TRUE; } diff --git a/sys/d3d11/gstd3d11shader.h b/sys/d3d11/gstd3d11shader.h index e558696..0ef064d 100644 --- a/sys/d3d11/gstd3d11shader.h +++ b/sys/d3d11/gstd3d11shader.h @@ -63,6 +63,14 @@ gboolean gst_d3d11_draw_quad (GstD3D11Quad * quad, ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES], guint num_rtv); +gboolean gst_d3d11_draw_quad_unlocked (GstD3D11Quad * quad, + D3D11_VIEWPORT viewport[GST_VIDEO_MAX_PLANES], + guint num_viewport, + ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES], + guint num_srv, + ID3D11RenderTargetView *rtv[GST_VIDEO_MAX_PLANES], + guint num_rtv); + G_END_DECLS #endif /* __GST_D3D11_SHADER_H__ */ diff --git a/sys/d3d11/gstd3d11upload.c b/sys/d3d11/gstd3d11upload.c index 9c02901..7ab75cd 100644 --- a/sys/d3d11/gstd3d11upload.c +++ b/sys/d3d11/gstd3d11upload.c @@ -314,32 +314,24 @@ gst_d3d11_upload_decide_allocation (GstBaseTransform * trans, GstQuery * query) query); } -typedef struct -{ - GstD3D11BaseFilter *filter; - GstBuffer *inbuf; - GstBuffer *outbuf; - GstFlowReturn ret; -} UploadTransformData; - -static void -upload_transform_dynamic (GstD3D11Device * device, UploadTransformData * data) +static GstFlowReturn +upload_transform_dynamic (GstD3D11BaseFilter * filter, + GstD3D11Device * device, GstBuffer * inbuf, GstBuffer * outbuf) { GstVideoFrame in_frame; - GstD3D11BaseFilter *filter = data->filter; gint i, j, k; + GstFlowReturn ret = GST_FLOW_OK; ID3D11DeviceContext *device_context = gst_d3d11_device_get_device_context_handle (device); - data->ret = GST_FLOW_OK; - - if (!gst_video_frame_map (&in_frame, &filter->in_info, data->inbuf, + if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf, GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) goto invalid_buffer; - for (i = 0, j = 0; i < gst_buffer_n_memory (data->outbuf); i++) { + gst_d3d11_device_lock (device); + for (i = 0, j = 0; i < gst_buffer_n_memory (outbuf); i++) { GstD3D11Memory *dmem = - (GstD3D11Memory *) gst_buffer_peek_memory (data->outbuf, i); + (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, i); D3D11_MAPPED_SUBRESOURCE map; HRESULT hr; D3D11_TEXTURE2D_DESC *desc = &dmem->desc; @@ -353,7 +345,8 @@ upload_transform_dynamic (GstD3D11Device * device, UploadTransformData * data) if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (filter, "Failed to map staging texture (0x%x)", (guint) hr); - data->ret = GST_FLOW_ERROR; + gst_d3d11_device_unlock (device); + ret = GST_FLOW_ERROR; goto done; } @@ -381,35 +374,35 @@ upload_transform_dynamic (GstD3D11Device * device, UploadTransformData * data) ID3D11DeviceContext_Unmap (device_context, (ID3D11Resource *) dmem->texture, 0); } + gst_d3d11_device_unlock (device); done: gst_video_frame_unmap (&in_frame); - data->ret = GST_FLOW_OK; - return; + return ret; /* ERRORS */ invalid_buffer: { GST_ELEMENT_WARNING (filter, CORE, NOT_IMPLEMENTED, (NULL), ("invalid video buffer received")); - data->ret = GST_FLOW_ERROR; - return; + return GST_FLOW_ERROR; } } -static void -upload_transform (GstD3D11Device * device, UploadTransformData * data) +static GstFlowReturn +upload_transform (GstD3D11BaseFilter * filter, GstBuffer * inbuf, + GstBuffer * outbuf) { GstVideoFrame in_frame, out_frame; - GstD3D11BaseFilter *filter = data->filter; gint i; + GstFlowReturn ret = GST_FLOW_OK; - if (!gst_video_frame_map (&in_frame, &filter->in_info, data->inbuf, + if (!gst_video_frame_map (&in_frame, &filter->in_info, inbuf, GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) goto invalid_buffer; - if (!gst_video_frame_map (&out_frame, &filter->out_info, data->outbuf, + if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf, GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)) { gst_video_frame_unmap (&in_frame); goto invalid_buffer; @@ -418,24 +411,22 @@ upload_transform (GstD3D11Device * device, UploadTransformData * data) for (i = 0; i < GST_VIDEO_FRAME_N_PLANES (&in_frame); i++) { if (!gst_video_frame_copy_plane (&out_frame, &in_frame, i)) { GST_ERROR_OBJECT (filter, "Couldn't copy %dth plane", i); - data->ret = GST_FLOW_ERROR; - return; + ret = GST_FLOW_ERROR; + break; } } gst_video_frame_unmap (&out_frame); gst_video_frame_unmap (&in_frame); - data->ret = GST_FLOW_OK; - return; + return ret; /* ERRORS */ invalid_buffer: { GST_ELEMENT_WARNING (filter, CORE, NOT_IMPLEMENTED, (NULL), ("invalid video buffer received")); - data->ret = GST_FLOW_ERROR; - return; + return GST_FLOW_ERROR; } } @@ -446,32 +437,16 @@ gst_d3d11_upload_transform (GstBaseTransform * trans, GstBuffer * inbuf, GstD3D11BaseFilter *filter = GST_D3D11_BASE_FILTER (trans); GstMemory *mem; GstD3D11Device *device; - UploadTransformData data; - gboolean to_dynamic = FALSE; mem = gst_buffer_peek_memory (outbuf, 0); if (gst_is_d3d11_memory (mem)) { GstD3D11Memory *dmem = (GstD3D11Memory *) mem; device = dmem->device; - if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC) - to_dynamic = TRUE; - } else { - device = filter->device; - } - - data.filter = filter; - data.inbuf = inbuf; - data.outbuf = outbuf; - data.ret = GST_FLOW_OK; - - if (to_dynamic) { - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) upload_transform_dynamic, &data); - } else { - gst_d3d11_device_thread_add (device, - (GstD3D11DeviceThreadFunc) upload_transform, &data); + if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC) { + return upload_transform_dynamic (filter, device, inbuf, outbuf); + } } - return data.ret; + return upload_transform (filter, inbuf, outbuf); } diff --git a/sys/d3d11/gstd3d11window.c b/sys/d3d11/gstd3d11window.c index 5fd5303..1c43b0e 100644 --- a/sys/d3d11/gstd3d11window.c +++ b/sys/d3d11/gstd3d11window.c @@ -70,15 +70,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_d3d11_window_debug); #define gst_d3d11_window_parent_class parent_class G_DEFINE_TYPE (GstD3D11Window, gst_d3d11_window, GST_TYPE_OBJECT); -typedef struct -{ - GstD3D11Window *window; - GstVideoRectangle *rect; - GstBuffer *buffer; - - GstFlowReturn ret; -} FramePresentData; - static void gst_d3d11_window_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_d3d11_window_get_property (GObject * object, guint prop_id, @@ -87,12 +78,11 @@ static void gst_d3d11_window_constructed (GObject * object); static void gst_d3d11_window_dispose (GObject * object); static void gst_d3d11_window_finalize (GObject * object); static gpointer gst_d3d11_window_thread_func (gpointer data); -static gboolean _create_window (GstD3D11Window * self); -static void _open_window (GstD3D11Window * self); -static void _close_window (GstD3D11Window * self); +static gboolean gst_d3d11_window_create_internal_window (GstD3D11Window * self); +static void gst_d3d11_window_close_internal_window (GstD3D11Window * self); static void release_external_win_id (GstD3D11Window * self); -static void _present_on_device_thread (GstD3D11Device * device, - FramePresentData * data); +static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self, + GstBuffer * buffer); static void gst_d3d11_window_class_init (GstD3D11WindowClass * klass) @@ -268,8 +258,7 @@ gst_d3d11_window_dispose (GObject * object) } if (self->device) { - gst_d3d11_device_thread_add (self->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_release_resources, self); + gst_d3d11_window_release_resources (self->device, self); } if (self->converter) { @@ -317,20 +306,16 @@ gst_d3d11_window_thread_func (gpointer data) GST_DEBUG_OBJECT (self, "Enter loop"); g_main_context_push_thread_default (self->main_context); - self->created = _create_window (self); + self->created = gst_d3d11_window_create_internal_window (self); source = g_idle_source_new (); g_source_set_callback (source, (GSourceFunc) running_cb, self, NULL); g_source_attach (source, self->main_context); g_source_unref (source); - if (self->created) - _open_window (self); - g_main_loop_run (self->loop); - if (self->created) - _close_window (self); + gst_d3d11_window_close_internal_window (self); g_main_context_pop_thread_default (self->main_context); @@ -354,16 +339,7 @@ msg_cb (GIOChannel * source, GIOCondition condition, gpointer data) } static void -_open_window (GstD3D11Window * self) -{ - self->msg_io_channel = g_io_channel_win32_new_messages (0); - self->msg_source = g_io_create_watch (self->msg_io_channel, G_IO_IN); - g_source_set_callback (self->msg_source, (GSourceFunc) msg_cb, self, NULL); - g_source_attach (self->msg_source, self->main_context); -} - -static void -_close_window (GstD3D11Window * self) +gst_d3d11_window_close_internal_window (GstD3D11Window * self) { if (self->internal_win_id) { RemoveProp (self->internal_win_id, D3D11_WINDOW_PROP_NAME); @@ -451,7 +427,7 @@ release_external_win_id (GstD3D11Window * self) } static gboolean -_create_window (GstD3D11Window * self) +gst_d3d11_window_create_internal_window (GstD3D11Window * self) { WNDCLASSEX wc; ATOM atom = 0; @@ -519,36 +495,45 @@ _create_window (GstD3D11Window * self) GST_LOG_OBJECT (self, "Created a internal d3d11 window %p", self->internal_win_id); + self->msg_io_channel = + g_io_channel_win32_new_messages ((guintptr) self->internal_win_id); + self->msg_source = g_io_create_watch (self->msg_io_channel, G_IO_IN); + g_source_set_callback (self->msg_source, (GSourceFunc) msg_cb, self, NULL); + g_source_attach (self->msg_source, self->main_context); + return TRUE; } static void -gst_d3d11_window_on_resize (GstD3D11Device * device, GstD3D11Window * window) +gst_d3d11_window_on_resize (GstD3D11Window * window, gboolean redraw) { HRESULT hr; ID3D11Device *d3d11_dev; guint width, height; D3D11_TEXTURE2D_DESC desc; DXGI_SWAP_CHAIN_DESC swap_desc; - ID3D11Texture2D *backbuffer; + ID3D11Texture2D *backbuffer = NULL; + gst_d3d11_device_lock (window->device); if (!window->swap_chain) - return; + goto done; - d3d11_dev = gst_d3d11_device_get_device_handle (device); + d3d11_dev = gst_d3d11_device_get_device_handle (window->device); if (window->rtv) { ID3D11RenderTargetView_Release (window->rtv); window->rtv = NULL; } + window->pending_resize = FALSE; + /* Set zero width and height here. dxgi will decide client area by itself */ IDXGISwapChain_GetDesc (window->swap_chain, &swap_desc); hr = IDXGISwapChain_ResizeBuffers (window->swap_chain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, swap_desc.Flags); if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (window, "Couldn't resize buffers, hr: 0x%x", (guint) hr); - return; + goto done; } hr = IDXGISwapChain_GetBuffer (window->swap_chain, @@ -556,7 +541,7 @@ gst_d3d11_window_on_resize (GstD3D11Device * device, GstD3D11Window * window) if (!gst_d3d11_result (hr)) { GST_ERROR_OBJECT (window, "Cannot get backbuffer from swapchain, hr: 0x%x", (guint) hr); - return; + goto done; } ID3D11Texture2D_GetDesc (backbuffer, &desc); @@ -604,27 +589,14 @@ gst_d3d11_window_on_resize (GstD3D11Device * device, GstD3D11Window * window) goto done; } - if (window->cached_buffer) { - FramePresentData present_data = { 0, }; - - present_data.window = window; - present_data.rect = &window->rect; - present_data.buffer = window->cached_buffer; - GST_DEBUG_OBJECT (window, "redraw cached buffer"); - - _present_on_device_thread (window->device, &present_data); - } + if (redraw) + gst_d3d111_window_present (window, NULL); done: - ID3D11Texture2D_Release (backbuffer); -} + if (backbuffer) + ID3D11Texture2D_Release (backbuffer); -static void -gst_d3d11_window_on_size (GstD3D11Window * self, - HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - gst_d3d11_device_thread_add_full (self->device, G_PRIORITY_HIGH, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_on_resize, self, NULL); + gst_d3d11_device_unlock (window->device); } static void @@ -707,12 +679,12 @@ gst_d3d11_window_handle_window_proc (GstD3D11Window * self, { switch (uMsg) { case WM_SIZE: - gst_d3d11_window_on_size (self, hWnd, wParam, lParam); + gst_d3d11_window_on_resize (self, TRUE); break; case WM_CLOSE: if (self->internal_win_id) { ShowWindow (self->internal_win_id, SW_HIDE); - _close_window (self); + gst_d3d11_window_close_internal_window (self); } break; case WM_KEYDOWN: @@ -760,6 +732,9 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) gst_d3d11_window_handle_window_proc (self, hWnd, uMsg, wParam, lParam); } + if (uMsg == WM_SIZE) + return 0; + return DefWindowProc (hWnd, uMsg, wParam, lParam); } @@ -964,33 +939,26 @@ gst_d3d11_window_color_space_from_video_info (GstD3D11Window * self, } #endif -typedef struct -{ - GstD3D11Window *self; - HWND hwnd; - IDXGISwapChain *swap_chain; -} MakeWindowAssociationData; - static void -gst_d3d11_window_disable_alt_enter (GstD3D11Device * device, - MakeWindowAssociationData * data) +gst_d3d11_window_disable_alt_enter (GstD3D11Window * window, + IDXGISwapChain * swap_chain, HWND hwnd) { IDXGIFactory1 *factory = NULL; HRESULT hr; - hr = IDXGISwapChain_GetParent (data->swap_chain, &IID_IDXGIFactory1, + hr = IDXGISwapChain_GetParent (swap_chain, &IID_IDXGIFactory1, (void **) &factory); if (!gst_d3d11_result (hr) || !factory) { - GST_WARNING_OBJECT (data->self, + GST_WARNING_OBJECT (window, "Cannot get parent dxgi factory for swapchain %p, hr: 0x%x", - data->swap_chain, (guint) hr); + swap_chain, (guint) hr); return; } hr = IDXGIFactory1_MakeWindowAssociation (factory, - data->hwnd, DXGI_MWA_NO_ALT_ENTER); + hwnd, DXGI_MWA_NO_ALT_ENTER); if (!gst_d3d11_result (hr)) { - GST_WARNING_OBJECT (data->self, + GST_WARNING_OBJECT (window, "MakeWindowAssociation failure, hr: 0x%x", (guint) hr); } @@ -1003,7 +971,6 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, { DXGI_SWAP_CHAIN_DESC desc = { 0, }; GstCaps *render_caps; - MakeWindowAssociationData mwa_data = { 0, }; UINT swapchain_flags = 0; DXGI_SWAP_EFFECT swap_effect = DXGI_SWAP_EFFECT_DISCARD; #if (DXGI_HEADER_VERSION >= 5) @@ -1112,8 +1079,9 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, #endif if (window->swap_chain) { - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_release_resources, window); + gst_d3d11_device_lock (window->device); + gst_d3d11_window_release_resources (window->device, window); + gst_d3d11_device_unlock (window->device); } window->aspect_ratio_n = aspect_ratio_n; @@ -1205,11 +1173,10 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, } /* disable alt+enter here. It should be manually handled */ - mwa_data.self = window; - mwa_data.swap_chain = window->swap_chain; - mwa_data.hwnd = desc.OutputWindow; - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_disable_alt_enter, &mwa_data); + gst_d3d11_device_lock (window->device); + gst_d3d11_window_disable_alt_enter (window, + window->swap_chain, desc.OutputWindow); + gst_d3d11_device_unlock (window->device); #if (DXGI_HEADER_VERSION >= 5) if (swapchain4_available) { @@ -1252,12 +1219,10 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, } #endif - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_on_resize, window); + gst_d3d11_window_on_resize (window, FALSE); if (!window->rtv) { - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_release_resources, window); + gst_d3d11_window_release_resources (window->device, window); GST_ERROR_OBJECT (window, "Failed to setup internal resources"); g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED, "Failed to setup internal resources"); @@ -1337,28 +1302,15 @@ gst_d3d11_window_set_render_rectangle (GstD3D11Window * window, gint x, gint y, /* TODO: resize window and view */ } -void -gst_d3d11_window_get_surface_dimensions (GstD3D11Window * window, - guint * width, guint * height) +static GstFlowReturn +gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) { - g_return_if_fail (GST_IS_D3D11_WINDOW (window)); - - if (width) - *width = window->surface_width; - if (height) - *height = window->surface_height; -} - -static void -_present_on_device_thread (GstD3D11Device * device, FramePresentData * data) -{ - GstD3D11Window *self = data->window; - ID3D11DeviceContext *device_context; HRESULT hr; - UINT present_flags = DXGI_PRESENT_DO_NOT_WAIT; + UINT present_flags = 0; - device_context = gst_d3d11_device_get_device_context_handle (device); - gst_buffer_replace (&self->cached_buffer, data->buffer); + if (buffer) { + gst_buffer_replace (&self->cached_buffer, buffer); + } if (self->cached_buffer) { ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES]; @@ -1381,29 +1333,30 @@ _present_on_device_thread (GstD3D11Device * device, FramePresentData * data) gst_d3d11_color_converter_update_rect (self->converter, &rect); gst_d3d11_color_converter_convert (self->converter, srv, &self->rtv); - } + #if (DXGI_HEADER_VERSION >= 5) - if (self->allow_tearing) { - present_flags |= DXGI_PRESENT_ALLOW_TEARING; - } + if (self->allow_tearing) { + present_flags |= DXGI_PRESENT_ALLOW_TEARING; + } #endif - hr = IDXGISwapChain_Present (self->swap_chain, 0, present_flags); + hr = IDXGISwapChain_Present (self->swap_chain, 0, present_flags); - if (!gst_d3d11_result (hr)) { - GST_WARNING_OBJECT (self, "Direct3D cannot present texture, hr: 0x%x", - (guint) hr); + if (!gst_d3d11_result (hr)) { + GST_WARNING_OBJECT (self, "Direct3D cannot present texture, hr: 0x%x", + (guint) hr); + } } - data->ret = GST_FLOW_OK; + return GST_FLOW_OK; } GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer, GstVideoRectangle * rect) { - FramePresentData data; GstMemory *mem; + GstFlowReturn ret; g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR); g_return_val_if_fail (rect != NULL, GST_FLOW_ERROR); @@ -1428,28 +1381,15 @@ gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer, GST_OBJECT_LOCK (window); if (window->pending_resize) { - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_on_resize, window); - window->pending_resize = FALSE; + gst_d3d11_window_on_resize (window, FALSE); } GST_OBJECT_UNLOCK (window); - data.window = window; - data.rect = rect; - data.buffer = buffer; - data.ret = GST_FLOW_OK; - - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) _present_on_device_thread, &data); + gst_d3d11_device_lock (window->device); + ret = gst_d3d111_window_present (window, buffer); + gst_d3d11_device_unlock (window->device); - return data.ret; -} - -static void -gst_d3d11_window_flush_internal (GstD3D11Device * device, - GstD3D11Window * window) -{ - gst_clear_buffer (&window->cached_buffer); + return ret; } gboolean @@ -1457,8 +1397,7 @@ gst_d3d11_window_flush (GstD3D11Window * window) { g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), FALSE); - gst_d3d11_device_thread_add (window->device, - (GstD3D11DeviceThreadFunc) gst_d3d11_window_flush_internal, window); + gst_clear_buffer (&window->cached_buffer); return TRUE; } diff --git a/sys/d3d11/gstd3d11window.h b/sys/d3d11/gstd3d11window.h index 6c103d8..bcde80d 100644 --- a/sys/d3d11/gstd3d11window.h +++ b/sys/d3d11/gstd3d11window.h @@ -128,10 +128,6 @@ void gst_d3d11_window_set_render_rectangle (GstD3D11Window * window gint x, gint y, gint width, gint height); -void gst_d3d11_window_get_surface_dimensions (GstD3D11Window * window, - guint * width, - guint * height); - gboolean gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, -- 2.7.4