[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