wineandroid: Support creating a separate native window for OpenGL rendering in the client area.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-06-22 19:28:57 +02:00
parent 116f8d2efe
commit 95c4516b65
4 changed files with 51 additions and 33 deletions

View File

@ -512,7 +512,7 @@ public void create_desktop_window( int hwnd )
wine_config_changed( getResources().getConfiguration().densityDpi ); wine_config_changed( getResources().getConfiguration().densityDpi );
} }
public void create_window( int hwnd, int parent, int pid ) public void create_window( int hwnd, boolean opengl, int parent, int pid )
{ {
WineWindow win = get_window( hwnd ); WineWindow win = get_window( hwnd );
if (win == null) win = new WineWindow( hwnd, get_window( parent )); if (win == null) win = new WineWindow( hwnd, get_window( parent ));
@ -544,9 +544,9 @@ public void createDesktopWindow( final int hwnd )
runOnUiThread( new Runnable() { public void run() { create_desktop_window( hwnd ); }} ); runOnUiThread( new Runnable() { public void run() { create_desktop_window( hwnd ); }} );
} }
public void createWindow( final int hwnd, final int parent, final int pid ) public void createWindow( final int hwnd, final boolean opengl, final int parent, final int pid )
{ {
runOnUiThread( new Runnable() { public void run() { create_window( hwnd, parent, pid ); }} ); runOnUiThread( new Runnable() { public void run() { create_window( hwnd, opengl, parent, pid ); }} );
} }
public void destroyWindow( final int hwnd ) public void destroyWindow( final int hwnd )

View File

@ -53,11 +53,11 @@ DECL_FUNCPTR( ANativeWindow_release );
*/ */
extern void start_android_device(void) DECLSPEC_HIDDEN; extern void start_android_device(void) DECLSPEC_HIDDEN;
extern void register_native_window( HWND hwnd, struct ANativeWindow *win ) DECLSPEC_HIDDEN; extern void register_native_window( HWND hwnd, struct ANativeWindow *win, BOOL client ) DECLSPEC_HIDDEN;
extern struct ANativeWindow *create_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN; extern struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl ) DECLSPEC_HIDDEN;
extern struct ANativeWindow *grab_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN; extern struct ANativeWindow *grab_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN;
extern void release_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN; extern void release_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN;
extern void destroy_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN; extern void destroy_ioctl_window( HWND hwnd, BOOL opengl ) DECLSPEC_HIDDEN;
extern int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *client_rect, extern int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *client_rect,
const RECT *visible_rect, UINT style, UINT flags, const RECT *visible_rect, UINT style, UINT flags,
HWND after, HWND owner ) DECLSPEC_HIDDEN; HWND after, HWND owner ) DECLSPEC_HIDDEN;

View File

