1 /*****************************************************************************
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 *****************************************************************************/
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>
34 #include <vlc_modules.h>
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
);
51 vlc_objres_clear(VLC_OBJECT(gl
));
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
;
63 enum vlc_gl_api_type api_type
;
65 switch (flags
/*& VLC_OPENGL_API_MASK*/)
69 api_type
= VLC_OPENGL
;
73 api_type
= VLC_OPENGL_ES2
;
79 glpriv
= vlc_custom_create(VLC_OBJECT(wnd
), sizeof (*glpriv
), "gl");
80 if (unlikely(glpriv
== NULL
))
83 vlc_gl_t
*gl
= &glpriv
->gl
;
84 gl
->api_type
= api_type
;
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
);
93 assert(gl
->make_current
&& gl
->release_current
&& gl
->swap
94 && gl
->get_proc_address
);
95 vlc_atomic_rc_init(&glpriv
->rc
);
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
;
108 enum vlc_gl_api_type api_type
;
110 switch (flags
/*& VLC_OPENGL_API_MASK*/)
113 type
= "opengl offscreen";
114 api_type
= VLC_OPENGL
;
117 type
= "opengl es2 offscreen";
118 api_type
= VLC_OPENGL_ES2
;
124 glpriv
= vlc_custom_create(parent
, sizeof (*glpriv
), "gl");
125 if (unlikely(glpriv
== 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
;
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
,
140 if (gl
->module
== NULL
)
142 vlc_object_delete(gl
);
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
);
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
))
171 if (gl
->destroy
!= NULL
)
173 vlc_objres_clear(VLC_OBJECT(gl
));
174 vlc_object_delete(gl
);
177 #include <vlc_vout_window.h>
179 typedef struct vlc_gl_surface
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
);
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
))
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
= {
218 char *modlist
= var_InheritString(obj
, "window");
220 vout_window_t
*surface
= vout_window_New(obj
, modlist
, &owner
);
224 if (vout_window_Enable(surface
, cfg
)) {
225 vout_window_Delete(surface
);
231 /* TODO: support ES? */
232 struct vout_display_cfg dcfg
= {
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
;
244 vlc_mutex_unlock(&sys
->lock
);
246 vlc_gl_t
*gl
= vlc_gl_Create(&dcfg
, VLC_OPENGL
, NULL
);
248 vout_window_Disable(surface
);
249 vout_window_Delete(surface
);
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
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
;
275 vlc_mutex_lock(&sys
->lock
);
276 if (sys
->width
>= 0 && sys
->height
>= 0)
279 *height
= sys
->height
;
283 vlc_gl_Resize(gl
, *width
, *height
);
286 vlc_mutex_unlock(&sys
->lock
);
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
;
296 vout_window_Disable(surface
);
297 vout_window_Delete(surface
);