mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
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.
This commit is contained in:
parent
a0a85cd80c
commit
0788492461
12 changed files with 409 additions and 965 deletions
|
@ -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;
|
||||
|
||||
|
@ -215,17 +215,6 @@ clear_shader_resource (GstD3D11Device * device, GstD3D11ColorConvert * self)
|
|||
self->converter = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -781,32 +770,25 @@ format_unknown:
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
static GstFlowReturn
|
||||
gst_d3d11_color_convert_transform (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf)
|
||||
{
|
||||
GstD3D11ColorConvert *self;
|
||||
GstBuffer *in_buf;
|
||||
GstBuffer *out_buf;
|
||||
|
||||
gboolean ret;
|
||||
} DoConvertData;
|
||||
|
||||
static void
|
||||
do_convert (GstD3D11Device * device, DoConvertData * data)
|
||||
{
|
||||
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");
|
||||
|
||||
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);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
priv = device->priv;
|
||||
|
||||
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;
|
||||
|
||||
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,68 +600,65 @@ 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;
|
||||
if (!gst_d3d11_result (hr)) {
|
||||
GST_ERROR_OBJECT (device, "Cannot create SwapChain Object: 0x%x",
|
||||
(guint) hr);
|
||||
swap_chain = NULL;
|
||||
}
|
||||
|
||||
return swap_chain;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gst_d3d11_device_release_swap_chain_internal (GstD3D11Device * device,
|
||||
IDXGISwapChain * swap_chain)
|
||||
{
|
||||
IDXGISwapChain_Release (swap_chain);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_d3d11_device_release_swap_chain:
|
||||
* @device: a #GstD3D11Device
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
GstD3D11DevicePrivate *priv;
|
||||
HRESULT hr;
|
||||
ID3D11Texture2D *texture;
|
||||
|
||||
hr = ID3D11Device_CreateTexture2D (priv->device, data->desc,
|
||||
data->inital_data, &data->texture);
|
||||
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (desc != NULL, NULL);
|
||||
|
||||
priv = device->priv;
|
||||
|
||||
hr = ID3D11Device_CreateTexture2D (priv->device, desc, inital_data, &texture);
|
||||
if (!gst_d3d11_result (hr)) {
|
||||
const D3D11_TEXTURE2D_DESC *desc = data->desc;
|
||||
|
||||
GST_ERROR ("Failed to create texture (0x%x)", (guint) hr);
|
||||
|
||||
GST_WARNING ("Direct3D11 Allocation params");
|
||||
|
@ -907,35 +672,10 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11Texture2D *
|
||||
gst_d3d11_device_create_texture (GstD3D11Device * device,
|
||||
const D3D11_TEXTURE2D_DESC * desc,
|
||||
const D3D11_SUBRESOURCE_DATA * inital_data)
|
||||
{
|
||||
CreateTextureData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (desc != NULL, NULL);
|
||||
|
||||
data.texture = NULL;
|
||||
data.desc = desc;
|
||||
data.inital_data = inital_data;
|
||||
|
||||
gst_d3d11_device_thread_add (device, (GstD3D11DeviceThreadFunc)
|
||||
gst_d3d11_device_create_texture_internal, &data);
|
||||
|
||||
return data.texture;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_d3d11_device_release_texture_internal (GstD3D11Device * device,
|
||||
ID3D11Texture2D * texture)
|
||||
{
|
||||
ID3D11Texture2D_Release (texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -945,6 +685,32 @@ gst_d3d11_device_release_texture (GstD3D11Device * device,
|
|||
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);
|
||||
ID3D11Texture2D_Release (texture);
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d11_device_lock (GstD3D11Device * device)
|
||||
{
|
||||
GstD3D11DevicePrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_D3D11_DEVICE (device));
|
||||
|
||||
priv = device->priv;
|
||||
|
||||
GST_TRACE_OBJECT (device, "device locking");
|
||||
g_rec_mutex_lock (&priv->extern_lock);
|
||||
GST_TRACE_OBJECT (device, "device locked");
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d11_device_unlock (GstD3D11Device * device)
|
||||
{
|
||||
GstD3D11DevicePrivate *priv;
|
||||
|
||||
g_return_if_fail (GST_IS_D3D11_DEVICE (device));
|
||||
|
||||
priv = device->priv;
|
||||
|
||||
g_rec_mutex_unlock (&priv->extern_lock);
|
||||
GST_TRACE_OBJECT (device, "device unlocked");
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
ID3D11DeviceContext *device_context =
|
||||
gst_d3d11_device_get_device_context_handle (dmem->device);
|
||||
|
||||
data.dst = (ID3D11Resource *) dmem->texture;
|
||||
data.src = (ID3D11Resource *) dmem->staging;
|
||||
|
||||
gst_d3d11_device_thread_add (dmem->device,
|
||||
(GstD3D11DeviceThreadFunc) copy_texture, &data);
|
||||
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);
|
||||
map_type = gst_map_flags_to_d3d11 (flags);
|
||||
|
||||
gst_d3d11_device_thread_add (dmem->device, (GstD3D11DeviceThreadFunc)
|
||||
map_cpu_access_data, &map_data);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -387,38 +363,29 @@ gst_d3d11_allocator_dummy_alloc (GstAllocator * allocator, gsize size,
|
|||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
release_texture (GstD3D11Device * device, 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 (mem->shader_resource_view[i])
|
||||
ID3D11ShaderResourceView_Release (mem->shader_resource_view[i]);
|
||||
mem->shader_resource_view[i] = NULL;
|
||||
}
|
||||
|
||||
if (mem->texture)
|
||||
ID3D11Texture2D_Release (mem->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;
|
||||
gint i;
|
||||
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) release_texture, dmem);
|
||||
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
|
||||
if (dmem->render_target_view[i])
|
||||
ID3D11RenderTargetView_Release (dmem->render_target_view[i]);
|
||||
dmem->render_target_view[i] = NULL;
|
||||
|
||||
gst_object_unref (device);
|
||||
if (dmem->shader_resource_view[i])
|
||||
ID3D11ShaderResourceView_Release (dmem->shader_resource_view[i]);
|
||||
dmem->shader_resource_view[i] = NULL;
|
||||
}
|
||||
|
||||
if (dmem->texture)
|
||||
ID3D11Texture2D_Release (dmem->texture);
|
||||
|
||||
if (dmem->staging)
|
||||
ID3D11Texture2D_Release (dmem->staging);
|
||||
|
||||
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, data->texture, 0);
|
||||
ID3D11DeviceContext_Unmap (device_context, (ID3D11Resource *) texture, 0);
|
||||
gst_d3d11_device_unlock (device);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
gst_d3d11_device_unlock (device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_d3d11_create_pixel_shader (GstD3D11Device * device,
|
||||
const gchar * source, ID3D11PixelShader ** shader)
|
||||
{
|
||||
CreatePSData 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 (shader != NULL, FALSE);
|
||||
|
||||
data.source = source;
|
||||
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) create_pixel_shader, &data);
|
||||
|
||||
*shader = data.shader;
|
||||
return data.ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
}
|
||||
*shader = vshader;
|
||||
*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, };
|
||||
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);
|
||||
done:
|
||||
gst_d3d11_device_unlock (device);
|
||||
|
||||
data.source = source;
|
||||
data.input_desc = input_desc;
|
||||
data.desc_len = desc_len;
|
||||
|
||||
gst_d3d11_device_thread_add (device,
|
||||
(GstD3D11DeviceThreadFunc) create_vertex_shader, &data);
|
||||
|
||||
*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);
|
||||
}
|
||||
|
||||
void
|
||||
gst_d3d11_quad_free (GstD3D11Quad * quad)
|
||||
{
|
||||
g_return_if_fail (quad != NULL);
|
||||
|
||||
if (quad->device) {
|
||||
gst_d3d11_device_thread_add (quad->device,
|
||||
(GstD3D11DeviceThreadFunc) quad_free, quad);
|
||||
|
||||
gst_object_unref (quad->device);
|
||||
}
|
||||
|
||||
gst_clear_object (&quad->device);
|
||||
g_free (quad);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
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)
|
||||
{
|
||||
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)
|
||||
g_return_val_if_fail (quad != NULL, FALSE);
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
0, num_srv, clear_view);
|
||||
ID3D11DeviceContext_OMSetRenderTargets (context_handle, 0, NULL, NULL);
|
||||
|
||||
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);
|
||||
|
||||
return data.ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
if (dmem->desc.Usage == D3D11_USAGE_DYNAMIC) {
|
||||
return upload_transform_dynamic (filter, device, inbuf, outbuf);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return data.ret;
|
||||
return upload_transform (filter, inbuf, outbuf);
|
||||
}
|
||||
|
|
|
@ -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_lock (window->device);
|
||||
ret = gst_d3d111_window_present (window, buffer);
|
||||
gst_d3d11_device_unlock (window->device);
|
||||
|
||||
gst_d3d11_device_thread_add (window->device,
|
||||
(GstD3D11DeviceThreadFunc) _present_on_device_thread, &data);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue