Revert "gl: Use GstGLDisplayEGL directly instead of creating a GstGLDisplayVIVFb...
[platform/upstream/gst-plugins-good.git] / ext / qt / gstqtglutility.cc
1 /*
2  * GStreamer
3  * Copyright (C) 2016 Freescale Semiconductor, Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstqtglutility.h"
26 #include <QtGui/QGuiApplication>
27
28 #if GST_GL_HAVE_WINDOW_X11 && defined (HAVE_QT_X11)
29 #include <QX11Info>
30 #include <gst/gl/x11/gstgldisplay_x11.h>
31 #if GST_GL_HAVE_PLATFORM_GLX
32 #include <gst/gl/x11/gstglcontext_glx.h>
33 #elif GST_GL_HAVE_PLATFORM_EGL
34 #include <gst/gl/egl/gstglcontext_egl.h>
35 #endif
36 #endif
37
38 #if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_WAYLAND)
39 #include <qpa/qplatformnativeinterface.h>
40 #include <gst/gl/wayland/gstgldisplay_wayland.h>
41 #endif
42
43 #if GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_EGLFS)
44 #if GST_GL_HAVE_WINDOW_VIV_FB
45 #include <qpa/qplatformnativeinterface.h>
46 #include <gst/gl/viv-fb/gstgldisplay_viv_fb.h>
47 #else
48 #include <gst/gl/egl/gstegl.h>
49 #include <gst/gl/egl/gstgldisplay_egl.h>
50 #endif
51 #include <gst/gl/egl/gstglcontext_egl.h>
52 #endif
53
54 #if GST_GL_HAVE_WINDOW_COCOA && GST_GL_HAVE_PLATFORM_CGL && defined (HAVE_QT_MAC)
55 #include <gst/gl/cocoa/gstgldisplay_cocoa.h>
56 #endif
57
58 #define GST_CAT_DEFAULT qt_gl_utils_debug
59 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
60
61 GstGLDisplay *
62 gst_qt_get_gl_display ()
63 {
64   GstGLDisplay *display = NULL;
65   QGuiApplication *app = static_cast<QGuiApplication *> (QCoreApplication::instance ());
66   static volatile gsize _debug;
67
68   g_assert (app != NULL);
69
70   if (g_once_init_enter (&_debug)) {
71     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "qtglutility", 0,
72         "Qt gl utility functions");
73     g_once_init_leave (&_debug, 1);
74   }
75   GST_INFO ("QGuiApplication::instance()->platformName() %s", app->platformName().toUtf8().data());
76
77 #if GST_GL_HAVE_WINDOW_X11 && defined (HAVE_QT_X11)
78   if (QString::fromUtf8 ("xcb") == app->platformName())
79     display = (GstGLDisplay *)
80         gst_gl_display_x11_new_with_display (QX11Info::display ());
81 #endif
82 #if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_WAYLAND)
83   if (QString::fromUtf8 ("wayland") == app->platformName()
84         || QString::fromUtf8 ("wayland-egl") == app->platformName()){
85     struct wl_display * wayland_display;
86     QPlatformNativeInterface *native =
87         QGuiApplication::platformNativeInterface();
88     wayland_display = (struct wl_display *)
89         native->nativeResourceForWindow("display", NULL);
90     display = (GstGLDisplay *)
91         gst_gl_display_wayland_new_with_display (wayland_display);
92   }
93 #endif
94 #if GST_GL_HAVE_PLATFORM_EGL && GST_GL_HAVE_WINDOW_ANDROID
95   if (QString::fromUtf8 ("android") == app->platformName())
96     display = (GstGLDisplay *) gst_gl_display_egl_new_with_egl_display (eglGetDisplay(EGL_DEFAULT_DISPLAY));
97 #elif GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_EGLFS)
98   if (QString::fromUtf8("eglfs") == app->platformName()) {
99 #if GST_GL_HAVE_WINDOW_VIV_FB
100     /* FIXME: Could get the display directly from Qt like this
101       QPlatformNativeInterface *native =
102           QGuiApplication::platformNativeInterface();
103       EGLDisplay egl_display = (EGLDisplay)
104           native->nativeResourceForWindow("egldisplay", NULL);
105
106       However we seem to have no way for getting the EGLNativeDisplayType, aka
107       native_display, via public API. As such we have to assume that display 0
108       is always used. Only way around that is parsing the index the same way as
109       Qt does in QEGLDeviceIntegration::fbDeviceName(), so let's do that.
110     */
111     const gchar *fb_dev;
112     gint disp_idx = 0;
113
114     fb_dev = g_getenv ("QT_QPA_EGLFS_FB");
115     if (fb_dev) {
116       if (sscanf (fb_dev, "/dev/fb%d", &disp_idx) != 1)
117         disp_idx = 0;
118     }
119
120     display = (GstGLDisplay *) gst_gl_display_viv_fb_new (disp_idx);
121 #else
122     display = (GstGLDisplay *) gst_gl_display_egl_new_with_egl_display (eglGetDisplay(EGL_DEFAULT_DISPLAY));
123 #endif
124   }
125 #endif
126
127 #if GST_GL_HAVE_WINDOW_COCOA && GST_GL_HAVE_PLATFORM_CGL && defined (HAVE_QT_MAC)
128   if (QString::fromUtf8 ("cocoa") == app->platformName())
129     display = (GstGLDisplay *) gst_gl_display_cocoa_new ();
130 #endif
131 #if GST_GL_HAVE_WINDOW_EAGL && GST_GL_HAVE_PLATFORM_EAGL && defined (HAVE_QT_IOS)
132   if (QString::fromUtf8 ("ios") == app->platformName())
133     display = gst_gl_display_new ();
134 #endif
135 #if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (HAVE_QT_WIN32)
136   if (QString::fromUtf8 ("windows") == app->platformName())
137     display = gst_gl_display_new ();
138 #endif
139
140   if (!display)
141     display = gst_gl_display_new ();
142
143   return display;
144 }
145
146 gboolean
147 gst_qt_get_gl_wrapcontext (GstGLDisplay * display,
148     GstGLContext **wrap_glcontext, GstGLContext **context)
149 {
150   GstGLPlatform platform = (GstGLPlatform) 0;
151   GstGLAPI gl_api;
152   guintptr gl_handle;
153   GError *error = NULL;
154
155   g_return_val_if_fail (display != NULL && wrap_glcontext != NULL, FALSE);
156
157 #if GST_GL_HAVE_WINDOW_X11 && defined (HAVE_QT_X11)
158   if (GST_IS_GL_DISPLAY_X11 (display)) {
159 #if GST_GL_HAVE_PLATFORM_GLX
160     platform = GST_GL_PLATFORM_GLX;
161 #elif GST_GL_HAVE_PLATFORM_EGL
162     platform = GST_GL_PLATFORM_EGL;
163 #endif
164   }
165 #endif
166 #if GST_GL_HAVE_WINDOW_WAYLAND && defined (HAVE_QT_WAYLAND)
167   if (GST_IS_GL_DISPLAY_WAYLAND (display)) {
168     platform = GST_GL_PLATFORM_EGL;
169   }
170 #endif
171 #if GST_GL_HAVE_PLATFORM_EGL && defined (HAVE_QT_EGLFS)
172 #if GST_GL_HAVE_WINDOW_VIV_FB
173   if (GST_IS_GL_DISPLAY_VIV_FB (display)) {
174 #else
175   if (GST_IS_GL_DISPLAY_EGL (display)) {
176 #endif
177     platform = GST_GL_PLATFORM_EGL;
178   }
179 #endif
180   if (platform == 0) {
181 #if GST_GL_HAVE_WINDOW_COCOA && GST_GL_HAVE_PLATFORM_CGL && defined (HAVE_QT_MAC)
182     platform = GST_GL_PLATFORM_CGL;
183 #elif GST_GL_HAVE_WINDOW_EAGL && GST_GL_HAVE_PLATFORM_EAGL && defined (HAVE_QT_IOS)
184     platform = GST_GL_PLATFORM_EAGL;
185 #elif GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (HAVE_QT_WIN32)
186     platform = GST_GL_PLATFORM_WGL;
187 #else
188     GST_ERROR ("Unknown platform");
189     return FALSE;
190 #endif
191   }
192
193   gl_api = gst_gl_context_get_current_gl_api (platform, NULL, NULL);
194   gl_handle = gst_gl_context_get_current_gl_context (platform);
195   if (gl_handle)
196     *wrap_glcontext =
197         gst_gl_context_new_wrapped (display, gl_handle,
198         platform, gl_api);
199
200   if (!*wrap_glcontext) {
201     GST_ERROR ("cannot wrap qt OpenGL context");
202     return FALSE;
203   }
204  
205   (void) platform;
206   (void) gl_api;
207   (void) gl_handle;
208
209   gst_gl_context_activate (*wrap_glcontext, TRUE);
210   if (!gst_gl_context_fill_info (*wrap_glcontext, &error)) {
211     GST_ERROR ("failed to retrieve qt context info: %s", error->message);
212     g_object_unref (*wrap_glcontext);
213     *wrap_glcontext = NULL;
214     return FALSE;
215   } else {
216     gst_gl_display_filter_gl_api (display, gst_gl_context_get_gl_api (*wrap_glcontext));
217 #if GST_GL_HAVE_WINDOW_WIN32 && GST_GL_HAVE_PLATFORM_WGL && defined (HAVE_QT_WIN32)  
218     g_return_val_if_fail (context != NULL, FALSE);
219
220     G_STMT_START {
221       GstGLWindow *window;
222       HDC device;
223
224       /* If there's no wglCreateContextAttribsARB() support, then we would fallback to
225        * wglShareLists() which will fail with ERROR_BUSY (0xaa) if either of the GL
226        * contexts are current in any other thread.
227        *
228        * The workaround here is to temporarily disable Qt's GL context while we
229        * set up our own.
230        *
231        * Sometimes wglCreateContextAttribsARB()
232        * exists, but isn't functional (some Intel drivers), so it's easiest to do this
233        * unconditionally.
234        */
235       *context = gst_gl_context_new (display);
236       window = gst_gl_context_get_window (*context);
237       device = (HDC) gst_gl_window_get_display (window);
238
239       wglMakeCurrent (device, 0);
240       gst_object_unref (window);
241       if (!gst_gl_context_create (*context, *wrap_glcontext, &error)) {
242         GST_ERROR ("%p failed to create shared GL context: %s", this, error->message);
243         g_object_unref (*context);
244         *context = NULL;
245         g_object_unref (*wrap_glcontext);
246         *wrap_glcontext = NULL;
247         wglMakeCurrent (device, (HGLRC) gl_handle);
248         return FALSE;
249       }
250       wglMakeCurrent (device, (HGLRC) gl_handle);
251     }
252 #endif
253     gst_gl_context_activate (*wrap_glcontext, FALSE);
254   } G_STMT_END;
255
256   return TRUE;
257 }