diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 48b595fc40c..7b4e348150b 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -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 )