1 /*****************************************************************************
2 * glwin32.c: Windows OpenGL provider
3 *****************************************************************************
4 * Copyright (C) 2001-2009 VLC authors and VideoLAN
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 *****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_vout_display.h>
34 #include "../opengl/vout_helper.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static int Open (vlc_object_t
*);
43 static void Close(vlc_object_t
*);
45 #define HW_GPU_AFFINITY_TEXT N_("GPU affinity")
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
)
60 /*****************************************************************************
62 *****************************************************************************/
63 struct vout_display_sys_t
65 vout_display_sys_win32_t sys
;
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
);
88 pfd
.dwFlags
= PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
;
89 pfd
.iPixelType
= PFD_TYPE_RGBA
;
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 */
115 if (!fncEnumGpusNV(nVidiaAffinity
, &hGPU
)) return;
117 /* make the affinity DC */
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",
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
);
136 pfd
.dwFlags
= PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
;
137 pfd
.iPixelType
= PFD_TYPE_RGBA
;
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
));
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
);
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
);
203 pfd
.dwFlags
= PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
;
204 pfd
.iPixelType
= PFD_TYPE_RGBA
;
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");
229 sys
->gl
= vlc_object_create(object
, sizeof(*sys
->gl
));
231 if (unlikely(!sys
->gl
))
234 sys
->gl
->swap
= Swap
;
235 sys
->gl
->getProcAddress
= OurGetProcAddress
;
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
);
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 */
255 vd
->prepare
= Prepare
;
256 vd
->display
= Display
;
257 vd
->control
= Control
;
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
;
276 vout_display_opengl_Delete(sys
->vgl
);
279 vlc_object_release(sys
->gl
);
281 if (sys
->hGLDC
&& sys
->hGLRC
)
282 wglMakeCurrent(NULL
, NULL
);
284 wglDeleteContext(sys
->hGLRC
);
286 ReleaseDC(sys
->sys
.hvideownd
, sys
->hGLDC
);
287 DestroyGPUAffinityDC(vd
);
295 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
)
297 vout_display_sys_t
*sys
= vd
->sys
;
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
);
319 subpicture_Delete(subpicture
);
324 static void Manage (vout_display_t
*vd
)
326 vout_display_sys_t
*sys
= vd
->sys
;
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
)
346 return wglGetProcAddress(name
);