[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