[621/906] GstGLRendererAPI => GstGLAPI and get GstGLAPI from a window

This commit is contained in:
Matthew Waters 2012-12-03 15:04:49 +11:00 committed by Tim-Philipp Müller
parent e1ec48b6cf
commit 0be301af24
20 changed files with 270 additions and 239 deletions

View file

@ -58,7 +58,7 @@ struct _GstGLWindowCocoaClass {
GType gst_gl_window_cocoa_get_type (void);
GstGLWindowCocoa * gst_gl_window_cocoa_new (GstGLRendererAPI render_api,
GstGLWindowCocoa * gst_gl_window_cocoa_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -123,6 +123,7 @@ void gst_gl_window_cocoa_quit (GstGLWindow * window, GstGLWindowCB callback,
gpointer data);
void gst_gl_window_cocoa_send_message (GstGLWindow * window,
GstGLWindowCB callback, gpointer data);
GstGLAPI gst_gl_window_cocoa_get_gl_api (GstGLWindow * window);
struct _GstGLWindowCocoaPrivate
{
@ -177,6 +178,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit);
window_class->send_message =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_gl_api);
#ifndef GNUSTEP
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@ -194,7 +197,7 @@ gst_gl_window_cocoa_init (GstGLWindowCocoa * window)
/* Must be called in the gl thread */
GstGLWindowCocoa *
gst_gl_window_cocoa_new (GstGLRendererAPI render_api, guintptr external_gl_context)
gst_gl_window_cocoa_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowCocoa *window = g_object_new (GST_GL_TYPE_WINDOW_COCOA, NULL);
GstGLWindowCocoaPrivate *priv = window->priv;
@ -446,6 +449,11 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
}
}
GstGLAPI
gst_gl_window_cocoa_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_OPENGL;
}
/* =============================================================*/
/* */

View file

@ -0,0 +1,83 @@
/*
* GStreamer
* Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_GL_RENDERER_H__
#define __GST_GL_RENDERER_H__
/* OpenGL 2.0 for Embedded Systems */
#ifdef HAVE_GLES2
# include <GLES2/gl2.h>
# if !HAVE_OPENGL
# include "gstgles2.h"
# endif
#endif
/* OpenGL for usual systems */
#if HAVE_OPENGL
# if __APPLE__
# include <GL/glew.h>
# include <OpenGL/OpenGL.h>
# include <OpenGL/gl.h>
# else
# include <GL/glew.h>
# include <GL/gl.h>
# endif
#endif
#if HAVE_GLX
# include <GL/glx.h>
#endif
#if HAVE_EGL
# undef UNICODE
# include <EGL/egl.h>
# define UNICODE
#endif
#include <gst/gst.h>
G_BEGIN_DECLS
typedef enum {
GST_GL_API_NONE = 0,
GST_GL_API_OPENGL = (1 << 0),
GST_GL_API_OPENGL3 = (1 << 1),
GST_GL_API_GLES = (1 << 15),
GST_GL_API_GLES2 = (1 << 16),
GST_GL_API_GLES3 = (1 << 17),
GST_GL_API_ANY = G_MAXUINT32
} GstGLAPI;
typedef enum
{
GST_GL_PLATFORM_UNKNOWN = 0,
GST_GL_PLATFORM_EGL,
GST_GL_PLATFORM_GLX,
GST_GL_PLATFORM_WGL,
GST_GL_PLATFORM_CGL,
GST_GL_PLATFORM_ANY = 254,
GST_GL_PLATFORM_LAST = 255
} GstGLPlatform;
G_END_DECLS
#endif /* __GST_GL_WINDOW_H__ */

View file

