mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
[701/906] display: move context creation into window
This commit is contained in:
parent
9c633e658a
commit
c6988cb064
12 changed files with 583 additions and 420 deletions
|
@ -62,9 +62,7 @@ void gst_gl_display_thread_run_generic (GstGLDisplay * display);
|
|||
|
||||
struct _GstGLDisplayPrivate
|
||||
{
|
||||
/* conditions */
|
||||
GCond cond_create_context;
|
||||
GCond cond_destroy_context;
|
||||
GstGLWindow *window;
|
||||
|
||||
/* generic gl code */
|
||||
GstGLDisplayThreadFunc generic_callback;
|
||||
|
@ -91,13 +89,8 @@ gst_gl_display_init (GstGLDisplay * display)
|
|||
/* thread safe */
|
||||
g_mutex_init (&display->mutex);
|
||||
|
||||
g_cond_init (&display->priv->cond_create_context);
|
||||
g_cond_init (&display->priv->cond_destroy_context);
|
||||
|
||||
display->gl_vtable = g_slice_alloc0 (sizeof (GstGLFuncs));
|
||||
|
||||
display->gl_window = gst_gl_window_new ();
|
||||
|
||||
gst_gl_memory_init ();
|
||||
}
|
||||
|
||||
|
@ -106,39 +99,8 @@ gst_gl_display_finalize (GObject * object)
|
|||
{
|
||||
GstGLDisplay *display = GST_GL_DISPLAY (object);
|
||||
|
||||
if (display->gl_window) {
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
gst_gl_window_set_resize_callback (display->gl_window, NULL, NULL);
|
||||
gst_gl_window_set_draw_callback (display->gl_window, NULL, NULL);
|
||||
gst_gl_window_set_close_callback (display->gl_window, NULL, NULL);
|
||||
|
||||
if (display->context_created) {
|
||||
GST_INFO ("send quit gl window loop");
|
||||
gst_gl_window_quit (display->gl_window,
|
||||
GST_GL_WINDOW_CB (gst_gl_display_thread_destroy_context), display);
|
||||
|
||||
GST_INFO ("quit sent to gl window loop");
|
||||
|
||||
g_cond_wait (&display->priv->cond_destroy_context, &display->mutex);
|
||||
GST_INFO ("quit received from gl window");
|
||||
}
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
if (display->gl_thread) {
|
||||
gpointer ret = g_thread_join (display->gl_thread);
|
||||
GST_INFO ("gl thread joined");
|
||||
if (ret != NULL)
|
||||
GST_ERROR ("gl thread returned a not null pointer");
|
||||
display->gl_thread = NULL;
|
||||
}
|
||||
|
||||
g_mutex_clear (&display->mutex);
|
||||
|
||||
g_cond_clear (&display->priv->cond_destroy_context);
|
||||
g_cond_clear (&display->priv->cond_create_context);
|
||||
|
||||
if (display->error_message) {
|
||||
g_free (display->error_message);
|
||||
display->error_message = NULL;
|
||||
|
@ -148,271 +110,13 @@ gst_gl_display_finalize (GObject * object)
|
|||
g_slice_free (GstGLFuncs, display->gl_vtable);
|
||||
display->gl_vtable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_create_context_gles2 (GstGLDisplay * display, gint * gl_major, gint * gl_minor)
|
||||
{
|
||||
const GstGLFuncs *gl;
|
||||
GLenum gl_err = GL_NO_ERROR;
|
||||
|
||||
gl = display->gl_vtable;
|
||||
|
||||
GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
|
||||
GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
|
||||
gl->GetString (GL_SHADING_LANGUAGE_VERSION));
|
||||
GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
|
||||
GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
|
||||
|
||||
gl_err = gl->GetError ();
|
||||
if (gl_err != GL_NO_ERROR) {
|
||||
gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err);
|
||||
return FALSE;
|
||||
}
|
||||
#if GST_GL_HAVE_GLES2
|
||||
if (!GL_ES_VERSION_2_0) {
|
||||
gst_gl_display_set_error (display, "OpenGL|ES >= 2.0 is required");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
_gst_gl_feature_check_ext_functions (display, 0, 0,
|
||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
||||
|
||||
if (gl_major)
|
||||
*gl_major = 2;
|
||||
if (gl_minor)
|
||||
*gl_minor = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_create_context_opengl (GstGLDisplay * display, gint * gl_major,
|
||||
gint * gl_minor)
|
||||
{
|
||||
const GstGLFuncs *gl;
|
||||
guint maj, min;
|
||||
GLenum gl_err = GL_NO_ERROR;
|
||||
GString *opengl_version = NULL;
|
||||
|
||||
gl = display->gl_vtable;
|
||||
|
||||
GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
|
||||
GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
|
||||
gl->GetString (GL_SHADING_LANGUAGE_VERSION));
|
||||
GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
|
||||
GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
|
||||
|
||||
gl_err = gl->GetError ();
|
||||
if (gl_err != GL_NO_ERROR) {
|
||||
gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err);
|
||||
return FALSE;
|
||||
}
|
||||
opengl_version =
|
||||
g_string_truncate (g_string_new ((gchar *) gl->GetString (GL_VERSION)),
|
||||
3);
|
||||
|
||||
sscanf (opengl_version->str, "%d.%d", &maj, &min);
|
||||
|
||||
g_string_free (opengl_version, TRUE);
|
||||
|
||||
/* OpenGL > 1.2.0 */
|
||||
if ((maj < 1) || (maj < 2 && maj >= 1 && min < 2)) {
|
||||
gst_gl_display_set_error (display, "OpenGL >= 1.2.0 required, found %u.%u",
|
||||
maj, min);
|
||||
return FALSE;
|
||||
if (display->priv->window) {
|
||||
gst_object_unref (display->priv->window);
|
||||
display->priv->window = NULL;
|
||||
}
|
||||
|
||||
_gst_gl_feature_check_ext_functions (display, maj, min,
|
||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
||||
|
||||
if (gl_major)
|
||||
*gl_major = maj;
|
||||
if (gl_minor)
|
||||
*gl_minor = min;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
_compiled_api (void)
|
||||
{
|
||||
GstGLAPI ret = GST_GL_API_NONE;
|
||||
|
||||
#if GST_GL_HAVE_OPENGL
|
||||
ret |= GST_GL_API_OPENGL;
|
||||
#endif
|
||||
#if GST_GL_HAVE_GLES2
|
||||
ret |= GST_GL_API_GLES2;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
_parse_gl_api (const gchar * apis_s)
|
||||
{
|
||||
GstGLAPI ret = GST_GL_API_NONE;
|
||||
gchar *apis = (gchar *) apis_s;
|
||||
|
||||
while (apis) {
|
||||
if (apis[0] == '\0') {
|
||||
break;
|
||||
} else if (apis[0] == ' ' || apis[0] == ',') {
|
||||
apis = &apis[1];
|
||||
} else if (g_strstr_len (apis, 7, "opengl3")) {
|
||||
ret |= GST_GL_API_OPENGL3;
|
||||
apis = &apis[7];
|
||||
} else if (g_strstr_len (apis, 6, "opengl")) {
|
||||
ret |= GST_GL_API_OPENGL;
|
||||
apis = &apis[6];
|
||||
} else if (g_strstr_len (apis, 5, "gles1")) {
|
||||
ret |= GST_GL_API_GLES;
|
||||
apis = &apis[5];
|
||||
} else if (g_strstr_len (apis, 5, "gles2")) {
|
||||
ret |= GST_GL_API_GLES2;
|
||||
apis = &apis[5];
|
||||
} else if (g_strstr_len (apis, 5, "gles3")) {
|
||||
ret |= GST_GL_API_GLES3;
|
||||
apis = &apis[5];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == GST_GL_API_NONE)
|
||||
ret = GST_GL_API_ANY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpointer
|
||||
gst_gl_display_thread_create_context (GstGLDisplay * display)
|
||||
{
|
||||
GstGLFuncs *gl;
|
||||
gint gl_major = 0;
|
||||
gboolean ret = FALSE;
|
||||
GError *error = NULL;
|
||||
GstGLAPI compiled_api, user_api;
|
||||
gchar *api_string;
|
||||
gchar *compiled_api_s;
|
||||
gchar *user_api_string;
|
||||
const gchar *user_choice;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
gl = display->gl_vtable;
|
||||
compiled_api = _compiled_api ();
|
||||
|
||||
if (!display->gl_window) {
|
||||
gst_gl_display_set_error (display, "Failed to create opengl window");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
user_choice = g_getenv ("GST_GL_API");
|
||||
|
||||
user_api = _parse_gl_api (user_choice);
|
||||
user_api_string = gst_gl_api_string (user_api);
|
||||
|
||||
compiled_api_s = gst_gl_api_string (compiled_api);
|
||||
|
||||
GST_INFO ("Attempting to create opengl context. user chosen api(s):%s, "
|
||||
"compiled api support:%s", user_api_string, compiled_api_s);
|
||||
|
||||
if (!gst_gl_window_create_context (display->gl_window,
|
||||
compiled_api & user_api, display->external_gl_context, &error)) {
|
||||
gst_gl_display_set_error (display,
|
||||
error ? error->message : "Failed to create gl window");
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
goto failure;
|
||||
}
|
||||
GST_INFO ("window created context");
|
||||
|
||||
display->gl_api = gst_gl_window_get_gl_api (display->gl_window);
|
||||
g_assert (display->gl_api != GST_GL_API_NONE
|
||||
&& display->gl_api != GST_GL_API_ANY);
|
||||
|
||||
api_string = gst_gl_api_string (display->gl_api);
|
||||
GST_INFO ("available GL APIs: %s", api_string);
|
||||
|
||||
if (((compiled_api & display->gl_api) & user_api) == GST_GL_API_NONE) {
|
||||
gst_gl_display_set_error (display, "failed to create context, window "
|
||||
"could not provide correct api. user:%s, compiled:%s, window:%s",
|
||||
user_api_string, compiled_api_s, api_string);
|
||||
g_free (api_string);
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_free (api_string);
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
|
||||
gl->GetError =
|
||||
gst_gl_window_get_proc_address (display->gl_window, "glGetError");
|
||||
gl->GetString =
|
||||
gst_gl_window_get_proc_address (display->gl_window, "glGetString");
|
||||
|
||||
if (!gl->GetError || !gl->GetString) {
|
||||
gst_gl_display_set_error (display,
|
||||
"could not GetProcAddress core opengl functions");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* gl api specific code */
|
||||
if (!ret && USING_OPENGL (display))
|
||||
ret = _create_context_opengl (display, &gl_major, NULL);
|
||||
if (!ret && USING_GLES2 (display))
|
||||
ret = _create_context_gles2 (display, &gl_major, NULL);
|
||||
|
||||
if (!ret || !gl_major) {
|
||||
GST_WARNING ("GL api specific initialization failed");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_cond_signal (&display->priv->cond_create_context);
|
||||
|
||||
display->isAlive = TRUE;
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
gst_gl_window_run (display->gl_window);
|
||||
|
||||
GST_INFO ("loop exited\n");
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
display->isAlive = FALSE;
|
||||
|
||||
g_object_unref (G_OBJECT (display->gl_window));
|
||||
|
||||
display->gl_window = NULL;
|
||||
|
||||
g_cond_signal (&display->priv->cond_destroy_context);
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return NULL;
|
||||
|
||||
failure:
|
||||
{
|
||||
if (display->gl_window) {
|
||||
g_object_unref (display->gl_window);
|
||||
display->gl_window = NULL;
|
||||
}
|
||||
|
||||
g_cond_signal (&display->priv->cond_create_context);
|
||||
gst_gl_display_unlock (display);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gst_gl_display_thread_destroy_context (GstGLDisplay * display)
|
||||
{
|
||||
GST_INFO ("Context destroyed");
|
||||
G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
@ -434,8 +138,6 @@ gst_gl_display_set_error (GstGLDisplay * display, const char *format, ...)
|
|||
va_end (args);
|
||||
|
||||
GST_WARNING ("%s", display->error_message);
|
||||
|
||||
display->isAlive = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -470,83 +172,55 @@ gst_gl_display_new (void)
|
|||
return g_object_new (GST_GL_TYPE_DISPLAY, NULL);
|
||||
}
|
||||
|
||||
/* Create an opengl context (one context for one GstGLDisplay) */
|
||||
gboolean
|
||||
gst_gl_display_create_context (GstGLDisplay * display,
|
||||
gulong external_gl_context)
|
||||
{
|
||||
gboolean isAlive = FALSE;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
if (!display->context_created) {
|
||||
display->external_gl_context = external_gl_context;
|
||||
|
||||
display->gl_thread = g_thread_new ("gstglcontext",
|
||||
(GThreadFunc) gst_gl_display_thread_create_context, display);
|
||||
|
||||
g_cond_wait (&display->priv->cond_create_context, &display->mutex);
|
||||
|
||||
display->context_created = TRUE;
|
||||
|
||||
GST_INFO ("gl thread created");
|
||||
}
|
||||
|
||||
isAlive = display->isAlive;
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return isAlive;
|
||||
}
|
||||
|
||||
void
|
||||
gst_gl_display_thread_add (GstGLDisplay * display,
|
||||
GstGLDisplayThreadFunc func, gpointer data)
|
||||
{
|
||||
g_return_if_fail (GST_IS_GL_DISPLAY (display));
|
||||
g_return_if_fail (GST_GL_IS_WINDOW (display->priv->window));
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
display->priv->data = data;
|
||||
display->priv->generic_callback = func;
|
||||
gst_gl_window_send_message (display->gl_window,
|
||||
|
||||
gst_gl_window_send_message (display->priv->window,
|
||||
GST_GL_WINDOW_CB (gst_gl_display_thread_run_generic), display);
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
guintptr
|
||||
gst_gl_display_get_internal_gl_context (GstGLDisplay * display)
|
||||
{
|
||||
gulong external_gl_context = 0;
|
||||
gst_gl_display_lock (display);
|
||||
external_gl_context = gst_gl_window_get_gl_context (display->gl_window);
|
||||
gst_gl_display_unlock (display);
|
||||
return external_gl_context;
|
||||
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), 0);
|
||||
g_return_val_if_fail (GST_GL_IS_WINDOW (display->priv->window), 0);
|
||||
|
||||
return gst_gl_window_get_gl_context (display->priv->window);
|
||||
}
|
||||
|
||||
void
|
||||
gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate)
|
||||
{
|
||||
g_return_if_fail (GST_IS_GL_DISPLAY (display));
|
||||
g_return_if_fail (GST_GL_IS_WINDOW (display->priv->window));
|
||||
|
||||
if (!activate)
|
||||
gst_gl_display_lock (display);
|
||||
gst_gl_window_activate (display->gl_window, activate);
|
||||
|
||||
gst_gl_window_activate (display->priv->window, activate);
|
||||
|
||||
if (activate)
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display)
|
||||
{
|
||||
return display->gl_api;
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
gst_gl_display_get_gl_api (GstGLDisplay * display)
|
||||
{
|
||||
GstGLAPI api;
|
||||
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), GST_GL_API_NONE);
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
api = gst_gl_display_get_gl_api_unlocked (display);
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return api;
|
||||
return display->gl_api;
|
||||
}
|
||||
|
||||
gpointer
|
||||
|
@ -554,13 +228,50 @@ gst_gl_display_get_gl_vtable (GstGLDisplay * display)
|
|||
{
|
||||
gpointer gl;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
|
||||
|
||||
gl = display->gl_vtable;
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return gl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
//------------------------ END PUBLIC ------------------------
|
||||
//------------------------------------------------------------
|
||||
void
|
||||
gst_gl_display_set_window (GstGLDisplay * display, GstGLWindow * window)
|
||||
{
|
||||
g_return_if_fail (GST_IS_GL_DISPLAY (display));
|
||||
g_return_if_fail (GST_GL_IS_WINDOW (window));
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
if (display->priv->window)
|
||||
gst_object_unref (display->priv->window);
|
||||
|
||||
display->priv->window = gst_object_ref (window);
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
GstGLWindow *
|
||||
gst_gl_display_get_window (GstGLDisplay * display)
|
||||
{
|
||||
GstGLWindow *window;
|
||||
|
||||
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
window =
|
||||
display->priv->window ? gst_object_ref (display->priv->window) : NULL;
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
GstGLWindow *
|
||||
gst_gl_display_get_window_unlocked (GstGLDisplay * display)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
|
||||
|
||||
return display->priv->window ? gst_object_ref (display->priv->window) : NULL;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <gst/video/video.h>
|
||||
|
||||
typedef struct _GstGLShader GstGLShader;
|
||||
typedef struct _GstGLWindow GstGLWindow;
|
||||
|
||||
#include "gstglwindow.h"
|
||||
#include "gstglshader.h"
|
||||
|
@ -89,12 +90,6 @@ struct _GstGLDisplay
|
|||
/* thread safe */
|
||||
GMutex mutex;
|
||||
|
||||
/* gl context */
|
||||
GThread *gl_thread;
|
||||
GstGLWindow *gl_window;
|
||||
gboolean isAlive;
|
||||
gboolean context_created;
|
||||
|
||||
/* gl API we are using */
|
||||
GstGLAPI gl_api;
|
||||
/* foreign gl context */
|
||||
|
@ -115,9 +110,6 @@ struct _GstGLDisplayClass
|
|||
|
||||
GstGLDisplay *gst_gl_display_new (void);
|
||||
|
||||
gboolean gst_gl_display_create_context (GstGLDisplay * display,
|
||||
gulong external_gl_context);
|
||||
|
||||
void gst_gl_display_thread_add (GstGLDisplay * display,
|
||||
GstGLDisplayThreadFunc func, gpointer data);
|
||||
|
||||
|
@ -126,15 +118,17 @@ void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activa
|
|||
|
||||
/* Must be called inside a lock/unlock on display, or within the glthread */
|
||||
void gst_gl_display_set_error (GstGLDisplay * display, const char * format, ...);
|
||||
gboolean gst_gl_display_check_framebuffer_status (GstGLDisplay * display);
|
||||
|
||||
void gst_gl_display_lock (GstGLDisplay * display);
|
||||
void gst_gl_display_unlock (GstGLDisplay * display);
|
||||
GstGLAPI gst_gl_display_get_gl_api (GstGLDisplay * display);
|
||||
GstGLAPI gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display);
|
||||
|
||||
gpointer gst_gl_display_get_gl_vtable (GstGLDisplay * display);
|
||||
|
||||
void gst_gl_display_set_window (GstGLDisplay * display, GstGLWindow * window);
|
||||
GstGLWindow * gst_gl_display_get_window (GstGLDisplay * display);
|
||||
GstGLWindow * gst_gl_display_get_window_unlocked (GstGLDisplay * display);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_GL_H__ */
|
||||
|
|
|
@ -43,11 +43,11 @@
|
|||
* calling thread.
|
||||
*/
|
||||
|
||||
#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL)
|
||||
#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3)
|
||||
#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES)
|
||||
#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2)
|
||||
#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3)
|
||||
#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL)
|
||||
#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3)
|
||||
#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES)
|
||||
#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2)
|
||||
#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3)
|
||||
|
||||
static void _do_download (GstGLDisplay * display, GstGLDownload * download);
|
||||
static void _init_download (GstGLDisplay * display, GstGLDownload * download);
|
||||
|
|
|
@ -150,6 +150,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
|
|||
const char *suffix = NULL;
|
||||
int func_num;
|
||||
GstGLFuncs *gst_gl = display->gl_vtable;
|
||||
GstGLWindow *window = NULL;
|
||||
|
||||
/* First check whether the functions should be directly provided by
|
||||
GL */
|
||||
|
@ -172,6 +173,9 @@ _gst_gl_feature_check (GstGLDisplay * display,
|
|||
if (suffix == NULL)
|
||||
goto error;
|
||||
|
||||
window = gst_gl_display_get_window (display);
|
||||
g_assert (window);
|
||||
|
||||
/* Try to get all of the entry points */
|
||||
for (func_num = 0; data->functions[func_num].name; func_num++) {
|
||||
void *func;
|
||||
|
@ -183,8 +187,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
|
|||
suffix, NULL);
|
||||
GST_TRACE ("%s should %sbe in core", full_function_name,
|
||||
in_core ? "" : "not ");
|
||||
func =
|
||||
gst_gl_window_get_proc_address (display->gl_window, full_function_name);
|
||||
func = gst_gl_window_get_proc_address (window, full_function_name);
|
||||
|
||||
if (func == NULL && in_core) {
|
||||
GST_TRACE ("%s was not found in core, trying the extension version",
|
||||
|
@ -196,8 +199,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
|
|||
g_free (full_function_name);
|
||||
full_function_name = g_strconcat ("gl", data->functions[func_num].name,
|
||||
suffix, NULL);
|
||||
func = gst_gl_window_get_proc_address (display->gl_window,
|
||||
full_function_name);
|
||||
func = gst_gl_window_get_proc_address (window, full_function_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,6 +214,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
|
|||
}
|
||||
|
||||
g_free (full_function_name);
|
||||
gst_object_unref (window);
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
@ -230,6 +233,9 @@ error:
|
|||
g_free (full_function_name);
|
||||
}
|
||||
|
||||
if (window)
|
||||
gst_object_unref (window);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,11 +253,18 @@ gst_gl_filter_start (GstBaseTransform * bt)
|
|||
filter->display =
|
||||
g_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
||||
else {
|
||||
GstGLWindow *window;
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
filter->display = gst_gl_display_new ();
|
||||
if (!gst_gl_display_create_context (filter->display, 0)) {
|
||||
window = gst_gl_window_new (filter->display);
|
||||
gst_gl_display_set_window (filter->display, window);
|
||||
g_object_unref (window);
|
||||
|
||||
if (!gst_gl_window_create_context (window, 0, &error)) {
|
||||
GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND,
|
||||
GST_GL_DISPLAY_ERR_MSG (filter->display), (NULL));
|
||||
("%s", error->message), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -727,9 +734,10 @@ gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
|
|||
if (filter_class->display_init_cb != NULL) {
|
||||
gst_gl_display_thread_add (filter->display, gst_gl_filter_start_gl, filter);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!filter->display->isAlive)
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
if (filter_class->onInitFBO) {
|
||||
if (!filter_class->onInitFBO (filter))
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <gst/video/video.h>
|
||||
|
||||
#include "gstglmemory.h"
|
||||
#include "gstglutils.h"
|
||||
|
||||
/**
|
||||
* SECTION:gstglmemory
|
||||
|
|
|
@ -935,11 +935,18 @@ gst_gl_mixer_activate (GstGLMixer * mix, gboolean activate)
|
|||
mix->display =
|
||||
g_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
|
||||
else {
|
||||
GstGLWindow *window;
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Creating GstGLDisplay");
|
||||
mix->display = gst_gl_display_new ();
|
||||
if (!gst_gl_display_create_context (mix->display, 0)) {
|
||||
window = gst_gl_window_new (mix->display);
|
||||
gst_gl_display_set_window (mix->display, window);
|
||||
g_object_unref (window);
|
||||
|
||||
if (!gst_gl_window_create_context (window, 0, &error)) {
|
||||
GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND,
|
||||
GST_GL_DISPLAY_ERR_MSG (mix->display), (NULL));
|
||||
("%s", error->message), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,11 +43,11 @@
|
|||
* calling thread.
|
||||
*/
|
||||
|
||||
#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL)
|
||||
#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3)
|
||||
#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES)
|
||||
#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2)
|
||||
#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3)
|
||||
#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL)
|
||||
#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3)
|
||||
#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES)
|
||||
#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2)
|
||||
#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3)
|
||||
|
||||
static void _do_upload (GstGLDisplay * display, GstGLUpload * upload);
|
||||
static void _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload);
|
||||
|
|
|
@ -234,18 +234,24 @@ void
|
|||
gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture,
|
||||
GstVideoFormat v_format, GLint width, GLint height)
|
||||
{
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
|
||||
if (display->isAlive) {
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
gen_texture_width = width;
|
||||
gen_texture_height = height;
|
||||
gen_texture_video_format = v_format;
|
||||
gst_gl_window_send_message (display->gl_window,
|
||||
gst_gl_window_send_message (window,
|
||||
GST_GL_WINDOW_CB (gst_gl_display_gen_texture_window_cb), display);
|
||||
*pTexture = gen_texture;
|
||||
} else
|
||||
*pTexture = 0;
|
||||
|
||||
gst_object_unref (window);
|
||||
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
|
@ -263,21 +269,26 @@ gboolean
|
|||
gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height,
|
||||
GLuint * fbo, GLuint * depthbuffer)
|
||||
{
|
||||
gboolean isAlive = FALSE;
|
||||
gboolean alive = FALSE;
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
gen_fbo_width = width;
|
||||
gen_fbo_height = height;
|
||||
gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_gen_fbo),
|
||||
display);
|
||||
gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gen_fbo), display);
|
||||
*fbo = generated_fbo;
|
||||
*depthbuffer = generated_depth_buffer;
|
||||
}
|
||||
isAlive = display->isAlive;
|
||||
alive = gst_gl_window_is_running (window);
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return isAlive;
|
||||
return alive;
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,10 +308,13 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width,
|
|||
gdouble proj_param2, gdouble proj_param3, gdouble proj_param4,
|
||||
GstGLDisplayProjection projection, gpointer * stuff)
|
||||
{
|
||||
gboolean isAlive;
|
||||
gboolean alive;
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
use_fbo = fbo;
|
||||
use_depth_buffer = depth_buffer;
|
||||
use_fbo_texture = texture_fbo;
|
||||
|
@ -316,13 +330,14 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width,
|
|||
input_texture_width = input_tex_width;
|
||||
input_texture_height = input_tex_height;
|
||||
input_texture = input_tex;
|
||||
gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_use_fbo),
|
||||
display);
|
||||
gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_use_fbo), display);
|
||||
}
|
||||
isAlive = display->isAlive;
|
||||
alive = gst_gl_window_is_running (window);
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return isAlive;
|
||||
return alive;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -330,10 +345,13 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width,
|
|||
gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
|
||||
GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff)
|
||||
{
|
||||
gboolean isAlive;
|
||||
gboolean alive;
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
use_fbo = fbo;
|
||||
use_depth_buffer = depth_buffer;
|
||||
use_fbo_texture = texture_fbo;
|
||||
|
@ -341,26 +359,33 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width,
|
|||
use_fbo_height = texture_fbo_height;
|
||||
use_fbo_scene_cb_v2 = cb;
|
||||
use_fbo_stuff = stuff;
|
||||
gst_gl_window_send_message (display->gl_window,
|
||||
gst_gl_window_send_message (window,
|
||||
GST_GL_WINDOW_CB (_use_fbo_v2), display);
|
||||
}
|
||||
isAlive = display->isAlive;
|
||||
alive = gst_gl_window_is_running (window);
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return isAlive;
|
||||
return alive;
|
||||
}
|
||||
|
||||
/* Called by gltestsrc and glfilter */
|
||||
void
|
||||
gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer)
|
||||
{
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
del_fbo = fbo;
|
||||
del_depth_buffer = depth_buffer;
|
||||
gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_del_fbo),
|
||||
display);
|
||||
gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_del_fbo), display);
|
||||
}
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
|
@ -371,13 +396,16 @@ gst_gl_display_gen_shader (GstGLDisplay * display,
|
|||
const gchar * shader_vertex_source,
|
||||
const gchar * shader_fragment_source, GstGLShader ** shader)
|
||||
{
|
||||
gboolean isAlive;
|
||||
gboolean alive;
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
gen_shader_vertex_source = shader_vertex_source;
|
||||
gen_shader_fragment_source = shader_fragment_source;
|
||||
gst_gl_window_send_message (display->gl_window,
|
||||
gst_gl_window_send_message (window,
|
||||
GST_GL_WINDOW_CB (_gen_shader), display);
|
||||
if (shader)
|
||||
*shader = gen_shader;
|
||||
|
@ -385,10 +413,12 @@ gst_gl_display_gen_shader (GstGLDisplay * display,
|
|||
gen_shader_vertex_source = NULL;
|
||||
gen_shader_fragment_source = NULL;
|
||||
}
|
||||
isAlive = display->isAlive;
|
||||
alive = gst_gl_window_is_running (window);
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
|
||||
return isAlive;
|
||||
return alive;
|
||||
}
|
||||
|
||||
|
||||
|
@ -396,12 +426,18 @@ gst_gl_display_gen_shader (GstGLDisplay * display,
|
|||
void
|
||||
gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader)
|
||||
{
|
||||
GstGLWindow *window;
|
||||
|
||||
gst_gl_display_lock (display);
|
||||
if (display->isAlive) {
|
||||
|
||||
window = gst_gl_display_get_window_unlocked (display);
|
||||
if (gst_gl_window_is_running (window)) {
|
||||
del_shader = shader;
|
||||
gst_gl_window_send_message (display->gl_window,
|
||||
gst_gl_window_send_message (window,
|
||||
GST_GL_WINDOW_CB (_del_shader), display);
|
||||
}
|
||||
|
||||
gst_object_unref (window);
|
||||
gst_gl_display_unlock (display);
|
||||
}
|
||||
|
||||
|
|
|
@ -99,4 +99,6 @@ gboolean gst_gl_display_gen_shader (GstGLDisplay * display,
|
|||
const gchar * shader_fragment_source, GstGLShader ** shader);
|
||||
void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader);
|
||||
|
||||
gboolean gst_gl_display_check_framebuffer_status (GstGLDisplay * display);
|
||||
|
||||
#endif /* __GST_GL_UTILS_H__ */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#endif
|
||||
|
||||
#include <gmodule.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gstglwindow.h"
|
||||
|
||||
|
@ -39,12 +40,45 @@
|
|||
#include "wayland/gstglwindow_wayland_egl.h"
|
||||
#endif
|
||||
|
||||
#include "gstglfeature.h"
|
||||
|
||||
#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL)
|
||||
#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3)
|
||||
#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES)
|
||||
#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2)
|
||||
#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3)
|
||||
|
||||
#define GST_CAT_DEFAULT gst_gl_window_debug
|
||||
GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
||||
|
||||
#define gst_gl_window_parent_class parent_class
|
||||
G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT);
|
||||
|
||||
#define GST_GL_WINDOW_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate))
|
||||
|
||||
struct _GstGLWindowPrivate
|
||||
{
|
||||
GstGLDisplay *display;
|
||||
|
||||
GThread *gl_thread;
|
||||
|
||||
/* conditions */
|
||||
GMutex render_lock;
|
||||
GCond cond_create_context;
|
||||
GCond cond_destroy_context;
|
||||
|
||||
gboolean context_created;
|
||||
gboolean alive;
|
||||
|
||||
guintptr external_gl_context;
|
||||
GstGLAPI gl_api;
|
||||
GError **error;
|
||||
};
|
||||
|
||||
static gpointer _gst_gl_window_thread_create_context (GstGLWindow * window);
|
||||
static void gst_gl_window_finalize (GObject * object);
|
||||
|
||||
GQuark
|
||||
gst_gl_window_error_quark (void)
|
||||
{
|
||||
|
@ -54,19 +88,30 @@ gst_gl_window_error_quark (void)
|
|||
static void
|
||||
gst_gl_window_init (GstGLWindow * window)
|
||||
{
|
||||
window->priv = GST_GL_WINDOW_GET_PRIVATE (window);
|
||||
|
||||
g_mutex_init (&window->lock);
|
||||
window->need_lock = TRUE;
|
||||
|
||||
g_mutex_init (&window->priv->render_lock);
|
||||
g_cond_init (&window->priv->cond_create_context);
|
||||
g_cond_init (&window->priv->cond_destroy_context);
|
||||
window->priv->context_created = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_window_class_init (GstGLWindowClass * klass)
|
||||
{
|
||||
g_type_class_add_private (klass, sizeof (GstGLWindowPrivate));
|
||||
|
||||
klass->get_proc_address =
|
||||
GST_DEBUG_FUNCPTR (gst_gl_window_default_get_proc_address);
|
||||
|
||||
G_OBJECT_CLASS (klass)->finalize = gst_gl_window_finalize;
|
||||
}
|
||||
|
||||
GstGLWindow *
|
||||
gst_gl_window_new (void)
|
||||
gst_gl_window_new (GstGLDisplay * display)
|
||||
{
|
||||
GstGLWindow *window = NULL;
|
||||
const gchar *user_choice;
|
||||
|
@ -106,9 +151,43 @@ gst_gl_window_new (void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
window->priv->display = display;
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gl_window_finalize (GObject * object)
|
||||
{
|
||||
GstGLWindow *window = GST_GL_WINDOW (object);
|
||||
|
||||
if (window) {
|
||||
gst_gl_window_set_resize_callback (window, NULL, NULL);
|
||||
gst_gl_window_set_draw_callback (window, NULL, NULL);
|
||||
gst_gl_window_set_close_callback (window, NULL, NULL);
|
||||
|
||||
if (window->priv->alive) {
|
||||
GST_INFO ("send quit gl window loop");
|
||||
gst_gl_window_quit (window, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (window->priv->gl_thread) {
|
||||
gpointer ret = g_thread_join (window->priv->gl_thread);
|
||||
GST_INFO ("gl thread joined");
|
||||
if (ret != NULL)
|
||||
GST_ERROR ("gl thread returned a non-null pointer");
|
||||
window->priv->gl_thread = NULL;
|
||||
}
|
||||
|
||||
g_mutex_clear (&window->priv->render_lock);
|
||||
|
||||
g_cond_clear (&window->priv->cond_destroy_context);
|
||||
g_cond_clear (&window->priv->cond_create_context);
|
||||
|
||||
G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
guintptr
|
||||
gst_gl_window_get_gl_context (GstGLWindow * window)
|
||||
{
|
||||
|
@ -209,10 +288,17 @@ gst_gl_window_quit (GstGLWindow * window, GstGLWindowCB callback, gpointer data)
|
|||
|
||||
GST_GL_WINDOW_LOCK (window);
|
||||
|
||||
window->priv->alive = FALSE;
|
||||
|
||||
window->close = callback;
|
||||
window->close_data = data;
|
||||
window_class->quit (window, callback, data);
|
||||
|
||||
GST_INFO ("quit sent to gl window loop");
|
||||
|
||||
g_cond_wait (&window->priv->cond_destroy_context, &window->priv->render_lock);
|
||||
GST_INFO ("quit received from gl window");
|
||||
|
||||
GST_GL_WINDOW_UNLOCK (window);
|
||||
}
|
||||
|
||||
|
@ -331,7 +417,7 @@ gst_gl_window_get_proc_address (GstGLWindow * window, const gchar * name)
|
|||
|
||||
|
||||
gboolean
|
||||
gst_gl_window_create_context (GstGLWindow * window, GstGLAPI gl_api,
|
||||
_priv_gst_gl_window_create_context (GstGLWindow * window, GstGLAPI gl_api,
|
||||
guintptr external_gl_context, GError ** error)
|
||||
{
|
||||
gboolean ret;
|
||||
|
@ -368,3 +454,309 @@ gst_gl_window_default_get_proc_address (GstGLWindow * window,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create an opengl context (one context for one GstGLDisplay) */
|
||||
gboolean
|
||||
gst_gl_window_create_context (GstGLWindow * window,
|
||||
guintptr external_gl_context, GError ** error)
|
||||
{
|
||||
gboolean alive = FALSE;
|
||||
GstGLWindowClass *window_class;
|
||||
|
||||
g_return_val_if_fail (GST_GL_IS_WINDOW (window), FALSE);
|
||||
window_class = GST_GL_WINDOW_GET_CLASS (window);
|
||||
g_return_val_if_fail (window_class->create_context != NULL, FALSE);
|
||||
|
||||
g_mutex_lock (&window->priv->render_lock);
|
||||
|
||||
if (!window->priv->context_created) {
|
||||
window->priv->external_gl_context = external_gl_context;
|
||||
window->priv->error = error;
|
||||
|
||||
window->priv->gl_thread = g_thread_new ("gstglcontext",
|
||||
(GThreadFunc) _gst_gl_window_thread_create_context, window);
|
||||
|
||||
g_cond_wait (&window->priv->cond_create_context,
|
||||
&window->priv->render_lock);
|
||||
|
||||
window->priv->context_created = TRUE;
|
||||
|
||||
GST_INFO ("gl thread created");
|
||||
}
|
||||
|
||||
alive = window->priv->alive;
|
||||
|
||||
g_mutex_unlock (&window->priv->render_lock);
|
||||
|
||||
return alive;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_gl_window_is_running (GstGLWindow * window)
|
||||
{
|
||||
return window->priv->alive;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_create_context_gles2 (GstGLWindow * window, gint * gl_major, gint * gl_minor)
|
||||
{
|
||||
GstGLDisplay *display;
|
||||
const GstGLFuncs *gl;
|
||||
GLenum gl_err = GL_NO_ERROR;
|
||||
GError **error;
|
||||
|
||||
display = window->priv->display;
|
||||
gl = display->gl_vtable;
|
||||
error = window->priv->error;
|
||||
|
||||
GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
|
||||
GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
|
||||
gl->GetString (GL_SHADING_LANGUAGE_VERSION));
|
||||
GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
|
||||
GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
|
||||
|
||||
gl_err = gl->GetError ();
|
||||
if (gl_err != GL_NO_ERROR) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
|
||||
"glGetString error: 0x%x", gl_err);
|
||||
return FALSE;
|
||||
}
|
||||
#if GST_GL_HAVE_GLES2
|
||||
if (!GL_ES_VERSION_2_0) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS,
|
||||
"OpenGL|ES >= 2.0 is required");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
_gst_gl_feature_check_ext_functions (display, 0, 0,
|
||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
||||
|
||||
if (gl_major)
|
||||
*gl_major = 2;
|
||||
if (gl_minor)
|
||||
*gl_minor = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_create_context_opengl (GstGLWindow * window, gint * gl_major, gint * gl_minor)
|
||||
{
|
||||
GstGLDisplay *display;
|
||||
const GstGLFuncs *gl;
|
||||
guint maj, min;
|
||||
GLenum gl_err = GL_NO_ERROR;
|
||||
GString *opengl_version = NULL;
|
||||
GError **error;
|
||||
|
||||
display = window->priv->display;
|
||||
gl = display->gl_vtable;
|
||||
error = window->priv->error;
|
||||
|
||||
GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
|
||||
GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
|
||||
gl->GetString (GL_SHADING_LANGUAGE_VERSION));
|
||||
GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
|
||||
GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
|
||||
|
||||
gl_err = gl->GetError ();
|
||||
if (gl_err != GL_NO_ERROR) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
|
||||
"glGetString error: 0x%x", gl_err);
|
||||
return FALSE;
|
||||
}
|
||||
opengl_version =
|
||||
g_string_truncate (g_string_new ((gchar *) gl->GetString (GL_VERSION)),
|
||||
3);
|
||||
|
||||
sscanf (opengl_version->str, "%d.%d", &maj, &min);
|
||||
|
||||
g_string_free (opengl_version, TRUE);
|
||||
|
||||
/* OpenGL > 1.2.0 */
|
||||
if ((maj < 1) || (maj < 2 && maj >= 1 && min < 2)) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS,
|
||||
"OpenGL >= 1.2.0 required, found %u.%u", maj, min);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_gst_gl_feature_check_ext_functions (display, maj, min,
|
||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
||||
|
||||
if (gl_major)
|
||||
*gl_major = maj;
|
||||
if (gl_minor)
|
||||
*gl_minor = min;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
_compiled_api (void)
|
||||
{
|
||||
GstGLAPI ret = GST_GL_API_NONE;
|
||||
|
||||
#if GST_GL_HAVE_OPENGL
|
||||
ret |= GST_GL_API_OPENGL;
|
||||
#endif
|
||||
#if GST_GL_HAVE_GLES2
|
||||
ret |= GST_GL_API_GLES2;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstGLAPI
|
||||
_parse_gl_api (const gchar * apis_s)
|
||||
{
|
||||
GstGLAPI ret = GST_GL_API_NONE;
|
||||
gchar *apis = (gchar *) apis_s;
|
||||
|
||||
while (apis) {
|
||||
if (apis[0] == '\0') {
|
||||
break;
|
||||
} else if (apis[0] == ' ' || apis[0] == ',') {
|
||||
apis = &apis[1];
|
||||
} else if (g_strstr_len (apis, 7, "opengl3")) {
|
||||
ret |= GST_GL_API_OPENGL3;
|
||||
apis = &apis[7];
|
||||
} else if (g_strstr_len (apis, 6, "opengl")) {
|
||||
ret |= GST_GL_API_OPENGL;
|
||||
apis = &apis[6];
|
||||
} else if (g_strstr_len (apis, 5, "gles1")) {
|
||||
ret |= GST_GL_API_GLES;
|
||||
apis = &apis[5];
|
||||
} else if (g_strstr_len (apis, 5, "gles2")) {
|
||||
ret |= GST_GL_API_GLES2;
|
||||
apis = &apis[5];
|
||||
} else if (g_strstr_len (apis, 5, "gles3")) {
|
||||
ret |= GST_GL_API_GLES3;
|
||||
apis = &apis[5];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == GST_GL_API_NONE)
|
||||
ret = GST_GL_API_ANY;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_gst_gl_window_thread_create_context (GstGLWindow * window)
|
||||
{
|
||||
GstGLWindowClass *window_class;
|
||||
GstGLDisplay *display;
|
||||
GstGLFuncs *gl;
|
||||
gint gl_major = 0;
|
||||
gboolean ret = FALSE;
|
||||
GstGLAPI compiled_api, user_api;
|
||||
gchar *api_string;
|
||||
gchar *compiled_api_s;
|
||||
gchar *user_api_string;
|
||||
const gchar *user_choice;
|
||||
GError **error;
|
||||
|
||||
window_class = GST_GL_WINDOW_GET_CLASS (window);
|
||||
error = window->priv->error;
|
||||
display = window->priv->display;
|
||||
|
||||
g_mutex_lock (&window->priv->render_lock);
|
||||
|
||||
gl = display->gl_vtable;
|
||||
compiled_api = _compiled_api ();
|
||||
|
||||
user_choice = g_getenv ("GST_GL_API");
|
||||
|
||||
user_api = _parse_gl_api (user_choice);
|
||||
user_api_string = gst_gl_api_string (user_api);
|
||||
|
||||
compiled_api_s = gst_gl_api_string (compiled_api);
|
||||
|
||||
GST_INFO ("Attempting to create opengl context. user chosen api(s):%s, "
|
||||
"compiled api support:%s", user_api_string, compiled_api_s);
|
||||
|
||||
if (!window_class->create_context (window, compiled_api & user_api,
|
||||
window->priv->external_gl_context, error)) {
|
||||
g_assert (error == NULL || *error != NULL);
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
goto failure;
|
||||
}
|
||||
GST_INFO ("window created context");
|
||||
|
||||
display->gl_api = gst_gl_window_get_gl_api (window);
|
||||
g_assert (display->gl_api != GST_GL_API_NONE
|
||||
&& display->gl_api != GST_GL_API_ANY);
|
||||
|
||||
api_string = gst_gl_api_string (display->gl_api);
|
||||
GST_INFO ("available GL APIs: %s", api_string);
|
||||
|
||||
if (((compiled_api & display->gl_api) & user_api) == GST_GL_API_NONE) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API,
|
||||
"failed to create context, window "
|
||||
"could not provide correct api. user:%s, compiled:%s, window:%s",
|
||||
user_api_string, compiled_api_s, api_string);
|
||||
g_free (api_string);
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_free (api_string);
|
||||
g_free (compiled_api_s);
|
||||
g_free (user_api_string);
|
||||
|
||||
gl->GetError = gst_gl_window_get_proc_address (window, "glGetError");
|
||||
gl->GetString = gst_gl_window_get_proc_address (window, "glGetString");
|
||||
|
||||
if (!gl->GetError || !gl->GetString) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
|
||||
"could not GetProcAddress core opengl functions");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* gl api specific code */
|
||||
if (!ret && USING_OPENGL (display))
|
||||
ret = _create_context_opengl (window, &gl_major, NULL);
|
||||
if (!ret && USING_GLES2 (display))
|
||||
ret = _create_context_gles2 (window, &gl_major, NULL);
|
||||
|
||||
if (!ret || !gl_major) {
|
||||
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
|
||||
"GL api specific initialization failed");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_cond_signal (&window->priv->cond_create_context);
|
||||
|
||||
window->priv->alive = TRUE;
|
||||
g_mutex_unlock (&window->priv->render_lock);
|
||||
|
||||
gst_gl_window_run (window);
|
||||
|
||||
GST_INFO ("loop exited\n");
|
||||
|
||||
g_mutex_lock (&window->priv->render_lock);
|
||||
|
||||
window->priv->alive = FALSE;
|
||||
|
||||
// g_object_unref (G_OBJECT (display->gl_window));
|
||||
|
||||
// display->gl_window = NULL;
|
||||
|
||||
g_cond_signal (&window->priv->cond_destroy_context);
|
||||
|
||||
g_mutex_unlock (&window->priv->render_lock);
|
||||
|
||||
return NULL;
|
||||
|
||||
failure:
|
||||
{
|
||||
g_cond_signal (&window->priv->cond_create_context);
|
||||
g_mutex_unlock (&window->priv->render_lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
#ifndef __GST_GL_WINDOW_H__
|
||||
#define __GST_GL_WINDOW_H__
|
||||
|
||||
typedef struct _GstGLDisplay GstGLDisplay;
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstglapi.h"
|
||||
#include "gstgldisplay.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -90,6 +93,8 @@ struct _GstGLWindow {
|
|||
|
||||
/*< private >*/
|
||||
gpointer _reserved[GST_PADDING];
|
||||
|
||||
GstGLWindowPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GstGLWindowClass {
|
||||
|
@ -119,7 +124,7 @@ struct _GstGLWindowClass {
|
|||
GQuark gst_gl_window_error_quark (void);
|
||||
GType gst_gl_window_get_type (void);
|
||||
|
||||
GstGLWindow * gst_gl_window_new (void);
|
||||
GstGLWindow * gst_gl_window_new (GstGLDisplay *display);
|
||||
|
||||
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);
|
||||
|
@ -140,11 +145,12 @@ gpointer gst_gl_window_get_proc_address (GstGLWindow *window, const gchar *
|
|||
GstGLPlatform gst_gl_window_get_platform (GstGLWindow *window);
|
||||
GstGLAPI gst_gl_window_get_gl_api (GstGLWindow *window);
|
||||
|
||||
gboolean gst_gl_window_create_context (GstGLWindow *window, GstGLAPI gl_api,
|
||||
guintptr external_gl_context, GError ** error);
|
||||
gboolean gst_gl_window_create_context (GstGLWindow *window, guintptr external_gl_context, GError ** error);
|
||||
|
||||
gpointer gst_gl_window_default_get_proc_address (GstGLWindow *window, const gchar *name);
|
||||
|
||||
gboolean gst_gl_window_is_running (GstGLWindow *window);
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_gl_window_debug);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Reference in a new issue