f3c5436beef2c1ebfa76729b087d665e8c1a081c
[platform/upstream/gstreamer.git] / gst-libs / gst / gl / android / gstglwindow_android_egl.c
1 /*
2  * GStreamer
3  * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
4  * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
5  * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /* TODO: - Window resize handling
24  *       - Event handling input event handling
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <gst/gst.h>
32
33 #include <gst/gl/egl/gstglcontext_egl.h>
34 #include "gstglwindow_android_egl.h"
35
36 #define GST_CAT_DEFAULT gst_gl_window_debug
37
38 #define gst_gl_window_android_egl_parent_class parent_class
39 G_DEFINE_TYPE (GstGLWindowAndroidEGL, gst_gl_window_android_egl,
40     GST_GL_TYPE_WINDOW);
41 static void gst_gl_window_android_egl_finalize (GObject * object);
42
43 static guintptr gst_gl_window_android_egl_get_display (GstGLWindow * window);
44 static guintptr gst_gl_window_android_egl_get_window_handle (GstGLWindow *
45     window);
46 static void gst_gl_window_android_egl_set_window_handle (GstGLWindow * window,
47     guintptr handle);
48 static void gst_gl_window_android_egl_draw (GstGLWindow * window);
49 static void gst_gl_window_android_egl_run (GstGLWindow * window);
50 static void gst_gl_window_android_egl_quit (GstGLWindow * window);
51 static void gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
52     GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
53 static gboolean gst_gl_window_android_egl_open (GstGLWindow * window,
54     GError ** error);
55 static void gst_gl_window_android_egl_close (GstGLWindow * window);
56
57 static void
58 gst_gl_window_android_egl_class_init (GstGLWindowAndroidEGLClass * klass)
59 {
60   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
61   GObjectClass *gobject_class = (GObjectClass *) klass;
62
63   window_class->get_display =
64       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_get_display);
65   window_class->get_window_handle =
66       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_get_window_handle);
67   window_class->set_window_handle =
68       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_set_window_handle);
69   window_class->draw_unlocked =
70       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_draw);
71   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_draw);
72   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_run);
73   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_quit);
74   window_class->send_message_async =
75       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message_async);
76   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_open);
77   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_close);
78
79   gobject_class->finalize = gst_gl_window_android_egl_finalize;
80 }
81
82 static void
83 gst_gl_window_android_egl_init (GstGLWindowAndroidEGL * window)
84 {
85   window->main_context = g_main_context_new ();
86   window->loop = g_main_loop_new (window->main_context, FALSE);
87 }
88
89 static void
90 gst_gl_window_android_egl_finalize (GObject * object)
91 {
92   GstGLWindowAndroidEGL *window_egl = GST_GL_WINDOW_ANDROID_EGL (object);
93
94   g_main_loop_unref (window_egl->loop);
95   g_main_context_unref (window_egl->main_context);
96
97   G_OBJECT_CLASS (parent_class)->finalize (object);
98 }
99
100 /* Must be called in the gl thread */
101 GstGLWindowAndroidEGL *
102 gst_gl_window_android_egl_new (void)
103 {
104   GstGLWindowAndroidEGL *window;
105
106   GST_DEBUG ("creating Android EGL window");
107
108   window = g_object_new (GST_GL_TYPE_WINDOW_ANDROID_EGL, NULL);
109
110   return window;
111 }
112
113 static gboolean
114 gst_gl_window_android_egl_open (GstGLWindow * window, GError ** error)
115 {
116   return TRUE;
117 }
118
119 static void
120 gst_gl_window_android_egl_close (GstGLWindow * window)
121 {
122 }
123
124 static void
125 gst_gl_window_android_egl_run (GstGLWindow * window)
126 {
127   GstGLWindowAndroidEGL *window_egl;
128
129   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
130
131   GST_LOG ("starting main loop");
132   g_main_loop_run (window_egl->loop);
133   GST_LOG ("exiting main loop");
134 }
135
136 static void
137 gst_gl_window_android_egl_quit (GstGLWindow * window)
138 {
139   GstGLWindowAndroidEGL *window_egl;
140
141   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
142
143   GST_LOG ("sending quit");
144
145   g_main_loop_quit (window_egl->loop);
146
147   GST_LOG ("quit sent");
148 }
149
150 typedef struct _GstGLMessage
151 {
152   GstGLWindowCB callback;
153   gpointer data;
154   GDestroyNotify destroy;
155 } GstGLMessage;
156
157 static gboolean
158 _run_message (GstGLMessage * message)
159 {
160   if (message->callback)
161     message->callback (message->data);
162
163   if (message->destroy)
164     message->destroy (message->data);
165
166   g_slice_free (GstGLMessage, message);
167
168   return FALSE;
169 }
170
171 static void
172 gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
173     GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
174 {
175   GstGLWindowAndroidEGL *window_egl;
176   GstGLMessage *message;
177
178   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
179   message = g_slice_new (GstGLMessage);
180
181   message->callback = callback;
182   message->data = data;
183   message->destroy = destroy;
184
185   g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
186       message);
187 }
188
189 static void
190 gst_gl_window_android_egl_set_window_handle (GstGLWindow * window,
191     guintptr handle)
192 {
193   GstGLWindowAndroidEGL *window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
194
195   window_egl->native_window = (EGLNativeWindowType) handle;
196 }
197
198 static guintptr
199 gst_gl_window_android_egl_get_window_handle (GstGLWindow * window)
200 {
201   GstGLWindowAndroidEGL *window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
202
203   return (guintptr) window_egl->native_window;
204 }
205
206 static void
207 draw_cb (gpointer data)
208 {
209   GstGLWindowAndroidEGL *window_egl = data;
210   GstGLWindow *window = GST_GL_WINDOW (window_egl);
211   GstGLContext *context = gst_gl_window_get_context (window);
212   GstGLContextEGL *context_egl = GST_GL_CONTEXT_EGL (context);
213   GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
214
215   if (context_egl->egl_surface) {
216     gint width, height;
217
218     if (eglQuerySurface (context_egl->egl_display,
219             context_egl->egl_surface, EGL_WIDTH, &width) &&
220         eglQuerySurface (context_egl->egl_display,
221             context_egl->egl_surface, EGL_HEIGHT, &height)
222         && (width != window_egl->window_width
223             || height != window_egl->window_height)) {
224       window_egl->window_width = width;
225       window_egl->window_height = height;
226
227       if (window->resize)
228         window->resize (window->resize_data, width, height);
229     }
230   }
231
232   if (window->draw)
233     window->draw (window->draw_data);
234
235   context_class->swap_buffers (context);
236
237   gst_object_unref (context);
238 }
239
240 static void
241 gst_gl_window_android_egl_draw (GstGLWindow * window)
242 {
243   gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, window);
244 }
245
246 static guintptr
247 gst_gl_window_android_egl_get_display (GstGLWindow * window)
248 {
249   return 0;
250 }