From 5298d95195d8489f0d836a2060b82a773aeb982b Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 24 Dec 2019 14:00:15 +0900 Subject: [PATCH] d3d11window: Make use of partial presentation with IDXGISwapChain1::Present1 Since we might draw on partial area of backbuffer in case of force-aspect-ratio, presenting only updated area is more efficient way. See also https://docs.microsoft.com/ko-kr/windows/win32/direct3ddxgi/dxgi-1-2-presentation-improvements --- sys/d3d11/gstd3d11window.c | 66 +++++++++++++++++++++++--------------- sys/d3d11/gstd3d11window.h | 3 +- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/sys/d3d11/gstd3d11window.c b/sys/d3d11/gstd3d11window.c index 1c96144a4c..561b5c6d44 100644 --- a/sys/d3d11/gstd3d11window.c +++ b/sys/d3d11/gstd3d11window.c @@ -581,6 +581,7 @@ gst_d3d11_window_on_resize (GstD3D11Window * window, gboolean redraw) D3D11_TEXTURE2D_DESC desc; DXGI_SWAP_CHAIN_DESC swap_desc; ID3D11Texture2D *backbuffer = NULL; + GstVideoRectangle src_rect, dst_rect, rst_rect; gst_d3d11_device_lock (window->device); if (!window->swap_chain) @@ -618,8 +619,6 @@ gst_d3d11_window_on_resize (GstD3D11Window * window, gboolean redraw) height = window->height; { - GstVideoRectangle src_rect, dst_rect; - src_rect.x = 0; src_rect.y = 0; src_rect.w = width * window->aspect_ratio_n; @@ -634,17 +633,20 @@ gst_d3d11_window_on_resize (GstD3D11Window * window, gboolean redraw) src_rect.w = width * window->aspect_ratio_n; src_rect.h = height * window->aspect_ratio_d; - gst_video_sink_center_rect (src_rect, dst_rect, &window->render_rect, - TRUE); + gst_video_sink_center_rect (src_rect, dst_rect, &rst_rect, TRUE); } else { - window->render_rect = dst_rect; + 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, window->render_rect.x, window->render_rect.y, - window->render_rect.w, window->render_rect.h); + desc.Width, desc.Height, rst_rect.x, rst_rect.y, rst_rect.w, rst_rect.h); hr = ID3D11Device_CreateRenderTargetView (d3d11_dev, (ID3D11Resource *) backbuffer, NULL, &window->rtv); @@ -1126,7 +1128,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, { DXGI_SWAP_CHAIN_DESC desc = { 0, }; GstCaps *render_caps; - UINT swapchain_flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + UINT swapchain_flags = 0; DXGI_SWAP_EFFECT swap_effect = DXGI_SWAP_EFFECT_DISCARD; #if (DXGI_HEADER_VERSION >= 5) gboolean have_cll = FALSE; @@ -1215,6 +1217,7 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, } window->allow_tearing = FALSE; + window->have_swapchain1 = FALSE; #if (DXGI_HEADER_VERSION >= 5) if (!gst_video_content_light_level_from_caps (&window->content_light_level, caps)) { @@ -1237,10 +1240,6 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, GST_DEBUG_OBJECT (window, "DXGI 1.5 interface is available"); swapchain4_available = TRUE; - /* For non-DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 color space support, - * DXGI_SWAP_EFFECT_FLIP_DISCARD instead of DXGI_SWAP_EFFECT_DISCARD */ - swap_effect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - g_object_get (window->device, "allow-tearing", &allow_tearing, NULL); if (allow_tearing) { GST_DEBUG_OBJECT (window, "device support tearning"); @@ -1259,10 +1258,10 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, window->aspect_ratio_n = aspect_ratio_n; window->aspect_ratio_d = aspect_ratio_d; - window->render_rect.x = 0; - window->render_rect.y = 0; - window->render_rect.w = width; - window->render_rect.h = height; + window->render_rect.left = 0; + window->render_rect.top = 0; + window->render_rect.right = width; + window->render_rect.bottom = height; if (window->external_win_id) { RECT client_rect = { 0, }; @@ -1309,6 +1308,8 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint width, guint height, if (!window->swap_chain) { GST_WARNING_OBJECT (window, "Failed to create swapchain1"); + } else { + window->have_swapchain1 = TRUE; } } #endif @@ -1503,15 +1504,10 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) } if (self->first_present) { - RECT rect; - - rect.left = self->render_rect.x; - rect.right = self->render_rect.x + self->render_rect.w; - rect.top = self->render_rect.y; - rect.bottom = self->render_rect.y + self->render_rect.h; - - gst_d3d11_color_converter_update_rect (self->converter, &rect); - gst_d3d11_overlay_compositor_update_rect (self->compositor, &rect); + gst_d3d11_color_converter_update_rect (self->converter, + &self->render_rect); + gst_d3d11_overlay_compositor_update_rect (self->compositor, + &self->render_rect); } gst_d3d11_color_converter_convert_unlocked (self->converter, @@ -1526,7 +1522,25 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) } #endif - hr = IDXGISwapChain_Present (self->swap_chain, 0, present_flags); +#if (DXGI_HEADER_VERSION >= 2) + if (self->have_swapchain1) { + DXGI_PRESENT_PARAMETERS present_params = { 0, }; + if (self->first_present) { + /* the first present should not specify dirty-rect */ + hr = IDXGISwapChain1_Present1 ((IDXGISwapChain1 *) self->swap_chain, + 0, present_flags, &present_params); + } else { + present_params.DirtyRectsCount = 1; + present_params.pDirtyRects = &self->render_rect; + hr = IDXGISwapChain1_Present1 ((IDXGISwapChain1 *) self->swap_chain, + 0, present_flags, &present_params); + } + } else +#endif + { + hr = IDXGISwapChain_Present (self->swap_chain, 0, present_flags); + } + self->first_present = FALSE; if (!gst_d3d11_result (hr, self->device)) { diff --git a/sys/d3d11/gstd3d11window.h b/sys/d3d11/gstd3d11window.h index 6934ebf0b2..b9c7366841 100644 --- a/sys/d3d11/gstd3d11window.h +++ b/sys/d3d11/gstd3d11window.h @@ -73,7 +73,7 @@ struct _GstD3D11Window GstVideoContentLightLevel content_light_level; /* calculated rect with aspect ratio and window area */ - GstVideoRectangle render_rect; + RECT render_rect; /* requested rect via gst_d3d11_window_render */ GstVideoRectangle rect; @@ -111,6 +111,7 @@ struct _GstD3D11Window ID3D11RenderTargetView *rtv; DXGI_FORMAT format; gboolean first_present; + gboolean have_swapchain1; GstD3D11Device *device;