From 01439ef590a0915bc29199786c23270146396842 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 22 Jun 2017 22:50:32 +0200 Subject: [PATCH] wineandroid: Create a proper EGL window surface once we receive a surface from Java. Signed-off-by: Alexandre Julliard --- 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 2cd167f8b08..29daefeb2d4 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 54c409bc3c6..472f4bacf1d 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 60f14b42342..910652bfe69 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 0e94115534b..f7a13dfe2ca 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)