vout: rename and invert has_hide_mouse
[vlc.git] / modules / video_output / win32 / glwin32.c
blobc6eb15650b2ff0c0417054c3ed2a00a35f2e801a
1 /*****************************************************************************
2 * glwin32.c: Windows OpenGL provider
3 *****************************************************************************
4 * Copyright (C) 2001-2009 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_vout_display.h>
31 #include <windows.h>
33 #define GLEW_STATIC
34 #include "../opengl/vout_helper.h"
35 #include <GL/wglew.h>
37 #include "common.h"
39 /*****************************************************************************
40 * Module descriptor
41 *****************************************************************************/
42 static int Open (vlc_object_t *);
43 static void Close(vlc_object_t *);
45 #define HW_GPU_AFFINITY_TEXT N_("GPU affinity")
47 vlc_module_begin()
48 set_category(CAT_VIDEO)
49 set_subcategory(SUBCAT_VIDEO_VOUT)
50 set_shortname("OpenGL")
51 set_description(N_("OpenGL video output"))
53 add_integer("gpu-affinity", -1, HW_GPU_AFFINITY_TEXT, HW_GPU_AFFINITY_TEXT, true)
55 set_capability("vout display", 220)
56 add_shortcut("glwin32", "opengl")
57 set_callbacks(Open, Close)
58 vlc_module_end()
60 /*****************************************************************************
61 * Local prototypes.
62 *****************************************************************************/
63 struct vout_display_sys_t
65 vout_display_sys_win32_t sys;
67 HDC hGLDC;
68 HGLRC hGLRC;
69 vlc_gl_t *gl;
70 vout_display_opengl_t *vgl;
71 HDC affinityHDC; // DC for the selected GPU
74 static picture_pool_t *Pool (vout_display_t *, unsigned);
75 static void Prepare(vout_display_t *, picture_t *, subpicture_t *);
76 static void Display(vout_display_t *, picture_t *, subpicture_t *);
77 static void Manage (vout_display_t *);
79 static void Swap (vlc_gl_t *);
80 static void *OurGetProcAddress(vlc_gl_t *, const char *);
82 /* Create an GPU Affinity DC */
83 static void CreateGPUAffinityDC(vout_display_t *vd, UINT nVidiaAffinity) {
84 PIXELFORMATDESCRIPTOR pfd;
85 memset(&pfd, 0, sizeof(pfd));
86 pfd.nSize = sizeof(pfd);
87 pfd.nVersion = 1;
88 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
89 pfd.iPixelType = PFD_TYPE_RGBA;
90 pfd.cColorBits = 24;
91 pfd.cDepthBits = 16;
92 pfd.iLayerType = PFD_MAIN_PLANE;
94 /* create a temporary GL context */
95 HDC winDC = GetDC(vd->sys->sys.hvideownd);
96 SetPixelFormat(winDC, ChoosePixelFormat(winDC, &pfd), &pfd);
97 HGLRC hGLRC = wglCreateContext(winDC);
98 wglMakeCurrent(winDC, hGLRC);
100 /* Initialize the necessary function pointers */
101 PFNWGLENUMGPUSNVPROC fncEnumGpusNV = (PFNWGLENUMGPUSNVPROC)wglGetProcAddress("wglEnumGpusNV");
102 PFNWGLCREATEAFFINITYDCNVPROC fncCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)wglGetProcAddress("wglCreateAffinityDCNV");
104 /* delete the temporary GL context */
105 wglDeleteContext(hGLRC);
107 /* see if we have the extensions */
108 if (!fncEnumGpusNV || !fncCreateAffinityDCNV) return;
110 /* find the graphics card */
111 HGPUNV GpuMask[2];
112 GpuMask[0] = NULL;
113 GpuMask[1] = NULL;
114 HGPUNV hGPU;
115 if (!fncEnumGpusNV(nVidiaAffinity, &hGPU)) return;
117 /* make the affinity DC */
118 GpuMask[0] = hGPU;
119 vd->sys->affinityHDC = fncCreateAffinityDCNV(GpuMask);
120 if (vd->sys->affinityHDC == NULL) return;
121 SetPixelFormat(vd->sys->affinityHDC,
122 ChoosePixelFormat(vd->sys->affinityHDC, &pfd), &pfd);
124 msg_Dbg( vd, "GPU affinity set to adapter: %d",
125 nVidiaAffinity );
128 /* Destroy an GPU Affinity DC */
129 static void DestroyGPUAffinityDC(vout_display_t *vd) {
130 if (vd->sys->affinityHDC == NULL) return;
132 PIXELFORMATDESCRIPTOR pfd;
133 memset(&pfd, 0, sizeof(pfd));
134 pfd.nSize = sizeof(pfd);
135 pfd.nVersion = 1;
136 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
137 pfd.iPixelType = PFD_TYPE_RGBA;
138 pfd.cColorBits = 24;
139 pfd.cDepthBits = 16;
140 pfd.iLayerType = PFD_MAIN_PLANE;
142 /* create a temporary GL context */
143 HDC winDC = GetDC(vd->sys->sys.hvideownd);
144 SetPixelFormat(winDC, ChoosePixelFormat(winDC, &pfd), &pfd);
145 HGLRC hGLRC = wglCreateContext(winDC);
146 wglMakeCurrent(winDC, hGLRC);
148 /* Initialize the necessary function pointers */
149 PFNWGLDELETEDCNVPROC fncDeleteDCNV = (PFNWGLDELETEDCNVPROC)wglGetProcAddress("wglDeleteDCNV");
151 /* delete the temporary GL context */
152 wglDeleteContext(hGLRC);
154 /* see if we have the extensions */
155 if (!fncDeleteDCNV) return;
157 /* delete the affinity DC */
158 fncDeleteDCNV(vd->sys->affinityHDC);
161 static int Control(vout_display_t *vd, int query, va_list args)
163 vout_display_sys_t *sys = vd->sys;
165 if (query == VOUT_DISPLAY_CHANGE_VIEWPOINT)
166 return vout_display_opengl_SetViewpoint(sys->vgl,
167 &va_arg (args, const vout_display_cfg_t* )->viewpoint);
169 return CommonControl(vd, query, args);
173 * It creates an OpenGL vout display.
175 static int Open(vlc_object_t *object)
177 vout_display_t *vd = (vout_display_t *)object;
178 vout_display_sys_t *sys;
180 /* Allocate structure */
181 vd->sys = sys = calloc(1, sizeof(*sys));
182 if (!sys)
183 return VLC_ENOMEM;
185 /* */
186 if (CommonInit(vd))
187 goto error;
189 EventThreadUpdateTitle(sys->sys.event, VOUT_TITLE " (OpenGL output)");
191 /* process selected GPU affinity */
192 int nVidiaAffinity = var_InheritInteger(vd, "gpu-affinity");
193 if (nVidiaAffinity >= 0) CreateGPUAffinityDC(vd, nVidiaAffinity);
195 /* */
196 sys->hGLDC = GetDC(sys->sys.hvideownd);
198 /* Set the pixel format for the DC */
199 PIXELFORMATDESCRIPTOR pfd;
200 memset(&pfd, 0, sizeof(pfd));
201 pfd.nSize = sizeof(pfd);
202 pfd.nVersion = 1;
203 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
204 pfd.iPixelType = PFD_TYPE_RGBA;
205 pfd.cColorBits = 24;
206 pfd.cDepthBits = 16;
207 pfd.iLayerType = PFD_MAIN_PLANE;
208 SetPixelFormat(sys->hGLDC,
209 ChoosePixelFormat(sys->hGLDC, &pfd), &pfd);
212 * Create and enable the render context
213 * For GPU affinity, attach the window DC
214 * to the GPU affinity DC
216 sys->hGLRC = wglCreateContext((sys->affinityHDC != NULL) ? sys->affinityHDC : sys->hGLDC);
217 wglMakeCurrent(sys->hGLDC, sys->hGLRC);
219 const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
220 #ifdef WGL_EXT_swap_control
221 if (HasExtension(extensions, "WGL_EXT_swap_control")) {
222 PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
223 if (SwapIntervalEXT)
224 SwapIntervalEXT(1);
226 #endif
228 /* */
229 sys->gl = vlc_object_create(object, sizeof(*sys->gl));
231 if (unlikely(!sys->gl))
232 goto error;
234 sys->gl->swap = Swap;
235 sys->gl->getProcAddress = OurGetProcAddress;
236 sys->gl->sys = vd;
238 video_format_t fmt = vd->fmt;
239 const vlc_fourcc_t *subpicture_chromas;
240 sys->vgl = vout_display_opengl_New(&fmt, &subpicture_chromas, sys->gl,
241 &vd->cfg->viewpoint);
242 if (!sys->vgl)
243 goto error;
245 vout_display_info_t info = vd->info;
246 info.has_double_click = true;
247 info.needs_hide_mouse = true;
248 info.subpicture_chromas = subpicture_chromas;
250 /* Setup vout_display now that everything is fine */
251 vd->fmt = fmt;
252 vd->info = info;
254 vd->pool = Pool;
255 vd->prepare = Prepare;
256 vd->display = Display;
257 vd->control = Control;
258 vd->manage = Manage;
260 return VLC_SUCCESS;
262 error:
263 Close(object);
264 return VLC_EGENERIC;
268 * It destroys an OpenGL vout display.
270 static void Close(vlc_object_t *object)
272 vout_display_t *vd = (vout_display_t *)object;
273 vout_display_sys_t *sys = vd->sys;
275 if (sys->vgl)
276 vout_display_opengl_Delete(sys->vgl);
278 if (sys->gl)
279 vlc_object_release(sys->gl);
281 if (sys->hGLDC && sys->hGLRC)
282 wglMakeCurrent(NULL, NULL);
283 if (sys->hGLRC)
284 wglDeleteContext(sys->hGLRC);
285 if (sys->hGLDC)
286 ReleaseDC(sys->sys.hvideownd, sys->hGLDC);
287 DestroyGPUAffinityDC(vd);
289 CommonClean(vd);
291 free(sys);
294 /* */
295 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
297 vout_display_sys_t *sys = vd->sys;
299 if (!sys->sys.pool)
300 sys->sys.pool = vout_display_opengl_GetPool(sys->vgl, count);
301 return sys->sys.pool;
304 static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
306 vout_display_sys_t *sys = vd->sys;
308 vout_display_opengl_Prepare(sys->vgl, picture, subpicture);
311 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
313 vout_display_sys_t *sys = vd->sys;
315 vout_display_opengl_Display(sys->vgl, &vd->source);
317 picture_Release(picture);
318 if (subpicture)
319 subpicture_Delete(subpicture);
321 CommonDisplay(vd);
324 static void Manage (vout_display_t *vd)
326 vout_display_sys_t *sys = vd->sys;
328 CommonManage(vd);
330 const int width = sys->sys.rect_dest.right - sys->sys.rect_dest.left;
331 const int height = sys->sys.rect_dest.bottom - sys->sys.rect_dest.top;
332 vout_display_opengl_SetWindowAspectRatio(sys->vgl, (float)width / height);
333 glViewport(0, 0, width, height);
336 static void Swap(vlc_gl_t *gl)
338 vout_display_t *vd = gl->sys;
340 SwapBuffers(vd->sys->hGLDC);
343 static void *OurGetProcAddress(vlc_gl_t *gl, const char *name)
345 VLC_UNUSED(gl);
346 return wglGetProcAddress(name);