After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 749411 - glcontext_egl should call eglTerminate to free resources for non EGL DISPLAY types
glcontext_egl should call eglTerminate to free resources for non EGL DISPLAY ...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
1.4.5
Other Linux
: Normal normal
: 1.5.1
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2015-05-15 06:06 UTC by Jian Li
Modified: 2015-05-26 02:58 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch (1.18 KB, patch)
2015-05-15 06:06 UTC, Jian Li
none Details | Review

Description Jian Li 2015-05-15 06:06:01 UTC
Created attachment 303402 [details] [review]
patch

We found memory leak in wayland, x11 backend with glimagesink, then found eglTerminate isn't called in egl context for non GST_GL_DISPLAY_TYPE_EGL types.

Here is the patch for fixing, please help review it.
Comment 1 Matthew Waters (ystreet00) 2015-05-17 05:45:07 UTC
destroy_context is not the correct place to call eglTerminate.  What if you have multiple GL contexts? They will all fail in some way from the eglTerminate call.

This should be done in a GstGLDisplayEGL class that the egl using window systems' GstGLDisplay (wayland/x11/rpi/etc) would hold a reference to. Then it would be possible to differentiate between an EGLDisplay and a winsys display as well as get the EGLDisplay from a winsys GstGLDisplay.
Comment 2 Jian Li 2015-05-18 05:37:10 UTC
Please note this eglTerminate only be called when the display type is not GST_GL_DISPLAY_TYPE_EGL, say the egl_display is created in this context, so this case means each egl context should have it's own egl display. 
I noticed both x11 and wayland backend go into this case.
Comment 3 Matthew Waters (ystreet00) 2015-05-18 09:31:10 UTC
That may be the case however calling eglTerminate while there's a possibility of there being another user of that display will cause problems.  As we don't know exactly how the native display -> EGLDisplay eglGetDisplay() is implemented (maybe a simple mapping or it might return new EGLDisplay's for each call), we cannot terminate access to an EGLDisplay without knowing nobody is currently using it.

See my comment above on how this should be solved.
Comment 4 Jian Li 2015-05-19 02:56:39 UTC
This is not the display sharing case, it will create a egl_display in gst_gl_context_egl_create_context() if it's not GST_GL_DISPLAY_TYPE_EGL type, see below code, this means one context will have it's own egl_display, shall it release the resources when this context is destroyed?

  if (display->type == GST_GL_DISPLAY_TYPE_EGL) {
    egl->egl_display = (EGLDisplay) gst_gl_display_get_handle (display);
  } else {
    guintptr native_display = gst_gl_display_get_handle (display);

    if (!native_display) {
      GstGLWindow *window = NULL;
      GST_WARNING ("Failed to get a global display handle, falling back to "
          "per-window display handles.  Context sharing may not work");

      if (other_context)
        window = gst_gl_context_get_window (other_context);
      if (!window)
        window = gst_gl_context_get_window (context);
      if (window) {
        native_display = gst_gl_window_get_display (window);
        gst_object_unref (window);
      }
    }

    egl->egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display);
  }