@ -1,104 +0,0 @@
/*
* GStreamer
* Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_GL_RENDERER_H__
#define __GST_GL_RENDERER_H__
/* OpenGL 2.0 for Embedded Systems */
#ifdef GST_GL_RENDERER_GLES2
# undef UNICODE
# include <EGL/egl.h>
# define UNICODE
# include <GLES2/gl2.h>
# include "gstgles2.h"
/* OpenGL for usual systems */
#endif
#if GST_GL_RENDERER_GL || GST_GL_RENDERER_GL3
# if __APPLE__
# include <GL/glew.h>
# include <OpenGL/OpenGL.h>
# include <OpenGL/gl.h>
# else
# if HAVE_GLEW
# include <GL/glew.h>
# endif
# include <GL/gl.h>
# endif
#endif
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_GL_TYPE_RENDERER (gst_gl_renderer_get_type())
#define GST_GL_RENDERER(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_RENDERER, GstGLRenderer))
#define GST_GL_RENDERER_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_RENDERER, GstGLRendererClass))
#define GST_GL_IS_RENDERER(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_RENDERER))
#define GST_GL_IS_RENDERER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_RENDERER))
#define GST_GL_RENDERER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_RENDERER, GstGLRendererClass))
#define GST_GL_RENDERER_ERROR (gst_gl_renderer_error_quark ())
typedef struct _GstGLRenderer GstGLRenderer;
typedef struct _GstGLRendererPrivate GstGLRendererPrivate;
typedef struct _GstGLRendererClass GstGLRendererClass;
typedef enum {
GST_GL_RENDERER_API_OPENGL = 1,
GST_GL_RENDERER_API_OPENGL3 = 2,
GST_GL_RENDERER_API_GLES = 40,
GST_GL_RENDERER_API_GLES2 = 41,
GST_GL_RENDERER_API_GLES3 = 42,
GST_GL_RENDERER_API_ANY = 254,
GST_GL_RENDERER_API_LAST = 255
} GstGLRendererAPI;
struct _GstGLRenderer {
/*< private >*/
GObject parent;
/*< public >*/
GstGLRendererAPI renderer_api;
/*< private >*/
gpointer _reserved[GST_PADDING_LARGE];
};
struct _GstGLRendererClass {
/*< private >*/
GObjectClass parent_class;
/*< private >*/
gpointer _reserved[GST_PADDING_LARGE];
};
/* methods */
GQuark gst_gl_renderer_error_quark (void);
GType gst_gl_renderer_get_type (void);
GstGLRenderer * gst_gl_renderer_new ();
GstGLRendererAPI gst_gl_renderer_get_renderer_api (GstGLRenderer *renderer);
G_END_DECLS
#endif /* __GST_GL_WINDOW_H__ */

View file

