d3d11videosink: Use single GstD3D11Converter object

GstD3D11Converter supports videoprocessor and texture upload.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2697>
This commit is contained in:
Seungha Yang 2022-07-01 23:49:49 +09:00
parent 46a3394581
commit 5eeec16502
4 changed files with 306 additions and 925 deletions

View file

@ -125,10 +125,6 @@ struct _GstD3D11VideoSink
GstVideoRectangle render_rect; GstVideoRectangle render_rect;
gboolean pending_render_rect; gboolean pending_render_rect;
GstBufferPool *fallback_pool;
gboolean have_video_processor;
gboolean processor_in_use;
/* For drawing on user texture */ /* For drawing on user texture */
gboolean drawing; gboolean drawing;
GstBuffer *current_buffer; GstBuffer *current_buffer;
@ -596,10 +592,8 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
} }
self->have_video_processor = FALSE;
if (!gst_d3d11_window_prepare (self->window, GST_VIDEO_SINK_WIDTH (self), if (!gst_d3d11_window_prepare (self->window, GST_VIDEO_SINK_WIDTH (self),
GST_VIDEO_SINK_HEIGHT (self), caps, &self->have_video_processor, GST_VIDEO_SINK_HEIGHT (self), caps, &error)) {
&error)) {
GstMessage *error_msg; GstMessage *error_msg;
GST_ERROR_OBJECT (self, "cannot create swapchain"); GST_ERROR_OBJECT (self, "cannot create swapchain");
@ -611,44 +605,6 @@ gst_d3d11_video_sink_update_window (GstD3D11VideoSink * self, GstCaps * caps)
return FALSE; return FALSE;
} }
if (self->fallback_pool) {
gst_buffer_pool_set_active (self->fallback_pool, FALSE);
gst_clear_object (&self->fallback_pool);
}
{
GstD3D11AllocationParams *d3d11_params;
gint bind_flags = D3D11_BIND_SHADER_RESOURCE;
if (self->have_video_processor) {
/* To create video processor input view, one of following bind flags
* is required
* NOTE: Any texture arrays which were created with D3D11_BIND_DECODER flag
* cannot be used for shader input.
*
* D3D11_BIND_DECODER
* D3D11_BIND_VIDEO_ENCODER
* D3D11_BIND_RENDER_TARGET
* D3D11_BIND_UNORDERED_ACCESS_VIEW
*/
bind_flags |= D3D11_BIND_RENDER_TARGET;
}
d3d11_params = gst_d3d11_allocation_params_new (self->device,
&self->info, GST_D3D11_ALLOCATION_FLAG_DEFAULT, bind_flags, 0);
self->fallback_pool = gst_d3d11_buffer_pool_new_with_options (self->device,
caps, d3d11_params, 2, 0);
gst_d3d11_allocation_params_free (d3d11_params);
}
if (!self->fallback_pool) {
GST_ERROR_OBJECT (self, "Failed to configure fallback pool");
return FALSE;
}
self->processor_in_use = FALSE;
if (self->title) { if (self->title) {
gst_d3d11_window_set_title (self->window, self->title); gst_d3d11_window_set_title (self->window, self->title);
g_clear_pointer (&self->title, g_free); g_clear_pointer (&self->title, g_free);
@ -838,12 +794,6 @@ gst_d3d11_video_sink_stop (GstBaseSink * sink)
GST_DEBUG_OBJECT (self, "Stop"); GST_DEBUG_OBJECT (self, "Stop");
if (self->fallback_pool) {
gst_buffer_pool_set_active (self->fallback_pool, FALSE);
gst_object_unref (self->fallback_pool);
self->fallback_pool = NULL;
}
if (self->window) if (self->window)
gst_d3d11_window_unprepare (self->window); gst_d3d11_window_unprepare (self->window);
@ -1050,108 +1000,6 @@ gst_d3d11_video_sink_event (GstBaseSink * sink, GstEvent * event)
return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
} }
static gboolean
gst_d3d11_video_sink_upload_frame (GstD3D11VideoSink * self, GstBuffer * inbuf,
GstBuffer * outbuf)
{
GstVideoFrame in_frame, out_frame;
gboolean ret;
GST_LOG_OBJECT (self, "Copy to fallback buffer");
if (!gst_video_frame_map (&in_frame, &self->info, inbuf,
(GstMapFlags) (GST_MAP_READ | GST_VIDEO_FRAME_MAP_FLAG_NO_REF)))
goto invalid_buffer;
if (!gst_video_frame_map (&out_frame, &self->info, outbuf,
(GstMapFlags) (GST_MAP_WRITE | GST_VIDEO_FRAME_MAP_FLAG_NO_REF))) {
gst_video_frame_unmap (&in_frame);
goto invalid_buffer;
}
ret = gst_video_frame_copy (&out_frame, &in_frame);
gst_video_frame_unmap (&in_frame);
gst_video_frame_unmap (&out_frame);
return ret;
/* ERRORS */
invalid_buffer:
{
GST_ELEMENT_WARNING (self, CORE, NOT_IMPLEMENTED, (NULL),
("invalid video buffer received"));
return FALSE;
}
}
static gboolean
gst_d3d11_video_sink_copy_d3d11_to_d3d11 (GstD3D11VideoSink * self,
GstBuffer * inbuf, GstBuffer * outbuf)
{
GST_LOG_OBJECT (self, "Copy to fallback buffer using device memory copy");
return gst_d3d11_buffer_copy_into (outbuf, inbuf, &self->info);
}
static gboolean
gst_d3d11_video_sink_get_fallback_buffer (GstD3D11VideoSink * self,
GstBuffer * inbuf, GstBuffer ** fallback_buf, gboolean device_copy)
{
GstBuffer *outbuf = NULL;
ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES];
GstVideoOverlayCompositionMeta *compo_meta;
GstVideoCropMeta *crop_meta;
if (!self->fallback_pool ||
!gst_buffer_pool_set_active (self->fallback_pool, TRUE) ||
gst_buffer_pool_acquire_buffer (self->fallback_pool, &outbuf,
NULL) != GST_FLOW_OK) {
GST_ERROR_OBJECT (self, "fallback pool is unavailable");
return FALSE;
}
/* Ensure SRV */
if (!gst_d3d11_buffer_get_shader_resource_view (outbuf, view)) {
GST_ERROR_OBJECT (self, "fallback SRV is unavailable");
goto error;
}
if (device_copy) {
if (!gst_d3d11_video_sink_copy_d3d11_to_d3d11 (self, inbuf, outbuf)) {
GST_ERROR_OBJECT (self, "cannot copy frame");
goto error;
}
} else if (!gst_d3d11_video_sink_upload_frame (self, inbuf, outbuf)) {
GST_ERROR_OBJECT (self, "cannot upload frame");
goto error;
}
/* Copy overlaycomposition meta if any */
compo_meta = gst_buffer_get_video_overlay_composition_meta (inbuf);
if (compo_meta)
gst_buffer_add_video_overlay_composition_meta (outbuf, compo_meta->overlay);
/* And copy crop meta as well */
crop_meta = gst_buffer_get_video_crop_meta (inbuf);
if (crop_meta) {
GstVideoCropMeta *new_crop_meta = gst_buffer_add_video_crop_meta (outbuf);
new_crop_meta->x = crop_meta->x;
new_crop_meta->y = crop_meta->y;
new_crop_meta->width = crop_meta->width;
new_crop_meta->height = crop_meta->height;
}
*fallback_buf = outbuf;
return TRUE;
error:
gst_buffer_unref (outbuf);
return FALSE;
}
static void static void
gst_d3d11_video_sink_check_device_update (GstD3D11VideoSink * self, gst_d3d11_video_sink_check_device_update (GstD3D11VideoSink * self,
GstBuffer * buf) GstBuffer * buf)
@ -1199,10 +1047,6 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
{ {
GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink); GstD3D11VideoSink *self = GST_D3D11_VIDEO_SINK (sink);
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *fallback_buf = NULL;
ID3D11Device *device_handle =
gst_d3d11_device_get_device_handle (self->device);
ID3D11ShaderResourceView *view[GST_VIDEO_MAX_PLANES];
gst_d3d11_video_sink_check_device_update (self, buf); gst_d3d11_video_sink_check_device_update (self, buf);
@ -1221,54 +1065,11 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
} }
if (!gst_d3d11_buffer_can_access_device (buf, device_handle)) {
GST_LOG_OBJECT (self, "Need fallback buffer");
if (!gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf,
FALSE)) {
return GST_FLOW_ERROR;
}
} else {
gboolean direct_rendering = FALSE;
/* Check if we can use video processor for conversion */
if (gst_buffer_n_memory (buf) == 1 && self->have_video_processor) {
GstD3D11Memory *mem = (GstD3D11Memory *) gst_buffer_peek_memory (buf, 0);
D3D11_TEXTURE2D_DESC desc;
gst_d3d11_memory_get_texture_desc (mem, &desc);
if ((desc.BindFlags & D3D11_BIND_DECODER) == D3D11_BIND_DECODER) {
GST_TRACE_OBJECT (self,
"Got VideoProcessor compatible texture, do direct rendering");
direct_rendering = TRUE;
self->processor_in_use = TRUE;
} else if (self->processor_in_use &&
(desc.BindFlags & D3D11_BIND_RENDER_TARGET) ==
D3D11_BIND_RENDER_TARGET) {
direct_rendering = TRUE;
}
}
/* Or, SRV should be available */
if (!direct_rendering) {
if (gst_d3d11_buffer_get_shader_resource_view (buf, view)) {
GST_TRACE_OBJECT (self, "SRV is available, do direct rendering");
direct_rendering = TRUE;
}
}
if (!direct_rendering &&
!gst_d3d11_video_sink_get_fallback_buffer (self, buf, &fallback_buf,
TRUE)) {
return GST_FLOW_ERROR;
}
}
gst_d3d11_window_show (self->window); gst_d3d11_window_show (self->window);
if (self->draw_on_shared_texture) { if (self->draw_on_shared_texture) {
g_rec_mutex_lock (&self->draw_lock); g_rec_mutex_lock (&self->draw_lock);
self->current_buffer = fallback_buf ? fallback_buf : buf; self->current_buffer = buf;
self->drawing = TRUE; self->drawing = TRUE;
GST_LOG_OBJECT (self, "Begin drawing"); GST_LOG_OBJECT (self, "Begin drawing");
@ -1279,15 +1080,12 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf)
GST_LOG_OBJECT (self, "End drawing"); GST_LOG_OBJECT (self, "End drawing");
self->drawing = FALSE; self->drawing = FALSE;
self->current_buffer = NULL; self->current_buffer = nullptr;
g_rec_mutex_unlock (&self->draw_lock); g_rec_mutex_unlock (&self->draw_lock);
} else { } else {
ret = gst_d3d11_window_render (self->window, ret = gst_d3d11_window_render (self->window, buf);
fallback_buf ? fallback_buf : buf);
} }
gst_clear_buffer (&fallback_buf);
if (ret == GST_D3D11_WINDOW_FLOW_CLOSED) { if (ret == GST_D3D11_WINDOW_FLOW_CLOSED) {
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
("Output window was closed"), (NULL)); ("Output window was closed"), (NULL));

