wineandroid: Forward native window perform() calls to the desktop process.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-06-05 12:26:40 +02:00
parent f69836eba9
commit 4c1f541c13
1 changed files with 180 additions and 2 deletions

View File

@ -57,6 +57,7 @@ enum android_ioctl
IOCTL_DESTROY_WINDOW,
IOCTL_WINDOW_POS_CHANGED,
IOCTL_QUERY,
IOCTL_PERFORM,
NB_IOCTLS
};
@ -65,6 +66,8 @@ struct native_win_data
{
struct ANativeWindow *parent;
HWND hwnd;
int api;
int buffer_format;
};
/* wrapper for a native window in the context of the client (non-Java) process */
@ -110,6 +113,13 @@ struct ioctl_android_query
int value;
};
struct ioctl_android_perform
{
struct ioctl_header hdr;
int operation;
int args[4];
};
static inline DWORD current_client_id(void)
{
return HandleToUlong( PsGetCurrentProcessId() );
@ -171,6 +181,8 @@ static struct native_win_data *create_native_win_data( HWND hwnd )
}
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return NULL;
data->hwnd = hwnd;
data->api = NATIVE_WINDOW_API_CPU;
data->buffer_format = PF_BGRA_8888;
data_map[idx] = data;
return data;
}
@ -193,7 +205,8 @@ static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR
if (win)
{
wrap_java_call();
win->perform( win, NATIVE_WINDOW_API_CONNECT, NATIVE_WINDOW_API_CPU );
if (data->api) win->perform( win, NATIVE_WINDOW_API_CONNECT, data->api );
win->perform( win, NATIVE_WINDOW_SET_BUFFERS_FORMAT, data->buffer_format );
unwrap_java_call();
}
TRACE( "%p -> %p win %p\n", hwnd, data, win );
@ -374,6 +387,93 @@ static NTSTATUS query_ioctl( void *data, DWORD in_size, DWORD out_size, ULONG_PT
return android_error_to_status( ret );
}
static NTSTATUS perform_ioctl( void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size )
{
struct ioctl_android_perform *res = data;
struct ANativeWindow *parent;
struct native_win_data *win_data;
int ret = -ENOENT;
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE;
if (!(parent = win_data->parent)) return STATUS_DEVICE_NOT_READY;
switch (res->operation)
{
case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0] );
unwrap_java_call();
if (!ret) win_data->buffer_format = res->args[0];
break;
case NATIVE_WINDOW_API_CONNECT:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0] );
unwrap_java_call();
if (!ret) win_data->api = res->args[0];
break;
case NATIVE_WINDOW_API_DISCONNECT:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0] );
unwrap_java_call();
if (!ret) win_data->api = 0;
break;
case NATIVE_WINDOW_SET_USAGE:
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
case NATIVE_WINDOW_SET_SCALING_MODE:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0] );
unwrap_java_call();
break;
case NATIVE_WINDOW_SET_BUFFER_COUNT:
wrap_java_call();
ret = parent->perform( parent, res->operation, (size_t)res->args[0] );
unwrap_java_call();
break;
case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0], res->args[1] );
unwrap_java_call();
break;
case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0], res->args[1], res->args[2] );
unwrap_java_call();
break;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
wrap_java_call();
ret = parent->perform( parent, res->operation, res->args[0] | ((int64_t)res->args[1] << 32) );
unwrap_java_call();
break;
case NATIVE_WINDOW_CONNECT:
case NATIVE_WINDOW_DISCONNECT:
case NATIVE_WINDOW_UNLOCK_AND_POST:
wrap_java_call();
ret = parent->perform( parent, res->operation );
unwrap_java_call();
break;
case NATIVE_WINDOW_SET_CROP:
{
android_native_rect_t rect;
rect.left = res->args[0];
rect.top = res->args[1];
rect.right = res->args[2];
rect.bottom = res->args[3];
wrap_java_call();
ret = parent->perform( parent, res->operation, &rect );
unwrap_java_call();
break;
}
case NATIVE_WINDOW_LOCK:
default:
FIXME( "unsupported perform op %d\n", res->operation );
break;
}
return android_error_to_status( ret );
}
typedef NTSTATUS (*ioctl_func)( void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size );
static const ioctl_func ioctl_funcs[] =
{
@ -381,6 +481,7 @@ static const ioctl_func ioctl_funcs[] =
destroyWindow_ioctl, /* IOCTL_DESTROY_WINDOW */
windowPosChanged_ioctl, /* IOCTL_WINDOW_POS_CHANGED */
query_ioctl, /* IOCTL_QUERY */
perform_ioctl, /* IOCTL_PERFORM */
};
static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp )
@ -581,7 +682,84 @@ static int query( const ANativeWindow *window, int what, int *value )
static int perform( ANativeWindow *window, int operation, ... )
{
return 0;
static const char * const names[] =
{
"SET_USAGE", "CONNECT", "DISCONNECT", "SET_CROP", "SET_BUFFER_COUNT", "SET_BUFFERS_GEOMETRY",
"SET_BUFFERS_TRANSFORM", "SET_BUFFERS_TIMESTAMP", "SET_BUFFERS_DIMENSIONS", "SET_BUFFERS_FORMAT",
"SET_SCALING_MODE", "LOCK", "UNLOCK_AND_POST", "API_CONNECT", "API_DISCONNECT",
"SET_BUFFERS_USER_DIMENSIONS", "SET_POST_TRANSFORM_CROP"
};
struct native_win_wrapper *win = (struct native_win_wrapper *)window;
struct ioctl_android_perform perf;
va_list args;
perf.hdr.hwnd = HandleToLong( win->hwnd );
perf.operation = operation;
memset( perf.args, 0, sizeof(perf.args) );
va_start( args, operation );
switch (operation)
{
case NATIVE_WINDOW_SET_USAGE:
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
case NATIVE_WINDOW_SET_SCALING_MODE:
case NATIVE_WINDOW_API_CONNECT:
case NATIVE_WINDOW_API_DISCONNECT:
perf.args[0] = va_arg( args, int );
TRACE( "hwnd %p %s arg %d\n", win->hwnd, names[operation], perf.args[0] );
break;
case NATIVE_WINDOW_SET_BUFFER_COUNT:
perf.args[0] = va_arg( args, size_t );
TRACE( "hwnd %p %s count %d\n", win->hwnd, names[operation], perf.args[0] );
break;
case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
perf.args[0] = va_arg( args, int );
perf.args[1] = va_arg( args, int );
TRACE( "hwnd %p %s arg %dx%d\n", win->hwnd, names[operation], perf.args[0], perf.args[1] );
break;
case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
perf.args[0] = va_arg( args, int );
perf.args[1] = va_arg( args, int );
perf.args[2] = va_arg( args, int );
TRACE( "hwnd %p %s arg %dx%d %d\n", win->hwnd, names[operation],
perf.args[0], perf.args[1], perf.args[2] );
break;
case NATIVE_WINDOW_SET_CROP:
{
android_native_rect_t *rect = va_arg( args, android_native_rect_t * );
perf.args[0] = rect->left;
perf.args[1] = rect->top;
perf.args[2] = rect->right;
perf.args[3] = rect->bottom;
TRACE( "hwnd %p %s rect %d,%d-%d,%d\n", win->hwnd, names[operation],
perf.args[0], perf.args[1], perf.args[2], perf.args[3] );
break;
}
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
{
int64_t timestamp = va_arg( args, int64_t );
perf.args[0] = timestamp;
perf.args[1] = timestamp >> 32;
TRACE( "hwnd %p %s arg %08x%08x\n", win->hwnd, names[operation], perf.args[1], perf.args[0] );
break;
}
case NATIVE_WINDOW_LOCK:
case NATIVE_WINDOW_UNLOCK_AND_POST:
case NATIVE_WINDOW_CONNECT:
case NATIVE_WINDOW_DISCONNECT:
TRACE( "hwnd %p %s\n", win->hwnd, names[operation] );
break;
case NATIVE_WINDOW_SET_POST_TRANSFORM_CROP:
default:
FIXME( "unsupported perform hwnd %p op %d %s\n", win->hwnd, operation,
operation < sizeof(names)/sizeof(names[0]) ? names[operation] : "???" );
break;
}
va_end( args );
return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL );
}
struct ANativeWindow *create_ioctl_window( HWND hwnd )