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