View file

@ -103,13 +103,11 @@ static void gst_d3d11_window_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_d3d11_window_dispose (GObject * object); static void gst_d3d11_window_dispose (GObject * object);
static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self, static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self,
GstBuffer * buffer, ID3D11VideoProcessorOutputView * pov, GstBuffer * buffer, GstBuffer * render_target);
ID3D11RenderTargetView * rtv);
static void gst_d3d11_window_on_resize_default (GstD3D11Window * window, static void gst_d3d11_window_on_resize_default (GstD3D11Window * window,
guint width, guint height); guint width, guint height);
static gboolean gst_d3d11_window_prepare_default (GstD3D11Window * window, static gboolean gst_d3d11_window_prepare_default (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, guint display_width, guint display_height, GstCaps * caps, GError ** error);
gboolean * video_processor_available, GError ** error);
static void static void
gst_d3d11_window_class_init (GstD3D11WindowClass * klass) gst_d3d11_window_class_init (GstD3D11WindowClass * klass)
@ -251,132 +249,116 @@ gst_d3d11_window_get_property (GObject * object, guint prop_id,
} }
} }
static void
gst_d3d11_window_release_resources (GstD3D11Device * device,
GstD3D11Window * window)
{
GST_D3D11_CLEAR_COM (window->rtv);
GST_D3D11_CLEAR_COM (window->pov);
GST_D3D11_CLEAR_COM (window->swap_chain);
}
static void static void
gst_d3d11_window_dispose (GObject * object) gst_d3d11_window_dispose (GObject * object)
{ {
GstD3D11Window *self = GST_D3D11_WINDOW (object); GstD3D11Window *self = GST_D3D11_WINDOW (object);
if (self->device) gst_clear_buffer (&self->backbuffer);
gst_d3d11_window_release_resources (self->device, self); GST_D3D11_CLEAR_COM (self->swap_chain);
g_clear_pointer (&self->processor, gst_d3d11_video_processor_free);
gst_clear_object (&self->compositor); gst_clear_object (&self->compositor);
gst_clear_object (&self->converter); gst_clear_object (&self->converter);
gst_clear_buffer (&self->cached_buffer); gst_clear_buffer (&self->cached_buffer);
gst_clear_object (&self->device); gst_clear_object (&self->device);
gst_clear_object (&self->allocator);
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
static void static void
gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width, gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
guint height) guint height)
{ {
GstD3D11Device *device = self->device;
HRESULT hr; HRESULT hr;
ID3D11Device *device_handle;
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
DXGI_SWAP_CHAIN_DESC swap_desc; DXGI_SWAP_CHAIN_DESC swap_desc;
ID3D11Texture2D *backbuffer = NULL; ComPtr < ID3D11Texture2D > backbuffer;
GstVideoRectangle src_rect, dst_rect, rst_rect; GstVideoRectangle src_rect, dst_rect, rst_rect;
IDXGISwapChain *swap_chain; IDXGISwapChain *swap_chain;
GstMemory *mem;
GstD3D11Memory *dmem;
ID3D11RenderTargetView *rtv;
gst_d3d11_device_lock (window->device); gst_d3d11_device_lock (device);
if (!window->swap_chain)
gst_clear_buffer (&self->backbuffer);
if (!self->swap_chain)
goto done; goto done;
device_handle = gst_d3d11_device_get_device_handle (window->device); swap_chain = self->swap_chain;
swap_chain = window->swap_chain;
GST_D3D11_CLEAR_COM (window->rtv);
GST_D3D11_CLEAR_COM (window->pov);
swap_chain->GetDesc (&swap_desc); swap_chain->GetDesc (&swap_desc);
hr = swap_chain->ResizeBuffers (0, width, height, window->dxgi_format, hr = swap_chain->ResizeBuffers (0, width, height, self->dxgi_format,
swap_desc.Flags); swap_desc.Flags);
if (!gst_d3d11_result (hr, window->device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR_OBJECT (window, "Couldn't resize buffers, hr: 0x%x", (guint) hr); GST_ERROR_OBJECT (self, "Couldn't resize buffers, hr: 0x%x", (guint) hr);
goto done; goto done;
} }
hr = swap_chain->GetBuffer (0, IID_PPV_ARGS (&backbuffer)); hr = swap_chain->GetBuffer (0, IID_PPV_ARGS (&backbuffer));
if (!gst_d3d11_result (hr, window->device)) { if (!gst_d3d11_result (hr, device)) {
GST_ERROR_OBJECT (window, GST_ERROR_OBJECT (self,
"Cannot get backbuffer from swapchain, hr: 0x%x", (guint) hr); "Cannot get backbuffer from swapchain, hr: 0x%x", (guint) hr);
goto done; goto done;
} }
backbuffer->GetDesc (&desc); mem = gst_d3d11_allocator_alloc_wrapped_native_size (self->allocator,
window->surface_width = desc.Width; self->device, backbuffer.Get (), nullptr, nullptr);
window->surface_height = desc.Height; if (!mem) {
GST_ERROR_OBJECT (self, "Couldn't allocate wrapped memory");
{
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.w = window->surface_width;
dst_rect.h = window->surface_height;
if (window->force_aspect_ratio) {
src_rect.x = 0;
src_rect.y = 0;
src_rect.w = GST_VIDEO_INFO_WIDTH (&window->render_info);
src_rect.h = GST_VIDEO_INFO_HEIGHT (&window->render_info);
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
} else {
rst_rect = dst_rect;
}
}
window->render_rect.left = rst_rect.x;
window->render_rect.top = rst_rect.y;
window->render_rect.right = rst_rect.x + rst_rect.w;
window->render_rect.bottom = rst_rect.y + rst_rect.h;
GST_LOG_OBJECT (window,
"New client area %dx%d, render rect x: %d, y: %d, %dx%d",
desc.Width, desc.Height, rst_rect.x, rst_rect.y, rst_rect.w, rst_rect.h);
hr = device_handle->CreateRenderTargetView (backbuffer, NULL, &window->rtv);
if (!gst_d3d11_result (hr, window->device)) {
GST_ERROR_OBJECT (window, "Cannot create render target view, hr: 0x%x",
(guint) hr);
goto done; goto done;
} }
if (window->processor) { dmem = GST_D3D11_MEMORY_CAST (mem);
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc; rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
if (!rtv) {
pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; GST_ERROR_OBJECT (self, "RTV is unavailable");
pov_desc.Texture2D.MipSlice = 0; gst_memory_unref (mem);
goto done;
if (!gst_d3d11_video_processor_create_output_view (window->processor,
&pov_desc, backbuffer, &window->pov))
goto done;
} }
window->first_present = TRUE; self->backbuffer = gst_buffer_new ();
gst_buffer_append_memory (self->backbuffer, mem);
backbuffer->GetDesc (&desc);
self->surface_width = desc.Width;
self->surface_height = desc.Height;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.w = self->surface_width;
dst_rect.h = self->surface_height;
if (self->force_aspect_ratio) {
src_rect.x = 0;
src_rect.y = 0;
src_rect.w = GST_VIDEO_INFO_WIDTH (&self->render_info);
src_rect.h = GST_VIDEO_INFO_HEIGHT (&self->render_info);
gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE);
} else {
rst_rect = dst_rect;
}
self->render_rect.left = rst_rect.x;
self->render_rect.top = rst_rect.y;
self->render_rect.right = rst_rect.x + rst_rect.w;
self->render_rect.bottom = rst_rect.y + rst_rect.h;
GST_LOG_OBJECT (self,
"New client area %dx%d, render rect x: %d, y: %d, %dx%d",
desc.Width, desc.Height, rst_rect.x, rst_rect.y, rst_rect.w, rst_rect.h);
self->first_present = TRUE;
/* redraw the last scene if cached buffer exits */ /* redraw the last scene if cached buffer exits */
if (window->cached_buffer) { if (self->cached_buffer)
gst_d3d111_window_present (window, window->cached_buffer, gst_d3d111_window_present (self, self->cached_buffer, self->backbuffer);
window->pov, window->rtv);
}
done: done:
GST_D3D11_CLEAR_COM (backbuffer); gst_d3d11_device_unlock (device);
gst_d3d11_device_unlock (window->device);
} }
void void
@ -413,8 +395,7 @@ typedef struct
gboolean gboolean
gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width, gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
guint display_height, GstCaps * caps, gboolean * video_processor_available, guint display_height, GstCaps * caps, GError ** error)
GError ** error)
{ {
GstD3D11WindowClass *klass; GstD3D11WindowClass *klass;
@ -426,19 +407,17 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width,
GST_DEBUG_OBJECT (window, "Prepare window, display resolution %dx%d, caps %" GST_DEBUG_OBJECT (window, "Prepare window, display resolution %dx%d, caps %"
GST_PTR_FORMAT, display_width, display_height, caps); GST_PTR_FORMAT, display_width, display_height, caps);
return klass->prepare (window, display_width, display_height, caps, return klass->prepare (window, display_width, display_height, caps, error);
video_processor_available, error);
} }
static gboolean static gboolean
gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width, gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
guint display_height, GstCaps * caps, gboolean * video_processor_available, guint display_height, GstCaps * caps, GError ** error)
GError ** error)
{ {
GstD3D11Device *device = window->device;
GstD3D11WindowClass *klass; GstD3D11WindowClass *klass;
guint swapchain_flags = 0; guint swapchain_flags = 0;
ID3D11Device *device_handle; ID3D11Device *device_handle;
guint i;
guint num_supported_format = 0; guint num_supported_format = 0;
HRESULT hr; HRESULT hr;
UINT display_flags = UINT display_flags =
@ -452,28 +431,41 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
const GstD3D11WindowDisplayFormat *chosen_format = NULL; const GstD3D11WindowDisplayFormat *chosen_format = NULL;
GstDxgiColorSpace swapchain_colorspace; GstDxgiColorSpace swapchain_colorspace;
gboolean found_swapchain_colorspace = FALSE; gboolean found_swapchain_colorspace = FALSE;
gboolean have_hdr10 = FALSE; gboolean hdr10_aware = FALSE;
gboolean have_hdr10_meta = FALSE;
DXGI_COLOR_SPACE_TYPE native_colorspace_type = DXGI_COLOR_SPACE_TYPE native_colorspace_type =
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
DXGI_HDR_METADATA_HDR10 hdr10_metadata = { 0, }; ComPtr < IDXGIFactory5 > factory5;
GstDxgiColorSpace in_dxgi_colorspace; IDXGIFactory1 *factory_handle;
GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER; BOOL allow_tearing = FALSE;
GstVideoMasteringDisplayInfo mdcv;
GstVideoContentLightLevel cll;
ComPtr < IDXGISwapChain3 > swapchain3;
GstStructure *s;
const gchar *cll_str = nullptr;
const gchar *mdcv_str = nullptr;
if (!window->allocator) {
window->allocator =
(GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
if (!window->allocator) {
GST_ERROR_OBJECT (window, "Allocator is unavailable");
return FALSE;
}
}
/* Step 1: Clear old resources and objects */ /* Step 1: Clear old resources and objects */
gst_clear_buffer (&window->cached_buffer); gst_clear_buffer (&window->cached_buffer);
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free);
gst_clear_object (&window->compositor); gst_clear_object (&window->compositor);
gst_clear_object (&window->converter); gst_clear_object (&window->converter);
window->processor_in_use = FALSE;
/* Step 2: Decide display color format /* Step 2: Decide display color format
* If upstream format is 10bits, try DXGI_FORMAT_R10G10B10A2_UNORM first * If upstream format is 10bits, try DXGI_FORMAT_R10G10B10A2_UNORM first
* Otherwise, use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM * Otherwise, use DXGI_FORMAT_B8G8R8A8_UNORM or DXGI_FORMAT_B8G8R8A8_UNORM
*/ */
gst_video_info_from_caps (&window->info, caps); gst_video_info_from_caps (&window->info, caps);
device_handle = gst_d3d11_device_get_device_handle (window->device); device_handle = gst_d3d11_device_get_device_handle (device);
for (i = 0; i < G_N_ELEMENTS (formats); i++) { for (guint i = 0; i < G_N_ELEMENTS (formats); i++) {
hr = device_handle->CheckFormatSupport (formats[i].dxgi_format, hr = device_handle->CheckFormatSupport (formats[i].dxgi_format,
&supported_flags); &supported_flags);
if (SUCCEEDED (hr) && (supported_flags & display_flags) == display_flags) { if (SUCCEEDED (hr) && (supported_flags & display_flags) == display_flags) {
@ -492,7 +484,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
return FALSE; return FALSE;
} }
for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) { for (guint i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) {
if (GST_VIDEO_INFO_COMP_DEPTH (&window->info, i) > 8) { if (GST_VIDEO_INFO_COMP_DEPTH (&window->info, i) > 8) {
if (formats[2].supported) { if (formats[2].supported) {
chosen_format = &formats[2]; chosen_format = &formats[2];
@ -503,7 +495,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
if (!chosen_format) { if (!chosen_format) {
/* prefer native format over conversion */ /* prefer native format over conversion */
for (i = 0; i < 2; i++) { for (guint i = 0; i < 2; i++) {
if (formats[i].supported && if (formats[i].supported &&
formats[i].gst_format == GST_VIDEO_INFO_FORMAT (&window->info)) { formats[i].gst_format == GST_VIDEO_INFO_FORMAT (&window->info)) {
chosen_format = &formats[i]; chosen_format = &formats[i];
@ -513,7 +505,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
/* choose any color space then */ /* choose any color space then */
if (!chosen_format) { if (!chosen_format) {
for (i = 0; i < G_N_ELEMENTS (formats); i++) { for (guint i = 0; i < G_N_ELEMENTS (formats); i++) {
if (formats[i].supported) { if (formats[i].supported) {
chosen_format = &formats[i]; chosen_format = &formats[i];
break; break;
@ -522,7 +514,7 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
} }
} }
g_assert (chosen_format != NULL); g_assert (chosen_format != nullptr);
GST_DEBUG_OBJECT (window, "chosen render format %s (DXGI_FORMAT %d)", GST_DEBUG_OBJECT (window, "chosen render format %s (DXGI_FORMAT %d)",
gst_video_format_to_string (chosen_format->gst_format), gst_video_format_to_string (chosen_format->gst_format),
@ -532,28 +524,17 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
* (or reuse old swapchain if the format is not changed) */ * (or reuse old swapchain if the format is not changed) */
window->allow_tearing = FALSE; window->allow_tearing = FALSE;
{ factory_handle = gst_d3d11_device_get_dxgi_factory_handle (device);
ComPtr < IDXGIFactory5 > factory5; hr = factory_handle->QueryInterface (IID_PPV_ARGS (&factory5));
IDXGIFactory1 *factory_handle; if (SUCCEEDED (hr)) {
BOOL allow_tearing = FALSE; hr = factory5->CheckFeatureSupport (DXGI_FEATURE_PRESENT_ALLOW_TEARING,
(void *) &allow_tearing, sizeof (allow_tearing));
factory_handle = gst_d3d11_device_get_dxgi_factory_handle (window->device);
hr = factory_handle->QueryInterface (IID_PPV_ARGS (&factory5));
if (SUCCEEDED (hr)) {
hr = factory5->CheckFeatureSupport (DXGI_FEATURE_PRESENT_ALLOW_TEARING,
(void *) &allow_tearing, sizeof (allow_tearing));
}
if (SUCCEEDED (hr) && allow_tearing)
window->allow_tearing = allow_tearing;
} }
if (window->allow_tearing) { if (SUCCEEDED (hr) && allow_tearing)
GST_DEBUG_OBJECT (window, "device supports tearing"); window->allow_tearing = allow_tearing;
swapchain_flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
}
gst_d3d11_device_lock (window->device); gst_d3d11_device_lock (device);
window->dxgi_format = chosen_format->dxgi_format; window->dxgi_format = chosen_format->dxgi_format;
klass = GST_D3D11_WINDOW_GET_CLASS (window); klass = GST_D3D11_WINDOW_GET_CLASS (window);
@ -580,35 +561,6 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
window->prev_input_rect = window->input_rect; window->prev_input_rect = window->input_rect;
/* Step 4: Decide render color space and set it on converter/processor */
{
GstVideoMasteringDisplayInfo minfo;
GstVideoContentLightLevel cll;
if (gst_video_mastering_display_info_from_caps (&minfo, caps) &&
gst_video_content_light_level_from_caps (&cll, caps)) {
ComPtr < IDXGISwapChain4 > swapchain4;
HRESULT hr;
hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain4));
if (gst_d3d11_result (hr, window->device)) {
GST_DEBUG_OBJECT (window, "Have HDR metadata, set to DXGI swapchain");
gst_d3d11_hdr_meta_data_to_dxgi (&minfo, &cll, &hdr10_metadata);
hr = swapchain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10,
sizeof (DXGI_HDR_METADATA_HDR10), &hdr10_metadata);
if (!gst_d3d11_result (hr, window->device)) {
GST_WARNING_OBJECT (window, "Couldn't set HDR metadata, hr 0x%x",
(guint) hr);
} else {
have_hdr10 = TRUE;
}
}
}
}
/* Step 5: Choose display color space */
gst_video_info_set_format (&window->render_info, gst_video_info_set_format (&window->render_info,
chosen_format->gst_format, display_width, display_height); chosen_format->gst_format, display_width, display_height);
@ -621,36 +573,63 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
* target display color space type */ * target display color space type */
window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
{ s = gst_caps_get_structure (caps, 0);
ComPtr < IDXGISwapChain3 > swapchain3; mdcv_str = gst_structure_get_string (s, "mastering-display-info");
HRESULT hr; cll_str = gst_structure_get_string (s, "content-light-level");
if (mdcv_str && cll_str &&
gst_video_mastering_display_info_from_string (&mdcv, mdcv_str) &&
gst_video_content_light_level_from_string (&cll, cll_str)) {
have_hdr10_meta = TRUE;
}
hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain3)); hr = window->swap_chain->QueryInterface (IID_PPV_ARGS (&swapchain3));
if (gst_d3d11_result (hr, device)) {
found_swapchain_colorspace =
gst_d3d11_find_swap_chain_color_space (&window->render_info,
swapchain3.Get (), &swapchain_colorspace);
if (found_swapchain_colorspace) {
native_colorspace_type =
(DXGI_COLOR_SPACE_TYPE) swapchain_colorspace.dxgi_color_space_type;
hr = swapchain3->SetColorSpace1 (native_colorspace_type);
if (!gst_d3d11_result (hr, window->device)) {
GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x",
native_colorspace_type, (guint) hr);
found_swapchain_colorspace = FALSE;
native_colorspace_type = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
} else {
ComPtr < IDXGISwapChain4 > swapchain4;
if (gst_d3d11_result (hr, window->device)) { GST_DEBUG_OBJECT (window, "Set colorspace %d", native_colorspace_type);
found_swapchain_colorspace =
gst_d3d11_find_swap_chain_color_space (&window->render_info,
swapchain3.Get (), &swapchain_colorspace);
if (found_swapchain_colorspace) {
native_colorspace_type =
(DXGI_COLOR_SPACE_TYPE) swapchain_colorspace.dxgi_color_space_type;
hr = swapchain3->SetColorSpace1 (native_colorspace_type);
if (!gst_d3d11_result (hr, window->device)) {
GST_WARNING_OBJECT (window, "Failed to set colorspace %d, hr: 0x%x",
native_colorspace_type, (guint) hr);
found_swapchain_colorspace = FALSE;
native_colorspace_type = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
} else {
GST_DEBUG_OBJECT (window,
"Set colorspace %d", native_colorspace_type);
/* update with selected display color space */ /* update with selected display color space */
window->render_info.colorimetry.primaries = window->render_info.colorimetry.primaries =
swapchain_colorspace.primaries; swapchain_colorspace.primaries;
window->render_info.colorimetry.transfer = window->render_info.colorimetry.transfer =
swapchain_colorspace.transfer; swapchain_colorspace.transfer;
window->render_info.colorimetry.range = swapchain_colorspace.range; window->render_info.colorimetry.range = swapchain_colorspace.range;
window->render_info.colorimetry.matrix = swapchain_colorspace.matrix; window->render_info.colorimetry.matrix = swapchain_colorspace.matrix;
/* DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 = 12, undefined in old
* mingw header */
if (native_colorspace_type == 12 && have_hdr10_meta) {
hr = swapchain3.As (&swapchain4);
if (gst_d3d11_result (hr, device)) {
DXGI_HDR_METADATA_HDR10 hdr10_metadata = { 0, };
GST_DEBUG_OBJECT (window,
"Have HDR metadata, set to DXGI swapchain");
gst_d3d11_hdr_meta_data_to_dxgi (&mdcv, &cll, &hdr10_metadata);
hr = swapchain4->SetHDRMetaData (DXGI_HDR_METADATA_TYPE_HDR10,
sizeof (DXGI_HDR_METADATA_HDR10), &hdr10_metadata);
if (!gst_d3d11_result (hr, device)) {
GST_WARNING_OBJECT (window,
"Couldn't set HDR metadata, hr 0x%x", (guint) hr);
} else {
hdr10_aware = TRUE;
}
}
} }
} }
} }
@ -664,66 +643,10 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
window->render_info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709; window->render_info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
window->render_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB; window->render_info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
} else if (gst_d3d11_video_info_to_dxgi_color_space (&window->info,
&in_dxgi_colorspace)) {
GstD3D11Format in_format;
gboolean hardware = FALSE;
GstD3D11VideoProcessor *processor = NULL;
DXGI_FORMAT in_dxgi_format;
gst_d3d11_device_get_format (window->device,
GST_VIDEO_INFO_FORMAT (&window->info), &in_format);
in_dxgi_format = in_format.dxgi_format;
if (in_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
g_object_get (window->device, "hardware", &hardware, NULL);
}
if (hardware) {
processor =
gst_d3d11_video_processor_new (window->device,
GST_VIDEO_INFO_WIDTH (&window->info),
GST_VIDEO_INFO_HEIGHT (&window->info), display_width, display_height);
}
if (processor) {
DXGI_FORMAT out_dxgi_format = chosen_format->dxgi_format;
DXGI_COLOR_SPACE_TYPE in_dxgi_color_space =
(DXGI_COLOR_SPACE_TYPE) in_dxgi_colorspace.dxgi_color_space_type;
DXGI_COLOR_SPACE_TYPE out_dxgi_color_space = native_colorspace_type;
if (!gst_d3d11_video_processor_check_format_conversion (processor,
in_dxgi_format, in_dxgi_color_space, out_dxgi_format,
out_dxgi_color_space)) {
GST_DEBUG_OBJECT (window, "Conversion is not supported by device");
gst_d3d11_video_processor_free (processor);
processor = NULL;
} else {
GST_DEBUG_OBJECT (window, "video processor supports conversion");
gst_d3d11_video_processor_set_input_dxgi_color_space (processor,
in_dxgi_color_space);
gst_d3d11_video_processor_set_output_dxgi_color_space (processor,
out_dxgi_color_space);
if (have_hdr10) {
GST_DEBUG_OBJECT (window, "Set HDR metadata on video processor");
gst_d3d11_video_processor_set_input_hdr10_metadata (processor,
&hdr10_metadata);
gst_d3d11_video_processor_set_output_hdr10_metadata (processor,
&hdr10_metadata);
}
}
window->processor = processor;
}
} }
*video_processor_available = !!window->processor; window->converter = gst_d3d11_converter_new (device,
&window->info, &window->render_info, nullptr);
/* configure shader even if video processor is available for fallback */
window->converter =
gst_d3d11_converter_new (window->device, &window->info,
&window->render_info, &method);
if (!window->converter) { if (!window->converter) {
GST_ERROR_OBJECT (window, "Cannot create converter"); GST_ERROR_OBJECT (window, "Cannot create converter");
@ -732,6 +655,15 @@ gst_d3d11_window_prepare_default (GstD3D11Window * window, guint display_width,
goto error; goto error;
} }
if (have_hdr10_meta) {
g_object_set (window->converter, "src-mastering-display-info", mdcv_str,
"src-content-light-level", cll_str, nullptr);
if (hdr10_aware) {
g_object_set (window->converter, "dest-mastering-display-info", mdcv_str,
"dest-content-light-level", cll_str, nullptr);
}
}
window->compositor = window->compositor =
gst_d3d11_overlay_compositor_new (window->device, &window->render_info); gst_d3d11_overlay_compositor_new (window->device, &window->render_info);
if (!window->compositor) { if (!window->compositor) {
@ -799,225 +731,112 @@ gst_d3d11_window_set_title (GstD3D11Window * window, const gchar * title)
klass->set_title (window, title); klass->set_title (window, title);
} }
static gboolean
gst_d3d11_window_buffer_ensure_processor_input (GstD3D11Window * self,
GstBuffer * buffer, ID3D11VideoProcessorInputView ** in_view)
{
GstD3D11Memory *mem;
ID3D11VideoProcessorInputView *piv;
if (!self->processor)
return FALSE;
if (gst_buffer_n_memory (buffer) != 1)
return FALSE;
mem = (GstD3D11Memory *) gst_buffer_peek_memory (buffer, 0);
piv = gst_d3d11_video_processor_get_input_view (self->processor, mem);
if (!piv) {
GST_LOG_OBJECT (self, "Failed to get processor input view");
return FALSE;
}
*in_view = piv;
return TRUE;
}
static gboolean
gst_d3d11_window_do_processor (GstD3D11Window * self,
ID3D11VideoProcessorInputView * piv, ID3D11VideoProcessorOutputView * pov,
RECT * input_rect)
{
gboolean ret;
ret = gst_d3d11_video_processor_render_unlocked (self->processor,
input_rect, piv, &self->render_rect, pov);
if (!ret) {
GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using processor");
} else {
GST_TRACE_OBJECT (self, "Rendered using processor");
self->processor_in_use = TRUE;
}
return ret;
}
static gboolean
gst_d3d11_window_do_convert (GstD3D11Window * self,
ID3D11ShaderResourceView * srv[GST_VIDEO_MAX_PLANES],
ID3D11RenderTargetView * rtv, RECT * input_rect)
{
RECT *prev = &self->prev_input_rect;
if (input_rect->left != prev->left || input_rect->top != prev->top ||
input_rect->right != prev->right || input_rect->bottom != prev->bottom) {
g_object_set (self->converter, "src-x", (gint) input_rect->left,
"src-y", (gint) input_rect->top,
"src-width", (gint) (input_rect->right - input_rect->left),
"src-height", (gint) (input_rect->bottom - input_rect->top), nullptr);
*prev = *input_rect;
}
if (!gst_d3d11_converter_convert_unlocked (self->converter, srv, &rtv)) {
GST_ERROR_OBJECT (self, "Couldn't render to backbuffer using converter");
return FALSE;
} else {
GST_TRACE_OBJECT (self, "Rendered using converter");
}
return TRUE;
}
static GstFlowReturn static GstFlowReturn
gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer,
ID3D11VideoProcessorOutputView * pov, ID3D11RenderTargetView * rtv) GstBuffer * backbuffer)
{ {
GstD3D11WindowClass *klass = GST_D3D11_WINDOW_GET_CLASS (self); GstD3D11WindowClass *klass = GST_D3D11_WINDOW_GET_CLASS (self);
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
guint present_flags = 0; guint present_flags = 0;
GstVideoCropMeta *crop_meta;
RECT input_rect = self->input_rect;
RECT *prev_rect = &self->prev_input_rect;
ID3D11RenderTargetView *rtv;
GstMemory *mem;
GstD3D11Memory *dmem;
if (!buffer) if (!buffer)
return GST_FLOW_OK; return GST_FLOW_OK;
{ if (!backbuffer) {
GstMapInfo infos[GST_VIDEO_MAX_PLANES]; GST_ERROR_OBJECT (self, "Empty render target");
ID3D11ShaderResourceView *srv[GST_VIDEO_MAX_PLANES]; return GST_FLOW_ERROR;
ID3D11VideoProcessorInputView *piv = NULL;
ID3D11Device *device_handle =
gst_d3d11_device_get_device_handle (self->device);
gboolean can_convert = FALSE;
gboolean can_process = FALSE;
gboolean convert_ret = FALSE;
RECT input_rect = self->input_rect;
GstVideoCropMeta *crop_meta;
/* Map memory in any case so that we can upload pending stage texture */
if (!gst_d3d11_buffer_map (buffer, device_handle, infos, GST_MAP_READ)) {
GST_ERROR_OBJECT (self, "Couldn't map buffer");
return GST_FLOW_ERROR;
}
can_convert = gst_d3d11_buffer_get_shader_resource_view (buffer, srv);
if (pov) {
can_process = gst_d3d11_window_buffer_ensure_processor_input (self,
buffer, &piv);
}
if (!can_convert && !can_process) {
GST_ERROR_OBJECT (self, "Input texture cannot be used for converter");
return GST_FLOW_ERROR;
}
crop_meta = gst_buffer_get_video_crop_meta (buffer);
/* Do minimal validate */
if (crop_meta) {
ID3D11Texture2D *texture = (ID3D11Texture2D *) infos[0].data;
D3D11_TEXTURE2D_DESC desc = { 0, };
texture->GetDesc (&desc);
if (desc.Width < crop_meta->x + crop_meta->width ||
desc.Height < crop_meta->y + crop_meta->height) {
GST_WARNING_OBJECT (self, "Invalid crop meta, ignore");
crop_meta = nullptr;
}
}
if (crop_meta) {
input_rect.left = crop_meta->x;
input_rect.right = crop_meta->x + crop_meta->width;
input_rect.top = crop_meta->y;
input_rect.bottom = crop_meta->y + crop_meta->height;
}
if (self->first_present) {
D3D11_VIEWPORT viewport;
viewport.TopLeftX = self->render_rect.left;
viewport.TopLeftY = self->render_rect.top;
viewport.Width = self->render_rect.right - self->render_rect.left;
viewport.Height = self->render_rect.bottom - self->render_rect.top;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
g_object_set (self->converter, "dest-x", (gint) self->render_rect.left,
"dest-y", (gint) self->render_rect.top,
"dest-width",
(gint) (self->render_rect.right - self->render_rect.left),
"dest-height",
(gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
gst_d3d11_overlay_compositor_update_viewport (self->compositor,
&viewport);
}
/* Converter preference order
* 1) If this texture can be converted via processor, and we used processor
* previously, use processor
* 2) If SRV is available, use converter
* 3) otherwise, use processor
*/
if (can_process && self->processor_in_use) {
convert_ret = gst_d3d11_window_do_processor (self, piv, pov, &input_rect);
} else if (can_convert) {
convert_ret = gst_d3d11_window_do_convert (self, srv, rtv, &input_rect);
} else if (can_process) {
convert_ret = gst_d3d11_window_do_processor (self, piv, pov, &input_rect);
} else {
g_assert_not_reached ();
ret = GST_FLOW_ERROR;
goto unmap_and_out;
}
if (!convert_ret) {
ret = GST_FLOW_ERROR;
goto unmap_and_out;
}
gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv);
if (self->allow_tearing && self->fullscreen) {
present_flags |= DXGI_PRESENT_ALLOW_TEARING;
}
if (klass->present)
ret = klass->present (self, present_flags);
self->first_present = FALSE;
unmap_and_out:
gst_d3d11_buffer_unmap (buffer, infos);
} }
mem = gst_buffer_peek_memory (backbuffer, 0);
if (!gst_is_d3d11_memory (mem)) {
GST_ERROR_OBJECT (self, "Invalid back buffer");
return GST_FLOW_ERROR;
}
dmem = GST_D3D11_MEMORY_CAST (mem);
rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
if (!rtv) {
GST_ERROR_OBJECT (self, "RTV is unavailable");
return GST_FLOW_ERROR;
}
crop_meta = gst_buffer_get_video_crop_meta (buffer);
if (crop_meta) {
input_rect.left = crop_meta->x;
input_rect.right = crop_meta->x + crop_meta->width;
input_rect.top = crop_meta->y;
input_rect.bottom = crop_meta->y + crop_meta->height;
}
if (input_rect.left != prev_rect->left || input_rect.top != prev_rect->top ||
input_rect.right != prev_rect->right ||
input_rect.bottom != prev_rect->bottom) {
g_object_set (self->converter, "src-x", (gint) input_rect.left,
"src-y", (gint) input_rect.top,
"src-width", (gint) (input_rect.right - input_rect.left),
"src-height", (gint) (input_rect.bottom - input_rect.top), nullptr);
self->prev_input_rect = input_rect;
}
if (self->first_present) {
D3D11_VIEWPORT viewport;
viewport.TopLeftX = self->render_rect.left;
viewport.TopLeftY = self->render_rect.top;
viewport.Width = self->render_rect.right - self->render_rect.left;
viewport.Height = self->render_rect.bottom - self->render_rect.top;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
g_object_set (self->converter, "dest-x", (gint) self->render_rect.left,
"dest-y", (gint) self->render_rect.top,
"dest-width",
(gint) (self->render_rect.right - self->render_rect.left),
"dest-height",
(gint) (self->render_rect.bottom - self->render_rect.top), nullptr);
gst_d3d11_overlay_compositor_update_viewport (self->compositor, &viewport);
}
if (!gst_d3d11_converter_convert_buffer_unlocked (self->converter,
buffer, backbuffer)) {
GST_ERROR_OBJECT (self, "Couldn't render buffer");
return GST_FLOW_ERROR;
}
gst_d3d11_overlay_compositor_upload (self->compositor, buffer);
gst_d3d11_overlay_compositor_draw_unlocked (self->compositor, &rtv);
if (self->allow_tearing && self->fullscreen)
present_flags |= DXGI_PRESENT_ALLOW_TEARING;
if (klass->present)
ret = klass->present (self, present_flags);
self->first_present = FALSE;
return ret; return ret;
} }
GstFlowReturn GstFlowReturn
gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer) gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer)
{ {
GstMemory *mem;
GstFlowReturn ret; GstFlowReturn ret;
g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR);
if (buffer) {
mem = gst_buffer_peek_memory (buffer, 0);
if (!gst_is_d3d11_memory (mem)) {
GST_ERROR_OBJECT (window, "Invalid buffer");
return GST_FLOW_ERROR;
}
}
gst_d3d11_device_lock (window->device); gst_d3d11_device_lock (window->device);
if (buffer) if (buffer)
gst_buffer_replace (&window->cached_buffer, buffer); gst_buffer_replace (&window->cached_buffer, buffer);
ret = gst_d3d111_window_present (window, window->cached_buffer, ret = gst_d3d111_window_present (window, window->cached_buffer,
window->pov, window->rtv); window->backbuffer);
gst_d3d11_device_unlock (window->device); gst_d3d11_device_unlock (window->device);
return ret; return ret;
@ -1029,11 +848,8 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
guint64 acquire_key, guint64 release_key) guint64 acquire_key, guint64 release_key)
{ {
GstD3D11WindowClass *klass; GstD3D11WindowClass *klass;
GstMemory *mem;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstD3D11WindowSharedHandleData data = { NULL, }; GstD3D11WindowSharedHandleData data = { nullptr, };
ID3D11VideoProcessorOutputView *pov = NULL;
ID3D11RenderTargetView *rtv = NULL;
g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR); g_return_val_if_fail (GST_IS_D3D11_WINDOW (window), GST_FLOW_ERROR);
@ -1042,13 +858,6 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
g_assert (klass->open_shared_handle != NULL); g_assert (klass->open_shared_handle != NULL);
g_assert (klass->release_shared_handle != NULL); g_assert (klass->release_shared_handle != NULL);
mem = gst_buffer_peek_memory (buffer, 0);
if (!gst_is_d3d11_memory (mem)) {
GST_ERROR_OBJECT (window, "Invalid buffer");
return GST_FLOW_ERROR;
}
data.shared_handle = shared_handle; data.shared_handle = shared_handle;
data.texture_misc_flags = texture_misc_flags; data.texture_misc_flags = texture_misc_flags;
data.acquire_key = acquire_key; data.acquire_key = acquire_key;
@ -1061,15 +870,7 @@ gst_d3d11_window_render_on_shared_handle (GstD3D11Window * window,
return GST_FLOW_OK; return GST_FLOW_OK;
} }
if (data.fallback_rtv) { ret = gst_d3d111_window_present (window, buffer, data.render_target);
rtv = data.fallback_rtv;
pov = data.fallback_pov;
} else {
rtv = data.rtv;
pov = data.pov;
}
ret = gst_d3d111_window_present (window, buffer, pov, rtv);
klass->release_shared_handle (window, &data); klass->release_shared_handle (window, &data);
gst_d3d11_device_unlock (window->device); gst_d3d11_device_unlock (window->device);

View file

@ -69,13 +69,8 @@ typedef struct
guint64 acquire_key; guint64 acquire_key;
guint64 release_key; guint64 release_key;
ID3D11Texture2D *texture; GstBuffer *render_target;
IDXGIKeyedMutex *keyed_mutex; IDXGIKeyedMutex *keyed_mutex;
ID3D11VideoProcessorOutputView *pov;
ID3D11RenderTargetView *rtv;
ID3D11VideoProcessorOutputView *fallback_pov;
ID3D11RenderTargetView *fallback_rtv;
} GstD3D11WindowSharedHandleData; } GstD3D11WindowSharedHandleData;
struct _GstD3D11Window struct _GstD3D11Window
@ -85,6 +80,7 @@ struct _GstD3D11Window
/*< protected >*/ /*< protected >*/
gboolean initialized; gboolean initialized;
GstD3D11Device *device; GstD3D11Device *device;
GstD3D11Allocator *allocator;
guintptr external_handle; guintptr external_handle;
/* properties */ /* properties */
@ -97,12 +93,9 @@ struct _GstD3D11Window
GstVideoInfo info; GstVideoInfo info;
GstVideoInfo render_info; GstVideoInfo render_info;
GstD3D11VideoProcessor *processor;
GstD3D11Converter *converter; GstD3D11Converter *converter;
GstD3D11OverlayCompositor *compositor; GstD3D11OverlayCompositor *compositor;
gboolean processor_in_use;
/* calculated rect with aspect ratio and window area */ /* calculated rect with aspect ratio and window area */
RECT render_rect; RECT render_rect;
@ -117,8 +110,7 @@ struct _GstD3D11Window
guint surface_height; guint surface_height;
IDXGISwapChain *swap_chain; IDXGISwapChain *swap_chain;
ID3D11RenderTargetView *rtv; GstBuffer *backbuffer;
ID3D11VideoProcessorOutputView *pov;
DXGI_FORMAT dxgi_format; DXGI_FORMAT dxgi_format;
GstBuffer *cached_buffer; GstBuffer *cached_buffer;
@ -158,7 +150,6 @@ struct _GstD3D11WindowClass
guint display_width, guint display_width,
guint display_height, guint display_height,
GstCaps * caps, GstCaps * caps,
gboolean * video_processor_available,
GError ** error); GError ** error);
void (*unprepare) (GstD3D11Window * window); void (*unprepare) (GstD3D11Window * window);
@ -190,7 +181,6 @@ gboolean gst_d3d11_window_prepare (GstD3D11Window * window,
guint display_width, guint display_width,
guint display_height, guint display_height,
GstCaps * caps, GstCaps * caps,
gboolean * video_processor_available,
GError ** error); GError ** error);
GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window, GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window,

View file

@ -49,9 +49,7 @@ G_DEFINE_TYPE (GstD3D11WindowDummy, gst_d3d11_window_dummy,
static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
guint width, guint height); guint width, guint height);
static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window, static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, guint display_width, guint display_height, GstCaps * caps, GError ** error);
gboolean * video_processor_available, GError ** error);
static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window);
static gboolean static gboolean
gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window, gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
GstD3D11WindowSharedHandleData * data); GstD3D11WindowSharedHandleData * data);
@ -67,8 +65,6 @@ gst_d3d11_window_dummy_class_init (GstD3D11WindowDummyClass * klass)
window_class->on_resize = window_class->on_resize =
GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize); GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize);
window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare); window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare);
window_class->unprepare =
GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_unprepare);
window_class->open_shared_handle = window_class->open_shared_handle =
GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle); GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle);
window_class->release_shared_handle = window_class->release_shared_handle =
@ -82,13 +78,19 @@ gst_d3d11_window_dummy_init (GstD3D11WindowDummy * self)
static gboolean static gboolean
gst_d3d11_window_dummy_prepare (GstD3D11Window * window, gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, guint display_width, guint display_height, GstCaps * caps, GError ** error)
gboolean * video_processor_available, GError ** error)
{ {
GstDxgiColorSpace in_space;
GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER; GstD3D11ConverterMethod method = GST_D3D11_CONVERTER_METHOD_SHADER;
g_clear_pointer (&window->processor, gst_d3d11_video_processor_free); if (!window->allocator) {
window->allocator =
(GstD3D11Allocator *) gst_allocator_find (GST_D3D11_MEMORY_NAME);
if (!window->allocator) {
GST_ERROR_OBJECT (window, "Allocator is unavailable");
return FALSE;
}
}
gst_clear_object (&window->compositor); gst_clear_object (&window->compositor);
gst_clear_object (&window->converter); gst_clear_object (&window->converter);
@ -116,63 +118,7 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255; window->render_info.colorimetry.range = GST_VIDEO_COLOR_RANGE_0_255;
gst_d3d11_device_lock (window->device); gst_d3d11_device_lock (window->device);
window->converter = gst_d3d11_converter_new (window->device, &window->info,
if (gst_d3d11_video_info_to_dxgi_color_space (&window->info, &in_space)) {
GstD3D11Format in_format;
gboolean hardware = FALSE;
GstD3D11VideoProcessor *processor = NULL;
guint i;
DXGI_FORMAT formats_to_check[] = {
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R10G10B10A2_UNORM
};
DXGI_FORMAT in_dxgi_format;
gst_d3d11_device_get_format (window->device,
GST_VIDEO_INFO_FORMAT (&window->info), &in_format);
in_dxgi_format = in_format.dxgi_format;
if (in_format.dxgi_format != DXGI_FORMAT_UNKNOWN) {
g_object_get (window->device, "hardware", &hardware, NULL);
}
if (hardware) {
processor =
gst_d3d11_video_processor_new (window->device,
GST_VIDEO_INFO_WIDTH (&window->info),
GST_VIDEO_INFO_HEIGHT (&window->info), display_width, display_height);
}
/* Check if video processor can support all possible output dxgi formats */
for (i = 0; i < G_N_ELEMENTS (formats_to_check) && processor; i++) {
DXGI_FORMAT out_dxgi_format = formats_to_check[i];
DXGI_COLOR_SPACE_TYPE in_dxgi_color_space =
(DXGI_COLOR_SPACE_TYPE) in_space.dxgi_color_space_type;
if (!gst_d3d11_video_processor_check_format_conversion (processor,
in_dxgi_format, in_dxgi_color_space, out_dxgi_format,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709)) {
GST_DEBUG_OBJECT (window, "Conversion is not supported by device");
g_clear_pointer (&processor, gst_d3d11_video_processor_free);
break;
}
}
if (processor) {
gst_d3d11_video_processor_set_input_dxgi_color_space (processor,
(DXGI_COLOR_SPACE_TYPE) in_space.dxgi_color_space_type);
gst_d3d11_video_processor_set_output_dxgi_color_space (processor,
DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
}
window->processor = processor;
}
*video_processor_available = !!window->processor;
window->converter =
gst_d3d11_converter_new (window->device, &window->info,
&window->render_info, &method); &window->render_info, &method);
if (!window->converter) { if (!window->converter) {
@ -201,22 +147,6 @@ error:
return FALSE; return FALSE;
} }
static void
gst_d3d11_window_dummy_clear_resources (GstD3D11WindowDummy * self)
{
GST_D3D11_CLEAR_COM (self->fallback_pov);
GST_D3D11_CLEAR_COM (self->fallback_rtv);
GST_D3D11_CLEAR_COM (self->fallback_texture);
}
static void
gst_d3d11_window_dummy_unprepare (GstD3D11Window * window)
{
GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
gst_d3d11_window_dummy_clear_resources (self);
}
static void static void
gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
guint width, guint height) guint width, guint height)
@ -247,108 +177,26 @@ gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
window->first_present = TRUE; window->first_present = TRUE;
} }
static gboolean
gst_d3d11_window_dummy_setup_fallback_texture (GstD3D11Window * window,
D3D11_TEXTURE2D_DESC * shared_desc)
{
GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
D3D11_TEXTURE2D_DESC desc = { 0, };
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc;
ID3D11Device *device_handle =
gst_d3d11_device_get_device_handle (window->device);
gboolean need_new_texture = FALSE;
HRESULT hr;
if (!self->fallback_texture) {
GST_DEBUG_OBJECT (self,
"We have no configured fallback texture, create new one");
need_new_texture = TRUE;
} else {
self->fallback_texture->GetDesc (&desc);
if (shared_desc->Format != desc.Format) {
GST_DEBUG_OBJECT (self, "Texture formats are different, create new one");
need_new_texture = TRUE;
} else if (shared_desc->Width > desc.Width ||
shared_desc->Height > desc.Height) {
GST_DEBUG_OBJECT (self, "Needs larger size of fallback texture");
need_new_texture = TRUE;
}
}
if (!need_new_texture)
return TRUE;
gst_d3d11_window_dummy_clear_resources (self);
desc.Width = shared_desc->Width;
desc.Height = shared_desc->Height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = shared_desc->Format;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
hr = device_handle->CreateTexture2D (&desc, NULL, &self->fallback_texture);
if (!gst_d3d11_result (hr, window->device)) {
GST_ERROR_OBJECT (self, "Couldn't create fallback texture");
return FALSE;
}
rtv_desc.Format = DXGI_FORMAT_UNKNOWN;
rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtv_desc.Texture2D.MipSlice = 0;
hr = device_handle->CreateRenderTargetView (self->fallback_texture, &rtv_desc,
&self->fallback_rtv);
if (!gst_d3d11_result (hr, window->device)) {
GST_ERROR_OBJECT (self,
"Couldn't get render target view from fallback texture");
gst_d3d11_window_dummy_clear_resources (self);
return FALSE;
}
if (window->processor) {
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc;
pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
pov_desc.Texture2D.MipSlice = 0;
if (!gst_d3d11_video_processor_create_output_view (window->processor,
&pov_desc, self->fallback_texture, &self->fallback_pov)) {
GST_ERROR_OBJECT (window,
"ID3D11VideoProcessorOutputView is unavailable");
gst_d3d11_window_dummy_clear_resources (self);
return FALSE;
}
}
return TRUE;
}
/* *INDENT-OFF* */
static gboolean static gboolean
gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window, gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
GstD3D11WindowSharedHandleData * data) GstD3D11WindowSharedHandleData * data)
{ {
GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
GstD3D11Device *device = window->device; GstD3D11Device *device = window->device;
ID3D11Device *device_handle; ID3D11Device *device_handle;
HRESULT hr; HRESULT hr;
ID3D11Texture2D *texture = NULL; ComPtr < ID3D11Texture2D > texture;
IDXGIKeyedMutex *keyed_mutex = NULL; ComPtr < IDXGIKeyedMutex > keyed_mutex;
ID3D11VideoProcessorOutputView *pov = NULL; ID3D11RenderTargetView *rtv;
ID3D11RenderTargetView *rtv = NULL; GstMemory *mem;
GstD3D11Memory *dmem;
D3D11_TEXTURE2D_DESC desc; D3D11_TEXTURE2D_DESC desc;
gboolean use_keyed_mutex = FALSE; gboolean use_keyed_mutex = FALSE;
gboolean need_fallback_texture = FALSE;
device_handle = gst_d3d11_device_get_device_handle (device); device_handle = gst_d3d11_device_get_device_handle (device);
if ((data->texture_misc_flags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) == if ((data->texture_misc_flags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) ==
D3D11_RESOURCE_MISC_SHARED_NTHANDLE) { D3D11_RESOURCE_MISC_SHARED_NTHANDLE) {
ComPtr<ID3D11Device1> device1_handle; ComPtr < ID3D11Device1 > device1_handle;
hr = device_handle->QueryInterface (IID_PPV_ARGS (&device1_handle)); hr = device_handle->QueryInterface (IID_PPV_ARGS (&device1_handle));
if (!gst_d3d11_result (hr, device)) if (!gst_d3d11_result (hr, device))
@ -370,82 +218,47 @@ gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
if (use_keyed_mutex) { if (use_keyed_mutex) {
hr = texture->QueryInterface (IID_PPV_ARGS (&keyed_mutex)); hr = texture->QueryInterface (IID_PPV_ARGS (&keyed_mutex));
if (!gst_d3d11_result (hr, device)) if (!gst_d3d11_result (hr, device)) {
goto out; GST_ERROR_OBJECT (window, "Keyed mutex is unavailable");
} return FALSE;
if (window->processor) {
if (use_keyed_mutex) {
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC pov_desc;
pov_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
pov_desc.Texture2D.MipSlice = 0;
if (!gst_d3d11_video_processor_create_output_view (window->processor,
&pov_desc, texture, &pov)) {
GST_WARNING_OBJECT (window,
"ID3D11VideoProcessorOutputView is unavailable");
}
} else {
/* HACK: If external texture was created without keyed mutext
* and we need to used videoprocessor to convert decoder output texture
* to external texture, converted texture by videoprocessor seems to be broken
* Probably that's because of missing flush/sync API around videoprocessor.
* (e.g., ID3D11VideoContext and ID3D11VideoProcessor have no
* flushing api such as ID3D11DeviceContext::Flush).
* To workaround the case, we need to use fallback texture and copy back
* to external texture
*/
need_fallback_texture = TRUE;
GST_TRACE_OBJECT (window,
"We are using video processor but keyed mutex is unavailable");
if (!gst_d3d11_window_dummy_setup_fallback_texture (window, &desc)) {
goto out;
}
} }
} }
hr = device_handle->CreateRenderTargetView ((ID3D11Resource *) texture, mem = gst_d3d11_allocator_alloc_wrapped_native_size (window->allocator,
NULL, &rtv); device, texture.Get (), nullptr, nullptr);
if (!gst_d3d11_result (hr, device)) if (!mem) {
goto out; GST_ERROR_OBJECT (window, "Couldn't allocate memory");
return FALSE;
}
dmem = GST_D3D11_MEMORY_CAST (mem);
rtv = gst_d3d11_memory_get_render_target_view (dmem, 0);
if (!rtv) {
GST_ERROR_OBJECT (window, "Render target view is unavailable");
gst_memory_unref (mem);
return FALSE;
}
if (keyed_mutex) { if (keyed_mutex) {
hr = keyed_mutex->AcquireSync(data->acquire_key, INFINITE); hr = keyed_mutex->AcquireSync (data->acquire_key, INFINITE);
if (!gst_d3d11_result (hr, device)) if (!gst_d3d11_result (hr, device)) {
goto out; GST_ERROR_OBJECT (window, "Couldn't acquire sync");
gst_memory_unref (mem);
return FALSE;
}
} }
/* Everything is prepared now */ /* Everything is prepared now */
gst_d3d11_window_dummy_on_resize (window, desc.Width, desc.Height); gst_d3d11_window_dummy_on_resize (window, desc.Width, desc.Height);
/* Move owned resources */ /* Move owned resources */
data->texture = texture; data->render_target = gst_buffer_new ();
data->keyed_mutex = keyed_mutex; gst_buffer_append_memory (data->render_target, mem);
data->pov = pov; if (keyed_mutex)
data->rtv = rtv; data->keyed_mutex = keyed_mutex.Detach ();
if (need_fallback_texture) {
data->fallback_pov = self->fallback_pov;
data->fallback_rtv = self->fallback_rtv;
} else {
data->fallback_pov = nullptr;
data->fallback_rtv = nullptr;
}
return TRUE; return TRUE;
out:
GST_D3D11_CLEAR_COM (texture);
GST_D3D11_CLEAR_COM (keyed_mutex);
GST_D3D11_CLEAR_COM (pov);
GST_D3D11_CLEAR_COM (rtv);
return FALSE;
} }
/* *INDENT-ON* */
static gboolean static gboolean
gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window, gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
@ -460,7 +273,7 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
hr = data->keyed_mutex->ReleaseSync (data->release_key); hr = data->keyed_mutex->ReleaseSync (data->release_key);
gst_d3d11_result (hr, device); gst_d3d11_result (hr, device);
data->keyed_mutex->Release (); GST_D3D11_CLEAR_COM (data->keyed_mutex);
} else { } else {
/* *INDENT-OFF* */ /* *INDENT-OFF* */
ComPtr<ID3D11Query> query; ComPtr<ID3D11Query> query;
@ -482,30 +295,11 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
return FALSE; return FALSE;
} }
/* Copy from fallback texture to user's texture */
if (data->fallback_rtv) {
D3D11_BOX src_box;
D3D11_TEXTURE2D_DESC desc;
ID3D11DeviceContext *context_handle =
gst_d3d11_device_get_device_context_handle (device);
data->texture->GetDesc (&desc);
src_box.left = 0;
src_box.top = 0;
src_box.front = 0;
src_box.back = 1;
src_box.right = desc.Width;
src_box.bottom = desc.Height;
context_handle->CopySubresourceRegion (data->texture, 0, 0, 0, 0,
self->fallback_texture, 0, &src_box);
}
context_handle->End (query.Get ()); context_handle->End (query.Get ());
/* Wait until all issued GPU commands are finished */ /* Wait until all issued GPU commands are finished */
do { do {
context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
} while (!sync_done && (hr == S_OK || hr == S_FALSE)); } while (!sync_done && (hr == S_OK || hr == S_FALSE));
if (!gst_d3d11_result (hr, device)) { if (!gst_d3d11_result (hr, device)) {
@ -514,9 +308,7 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
} }
} }
GST_D3D11_CLEAR_COM (data->rtv); gst_clear_buffer (&data->render_target);
GST_D3D11_CLEAR_COM (data->pov);
GST_D3D11_CLEAR_COM (data->texture);
return TRUE; return TRUE;
} }