From de72735e8f9b1fdae8fcd0e38e5c64b5437b9374 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Thu, 19 Dec 2013 11:07:59 +0300 Subject: [PATCH] YaGL/VIGS: Use wglMakeCurrent instead of wglMakeContextCurrentARB when possible GPUs like Intel HD Graphics 2000 and some ATI cards may crash when using wglMakeContextCurrentARB when draw_sfc == read_sfc. We work around this by using wglMakeCurrent in this case Change-Id: I80735a546d6e506ecc3581a5e78fdc8e04f3a95c --- hw/vigs/vigs_gl_backend_wgl.c | 43 ++++++--------- hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c | 86 ++++++++++++++--------------- 2 files changed, 57 insertions(+), 72 deletions(-) diff --git a/hw/vigs/vigs_gl_backend_wgl.c b/hw/vigs/vigs_gl_backend_wgl.c index 12fced5..72b94ab 100644 --- a/hw/vigs/vigs_gl_backend_wgl.c +++ b/hw/vigs/vigs_gl_backend_wgl.c @@ -107,11 +107,11 @@ struct vigs_gl_backend_wgl PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB; PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB; PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB; - PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB; HWND win; HDC dc; HPBUFFERARB sfc; + HDC sfc_dc; HGLRC ctx; }; @@ -180,6 +180,13 @@ static bool vigs_gl_backend_wgl_create_surface(struct vigs_gl_backend_wgl *gl_ba return false; } + gl_backend_wgl->sfc_dc = gl_backend_wgl->wglGetPbufferDCARB(gl_backend_wgl->sfc); + + if (!gl_backend_wgl->sfc_dc) { + VIGS_LOG_CRITICAL("wglGetPbufferDCARB failed"); + return false; + } + return true; } @@ -208,26 +215,17 @@ static bool vigs_gl_backend_wgl_make_current(struct vigs_gl_backend *gl_backend, { struct vigs_gl_backend_wgl *gl_backend_wgl = (struct vigs_gl_backend_wgl*)gl_backend; - HDC dc; if (enable) { - dc = gl_backend_wgl->wglGetPbufferDCARB(gl_backend_wgl->sfc); - - if (!dc) { - VIGS_LOG_CRITICAL("wglGetPbufferDCARB failed"); + if (!gl_backend_wgl->wglMakeCurrent(gl_backend_wgl->sfc_dc, gl_backend_wgl->ctx)) { + VIGS_LOG_CRITICAL("wglMakeCurrent failed"); return false; } - - if (!gl_backend_wgl->wglMakeContextCurrentARB(dc, dc, gl_backend_wgl->ctx)) { - VIGS_LOG_CRITICAL("wglMakeContextCurrentARB failed"); - gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, dc); + } else { + if (!gl_backend_wgl->wglMakeCurrent(NULL, NULL)) { + VIGS_LOG_CRITICAL("wglMakeCurrent failed"); return false; } - } else { - if (!gl_backend_wgl->wglMakeContextCurrentARB(NULL, NULL, NULL)) { - VIGS_LOG_CRITICAL("wglMakeContextCurrentARB failed"); - return false; - } } return true; @@ -236,16 +234,11 @@ static bool vigs_gl_backend_wgl_make_current(struct vigs_gl_backend *gl_backend, static void vigs_gl_backend_wgl_destroy(struct vigs_backend *backend) { struct vigs_gl_backend_wgl *gl_backend_wgl = (struct vigs_gl_backend_wgl*)backend; - HDC dc; vigs_gl_backend_cleanup(&gl_backend_wgl->base); gl_backend_wgl->wglDeleteContext(gl_backend_wgl->ctx); - - dc = gl_backend_wgl->wglGetPbufferDCARB(gl_backend_wgl->sfc); - if (dc) { - gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, dc); - } + gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, gl_backend_wgl->sfc_dc); gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->sfc); ReleaseDC(gl_backend_wgl->win, gl_backend_wgl->dc); @@ -383,7 +376,6 @@ struct vigs_backend *vigs_gl_backend_create(void *display) VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLRELEASEPBUFFERDCARBPROC, wglReleasePbufferDCARB); VIGS_WGL_GET_EXT_PROC(WGL_ARB_pbuffer, PFNWGLDESTROYPBUFFERARBPROC, wglDestroyPbufferARB); VIGS_WGL_GET_EXT_PROC(WGL_ARB_pixel_format, PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB); - VIGS_WGL_GET_EXT_PROC(WGL_ARB_make_current_read, PFNWGLMAKECONTEXTCURRENTARBPROC, wglMakeContextCurrentARB); VIGS_GL_GET_PROC(GenTextures, glGenTextures); VIGS_GL_GET_PROC(DeleteTextures, glDeleteTextures); @@ -493,11 +485,10 @@ fail: if (gl_backend_wgl->ctx) { gl_backend_wgl->wglDeleteContext(gl_backend_wgl->ctx); } + if (gl_backend_wgl->sfc_dc) { + gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, gl_backend_wgl->sfc_dc); + } if (gl_backend_wgl->sfc) { - HDC dc = gl_backend_wgl->wglGetPbufferDCARB(gl_backend_wgl->sfc); - if (dc) { - gl_backend_wgl->wglReleasePbufferDCARB(gl_backend_wgl->sfc, dc); - } gl_backend_wgl->wglDestroyPbufferARB(gl_backend_wgl->sfc); } if (gl_backend_wgl->dc) { diff --git a/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c b/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c index ae9abb0..d58c24b 100644 --- a/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c +++ b/hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c @@ -89,6 +89,11 @@ typedef struct YaglEglWglDpy { GHashTable *dc_table; } YaglEglWglDpy; +typedef struct YaglEglWglSurface { + HPBUFFERARB pbuffer; + HDC dc; +} YaglEglWglSurface; + typedef struct YaglEglWglDriver { struct yagl_egl_driver base; @@ -544,8 +549,10 @@ static bool yagl_egl_wgl_make_current(struct yagl_egl_driver *driver, EGLContext egl_glc) { YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver); - HDC draw_dc = NULL, read_dc = NULL; + YaglEglWglSurface *egl_draw_sfc = egl_draw_surf; + YaglEglWglSurface *egl_read_sfc = egl_read_surf; HGLRC glc = NULL; + BOOL res; YAGL_EGL_WGL_ENTER(yagl_egl_wgl_make_current, "dpy = %p, draw = %p, read = %p, ctx = %p", @@ -558,27 +565,15 @@ static bool yagl_egl_wgl_make_current(struct yagl_egl_driver *driver, glc = (HGLRC)egl_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_draw_sfc != egl_read_sfc) { + res = egl_wgl->wglMakeContextCurrentARB((egl_draw_sfc ? egl_draw_sfc->dc : NULL), + (egl_read_sfc ? egl_read_sfc->dc : NULL), + glc); + } else { + res = egl_wgl->wglMakeCurrent((egl_draw_sfc ? egl_draw_sfc->dc : NULL), glc); } - if (egl_wgl->wglMakeContextCurrentARB(draw_dc, read_dc, glc) == FALSE) { + if (!res) { goto fail; } @@ -589,14 +584,6 @@ static bool yagl_egl_wgl_make_current(struct yagl_egl_driver *driver, 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; @@ -629,7 +616,7 @@ static EGLSurface yagl_egl_wgl_pbuffer_surface_create(struct yagl_egl_driver *dr YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver); HDC dc = NULL; YaglEglWglDpy * dpy = (YaglEglWglDpy *)egl_dpy; - HPBUFFERARB pbuffer; + YaglEglWglSurface * sfc = NULL; int pbuff_attribs[] = { WGL_PBUFFER_LARGEST_ARB, FALSE, WGL_TEXTURE_TARGET_ARB, WGL_NO_TEXTURE_ARB, @@ -667,22 +654,35 @@ static EGLSurface yagl_egl_wgl_pbuffer_surface_create(struct yagl_egl_driver *dr goto fail; } - pbuffer = egl_wgl->wglCreatePbufferARB(dc, cfg->config_id, - width, height, pbuff_attribs); + sfc = g_new0(YaglEglWglSurface, 1); + + sfc->pbuffer = egl_wgl->wglCreatePbufferARB(dc, cfg->config_id, + width, height, pbuff_attribs); - if (!pbuffer) { + if (!sfc->pbuffer) { goto fail; } - YAGL_LOG_FUNC_EXIT("Surface created: %p", pbuffer); + sfc->dc = egl_wgl->wglGetPbufferDCARB(sfc->pbuffer); - return (EGLSurface)pbuffer; + if (!sfc->dc) { + egl_wgl->wglDestroyPbufferARB(sfc->pbuffer); + goto fail; + } + + YAGL_LOG_FUNC_EXIT("Surface created: %p", sfc); + + return (EGLSurface)sfc; fail: YAGL_LOG_ERROR_WIN(); YAGL_LOG_FUNC_EXIT("Surface creation failed"); + if (sfc) { + g_free(sfc); + } + return EGL_NO_SURFACE; } @@ -691,26 +691,20 @@ static void yagl_egl_wgl_pbuffer_surface_destroy(struct yagl_egl_driver *driver, EGLSurface surf) { YaglEglWglDriver *egl_wgl = (YaglEglWglDriver *)(driver); - HDC pbuf_dc = NULL; + YaglEglWglSurface *egl_sfc = surf; YAGL_EGL_WGL_ENTER(yagl_egl_wgl_pbuffer_surface_destroy, "dpy = %p, sfc = %p", egl_dpy, surf); - pbuf_dc = egl_wgl->wglGetPbufferDCARB((HPBUFFERARB)surf); + egl_wgl->wglReleasePbufferDCARB(egl_sfc->pbuffer, egl_sfc->dc); - if (!pbuf_dc || - egl_wgl->wglReleasePbufferDCARB((HPBUFFERARB)surf, pbuf_dc) != 1) { - YAGL_LOG_ERROR_WIN(); - } + egl_wgl->wglDestroyPbufferARB(egl_sfc->pbuffer); - 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"); - } + g_free(egl_sfc); + + YAGL_LOG_FUNC_EXIT("Surface destroyed"); } static void yagl_egl_wgl_destroy(struct yagl_egl_driver *driver) -- 2.7.4