Commit db93ff06 authored by Adrien Maglo's avatar Adrien Maglo Committed by Jean-Baptiste Kempf

WGL: OpenGL provider module for Windows

Reactivate the support of projectM and 3dspectrum visualization modules
on Windows.

fix #13650
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent bb836809
......@@ -122,6 +122,7 @@ Video ouput:
* Added Direct3D11 video mode supporting both Windows desktop and WinRT modes,
supporting subpicture blending and hardware acceleration
* EFL Evas video output with Tizen TBM Surface support
* New OpenGL provider for Windows
Text renderer:
* CTL support through Harfbuzz in the Freetype module
......
......@@ -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>
......
......@@ -447,6 +447,7 @@ $Id$
* wav: Wav demuxer
* wave: Wave video effect
* waveout: simple audio output module for Windows
* wgl: WGL extension for OpenGL
* win_hotkeys: module to catch hotkeys when application doesn't have the focus
* win_msg: Windows Messages module
* windrive: Windows logical disc drives
......
......@@ -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 \
......
......@@ -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
......
/*****************************************************************************
* wgl.c: WGL extension for OpenGL
*****************************************************************************
* Copyright © 2009-2016 VLC authors and VideoLAN
*
* Authors: Adrien Maglo <magsoft@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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment