Alexandre Julliard : wineandroid: Create a proper EGL window surface once we receive a surface from Java.

Alexandre Julliard julliard at winehq.org
Thu Jun 22 16:50:52 CDT 2017


Module: wine
Branch: master
Commit: 01439ef590a0915bc29199786c23270146396842
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=01439ef590a0915bc29199786c23270146396842

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jun 22 22:50:32 2017 +0200

wineandroid: Create a proper EGL window surface once we receive a surface from Java.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wineandroid.drv/android.h |  1 +
 dlls/wineandroid.drv/device.c  |  4 +-
 dlls/wineandroid.drv/opengl.c  | 86 +++++++++++++++++++++++++++++++++++++++++-
 dlls/wineandroid.drv/window.c  |  6 ++-
 4 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h
index 2cd167f..29daefe 100644
--- a/dlls/wineandroid.drv/android.h
+++ b/dlls/wineandroid.drv/android.h
@@ -52,6 +52,7 @@ DECL_FUNCPTR( ANativeWindow_release );
  * OpenGL driver
  */
 
+extern void update_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
 extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
 extern struct opengl_funcs *get_wgl_driver( UINT version ) DECLSPEC_HIDDEN;
 
diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c
index 54c409b..472f4ba 100644
--- a/dlls/wineandroid.drv/device.c
+++ b/dlls/wineandroid.drv/device.c
@@ -461,7 +461,7 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
     if (!data || data->parent == win)
     {
         if (win) pANativeWindow_release( win );
-        if (data && win) PostMessageW( hwnd, WM_ANDROID_REFRESH, 0, 0 );
+        if (data && win) PostMessageW( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
         TRACE( "%p -> %p win %p (unchanged)\n", hwnd, data, win );
         return;
     }
@@ -475,7 +475,7 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
         win->perform( win, NATIVE_WINDOW_SET_BUFFERS_FORMAT, data->buffer_format );
         win->setSwapInterval( win, data->swap_interval );
         unwrap_java_call();
-        PostMessageW( hwnd, WM_ANDROID_REFRESH, 0, 0 );
+        PostMessageW( hwnd, WM_ANDROID_REFRESH, opengl, 0 );
     }
     TRACE( "%p -> %p win %p\n", hwnd, data, win );
 }
diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c
index 60f14b4..910652b 100644
--- a/dlls/wineandroid.drv/opengl.c
+++ b/dlls/wineandroid.drv/opengl.c
@@ -76,7 +76,9 @@ struct wgl_context
     struct list entry;
     EGLConfig  config;
     EGLContext context;
+    EGLSurface surface;
     HWND       hwnd;
+    BOOL       refresh;
 };
 
 struct gl_drawable
@@ -86,6 +88,7 @@ struct gl_drawable
     HDC             hdc;
     int             format;
     ANativeWindow  *window;
+    EGLSurface      surface;
     EGLSurface      pbuffer;
 };
 
@@ -100,6 +103,9 @@ static struct opengl_funcs egl_funcs;
 static struct list gl_contexts = LIST_INIT( gl_contexts );
 static struct list gl_drawables = LIST_INIT( gl_drawables );
 
+static void (*pglFinish)(void);
+static void (*pglFlush)(void);
+
 static CRITICAL_SECTION drawable_section;
 static CRITICAL_SECTION_DEBUG critsect_debug =
 {
@@ -123,6 +129,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, HDC hdc, int format )
     gl->hdc    = hdc;
     gl->format = format;
     gl->window = create_ioctl_window( hwnd, TRUE );
+    gl->surface = 0;
     gl->pbuffer = p_eglCreatePbufferSurface( display, pixel_formats[gl->format - 1].config, attribs );
     EnterCriticalSection( &drawable_section );
     list_add_head( &gl_drawables, &gl->entry );
@@ -157,6 +164,7 @@ void destroy_gl_drawable( HWND hwnd )
     {
         if (gl->hwnd != hwnd) continue;
         list_remove( &gl->entry );
+        if (gl->surface) p_eglDestroySurface( display, gl->surface );
         if (gl->pbuffer) p_eglDestroySurface( display, gl->pbuffer );
         release_ioctl_window( gl->window );
         HeapFree( GetProcessHeap(), 0, gl );
@@ -165,6 +173,45 @@ void destroy_gl_drawable( HWND hwnd )
     LeaveCriticalSection( &drawable_section );
 }
 
+static BOOL refresh_context( struct wgl_context *ctx )
+{
+    BOOL ret = InterlockedExchange( &ctx->refresh, FALSE );
+
+    if (ret)
+    {
+        TRACE( "refreshing hwnd %p context %p surface %p\n", ctx->hwnd, ctx->context, ctx->surface );
+        p_eglMakeCurrent( display, ctx->surface, ctx->surface, ctx->context );
+        RedrawWindow( ctx->hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
+    }
+    return ret;
+}
+
+void update_gl_drawable( HWND hwnd )
+{
+    struct gl_drawable *gl;
+    struct wgl_context *ctx;
+
+    if ((gl = get_gl_drawable( hwnd, 0 )))
+    {
+        if (!gl->surface &&
+            (gl->surface = p_eglCreateWindowSurface( display, pixel_formats[gl->format - 1].config, gl->window, NULL )))
+        {
+            LIST_FOR_EACH_ENTRY( ctx, &gl_contexts, struct wgl_context, entry )
+            {
+                if (ctx->hwnd != hwnd) continue;
+                TRACE( "hwnd %p refreshing %p %scurrent\n", hwnd, ctx, NtCurrentTeb()->glContext == ctx ? "" : "not " );
+                ctx->surface = gl->surface;
+                if (NtCurrentTeb()->glContext == ctx)
+                    p_eglMakeCurrent( display, ctx->surface, ctx->surface, ctx->context );
+                else
+                    InterlockedExchange( &ctx->refresh, TRUE );
+            }
+        }
+        release_gl_drawable( gl );
+        RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE );
+    }
+}
+
 static BOOL set_pixel_format( HDC hdc, int format, BOOL allow_change )
 {
     struct gl_drawable *gl;
@@ -214,6 +261,8 @@ static struct wgl_context *create_context( HDC hdc, struct wgl_context *share, c
     ctx = HeapAlloc( GetProcessHeap(), 0, sizeof(*ctx) );
 
     ctx->config  = pixel_formats[gl->format - 1].config;
+    ctx->surface = 0;
+    ctx->refresh = FALSE;
     ctx->context = p_eglCreateContext( display, ctx->config,
                                        share ? share->context : EGL_NO_CONTEXT, attribs );
     TRACE( "%p fmt %d ctx %p\n", hdc, gl->format, ctx->context );
@@ -376,12 +425,14 @@ static BOOL android_wglMakeCurrent( HDC hdc, struct wgl_context *ctx )
     hwnd = WindowFromDC( hdc );
     if ((gl = get_gl_drawable( hwnd, hdc )))
     {
-        EGLSurface surface = gl->pbuffer;
+        EGLSurface surface = gl->surface ? gl->surface : gl->pbuffer;
         TRACE( "%p hwnd %p context %p surface %p\n", hdc, gl->hwnd, ctx->context, surface );
         ret = p_eglMakeCurrent( display, surface, surface, ctx->context );
         if (ret)
         {
+            ctx->surface = gl->surface;
             ctx->hwnd    = hwnd;
+            ctx->refresh = FALSE;
             NtCurrentTeb()->glContext = ctx;
             goto done;
         }
@@ -419,10 +470,33 @@ static BOOL android_wglSwapBuffers( HDC hdc )
 
     if (!ctx) return FALSE;
 
-    TRACE( "%p hwnd %p context %p\n", hdc, ctx->hwnd, ctx->context );
+    TRACE( "%p hwnd %p context %p surface %p\n", hdc, ctx->hwnd, ctx->context, ctx->surface );
+
+    if (refresh_context( ctx )) return TRUE;
+    if (ctx->surface) p_eglSwapBuffers( display, ctx->surface );
     return TRUE;
 }
 
+static void wglFinish(void)
+{
+    struct wgl_context *ctx = NtCurrentTeb()->glContext;
+
+    if (!ctx) return;
+    TRACE( "hwnd %p context %p\n", ctx->hwnd, ctx->context );
+    refresh_context( ctx );
+    pglFinish();
+}
+
+static void wglFlush(void)
+{
+    struct wgl_context *ctx = NtCurrentTeb()->glContext;
+
+    if (!ctx) return;
+    TRACE( "hwnd %p context %p\n", ctx->hwnd, ctx->context );
+    refresh_context( ctx );
+    pglFlush();
+}
+
 static void register_extension( const char *ext )
 {
     if (wgl_extensions[0]) strcat( wgl_extensions, " " );
@@ -729,6 +803,14 @@ static void init_extensions(void)
     LOAD_FUNCPTR( glVertexBindingDivisor );
     LOAD_FUNCPTR( glWaitSync );
 #undef LOAD_FUNCPTR
+
+    /* redirect some standard OpenGL functions */
+
+#define REDIRECT(func) \
+    do { p##func = egl_funcs.gl.p_##func; egl_funcs.gl.p_##func = w##func; } while(0)
+    REDIRECT(glFinish);
+    REDIRECT(glFlush);
+#undef REDIRECT
 }
 
 static BOOL egl_init(void)
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index 0e94115..f7a13df 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -1330,7 +1330,11 @@ LRESULT CDECL ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
     switch (msg)
     {
     case WM_ANDROID_REFRESH:
-        if ((data = get_win_data( hwnd )))
+        if (wp)  /* opengl client window */
+        {
+            update_gl_drawable( hwnd );
+        }
+        else if ((data = get_win_data( hwnd )))
         {
             struct window_surface *surface = data->surface;
             if (surface)




More information about the wine-cvs mailing list