@ -91,6 +91,7 @@ struct native_win_data
struct ANativeWindowBuffer *buffers[NB_CACHED_BUFFERS]; struct ANativeWindowBuffer *buffers[NB_CACHED_BUFFERS];
void *mappings[NB_CACHED_BUFFERS]; void *mappings[NB_CACHED_BUFFERS];
HWND hwnd; HWND hwnd;
BOOL opengl;
int api; int api;
int buffer_format; int buffer_format;
int swap_interval; int swap_interval;
@ -104,6 +105,7 @@ struct native_win_wrapper
struct native_buffer_wrapper *buffers[NB_CACHED_BUFFERS]; struct native_buffer_wrapper *buffers[NB_CACHED_BUFFERS];
struct ANativeWindowBuffer *locked_buffer; struct ANativeWindowBuffer *locked_buffer;
HWND hwnd; HWND hwnd;
BOOL opengl;
LONG ref; LONG ref;
}; };
@ -121,6 +123,7 @@ struct native_buffer_wrapper
struct ioctl_header struct ioctl_header
{ {
int hwnd; int hwnd;
BOOL opengl;
}; };
struct ioctl_android_create_window struct ioctl_android_create_window
@ -228,23 +231,24 @@ static inline void unwrap_java_call(void) { }
static struct native_win_data *data_map[65536]; static struct native_win_data *data_map[65536];
static unsigned int data_map_idx( HWND hwnd ) static unsigned int data_map_idx( HWND hwnd, BOOL opengl )
{ {
return LOWORD(hwnd); /* window handles are always even, so use low-order bit for opengl flag */
return LOWORD(hwnd) + !!opengl;
} }
static struct native_win_data *get_native_win_data( HWND hwnd ) static struct native_win_data *get_native_win_data( HWND hwnd, BOOL opengl )
{ {
struct native_win_data *data = data_map[data_map_idx( hwnd )]; struct native_win_data *data = data_map[data_map_idx( hwnd, opengl )];
if (data && data->hwnd == hwnd) return data; if (data && data->hwnd == hwnd && !data->opengl == !opengl) return data;
WARN( "unknown win %p\n", hwnd ); WARN( "unknown win %p opengl %u\n", hwnd, opengl );
return NULL; return NULL;
} }
static struct native_win_data *get_ioctl_native_win_data( const struct ioctl_header *hdr ) static struct native_win_data *get_ioctl_native_win_data( const struct ioctl_header *hdr )
{ {
return get_native_win_data( LongToHandle(hdr->hwnd) ); return get_native_win_data( LongToHandle(hdr->hwnd), hdr->opengl );
} }
static void wait_fence_and_close( int fence ) static void wait_fence_and_close( int fence )
@ -412,7 +416,7 @@ static void release_native_window( struct native_win_data *data )
static void free_native_win_data( struct native_win_data *data ) static void free_native_win_data( struct native_win_data *data )
{ {
unsigned int idx = data_map_idx( data->hwnd ); unsigned int idx = data_map_idx( data->hwnd, data->opengl );
InterlockedCompareExchangePointer( (void **)&capture_window, 0, data->hwnd ); InterlockedCompareExchangePointer( (void **)&capture_window, 0, data->hwnd );
release_native_window( data ); release_native_window( data );
@ -420,9 +424,9 @@ static void free_native_win_data( struct native_win_data *data )
data_map[idx] = NULL; data_map[idx] = NULL;
} }
static struct native_win_data *create_native_win_data( HWND hwnd ) static struct native_win_data *create_native_win_data( HWND hwnd, BOOL opengl )
{ {
unsigned int i, idx = data_map_idx( hwnd ); unsigned int i, idx = data_map_idx( hwnd, opengl );
struct native_win_data *data = data_map[idx]; struct native_win_data *data = data_map[idx];
if (data) if (data)
@ -432,7 +436,8 @@ static struct native_win_data *create_native_win_data( HWND hwnd )
} }
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return NULL; if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return NULL;
data->hwnd = hwnd; data->hwnd = hwnd;
data->api = NATIVE_WINDOW_API_CPU; data->opengl = opengl;
if (!opengl) data->api = NATIVE_WINDOW_API_CPU;
data->buffer_format = PF_BGRA_8888; data->buffer_format = PF_BGRA_8888;
data_map[idx] = data; data_map[idx] = data;
for (i = 0; i < NB_CACHED_BUFFERS; i++) data->buffer_lru[i] = -1; for (i = 0; i < NB_CACHED_BUFFERS; i++) data->buffer_lru[i] = -1;
@ -443,7 +448,8 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
{ {
HWND hwnd = (HWND)arg1; HWND hwnd = (HWND)arg1;
struct ANativeWindow *win = (struct ANativeWindow *)arg2; struct ANativeWindow *win = (struct ANativeWindow *)arg2;
struct native_win_data *data = get_native_win_data( hwnd ); BOOL opengl = arg3;
struct native_win_data *data = get_native_win_data( hwnd, opengl );
if (!data || data->parent == win) if (!data || data->parent == win)
{ {
@ -468,9 +474,9 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
} }
/* register a native window received from the Java side for use in ioctls */ /* register a native window received from the Java side for use in ioctls */
void register_native_window( HWND hwnd, struct ANativeWindow *win ) void register_native_window( HWND hwnd, struct ANativeWindow *win, BOOL opengl )
{ {
NtQueueApcThread( thread, register_native_window_callback, (ULONG_PTR)hwnd, (ULONG_PTR)win, 0 ); NtQueueApcThread( thread, register_native_window_callback, (ULONG_PTR)hwnd, (ULONG_PTR)win, opengl );
} }
/* get the capture window stored in the desktop process */ /* get the capture window stored in the desktop process */
@ -569,15 +575,15 @@ static NTSTATUS createWindow_ioctl( void *data, DWORD in_size, DWORD out_size, U
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
if (!(win_data = create_native_win_data( LongToHandle(res->hdr.hwnd) ))) if (!(win_data = create_native_win_data( LongToHandle(res->hdr.hwnd), res->hdr.opengl )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
TRACE( "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent ); TRACE( "hwnd %08x opengl %u parent %08x\n", res->hdr.hwnd, res->hdr.opengl, res->parent );
if (!(object = load_java_method( &method, "createWindow", "(III)V" ))) return STATUS_NOT_SUPPORTED; if (!(object = load_java_method( &method, "createWindow", "(IZII)V" ))) return STATUS_NOT_SUPPORTED;
wrap_java_call(); wrap_java_call();
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->parent, pid ); (*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->hdr.opengl, res->parent, pid );
unwrap_java_call(); unwrap_java_call();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -593,7 +599,7 @@ static NTSTATUS destroyWindow_ioctl( void *data, DWORD in_size, DWORD out_size,
if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE;
TRACE( "hwnd %08x\n", res->hdr.hwnd ); TRACE( "hwnd %08x opengl %u\n", res->hdr.hwnd, res->hdr.opengl );
if (!(object = load_java_method( &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED; if (!(object = load_java_method( &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED;
@ -1076,6 +1082,7 @@ static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuff
int ret, use_win32 = !gralloc_module; int ret, use_win32 = !gralloc_module;
res.hdr.hwnd = HandleToLong( win->hwnd ); res.hdr.hwnd = HandleToLong( win->hwnd );
res.hdr.opengl = win->opengl;
res.win32 = use_win32; res.win32 = use_win32;
ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, ret = android_ioctl( IOCTL_DEQUEUE_BUFFER,
&res, offsetof( struct ioctl_android_dequeueBuffer, native_handle ), &res, offsetof( struct ioctl_android_dequeueBuffer, native_handle ),
@ -1136,6 +1143,7 @@ static int cancelBuffer( struct ANativeWindow *window, struct ANativeWindowBuffe
buffer->stride, buffer->format, buffer->usage, fence ); buffer->stride, buffer->format, buffer->usage, fence );
cancel.buffer_id = buf->buffer_id; cancel.buffer_id = buf->buffer_id;
cancel.hdr.hwnd = HandleToLong( win->hwnd ); cancel.hdr.hwnd = HandleToLong( win->hwnd );
cancel.hdr.opengl = win->opengl;
wait_fence_and_close( fence ); wait_fence_and_close( fence );
return android_ioctl( IOCTL_CANCEL_BUFFER, &cancel, sizeof(cancel), NULL, NULL ); return android_ioctl( IOCTL_CANCEL_BUFFER, &cancel, sizeof(cancel), NULL, NULL );
} }
@ -1151,6 +1159,7 @@ static int queueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer
buffer->stride, buffer->format, buffer->usage, fence ); buffer->stride, buffer->format, buffer->usage, fence );
queue.buffer_id = buf->buffer_id; queue.buffer_id = buf->buffer_id;
queue.hdr.hwnd = HandleToLong( win->hwnd ); queue.hdr.hwnd = HandleToLong( win->hwnd );
queue.hdr.opengl = win->opengl;
wait_fence_and_close( fence ); wait_fence_and_close( fence );
return android_ioctl( IOCTL_QUEUE_BUFFER, &queue, sizeof(queue), NULL, NULL ); return android_ioctl( IOCTL_QUEUE_BUFFER, &queue, sizeof(queue), NULL, NULL );
} }
@ -1185,6 +1194,7 @@ static int setSwapInterval( struct ANativeWindow *window, int interval )
TRACE( "hwnd %p interval %d\n", win->hwnd, interval ); TRACE( "hwnd %p interval %d\n", win->hwnd, interval );
swap.hdr.hwnd = HandleToLong( win->hwnd ); swap.hdr.hwnd = HandleToLong( win->hwnd );
swap.hdr.opengl = win->opengl;
swap.interval = interval; swap.interval = interval;
return android_ioctl( IOCTL_SET_SWAP_INT, &swap, sizeof(swap), NULL, NULL ); return android_ioctl( IOCTL_SET_SWAP_INT, &swap, sizeof(swap), NULL, NULL );
} }
@ -1197,6 +1207,7 @@ static int query( const ANativeWindow *window, int what, int *value )
int ret; int ret;
query.hdr.hwnd = HandleToLong( win->hwnd ); query.hdr.hwnd = HandleToLong( win->hwnd );
query.hdr.opengl = win->opengl;
query.what = what; query.what = what;
ret = android_ioctl( IOCTL_QUERY, &query, sizeof(query), &query, &size ); ret = android_ioctl( IOCTL_QUERY, &query, sizeof(query), &query, &size );
TRACE( "hwnd %p what %d got %d -> %p\n", win->hwnd, what, query.value, value ); TRACE( "hwnd %p what %d got %d -> %p\n", win->hwnd, what, query.value, value );
@ -1219,6 +1230,7 @@ static int perform( ANativeWindow *window, int operation, ... )
va_list args; va_list args;
perf.hdr.hwnd = HandleToLong( win->hwnd ); perf.hdr.hwnd = HandleToLong( win->hwnd );
perf.hdr.opengl = win->opengl;
perf.operation = operation; perf.operation = operation;
memset( perf.args, 0, sizeof(perf.args) ); memset( perf.args, 0, sizeof(perf.args) );
@ -1337,7 +1349,7 @@ static int perform( ANativeWindow *window, int operation, ... )
return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL ); return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL );
} }
struct ANativeWindow *create_ioctl_window( HWND hwnd ) struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl )
{ {
struct ioctl_android_create_window req; struct ioctl_android_create_window req;
struct native_win_wrapper *win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*win) ); struct native_win_wrapper *win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*win) );
@ -1361,9 +1373,11 @@ struct ANativeWindow *create_ioctl_window( HWND hwnd )
win->win.cancelBuffer = cancelBuffer; win->win.cancelBuffer = cancelBuffer;
win->ref = 1; win->ref = 1;
win->hwnd = hwnd; win->hwnd = hwnd;
TRACE( "-> %p %p\n", win, win->hwnd ); win->opengl = opengl;
TRACE( "-> %p %p opengl=%u\n", win, win->hwnd, opengl );
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( win->hwnd );
req.hdr.opengl = win->opengl;
req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent ); req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent );
android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL ); android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL );
@ -1388,15 +1402,16 @@ void release_ioctl_window( struct ANativeWindow *window )
for (i = 0; i < sizeof(win->buffers)/sizeof(win->buffers[0]); i++) for (i = 0; i < sizeof(win->buffers)/sizeof(win->buffers[0]); i++)
if (win->buffers[i]) win->buffers[i]->buffer.common.decRef( &win->buffers[i]->buffer.common ); if (win->buffers[i]) win->buffers[i]->buffer.common.decRef( &win->buffers[i]->buffer.common );
destroy_ioctl_window( win->hwnd ); destroy_ioctl_window( win->hwnd, win->opengl );
HeapFree( GetProcessHeap(), 0, win ); HeapFree( GetProcessHeap(), 0, win );
} }
void destroy_ioctl_window( HWND hwnd ) void destroy_ioctl_window( HWND hwnd, BOOL opengl )
{ {
struct ioctl_android_destroy_window req; struct ioctl_android_destroy_window req;
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = opengl;
android_ioctl( IOCTL_DESTROY_WINDOW, &req, sizeof(req), NULL, NULL ); android_ioctl( IOCTL_DESTROY_WINDOW, &req, sizeof(req), NULL, NULL );
} }
@ -1406,6 +1421,7 @@ int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *cl
struct ioctl_android_window_pos_changed req; struct ioctl_android_window_pos_changed req;
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = FALSE;
req.window_rect = *window_rect; req.window_rect = *window_rect;
req.client_rect = *client_rect; req.client_rect = *client_rect;
req.visible_rect = *visible_rect; req.visible_rect = *visible_rect;
@ -1421,6 +1437,7 @@ int ioctl_set_window_parent( HWND hwnd, HWND parent )
struct ioctl_android_set_window_parent req; struct ioctl_android_set_window_parent req;
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = FALSE;
req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent ); req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent );
return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL ); return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL );
} }
@ -1430,5 +1447,6 @@ int ioctl_set_capture( HWND hwnd )
struct ioctl_android_set_capture req; struct ioctl_android_set_capture req;
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = FALSE;
return android_ioctl( IOCTL_SET_CAPTURE, &req, sizeof(req), NULL, NULL ); return android_ioctl( IOCTL_SET_CAPTURE, &req, sizeof(req), NULL, NULL );
} }

