From a80e10ac5c85107592da3ce327d7739415cc9cb7 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Thu, 22 Sep 2016 16:34:38 +0900 Subject: [PATCH] libs: display{egl,glx}: cache GstVaapiTextures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit instances when created and reuse This patch improves performance when glimagesink uploads a GL texture. It caches the GStVaapiTexture instances in GstVaapiDisplay{GLX,EGL}, using an instance of GstVaapiTextureMap, so our internal texture structure can be found by matching the GL texture id for each frame upload process, avoiding the internal texture structure creation and its following destruction. https://bugzilla.gnome.org/show_bug.cgi?id=769293 Signed-off-by: Víctor Manuel Jáquez Leal --- gst-libs/gst/vaapi/gstvaapidisplay.c | 26 ++++++++++ gst-libs/gst/vaapi/gstvaapidisplay.h | 3 ++ gst-libs/gst/vaapi/gstvaapidisplay_egl.c | 48 +++++++++++++++++-- gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h | 3 ++ gst-libs/gst/vaapi/gstvaapidisplay_glx.c | 46 ++++++++++++++++-- gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h | 3 ++ gst-libs/gst/vaapi/gstvaapidisplay_priv.h | 4 ++ gst/vaapi/gstvaapivideometa_texture.c | 24 ++++++---- 8 files changed, 142 insertions(+), 15 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.c b/gst-libs/gst/vaapi/gstvaapidisplay.c index a733423dbe..32738a116e 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay.c +++ b/gst-libs/gst/vaapi/gstvaapidisplay.c @@ -32,6 +32,7 @@ #include "gstvaapiutils.h" #include "gstvaapivalue.h" #include "gstvaapidisplay.h" +#include "gstvaapitexturemap.h" #include "gstvaapidisplay_priv.h" #include "gstvaapiworkarounds.h" #include "gstvaapiversion.h" @@ -2149,3 +2150,28 @@ gst_vaapi_display_has_opengl (GstVaapiDisplay * display) return (klass->display_type == GST_VAAPI_DISPLAY_TYPE_GLX || klass->display_type == GST_VAAPI_DISPLAY_TYPE_EGL); } + +/** + * gst_vaapi_display_reset_texture_map: + * @display: a #GstVaapiDisplay + * + * Reset the internal #GstVaapiTextureMap if available. + * + * This function is thread safe. + */ +void +gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display) +{ + GstVaapiDisplayClass *klass; + GstVaapiTextureMap *map; + + g_return_if_fail (display != NULL); + + if (!gst_vaapi_display_has_opengl (display)) + return; + klass = GST_VAAPI_DISPLAY_GET_CLASS (display); + if (!klass->get_texture_map) + return; + if ((map = klass->get_texture_map (display))) + gst_vaapi_texture_map_reset (map); +} diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.h b/gst-libs/gst/vaapi/gstvaapidisplay.h index f4cc8653d9..600f276eca 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay.h +++ b/gst-libs/gst/vaapi/gstvaapidisplay.h @@ -257,6 +257,9 @@ gst_vaapi_display_get_vendor_string (GstVaapiDisplay * display); gboolean gst_vaapi_display_has_opengl (GstVaapiDisplay * display); +void +gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display); + G_END_DECLS #endif /* GST_VAAPI_DISPLAY_H */ diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_egl.c b/gst-libs/gst/vaapi/gstvaapidisplay_egl.c index feab6408fb..f049de98ca 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay_egl.c +++ b/gst-libs/gst/vaapi/gstvaapidisplay_egl.c @@ -232,14 +232,49 @@ gst_vaapi_display_egl_create_window (GstVaapiDisplay * display, GstVaapiID id, return gst_vaapi_window_egl_new (display, width, height); } +static void +ensure_texture_map (GstVaapiDisplayEGL * display) +{ + if (!display->texture_map) + display->texture_map = gst_vaapi_texture_map_new (); +} + static GstVaapiTexture * gst_vaapi_display_egl_create_texture (GstVaapiDisplay * display, GstVaapiID id, guint target, guint format, guint width, guint height) { - if (id != GST_VAAPI_ID_INVALID) - return gst_vaapi_texture_egl_new_wrapped (display, id, target, format, - width, height); - return gst_vaapi_texture_egl_new (display, target, format, width, height); + GstVaapiDisplayEGL *dpy = GST_VAAPI_DISPLAY_EGL (display); + GstVaapiTexture *texture; + + if (id == GST_VAAPI_ID_INVALID) + return gst_vaapi_texture_egl_new (display, target, format, width, height); + + ensure_texture_map (dpy); + if (!(texture = gst_vaapi_texture_map_lookup (dpy->texture_map, id))) { + if ((texture = + gst_vaapi_texture_egl_new_wrapped (display, id, target, format, + width, height))) { + gst_vaapi_texture_map_add (dpy->texture_map, texture, id); + } + } + + return texture; +} + +static GstVaapiTextureMap * +gst_vaapi_display_egl_get_texture_map (GstVaapiDisplay * display) +{ + return GST_VAAPI_DISPLAY_EGL (display)->texture_map; +} + +static void +gst_vaapi_display_egl_finalize (GstVaapiDisplay * display) +{ + GstVaapiDisplayEGL *dpy = GST_VAAPI_DISPLAY_EGL (display); + + if (dpy->texture_map) + gst_object_unref (dpy->texture_map); + GST_VAAPI_DISPLAY_EGL_GET_CLASS (display)->parent_finalize (display); } static void @@ -254,6 +289,10 @@ gst_vaapi_display_egl_class_init (GstVaapiDisplayEGLClass * klass) gst_vaapi_display_class_init (dpy_class); + /* chain up destructor */ + klass->parent_finalize = object_class->finalize; + object_class->finalize = (GDestroyNotify) gst_vaapi_display_egl_finalize; + object_class->size = sizeof (GstVaapiDisplayEGL); dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_EGL; dpy_class->bind_display = (GstVaapiDisplayBindFunc) @@ -280,6 +319,7 @@ gst_vaapi_display_egl_class_init (GstVaapiDisplayEGLClass * klass) gst_vaapi_display_egl_create_window; dpy_class->create_texture = (GstVaapiDisplayCreateTextureFunc) gst_vaapi_display_egl_create_texture; + dpy_class->get_texture_map = gst_vaapi_display_egl_get_texture_map; } static inline const GstVaapiDisplayClass * diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h index 3db5ad8980..96e2b43b85 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h @@ -24,6 +24,7 @@ #define GST_VAAPI_DISPLAY_EGL_PRIV_H #include +#include #include "gstvaapidisplay_egl.h" #include "gstvaapidisplay_priv.h" #include "gstvaapiutils_egl.h" @@ -79,6 +80,7 @@ struct _GstVaapiDisplayEGL EglDisplay *egl_display; EglContext *egl_context; guint gles_version; + GstVaapiTextureMap *texture_map; }; /** @@ -90,6 +92,7 @@ struct _GstVaapiDisplayEGLClass { /*< private >*/ GstVaapiDisplayClass parent_class; + GDestroyNotify parent_finalize; }; G_GNUC_INTERNAL diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx.c b/gst-libs/gst/vaapi/gstvaapidisplay_glx.c index 32aa714113..9b4a007cbc 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay_glx.c +++ b/gst-libs/gst/vaapi/gstvaapidisplay_glx.c @@ -50,13 +50,48 @@ gst_vaapi_display_glx_create_window (GstVaapiDisplay * display, GstVaapiID id, gst_vaapi_window_glx_new (display, width, height); } +static void +ensure_texture_map (GstVaapiDisplayGLX * display) +{ + if (!display->texture_map) + display->texture_map = gst_vaapi_texture_map_new (); +} + static GstVaapiTexture * gst_vaapi_display_glx_create_texture (GstVaapiDisplay * display, GstVaapiID id, guint target, guint format, guint width, guint height) { - return id != GST_VAAPI_ID_INVALID ? - gst_vaapi_texture_glx_new_wrapped (display, id, target, format) : - gst_vaapi_texture_glx_new (display, target, format, width, height); + GstVaapiTexture *texture; + GstVaapiDisplayGLX *dpy = GST_VAAPI_DISPLAY_GLX (display); + + if (id == GST_VAAPI_ID_INVALID) + return gst_vaapi_texture_glx_new (display, target, format, width, height); + + ensure_texture_map (dpy); + if (!(texture = gst_vaapi_texture_map_lookup (dpy->texture_map, id))) { + if ((texture = + gst_vaapi_texture_glx_new_wrapped (display, id, target, format))) { + gst_vaapi_texture_map_add (dpy->texture_map, texture, id); + } + } + + return texture; +} + +static GstVaapiTextureMap * +gst_vaapi_display_glx_get_texture_map (GstVaapiDisplay * display) +{ + return GST_VAAPI_DISPLAY_GLX (display)->texture_map; +} + +static void +gst_vaapi_display_glx_finalize (GstVaapiDisplay * display) +{ + GstVaapiDisplayGLX *dpy = GST_VAAPI_DISPLAY_GLX (display); + + if (dpy->texture_map) + gst_object_unref (dpy->texture_map); + GST_VAAPI_DISPLAY_GLX_GET_CLASS (display)->parent_finalize (display); } static void @@ -68,10 +103,15 @@ gst_vaapi_display_glx_class_init (GstVaapiDisplayGLXClass * klass) gst_vaapi_display_x11_class_init (&klass->parent_class); + /* chain up destructor */ + klass->parent_finalize = object_class->finalize; + object_class->finalize = (GDestroyNotify) gst_vaapi_display_glx_finalize; + object_class->size = sizeof (GstVaapiDisplayGLX); dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_GLX; dpy_class->create_window = gst_vaapi_display_glx_create_window; dpy_class->create_texture = gst_vaapi_display_glx_create_texture; + dpy_class->get_texture_map = gst_vaapi_display_glx_get_texture_map; } static inline const GstVaapiDisplayClass * diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h index 63f7175ce7..4da88228a6 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidisplay_glx_priv.h @@ -25,6 +25,7 @@ #include #include +#include #include "gstvaapidisplay_x11_priv.h" G_BEGIN_DECLS @@ -53,6 +54,7 @@ struct _GstVaapiDisplayGLX { /*< private >*/ GstVaapiDisplayX11 parent_instance; + GstVaapiTextureMap *texture_map; }; /** @@ -64,6 +66,7 @@ struct _GstVaapiDisplayGLXClass { /*< private >*/ GstVaapiDisplayX11Class parent_class; + GDestroyNotify parent_finalize; }; G_END_DECLS diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_priv.h index fd50fe79e2..12b5184bfe 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay_priv.h +++ b/gst-libs/gst/vaapi/gstvaapidisplay_priv.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "gstvaapiminiobject.h" G_BEGIN_DECLS @@ -73,6 +74,8 @@ typedef GstVaapiWindow *(*GstVaapiDisplayCreateWindowFunc) ( typedef GstVaapiTexture *(*GstVaapiDisplayCreateTextureFunc) ( GstVaapiDisplay * display, GstVaapiID id, guint target, guint format, guint width, guint height); +typedef GstVaapiTextureMap *(*GstVaapiDisplayGetTextureMapFunc) ( + GstVaapiDisplay * display); typedef guintptr (*GstVaapiDisplayGetVisualIdFunc) (GstVaapiDisplay * display, GstVaapiWindow * window); @@ -226,6 +229,7 @@ struct _GstVaapiDisplayClass GstVaapiDisplayGetColormapFunc get_colormap; GstVaapiDisplayCreateWindowFunc create_window; GstVaapiDisplayCreateTextureFunc create_texture; + GstVaapiDisplayGetTextureMapFunc get_texture_map; }; /* Initialization types */ diff --git a/gst/vaapi/gstvaapivideometa_texture.c b/gst/vaapi/gstvaapivideometa_texture.c index 01e33852fd..fb1535a760 100644 --- a/gst/vaapi/gstvaapivideometa_texture.c +++ b/gst/vaapi/gstvaapivideometa_texture.c @@ -176,26 +176,34 @@ gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta, gst_vaapi_video_meta_get_surface_proxy (vmeta); GstVaapiSurface *const surface = gst_vaapi_surface_proxy_get_surface (proxy); GstVaapiDisplay *const dpy = GST_VAAPI_OBJECT_DISPLAY (surface); + GstVaapiTexture *texture = NULL; if (!gst_vaapi_display_has_opengl (dpy)) return FALSE; - if (!meta_texture->texture || + if (meta_texture->texture /* Check whether VA display changed */ - GST_VAAPI_OBJECT_DISPLAY (meta_texture->texture) != dpy || + && GST_VAAPI_OBJECT_DISPLAY (meta_texture->texture) == dpy /* Check whether texture id changed */ - gst_vaapi_texture_get_id (meta_texture->texture) != texture_id[0]) { + && (gst_vaapi_texture_get_id (meta_texture->texture) == texture_id[0])) { + texture = meta_texture->texture; + } + + if (!texture) { /* FIXME: should we assume target? */ - GstVaapiTexture *const texture = + texture = gst_vaapi_texture_new_wrapped (dpy, texture_id[0], GL_TEXTURE_2D, meta_texture->gl_format, meta_texture->width, meta_texture->height); - gst_vaapi_texture_replace (&meta_texture->texture, texture); - if (!texture) - return FALSE; - gst_vaapi_texture_unref (texture); } + if (meta_texture->texture != texture) { + gst_vaapi_texture_replace (&meta_texture->texture, texture); + } + + if (!texture) + return FALSE; + gst_vaapi_texture_set_orientation_flags (meta_texture->texture, get_texture_orientation_flags (meta->texture_orientation));