diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.c b/gst-libs/gst/vaapi/gstvaapidisplay.c
index a733423..c58bc79 100644
--- a/gst-libs/gst/vaapi/gstvaapidisplay.c
+++ b/gst-libs/gst/vaapi/gstvaapidisplay.c
@@ -870,6 +870,11 @@ gst_vaapi_display_destroy (GstVaapiDisplay * display)
   g_free (priv->vendor_string);
   priv->vendor_string = NULL;
 
+  if (priv->texture_table) {
+    gst_vaapi_display_remove_all_textures (display);
+    g_hash_table_destroy (priv->texture_table);
+  }
+
   gst_vaapi_display_replace_internal (&priv->parent, NULL);
 
   if (priv->cache) {
@@ -1004,6 +1009,10 @@ gst_vaapi_display_init (GstVaapiDisplay * display)
 
   g_rec_mutex_init (&priv->mutex);
 
+  priv->texture_table =
+      g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+      (GDestroyNotify) gst_vaapi_texture_unref);
+
   if (dpy_class->init)
     dpy_class->init (display);
 }
@@ -2149,3 +2158,33 @@ gst_vaapi_display_has_opengl (GstVaapiDisplay * display)
   return (klass->display_type == GST_VAAPI_DISPLAY_TYPE_GLX ||
       klass->display_type == GST_VAAPI_DISPLAY_TYPE_EGL);
 }
+
+gpointer
+gst_vaapi_display_create_texture (GstVaapiDisplay * display, guint id,
+    guint target, guint format, guint width, guint height)
+{
+  GstVaapiTexture *texture;
+  GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
+
+  texture =
+      gst_vaapi_texture_new_wrapped (display, id, target, format, width,
+      height);
+  g_hash_table_insert (priv->texture_table, GUINT_TO_POINTER (id), texture);
+
+  return (gpointer) texture;
+}
+
+void
+gst_vaapi_display_remove_all_textures (GstVaapiDisplay * display)
+{
+  GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
+  g_hash_table_remove_all (priv->texture_table);
+}
+
+gpointer
+gst_vaapi_display_texture_lookup (GstVaapiDisplay * display, guint id)
+{
+  GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
+
+  return g_hash_table_lookup (priv->texture_table, GUINT_TO_POINTER (id));
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.h b/gst-libs/gst/vaapi/gstvaapidisplay.h
index f4cc865..37fcd41 100644
--- a/gst-libs/gst/vaapi/gstvaapidisplay.h
+++ b/gst-libs/gst/vaapi/gstvaapidisplay.h
@@ -257,6 +257,15 @@ gst_vaapi_display_get_vendor_string (GstVaapiDisplay * display);
 gboolean
 gst_vaapi_display_has_opengl (GstVaapiDisplay * display);
 
+gpointer
+gst_vaapi_display_create_texture (GstVaapiDisplay * display, guint id, guint target, guint format, guint width, guint height);
+
+void
+gst_vaapi_display_remove_all_textures (GstVaapiDisplay * display);
+
+gpointer
+gst_vaapi_display_texture_lookup (GstVaapiDisplay * display, guint id);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_DISPLAY_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_priv.h
index fd50fe7..cb952ab 100644
--- a/gst-libs/gst/vaapi/gstvaapidisplay_priv.h
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_priv.h
@@ -169,6 +169,7 @@ struct _GstVaapiDisplayPrivate
   guint use_foreign_display:1;
   guint has_vpp:1;
   guint has_profiles:1;
+  GHashTable *texture_table;
 };
 
 /**
diff --git a/gst/vaapi/gstvaapivideometa_texture.c b/gst/vaapi/gstvaapivideometa_texture.c
index 01e3385..598ecaa 100644
--- a/gst/vaapi/gstvaapivideometa_texture.c
+++ b/gst/vaapi/gstvaapivideometa_texture.c
@@ -176,30 +176,32 @@ 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;
 
   if (!gst_vaapi_display_has_opengl (dpy))
     return FALSE;
 
-  if (!meta_texture->texture ||
-      /* Check whether VA display changed */
-      GST_VAAPI_OBJECT_DISPLAY (meta_texture->texture) != dpy ||
-      /* Check whether texture id changed */
-      gst_vaapi_texture_get_id (meta_texture->texture) != texture_id[0]) {
-    /* FIXME: should we assume target? */
-    GstVaapiTexture *const 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);
+  texture = (GstVaapiTexture *) gst_vaapi_display_texture_lookup (dpy,
+      texture_id[0]);
+
+  if (texture && GST_VAAPI_OBJECT_DISPLAY (texture) != dpy) {
+    gst_vaapi_display_remove_all_textures (dpy);
+    texture = NULL;
   }
 
-  gst_vaapi_texture_set_orientation_flags (meta_texture->texture,
+  if (!texture)
+    texture =
+        (GstVaapiTexture *) gst_vaapi_display_create_texture (dpy,
+        texture_id[0], GL_TEXTURE_2D, meta_texture->gl_format,
+        meta_texture->width, meta_texture->height);
+
+  if (!texture)
+    return FALSE;
+
+  gst_vaapi_texture_set_orientation_flags (texture,
       get_texture_orientation_flags (meta->texture_orientation));
 
-  return gst_vaapi_texture_put_surface (meta_texture->texture, surface,
+  return gst_vaapi_texture_put_surface (texture, surface,
       gst_vaapi_surface_proxy_get_crop_rect (proxy),
       gst_vaapi_video_meta_get_render_flags (vmeta));
 }
