]> git.sesse.net Git - vlc/blob - modules/video_output/gl.c
decoder: fix data race in input_DecoderFrameNext()
[vlc] / modules / video_output / gl.c
1 /**
2  * @file gl.c
3  * @brief OpenGL video output module
4  */
5 /*****************************************************************************
6  * Copyright © 2010-2011 Rémi Denis-Courmont
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <assert.h>
29
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_vout_display.h>
33 #include <vlc_opengl.h>
34 #include "opengl.h"
35
36 /* Plugin callbacks */
37 static int Open (vlc_object_t *);
38 static void Close (vlc_object_t *);
39
40 #define GL_TEXT N_("OpenGL extension")
41 #define GLES2_TEXT N_("OpenGL ES 2 extension")
42 #define GLES_TEXT N_("OpenGL ES extension")
43 #define PROVIDER_LONGTEXT N_( \
44     "Extension through which to use the Open Graphics Library (OpenGL).")
45
46 vlc_module_begin ()
47 #if USE_OPENGL_ES == 2
48 # define API VLC_OPENGL_ES2
49 # define MODULE_VARNAME "gles2"
50     set_shortname (N_("OpenGL ES2"))
51     set_description (N_("OpenGL for Embedded Systems 2 video output"))
52     set_capability ("vout display", /*265*/0)
53     set_callbacks (Open, Close)
54     add_shortcut ("opengles2", "gles2")
55     add_module ("gles2", "opengl es2", NULL,
56                 GLES2_TEXT, PROVIDER_LONGTEXT, true)
57
58 #elif USE_OPENGL_ES == 1
59 # define API VLC_OPENGL_ES
60 # define MODULE_VARNAME "gles"
61     set_shortname (N_("OpenGL ES"))
62     set_description (N_("OpenGL for Embedded Systems video output"))
63     set_capability ("vout display", /*260*/0)
64     set_callbacks (Open, Close)
65     add_shortcut ("opengles", "gles")
66     add_module ("gles", "opengl es", NULL,
67                 GLES_TEXT, PROVIDER_LONGTEXT, true)
68 #else
69 # define API VLC_OPENGL
70 # define MODULE_VARNAME "gl"
71     set_shortname (N_("OpenGL"))
72     set_description (N_("OpenGL video output (experimental)"))
73     set_category (CAT_VIDEO)
74     set_subcategory (SUBCAT_VIDEO_VOUT)
75     set_capability ("vout display", /*270*/0)
76     set_callbacks (Open, Close)
77     add_shortcut ("opengl", "gl")
78     add_module ("gl", "opengl", NULL,
79                 GL_TEXT, PROVIDER_LONGTEXT, true)
80 #endif
81 vlc_module_end ()
82
83 struct vout_display_sys_t
84 {
85     vout_display_opengl_t *vgl;
86     vlc_gl_t *gl;
87     picture_pool_t *pool;
88 };
89
90 /* Display callbacks */
91 static picture_pool_t *Pool (vout_display_t *, unsigned);
92 static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
93 static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
94 static int Control (vout_display_t *, int, va_list);
95
96 /**
97  * Allocates a surface and an OpenGL context for video output.
98  */
99 static int Open (vlc_object_t *obj)
100 {
101     vout_display_t *vd = (vout_display_t *)obj;
102     vout_display_sys_t *sys = malloc (sizeof (*sys));
103     if (unlikely(sys == NULL))
104         return VLC_ENOMEM;
105
106     sys->gl = NULL;
107     sys->pool = NULL;
108
109     vout_window_t *surface = vout_display_NewWindow (vd, VOUT_WINDOW_TYPE_INVALID);
110     if (surface == NULL)
111     {
112         msg_Err (vd, "parent window not available");
113         goto error;
114     }
115
116     sys->gl = vlc_gl_Create (surface, API, "$" MODULE_VARNAME);
117     if (sys->gl == NULL)
118         goto error;
119
120     vlc_gl_Resize (sys->gl, vd->cfg->display.width, vd->cfg->display.height);
121
122     /* Initialize video display */
123     const vlc_fourcc_t *spu_chromas;
124
125     if (vlc_gl_MakeCurrent (sys->gl))
126         goto error;
127
128     sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
129     vlc_gl_ReleaseCurrent (sys->gl);
130
131     if (sys->vgl == NULL)
132         goto error;
133
134     vd->sys = sys;
135     vd->info.has_pictures_invalid = false;
136     vd->info.has_event_thread = false;
137     vd->info.subpicture_chromas = spu_chromas;
138     vd->pool = Pool;
139     vd->prepare = PictureRender;
140     vd->display = PictureDisplay;
141     vd->control = Control;
142     vd->manage = NULL;
143     return VLC_SUCCESS;
144
145 error:
146     if (sys->gl != NULL)
147         vlc_gl_Destroy (sys->gl);
148     if (surface != NULL)
149         vout_display_DeleteWindow (vd, surface);
150     free (sys);
151     return VLC_EGENERIC;
152 }
153
154 /**
155  * Destroys the OpenGL context.
156  */
157 static void Close (vlc_object_t *obj)
158 {
159     vout_display_t *vd = (vout_display_t *)obj;
160     vout_display_sys_t *sys = vd->sys;
161     vlc_gl_t *gl = sys->gl;
162     vout_window_t *surface = gl->surface;
163
164     vlc_gl_MakeCurrent (gl);
165     vout_display_opengl_Delete (sys->vgl);
166     vlc_gl_ReleaseCurrent (gl);
167
168     vlc_gl_Destroy (gl);
169     vout_display_DeleteWindow (vd, surface);
170     free (sys);
171 }
172
173 /**
174  * Returns picture buffers
175  */
176 static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
177 {
178     vout_display_sys_t *sys = vd->sys;
179
180     if (!sys->pool)
181     {
182         vlc_gl_MakeCurrent (sys->gl);
183         sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
184         vlc_gl_ReleaseCurrent (sys->gl);
185     }
186     return sys->pool;
187 }
188
189 static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
190 {
191     vout_display_sys_t *sys = vd->sys;
192
193     vlc_gl_MakeCurrent (sys->gl);
194     vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
195     vlc_gl_ReleaseCurrent (sys->gl);
196 }
197
198 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
199 {
200     vout_display_sys_t *sys = vd->sys;
201
202     vlc_gl_MakeCurrent (sys->gl);
203     vout_display_opengl_Display (sys->vgl, &vd->source);
204     vlc_gl_ReleaseCurrent (sys->gl);
205
206     picture_Release (pic);
207     (void) subpicture;
208 }
209
210 static int Control (vout_display_t *vd, int query, va_list ap)
211 {
212     vout_display_sys_t *sys = vd->sys;
213
214     switch (query)
215     {
216       case VOUT_DISPLAY_HIDE_MOUSE: /* FIXME TODO */
217         break;
218 #ifndef NDEBUG
219       case VOUT_DISPLAY_RESET_PICTURES: // not needed
220         vlc_assert_unreachable();
221 #endif
222
223       case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
224       case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
225       case VOUT_DISPLAY_CHANGE_ZOOM:
226       {
227         const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
228         const video_format_t *src = &vd->source;
229         vout_display_place_t place;
230
231         vout_display_PlacePicture (&place, src, c, false);
232         vlc_gl_Resize (sys->gl, place.width, place.height);
233         vlc_gl_MakeCurrent (sys->gl);
234         glViewport (place.x, place.y, place.width, place.height);
235         vlc_gl_ReleaseCurrent (sys->gl);
236         return VLC_SUCCESS;
237       }
238
239       case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
240       case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
241       {
242         const vout_display_cfg_t *cfg = vd->cfg;
243         const video_format_t *src = va_arg (ap, const video_format_t *);
244         vout_display_place_t place;
245
246         vout_display_PlacePicture (&place, src, cfg, false);
247         vlc_gl_MakeCurrent (sys->gl);
248         glViewport (place.x, place.y, place.width, place.height);
249         vlc_gl_ReleaseCurrent (sys->gl);
250         return VLC_SUCCESS;
251       }
252       default:
253         msg_Err (vd, "Unknown request %d", query);
254     }
255     return VLC_EGENERIC;
256 }