]> git.sesse.net Git - vlc/blob - modules/video_output/gl.c
Used WGL_EXT_swap_control in glwin32.
[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 library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12  *
13  * This library 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 General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, 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", /*165*/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", /*160*/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_("Open Graphics Library video output"))
73     set_category (CAT_VIDEO)
74     set_subcategory (SUBCAT_VIDEO_VOUT)
75     set_capability ("vout display", /*170*/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
87     vout_window_t *window;
88     vlc_gl_t *gl;
89     picture_pool_t *pool;
90 };
91
92 /* Display callbacks */
93 static picture_pool_t *Pool (vout_display_t *, unsigned);
94 static void PictureRender (vout_display_t *, picture_t *, subpicture_t *);
95 static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
96 static int Control (vout_display_t *, int, va_list);
97
98 static vout_window_t *MakeWindow (vout_display_t *vd)
99 {
100     vout_window_cfg_t wnd_cfg;
101
102     memset (&wnd_cfg, 0, sizeof (wnd_cfg));
103     wnd_cfg.type = VOUT_WINDOW_TYPE_NATIVE;
104     wnd_cfg.x = var_InheritInteger (vd, "video-x");
105     wnd_cfg.y = var_InheritInteger (vd, "video-y");
106     wnd_cfg.width  = vd->cfg->display.width;
107     wnd_cfg.height = vd->cfg->display.height;
108
109     vout_window_t *wnd = vout_display_NewWindow (vd, &wnd_cfg);
110     if (wnd == NULL)
111         msg_Err (vd, "parent window not available");
112     return wnd;
113 }
114
115 /**
116  * Allocates a surface and an OpenGL context for video output.
117  */
118 static int Open (vlc_object_t *obj)
119 {
120     vout_display_t *vd = (vout_display_t *)obj;
121     vout_display_sys_t *sys = malloc (sizeof (*sys));
122     if (unlikely(sys == NULL))
123         return VLC_ENOMEM;
124
125     sys->gl = NULL;
126     sys->pool = NULL;
127
128     sys->window = MakeWindow (vd);
129     if (sys->window == NULL)
130         goto error;
131
132     sys->gl = vlc_gl_Create (sys->window, API, "$" MODULE_VARNAME);
133     if (sys->gl == NULL)
134         goto error;
135
136     if (vlc_gl_MakeCurrent (sys->gl))
137         goto error;
138
139     /* Initialize video display */
140     sys->vgl = vout_display_opengl_New (&vd->fmt, NULL, sys->gl);
141     if (!sys->vgl)
142         goto error;
143
144     vd->sys = sys;
145     vd->info.has_pictures_invalid = false;
146     vd->info.has_event_thread = false;
147     vd->pool = Pool;
148     vd->prepare = PictureRender;
149     vd->display = PictureDisplay;
150     vd->control = Control;
151     vd->manage = NULL;
152     return VLC_SUCCESS;
153
154 error:
155     if (sys->gl != NULL)
156         vlc_gl_Destroy (sys->gl);
157     if (sys->window != NULL)
158         vout_display_DeleteWindow (vd, sys->window);
159     free (sys);
160     return VLC_EGENERIC;
161 }
162
163 /**
164  * Destroys the OpenGL context.
165  */
166 static void Close (vlc_object_t *obj)
167 {
168     vout_display_t *vd = (vout_display_t *)obj;
169     vout_display_sys_t *sys = vd->sys;
170
171     vout_display_opengl_Delete (sys->vgl);
172     vlc_gl_Destroy (sys->gl);
173     vout_display_DeleteWindow (vd, sys->window);
174     free (sys);
175 }
176
177 /**
178  * Returns picture buffers
179  */
180 static picture_pool_t *Pool (vout_display_t *vd, unsigned count)
181 {
182     vout_display_sys_t *sys = vd->sys;
183
184     if (!sys->pool)
185         sys->pool = vout_display_opengl_GetPool (sys->vgl, count);
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     vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
194 }
195
196 static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
197 {
198     vout_display_sys_t *sys = vd->sys;
199
200     vout_display_opengl_Display (sys->vgl, &vd->source);
201     picture_Release (pic);
202     (void)subpicture;
203 }
204
205 static int Control (vout_display_t *vd, int query, va_list ap)
206 {
207     vout_display_sys_t *sys = vd->sys;
208
209     switch (query)
210     {
211       case VOUT_DISPLAY_HIDE_MOUSE: /* FIXME TODO */
212         break;
213 #ifndef NDEBUG
214       case VOUT_DISPLAY_RESET_PICTURES: // not needed
215         assert(0);
216 #endif
217       case VOUT_DISPLAY_CHANGE_FULLSCREEN:
218       {
219         const vout_display_cfg_t *cfg =
220             va_arg (ap, const vout_display_cfg_t *);
221
222         return vout_window_SetFullScreen (sys->window, cfg->is_fullscreen);
223       }
224
225       case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
226       {
227         unsigned state = va_arg (ap, unsigned);
228
229         return vout_window_SetState (sys->window, state);
230       }
231
232       case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
233       case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
234       case VOUT_DISPLAY_CHANGE_ZOOM:
235       {
236         const vout_display_cfg_t *cfg = va_arg (ap, const vout_display_cfg_t *);
237         const video_format_t *src = &vd->source;
238
239         if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE)
240         {
241             bool force = false;
242
243             force = va_arg (ap, int);
244             if (force
245              && (cfg->display.width  != vd->cfg->display.width
246               || cfg->display.height != vd->cfg->display.height)
247              && vout_window_SetSize (sys->window,
248                                      cfg->display.width, cfg->display.height))
249                 return VLC_EGENERIC;
250         }
251
252         vout_display_place_t place;
253
254         vout_display_PlacePicture (&place, src, cfg, false);
255         glViewport (0, 0, place.width, place.height);
256         return VLC_SUCCESS;
257       }
258
259       case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
260       case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
261       {
262         const vout_display_cfg_t *cfg = vd->cfg;
263         const video_format_t *src = va_arg (ap, const video_format_t *);
264         vout_display_place_t place;
265
266         vout_display_PlacePicture (&place, src, cfg, false);
267         glViewport (0, 0, place.width, place.height);
268         return VLC_SUCCESS;
269       }
270
271       case VOUT_DISPLAY_GET_OPENGL:
272       {
273         vlc_gl_t **pgl = va_arg (ap, vlc_gl_t **);
274
275         *pgl = sys->gl;
276         return VLC_SUCCESS;
277       }
278
279       default:
280         msg_Err (vd, "Unknown request %d", query);
281     }
282     return VLC_EGENERIC;
283 }