opengl: expose npot support in gl_api
[vlc.git] / modules / video_output / opengl / vout_helper.c
blobae955109b542e65ad8beda31bb0ace23e5adf9ea
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_subpicture.h>
37 #include <vlc_opengl.h>
38 #include <vlc_modules.h>
39 #include <vlc_vout.h>
40 #include <vlc_viewpoint.h>
42 #include "gl_api.h"
43 #include "gl_util.h"
44 #include "vout_helper.h"
45 #include "internal.h"
46 #include "renderer.h"
47 #include "sub_renderer.h"
49 struct vout_display_opengl_t {
51 vlc_gl_t *gl;
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[] = {
59 VLC_CODEC_RGBA,
63 static void
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;
74 fmt->i_width = nw_w;
75 fmt->i_visible_height = nw_vis_w * vis_h / vis_w;
76 fmt->i_visible_width = nw_vis_w;
78 else
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;
86 fmt->i_height = nw_h;
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,
94 vlc_gl_t *gl,
95 const vlc_viewpoint_t *viewpoint,
96 vlc_video_context *context)
98 vout_display_opengl_t *vgl = calloc(1, sizeof(*vgl));
99 if (!vgl)
100 return NULL;
102 vgl->gl = gl;
104 int ret = vlc_gl_api_Init(&vgl->api, gl);
105 if (ret != VLC_SUCCESS)
107 free(vgl);
108 return NULL;
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");
119 free(vgl);
120 return NULL;
122 #endif
124 /* Resize the format if it is greater than the maximum texture size
125 * supported by the hardware */
126 GLint max_tex_size;
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);
137 if (!vgl->renderer)
139 msg_Warn(gl, "Could not create renderer for %4.4s",
140 (const char *) &fmt->i_chroma);
141 free(vgl);
142 return NULL;
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);
152 free(vgl);
153 return NULL;
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);
162 return NULL;
165 *fmt = renderer->fmt;
166 if (subpicture_chromas) {
167 *subpicture_chromas = gl_subpicture_chromas;
170 GL_ASSERT_NOERROR(vt);
171 return vgl;
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);
180 /* */
181 vt->Finish();
182 vt->Flush();
184 vlc_gl_sub_renderer_Delete(vgl->sub_renderer);
185 vlc_gl_renderer_Delete(vgl->renderer);
187 GL_ASSERT_NOERROR(vt);
189 free(vgl);
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,
199 float f_sar)
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)
218 return ret;
220 ret = vlc_gl_sub_renderer_Prepare(vgl->sub_renderer, subpicture);
221 GL_ASSERT_NOERROR(&vgl->api.vt);
222 return ret;
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)
235 return ret;
237 ret = vlc_gl_sub_renderer_Draw(vgl->sub_renderer);
238 if (ret != VLC_SUCCESS)
239 return ret;
241 /* Display */
242 vlc_gl_Swap(vgl->gl);
244 GL_ASSERT_NOERROR(&vgl->api.vt);
246 return VLC_SUCCESS;