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

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-06-22 22:50:32 +02:00
parent 1f736b5f7c
commit 01439ef590
4 changed files with 92 additions and 5 deletions

View file

@ -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;

View file

@ -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 );
}

View file

@ -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)

View file

@ -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)