fourcc: add VLC_CODEC_VAAPI_420_10BPP fallbacks
[vlc.git] / src / video_output / opengl.c
blobc9dcdab57ba8096982dbefcdcba3a3f81bf62575
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 "libvlc.h"
32 #include <vlc_modules.h>
34 struct vlc_gl_priv_t
36 vlc_gl_t gl;
37 atomic_uint ref_count;
39 #undef vlc_gl_Create
40 /**
41 * Creates an OpenGL context (and its underlying surface).
43 * @note In most cases, you should vlc_gl_MakeCurrent() afterward.
45 * @param wnd window to use as OpenGL surface
46 * @param flags OpenGL context type
47 * @param name module name (or NULL for auto)
48 * @return a new context, or NULL on failure
50 vlc_gl_t *vlc_gl_Create(struct vout_window_t *wnd, unsigned flags,
51 const char *name)
53 vlc_object_t *parent = (vlc_object_t *)wnd;
54 struct vlc_gl_priv_t *glpriv;
55 const char *type;
57 switch (flags /*& VLC_OPENGL_API_MASK*/)
59 case VLC_OPENGL:
60 type = "opengl";
61 break;
62 case VLC_OPENGL_ES2:
63 type = "opengl es2";
64 break;
65 default:
66 return NULL;
69 glpriv = vlc_custom_create(parent, sizeof (*glpriv), "gl");
70 if (unlikely(glpriv == NULL))
71 return NULL;
73 glpriv->gl.surface = wnd;
74 glpriv->gl.module = module_need(&glpriv->gl, type, name, true);
75 if (glpriv->gl.module == NULL)
77 vlc_object_release(&glpriv->gl);
78 return NULL;
80 atomic_init(&glpriv->ref_count, 1);
82 return &glpriv->gl;
85 void vlc_gl_Hold(vlc_gl_t *gl)
87 struct vlc_gl_priv_t *glpriv = (struct vlc_gl_priv_t *)gl;
88 atomic_fetch_add(&glpriv->ref_count, 1);
91 void vlc_gl_Release(vlc_gl_t *gl)
93 struct vlc_gl_priv_t *glpriv = (struct vlc_gl_priv_t *)gl;
94 if (atomic_fetch_sub(&glpriv->ref_count, 1) != 1)
95 return;
96 module_unneed(gl, gl->module);
97 vlc_object_release(gl);
100 #include <vlc_vout_window.h>
102 typedef struct vlc_gl_surface
104 int width;
105 int height;
106 vlc_mutex_t lock;
107 } vlc_gl_surface_t;
109 static void vlc_gl_surface_ResizeNotify(vout_window_t *surface,
110 unsigned width, unsigned height)
112 vlc_gl_surface_t *sys = surface->owner.sys;
114 msg_Dbg(surface, "resized to %ux%u", width, height);
116 vlc_mutex_lock(&sys->lock);
117 sys->width = width;
118 sys->height = height;
119 vlc_mutex_unlock(&sys->lock);
122 vlc_gl_t *vlc_gl_surface_Create(vlc_object_t *obj,
123 const vout_window_cfg_t *cfg,
124 struct vout_window_t **restrict wp)
126 vlc_gl_surface_t *sys = malloc(sizeof (*sys));
127 if (unlikely(sys == NULL))
128 return NULL;
130 sys->width = cfg->width;
131 sys->height = cfg->height;
132 vlc_mutex_init(&sys->lock);
134 vout_window_owner_t owner = {
135 .sys = sys,
136 .resized = vlc_gl_surface_ResizeNotify,
139 vout_window_t *surface = vout_window_New(obj, "$window", cfg, &owner);
140 if (surface == NULL)
141 goto error;
142 if (wp != NULL)
143 *wp = surface;
145 /* TODO: support ES? */
146 vlc_gl_t *gl = vlc_gl_Create(surface, VLC_OPENGL, NULL);
147 if (gl == NULL) {
148 vout_window_Delete(surface);
149 return NULL;
152 vlc_gl_Resize(gl, cfg->width, cfg->height);
153 return gl;
155 error:
156 vlc_mutex_destroy(&sys->lock);
157 free(sys);
158 return NULL;
162 * Checks if the dimensions of the surface used by the OpenGL context have
163 * changed (since the previous call), and the OpenGL viewport should be
164 * updated.
165 * \return true if at least one dimension has changed, false otherwise
166 * \warning This function is intrinsically race-prone.
167 * The dimensions can change asynchronously.
169 bool vlc_gl_surface_CheckSize(vlc_gl_t *gl, unsigned *restrict width,
170 unsigned *restrict height)
172 vout_window_t *surface = gl->surface;
173 vlc_gl_surface_t *sys = surface->owner.sys;
174 bool ret = false;
176 vlc_mutex_lock(&sys->lock);
177 if (sys->width >= 0 && sys->height >= 0)
179 *width = sys->width;
180 *height = sys->height;
181 sys->width = -1;
182 sys->height = -1;
184 vlc_gl_Resize(gl, *width, *height);
185 ret = true;
187 vlc_mutex_unlock(&sys->lock);
188 return ret;
191 void vlc_gl_surface_Destroy(vlc_gl_t *gl)
193 vout_window_t *surface = gl->surface;
194 vlc_gl_surface_t *sys = surface->owner.sys;
196 vlc_gl_Release(gl);
197 vout_window_Delete(surface);
198 vlc_mutex_destroy(&sys->lock);
199 free(sys);