Comment 5 Matthew Waters (ystreet00) 2015-05-19 05:16:26 UTC
(In reply to Jian Li from comment #4)
> This is not the display sharing case

That may be true/false according to the EGL implementation.

As I said above, we don't know how eglGetDisplay is implemented and the spec being unclear about this issue, calling eglTerminate on an EGLDisplay that has been eglGetDisplay-ed multiple times with the same native display could cause problems for the other GL contexts.  

I'd be happy to be proved wrong across all the EGL implementation out there (Android, Mesa, NVIDIA, AMD, X11, Wayland, WinCE?, rpi, Mali, etc) however see above for how this reference stuff should be solved.
Comment 6 Jian Li 2015-05-19 06:30:24 UTC
I got your point.

You mean eglTerminate will impact other connections with the eglDisplay? I believe it only releases resources of current eglDisplay connection.

I think eglTerminate is used to free the resources allocated in eglInitialize, not for eglGetDisplay, see below from spec:
https://www.khronos.org/registry/egl/sdk/docs/man/

eglGetDisplay obtains the EGL display connection for the native display native_display.
Use eglInitialize to initialize the display connection.

eglInitialize initialized the EGL display connection obtained with eglGetDisplay. 
Use eglTerminate to release resources associated with an EGL display connection.

Not sure if my understanding is correct.
Comment 7 Matthew Waters (ystreet00) 2015-05-21 05:20:35 UTC
eglTerminate attempts to release *any* resource associated with the EGLDisplay connection (or at least marks for deletion and freed when they are not used).  That being *any* EGLSurface/pbuffer/EGLImage?/EGLConfig or eglInitialize()ed, etc objects.
Comment 8 Jian Li 2015-05-22 07:08:00 UTC
So would this be solved if create a egl display with gst_gl_display_egl_new() rather than create a dummy display for wayland? This will make all the egl context share the same display. Why wayland used a dummy display in gst_gl_display_new()?

And I personal don't believe terminate one eglDisplay will impact other eglDisplay connection. Think about if I run two opengl applications at the same time, they all will get a eglDisplay each when start. If eglTerminate will impact other display connections, one application quit will cause another application has problem.
Comment 9 Matthew Waters (ystreet00) 2015-05-22 07:50:50 UTC
(In reply to Jian Li from comment #8)
> So would this be solved if create a egl display with
> gst_gl_display_egl_new() rather than create a dummy display for wayland?
> This will make all the egl context share the same display. Why wayland used
> a dummy display in gst_gl_display_new()?

Wayland needs its own GstGLDisplay subclass for other reasons.

See https://bugzilla.gnome.org/show_bug.cgi?id=709747

> And I personal don't believe terminate one eglDisplay will impact other
> eglDisplay connection.

They don't.

> Think about if I run two opengl applications at the
> same time, they all will get a eglDisplay each when start. If eglTerminate
> will impact other display connections, one application quit will cause
> another application has problem.

Different OpenGL applications are in different process spaces entirely.

Think about it like this.

The question is whether (eglGetDisplay (native_display) == eglGetDisplay (native_display)). OR in words, across two invocations of eglGetDisplay are the returned EGLDisplay's the same for the same input native display handle.  The spec is unclear therefore we cannot assume that they are or aren't.
Comment 10 Jian Li 2015-05-25 07:51:10 UTC
So the solution is to create a gldisplay_wayland class, move wayland display from window_wayland_egl to this class, and do eglGetDisplay and eglTerminate based on the reference count? When create egl context, it will get the egl display from this class directly.

I see there is GST_GL_DISPLAY_TYPE_WAYLAND defined, but no implementation.
Comment 11 Matthew Waters (ystreet00) 2015-05-25 08:09:10 UTC
commit 2704fdaa590b510316a0be1a4a41a7d77cada1ef
Author: Matthew Waters <matthew@centricular.com>
Date:   Thu May 21 17:48:31 2015 +1000

    gl/wayland: add GstGLDisplayWayland
    
    Simple implementation split from GstGLWindowWayland
    
    Can now have multiple glimagesink elements all displaying output
    linked via GL or otherwise (barring GL platform limitations).
    
    The intel driver is racy and can crash setting up the two glimagesink contexts.
    
    e.g.
    videotestsrc ! tee name=t ! queue ! glupload ! glimagesinkelement
      t. ! queue ! gleffects_blur ! glimagesinkelement
    
    videotestsrc ! glupload ! glfiltercube ! tee name=t ! queue ! glimagesinkelement
      t. ! queue ! gleffects_blur ! glimagesinkelement
Comment 12 Matthew Waters (ystreet00) 2015-05-25 08:16:59 UTC
(In reply to Jian Li from comment #10)
> So the solution is to create a gldisplay_wayland class, move wayland display
> from window_wayland_egl to this class, and do eglGetDisplay and eglTerminate
> based on the reference count? When create egl context, it will get the egl
> display from this class directly.

Something like that.  It might make more sense to have some kind of interface for that or maybe just a place to store related data on the GstGLDisplay (a GstStructure?).
Comment 13 Jian Li 2015-05-25 10:13:46 UTC
With this patch, I think we don't need to call eglTerminate. The whole process will share the same display, so there is only one display connection. When process quit, it will free the resources automatically, correct?

Actually I don't know where to call this eglTerminate with current code structure. If move eglGetDisplay into GstGLDisplayWayland, this will change the returned display to egl display, not wayland display.
Comment 14 Matthew Waters (ystreet00) 2015-05-25 10:19:08 UTC
(In reply to Jian Li from comment #13)
> With this patch, I think we don't need to call eglTerminate. The whole
> process will share the same display, so there is only one display
> connection. When process quit, it will free the resources automatically,
> correct?

The whole process was sharing the same display before, just through GstGLWindow instead of GstGLDisplay.  It's still advisable to call eglTerminate when you're done with EGL resources so you don't leak.

> Actually I don't know where to call this eglTerminate with current code
> structure. If move eglGetDisplay into GstGLDisplayWayland, this will change
> the returned display to egl display, not wayland display.

Yes, we need both native display and eglDisplay which is where the interface/GstStructure comes in.
Comment 15 Jian Li 2015-05-26 02:39:24 UTC
(In reply to Matthew Waters from comment #14)
> (In reply to Jian Li from comment #13)
> > With this patch, I think we don't need to call eglTerminate. The whole
> > process will share the same display, so there is only one display
> > connection. When process quit, it will free the resources automatically,
> > correct?
> 
> The whole process was sharing the same display before, just through
> GstGLWindow instead of GstGLDisplay.  It's still advisable to call
> eglTerminate when you're done with EGL resources so you don't leak.

Yes, whole process share the same GstGLWindow, but in loop playback, when destroy glimagesink, the GstGLWindow will be destroyed too, so that the wayland display destroyed. If you didn't call eglTerminate, leak occurs.

If split display from window, the display will be stored in the GstContext,in the whole process lifetime, only one display instance, this avoid resource leak.

> 
> > Actually I don't know where to call this eglTerminate with current code
> > structure. If move eglGetDisplay into GstGLDisplayWayland, this will change
> > the returned display to egl display, not wayland display.
> 
> Yes, we need both native display and eglDisplay which is where the
> interface/GstStructure comes in.