View File

@ -113,7 +113,7 @@ static struct android_win_data *alloc_win_data( HWND hwnd )
if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data)))) if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
{ {
data->hwnd = hwnd; data->hwnd = hwnd;
data->window = create_ioctl_window( hwnd ); data->window = create_ioctl_window( hwnd, FALSE );
EnterCriticalSection( &win_data_section ); EnterCriticalSection( &win_data_section );
win_data_context[context_idx(hwnd)] = data; win_data_context[context_idx(hwnd)] = data;
} }
@ -454,7 +454,7 @@ static int process_events( DWORD mask )
TRACE("SURFACE_CHANGED %p %p size %ux%u\n", event->data.surface.hwnd, TRACE("SURFACE_CHANGED %p %p size %ux%u\n", event->data.surface.hwnd,
event->data.surface.window, event->data.surface.width, event->data.surface.height ); event->data.surface.window, event->data.surface.width, event->data.surface.height );
register_native_window( event->data.surface.hwnd, event->data.surface.window ); register_native_window( event->data.surface.hwnd, event->data.surface.window, FALSE );
break; break;
case MOTION_EVENT: case MOTION_EVENT:
@ -945,7 +945,7 @@ static LRESULT CALLBACK desktop_wndproc_wrapper( HWND hwnd, UINT msg, WPARAM wp,
switch (msg) switch (msg)
{ {
case WM_PARENTNOTIFY: case WM_PARENTNOTIFY:
if (LOWORD(wp) == WM_DESTROY) destroy_ioctl_window( (HWND)lp ); if (LOWORD(wp) == WM_DESTROY) destroy_ioctl_window( (HWND)lp, FALSE );
break; break;
} }
return desktop_orig_wndproc( hwnd, msg, wp, lp ); return desktop_orig_wndproc( hwnd, msg, wp, lp );