From 96831233a32d3b5bb036ddbe65ef307be5f2148c Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sun, 22 Nov 2020 04:39:57 +0900 Subject: [PATCH] d3d11videosink: Add a property to support rendering statistics data on window Add a new property "render-stats" to allow rendering statistics data on window for debugging and/or development purpose. Text rendering will be accelerated by GPU since this implementation uses Direct2D/DirectWrite API and Direct3D inter-op for minimal overhead. Specifically, text data will be rendered on swapchain backbuffer directly without any copy/allocation of extra texture. Part-of: --- sys/d3d11/gstd3d11videosink.c | 35 ++++- sys/d3d11/gstd3d11videosinkbin.c | 11 ++ sys/d3d11/gstd3d11window.cpp | 303 +++++++++++++++++++++++++++++++++++++-- sys/d3d11/gstd3d11window.h | 7 +- sys/d3d11/meson.build | 11 ++ 5 files changed, 352 insertions(+), 15 deletions(-) diff --git a/sys/d3d11/gstd3d11videosink.c b/sys/d3d11/gstd3d11videosink.c index 8bb5aa0..ed94448 100644 --- a/sys/d3d11/gstd3d11videosink.c +++ b/sys/d3d11/gstd3d11videosink.c @@ -44,6 +44,7 @@ enum PROP_ENABLE_NAVIGATION_EVENTS, PROP_FULLSCREEN_TOGGLE_MODE, PROP_FULLSCREEN, + PROP_RENDER_STATS, }; #define DEFAULT_ADAPTER -1 @@ -51,6 +52,7 @@ enum #define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE #define DEFAULT_FULLSCREEN_TOGGLE_MODE GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE #define DEFAULT_FULLSCREEN FALSE +#define DEFAULT_RENDER_STATS FALSE static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -84,6 +86,7 @@ struct _GstD3D11VideoSink gboolean enable_navigation_events; GstD3D11WindowFullscreenToggleMode fullscreen_toggle_mode; gboolean fullscreen; + gboolean render_stats; /* saved render rectangle until we have a window */ GstVideoRectangle render_rect; @@ -178,6 +181,16 @@ gst_d3d11_video_sink_class_init (GstD3D11VideoSinkClass * klass) "Ignored when \"fullscreen-toggle-mode\" does not include \"property\"", DEFAULT_FULLSCREEN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#ifdef HAVE_DIRECT_WRITE + g_object_class_install_property (gobject_class, PROP_RENDER_STATS, + g_param_spec_boolean ("render-stats", + "Render Stats", + "Render statistics data (e.g., average framerate) on window", + DEFAULT_RENDER_STATS, + GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_READY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif + element_class->set_context = GST_DEBUG_FUNCPTR (gst_d3d11_video_sink_set_context); @@ -213,6 +226,7 @@ gst_d3d11_video_sink_init (GstD3D11VideoSink * self) self->enable_navigation_events = DEFAULT_ENABLE_NAVIGATION_EVENTS; self->fullscreen_toggle_mode = DEFAULT_FULLSCREEN_TOGGLE_MODE; self->fullscreen = DEFAULT_FULLSCREEN; + self->render_stats = DEFAULT_RENDER_STATS; } static void @@ -252,6 +266,11 @@ gst_d3d11_videosink_set_property (GObject * object, guint prop_id, g_object_set (self->window, "fullscreen", self->fullscreen, NULL); } break; +#ifdef HAVE_DIRECT_WRITE + case PROP_RENDER_STATS: + self->render_stats = g_value_get_boolean (value); + break; +#endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -285,6 +304,11 @@ gst_d3d11_videosink_get_property (GObject * object, guint prop_id, g_value_set_boolean (value, self->fullscreen); } break; +#ifdef HAVE_DIRECT_WRITE + case PROP_RENDER_STATS: + g_value_set_boolean (value, self->render_stats); + break; +#endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -592,6 +616,9 @@ gst_d3d11_video_sink_start (GstBaseSink * sink) "fullscreen-toggle-mode", self->fullscreen_toggle_mode, "fullscreen", self->fullscreen, "enable-navigation-events", self->enable_navigation_events, NULL); +#ifdef HAVE_DIRECT_WRITE + g_object_set (self->window, "render-stats", self->render_stats, NULL); +#endif GST_OBJECT_UNLOCK (self); g_signal_connect (self->window, "key-event", @@ -864,6 +891,7 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) gboolean need_unref = FALSE; gboolean do_device_copy = TRUE; gint i; + GstStructure *stats = NULL; render_buf = buf; @@ -955,7 +983,10 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) rect.w = self->video_width; rect.h = self->video_height; - ret = gst_d3d11_window_render (self->window, render_buf, &rect); + if (self->render_stats) + stats = gst_base_sink_get_stats (GST_BASE_SINK_CAST (self)); + + ret = gst_d3d11_window_render (self->window, render_buf, &rect, stats); if (need_unref) gst_buffer_unref (render_buf); @@ -1013,7 +1044,7 @@ gst_d3d11_video_sink_expose (GstVideoOverlay * overlay) rect.w = GST_VIDEO_SINK_WIDTH (self); rect.h = GST_VIDEO_SINK_HEIGHT (self); - gst_d3d11_window_render (self->window, NULL, &rect); + gst_d3d11_window_render (self->window, NULL, &rect, NULL); } } diff --git a/sys/d3d11/gstd3d11videosinkbin.c b/sys/d3d11/gstd3d11videosinkbin.c index d6481d7..0ed16ee 100644 --- a/sys/d3d11/gstd3d11videosinkbin.c +++ b/sys/d3d11/gstd3d11videosinkbin.c @@ -60,6 +60,7 @@ enum PROP_ENABLE_NAVIGATION_EVENTS, PROP_FULLSCREEN_TOGGLE_MODE, PROP_FULLSCREEN, + PROP_RENDER_STATS, }; /* basesink */ @@ -85,6 +86,7 @@ enum #define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE #define DEFAULT_FULLSCREEN_TOGGLE_MODE GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE #define DEFAULT_FULLSCREEN FALSE +#define DEFAULT_RENDER_STATS FALSE static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -238,6 +240,15 @@ gst_d3d11_video_sink_bin_class_init (GstD3D11VideoSinkBinClass * klass) "fullscreen", "Ignored when \"fullscreen-toggle-mode\" does not include \"property\"", DEFAULT_FULLSCREEN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#ifdef HAVE_DIRECT_WRITE + g_object_class_install_property (gobject_class, PROP_RENDER_STATS, + g_param_spec_boolean ("render-stats", + "Render Stats", + "Render statistics data (e.g., average framerate) on window", + DEFAULT_RENDER_STATS, + GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_READY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif gst_element_class_set_static_metadata (element_class, "Direct3D11 video sink bin", "Sink/Video", diff --git a/sys/d3d11/gstd3d11window.cpp b/sys/d3d11/gstd3d11window.cpp index e4714a1..77051b7 100644 --- a/sys/d3d11/gstd3d11window.cpp +++ b/sys/d3d11/gstd3d11window.cpp @@ -34,9 +34,17 @@ #endif #include #include +#endif + +#ifdef HAVE_DIRECT_WRITE +#include +#include +#include +#endif + +#if GST_D3D11_WINAPI_ONLY_APP || defined(HAVE_DIRECT_WRITE) #include #include - using namespace Microsoft::WRL; #endif @@ -45,6 +53,21 @@ GST_DEBUG_CATEGORY_EXTERN (gst_d3d11_window_debug); #define GST_CAT_DEFAULT gst_d3d11_window_debug } +struct _GstD3D11WindowPrivate +{ +#ifdef HAVE_DIRECT_WRITE + IDWriteFactory *dwrite_factory; + IDWriteTextFormat *dwrite_format; + + ID2D1Factory1 *d2d_factory; + ID2D1Device *d2d_device; + ID2D1DeviceContext *d2d_device_context; + ID2D1SolidColorBrush *d2d_brush; +#else + gpointer dummy; +#endif +}; + enum { PROP_0, @@ -54,12 +77,14 @@ enum PROP_FULLSCREEN_TOGGLE_MODE, PROP_FULLSCREEN, PROP_WINDOW_HANDLE, + PROP_RENDER_STATS, }; #define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_FULLSCREEN_TOGGLE_MODE GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE #define DEFAULT_FULLSCREEN FALSE +#define DEFAULT_RENDER_STATS FALSE enum { @@ -94,7 +119,8 @@ gst_d3d11_window_fullscreen_toggle_mode_type (void) } #define gst_d3d11_window_parent_class parent_class -G_DEFINE_ABSTRACT_TYPE (GstD3D11Window, gst_d3d11_window, GST_TYPE_OBJECT); +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstD3D11Window, gst_d3d11_window, + GST_TYPE_OBJECT); static void gst_d3d11_window_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -102,7 +128,7 @@ static void gst_d3d11_window_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_d3d11_window_dispose (GObject * object); static GstFlowReturn gst_d3d111_window_present (GstD3D11Window * self, - GstBuffer * buffer); + GstBuffer * buffer, GstStructure * stats); static void gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width, guint height); @@ -158,6 +184,15 @@ gst_d3d11_window_class_init (GstD3D11WindowClass * klass) (GParamFlags) (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS))); +#ifdef HAVE_DIRECT_WRITE + g_object_class_install_property (gobject_class, PROP_RENDER_STATS, + g_param_spec_boolean ("render-stats", + "Render Stats", + "Render statistics data (e.g., average framerate) on window", + DEFAULT_RENDER_STATS, + (GParamFlags) (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS))); +#endif + d3d11_window_signals[SIGNAL_KEY_EVENT] = g_signal_new ("key-event", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, @@ -176,6 +211,10 @@ gst_d3d11_window_init (GstD3D11Window * self) self->enable_navigation_events = DEFAULT_ENABLE_NAVIGATION_EVENTS; self->fullscreen_toggle_mode = GST_D3D11_WINDOW_FULLSCREEN_TOGGLE_MODE_NONE; self->fullscreen = DEFAULT_FULLSCREEN; + self->render_stats = DEFAULT_RENDER_STATS; + + self->priv = + (GstD3D11WindowPrivate *) gst_d3d11_window_get_instance_private (self); } static void @@ -213,6 +252,11 @@ gst_d3d11_window_set_property (GObject * object, guint prop_id, case PROP_WINDOW_HANDLE: self->external_handle = (guintptr) g_value_get_pointer (value); break; +#ifdef HAVE_DIRECT_WRITE + case PROP_RENDER_STATS: + self->render_stats = g_value_get_boolean (value); + break; +#endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -244,10 +288,155 @@ gst_d3d11_window_get_property (GObject * object, guint prop_id, } } +#ifdef HAVE_DIRECT_WRITE +static void +gst_d3d11_window_release_dwrite_resources (GstD3D11Window * self) +{ + GstD3D11WindowPrivate *priv = self->priv; + + if (priv->d2d_device_context) { + priv->d2d_device_context->Release (); + priv->d2d_device_context = NULL; + } + + if (priv->d2d_factory) { + priv->d2d_factory->Release (); + priv->d2d_factory = NULL; + } + + if (priv->d2d_device) { + priv->d2d_device->Release (); + priv->d2d_device = NULL; + } + + if (priv->d2d_brush) { + priv->d2d_brush->Release (); + priv->d2d_brush = NULL; + } + + if (priv->dwrite_factory) { + priv->dwrite_factory->Release (); + priv->dwrite_factory = NULL; + } + + if (priv->dwrite_format) { + priv->dwrite_format->Release (); + priv->dwrite_format = NULL; + } +} + +static void +gst_d3d11_window_prepare_dwrite_device (GstD3D11Window * self) +{ + GstD3D11WindowPrivate *priv = self->priv; + HRESULT hr; + ComPtr dxgi_device; + ID3D11Device *device_handle; + + if (!self->device) { + GST_ERROR_OBJECT (self, "D3D11Device is unavailable"); + return; + } + + /* Already prepared */ + if (priv->d2d_device) + return; + + hr = D2D1CreateFactory (D2D1_FACTORY_TYPE_MULTI_THREADED, + IID_PPV_ARGS (&priv->d2d_factory)); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + device_handle = gst_d3d11_device_get_device_handle (self->device); + hr = device_handle->QueryInterface (IID_PPV_ARGS (&dxgi_device)); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + hr = priv->d2d_factory->CreateDevice (dxgi_device.Get (), &priv->d2d_device); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + hr = priv->d2d_device->CreateDeviceContext (D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, + &priv->d2d_device_context); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + hr = priv->d2d_device_context->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Yellow), + &priv->d2d_brush); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, + __uuidof (IDWriteFactory), (IUnknown **) &priv->dwrite_factory); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + /* Configure font */ + hr = priv->dwrite_factory->CreateTextFormat(L"Arial", NULL, + DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, 12.0f, L"en-US", &priv->dwrite_format); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + GST_DEBUG_OBJECT (self, "Direct2D device is prepared"); + + return; + +error: + gst_d3d11_window_release_dwrite_resources (self); +} + +static void +gst_d3d11_window_dwrite_on_resize (GstD3D11Window * self, + ID3D11Texture2D * backbuffer) +{ + GstD3D11WindowPrivate *priv = self->priv; + ComPtr dxgi_surface; + ComPtr bitmap; + D2D1_BITMAP_PROPERTIES1 prop; + HRESULT hr; + + if (!priv->d2d_device) + return; + + prop.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + prop.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + /* default dpi */ + prop.dpiX = 96.0f; + prop.dpiY = 96.0f; + prop.bitmapOptions = + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; + prop.colorContext = NULL; + + hr = backbuffer->QueryInterface (IID_PPV_ARGS (&dxgi_surface)); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + hr = priv->d2d_device_context->CreateBitmapFromDxgiSurface (dxgi_surface.Get (), + &prop, &bitmap); + if (!gst_d3d11_result (hr, self->device)) + goto error; + + priv->d2d_device_context->SetTarget (bitmap.Get ()); + + GST_LOG_OBJECT (self, "New D2D bitmap has been configured"); + + return; + +error: + gst_d3d11_window_release_dwrite_resources (self); +} + +#endif + static void gst_d3d11_window_release_resources (GstD3D11Device * device, GstD3D11Window * window) { +#ifdef HAVE_DIRECT_WRITE + gst_d3d11_window_release_dwrite_resources (window); +#endif + if (window->rtv) { window->rtv->Release (); window->rtv = NULL; @@ -287,6 +476,9 @@ static void gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width, guint height) { +#ifdef HAVE_DIRECT_WRITE + GstD3D11WindowPrivate *priv = window->priv; +#endif HRESULT hr; ID3D11Device *device_handle; D3D11_TEXTURE2D_DESC desc; @@ -312,6 +504,12 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width, window->pov = NULL; } +#ifdef HAVE_DIRECT_WRITE + /* D2D bitmap need to be cleared before resizing swapchain buffer */ + if (priv->d2d_device_context) + priv->d2d_device_context->SetTarget (NULL); +#endif + swap_chain->GetDesc (&swap_desc); hr = swap_chain->ResizeBuffers (0, width, height, window->dxgi_format, swap_desc.Flags); @@ -378,10 +576,15 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * window, guint width, goto done; } +#ifdef HAVE_DIRECT_WRITE + if (window->render_stats) + gst_d3d11_window_dwrite_on_resize (window, backbuffer); +#endif + window->first_present = TRUE; /* redraw the last scene if cached buffer exits */ - gst_d3d111_window_present (window, NULL); + gst_d3d111_window_present (window, NULL, NULL); done: if (backbuffer) @@ -489,14 +692,23 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width, return FALSE; } - for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) { - if (GST_VIDEO_INFO_COMP_DEPTH (&window->info, i) > 8) { - if (formats[2].supported) { - chosen_format = &formats[2]; +#ifdef HAVE_DIRECT_WRITE + if (window->render_stats && formats[1].supported) { + /* FIXME: D2D seems to be accepting only DXGI_FORMAT_B8G8R8A8_UNORM */ + chosen_format = &formats[1]; + } else +#else + { + for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&window->info); i++) { + if (GST_VIDEO_INFO_COMP_DEPTH (&window->info, i) > 8) { + if (formats[2].supported) { + chosen_format = &formats[2]; + } + break; } - break; } } +#endif if (!chosen_format) { /* prefer native format over conversion */ @@ -745,6 +957,11 @@ gst_d3d11_window_prepare (GstD3D11Window * window, guint display_width, "Cannot create overlay compositor"); goto error; } + +#ifdef HAVE_DIRECT_WRITE + if (window->render_stats) + gst_d3d11_window_prepare_dwrite_device (window); +#endif gst_d3d11_device_unlock (window->device); /* call resize to allocated resources */ @@ -815,8 +1032,60 @@ gst_d3d11_window_buffer_ensure_processor_input (GstD3D11Window * self, return TRUE; } +#ifdef HAVE_DIRECT_WRITE +static void +gst_d3d11_window_present_d2d (GstD3D11Window * self, GstStructure * stats) +{ + GstD3D11WindowPrivate *priv = self->priv; + HRESULT hr; + gdouble framerate = 0.0; + guint64 dropped = 0; + guint64 rendered = 0; + std::wostringstream stats_str; + ComPtr layout; + FLOAT left; + FLOAT top; + + if (!priv->d2d_device) + return; + + if (!stats) + return; + + gst_structure_get_double (stats, "average-rate", &framerate); + gst_structure_get_uint64 (stats, "dropped", &dropped); + gst_structure_get_uint64 (stats, "rendered", &rendered); + + stats_str.precision (5); + stats_str << "Average-rate: " << framerate << std::endl; + stats_str << "Dropped: " << dropped << std::endl; + stats_str << "Rendered: " << rendered << std::endl; + + hr = priv->dwrite_factory->CreateTextLayout (stats_str.str().c_str(), + (UINT32) stats_str.str().size(), priv->dwrite_format, + self->render_rect.right - self->render_rect.left, + self->render_rect.bottom - self->render_rect.top, + &layout); + if (!gst_d3d11_result (hr, self->device)) + return; + + left = self->render_rect.left + 5.0f; + top = self->render_rect.top + 5.0f; + + priv->d2d_device_context->BeginDraw (); + priv->d2d_device_context->DrawTextLayout(D2D1::Point2F(left, top), + layout.Get(), priv->d2d_brush); + + hr = priv->d2d_device_context->EndDraw (); + gst_d3d11_result (hr, self->device); + + return; +} +#endif + static GstFlowReturn -gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) +gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer, + GstStructure * stats) { GstD3D11WindowClass *klass = GST_D3D11_WINDOW_GET_CLASS (self); GstFlowReturn ret = GST_FLOW_OK; @@ -885,6 +1154,10 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) } #endif +#if HAVE_DIRECT_WRITE + gst_d3d11_window_present_d2d (self, stats); +#endif + ret = klass->present (self, present_flags); self->first_present = FALSE; @@ -895,7 +1168,7 @@ gst_d3d111_window_present (GstD3D11Window * self, GstBuffer * buffer) GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer, - GstVideoRectangle * rect) + GstVideoRectangle * rect, GstStructure * stats) { GstMemory *mem; GstFlowReturn ret; @@ -907,13 +1180,19 @@ gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer, if (!gst_is_d3d11_memory (mem)) { GST_ERROR_OBJECT (window, "Invalid buffer"); + if (stats) + gst_structure_free (stats); + return GST_FLOW_ERROR; } gst_d3d11_device_lock (window->device); - ret = gst_d3d111_window_present (window, buffer); + ret = gst_d3d111_window_present (window, buffer, stats); gst_d3d11_device_unlock (window->device); + if (stats) + gst_structure_free (stats); + return ret; } diff --git a/sys/d3d11/gstd3d11window.h b/sys/d3d11/gstd3d11window.h index 6ca6024..c72d9d7 100644 --- a/sys/d3d11/gstd3d11window.h +++ b/sys/d3d11/gstd3d11window.h @@ -41,6 +41,7 @@ G_BEGIN_DECLS typedef struct _GstD3D11Window GstD3D11Window; typedef struct _GstD3D11WindowClass GstD3D11WindowClass; +typedef struct _GstD3D11WindowPrivate GstD3D11WindowPrivate; #define GST_D3D11_WINDOW_FLOW_CLOSED GST_FLOW_CUSTOM_ERROR @@ -76,6 +77,7 @@ struct _GstD3D11Window GstD3D11WindowFullscreenToggleMode fullscreen_toggle_mode; gboolean requested_fullscreen; gboolean fullscreen; + gboolean render_stats; GstVideoInfo info; GstVideoInfo render_info; @@ -103,6 +105,8 @@ struct _GstD3D11Window GstBuffer *cached_buffer; gboolean first_present; gboolean allow_tearing; + + GstD3D11WindowPrivate *priv; }; struct _GstD3D11WindowClass @@ -153,7 +157,8 @@ gboolean gst_d3d11_window_prepare (GstD3D11Window * window, GstFlowReturn gst_d3d11_window_render (GstD3D11Window * window, GstBuffer * buffer, - GstVideoRectangle * src_rect); + GstVideoRectangle * src_rect, + GstStructure * stats); gboolean gst_d3d11_window_unlock (GstD3D11Window * window); diff --git a/sys/d3d11/meson.build b/sys/d3d11/meson.build index c88a4a6..2ba72f3 100644 --- a/sys/d3d11/meson.build +++ b/sys/d3d11/meson.build @@ -65,6 +65,8 @@ d3d11_lib = cc.find_library('d3d11', required : d3d11_option) dxgi_lib = cc.find_library('dxgi', required : d3d11_option) d3dcompiler_lib = cc.find_library('d3dcompiler', required: d3d11_option) runtimeobject_lib = cc.find_library('runtimeobject', required : false) +dwrite_lib = cc.find_library('dwrite', required : false) +d2d1_lib = cc.find_library('d2d1', required : false) foreach dxgi_h: dxgi_headers if not have_dxgi_header and cc.has_header(dxgi_h[0]) @@ -177,6 +179,15 @@ if get_option('debug') and not (winapi_app_only and get_option('b_vscrt') == 'md set_variable(f.get(3), true) endif endforeach + + # Maybe we want to implement DirectWrite based text rendering in the future, + # but currently only debugging purpose. + # Also, MinGW is not supported for now because of toolchain issue + if cc.get_id() == 'msvc' and dwrite_lib.found() and d2d1_lib.found() and cc.has_header('dwrite.h') and cc.has_header('d2d1_1.h') + d3d11_conf.set('HAVE_DIRECT_WRITE', 1) + extra_dep += [dwrite_lib, d2d1_lib] + message('Enable DirectWrite support in D3D11 plugin') + endif else message('Disable D3D11Debug and DXGIDebug layers') endif -- 2.7.4