[vlc-devel] [PATCH] WGL: OpenGL module for Windows
Denis Charmet
typx at dinauz.org
Wed Jun 8 15:00:52 CEST 2016
Hi,
On 2016-06-07 18:06, Adrien Maglo wrote:
> 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) {
why void if this function can failed and is specifically turned on by
the user?
Silently failing here might be an issue.
> + 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 */
necessary :)
> + 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);
If you flag the destruction in Close() shouldn't you do it here too?
> +
> + 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);
> +}
Regards,
--
Denis Charmet - TypX
Le mauvais esprit est un art de vivre
More information about the vlc-devel
mailing list