From: Twaik Yont <9674930+twaik@users.noreply.github.com> Replace legacy gralloc usage with the supported AHardwareBuffer API and update minSdkVersion to 26 to match platform requirements and avoid crashes on unsupported devices. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/android.h | 2 +- dlls/wineandroid.drv/android_native.h | 193 +-------- dlls/wineandroid.drv/build.gradle.in | 2 +- dlls/wineandroid.drv/device.c | 563 +++++++++++--------------- dlls/wineandroid.drv/init.c | 52 +-- 5 files changed, 233 insertions(+), 579 deletions(-) diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 16d60911174..3107136cb7e 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -119,7 +119,7 @@ enum android_window_messages WM_ANDROID_REFRESH = WM_WINE_FIRST_DRIVER_MSG, }; -extern void init_gralloc( const struct hw_module_t *module ); +extern void init_ahardwarebuffers(void); extern HWND get_capture_window(void); extern void init_monitors( int width, int height ); extern void set_screen_dpi( DWORD dpi ); diff --git a/dlls/wineandroid.drv/android_native.h b/dlls/wineandroid.drv/android_native.h index fc26beb6534..7c3c49630ad 100644 --- a/dlls/wineandroid.drv/android_native.h +++ b/dlls/wineandroid.drv/android_native.h @@ -26,16 +26,6 @@ /* Native window definitions */ -typedef struct native_handle -{ - int version; - int numFds; - int numInts; - int data[0]; -} native_handle_t; - -typedef const native_handle_t *buffer_handle_t; - struct android_native_base_t { int magic; @@ -53,18 +43,7 @@ typedef struct android_native_rect_t int32_t bottom; } android_native_rect_t; -struct ANativeWindowBuffer -{ - struct android_native_base_t common; - int width; - int height; - int stride; - int format; - int usage; - void *reserved[2]; - buffer_handle_t handle; - void *reserved_proc[8]; -}; +struct ANativeWindowBuffer; struct ANativeWindow { @@ -125,9 +104,7 @@ enum native_window_perform enum native_window_api { NATIVE_WINDOW_API_EGL = 1, - NATIVE_WINDOW_API_CPU = 2, - NATIVE_WINDOW_API_MEDIA = 3, - NATIVE_WINDOW_API_CAMERA = 4 + NATIVE_WINDOW_API_CPU = 2 }; enum android_pixel_format @@ -141,176 +118,10 @@ enum android_pixel_format PF_RGBA_4444 = 7 }; - -/* Hardware module definitions */ - -struct hw_module_methods_t; -struct hw_device_t; -struct android_ycbcr; - -struct hw_module_t -{ - uint32_t tag; - uint16_t module_api_version; - uint16_t hal_api_version; - const char *id; - const char *name; - const char *author; - struct hw_module_methods_t *methods; - void *dso; - void *reserved[32-7]; -}; - -struct hw_module_methods_t -{ - int (*open)(const struct hw_module_t *module, const char *id, struct hw_device_t **device); -}; - -struct hw_device_t -{ - uint32_t tag; - uint32_t version; - struct hw_module_t *module; - void *reserved[12]; - int (*close)(struct hw_device_t *device); -}; - -struct gralloc_module_t -{ - struct hw_module_t common; - int (*registerBuffer)(struct gralloc_module_t const *module, buffer_handle_t handle); - int (*unregisterBuffer)(struct gralloc_module_t const *module, buffer_handle_t handle); - int (*lock)(struct gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void **vaddr); - int (*unlock)(struct gralloc_module_t const *module, buffer_handle_t handle); - int (*perform)(struct gralloc_module_t const *module, int operation, ... ); - int (*lock_ycbcr)(struct gralloc_module_t const *module, buffer_handle_t handle, int usage, int l, int t, int w, int h, struct android_ycbcr *ycbcr); - void *reserved_proc[6]; -}; - #define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \ (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d)) #define ANDROID_NATIVE_WINDOW_MAGIC \ ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d') -#define ANDROID_NATIVE_BUFFER_MAGIC \ - ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r') - -enum gralloc_usage -{ - GRALLOC_USAGE_SW_READ_NEVER = 0x00000000, - GRALLOC_USAGE_SW_READ_RARELY = 0x00000002, - GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003, - GRALLOC_USAGE_SW_READ_MASK = 0x0000000F, - GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000, - GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020, - GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030, - GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0, - GRALLOC_USAGE_HW_TEXTURE = 0x00000100, - GRALLOC_USAGE_HW_RENDER = 0x00000200, - GRALLOC_USAGE_HW_2D = 0x00000400, - GRALLOC_USAGE_HW_COMPOSER = 0x00000800, - GRALLOC_USAGE_HW_FB = 0x00001000, - GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000, - GRALLOC_USAGE_HW_CAMERA_WRITE = 0x00020000, - GRALLOC_USAGE_HW_CAMERA_READ = 0x00040000, - GRALLOC_USAGE_HW_CAMERA_ZSL = 0x00060000, - GRALLOC_USAGE_HW_CAMERA_MASK = 0x00060000, - GRALLOC_USAGE_HW_MASK = 0x00071F00, - GRALLOC_USAGE_EXTERNAL_DISP = 0x00002000, - GRALLOC_USAGE_PROTECTED = 0x00004000, - GRALLOC_USAGE_PRIVATE_0 = 0x10000000, - GRALLOC_USAGE_PRIVATE_1 = 0x20000000, - GRALLOC_USAGE_PRIVATE_2 = 0x40000000, - GRALLOC_USAGE_PRIVATE_3 = 0x80000000, - GRALLOC_USAGE_PRIVATE_MASK = 0xF0000000, -}; - -#define GRALLOC_HARDWARE_MODULE_ID "gralloc" - -extern int hw_get_module(const char *id, const struct hw_module_t **module); - -typedef enum -{ - GRALLOC1_CAPABILITY_INVALID = 0, - GRALLOC1_CAPABILITY_TEST_ALLOCATE = 1, - GRALLOC1_CAPABILITY_LAYERED_BUFFERS = 2, - GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE = 3, - GRALLOC1_LAST_CAPABILITY = 3, -} gralloc1_capability_t; - -typedef enum -{ - GRALLOC1_FUNCTION_INVALID = 0, - GRALLOC1_FUNCTION_DUMP = 1, - GRALLOC1_FUNCTION_CREATE_DESCRIPTOR = 2, - GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR = 3, - GRALLOC1_FUNCTION_SET_CONSUMER_USAGE = 4, - GRALLOC1_FUNCTION_SET_DIMENSIONS = 5, - GRALLOC1_FUNCTION_SET_FORMAT = 6, - GRALLOC1_FUNCTION_SET_PRODUCER_USAGE = 7, - GRALLOC1_FUNCTION_GET_BACKING_STORE = 8, - GRALLOC1_FUNCTION_GET_CONSUMER_USAGE = 9, - GRALLOC1_FUNCTION_GET_DIMENSIONS = 10, - GRALLOC1_FUNCTION_GET_FORMAT = 11, - GRALLOC1_FUNCTION_GET_PRODUCER_USAGE = 12, - GRALLOC1_FUNCTION_GET_STRIDE = 13, - GRALLOC1_FUNCTION_ALLOCATE = 14, - GRALLOC1_FUNCTION_RETAIN = 15, - GRALLOC1_FUNCTION_RELEASE = 16, - GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES = 17, - GRALLOC1_FUNCTION_LOCK = 18, - GRALLOC1_FUNCTION_LOCK_FLEX = 19, - GRALLOC1_FUNCTION_UNLOCK = 20, - GRALLOC1_FUNCTION_SET_LAYER_COUNT = 21, - GRALLOC1_FUNCTION_GET_LAYER_COUNT = 22, - GRALLOC1_FUNCTION_VALIDATE_BUFFER_SIZE = 23, - GRALLOC1_FUNCTION_GET_TRANSPORT_SIZE = 24, - GRALLOC1_FUNCTION_IMPORT_BUFFER = 25, - GRALLOC1_LAST_FUNCTION = 25, -} gralloc1_function_descriptor_t; - -typedef enum -{ - GRALLOC1_ERROR_NONE = 0, - GRALLOC1_ERROR_BAD_DESCRIPTOR = 1, - GRALLOC1_ERROR_BAD_HANDLE = 2, - GRALLOC1_ERROR_BAD_VALUE = 3, - GRALLOC1_ERROR_NOT_SHARED = 4, - GRALLOC1_ERROR_NO_RESOURCES = 5, - GRALLOC1_ERROR_UNDEFINED = 6, - GRALLOC1_ERROR_UNSUPPORTED = 7, -} gralloc1_error_t; - -typedef enum -{ - GRALLOC1_PRODUCER_USAGE_NONE = 0, - GRALLOC1_PRODUCER_USAGE_CPU_READ = 1u << 1, - GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN = 1u << 2 | GRALLOC1_PRODUCER_USAGE_CPU_READ, - GRALLOC1_PRODUCER_USAGE_CPU_WRITE = 1u << 5, - GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN = 1u << 6 | GRALLOC1_PRODUCER_USAGE_CPU_WRITE, -} gralloc1_producer_usage_t; - -typedef enum -{ - GRALLOC1_CONSUMER_USAGE_NONE = 0, - GRALLOC1_CONSUMER_USAGE_CPU_READ = 1u << 1, - GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN = 1u << 2 | GRALLOC1_CONSUMER_USAGE_CPU_READ, -} gralloc1_consumer_usage_t; - -typedef struct gralloc1_device -{ - struct hw_device_t common; - void (*getCapabilities)(struct gralloc1_device *device, uint32_t *outCount, int32_t *outCapabilities); - void* (*getFunction)(struct gralloc1_device *device, int32_t descriptor); -} gralloc1_device_t; - -typedef struct gralloc1_rect -{ - int32_t left; - int32_t top; - int32_t width; - int32_t height; -} gralloc1_rect_t; - #endif /* __WINE_ANDROID_NATIVE_H */ diff --git a/dlls/wineandroid.drv/build.gradle.in b/dlls/wineandroid.drv/build.gradle.in index 8d0e138c9a2..56ffd06ca82 100644 --- a/dlls/wineandroid.drv/build.gradle.in +++ b/dlls/wineandroid.drv/build.gradle.in @@ -112,7 +112,7 @@ android defaultConfig { applicationId "org.winehq.wine" - minSdkVersion 17 + minSdkVersion 26 versionCode 1 versionName "@PACKAGE_VERSION@" } diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 8ae0172a57f..3d77033a980 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -24,11 +24,14 @@ #include "config.h" +#define __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ + #include <assert.h> #include <errno.h> #include <stdio.h> #include <stdarg.h> #include <sys/ioctl.h> +#include <sys/socket.h> #include <unistd.h> #include "ntstatus.h" @@ -41,8 +44,23 @@ #include "wine/server.h" #include "wine/debug.h" +#include <dlfcn.h> + WINE_DEFAULT_DEBUG_CHANNEL(android); +#define DECL_FUNCPTR(f) static typeof(f) * p##f = NULL + +struct AHardwareBuffer* ANativeWindowBuffer_getHardwareBuffer(struct ANativeWindowBuffer* anwb) __INTRODUCED_IN(26); + +DECL_FUNCPTR( AHardwareBuffer_describe ); +DECL_FUNCPTR( AHardwareBuffer_acquire ); +DECL_FUNCPTR( AHardwareBuffer_release ); +DECL_FUNCPTR( AHardwareBuffer_lock ); +DECL_FUNCPTR( AHardwareBuffer_unlock ); +DECL_FUNCPTR( AHardwareBuffer_recvHandleFromUnixSocket ); +DECL_FUNCPTR( AHardwareBuffer_sendHandleToUnixSocket ); +DECL_FUNCPTR( ANativeWindowBuffer_getHardwareBuffer ); + #ifndef SYNC_IOC_WAIT #define SYNC_IOC_WAIT _IOW('>', 0, __s32) #endif @@ -74,21 +92,11 @@ enum android_ioctl #define NB_CACHED_BUFFERS 4 -struct native_buffer_wrapper; - -/* buffer for storing a variable-size native handle inside an ioctl structure */ -union native_handle_buffer -{ - native_handle_t handle; - int space[256]; -}; - /* data about the native window in the context of the Java process */ struct native_win_data { struct ANativeWindow *parent; - struct ANativeWindowBuffer *buffers[NB_CACHED_BUFFERS]; - void *mappings[NB_CACHED_BUFFERS]; + struct AHardwareBuffer *buffers[NB_CACHED_BUFFERS]; HWND hwnd; BOOL opengl; int generation; @@ -102,25 +110,18 @@ struct native_win_data struct native_win_wrapper { struct ANativeWindow win; - struct native_buffer_wrapper *buffers[NB_CACHED_BUFFERS]; - struct ANativeWindowBuffer *locked_buffer; + struct + { + struct AHardwareBuffer *self; + int buffer_id; + int generation; + } buffers[NB_CACHED_BUFFERS]; + struct AHardwareBuffer *locked_buffer; HWND hwnd; BOOL opengl; LONG ref; }; -/* wrapper for a native buffer in the context of the client (non-Java) process */ -struct native_buffer_wrapper -{ - struct ANativeWindowBuffer buffer; - LONG ref; - HWND hwnd; - void *bits; - int buffer_id; - int generation; - union native_handle_buffer native_handle; -}; - struct ioctl_header { int hwnd; @@ -155,15 +156,9 @@ struct ioctl_android_window_pos_changed struct ioctl_android_dequeueBuffer { struct ioctl_header hdr; - int win32; - int width; - int height; - int stride; - int format; - int usage; - int buffer_id; - int generation; - union native_handle_buffer native_handle; + HANDLE handle; + int buffer_id; + int generation; }; struct ioctl_android_queueBuffer @@ -223,18 +218,6 @@ struct ioctl_android_set_cursor int bits[1]; }; -static struct gralloc_module_t *gralloc_module; -static struct gralloc1_device *gralloc1_device; -static BOOL gralloc1_caps[GRALLOC1_LAST_CAPABILITY + 1]; - -static gralloc1_error_t (*gralloc1_retain)( gralloc1_device_t *device, buffer_handle_t buffer ); -static gralloc1_error_t (*gralloc1_release)( gralloc1_device_t *device, buffer_handle_t buffer ); -static gralloc1_error_t (*gralloc1_lock)( gralloc1_device_t *device, buffer_handle_t buffer, - uint64_t producerUsage, uint64_t consumerUsage, - const gralloc1_rect_t *accessRegion, void **outData, - int32_t acquireFence ); -static gralloc1_error_t (*gralloc1_unlock)( gralloc1_device_t *device, buffer_handle_t buffer, - int32_t *outReleaseFence ); static inline BOOL is_in_desktop_process(void) { @@ -247,11 +230,6 @@ static inline DWORD current_client_id(void) return client_id ? client_id : GetCurrentProcessId(); } -static inline BOOL is_client_in_process(void) -{ - return current_client_id() == GetCurrentProcessId(); -} - #ifdef __i386__ /* the Java VM uses %fs/%gs for its own purposes, so we need to wrap the calls */ static WORD orig_fs, java_fs; @@ -327,75 +305,46 @@ static void wait_fence_and_close( int fence ) close( fence ); } -static int duplicate_fd( HANDLE client, int fd ) +static inline struct ANativeWindowBuffer *anwb_from_ahb(AHardwareBuffer *ahb) { - HANDLE handle, ret = 0; + static ptrdiff_t off = (ptrdiff_t)-1; - if (!wine_server_fd_to_handle( dup(fd), GENERIC_READ | SYNCHRONIZE, 0, &handle )) - NtDuplicateObject( GetCurrentProcess(), handle, client, &ret, - 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ); - - if (!ret) return -1; - return HandleToLong( ret ); -} + if (!ahb) return NULL; -static int map_native_handle( union native_handle_buffer *dest, const native_handle_t *src, - HANDLE mapping, HANDLE client ) -{ - const size_t size = offsetof( native_handle_t, data[src->numFds + src->numInts] ); - int i; - - if (mapping) /* only duplicate the mapping handle */ - { - HANDLE ret = 0; - if (!NtDuplicateObject( GetCurrentProcess(), mapping, client, &ret, - 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE )) - return -ENOSPC; - dest->handle.numFds = 0; - dest->handle.numInts = 1; - dest->handle.data[0] = HandleToLong( ret ); - return 0; - } - if (is_client_in_process()) /* transfer the actual handle pointer */ + if (off == (ptrdiff_t)-1) { - dest->handle.numFds = 0; - dest->handle.numInts = sizeof(src) / sizeof(int); - memcpy( dest->handle.data, &src, sizeof(src) ); - return 0; + struct ANativeWindowBuffer *fake = + (struct ANativeWindowBuffer *)(uintptr_t)0x10000u; + + AHardwareBuffer *h = pANativeWindowBuffer_getHardwareBuffer(fake); + off = (const char *)h - (const char *)fake; } - if (size > sizeof(*dest)) return -ENOSPC; - memcpy( dest, src, size ); - /* transfer file descriptors to the client process */ - for (i = 0; i < dest->handle.numFds; i++) - dest->handle.data[i] = duplicate_fd( client, src->data[i] ); - return 0; + + return (struct ANativeWindowBuffer *)((char *)ahb - off); } -static native_handle_t *unmap_native_handle( const native_handle_t *src ) +static AHardwareBuffer *ahb_from_anwb( struct native_win_wrapper *win, struct ANativeWindowBuffer *buffer, int *buffer_id, int *generation ) { - const size_t size = offsetof( native_handle_t, data[src->numFds + src->numInts] ); - native_handle_t *dest; - int i; + AHardwareBuffer *ahb; + unsigned int i; - if (!is_in_desktop_process()) + if (!buffer) return NULL; + + ahb = pANativeWindowBuffer_getHardwareBuffer(buffer); + + if (win) { - dest = malloc( size ); - memcpy( dest, src, size ); - /* fetch file descriptors passed from the server process */ - for (i = 0; i < dest->numFds; i++) - wine_server_handle_to_fd( LongToHandle(src->data[i]), GENERIC_READ | SYNCHRONIZE, - &dest->data[i], NULL ); - } - else memcpy( &dest, src->data, sizeof(dest) ); - return dest; -} + for (i = 0; i < NB_CACHED_BUFFERS; ++i) + { + if (win->buffers[i].self != ahb) continue; -static void close_native_handle( native_handle_t *handle ) -{ - int i; + if (buffer_id) *buffer_id = win->buffers[i].buffer_id; + if (generation) *generation = win->buffers[i].generation; + break; + } + } - for (i = 0; i < handle->numFds; i++) close( handle->data[i] ); - free( handle ); + return ahb; } /* insert a buffer index at the head of the LRU list */ @@ -414,8 +363,7 @@ static void insert_buffer_lru( struct native_win_data *win, int index ) win->buffer_lru[0] = index; } -static int register_buffer( struct native_win_data *win, struct ANativeWindowBuffer *buffer, - HANDLE *mapping, int *is_new ) +static int register_buffer( struct native_win_data *win, struct AHardwareBuffer *buffer, int *is_new ) { unsigned int i; @@ -434,27 +382,12 @@ static int register_buffer( struct native_win_data *win, struct ANativeWindowBuf TRACE( "%p %p evicting buffer %p id %d from cache\n", win->hwnd, win->parent, win->buffers[i], i ); - win->buffers[i]->common.decRef( &win->buffers[i]->common ); - if (win->mappings[i]) NtUnmapViewOfSection( GetCurrentProcess(), win->mappings[i] ); + pAHardwareBuffer_release(win->buffers[i]); } win->buffers[i] = buffer; - win->mappings[i] = NULL; - if (mapping) - { - OBJECT_ATTRIBUTES attr; - LARGE_INTEGER size; - SIZE_T count = 0; - size.QuadPart = buffer->stride * buffer->height * 4; - InitializeObjectAttributes( &attr, NULL, OBJ_OPENIF, NULL, NULL ); - NtCreateSection( mapping, - STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE, - &attr, &size, PAGE_READWRITE, 0, INVALID_HANDLE_VALUE ); - NtMapViewOfSection( *mapping, GetCurrentProcess(), &win->mappings[i], 0, 0, - NULL, &count, ViewShare, 0, PAGE_READONLY ); - } - buffer->common.incRef( &buffer->common ); + pAHardwareBuffer_acquire(buffer); *is_new = 1; TRACE( "%p %p %p -> %d\n", win->hwnd, win->parent, buffer, i ); @@ -470,7 +403,7 @@ static struct ANativeWindowBuffer *get_registered_buffer( struct native_win_data ERR( "unknown buffer %d for %p %p\n", id, win->hwnd, win->parent ); return NULL; } - return win->buffers[id]; + return anwb_from_ahb(win->buffers[id]); } static void release_native_window( struct native_win_data *data ) @@ -480,12 +413,10 @@ static void release_native_window( struct native_win_data *data ) if (data->parent) pANativeWindow_release( data->parent ); for (i = 0; i < NB_CACHED_BUFFERS; i++) { - if (data->buffers[i]) data->buffers[i]->common.decRef( &data->buffers[i]->common ); - if (data->mappings[i]) NtUnmapViewOfSection( GetCurrentProcess(), data->mappings[i] ); + if (data->buffers[i]) pAHardwareBuffer_release(data->buffers[i]); data->buffer_lru[i] = -1; } memset( data->buffers, 0, sizeof(data->buffers) ); - memset( data->mappings, 0, sizeof(data->mappings) ); } static void free_native_win_data( struct native_win_data *data ) @@ -555,93 +486,36 @@ void register_native_window( HWND hwnd, struct ANativeWindow *win, BOOL opengl ) NtQueueApcThread( thread, register_window_callback, (ULONG_PTR)hwnd, (ULONG_PTR)win, opengl ); } -void init_gralloc( const struct hw_module_t *module ) +#define LOAD_FUNCPTR(lib, func) do { \ + const char *err; \ + dlerror(); \ + p##func = dlsym( lib, #func ); \ + if (!p##func) \ + { \ + err = dlerror(); \ + ERR( "can't find symbol %s: %s\n", #func, err ? err : "unknown error" ); \ + abort(); \ + } \ +} while (0) +void init_ahardwarebuffers(void) { - struct hw_device_t *device; - int ret; - - TRACE( "got module %p ver %u.%u id %s name %s author %s\n", - module, module->module_api_version >> 8, module->module_api_version & 0xff, - debugstr_a(module->id), debugstr_a(module->name), debugstr_a(module->author) ); + void *libandroid; - switch (module->module_api_version >> 8) + if (!(libandroid = dlopen( "libandroid.so", RTLD_NOW ))) { - case 0: - gralloc_module = (struct gralloc_module_t *)module; - break; - case 1: - if (!(ret = module->methods->open( module, GRALLOC_HARDWARE_MODULE_ID, &device ))) - { - int32_t caps[64]; - uint32_t i, count = ARRAY_SIZE(caps); - - gralloc1_device = (struct gralloc1_device *)device; - gralloc1_retain = gralloc1_device->getFunction( gralloc1_device, GRALLOC1_FUNCTION_RETAIN ); - gralloc1_release = gralloc1_device->getFunction( gralloc1_device, GRALLOC1_FUNCTION_RELEASE ); - gralloc1_lock = gralloc1_device->getFunction( gralloc1_device, GRALLOC1_FUNCTION_LOCK ); - gralloc1_unlock = gralloc1_device->getFunction( gralloc1_device, GRALLOC1_FUNCTION_UNLOCK ); - TRACE( "got device version %u funcs %p %p %p %p\n", device->version, - gralloc1_retain, gralloc1_release, gralloc1_lock, gralloc1_unlock ); - - gralloc1_device->getCapabilities( gralloc1_device, &count, caps ); - if (count == ARRAY_SIZE(caps)) ERR( "too many gralloc capabilities\n" ); - for (i = 0; i < count; i++) - if (caps[i] < ARRAY_SIZE(gralloc1_caps)) gralloc1_caps[caps[i]] = TRUE; - } - else ERR( "failed to open gralloc err %d\n", ret ); - break; - default: - ERR( "unknown gralloc module version %u\n", module->module_api_version >> 8 ); - break; + const char *err = dlerror(); + ERR( "failed to dlopen libandroid.so: %s\n", err ? err : "unknown error" ); + abort(); } -} -static int gralloc_grab_buffer( struct ANativeWindowBuffer *buffer ) -{ - if (gralloc1_device) - return gralloc1_retain( gralloc1_device, buffer->handle ); - if (gralloc_module) - return gralloc_module->registerBuffer( gralloc_module, buffer->handle ); - return -ENODEV; -} - -static void gralloc_release_buffer( struct ANativeWindowBuffer *buffer ) -{ - if (gralloc1_device) gralloc1_release( gralloc1_device, buffer->handle ); - else if (gralloc_module) gralloc_module->unregisterBuffer( gralloc_module, buffer->handle ); - - if (!gralloc1_caps[GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE]) - close_native_handle( (native_handle_t *)buffer->handle ); -} - -static int gralloc_lock( struct ANativeWindowBuffer *buffer, void **bits ) -{ - if (gralloc1_device) - { - gralloc1_rect_t rect = { 0, 0, buffer->width, buffer->height }; - return gralloc1_lock( gralloc1_device, buffer->handle, - GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN | - GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, - GRALLOC1_CONSUMER_USAGE_NONE, &rect, bits, -1 ); - } - if (gralloc_module) - return gralloc_module->lock( gralloc_module, buffer->handle, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - 0, 0, buffer->width, buffer->height, bits ); - - *bits = ((struct native_buffer_wrapper *)buffer)->bits; - return 0; -} - -static void gralloc_unlock( struct ANativeWindowBuffer *buffer ) -{ - if (gralloc1_device) - { - int fence; - gralloc1_unlock( gralloc1_device, buffer->handle, &fence ); - wait_fence_and_close( fence ); - } - else if (gralloc_module) gralloc_module->unlock( gralloc_module, buffer->handle ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_describe ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_acquire ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_release ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_lock ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_unlock ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_recvHandleFromUnixSocket ); + LOAD_FUNCPTR( libandroid, AHardwareBuffer_sendHandleToUnixSocket ); + LOAD_FUNCPTR( libandroid, ANativeWindowBuffer_getHardwareBuffer ); } /* get the capture window stored in the desktop process */ @@ -805,53 +679,97 @@ static NTSTATUS dequeueBuffer_ioctl( void *data, DWORD in_size, DWORD out_size, struct ioctl_android_dequeueBuffer *res = data; struct native_win_data *win_data; struct ANativeWindowBuffer *buffer = NULL; + AHardwareBuffer *ahb = NULL; int fence, ret, is_new; if (out_size < sizeof( *res )) return STATUS_BUFFER_OVERFLOW; - - if (in_size < offsetof( struct ioctl_android_dequeueBuffer, native_handle )) - return STATUS_INVALID_PARAMETER; + if (in_size < sizeof(res->hdr)) 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; - *ret_size = offsetof( struct ioctl_android_dequeueBuffer, native_handle ); + res->handle = 0; + res->buffer_id = -1; + res->generation = 0; + *ret_size = sizeof(*res); + wrap_java_call(); ret = parent->dequeueBuffer( parent, &buffer, &fence ); unwrap_java_call(); - if (!ret) + if (ret) + { + ERR( "%08x failed %d\n", res->hdr.hwnd, ret ); + return android_error_to_status( ret ); + } + + if (!buffer) + { + TRACE( "got invalid buffer\n" ); + return STATUS_UNSUCCESSFUL; + } + + TRACE( "%08x got buffer %p fence %d\n", res->hdr.hwnd, buffer, fence ); + ahb = pANativeWindowBuffer_getHardwareBuffer( buffer ); + + res->buffer_id = register_buffer( win_data, ahb, &is_new ); + res->generation = win_data->generation; + res->handle = 0; + + if (is_new) { - HANDLE mapping = 0; + int sv[2] = { -1, -1 }; + HANDLE local = 0; + OBJECT_ATTRIBUTES attr = { .Length = sizeof(attr) }; + CLIENT_ID cid = { .UniqueProcess = UlongToHandle( current_client_id() ) }; + HANDLE process; - if (!buffer) + if (!ahb) { - TRACE( "got invalid buffer\n" ); + wait_fence_and_close( fence ); return STATUS_UNSUCCESSFUL; } - TRACE( "%08x got buffer %p fence %d\n", res->hdr.hwnd, buffer, fence ); - res->width = buffer->width; - res->height = buffer->height; - res->stride = buffer->stride; - res->format = buffer->format; - res->usage = buffer->usage; - res->buffer_id = register_buffer( win_data, buffer, res->win32 ? &mapping : NULL, &is_new ); - res->generation = win_data->generation; - if (is_new) + if (socketpair( AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv ) < 0) { - OBJECT_ATTRIBUTES attr = { .Length = sizeof(attr) }; - CLIENT_ID cid = { .UniqueProcess = UlongToHandle( current_client_id() ) }; - HANDLE process; - NtOpenProcess( &process, PROCESS_DUP_HANDLE, &attr, &cid ); - map_native_handle( &res->native_handle, buffer->handle, mapping, process ); - NtClose( process ); - *ret_size = sizeof( *res ); + wait_fence_and_close( fence ); + return STATUS_UNSUCCESSFUL; + } + + if (NtOpenProcess( &process, PROCESS_DUP_HANDLE, &attr, &cid )) + { + close( sv[0] ); + close( sv[1] ); + wait_fence_and_close( fence ); + return STATUS_UNSUCCESSFUL; + } + + if (!wine_server_fd_to_handle( dup(sv[1]), GENERIC_READ | SYNCHRONIZE, 0, &local )) + { + NTSTATUS status = NtDuplicateObject( GetCurrentProcess(), local, process, &res->handle, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE ); + if (status && local) NtClose( local ); + } + + NtClose( process ); + close( sv[1] ); + + if (!res->handle) + { + close( sv[0] ); + wait_fence_and_close( fence ); + return STATUS_UNSUCCESSFUL; + } + + ret = pAHardwareBuffer_sendHandleToUnixSocket( ahb, sv[0] ); + close( sv[0] ); + if (ret) + { + wait_fence_and_close( fence ); + return android_error_to_status( ret ); } - wait_fence_and_close( fence ); - return STATUS_SUCCESS; } - ERR( "%08x failed %d\n", res->hdr.hwnd, ret ); - return android_error_to_status( ret ); + + wait_fence_and_close( fence ); + return STATUS_SUCCESS; } static NTSTATUS cancelBuffer_ioctl( void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) @@ -893,15 +811,7 @@ static NTSTATUS queueBuffer_ioctl( void *data, DWORD in_size, DWORD out_size, UL if (!(buffer = get_registered_buffer( win_data, res->buffer_id ))) return STATUS_INVALID_HANDLE; - TRACE( "%08x buffer %p mapping %p\n", res->hdr.hwnd, buffer, win_data->mappings[res->buffer_id] ); - if (win_data->mappings[res->buffer_id]) - { - void *bits; - ret = gralloc_lock( buffer, &bits ); - if (ret) return android_error_to_status( ret ); - memcpy( bits, win_data->mappings[res->buffer_id], buffer->stride * buffer->height * 4 ); - gralloc_unlock( buffer ); - } + TRACE( "%08x buffer %p\n", res->hdr.hwnd, buffer ); wrap_java_call(); ret = parent->queueBuffer( parent, buffer, -1 ); unwrap_java_call(); @@ -1239,98 +1149,72 @@ static void win_decRef( struct android_native_base_t *base ) InterlockedDecrement( &win->ref ); } -static void buffer_incRef( struct android_native_base_t *base ) -{ - struct native_buffer_wrapper *buffer = (struct native_buffer_wrapper *)base; - InterlockedIncrement( &buffer->ref ); -} - -static void buffer_decRef( struct android_native_base_t *base ) -{ - struct native_buffer_wrapper *buffer = (struct native_buffer_wrapper *)base; - - if (!InterlockedDecrement( &buffer->ref )) - { - if (!is_in_desktop_process()) gralloc_release_buffer( &buffer->buffer ); - if (buffer->bits) NtUnmapViewOfSection( GetCurrentProcess(), buffer->bits ); - free( buffer ); - } -} - static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer **buffer, int *fence ) { struct native_win_wrapper *win = (struct native_win_wrapper *)window; struct ioctl_android_dequeueBuffer res = {0}; DWORD size = sizeof(res); - int ret, use_win32 = !gralloc_module && !gralloc1_device; + int ret; res.hdr.hwnd = HandleToLong( win->hwnd ); res.hdr.opengl = win->opengl; - res.win32 = use_win32; - ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, - &res, offsetof( struct ioctl_android_dequeueBuffer, native_handle ), - &res, &size ); + res.handle = 0; + res.buffer_id = -1; + res.generation = 0; + + ret = android_ioctl( IOCTL_DEQUEUE_BUFFER, &res, sizeof(res.hdr), &res, &size ); if (ret) return ret; + if (size < sizeof(res)) return -EINVAL; + + if (res.buffer_id < 0 || res.buffer_id >= NB_CACHED_BUFFERS) return -EINVAL; - /* if we received the native handle, this is a new buffer */ - if (size > offsetof( struct ioctl_android_dequeueBuffer, native_handle )) + if (res.handle) { - struct native_buffer_wrapper *buf = calloc( 1, sizeof(*buf) ); - - buf->buffer.common.magic = ANDROID_NATIVE_BUFFER_MAGIC; - buf->buffer.common.version = sizeof( buf->buffer ); - buf->buffer.common.incRef = buffer_incRef; - buf->buffer.common.decRef = buffer_decRef; - buf->buffer.width = res.width; - buf->buffer.height = res.height; - buf->buffer.stride = res.stride; - buf->buffer.format = res.format; - buf->buffer.usage = res.usage; - buf->buffer.handle = unmap_native_handle( &res.native_handle.handle ); - buf->ref = 1; - buf->hwnd = win->hwnd; - buf->buffer_id = res.buffer_id; - buf->generation = res.generation; - if (win->buffers[res.buffer_id]) - win->buffers[res.buffer_id]->buffer.common.decRef(&win->buffers[res.buffer_id]->buffer.common); - win->buffers[res.buffer_id] = buf; - - if (use_win32) - { - LARGE_INTEGER zero = { .QuadPart = 0 }; - SIZE_T count = 0; - HANDLE mapping = LongToHandle( res.native_handle.handle.data[0] ); - NtMapViewOfSection( mapping, GetCurrentProcess(), &buf->bits, 0, 0, &zero, &count, - ViewShare, 0, PAGE_READWRITE ); - NtClose( mapping ); - } - else if (!is_in_desktop_process()) + AHardwareBuffer *ahb = NULL; + int fd; + + if (wine_server_handle_to_fd( res.handle, GENERIC_READ | SYNCHRONIZE, &fd, NULL )) { - if ((ret = gralloc_grab_buffer( &buf->buffer )) < 0) - WARN( "hwnd %p, buffer %p failed to register %d %s\n", - win->hwnd, &buf->buffer, ret, strerror(-ret) ); + NtClose( res.handle ); + return -EINVAL; } + NtClose( res.handle ); + + ret = pAHardwareBuffer_recvHandleFromUnixSocket( fd, &ahb ); + close( fd ); + if (ret) return ret; + + if (win->buffers[res.buffer_id].self) + pAHardwareBuffer_release( win->buffers[res.buffer_id].self ); + + win->buffers[res.buffer_id].self = ahb; + win->buffers[res.buffer_id].buffer_id = res.buffer_id; + win->buffers[res.buffer_id].generation = res.generation; } - *buffer = &win->buffers[res.buffer_id]->buffer; + if (!win->buffers[res.buffer_id].self) return -EINVAL; + + *buffer = anwb_from_ahb(win->buffers[res.buffer_id].self); *fence = -1; - TRACE( "hwnd %p, buffer %p %dx%d stride %d fmt %d usage %d fence %d\n", - win->hwnd, *buffer, res.width, res.height, res.stride, res.format, res.usage, *fence ); + TRACE( "hwnd %p, buffer %p id %d gen %d fence %d\n", + win->hwnd, *buffer, res.buffer_id, res.generation, *fence ); return 0; } static int cancelBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer *buffer, int fence ) { struct native_win_wrapper *win = (struct native_win_wrapper *)window; - struct native_buffer_wrapper *buf = (struct native_buffer_wrapper *)buffer; struct ioctl_android_cancelBuffer cancel; - TRACE( "hwnd %p buffer %p %dx%d stride %d fmt %d usage %d fence %d\n", - win->hwnd, buffer, buffer->width, buffer->height, - buffer->stride, buffer->format, buffer->usage, fence ); - cancel.buffer_id = buf->buffer_id; - cancel.generation = buf->generation; + TRACE( "hwnd %p buffer %p fence %d\n", win->hwnd, buffer, fence ); + + if (!ahb_from_anwb( win, buffer, &cancel.buffer_id, &cancel.generation )) + { + wait_fence_and_close( fence ); + return -EINVAL; + } + cancel.hdr.hwnd = HandleToLong( win->hwnd ); cancel.hdr.opengl = win->opengl; wait_fence_and_close( fence ); @@ -1340,14 +1224,16 @@ static int cancelBuffer( struct ANativeWindow *window, struct ANativeWindowBuffe static int queueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer *buffer, int fence ) { struct native_win_wrapper *win = (struct native_win_wrapper *)window; - struct native_buffer_wrapper *buf = (struct native_buffer_wrapper *)buffer; struct ioctl_android_queueBuffer queue; - TRACE( "hwnd %p buffer %p %dx%d stride %d fmt %d usage %d fence %d\n", - win->hwnd, buffer, buffer->width, buffer->height, - buffer->stride, buffer->format, buffer->usage, fence ); - queue.buffer_id = buf->buffer_id; - queue.generation = buf->generation; + TRACE( "hwnd %p buffer %p fence %d\n", win->hwnd, buffer, fence ); + + if (!ahb_from_anwb( win, buffer, &queue.buffer_id, &queue.generation )) + { + wait_fence_and_close( fence ); + return -EINVAL; + } + queue.hdr.hwnd = HandleToLong( win->hwnd ); queue.hdr.opengl = win->opengl; wait_fence_and_close( fence ); @@ -1476,6 +1362,7 @@ static int perform( ANativeWindow *window, int operation, ... ) { struct ANativeWindowBuffer *buffer = NULL; struct ANativeWindow_Buffer *buffer_ret = va_arg( args, ANativeWindow_Buffer * ); + struct AHardwareBuffer* b = NULL; ARect *bounds = va_arg( args, ARect * ); int ret = window->dequeueBuffer_DEPRECATED( window, &buffer ); if (!ret && !buffer) @@ -1485,25 +1372,31 @@ static int perform( ANativeWindow *window, int operation, ... ) } if (!ret) { - if ((ret = gralloc_lock( buffer, &buffer_ret->bits ))) + if (!(b = ahb_from_anwb((struct native_win_wrapper*) window, buffer, NULL, NULL))) { + ret = -EINVAL; + } + + if (b && (ret = pAHardwareBuffer_lock( b, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, NULL, &buffer_ret->bits ))) { - WARN( "gralloc->lock %p failed %d %s\n", win->hwnd, ret, strerror(-ret) ); + WARN( "AHardwareBuffer_lock %p failed %d %s\n", win->hwnd, ret, strerror(-ret) ); window->cancelBuffer( window, buffer, -1 ); } } if (!ret) { - buffer_ret->width = buffer->width; - buffer_ret->height = buffer->height; - buffer_ret->stride = buffer->stride; - buffer_ret->format = buffer->format; - win->locked_buffer = buffer; + AHardwareBuffer_Desc d = {0}; + pAHardwareBuffer_describe(b, &d); + buffer_ret->width = d.width; + buffer_ret->height = d.height; + buffer_ret->stride = d.stride; + buffer_ret->format = d.format; + win->locked_buffer = b; if (bounds) { bounds->left = 0; bounds->top = 0; - bounds->right = buffer->width; - bounds->bottom = buffer->height; + bounds->right = d.width; + bounds->bottom = d.height; } } va_end( args ); @@ -1515,8 +1408,8 @@ static int perform( ANativeWindow *window, int operation, ... ) int ret = -EINVAL; if (win->locked_buffer) { - gralloc_unlock( win->locked_buffer ); - ret = window->queueBuffer( window, win->locked_buffer, -1 ); + pAHardwareBuffer_unlock(win->locked_buffer, NULL); + ret = window->queueBuffer( window, anwb_from_ahb(win->locked_buffer), -1 ); win->locked_buffer = NULL; } va_end( args ); @@ -1589,7 +1482,7 @@ void release_ioctl_window( struct ANativeWindow *window ) TRACE( "%p %p\n", win, win->hwnd ); for (i = 0; i < ARRAY_SIZE( win->buffers ); i++) - if (win->buffers[i]) win->buffers[i]->buffer.common.decRef( &win->buffers[i]->buffer.common ); + if (win->buffers[i].self) pAHardwareBuffer_release(win->buffers[i].self); destroy_ioctl_window( win->hwnd, win->opengl ); free( win ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 01c9671b68f..0adda2ad0ad 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -341,7 +341,6 @@ static const JNINativeMethod methods[] = DECL_FUNCPTR( __android_log_print ); DECL_FUNCPTR( ANativeWindow_fromSurface ); DECL_FUNCPTR( ANativeWindow_release ); -DECL_FUNCPTR( hw_get_module ); #ifndef DT_GNU_HASH #define DT_GNU_HASH 0x6ffffef5 @@ -440,55 +439,6 @@ static void *find_symbol( const struct dl_phdr_info* info, const char *var, int return NULL; } -static int enum_libs( struct dl_phdr_info* info, size_t size, void* data ) -{ - const char *p; - - if (!info->dlpi_name) return 0; - if (!(p = strrchr( info->dlpi_name, '/' ))) return 0; - if (strcmp( p, "/libhardware.so" )) return 0; - TRACE( "found libhardware at %p\n", info->dlpi_phdr ); - phw_get_module = find_symbol( info, "hw_get_module", STT_FUNC ); - return 1; -} - -static void load_hardware_libs(void) -{ - const struct hw_module_t *module; - int ret; - void *libhardware; - - if ((libhardware = dlopen( "libhardware.so", RTLD_GLOBAL ))) - { - LOAD_FUNCPTR( libhardware, hw_get_module ); - } - else - { - /* Android >= N disallows loading libhardware, so we load libandroid (which imports - * libhardware), and then we can find libhardware in the list of loaded libraries. - */ - if (!dlopen( "libandroid.so", RTLD_GLOBAL )) - { - ERR( "failed to load libandroid.so: %s\n", dlerror() ); - return; - } - dl_iterate_phdr( enum_libs, 0 ); - if (!phw_get_module) - { - ERR( "failed to find hw_get_module\n" ); - return; - } - } - - if ((ret = phw_get_module( GRALLOC_HARDWARE_MODULE_ID, &module ))) - { - ERR( "failed to load gralloc module err %d\n", ret ); - return; - } - - init_gralloc( module ); -} - static void load_android_libs(void) { void *libandroid, *liblog; @@ -533,7 +483,7 @@ static HRESULT android_init( void *arg ) object = *p_java_object; - load_hardware_libs(); + init_ahardwarebuffers(); pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10519