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>
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 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_subpicture.h>
37 #include <vlc_opengl.h>
38 #include <vlc_modules.h>
40 #include <vlc_viewpoint.h>
44 #include "vout_helper.h"
47 #include "sub_renderer.h"
49 struct vout_display_opengl_t
{
52 struct vlc_gl_api api
;
54 struct vlc_gl_renderer
*renderer
;
55 struct vlc_gl_sub_renderer
*sub_renderer
;
58 static const vlc_fourcc_t gl_subpicture_chromas
[] = {
64 ResizeFormatToGLMaxTexSize(video_format_t
*fmt
, unsigned int max_tex_size
)
66 if (fmt
->i_width
> fmt
->i_height
)
68 unsigned int const vis_w
= fmt
->i_visible_width
;
69 unsigned int const vis_h
= fmt
->i_visible_height
;
70 unsigned int const nw_w
= max_tex_size
;
71 unsigned int const nw_vis_w
= nw_w
* vis_w
/ fmt
->i_width
;
73 fmt
->i_height
= nw_w
* fmt
->i_height
/ fmt
->i_width
;
75 fmt
->i_visible_height
= nw_vis_w
* vis_h
/ vis_w
;
76 fmt
->i_visible_width
= nw_vis_w
;
80 unsigned int const vis_w
= fmt
->i_visible_width
;
81 unsigned int const vis_h
= fmt
->i_visible_height
;
82 unsigned int const nw_h
= max_tex_size
;
83 unsigned int const nw_vis_h
= nw_h
* vis_h
/ fmt
->i_height
;
85 fmt
->i_width
= nw_h
* fmt
->i_width
/ fmt
->i_height
;
87 fmt
->i_visible_width
= nw_vis_h
* vis_w
/ vis_h
;
88 fmt
->i_visible_height
= nw_vis_h
;
92 vout_display_opengl_t
*vout_display_opengl_New(video_format_t
*fmt
,
93 const vlc_fourcc_t
**subpicture_chromas
,
95 const vlc_viewpoint_t
*viewpoint
,
96 vlc_video_context
*context
)
98 vout_display_opengl_t
*vgl
= calloc(1, sizeof(*vgl
));
104 int ret
= vlc_gl_api_Init(&vgl
->api
, gl
);
105 if (ret
!= VLC_SUCCESS
)
111 const opengl_vtable_t
*vt
= &vgl
->api
.vt
;
113 #if !defined(USE_OPENGL_ES2)
114 const unsigned char *ogl_version
= vt
->GetString(GL_VERSION
);
115 bool supports_shaders
= strverscmp((const char *)ogl_version
, "2.0") >= 0;
116 if (!supports_shaders
)
118 msg_Err(gl
, "shaders not supported, bailing out");
124 /* Resize the format if it is greater than the maximum texture size
125 * supported by the hardware */
127 vt
->GetIntegerv(GL_MAX_TEXTURE_SIZE
, &max_tex_size
);
129 if ((GLint
)fmt
->i_width
> max_tex_size
||
130 (GLint
)fmt
->i_height
> max_tex_size
)
131 ResizeFormatToGLMaxTexSize(fmt
, max_tex_size
);
133 bool b_dump_shaders
= var_InheritInteger(gl
, "verbose") >= 4;
135 struct vlc_gl_renderer
*renderer
= vgl
->renderer
=
136 vlc_gl_renderer_New(gl
, &vgl
->api
, context
, fmt
, b_dump_shaders
);
139 msg_Warn(gl
, "Could not create renderer for %4.4s",
140 (const char *) &fmt
->i_chroma
);
145 GL_ASSERT_NOERROR(vt
);
147 vgl
->sub_renderer
= vlc_gl_sub_renderer_New(gl
, &vgl
->api
);
148 if (!vgl
->sub_renderer
)
150 msg_Err(gl
, "Could not create sub renderer");
151 vlc_gl_renderer_Delete(vgl
->renderer
);
156 GL_ASSERT_NOERROR(vt
);
158 if (renderer
->fmt
.projection_mode
!= PROJECTION_MODE_RECTANGULAR
159 && vout_display_opengl_SetViewpoint(vgl
, viewpoint
) != VLC_SUCCESS
)
161 vout_display_opengl_Delete(vgl
);
165 *fmt
= renderer
->fmt
;
166 if (subpicture_chromas
) {
167 *subpicture_chromas
= gl_subpicture_chromas
;
170 GL_ASSERT_NOERROR(vt
);
174 void vout_display_opengl_Delete(vout_display_opengl_t
*vgl
)
176 const opengl_vtable_t
*vt
= &vgl
->api
.vt
;
178 GL_ASSERT_NOERROR(vt
);
184 vlc_gl_sub_renderer_Delete(vgl
->sub_renderer
);
185 vlc_gl_renderer_Delete(vgl
->renderer
);
187 GL_ASSERT_NOERROR(vt
);
192 int vout_display_opengl_SetViewpoint(vout_display_opengl_t
*vgl
,
193 const vlc_viewpoint_t
*p_vp
)
195 return vlc_gl_renderer_SetViewpoint(vgl
->renderer
, p_vp
);
198 void vout_display_opengl_SetWindowAspectRatio(vout_display_opengl_t
*vgl
,
201 vlc_gl_renderer_SetWindowAspectRatio(vgl
->renderer
, f_sar
);
204 void vout_display_opengl_Viewport(vout_display_opengl_t
*vgl
, int x
, int y
,
205 unsigned width
, unsigned height
)
207 const opengl_vtable_t
*vt
= &vgl
->api
.vt
;
208 vt
->Viewport(x
, y
, width
, height
);
211 int vout_display_opengl_Prepare(vout_display_opengl_t
*vgl
,
212 picture_t
*picture
, subpicture_t
*subpicture
)
214 GL_ASSERT_NOERROR(&vgl
->api
.vt
);
216 int ret
= vlc_gl_renderer_Prepare(vgl
->renderer
, picture
);
217 if (ret
!= VLC_SUCCESS
)
220 ret
= vlc_gl_sub_renderer_Prepare(vgl
->sub_renderer
, subpicture
);
221 GL_ASSERT_NOERROR(&vgl
->api
.vt
);
224 int vout_display_opengl_Display(vout_display_opengl_t
*vgl
,
225 const video_format_t
*source
)
227 GL_ASSERT_NOERROR(&vgl
->api
.vt
);
229 /* Why drawing here and not in Render()? Because this way, the
230 OpenGL providers can call vout_display_opengl_Display to force redraw.
231 Currently, the OS X provider uses it to get a smooth window resizing */
233 int ret
= vlc_gl_renderer_Draw(vgl
->renderer
, source
);
234 if (ret
!= VLC_SUCCESS
)
237 ret
= vlc_gl_sub_renderer_Draw(vgl
->sub_renderer
);
238 if (ret
!= VLC_SUCCESS
)
242 vlc_gl_Swap(vgl
->gl
);
244 GL_ASSERT_NOERROR(&vgl
->api
.vt
);