[vlc-devel] [PATCH] WGL: OpenGL module for Windows
Adrien Maglo
magsoft at videolan.org
Tue Jun 7 18:06:03 CEST 2016
Reactivate the support of projectM and 3dspectrum visualization modules
on Windows.
fix #13650
---
configure.ac | 2 +-
modules/MODULES_LIST | 1 +
modules/video_output/Makefile.am | 14 +-
modules/video_output/win32/common.h | 6 +-
modules/video_output/win32/wgl.c | 261 ++++++++++++++++++++++++++++++++++++
5 files changed, 279 insertions(+), 5 deletions(-)
create mode 100644 modules/video_output/win32/wgl.c
diff --git a/configure.ac b/configure.ac
index d4533d0..d04acd0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3319,7 +3319,7 @@ AS_IF([test "${enable_directx}" != "no"], [
dnl OpenGL
AC_CHECK_HEADERS(GL/wglew.h, [
- VLC_ADD_PLUGIN([glwin32])
+ VLC_ADD_PLUGIN([glwin32, wgl])
],, [
#include <windows.h>
#include <GL/gl.h>
diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index 3c7f3d6..1c779c8 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -165,6 +165,7 @@ $Id$
* gles2: OpenGL ES2 video output using the generic OpenGL provider
* glspectrum: 3D OpenGL spectrum visualization
* glwin32: a opengl provider using DirectX OpenGL
+ * wgl: WGL extension for OpenGL
* glx: GLX extension for OpenGL
* gme: old console games music playback using Game Music Emu
* gnutls: GNU TLS encryption/decryption module
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 3bc2a95..e05d02a 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -219,13 +219,23 @@ libglwin32_plugin_la_SOURCES = video_output/win32/glwin32.c \
video_output/win32/common.c video_output/win32/common.h \
video_output/win32/events.c video_output/win32/events.h \
video_output/win32/win32touch.c video_output/win32/win32touch.h
+libwgl_plugin_la_SOURCES = video_output/win32/wgl.c \
+ video_output/opengl.c video_output/opengl.h
+
libglwin32_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_glwin32
+libwgl_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
+ -DMODULE_NAME_IS_wgl
+
libglwin32_plugin_la_LIBADD = -lopengl32 -lgdi32 -lole32 -luuid
+libwgl_plugin_la_LIBADD = -lopengl32 -lgdi32
+
libglwin32_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
+libwgl_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
+
if HAVE_WIN32_DESKTOP
-vout_LTLIBRARIES += $(LTLIBglwin32)
-EXTRA_LTLIBRARIES += libglwin32_plugin.la
+vout_LTLIBRARIES += $(LTLIBglwin32) $(LTLIBwgl)
+EXTRA_LTLIBRARIES += libglwin32_plugin.la libwgl_plugin.la
endif
libwingdi_plugin_la_SOURCES = video_output/win32/wingdi.c \
diff --git a/modules/video_output/win32/common.h b/modules/video_output/win32/common.h
index 3670a14..0e654e0 100644
--- a/modules/video_output/win32/common.h
+++ b/modules/video_output/win32/common.h
@@ -35,7 +35,7 @@
# include <d3d9.h>
# include <d3dx9effect.h>
#endif
-#ifdef MODULE_NAME_IS_glwin32
+#if defined(MODULE_NAME_IS_glwin32) || defined(MODULE_NAME_IS_wgl)
# include "../opengl.h"
#endif
#ifdef MODULE_NAME_IS_direct2d
@@ -150,11 +150,13 @@ struct vout_display_sys_t
bool wallpaper_requested;
#endif
-#ifdef MODULE_NAME_IS_glwin32
+#if defined(MODULE_NAME_IS_glwin32) || defined(MODULE_NAME_IS_wgl)
HDC hGLDC;
HGLRC hGLRC;
vlc_gl_t gl;
+# ifdef MODULE_NAME_IS_glwin32
vout_display_opengl_t *vgl;
+# endif
HDC affinityHDC; // DC for the selected GPU
#endif
diff --git a/modules/video_output/win32/wgl.c b/modules/video_output/win32/wgl.c
new file mode 100644
index 0000000..895e602
--- /dev/null
+++ b/modules/video_output/win32/wgl.c
@@ -0,0 +1,261 @@
+/*****************************************************************************
+ * wgl.c: WGL extension for OpenGL
+ *****************************************************************************
+ * Copyright © 2009-2016 VLC authors and VideoLAN
+ *
+ * Authors: Adrien Maglo <magsoft at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_display.h>
+#include <vlc_opengl.h>
+
+#include "../opengl.h"
+#include <GL/wglew.h>
+
+#include "common.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int Open(vlc_object_t *);
+static void Close(vlc_object_t *);
+
+#define HW_GPU_AFFINITY_TEXT N_("GPU affinity")
+
+vlc_module_begin()
+ set_shortname("WGL")
+ set_description(N_("WGL extension for OpenGL"))
+ set_category(CAT_VIDEO)
+ set_subcategory(SUBCAT_VIDEO_VOUT)
+
+ add_integer("gpu-affinity", -1, HW_GPU_AFFINITY_TEXT, HW_GPU_AFFINITY_TEXT, true)
+
+ set_capability("opengl", 50)
+ set_callbacks(Open, Close)
+ add_shortcut("wgl")
+vlc_module_end()
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+
+static void Swap(vlc_gl_t *);
+static void *OurGetProcAddress(vlc_gl_t *, const char *);
+static int MakeCurrent(vlc_gl_t *gl);
+static void ReleaseCurrent(vlc_gl_t *gl);
+
+
+/* Create an GPU Affinity DC */
+static void CreateGPUAffinityDC(vlc_gl_t *gl, UINT nVidiaAffinity) {
+ vout_display_sys_t *sys = gl->sys;
+
+ PIXELFORMATDESCRIPTOR pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cDepthBits = 16;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ /* create a temporary GL context */
+ HDC winDC = GetDC(sys->hvideownd);
+ SetPixelFormat(winDC, ChoosePixelFormat(winDC, &pfd), &pfd);
+ HGLRC hGLRC = wglCreateContext(winDC);
+ wglMakeCurrent(winDC, hGLRC);
+
+ /* Initialize the neccessary function pointers */
+ PFNWGLENUMGPUSNVPROC fncEnumGpusNV = (PFNWGLENUMGPUSNVPROC)wglGetProcAddress("wglEnumGpusNV");
+ PFNWGLCREATEAFFINITYDCNVPROC fncCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)wglGetProcAddress("wglCreateAffinityDCNV");
+
+ /* delete the temporary GL context */
+ wglDeleteContext(hGLRC);
+
+ /* see if we have the extensions */
+ if (!fncEnumGpusNV || !fncCreateAffinityDCNV) return;
+
+ /* find the graphics card */
+ HGPUNV GpuMask[2];
+ GpuMask[0] = NULL;
+ GpuMask[1] = NULL;
+ HGPUNV hGPU;
+ if (!fncEnumGpusNV(nVidiaAffinity, &hGPU)) return;
+
+ /* make the affinity DC */
+ GpuMask[0] = hGPU;
+ sys->affinityHDC = fncCreateAffinityDCNV(GpuMask);
+ if (sys->affinityHDC == NULL) return;
+ SetPixelFormat(sys->affinityHDC,
+ ChoosePixelFormat(sys->affinityHDC, &pfd), &pfd);
+
+ msg_Dbg(gl, "GPU affinity set to adapter: %d", nVidiaAffinity);
+}
+
+/* Destroy an GPU Affinity DC */
+static void DestroyGPUAffinityDC(vlc_gl_t *gl) {
+ vout_display_sys_t *sys = gl->sys;
+
+ if (sys->affinityHDC == NULL) return;
+
+ PIXELFORMATDESCRIPTOR pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cDepthBits = 16;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ /* create a temporary GL context */
+ HDC winDC = GetDC(sys->hvideownd);
+ SetPixelFormat(winDC, ChoosePixelFormat(winDC, &pfd), &pfd);
+ HGLRC hGLRC = wglCreateContext(winDC);
+ wglMakeCurrent(winDC, hGLRC);
+
+ /* Initialize the neccessary function pointers */
+ PFNWGLDELETEDCNVPROC fncDeleteDCNV = (PFNWGLDELETEDCNVPROC)wglGetProcAddress("wglDeleteDCNV");
+
+ /* delete the temporary GL context */
+ wglDeleteContext(hGLRC);
+
+ /* see if we have the extensions */
+ if (!fncDeleteDCNV) return;
+
+ /* delete the affinity DC */
+ fncDeleteDCNV(sys->affinityHDC);
+}
+
+static int Open(vlc_object_t *object)
+{
+ vlc_gl_t *gl = (vlc_gl_t *)object;
+ vout_display_sys_t *sys;
+
+ /* Allocate structure */
+ gl->sys = sys = calloc(1, sizeof(*sys));
+ if (!sys)
+ return VLC_ENOMEM;
+
+ /* Process selected GPU affinity */
+ int nVidiaAffinity = var_InheritInteger(gl, "gpu-affinity");
+ if (nVidiaAffinity >= 0) CreateGPUAffinityDC(gl, nVidiaAffinity);
+
+ vout_window_t *wnd = gl->surface;
+ sys->hvideownd = wnd->handle.hwnd;
+ if (wnd->type != VOUT_WINDOW_TYPE_HWND)
+ goto error;
+
+ sys->hGLDC = GetDC(wnd->handle.hwnd);
+ if (sys->hGLDC == NULL)
+ {
+ msg_Err(gl, "Could not get the device context");
+ goto error;
+ }
+
+ /* Set the pixel format for the DC */
+ PIXELFORMATDESCRIPTOR pfd;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+ pfd.cDepthBits = 16;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+ SetPixelFormat(sys->hGLDC, ChoosePixelFormat(sys->hGLDC, &pfd), &pfd);
+
+ /* Create the context. */
+ sys->hGLRC = wglCreateContext((sys->affinityHDC != NULL) ? sys->affinityHDC : sys->hGLDC);
+ if (sys->hGLRC == NULL)
+ {
+ msg_Err(gl, "Could not create the OpenGL rendering context");
+ goto error;
+ }
+
+#ifdef WGL_EXT_swap_control
+ wglMakeCurrent(sys->hGLDC, sys->hGLRC);
+ /* Create an GPU Affinity DC */
+ const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
+ if (HasExtension(extensions, "WGL_EXT_swap_control")) {
+ PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
+ if (SwapIntervalEXT)
+ SwapIntervalEXT(1);
+ }
+ wglMakeCurrent(sys->hGLDC, NULL);
+#endif
+
+ gl->makeCurrent = MakeCurrent;
+ gl->releaseCurrent = ReleaseCurrent;
+ gl->resize = NULL;
+ gl->swap = Swap;
+ gl->getProcAddress = OurGetProcAddress;
+
+ return VLC_SUCCESS;
+
+error:
+ Close(object);
+ return VLC_EGENERIC;
+}
+
+static void Close(vlc_object_t *object)
+{
+ vlc_gl_t *gl = (vlc_gl_t *)object;
+ vout_display_sys_t *sys = gl->sys;
+
+#ifdef WGL_EXT_swap_control
+ wglMakeCurrent(sys->hGLDC, sys->hGLRC);
+ DestroyGPUAffinityDC(gl);
+#endif
+
+ if (sys->hGLRC)
+ wglDeleteContext(sys->hGLRC);
+ if (sys->hGLDC)
+ ReleaseDC(sys->hvideownd, sys->hGLDC);
+
+ free(sys);
+}
+
+static void Swap(vlc_gl_t *gl)
+{
+ vout_display_sys_t *sys = gl->sys;
+ SwapBuffers(sys->hGLDC);
+}
+
+static void *OurGetProcAddress(vlc_gl_t *gl, const char *name)
+{
+ VLC_UNUSED(gl);
+ return wglGetProcAddress(name);
+}
+
+static int MakeCurrent(vlc_gl_t *gl)
+{
+ vout_display_sys_t *sys = gl->sys;
+ bool success = wglMakeCurrent(sys->hGLDC, sys->hGLRC);
+ return success ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
+static void ReleaseCurrent(vlc_gl_t *gl)
+{
+ vout_display_sys_t *sys = gl->sys;
+ wglMakeCurrent (sys->hGLDC, NULL);
+}
--
2.7.4
More information about the vlc-devel
mailing list