@ -56,7 +56,7 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
}
GstGLWindow *
gst_gl_window_new (GstGLRendererAPI render_api, guintptr external_gl_context)
gst_gl_window_new (GstGLAPI api, guintptr external_gl_context)
{
GstGLWindow *window = NULL;
const gchar *user_choice;
@ -73,25 +73,20 @@ gst_gl_window_new (GstGLRendererAPI render_api, guintptr external_gl_context)
#ifdef HAVE_WINDOW_X11
if (!window && (!user_choice || g_strstr_len (user_choice, 3, "x11")))
window =
GST_GL_WINDOW (gst_gl_window_x11_new (render_api, external_gl_context));
window = GST_GL_WINDOW (gst_gl_window_x11_new (api, external_gl_context));
#endif
#ifdef HAVE_WINDOW_WIN32
if (!window && (!user_choice || g_strstr_len (user_choice, 5, "win32")))
window =
GST_GL_WINDOW (gst_gl_window_win32_new (render_api,
external_gl_context));
window = GST_GL_WINDOW (gst_gl_window_win32_new (api, external_gl_context));
#endif
#ifdef HAVE_WINDOW_COCOA
if (!window && (!user_choice || g_strstr_len (user_choice, 5, "cocoa")))
window =
GST_GL_WINDOW (gst_gl_window_cocoa_new (render_api,
external_gl_context));
window = GST_GL_WINDOW (gst_gl_window_cocoa_new (api, external_gl_context));
#endif
#ifdef HAVE_WINDOW_WAYLAND
if (!window && (!user_choice || g_strstr_len (user_choice, 7, "wayland")))
window =
GST_GL_WINDOW (gst_gl_window_wayland_egl_new (render_api,
GST_GL_WINDOW (gst_gl_window_wayland_egl_new (api,
external_gl_context));
#endif
if (!window) {
@ -286,3 +281,22 @@ gst_gl_window_set_close_callback (GstGLWindow * window, GstGLWindowCB callback,
GST_GL_WINDOW_UNLOCK (window);
}
GstGLAPI
gst_gl_window_get_gl_api (GstGLWindow * window)
{
GstGLAPI ret;
GstGLWindowClass *window_class;
g_return_val_if_fail (GST_GL_IS_WINDOW (window), GST_GL_API_NONE);
window_class = GST_GL_WINDOW_GET_CLASS (window);
g_return_val_if_fail (window_class->get_gl_api != NULL, GST_GL_API_NONE);
GST_GL_WINDOW_LOCK (window);
ret = window_class->get_gl_api (window);
GST_GL_WINDOW_UNLOCK (window);
return ret;
}

View file

@ -24,7 +24,7 @@
#include <gst/gst.h>
#include "gstglrenderer.h"
#include "gstglapi.h"
G_BEGIN_DECLS
@ -57,18 +57,6 @@ typedef void (*GstGLWindowResizeCB) (gpointer data, guint width, guint height);
#define GST_GL_WINDOW_CB(f) ((GstGLWindowCB) (f))
#define GST_GL_WINDOW_RESIZE_CB(f) ((GstGLWindowResizeCB) (f))
typedef enum
{
GST_GL_PLATFORM_UNKNOWN = 0,
GST_GL_PLATFORM_EGL,
GST_GL_PLATFORM_GLX,
GST_GL_PLATFORM_WGL,
GST_GL_PLATFORM_CGL,
GST_GL_PLATFORM_ANY = 254,
GST_GL_PLATFORM_LAST = 255
} GstGLPlatform;
typedef struct _GstGLWindow GstGLWindow;
typedef struct _GstGLWindowPrivate GstGLWindowPrivate;
typedef struct _GstGLWindowClass GstGLWindowClass;
@ -98,15 +86,16 @@ struct _GstGLWindowClass {
/*< private >*/
GObjectClass parent_class;
guintptr (*get_gl_context) (GstGLWindow *window);
gboolean (*activate) (GstGLWindow *window, gboolean activate);
void (*set_window_handle) (GstGLWindow *window, guintptr id);
gboolean (*share_context) (GstGLWindow *window, guintptr external_gl_context);
void (*draw_unlocked) (GstGLWindow *window, guint width, guint height);
void (*draw) (GstGLWindow *window, guint width, guint height);
void (*run) (GstGLWindow *window);
void (*quit) (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
void (*send_message) (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
guintptr (*get_gl_context) (GstGLWindow *window);
GstGLAPI (*get_gl_api) (GstGLWindow *window);
gboolean (*activate) (GstGLWindow *window, gboolean activate);
void (*set_window_handle) (GstGLWindow *window, guintptr id);
gboolean (*share_context) (GstGLWindow *window, guintptr external_gl_context);
void (*draw_unlocked) (GstGLWindow *window, guint width, guint height);
void (*draw) (GstGLWindow *window, guint width, guint height);
void (*run) (GstGLWindow *window);
void (*quit) (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
void (*send_message) (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
/*< private >*/
gpointer _reserved[GST_PADDING];
@ -117,7 +106,7 @@ struct _GstGLWindowClass {
GQuark gst_gl_window_error_quark (void);
GType gst_gl_window_get_type (void);
GstGLWindow * gst_gl_window_new (GstGLRendererAPI render_api, guintptr external_gl_context);
GstGLWindow * gst_gl_window_new (GstGLAPI gl_api, guintptr external_gl_context);
void gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
void gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowResizeCB callback, gpointer data);
@ -125,7 +114,7 @@ void gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB
void gst_gl_window_set_need_lock (GstGLWindow *window, gboolean need_lock);
guintptr gst_gl_window_get_gl_context (GstGLWindow *window);
gboolean gst_gl_window_activate (GstGLWindow *window, gboolean activate);
gboolean gst_gl_window_activate (GstGLWindow *window, gboolean activate);
void gst_gl_window_set_window_handle (GstGLWindow *window, guintptr handle);
guintptr gst_gl_window_get_window_handle (GstGLWindow *window);
void gst_gl_window_draw_unlocked (GstGLWindow *window, guint width, guint height);
@ -135,6 +124,7 @@ void gst_gl_window_quit (GstGLWindow *window, GstGLWindowCB
void gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
GstGLPlatform gst_gl_window_get_platform (GstGLWindow *window);
GstGLAPI gst_gl_window_get_gl_api (GstGLWindow *window);
GST_DEBUG_CATEGORY_EXTERN (gst_gl_window_debug);

View file

@ -52,7 +52,8 @@ static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window,
static void gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL *
window_egl);
static gboolean gst_gl_window_wayland_egl_create_context (GstGLWindowWaylandEGL
* window_egl, GstGLRendererAPI render_api, guintptr external_gl_context);
* window_egl, GstGLAPI gl_api, guintptr external_gl_context);
GstGLAPI gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window);
static void gst_gl_window_wayland_egl_finalize (GObject * object);
@ -271,6 +272,8 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass)
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit);
window_class->send_message =
GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_gl_api);
object_class->finalize = gst_gl_window_wayland_egl_finalize;
}
@ -282,8 +285,7 @@ gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window)
/* Must be called in the gl thread */
GstGLWindowWaylandEGL *
gst_gl_window_wayland_egl_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_wayland_egl_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWaylandEGL *window;
@ -313,7 +315,7 @@ gst_gl_window_wayland_egl_new (GstGLRendererAPI render_api,
g_source_attach (window->wl_source, window->main_context);
gst_gl_window_wayland_egl_create_context (window, render_api,
gst_gl_window_wayland_egl_create_context (window, gl_api,
external_gl_context);
return window;
@ -346,7 +348,7 @@ gst_gl_window_wayland_egl_finalize (GObject * object)
static gboolean
gst_gl_window_wayland_egl_create_context (GstGLWindowWaylandEGL * window_egl,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
EGLint config_attrib[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
@ -469,6 +471,12 @@ gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window)
return (guintptr) GST_GL_WINDOW_WAYLAND_EGL (window)->egl_context;
}
GstGLAPI
gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_GLES2;
}
static void
gst_gl_window_wayland_egl_swap_buffers (GstGLWindow * window)
{

View file

@ -25,8 +25,6 @@
#include <wayland-egl.h>
#include <wayland-cursor.h>
#include <EGL/egl.h>
#include "gstglwindow.h"
G_BEGIN_DECLS
@ -99,7 +97,7 @@ struct _GstGLWindowWaylandEGLClass {
GType gst_gl_window_wayland_egl_get_type (void);
GstGLWindowWaylandEGL * gst_gl_window_wayland_egl_new (GstGLRendererAPI render_api,
GstGLWindowWaylandEGL * gst_gl_window_wayland_egl_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -51,7 +51,7 @@ enum
struct _GstGLWindowWin32Private
{
GstGLRendererAPI render_api;
GstGLAPI gl_api;
guintptr external_gl_context;
gboolean activate;
gboolean activate_result;
@ -138,8 +138,7 @@ gst_gl_window_win32_init (GstGLWindowWin32 * window)
/* Must be called in the gl thread */
GstGLWindowWin32 *
gst_gl_window_win32_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_win32_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWin32 *window = NULL;
const gchar *user_choice;
@ -149,13 +148,13 @@ gst_gl_window_win32_new (GstGLRendererAPI render_api,
#if HAVE_WGL
if (!window && (!user_choice || g_strstr_len (user_choice, 3, "wgl")))
window =
GST_GL_WINDOW_WIN32 (gst_gl_window_win32_wgl_new (render_api,
GST_GL_WINDOW_WIN32 (gst_gl_window_win32_wgl_new (gl_api,
external_gl_context));
#endif
#if HAVE_EGL
if (!window && (!user_choice || g_strstr_len (user_choice, 3, "egl")))
window =
GST_GL_WINDOW_WIN32 (gst_gl_window_win32_egl_new (render_api,
GST_GL_WINDOW_WIN32 (gst_gl_window_win32_egl_new (gl_api,
external_gl_context));
#endif
if (!window) {
@ -164,7 +163,7 @@ gst_gl_window_win32_new (GstGLRendererAPI render_api,
return NULL;
}
window->priv->render_api = render_api;
window->priv->gl_api = gl_api;
window->priv->external_gl_context = external_gl_context;
return window;
@ -427,7 +426,7 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
window_class->choose_format (window_win32);
window_class->create_context (window_win32, priv->render_api,
window_class->create_context (window_win32, priv->gl_api,
priv->external_gl_context);
/* priv->gl_context = wglCreateContext (priv->device);

View file

@ -74,7 +74,7 @@ struct _GstGLWindowWin32Class {
GType gst_gl_window_win32_get_type (void);
GstGLWindowWin32 * gst_gl_window_win32_new (GstGLRendererAPI render_api,
GstGLWindowWin32 * gst_gl_window_win32_new (GstGLAPI gl_api,
guintptr external_gl_context);
gboolean gst_gl_window_win32_open_device (GstGLWindowWin32 *window_win32);

View file

@ -36,11 +36,12 @@ static gboolean gst_gl_window_win32_wgl_choose_format (GstGLWindowWin32 *
static gboolean gst_gl_window_win32_wgl_activate (GstGLWindowWin32 *
window_win32, gboolean activate);
static gboolean gst_gl_window_win32_wgl_create_context (GstGLWindowWin32 *
window_win32, GstGLRendererAPI render_api, guintptr external_gl_context);
window_win32, GstGLAPI gl_api, guintptr external_gl_context);
static void gst_gl_window_win32_wgl_destroy_context (GstGLWindowWin32 *
window_win32);
GstGLAPI gst_gl_window_win32_egl_get_gl_api (GstGLWindow * window);
const gchar *EGLErrorString ();
const gchar *WinEGLErrorString ();
#define GST_CAT_DEFAULT gst_gl_window_win32_egl_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@ -54,20 +55,24 @@ G_DEFINE_TYPE_WITH_CODE (GstGLWindowWin32EGL, gst_gl_window_win32_egl,
static void
gst_gl_window_win32_egl_class_init (GstGLWindowWin32EGLClass * klass)
{
GstGLWindowWin32Class *window_class = (GstGLWindowWin32 *) klass;
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
GstGLWindowWin32Class *window_win32_class = (GstGLWindowWin32 *) klass;
window_win32_class->get_gl_context =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_get_gl_context);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_get_gl_context);
window_win32_class->choose_format =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_choose_format);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_choose_format);
window_win32_class->activate =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_activate);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_activate);
window_win32_class->create_context =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_create_context);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_create_context);
window_win32_class->destroy_context =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_destroy_context);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_destroy_context);
window_win32_class->swap_buffers =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_swap_buffers);
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_swap_buffers);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_egl_get_gl_api);
}
static void
@ -77,8 +82,7 @@ gst_gl_window_win32_egl_init (GstGLWindow * window)
/* Must be called in the gl thread */
GstGLWindowWin32EGL *
gst_gl_window_win32_egl_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_win32_egl_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWin32EGL *window =
g_object_new (GST_GL_TYPE_WINDOW_WIN32_EGL, NULL);
@ -115,7 +119,7 @@ gst_gl_window_win32_egl_activate (GstGLWindowWin32 * window_win32,
static gboolean
gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWin32EGL *window_egl;
EGLint majorVersion;
@ -142,7 +146,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
if (priv->display != EGL_NO_DISPLAY)
GST_DEBUG ("display retrieved: %d\n", window_egl->display);
else {
GST_DEBUG ("failed to retrieve display %s\n", EGLErrorString ());
GST_DEBUG ("failed to retrieve display %s\n", WinEGLErrorString ());
goto failure;
}
@ -150,7 +154,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GST_DEBUG ("egl initialized: %d.%d\n", majorVersion, minorVersion);
else {
GST_DEBUG ("failed to initialize egl %d, %s\n", priv->display,
EGLErrorString ());
WinEGLErrorString ());
goto failure;
}
@ -158,7 +162,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GST_DEBUG ("configs retrieved: %d\n", numConfigs);
else {
GST_DEBUG ("failed to retrieve configs %d, %s\n", window_egl->display,
EGLErrorString ());
WinEGLErrorString ());
goto failure;
}
@ -166,7 +170,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GST_DEBUG ("config set: %d, %d\n", config, numConfigs);
else {
GST_DEBUG ("failed to set config %d, %s\n", window_egl->display,
EGLErrorString ());
WinEGLErrorString ());
goto failure;
}
@ -177,7 +181,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GST_DEBUG ("surface created: %d\n", window_egl->surface);
else {
GST_DEBUG ("failed to create surface %d, %d, %s\n", window_egl->display,
window_egl->surface, EGLErrorString ());
window_egl->surface, WinEGLErrorString ());
goto failure;
}
@ -191,7 +195,7 @@ gst_gl_window_win32_egl_create_context (GstGLWindowWin32 * window_win32,
GST_DEBUG
("failed to create glcontext %lud, extenal: %lud, %s\n",
(gulong) window_egl->egl_context, (gulong) external_gl_context,
EGLErrorString ());
WinEGLErrorString ());
goto failure;
}
@ -211,27 +215,33 @@ gst_gl_window_win32_egl_destroy_context (GstGLWindowWin32 * window_win32)
if (window_egl->egl_context) {
if (!eglDestroyContext (window_egl->display, window_egl->egl_context))
GST_DEBUG ("failed to destroy context %d, %s\n", window_egl->egl_context,
EGLErrorString ());
WinEGLErrorString ());
window_egl->egl_context = NULL;
}
if (window_egl->surface) {
if (!eglDestroySurface (window_egl->display, window_egl->surface))
GST_DEBUG ("failed to destroy surface %d, %s\n", window_egl->surface,
EGLErrorString ());
WinEGLErrorString ());
window_egl->surface = NULL;
}
if (window_egl->display) {
if (!eglTerminate (window_egl->display))
GST_DEBUG ("failed to terminate display %d, %s\n", window_egl->display,
EGLErrorString ());
WinEGLErrorString ());
window_egl->display = NULL;
}
}
GstGLAPI
gst_gl_window_win32_egl_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_GLES2;
}
const gchar *
EGLErrorString ()
WinEGLErrorString ()
{
EGLint nErr = eglGetError ();
switch (nErr) {

View file

@ -62,7 +62,7 @@ struct _GstGLWindowWin32EGLClass {
GType gst_gl_window_win32_egl_get_type (void);
GstGLWindowWin32EGL * gst_gl_window_win32_egl_new (GstGLRendererAPI render_api,
GstGLWindowWin32EGL * gst_gl_window_win32_egl_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -47,13 +47,15 @@ static gboolean gst_gl_window_win32_wgl_choose_format (GstGLWindowWin32 *
static gboolean gst_gl_window_win32_wgl_activate (GstGLWindowWin32 *
window_win32, gboolean activate);
static gboolean gst_gl_window_win32_wgl_create_context (GstGLWindowWin32 *
window_win32, GstGLRendererAPI render_api, guintptr external_gl_context);
window_win32, GstGLAPI gl_api, guintptr external_gl_context);
static void gst_gl_window_win32_wgl_destroy_context (GstGLWindowWin32 *
window_win32);
GstGLAPI gst_gl_window_win32_wgl_get_gl_api (GstGLWindow * window);
static void
gst_gl_window_win32_wgl_class_init (GstGLWindowWin32WGLClass * klass)
{
GstGLWindowClass *window_class;
GstGLWindowWin32Class *window_win32_class = (GstGLWindowWin32Class *) klass;
window_win32_class->get_gl_context =
@ -68,6 +70,9 @@ gst_gl_window_win32_wgl_class_init (GstGLWindowWin32WGLClass * klass)
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_destroy_context);
window_win32_class->swap_buffers =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_swap_buffers);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_get_gl_api);
}
static void
@ -77,8 +82,7 @@ gst_gl_window_win32_wgl_init (GstGLWindowWin32WGL * window)
/* Must be called in the gl thread */
GstGLWindowWin32WGL *
gst_gl_window_win32_wgl_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_win32_wgl_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWin32WGL *window =
g_object_new (GST_GL_TYPE_WINDOW_WIN32_WGL, NULL);
@ -90,7 +94,7 @@ gst_gl_window_win32_wgl_new (GstGLRendererAPI render_api,
static gboolean
gst_gl_window_win32_wgl_create_context (GstGLWindowWin32 * window_win32,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowWin32WGL *window_wgl;
@ -198,3 +202,9 @@ gst_gl_window_win32_wgl_activate (GstGLWindowWin32 * window_win32,
return result;
}
GstGLAPI
gst_gl_window_win32_wgl_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_OPENGL;
}

View file

@ -59,7 +59,7 @@ struct _GstGLWindowWin32WGLClass {
GType gst_gl_window_win32_wgl_get_type (void);
GstGLWindowWin32WGL * gst_gl_window_win32_wgl_new (GstGLRendererAPI render_api,
GstGLWindowWin32WGL * gst_gl_window_win32_wgl_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -213,8 +213,7 @@ gst_gl_window_x11_init (GstGLWindowX11 * window)
/* Must be called in the gl thread */
GstGLWindowX11 *
gst_gl_window_x11_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_x11_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11 *window = NULL;
const gchar *user_choice;
@ -224,41 +223,40 @@ gst_gl_window_x11_new (GstGLRendererAPI render_api,
#ifdef HAVE_GLX
#ifdef HAVE_EGL
/* try GLX first for Desktop OpenGL */
if (render_api == GST_GL_RENDERER_API_OPENGL
|| render_api == GST_GL_RENDERER_API_OPENGL3
|| render_api == GST_GL_RENDERER_API_ANY) {
if (gl_api == GST_GL_API_OPENGL
|| gl_api == GST_GL_API_OPENGL3 || gl_api == GST_GL_API_ANY) {
if (!window && (!user_choice
|| g_strstr_len (user_choice, 3, "glx") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (gl_api,
external_gl_context));
if (!window && (!user_choice
|| g_strstr_len (user_choice, 3, "egl") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (gl_api,
external_gl_context));
} else { /* try EGL first for OpenGL|ES */
if (!window && (!user_choice
|| g_strstr_len (user_choice, 3, "egl") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (gl_api,
external_gl_context));
if (!window && (!user_choice
|| g_strstr_len (user_choice, 3, "glx") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (gl_api,
external_gl_context));
}
#endif /* HAVE_EGL */
if (!window && (!user_choice || g_strstr_len (user_choice, 3, "glx") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new (gl_api,
external_gl_context));
#endif /* HAVE_GLX */
#ifdef HAVE_EGL
if (!window && (!user_choice || g_strstr_len (user_choice, 3, "egl") != NULL))
window =
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (render_api,
GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new (gl_api,
external_gl_context));
#endif /* HAVE_EGL */
if (!window) {
@ -272,7 +270,7 @@ gst_gl_window_x11_new (GstGLRendererAPI render_api,
gboolean
gst_gl_window_x11_open_device (GstGLWindowX11 * window_x11,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11Class *window_class = GST_GL_WINDOW_X11_GET_CLASS (window_x11);
@ -329,8 +327,7 @@ gst_gl_window_x11_open_device (GstGLWindowX11 * window_x11,
gst_gl_window_x11_create_window (window_x11);
if (!window_class->create_context (window_x11, render_api,
external_gl_context)) {
if (!window_class->create_context (window_x11, gl_api, external_gl_context)) {
GST_WARNING ("Failed to create context");
goto failure;
}
@ -648,13 +645,13 @@ gst_gl_window_x11_run (GstGLWindow * window)
if (window_x11->running) {
#if SIZEOF_VOID_P == 8
GstGLWindowCB custom_cb =
(GstGLWindowCB) (((event.xclient.data.
l[0] & 0xffffffff) << 32) | (event.xclient.data.
l[1] & 0xffffffff));
(GstGLWindowCB) (((event.xclient.
data.l[0] & 0xffffffff) << 32) | (event.xclient.
data.l[1] & 0xffffffff));
gpointer custom_data =
(gpointer) (((event.xclient.data.
l[2] & 0xffffffff) << 32) | (event.xclient.data.
l[3] & 0xffffffff));
(gpointer) (((event.xclient.
data.l[2] & 0xffffffff) << 32) | (event.xclient.
data.l[3] & 0xffffffff));
#else
GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
gpointer custom_data = (gpointer) event.xclient.data.l[1];
@ -683,13 +680,13 @@ gst_gl_window_x11_run (GstGLWindow * window)
&& event.xclient.message_type == wm_quit_loop) {
#if SIZEOF_VOID_P == 8
GstGLWindowCB destroy_cb =
(GstGLWindowCB) (((event.xclient.data.
l[0] & 0xffffffff) << 32) | (event.xclient.data.
l[1] & 0xffffffff));
(GstGLWindowCB) (((event.xclient.
data.l[0] & 0xffffffff) << 32) | (event.xclient.
data.l[1] & 0xffffffff));
gpointer destroy_data =
(gpointer) (((event.xclient.data.
l[2] & 0xffffffff) << 32) | (event.xclient.data.
l[3] & 0xffffffff));
(gpointer) (((event.xclient.
data.l[2] & 0xffffffff) << 32) | (event.xclient.
data.l[3] & 0xffffffff));
#else
GstGLWindowCB destroy_cb = (GstGLWindowCB) event.xclient.data.l[0];
gpointer destroy_data = (gpointer) event.xclient.data.l[1];
@ -707,13 +704,13 @@ gst_gl_window_x11_run (GstGLWindow * window)
&pending_event)) {
#if SIZEOF_VOID_P == 8
GstGLWindowCB custom_cb =
(GstGLWindowCB) (((event.xclient.data.
l[0] & 0xffffffff) << 32) | (event.xclient.data.
l[1] & 0xffffffff));
(GstGLWindowCB) (((event.xclient.
data.l[0] & 0xffffffff) << 32) | (event.xclient.
data.l[1] & 0xffffffff));
gpointer custom_data =
(gpointer) (((event.xclient.data.
l[2] & 0xffffffff) << 32) | (event.xclient.data.
l[3] & 0xffffffff));
(gpointer) (((event.xclient.
data.l[2] & 0xffffffff) << 32) | (event.xclient.
data.l[3] & 0xffffffff));
#else
GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
gpointer custom_data = (gpointer) event.xclient.data.l[1];

View file

@ -81,7 +81,7 @@ struct _GstGLWindowX11Class {
GstGLWindowClass parent_class;
gboolean (*choose_format) (GstGLWindowX11 *window);
gboolean (*create_context) (GstGLWindowX11 *window, GstGLRendererAPI render_api,
gboolean (*create_context) (GstGLWindowX11 *window, GstGLAPI gl_api,
guintptr external_gl_context);
void (*swap_buffers) (GstGLWindowX11 *window);
gboolean (*activate) (GstGLWindowX11 *window, gboolean activate);
@ -94,10 +94,10 @@ struct _GstGLWindowX11Class {
GType gst_gl_window_x11_get_type (void);
GstGLWindowX11 * gst_gl_window_x11_new (GstGLRendererAPI render_api,
GstGLWindowX11 * gst_gl_window_x11_new (GstGLAPI gl_api,
guintptr external_gl_context);
gboolean gst_gl_window_x11_open_device (GstGLWindowX11 *window_x11,
GstGLRendererAPI render_api,
GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -27,7 +27,7 @@
#include "gstglwindow_x11_egl.h"
const gchar *EGLErrorString ();
const gchar *X11EGLErrorString ();
#define GST_CAT_DEFAULT gst_gl_window_x11_egl_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@ -44,14 +44,16 @@ static void gst_gl_window_x11_egl_swap_buffers (GstGLWindowX11 * window_x11);
static gboolean gst_gl_window_x11_egl_activate (GstGLWindowX11 * window_x11,
gboolean activate);
static gboolean gst_gl_window_x11_egl_create_context (GstGLWindowX11 *
window_x11, GstGLRendererAPI render_api, guintptr external_gl_context);
window_x11, GstGLAPI gl_api, guintptr external_gl_context);
static void gst_gl_window_x11_egl_destroy_context (GstGLWindowX11 * window_x11);
static gboolean gst_gl_window_x11_egl_choose_format (GstGLWindowX11 *
window_x11);
GstGLAPI gst_gl_window_x11_egl_get_gl_api (GstGLWindow * window);
static void
gst_gl_window_x11_egl_class_init (GstGLWindowX11EGLClass * klass)
{
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
GstGLWindowX11Class *window_x11_class = (GstGLWindowX11Class *) klass;
window_x11_class->get_gl_context =
@ -66,6 +68,9 @@ gst_gl_window_x11_egl_class_init (GstGLWindowX11EGLClass * klass)
GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_choose_format);
window_x11_class->swap_buffers =
GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_swap_buffers);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_get_gl_api);
}
static void
@ -75,12 +80,11 @@ gst_gl_window_x11_egl_init (GstGLWindowX11EGL * window)
/* Must be called in the gl thread */
GstGLWindowX11EGL *
gst_gl_window_x11_egl_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_x11_egl_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11EGL *window = g_object_new (GST_GL_TYPE_WINDOW_X11_EGL, NULL);
gst_gl_window_x11_open_device (GST_GL_WINDOW_X11 (window), render_api,
gst_gl_window_x11_open_device (GST_GL_WINDOW_X11 (window), gl_api,
external_gl_context);
return window;
@ -100,7 +104,7 @@ gst_gl_window_x11_egl_choose_format (GstGLWindowX11 * window_x11)
static gboolean
gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11EGL *window_egl;
@ -130,7 +134,7 @@ gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
g_debug ("egl initialized: %d.%d\n", majorVersion, minorVersion);
else {
g_debug ("failed to initialize egl %ld, %s\n",
(gulong) window_egl->egl_display, EGLErrorString ());
(gulong) window_egl->egl_display, X11EGLErrorString ());
goto failure;
}
@ -139,7 +143,7 @@ gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
g_debug ("config set: %ld, %ld\n", (gulong) config, (gulong) numConfigs);
else {
g_debug ("failed to set config %ld, %s\n", (gulong) window_egl->egl_display,
EGLErrorString ());
X11EGLErrorString ());
goto failure;
}
@ -151,7 +155,7 @@ gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
else {
g_debug ("failed to create surface %ld, %ld, %ld, %s\n",
(gulong) window_egl->egl_display, (gulong) window_egl->egl_surface,
(gulong) window_egl->egl_display, EGLErrorString ());
(gulong) window_egl->egl_display, X11EGLErrorString ());
goto failure;
}
@ -166,7 +170,7 @@ gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
else {
g_debug ("failed to create glcontext %ld, %ld, %s\n",
(gulong) window_egl->egl_context, (gulong) window_egl->egl_display,
EGLErrorString ());
X11EGLErrorString ());
goto failure;
}
@ -222,8 +226,14 @@ gst_gl_window_x11_egl_swap_buffers (GstGLWindowX11 * window_x11)
eglSwapBuffers (window_egl->egl_display, window_egl->egl_surface);
}
GstGLAPI
gst_gl_window_x11_egl_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_GLES2;
}
const gchar *
EGLErrorString ()
X11EGLErrorString ()
{
EGLint nErr = eglGetError ();
switch (nErr) {

View file

@ -58,7 +58,7 @@ struct _GstGLWindowX11EGLClass {
GType gst_gl_window_x11_egl_get_type (void);
GstGLWindowX11EGL * gst_gl_window_x11_egl_new (GstGLRendererAPI render_api,
GstGLWindowX11EGL * gst_gl_window_x11_egl_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS

View file

@ -44,14 +44,16 @@ static void gst_gl_window_x11_glx_swap_buffers (GstGLWindowX11 * window_x11);
static gboolean gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11,
gboolean activate);
static gboolean gst_gl_window_x11_glx_create_context (GstGLWindowX11 *
window_x11, GstGLRendererAPI render_api, guintptr external_gl_context);
window_x11, GstGLAPI gl_api, guintptr external_gl_context);
static void gst_gl_window_x11_glx_destroy_context (GstGLWindowX11 * window_x11);
static gboolean gst_gl_window_x11_glx_choose_format (GstGLWindowX11 *
window_x11);
GstGLAPI gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window);
static void
gst_gl_window_x11_glx_class_init (GstGLWindowX11GLXClass * klass)
{
GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
GstGLWindowX11Class *window_x11_class = (GstGLWindowX11Class *) klass;
window_x11_class->get_gl_context =
@ -66,6 +68,9 @@ gst_gl_window_x11_glx_class_init (GstGLWindowX11GLXClass * klass)
GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_choose_format);
window_x11_class->swap_buffers =
GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_swap_buffers);
window_class->get_gl_api =
GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_gl_api);
}
static void
@ -75,12 +80,11 @@ gst_gl_window_x11_glx_init (GstGLWindowX11GLX * window)
/* Must be called in the gl thread */
GstGLWindowX11GLX *
gst_gl_window_x11_glx_new (GstGLRendererAPI render_api,
guintptr external_gl_context)
gst_gl_window_x11_glx_new (GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11GLX *window = g_object_new (GST_GL_TYPE_WINDOW_X11_GLX, NULL);
gst_gl_window_x11_open_device (GST_GL_WINDOW_X11 (window), render_api,
gst_gl_window_x11_open_device (GST_GL_WINDOW_X11 (window), gl_api,
external_gl_context);
return window;
@ -88,7 +92,7 @@ gst_gl_window_x11_glx_new (GstGLRendererAPI render_api,
static gboolean
gst_gl_window_x11_glx_create_context (GstGLWindowX11 * window_x11,
GstGLRendererAPI render_api, guintptr external_gl_context)
GstGLAPI gl_api, guintptr external_gl_context)
{
GstGLWindowX11GLX *window_glx;
@ -182,3 +186,9 @@ gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11, gboolean activate)
return result;
}
GstGLAPI
gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window)
{
return GST_GL_API_OPENGL;
}

View file

@ -21,8 +21,6 @@
#ifndef __GST_GL_WINDOW_X11_GLX_H__
#define __GST_GL_WINDOW_X11_GLX_H__
#include <GL/glx.h>
#include "gstglwindow_x11.h"
G_BEGIN_DECLS
@ -56,7 +54,7 @@ struct _GstGLWindowX11GLXClass {
GType gst_gl_window_x11_glx_get_type (void);
GstGLWindowX11GLX * gst_gl_window_x11_glx_new (GstGLRendererAPI render_api,
GstGLWindowX11GLX * gst_gl_window_x11_glx_new (GstGLAPI gl_api,
guintptr external_gl_context);
G_END_DECLS