qt/mlbasemodel: Add the 'getItemsForIndexes' function
[vlc.git] / src / video_output / opengl.c
blob778bd80a6e74ab74da63aff2beb1085af917bde1
1 /*****************************************************************************
2 * opengl.c: VLC GL API
3 *****************************************************************************
4 * Copyright (C) 2011 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <assert.h>
26 #include <stdlib.h>
28 #include <vlc_common.h>
29 #include <vlc_atomic.h>
30 #include <vlc_opengl.h>
31 #include <vlc_codec.h>
32 #include <vlc_vout_display.h>
33 #include "libvlc.h"
34 #include <vlc_modules.h>
36 struct vlc_gl_priv_t
38 vlc_gl_t gl;
39 vlc_atomic_rc_t rc;
42 static int vlc_gl_start(void *func, bool forced, va_list ap)
44 int (*activate)(vlc_gl_t *, unsigned, unsigned) = func;
45 vlc_gl_t *gl = va_arg(ap, vlc_gl_t *);
46 unsigned width = va_arg(ap, unsigned);
47 unsigned height = va_arg(ap, unsigned);
49 int ret = activate(gl, width, height);
50 if (ret)
51 vlc_objres_clear(VLC_OBJECT(gl));
52 (void) forced;
53 return ret;
56 vlc_gl_t *vlc_gl_Create(const struct vout_display_cfg *restrict cfg,
57 unsigned flags, const char *name)
59 vout_window_t *wnd = cfg->window;
60 struct vlc_gl_priv_t *glpriv;
61 const char *type;
63 enum vlc_gl_api_type api_type;
65 switch (flags /*& VLC_OPENGL_API_MASK*/)
67 case VLC_OPENGL:
68 type = "opengl";
69 api_type = VLC_OPENGL;
70 break;
71 case VLC_OPENGL_ES2:
72 type = "opengl es2";
73 api_type = VLC_OPENGL_ES2;
74 break;
75 default:
76 return NULL;
79 glpriv = vlc_custom_create(VLC_OBJECT(wnd), sizeof (*glpriv), "gl");
80 if (unlikely(glpriv == NULL))
81 return NULL;
83 vlc_gl_t *gl = &glpriv->gl;
84 gl->api_type = api_type;
85 gl->surface = wnd;
86 gl->module = vlc_module_load(gl, type, name, true, vlc_gl_start, gl,
87 cfg->display.width, cfg->display.height);
88 if (gl->module == NULL)
90 vlc_object_delete(gl);
91 return NULL;
93 assert(gl->make_current && gl->release_current && gl->swap
94 && gl->get_proc_address);
95 vlc_atomic_rc_init(&glpriv->rc);
97 return &glpriv->gl;
100 vlc_gl_t *vlc_gl_CreateOffscreen(vlc_object_t *parent,
101 struct vlc_decoder_device *device,
102 unsigned width, unsigned height,
103 unsigned flags, const char *name)
105 struct vlc_gl_priv_t *glpriv;
106 const char *type;
108 enum vlc_gl_api_type api_type;
110 switch (flags /*& VLC_OPENGL_API_MASK*/)
112 case VLC_OPENGL:
113 type = "opengl offscreen";
114 api_type = VLC_OPENGL;
115 break;
116 case VLC_OPENGL_ES2:
117 type = "opengl es2 offscreen";
118 api_type = VLC_OPENGL_ES2;
119 break;
120 default:
121 return NULL;
124 glpriv = vlc_custom_create(parent, sizeof (*glpriv), "gl");
125 if (unlikely(glpriv == NULL))
126 return NULL;
128 vlc_gl_t *gl = &glpriv->gl;
130 gl->api_type = api_type;
132 gl->offscreen_chroma_out = VLC_CODEC_UNKNOWN;
133 gl->offscreen_vflip = false;
134 gl->offscreen_vctx_out = NULL;
136 gl->surface = NULL;
137 gl->device = device ? vlc_decoder_device_Hold(device) : NULL;
138 gl->module = vlc_module_load(gl, type, name, true, vlc_gl_start, gl, width,
139 height);
140 if (gl->module == NULL)
142 vlc_object_delete(gl);
143 return NULL;
146 /* The implementation must initialize the output chroma */
147 assert(gl->offscreen_chroma_out != VLC_CODEC_UNKNOWN);
149 vlc_atomic_rc_init(&glpriv->rc);
151 assert(gl->make_current);
152 assert(gl->release_current);
153 assert(gl->swap_offscreen);
154 assert(gl->get_proc_address);
156 return &glpriv->gl;
159 void vlc_gl_Hold(vlc_gl_t *gl)
161 struct vlc_gl_priv_t *glpriv = (struct vlc_gl_priv_t *)gl;
162 vlc_atomic_rc_inc(&glpriv->rc);
165 void vlc_gl_Release(vlc_gl_t *gl)
167 struct vlc_gl_priv_t *glpriv = (struct vlc_gl_priv_t *)gl;
168 if (!vlc_atomic_rc_dec(&glpriv->rc))
169 return;
171 if (gl->destroy != NULL)
172 gl->destroy(gl);
173 vlc_objres_clear(VLC_OBJECT(gl));
174 vlc_object_delete(gl);
177 #include <vlc_vout_window.h>
179 typedef struct vlc_gl_surface
181 int width;
182 int height;
183 vlc_mutex_t lock;
184 } vlc_gl_surface_t;
186 static void vlc_gl_surface_ResizeNotify(vout_window_t *surface,
187 unsigned width, unsigned height)
189 vlc_gl_surface_t *sys = surface->owner.sys;
191 msg_Dbg(surface, "resized to %ux%u", width, height);
193 vlc_mutex_lock(&sys->lock);
194 sys->width = width;
195 sys->height = height;
196 vlc_mutex_unlock(&sys->lock);
199 vlc_gl_t *vlc_gl_surface_Create(vlc_object_t *obj,
200 const vout_window_cfg_t *cfg,
201 struct vout_window_t **restrict wp)
203 vlc_gl_surface_t *sys = malloc(sizeof (*sys));
204 if (unlikely(sys == NULL))
205 return NULL;
207 sys->width = cfg->width;
208 sys->height = cfg->height;
209 vlc_mutex_init(&sys->lock);
211 static const struct vout_window_callbacks cbs = {
212 .resized = vlc_gl_surface_ResizeNotify,
214 vout_window_owner_t owner = {
215 .cbs = &cbs,
216 .sys = sys,
218 char *modlist = var_InheritString(obj, "window");
220 vout_window_t *surface = vout_window_New(obj, modlist, &owner);
221 free(modlist);
222 if (surface == NULL)
223 goto error;
224 if (vout_window_Enable(surface, cfg)) {
225 vout_window_Delete(surface);
226 goto error;
228 if (wp != NULL)
229 *wp = surface;
231 /* TODO: support ES? */
232 struct vout_display_cfg dcfg = {
233 .window = surface,
234 .display = { .width = cfg->width, cfg->height },
237 vlc_mutex_lock(&sys->lock);
238 if (sys->width >= 0 && sys->height >= 0) {
239 dcfg.display.width = sys->width;
240 dcfg.display.height = sys->height;
241 sys->width = -1;
242 sys->height = -1;
244 vlc_mutex_unlock(&sys->lock);
246 vlc_gl_t *gl = vlc_gl_Create(&dcfg, VLC_OPENGL, NULL);
247 if (gl == NULL) {
248 vout_window_Disable(surface);
249 vout_window_Delete(surface);
250 goto error;
253 return gl;
255 error:
256 free(sys);
257 return NULL;
261 * Checks if the dimensions of the surface used by the OpenGL context have
262 * changed (since the previous call), and the OpenGL viewport should be
263 * updated.
264 * \return true if at least one dimension has changed, false otherwise
265 * \warning This function is intrinsically race-prone.
266 * The dimensions can change asynchronously.
268 bool vlc_gl_surface_CheckSize(vlc_gl_t *gl, unsigned *restrict width,
269 unsigned *restrict height)
271 vout_window_t *surface = gl->surface;
272 vlc_gl_surface_t *sys = surface->owner.sys;
273 bool ret = false;
275 vlc_mutex_lock(&sys->lock);
276 if (sys->width >= 0 && sys->height >= 0)
278 *width = sys->width;
279 *height = sys->height;
280 sys->width = -1;
281 sys->height = -1;
283 vlc_gl_Resize(gl, *width, *height);
284 ret = true;
286 vlc_mutex_unlock(&sys->lock);
287 return ret;
290 void vlc_gl_surface_Destroy(vlc_gl_t *gl)
292 vout_window_t *surface = gl->surface;
293 vlc_gl_surface_t *sys = surface->owner.sys;
295 vlc_gl_Release(gl);
296 vout_window_Disable(surface);
297 vout_window_Delete(surface);
298 free(sys);