qt: playlist: use item title if available
[vlc.git] / modules / video_output / opengl / vout_helper.c
blobad3eba280b77e5a86a5fba3081f9988e5fddf8fb
1 /*****************************************************************************
2 * vout_helper.c: OpenGL and OpenGL ES output common code
3 *****************************************************************************
4 * Copyright (C) 2004-2016 VLC authors and VideoLAN
5 * Copyright (C) 2009, 2011 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8 * Ilkka Ollakka <ileoo@videolan.org>
9 * Rémi Denis-Courmont
10 * Adrien Maglo <magsoft at videolan dot org>
11 * Felix Paul Kühne <fkuehne at videolan dot org>
12 * Pierre d'Herbemont <pdherbemont at videolan dot org>
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation; either version 2.1 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <assert.h>
33 #include <math.h>
35 #include <vlc_common.h>
36 #include <vlc_list.h>
37 #include <vlc_subpicture.h>
38 #include <vlc_opengl.h>
39 #include <vlc_modules.h>
40 #include <vlc_vout.h>
41 #include <vlc_viewpoint.h>
43 #include "filters.h"
44 #include "gl_api.h"
45 #include "gl_util.h"
46 #include "vout_helper.h"
47 #include "internal.h"
48 #include "renderer.h"
49 #include "sampler.h"
50 #include "sampler_priv.h"
51 #include "sub_renderer.h"
53 struct vout_display_opengl_t {
55 vlc_gl_t *gl;
56 struct vlc_gl_api api;
58 struct vlc_gl_interop *interop;
59 struct vlc_gl_renderer *renderer; /**< weak reference */
61 struct vlc_gl_filters *filters;
63 struct vlc_gl_interop *sub_interop;
64 struct vlc_gl_sub_renderer *sub_renderer;
67 static const vlc_fourcc_t gl_subpicture_chromas[] = {
68 VLC_CODEC_RGBA,
72 static void
73 ResizeFormatToGLMaxTexSize(video_format_t *fmt, unsigned int max_tex_size)
75 if (fmt->i_width > fmt->i_height)
77 unsigned int const vis_w = fmt->i_visible_width;
78 unsigned int const vis_h = fmt->i_visible_height;
79 unsigned int const nw_w = max_tex_size;
80 unsigned int const nw_vis_w = nw_w * vis_w / fmt->i_width;
82 fmt->i_height = nw_w * fmt->i_height / fmt->i_width;
83 fmt->i_width = nw_w;
84 fmt->i_visible_height = nw_vis_w * vis_h / vis_w;
85 fmt->i_visible_width = nw_vis_w;
87 else
89 unsigned int const vis_w = fmt->i_visible_width;
90 unsigned int const vis_h = fmt->i_visible_height;
91 unsigned int const nw_h = max_tex_size;
92 unsigned int const nw_vis_h = nw_h * vis_h / fmt->i_height;
94 fmt->i_width = nw_h * fmt->i_width / fmt->i_height;
95 fmt->i_height = nw_h;
96 fmt->i_visible_width = nw_vis_h * vis_w / vis_h;
97 fmt->i_visible_height = nw_vis_h;
101 vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
102 const vlc_fourcc_t **subpicture_chromas,
103 vlc_gl_t *gl,
104 const vlc_viewpoint_t *viewpoint,
105 vlc_video_context *context)
107 vout_display_opengl_t *vgl = calloc(1, sizeof(*vgl));
108 if (!vgl)
109 return NULL;
111 vgl->gl = gl;
113 int ret = vlc_gl_api_Init(&vgl->api, gl);
114 if (ret != VLC_SUCCESS)
115 goto free_vgl;
117 const struct vlc_gl_api *api = &vgl->api;
118 const opengl_vtable_t *vt = &api->vt;
120 #if !defined(USE_OPENGL_ES2)
121 const unsigned char *ogl_version = vt->GetString(GL_VERSION);
122 bool supports_shaders = strverscmp((const char *)ogl_version, "2.0") >= 0;
123 if (!supports_shaders)
125 msg_Err(gl, "shaders not supported, bailing out");
126 goto free_vgl;
128 #endif
130 /* Resize the format if it is greater than the maximum texture size
131 * supported by the hardware */
132 GLint max_tex_size;
133 vt->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
135 if ((GLint)fmt->i_width > max_tex_size ||
136 (GLint)fmt->i_height > max_tex_size)
137 ResizeFormatToGLMaxTexSize(fmt, max_tex_size);
139 vgl->interop = vlc_gl_interop_New(gl, api, context, fmt);
140 if (!vgl->interop)
142 msg_Err(gl, "Could not create interop");
143 goto free_vgl;
146 vgl->filters = vlc_gl_filters_New(gl, api, vgl->interop);
147 if (!vgl->filters)
149 msg_Err(gl, "Could not create filters");
150 goto delete_interop;
153 /* The renderer is the only filter, for now */
154 struct vlc_gl_filter *renderer_filter =
155 vlc_gl_filters_Append(vgl->filters, "renderer", NULL);
156 if (!renderer_filter)
158 msg_Warn(gl, "Could not create renderer for %4.4s",
159 (const char *) &fmt->i_chroma);
160 goto delete_filters;
163 /* The renderer is a special filter: we need its concrete instance to
164 * forward SetViewpoint() */
165 vgl->renderer = renderer_filter->sys;
167 ret = vlc_gl_filters_InitFramebuffers(vgl->filters);
168 if (ret != VLC_SUCCESS)
170 msg_Err(gl, "Could not init filters framebuffers");
171 goto delete_filters;
174 vgl->sub_interop = vlc_gl_interop_NewForSubpictures(gl, api);
175 if (!vgl->sub_interop)
177 msg_Err(gl, "Could not create sub interop");
178 goto delete_filters;
181 vgl->sub_renderer =
182 vlc_gl_sub_renderer_New(gl, api, vgl->sub_interop);
183 if (!vgl->sub_renderer)
185 msg_Err(gl, "Could not create sub renderer");
186 goto delete_sub_interop;
189 GL_ASSERT_NOERROR(vt);
191 if (fmt->projection_mode != PROJECTION_MODE_RECTANGULAR
192 && vout_display_opengl_SetViewpoint(vgl, viewpoint) != VLC_SUCCESS)
193 goto delete_sub_renderer;
195 /* Forward to the core the changes to the input format requested by the
196 * interop */
197 *fmt = vgl->interop->fmt_in;
199 if (subpicture_chromas) {
200 *subpicture_chromas = gl_subpicture_chromas;
203 GL_ASSERT_NOERROR(vt);
204 return vgl;
206 delete_sub_renderer:
207 vlc_gl_sub_renderer_Delete(vgl->sub_renderer);
208 delete_sub_interop:
209 vlc_gl_interop_Delete(vgl->sub_interop);
210 delete_filters:
211 vlc_gl_filters_Delete(vgl->filters);
212 delete_interop:
213 vlc_gl_interop_Delete(vgl->interop);
214 free_vgl:
215 free(vgl);
217 return NULL;
220 void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
222 const opengl_vtable_t *vt = &vgl->api.vt;
224 GL_ASSERT_NOERROR(vt);
226 /* */
227 vt->Finish();
228 vt->Flush();
230 vlc_gl_sub_renderer_Delete(vgl->sub_renderer);
231 vlc_gl_interop_Delete(vgl->sub_interop);
233 vlc_gl_filters_Delete(vgl->filters);
234 vlc_gl_interop_Delete(vgl->interop);
236 GL_ASSERT_NOERROR(vt);
238 free(vgl);
241 int vout_display_opengl_SetViewpoint(vout_display_opengl_t *vgl,
242 const vlc_viewpoint_t *p_vp)
244 return vlc_gl_renderer_SetViewpoint(vgl->renderer, p_vp);
247 void vout_display_opengl_SetWindowAspectRatio(vout_display_opengl_t *vgl,
248 float f_sar)
250 vlc_gl_renderer_SetWindowAspectRatio(vgl->renderer, f_sar);
253 void vout_display_opengl_Viewport(vout_display_opengl_t *vgl, int x, int y,
254 unsigned width, unsigned height)
256 vlc_gl_filters_SetViewport(vgl->filters, x, y, width, height);
259 int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
260 picture_t *picture, subpicture_t *subpicture)
262 GL_ASSERT_NOERROR(&vgl->api.vt);
264 int ret = vlc_gl_filters_UpdatePicture(vgl->filters, picture);
265 if (ret != VLC_SUCCESS)
266 return ret;
268 ret = vlc_gl_sub_renderer_Prepare(vgl->sub_renderer, subpicture);
269 GL_ASSERT_NOERROR(&vgl->api.vt);
270 return ret;
272 int vout_display_opengl_Display(vout_display_opengl_t *vgl)
274 GL_ASSERT_NOERROR(&vgl->api.vt);
276 /* Why drawing here and not in Render()? Because this way, the
277 OpenGL providers can call vout_display_opengl_Display to force redraw.
278 Currently, the OS X provider uses it to get a smooth window resizing */
280 int ret = vlc_gl_filters_Draw(vgl->filters);
281 if (ret != VLC_SUCCESS)
282 return ret;
284 ret = vlc_gl_sub_renderer_Draw(vgl->sub_renderer);
285 if (ret != VLC_SUCCESS)
286 return ret;
288 /* Display */
289 vlc_gl_Swap(vgl->gl);
291 GL_ASSERT_NOERROR(&vgl->api.vt);
293 return VLC_SUCCESS;