YaGL: implement EGL WGL driver to support Windows hosts
authorIgor Mitsyanko <i.mitsyanko@samsung.com>
Thu, 15 Nov 2012 13:41:23 +0000 (17:41 +0400)
committerEvgeny Voevodin <e.voevodin@samsung.com>
Mon, 26 Nov 2012 09:25:37 +0000 (13:25 +0400)
Signed-off-by: Igor Mitsyanko <i.mitsyanko@samsung.com>
hw/yagl_drivers/egl_wgl/yagl_egl_wgl.c

index 551979583494195efe17f82a75660262d6675132..6a6e256b458e17d1596b8620c7b430780ccd005c 100644 (file)
 #include <windows.h>
-#include <GL/wglext.h>
 #include <wingdi.h>
+#include <GL/gl.h>
+#include <GL/wglext.h>
+#include <glib.h>
 #include "yagl_egl_driver.h"
 #include "yagl_dyn_lib.h"
 #include "yagl_log.h"
+#include "yagl_egl_native_config.h"
+#include "yagl_egl_surface_attribs.h"
+#include "yagl_process.h"
 #include "yagl_tls.h"
 #include "yagl_thread.h"
 
+#define YAGL_EGL_WGL_WIN_CLASS                "YaGLwinClass"
+
+#define YAGL_EGL_WGL_ENTER(func, format, ...) \
+    YAGL_LOG_FUNC_ENTER((egl_wgl_ts ? egl_wgl_ts->ps->id : driver_ps->ps->id), \
+                        (egl_wgl_ts ? egl_wgl_ts->id : 0),                     \
+                        func, format,##__VA_ARGS__)
+
+/* Get a core WGL function address */
+#define YAGL_EGL_WGL_GET_PROC(proc_type, proc_name) \
+    do {                                                                      \
+        egl_wgl->proc_name =                                                  \
+            (proc_type)yagl_dyn_lib_get_sym(egl_driver->dyn_lib, #proc_name); \
+        if (!egl_wgl->proc_name) {                                            \
+            YAGL_LOG_ERROR("%s not found!", #proc_name);                      \
+            goto fail;                                                        \
+        }                                                                     \
+        YAGL_LOG_TRACE("Got %s address", #proc_name);                         \
+    } while (0)
+
+/* Get a mandatory WGL extension function pointer */
+#define YAGL_EGL_WGL_GET_EXT_PROC(ext_name, proc_name, proc_type) \
+    do {                                                                      \
+        if (!yagl_egl_wgl_search_ext(ext_str, #ext_name)) {                   \
+            YAGL_LOG_ERROR("%s extension not supported", #ext_name);          \
+            goto out;                                                         \
+        }                                                                     \
+        egl_wgl->proc_name = (proc_type)                                      \
+                        egl_wgl->wglGetProcAddress((LPCSTR)#proc_name);       \
+        if (!egl_wgl->proc_name) {                                            \
+            YAGL_LOG_ERROR("Mandatory function %s not found", #proc_name);    \
+            goto out;                                                         \
+        }                                                                     \
+        YAGL_LOG_TRACE("Got %s address", #proc_name);                         \
+    } while (0)
+
+static YAGL_DEFINE_TLS(struct yagl_thread_state *, egl_wgl_ts);
+
+typedef HGLRC (WINAPI *WGLCREATECONTEXTPROC)(HDC hdl);
+typedef BOOL (WINAPI *WGLDELETECONTEXTPROC)(HGLRC hdl);
+typedef PROC (WINAPI *WGLGETPROCADDRESSPROC)(LPCSTR sym);
+typedef BOOL (WINAPI *WGLMAKECURRENTPROC)(HDC dev_ctx, HGLRC rend_ctx);
+typedef BOOL (WINAPI *WGLSHARELISTSPROC)(HGLRC ctx1, HGLRC ctx2);
+
+typedef struct YaglEglWglDriverPS {
+    struct yagl_egl_driver_ps base;
+} YaglEglWglDriverPS;
+
+typedef struct YaglEglWglDpy {
+    HWND win;
+    GHashTable *dc_table;
+    HDC *dc_arr;
+    gint *cfgids;
+    unsigned cfgid_cnt;
+    unsigned max_cfgid;
+} YaglEglWglDpy;
+
+typedef struct YaglEglWglSG {
+    HGLRC shared_glc;
+    unsigned ref_cnt;
+} YaglEglWglSG;
+
+typedef struct YaglEglWglCtx {
+    HGLRC glc;
+    YaglEglWglSG *share_group;
+} YaglEglWglCtx;
+
+typedef struct YaglEglWglDriver {
+    struct yagl_egl_driver base;
+
+    WGLCREATECONTEXTPROC wglCreateContext;
+    WGLDELETECONTEXTPROC wglDeleteContext;
+    WGLGETPROCADDRESSPROC wglGetProcAddress;
+    WGLMAKECURRENTPROC wglMakeCurrent;
+    WGLSHARELISTSPROC wglShareLists;
+
+    /* WGL extensions */
+    PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT;
+    PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
+    PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB;
+    PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
+    PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB;
+    PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB;
+    PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB;
+    PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB;
+    PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB;
+} YaglEglWglDriver;
+
+static inline HWND yagl_egl_wgl_dummy_win_create(void)
+{
+    return CreateWindow(YAGL_EGL_WGL_WIN_CLASS, "YaGLwin",
+        WS_DISABLED | WS_POPUP, 0, 0, 1, 1, NULL, NULL, 0, 0);
+}
+
+static inline bool yagl_egl_wgl_dc_set_def_pixfmt(HDC dc)
+{
+    INT pixfmt_idx;
+    PIXELFORMATDESCRIPTOR pixfmt = {
+        .nSize = sizeof(PIXELFORMATDESCRIPTOR),
+        .nVersion = 1,
+        .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
+        .iPixelType = PFD_TYPE_RGBA,
+        .cColorBits = 32,
+        .cDepthBits = 24,
+        .cStencilBits = 8,
+        .iLayerType = PFD_MAIN_PLANE,
+    };
+
+    pixfmt_idx = ChoosePixelFormat(dc, &pixfmt);
+
+    if (pixfmt_idx == 0) {
+        return false;
+    }
+
+    if (SetPixelFormat(dc, pixfmt_idx, &pixfmt) == FALSE) {
+        return false;
+    }
+
+    return true;
+}
+
+static void yagl_egl_wgl_thread_init(struct yagl_egl_driver_ps *driver_ps,
+                                     struct yagl_thread_state *ts)
+{
+    egl_wgl_ts = ts;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_thread_init, NULL);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static EGLNativeDisplayType
+yagl_egl_wgl_display_create(struct yagl_egl_driver_ps *driver_ps)
+{
+    YaglEglWglDpy *dpy;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_display_create, NULL);
+
+    dpy = g_try_new0(YaglEglWglDpy, 1);
+
+    if (!dpy) {
+        goto fail;
+    }
+
+    dpy->win = yagl_egl_wgl_dummy_win_create();
+
+    if (!dpy->win) {
+        g_free(dpy);
+        goto fail;
+    }
+
+    dpy->dc_table = g_hash_table_new(g_int_hash, g_int_equal);
+
+    YAGL_LOG_FUNC_EXIT("Display created: %p", dpy);
+
+    return (EGLNativeDisplayType)dpy;
+
+fail:
+    YAGL_LOG_FUNC_EXIT("Display creation failed");
+
+    return NULL;
+}
+
+static gboolean yagl_egl_wgl_cfgdc_free(gpointer key,
+                                        gpointer value,
+                                        gpointer usrdata)
+{
+    HWND win = *((HWND *)usrdata);
+    HDC dc = *((HDC *)value);
+
+    ReleaseDC(win, dc);
+
+    return TRUE;
+}
+
+static void yagl_egl_wgl_display_destroy(struct yagl_egl_driver_ps *driver_ps,
+                                         EGLNativeDisplayType egl_dpy)
+{
+    YaglEglWglDpy *dpy = (YaglEglWglDpy *)egl_dpy;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_display_destroy, "%p", dpy);
+
+    g_hash_table_foreach_remove(dpy->dc_table,
+                                yagl_egl_wgl_cfgdc_free,
+                                &dpy->win);
+
+    g_hash_table_destroy(dpy->dc_table);
+
+    DestroyWindow(dpy->win);
+
+    g_free(dpy->cfgids);
+    g_free(dpy->dc_arr);
+    g_free(dpy);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static bool yagl_egl_wgl_config_fill(struct yagl_egl_driver_ps *driver_ps,
+                                     HDC dc,
+                                     struct yagl_egl_native_config *cfg,
+                                     int fmt_idx)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    PIXELFORMATDESCRIPTOR *pix_fmt = NULL;
+    bool filled = false;
+
+    enum {
+        YAGL_WGL_PIXEL_TYPE = 0,
+        YAGL_WGL_DRAW_TO_PBUFFER,
+        YAGL_WGL_DOUBLE_BUFFER,
+        YAGL_WGL_SUPPORT_OPENGL,
+        YAGL_WGL_ACCELERATION,
+        YAGL_WGL_NEED_PALETTE,
+        YAGL_WGL_TRANSPARENT,
+        YAGL_WGL_TRANSPARENT_RED_VALUE,
+        YAGL_WGL_TRANSPARENT_GREEN_VALUE,
+        YAGL_WGL_TRANSPARENT_BLUE_VALUE,
+        YAGL_WGL_COLOR_BITS,
+        YAGL_WGL_RED_BITS,
+        YAGL_WGL_GREEN_BITS,
+        YAGL_WGL_BLUE_BITS,
+        YAGL_WGL_ALPHA_BITS,
+        YAGL_WGL_DEPTH_BITS,
+        YAGL_WGL_STENCIL_BITS,
+        YAGL_WGL_MAX_PBUFFER_PIXELS,
+        YAGL_WGL_MAX_PBUFFER_WIDTH,
+        YAGL_WGL_MAX_PBUFFER_HEIGHT,
+        YAGL_WGL_NUMBER_OVERLAYS,
+        YAGL_WGL_NUMBER_UNDERLAYS,
+        YAGL_WGL_NUM_OF_QUERY_ATTRIBS,
+    };
+
+    const int query_list[YAGL_WGL_NUM_OF_QUERY_ATTRIBS] = {
+        [YAGL_WGL_PIXEL_TYPE] = WGL_PIXEL_TYPE_ARB,
+        [YAGL_WGL_DRAW_TO_PBUFFER] = WGL_DRAW_TO_PBUFFER_ARB,
+        [YAGL_WGL_DOUBLE_BUFFER] = WGL_DOUBLE_BUFFER_ARB,
+        [YAGL_WGL_SUPPORT_OPENGL] = WGL_SUPPORT_OPENGL_ARB,
+        [YAGL_WGL_ACCELERATION] = WGL_ACCELERATION_ARB,
+        [YAGL_WGL_NEED_PALETTE] = WGL_NEED_PALETTE_ARB,
+        [YAGL_WGL_TRANSPARENT] = WGL_TRANSPARENT_ARB,
+        [YAGL_WGL_TRANSPARENT_RED_VALUE] = WGL_TRANSPARENT_RED_VALUE_ARB,
+        [YAGL_WGL_TRANSPARENT_GREEN_VALUE] = WGL_TRANSPARENT_GREEN_VALUE_ARB,
+        [YAGL_WGL_TRANSPARENT_BLUE_VALUE] = WGL_TRANSPARENT_BLUE_VALUE_ARB,
+        [YAGL_WGL_COLOR_BITS] = WGL_COLOR_BITS_ARB,
+        [YAGL_WGL_RED_BITS] = WGL_RED_BITS_ARB,
+        [YAGL_WGL_GREEN_BITS] = WGL_GREEN_BITS_ARB,
+        [YAGL_WGL_BLUE_BITS] = WGL_BLUE_BITS_ARB,
+        [YAGL_WGL_ALPHA_BITS] = WGL_ALPHA_BITS_ARB,
+        [YAGL_WGL_DEPTH_BITS] = WGL_DEPTH_BITS_ARB,
+        [YAGL_WGL_STENCIL_BITS] = WGL_STENCIL_BITS_ARB,
+        [YAGL_WGL_MAX_PBUFFER_PIXELS] = WGL_MAX_PBUFFER_PIXELS_ARB,
+        [YAGL_WGL_MAX_PBUFFER_WIDTH] = WGL_MAX_PBUFFER_WIDTH_ARB,
+        [YAGL_WGL_MAX_PBUFFER_HEIGHT] = WGL_MAX_PBUFFER_HEIGHT_ARB,
+        [YAGL_WGL_NUMBER_OVERLAYS] = WGL_NUMBER_OVERLAYS_ARB,
+        [YAGL_WGL_NUMBER_UNDERLAYS] = WGL_NUMBER_UNDERLAYS_ARB,
+    };
+
+    int attr_vals[YAGL_WGL_NUM_OF_QUERY_ATTRIBS];
+
+    if (egl_wgl->wglGetPixelFormatAttribivARB(dc, fmt_idx, 0,
+                                              YAGL_WGL_NUM_OF_QUERY_ATTRIBS,
+                                              query_list, attr_vals) == FALSE) {
+        goto out;
+    }
+
+    if (attr_vals[YAGL_WGL_PIXEL_TYPE] != WGL_TYPE_RGBA_ARB ||
+        attr_vals[YAGL_WGL_DRAW_TO_PBUFFER] != TRUE ||
+        attr_vals[YAGL_WGL_DOUBLE_BUFFER] != TRUE ||
+        attr_vals[YAGL_WGL_SUPPORT_OPENGL] != TRUE ||
+        attr_vals[YAGL_WGL_ACCELERATION] != WGL_FULL_ACCELERATION_ARB ||
+        attr_vals[YAGL_WGL_NEED_PALETTE] != FALSE) {
+        goto out;
+    }
+
+    /* This structure is used as a config driver data to pass it to
+     * ChoosePixelFormat later */
+    pix_fmt = g_try_new0(PIXELFORMATDESCRIPTOR, 1);
+    if (!pix_fmt) {
+        goto out;
+    }
+
+    if (!DescribePixelFormat(dc, fmt_idx,
+                             sizeof(PIXELFORMATDESCRIPTOR),
+                             pix_fmt)) {
+        g_free(pix_fmt);
+        goto out;
+    }
+
+    yagl_egl_native_config_init(cfg);
+
+    if (attr_vals[YAGL_WGL_TRANSPARENT] == TRUE) {
+        cfg->transparent_type = EGL_TRANSPARENT_RGB;
+        cfg->trans_red_val = attr_vals[YAGL_WGL_TRANSPARENT_RED_VALUE];
+        cfg->trans_green_val = attr_vals[YAGL_WGL_TRANSPARENT_GREEN_VALUE];
+        cfg->trans_blue_val = attr_vals[YAGL_WGL_TRANSPARENT_BLUE_VALUE];
+    } else {
+        cfg->transparent_type = EGL_NONE;
+    }
+
+    cfg->config_id = fmt_idx;
+    cfg->buffer_size = attr_vals[YAGL_WGL_COLOR_BITS];
+    cfg->red_size = attr_vals[YAGL_WGL_RED_BITS];
+    cfg->green_size = attr_vals[YAGL_WGL_GREEN_BITS];
+    cfg->blue_size = attr_vals[YAGL_WGL_BLUE_BITS];
+    cfg->alpha_size = attr_vals[YAGL_WGL_ALPHA_BITS];
+    cfg->depth_size = attr_vals[YAGL_WGL_DEPTH_BITS];
+    cfg->stencil_size = attr_vals[YAGL_WGL_STENCIL_BITS];
+    cfg->max_pbuffer_width = attr_vals[YAGL_WGL_MAX_PBUFFER_WIDTH];
+    cfg->max_pbuffer_height = attr_vals[YAGL_WGL_MAX_PBUFFER_HEIGHT];
+    cfg->max_pbuffer_size = attr_vals[YAGL_WGL_MAX_PBUFFER_PIXELS];
+    cfg->native_visual_type = EGL_NONE;
+    cfg->native_visual_id = 0;
+    cfg->caveat = EGL_NONE;
+    cfg->frame_buffer_level = 0;
+    cfg->samples_per_pixel = 0;
+    cfg->max_swap_interval = 10;
+    cfg->min_swap_interval = 1;
+    cfg->driver_data = pix_fmt;
+
+    filled = true;
+
+out:
+    return filled;
+}
+
+static struct yagl_egl_native_config
+    *yagl_egl_wgl_config_enum(struct yagl_egl_driver_ps *driver_ps,
+                              EGLNativeDisplayType egl_dpy,
+                              int *num_configs)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    YaglEglWglDpy *dpy = (YaglEglWglDpy *)egl_dpy;
+    HDC dc;
+    struct yagl_egl_native_config *egl_configs = NULL;
+    UINT pixfmt_cnt = 0;
+    int pixfmt_cnt_max = 0, curr_fmt_idx, cfg_index = 0;
+    int *pixfmt_arr;
+    const int query_num_of_formats = WGL_NUMBER_PIXEL_FORMATS_ARB;
+    const int attrib_list[] = {
+        WGL_SUPPORT_OPENGL_ARB, TRUE,
+        WGL_DOUBLE_BUFFER_ARB, TRUE,
+        WGL_DRAW_TO_PBUFFER_ARB, TRUE,
+        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+        WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+        0,
+    };
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_config_enum, "display %p", dpy);
+
+    *num_configs = 0;
+
+    dc = GetDC(dpy->win);
+    if (!dc) {
+        goto out;
+    }
+
+    /* Query number of pixel formats */
+    if (egl_wgl->wglGetPixelFormatAttribivARB(dc, 0, 0, 1,
+                                              &query_num_of_formats,
+                                              &pixfmt_cnt_max) == FALSE ||
+        !pixfmt_cnt_max) {
+        pixfmt_cnt_max = DescribePixelFormat(dc, 1, 0, NULL);
+    }
+
+    if (pixfmt_cnt_max == 0) {
+        YAGL_LOG_ERROR("No pixel formats found");
+        goto out;
+    }
+
+    pixfmt_arr = g_try_new0(int, pixfmt_cnt_max);
+    if (!pixfmt_arr) {
+        goto out;
+    }
+
+    if (egl_wgl->wglChoosePixelFormatARB(dc, attrib_list, NULL,
+                                         pixfmt_cnt_max,
+                                         pixfmt_arr,
+                                         &pixfmt_cnt) == FALSE) {
+        pixfmt_cnt = pixfmt_cnt_max;
+
+        for (curr_fmt_idx = 0; curr_fmt_idx < pixfmt_cnt; ++curr_fmt_idx) {
+            pixfmt_arr[curr_fmt_idx] = curr_fmt_idx + 1;
+        }
+    }
+
+    YAGL_LOG_DEBUG("got %d pixel formats", pixfmt_cnt);
+
+    egl_configs = g_try_new0(struct yagl_egl_native_config, pixfmt_cnt);
+    if (!egl_configs) {
+        g_free(pixfmt_arr);
+        goto out;
+    }
+
+    for (curr_fmt_idx = 0; curr_fmt_idx < pixfmt_cnt; ++curr_fmt_idx) {
+        if (yagl_egl_wgl_config_fill(driver_ps, dc,
+                                     &egl_configs[cfg_index],
+                                     pixfmt_arr[curr_fmt_idx])) {
+            YAGL_LOG_TRACE("Added config with pixfmt=%d",
+                pixfmt_arr[curr_fmt_idx]);
+            ++cfg_index;
+        }
+    }
+
+    if (cfg_index < pixfmt_cnt) {
+        egl_configs = g_renew(struct yagl_egl_native_config,
+                                     egl_configs,
+                                     cfg_index);
+    }
+
+    *num_configs = cfg_index;
+
+    dpy->cfgids = g_new0(gint, cfg_index);
+    dpy->dc_arr = g_new0(HDC, cfg_index);
+    dpy->max_cfgid = cfg_index - 1;
+
+    g_free(pixfmt_arr);
+
+out:
+    if (dc) {
+        ReleaseDC(dpy->win, dc);
+    }
+
+    YAGL_LOG_INFO("WGL returned %d configs, %d are usable",
+                   pixfmt_cnt, cfg_index);
+
+    YAGL_LOG_FUNC_EXIT("Enumerated %d configs", cfg_index);
+
+    return egl_configs;
+}
+
+static void yagl_egl_wgl_config_cleanup(struct yagl_egl_driver_ps *driver_ps,
+                                        EGLNativeDisplayType dpy,
+                                        struct yagl_egl_native_config *cfg)
+{
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_config_cleanup,
+                       "dpy = %p, cfg = %d",
+                       dpy, cfg->config_id);
+
+    g_free(cfg->driver_data);
+    cfg->driver_data = NULL;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static HDC yagl_egl_wgl_dc_by_cfgid_get(YaglEglWglDpy *dpy,
+                                  const struct yagl_egl_native_config *cfg)
+{
+    HDC dc;
+    HDC *dc_p;
+
+    dc_p = g_hash_table_lookup(dpy->dc_table, &cfg->config_id);
+
+    if (dc_p) {
+        dc = *dc_p;
+        goto out;
+    }
+
+    assert(dpy->cfgid_cnt <= dpy->max_cfgid);
+
+    dc = GetDC(dpy->win);
+    if (!dc) {
+        goto out;
+    }
+
+    if (!SetPixelFormat(dc, cfg->config_id,
+                        (PIXELFORMATDESCRIPTOR *)cfg->driver_data)) {
+        ReleaseDC(dpy->win, dc);
+        dc = NULL;
+        goto out;
+    }
+
+    dpy->dc_arr[dpy->cfgid_cnt] = dc;
+    dpy->cfgids[dpy->cfgid_cnt] = cfg->config_id;
+
+    g_hash_table_insert(dpy->dc_table,
+                        &dpy->cfgids[dpy->cfgid_cnt],
+                        &dpy->dc_arr[dpy->cfgid_cnt]);
+
+    ++dpy->cfgid_cnt;
+
+out:
+    return dc;
+}
+
+static void yagl_egl_wgl_sharegrp_release(YaglEglWglDriver *egl_wgl,
+                                                 YaglEglWglSG *share_group)
+{
+       assert(share_group->ref_cnt > 0);
+
+       if (--share_group->ref_cnt == 0) {
+               egl_wgl->wglDeleteContext(share_group->shared_glc);
+               g_free(share_group);
+       }
+}
+
+static inline void yagl_egl_wgl_sharegrp_acquire(YaglEglWglSG *share_group)
+{
+       ++share_group->ref_cnt;
+}
+
+static EGLContext yagl_egl_wgl_context_create(struct yagl_egl_driver_ps *driver_ps,
+                                              EGLNativeDisplayType egl_dpy,
+                                              const struct yagl_egl_native_config *cfg,
+                                              yagl_client_api client_api,
+                                              EGLContext share_context)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    YaglEglWglDpy *dpy = (YaglEglWglDpy *)egl_dpy;
+    YaglEglWglCtx *egl_wgl_ctx;
+    HDC dc;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_context_create,
+                       "dpy = %p, api = %u, share_context = %p, cfgid=%d",
+                       dpy, client_api, share_context, cfg->config_id);
+
+    egl_wgl_ctx = g_try_new0(YaglEglWglCtx, 1);
+    if (!egl_wgl_ctx) {
+        goto fail;
+    }
+
+    dc = yagl_egl_wgl_dc_by_cfgid_get(dpy, cfg);
+    if (!dc) {
+        YAGL_LOG_ERROR("failed to get DC with cfgid=%d", cfg->config_id);
+        goto fail;
+    }
+
+    if (share_context != EGL_NO_CONTEXT) {
+        egl_wgl_ctx->share_group =
+            ((YaglEglWglCtx *)share_context)->share_group;
+    } else {
+        egl_wgl_ctx->share_group = g_try_new0(YaglEglWglSG, 1);
+
+        if (!egl_wgl_ctx->share_group) {
+            goto fail;
+        }
+
+        egl_wgl_ctx->share_group->shared_glc = egl_wgl->wglCreateContext(dc);
+        if (!egl_wgl_ctx->share_group->shared_glc) {
+            g_free(egl_wgl_ctx->share_group);
+            goto fail;
+        }
+    }
+
+    yagl_egl_wgl_sharegrp_acquire(egl_wgl_ctx->share_group);
+
+    egl_wgl_ctx->glc = egl_wgl->wglCreateContext(dc);
+    if (!egl_wgl_ctx->glc) {
+       yagl_egl_wgl_sharegrp_release(egl_wgl, egl_wgl_ctx->share_group);
+        goto fail;
+    }
+
+    if(!egl_wgl->wglShareLists(egl_wgl_ctx->share_group->shared_glc,
+                               egl_wgl_ctx->glc)) {
+       yagl_egl_wgl_sharegrp_release(egl_wgl, egl_wgl_ctx->share_group);
+        egl_wgl->wglDeleteContext(egl_wgl_ctx->glc);
+        goto fail;
+    }
+
+    YAGL_LOG_FUNC_EXIT("Context created: %p (HGLRC=%p, shared=%p refcnt=%u)",
+        egl_wgl_ctx, egl_wgl_ctx->glc, egl_wgl_ctx->share_group->shared_glc,
+        egl_wgl_ctx->share_group->ref_cnt);
+
+    return (EGLContext)egl_wgl_ctx;
+
+fail:
+    g_free(egl_wgl_ctx);
+
+    YAGL_LOG_ERROR_WIN();
+
+    YAGL_LOG_FUNC_EXIT("Failed to create new context");
+
+    return EGL_NO_CONTEXT;
+}
+
+static bool yagl_egl_wgl_make_current(struct yagl_egl_driver_ps *driver_ps,
+                                      EGLNativeDisplayType dc,
+                                      EGLSurface egl_draw_surf,
+                                      EGLSurface egl_read_surf,
+                                      EGLContext egl_glc)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    HDC draw_dc = NULL, read_dc = NULL;
+    HGLRC glc = NULL;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_make_current,
+                       "dpy = %p, draw = %p, read = %p, ctx = %p",
+                       dc,
+                       egl_draw_surf,
+                       egl_read_surf,
+                       egl_glc);
+
+    if (egl_glc != EGL_NO_CONTEXT) {
+        glc = ((YaglEglWglCtx *)egl_glc)->glc;
+    }
+
+    if (egl_draw_surf != EGL_NO_SURFACE) {
+        draw_dc = egl_wgl->wglGetPbufferDCARB((HPBUFFERARB)egl_draw_surf);
+
+        if (!draw_dc) {
+            goto fail;
+        }
+    }
+
+    if (egl_read_surf != EGL_NO_SURFACE) {
+        if (egl_read_surf == egl_draw_surf) {
+            read_dc = draw_dc;
+        } else {
+            read_dc = egl_wgl->wglGetPbufferDCARB((HPBUFFERARB)egl_read_surf);
+
+            if (!read_dc) {
+                goto fail;
+            }
+        }
+    }
+
+    if (egl_wgl->wglMakeContextCurrentARB(draw_dc, read_dc, glc) == FALSE) {
+        goto fail;
+    }
+
+    YAGL_LOG_FUNC_EXIT("context %p was made current", glc);
+
+    return true;
+
+fail:
+    YAGL_LOG_ERROR_WIN();
+
+    if (draw_dc) {
+        egl_wgl->wglReleasePbufferDCARB((HPBUFFERARB)egl_draw_surf, draw_dc);
+    }
+
+    if (read_dc && (egl_read_surf != egl_draw_surf)) {
+        egl_wgl->wglReleasePbufferDCARB((HPBUFFERARB)egl_read_surf, read_dc);
+    }
+
+    YAGL_LOG_FUNC_EXIT("Failed to make context %p current", glc);
+
+    return false;
+}
+
+static void yagl_egl_wgl_context_destroy(struct yagl_egl_driver_ps *driver_ps,
+                                         EGLNativeDisplayType egl_dpy,
+                                         EGLContext egl_glc)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    YaglEglWglCtx *wgl_ctx = (YaglEglWglCtx *)egl_glc;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_context_destroy,
+                       "dpy = %p, ctx = %p, glc=%p",
+                       egl_dpy, wgl_ctx, wgl_ctx->glc);
+
+    yagl_egl_wgl_sharegrp_release(egl_wgl, wgl_ctx->share_group);
+
+    if (egl_wgl->wglDeleteContext(wgl_ctx->glc) == FALSE) {
+        YAGL_LOG_ERROR_WIN();
+    }
+
+    g_free(wgl_ctx);
+
+    YAGL_LOG_FUNC_EXIT("Context destroyed");
+}
+
+static EGLSurface yagl_egl_wgl_pbuffer_surface_create(struct yagl_egl_driver_ps *driver_ps,
+                                                      EGLNativeDisplayType egl_dpy,
+                                                      const struct yagl_egl_native_config *cfg,
+                                                      EGLint width,
+                                                      EGLint height,
+                                                      const struct yagl_egl_pbuffer_attribs *attribs)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    HDC dc = NULL;
+    YaglEglWglDpy * dpy = (YaglEglWglDpy *)egl_dpy;
+    HPBUFFERARB pbuffer;
+    int pbuff_attribs[] = {
+        WGL_PBUFFER_LARGEST_ARB, FALSE,
+        WGL_TEXTURE_TARGET_ARB, WGL_NO_TEXTURE_ARB,
+        WGL_TEXTURE_FORMAT_ARB, WGL_NO_TEXTURE_ARB,
+        0
+    };
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_pbuffer_surface_create,
+                       "dpy = %p, width = %d, height = %d, cfgid=%d",
+                       egl_dpy,
+                       width,
+                       height,
+                       cfg->config_id);
+
+    if (attribs->largest) {
+        pbuff_attribs[1] = TRUE;
+    }
+
+    if (attribs->tex_target == EGL_TEXTURE_2D) {
+        pbuff_attribs[3] = WGL_TEXTURE_2D_ARB;
+    }
+
+    switch (attribs->tex_format) {
+    case EGL_TEXTURE_RGB:
+        pbuff_attribs[5] = WGL_TEXTURE_RGB_ARB;
+        break;
+    case EGL_TEXTURE_RGBA:
+        pbuff_attribs[5] = WGL_TEXTURE_RGBA_ARB;
+        break;
+    }
+
+    dc = yagl_egl_wgl_dc_by_cfgid_get(dpy, cfg);
+    if (!dc) {
+        YAGL_LOG_ERROR("failed to get DC with cfgid=%d", cfg->config_id);
+        goto fail;
+    }
+
+    pbuffer = egl_wgl->wglCreatePbufferARB(dc, cfg->config_id,
+             width, height, pbuff_attribs);
+
+    if (!pbuffer) {
+        goto fail;
+    }
+
+    YAGL_LOG_FUNC_EXIT("Surface created: %p", pbuffer);
+
+    return (EGLSurface)pbuffer;
+
+fail:
+    YAGL_LOG_ERROR_WIN();
+
+    YAGL_LOG_FUNC_EXIT("Surface creation failed");
+
+    return EGL_NO_SURFACE;
+}
+
+static void yagl_egl_wgl_pbuffer_surface_destroy(struct yagl_egl_driver_ps *driver_ps,
+                                                 EGLNativeDisplayType egl_dpy,
+                                                 EGLSurface surf)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver_ps->driver);
+    HDC pbuf_dc = NULL;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_pbuffer_surface_destroy,
+                       "dpy = %p, sfc = %p",
+                       egl_dpy,
+                       surf);
+
+    pbuf_dc = egl_wgl->wglGetPbufferDCARB((HPBUFFERARB)surf);
+
+    if (!pbuf_dc ||
+        egl_wgl->wglReleasePbufferDCARB((HPBUFFERARB)surf, pbuf_dc) != 1) {
+        YAGL_LOG_ERROR_WIN();
+    }
+
+    if (egl_wgl->wglDestroyPbufferARB((HPBUFFERARB)surf) == FALSE) {
+        YAGL_LOG_ERROR_WIN();
+        YAGL_LOG_FUNC_EXIT("Failed to destroy surface");
+    } else {
+        YAGL_LOG_FUNC_EXIT("Surface destroyed");
+    }
+}
+
+static void yagl_egl_wgl_wait_native(struct yagl_egl_driver_ps *driver_ps)
+{
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_wait_native, NULL);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_wgl_thread_fini(struct yagl_egl_driver_ps *driver_ps)
+{
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_thread_fini, NULL);
+
+    egl_wgl_ts = NULL;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_wgl_process_destroy(struct yagl_egl_driver_ps *driver_ps)
+{
+    YaglEglWglDriverPS *egl_glx_ps = (YaglEglWglDriverPS *)driver_ps;
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_process_destroy, NULL);
+
+    yagl_egl_driver_ps_cleanup(&egl_glx_ps->base);
+
+    g_free(egl_glx_ps);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static struct yagl_egl_driver_ps
+    *yagl_egl_wgl_process_init(struct yagl_egl_driver *driver,
+                               struct yagl_process_state *ps)
+{
+    YaglEglWglDriverPS *egl_wgl_ps = g_new0(YaglEglWglDriverPS, 1);
+    struct yagl_egl_driver_ps *driver_ps = &egl_wgl_ps->base;
+
+    yagl_egl_driver_ps_init(driver_ps, driver, ps);
+
+    YAGL_EGL_WGL_ENTER(yagl_egl_wgl_process_init, NULL);
+
+    driver_ps->thread_init = &yagl_egl_wgl_thread_init;
+    driver_ps->display_create = &yagl_egl_wgl_display_create;
+    driver_ps->display_destroy = &yagl_egl_wgl_display_destroy;
+    driver_ps->config_enum = &yagl_egl_wgl_config_enum;
+    driver_ps->config_cleanup = &yagl_egl_wgl_config_cleanup;
+    driver_ps->pbuffer_surface_create = &yagl_egl_wgl_pbuffer_surface_create;
+    driver_ps->pbuffer_surface_destroy = &yagl_egl_wgl_pbuffer_surface_destroy;
+    driver_ps->context_create = &yagl_egl_wgl_context_create;
+    driver_ps->context_destroy = &yagl_egl_wgl_context_destroy;
+    driver_ps->make_current = &yagl_egl_wgl_make_current;
+    driver_ps->wait_native = &yagl_egl_wgl_wait_native;
+    driver_ps->thread_fini = &yagl_egl_wgl_thread_fini;
+    driver_ps->destroy = &yagl_egl_wgl_process_destroy;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return driver_ps;
+}
+
+static void yagl_egl_wgl_destroy(struct yagl_egl_driver *driver)
+{
+    YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)driver;
+
+    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_destroy, NULL);
+
+    UnregisterClassA((LPCTSTR)YAGL_EGL_WGL_WIN_CLASS, NULL);
+
+    yagl_egl_driver_cleanup(driver);
+
+    g_free(egl_wgl);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+/*
+ * Check if extension string 'ext_string' contains extension name 'ext_name'.
+ * Needed because extension name could be a substring of a longer extension
+ * name.
+ */
+static bool yagl_egl_wgl_search_ext(const gchar *ext_string,
+                                    const gchar *ext_name)
+{
+    const size_t name_len = strlen(ext_name);
+    gchar *ext = g_strstr_len(ext_string, -1, ext_name);
+
+    while (ext) {
+        if (ext[name_len] == '\0' || ext[name_len] == ' ') {
+            break;
+        }
+
+        ext += name_len;
+        ext = g_strstr_len(ext, -1, ext_name);
+    }
+
+    return ext != NULL;
+}
+
+/*
+ *  A stub for YaGL window class window procedure callback
+ */
+static LRESULT CALLBACK yagl_egl_wgl_winproc(HWND win, UINT msg, WPARAM wparam,
+                                      LPARAM lparam)
+{
+    return DefWindowProcA(win, msg, wparam, lparam);
+}
+
+/*
+ * Initialize pointers to WGL extension functions.
+ * Pointers are acquired with wglGetProcAddress() function, which works only
+ * in a presence of a valid openGL context. Pointers returned by
+ * wglGetProcAddress() are themselves context-specific, but we assume that
+ * if two contexts refer to the same GPU, then the function pointers pulled
+ * from one context will work in another.
+ * Note that we only need current context to ACQUIRE function pointers,
+ * we don't need a context to use them.
+ */
+static bool yagl_egl_wgl_init_ext(YaglEglWglDriver *egl_wgl)
+{
+    HWND win;
+    HDC dc = NULL;
+    HGLRC glc = NULL;
+    const char *ext_str = NULL;
+    bool ext_initialized = false;
+
+    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_init_ext, NULL);
+
+    win = yagl_egl_wgl_dummy_win_create();
+    if (!win) {
+        goto out;
+    }
+
+    dc = GetDC(win);
+    if (!dc) {
+        goto out;
+    }
+
+    if (!yagl_egl_wgl_dc_set_def_pixfmt(dc)) {
+        goto out;
+    }
+
+    glc = egl_wgl->wglCreateContext(dc);
+    if (!glc) {
+        goto out;
+    }
+
+    if (!egl_wgl->wglMakeCurrent(dc, glc)) {
+        goto out;
+    }
+
+    /* WGL extensions couldn't be queried by glGetString(), we need to use
+     * wglGetExtensionsStringARB or wglGetExtensionsStringEXT for this, which
+     * themselves are extensions */
+    egl_wgl->wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
+            egl_wgl->wglGetProcAddress((LPCSTR)"wglGetExtensionsStringARB");
+    egl_wgl->wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
+            egl_wgl->wglGetProcAddress((LPCSTR)"wglGetExtensionsStringEXT");
+
+    if (egl_wgl->wglGetExtensionsStringARB) {
+        ext_str = egl_wgl->wglGetExtensionsStringARB(dc);
+    } else if (egl_wgl->wglGetExtensionsStringEXT) {
+        ext_str = egl_wgl->wglGetExtensionsStringEXT();
+    }
+
+    if (!ext_str) {
+        YAGL_LOG_ERROR("Couldn't acquire WGL extensions string");
+        goto out;
+    }
+
+    YAGL_LOG_INFO("WGL extensions: %s", ext_str);
+
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pixel_format, wglGetPixelFormatAttribivARB, PFNWGLGETPIXELFORMATATTRIBIVARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, wglCreatePbufferARB, PFNWGLCREATEPBUFFERARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, wglGetPbufferDCARB, PFNWGLGETPBUFFERDCARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, wglReleasePbufferDCARB, PFNWGLRELEASEPBUFFERDCARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, wglDestroyPbufferARB, PFNWGLDESTROYPBUFFERARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_pixel_format, wglChoosePixelFormatARB, PFNWGLCHOOSEPIXELFORMATARBPROC);
+    YAGL_EGL_WGL_GET_EXT_PROC(WGL_ARB_make_current_read, wglMakeContextCurrentARB, PFNWGLMAKECONTEXTCURRENTARBPROC);
+
+    ext_initialized = true;
+
+out:
+       if (glc) {
+           if (egl_wgl->wglMakeCurrent(NULL, NULL) == FALSE) {
+               YAGL_LOG_ERROR_WIN();
+           }
+
+           if (egl_wgl->wglDeleteContext(glc) == FALSE) {
+               YAGL_LOG_ERROR_WIN();
+           }
+       }
+
+       if (win) {
+           if (dc) {
+               ReleaseDC(win, dc);
+           }
+           DestroyWindow(win);
+       }
+
+    YAGL_LOG_FUNC_EXIT("Extensions initialized status: %u", ext_initialized);
+
+    return ext_initialized;
+}
+
 struct yagl_egl_driver *yagl_egl_wgl_create(void)
 {
+    YaglEglWglDriver *egl_wgl;
+    struct yagl_egl_driver *egl_driver;
+    WNDCLASSEXA yagl_win_class;
+
+    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_create, NULL);
+
+    egl_wgl = g_new0(YaglEglWglDriver, 1);
+
+    egl_driver = &egl_wgl->base;
+
+    yagl_egl_driver_init(egl_driver);
+
+    egl_driver->dyn_lib = yagl_dyn_lib_create();
+
+    if (!yagl_dyn_lib_load(egl_driver->dyn_lib, "opengl32")) {
+        YAGL_LOG_ERROR("Loading opengl32.dll failed with error: %s",
+                       yagl_dyn_lib_get_error(egl_driver->dyn_lib));
+        goto fail;
+    }
+
+    yagl_win_class.cbSize = sizeof(WNDCLASSEXA);
+    yagl_win_class.style = 0;
+    yagl_win_class.lpfnWndProc = &yagl_egl_wgl_winproc;
+    yagl_win_class.cbClsExtra = 0;
+    yagl_win_class.cbWndExtra = 0;
+    yagl_win_class.hInstance = NULL;
+    yagl_win_class.hIcon = NULL;
+    yagl_win_class.hCursor = NULL;
+    yagl_win_class.hbrBackground = NULL;
+    yagl_win_class.lpszMenuName =  NULL;
+    yagl_win_class.lpszClassName = YAGL_EGL_WGL_WIN_CLASS;
+    yagl_win_class.hIconSm = NULL;
+
+    if (!RegisterClassExA(&yagl_win_class)) {
+        goto fail;
+    }
+
+    YAGL_EGL_WGL_GET_PROC(WGLCREATECONTEXTPROC, wglCreateContext);
+    YAGL_EGL_WGL_GET_PROC(WGLDELETECONTEXTPROC, wglDeleteContext);
+    YAGL_EGL_WGL_GET_PROC(WGLGETPROCADDRESSPROC, wglGetProcAddress);
+    YAGL_EGL_WGL_GET_PROC(WGLMAKECURRENTPROC, wglMakeCurrent);
+    YAGL_EGL_WGL_GET_PROC(WGLSHARELISTSPROC, wglShareLists);
+
+    egl_driver->process_init = &yagl_egl_wgl_process_init;
+    egl_driver->destroy = &yagl_egl_wgl_destroy;
+
+    if (!yagl_egl_wgl_init_ext(egl_wgl)) {
+        goto fail;
+    }
+
+    YAGL_LOG_FUNC_EXIT("EGL_WGL driver created (%p)", egl_driver);
+
+    return egl_driver;
+
+fail:
+    yagl_egl_driver_cleanup(egl_driver);
+    g_free(egl_wgl);
+
+    YAGL_LOG_ERROR_WIN();
+
+    YAGL_LOG_FUNC_EXIT("EGL_WGL driver creation failed");
+
     return NULL;
 }
 
