YaGL/VIGS: Use wglMakeCurrent instead of wglMakeContextCurrentARB when possible 62/13962/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 19 Dec 2013 08:07:59 +0000 (11:07 +0300)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 19 Dec 2013 08:19:38 +0000 (12:19 +0400)
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
hw/yagl/yagl_drivers/egl_wgl/yagl_egl_wgl.c

index 12fced5..72b94ab 100644 (file)
@@ -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) {
index ae9abb0..d58c24b 100644 (file)
@@ -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)