+static void *yagl_egl_wgl_extaddr_get(struct yagl_dyn_lib *dyn_lib,
+                                      const char *sym)
+{
+    static WGLGETPROCADDRESSPROC wgl_get_procaddr_fn = NULL;
+    static WGLCREATECONTEXTPROC wgl_create_context_fn = NULL;
+    static WGLMAKECURRENTPROC wgl_make_current_fn = NULL;
+    static WGLDELETECONTEXTPROC wgl_delete_context_fn = NULL;
+    void *proc = NULL;
+    HWND win = NULL;
+    HDC dc = NULL;
+    HGLRC glc;
+
+    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_extaddr_get, "%s", sym);
+
+    if (!wgl_get_procaddr_fn) {
+        wgl_get_procaddr_fn = (WGLGETPROCADDRESSPROC)
+                yagl_dyn_lib_get_sym(dyn_lib, "wglGetProcAddress");
+    }
+
+    if (!wgl_create_context_fn) {
+        wgl_create_context_fn = (WGLCREATECONTEXTPROC)
+                yagl_dyn_lib_get_sym(dyn_lib, "wglCreateContext");
+    }
+
+    if (!wgl_make_current_fn) {
+        wgl_make_current_fn = (WGLMAKECURRENTPROC)
+                yagl_dyn_lib_get_sym(dyn_lib, "wglMakeCurrent");
+    }
+
+    if (!wgl_delete_context_fn) {
+        wgl_delete_context_fn = (WGLDELETECONTEXTPROC)
+                yagl_dyn_lib_get_sym(dyn_lib, "wglDeleteContext");
+    }
+
+    if (!wgl_get_procaddr_fn || !wgl_create_context_fn ||
+        !wgl_make_current_fn || !wgl_delete_context_fn) {
+        goto out;
+    }
+
+    /* To use wglGetProcAddress, create a temporary openGL context
+     * and make it current */
+
+    win = yagl_egl_wgl_dummy_win_create();
+    if (!win) {
+        goto out;
+    }
+
+    dc = GetDC(win);
+    if (!dc) {
+        goto out;
+    }
+
+    /* We need to set pixel format of dc before we can create GL context */
+    if (!yagl_egl_wgl_dc_set_def_pixfmt(dc)) {
+        goto out;
+    }
+
+    glc = wgl_create_context_fn(dc);
+    if (!glc) {
+        goto out;
+    }
+
+    if (wgl_make_current_fn(dc, glc) == FALSE) {
+        wgl_make_current_fn(NULL, NULL);
+        wgl_delete_context_fn(glc);
+        goto out;
+    }
+
+    proc = (void *)wgl_get_procaddr_fn((LPCSTR)sym);
+
+    if (wgl_make_current_fn(NULL, NULL) == FALSE) {
+        YAGL_LOG_ERROR_WIN();
+    }
+
+    if (wgl_delete_context_fn(glc) == FALSE) {
+        YAGL_LOG_ERROR_WIN();
+    }
+
+out:
+   if (!proc) {
+       YAGL_LOG_ERROR_WIN();
+   }
+
+    if (win) {
+        if (dc) {
+            ReleaseDC(win, dc);
+        }
+        DestroyWindow(win);
+    }
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return proc;
+}
+
+/* GetProcAddress only works for core OpenGL v.1.1 functions, while
+ * wglGetProcAddress will fail for <=v1.1 openGL functions, so we need them
+ * both */
 void *yagl_egl_wgl_procaddr_get(struct yagl_dyn_lib *dyn_lib,
                                        const char *sym)
 {
     void *proc = NULL;
 
-    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_get_procaddr, NULL);
+    YAGL_LOG_FUNC_ENTER_NPT(yagl_egl_wgl_get_procaddr,
+               "Retrieving %s address", sym);
+
+    proc = yagl_egl_wgl_extaddr_get(dyn_lib, sym);
+
+    if (!proc) {
+       YAGL_LOG_TRACE("wglGetProcAddress failed for %s, trying GetProcAddress",
+           sym);
+        proc = yagl_dyn_lib_get_sym(dyn_lib, sym);
+    }
+
+    YAGL_LOG_FUNC_EXIT("%s address: %p", sym, proc);
 
-    YAGL_LOG_FUNC_EXIT("%p", proc);
     return proc;
 }