include: Update the PEB and TEB structures.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobaa39ecf2228086b63c150bc28244ab0aaaf57abf
1 /*
2 * X11DRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #if 0
23 #pragma makedep unix
24 #endif
26 #include "config.h"
28 #include <fcntl.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/time.h>
34 #include <unistd.h>
35 #include <assert.h>
36 #include <dlfcn.h>
37 #include <X11/cursorfont.h>
38 #include <X11/Xlib.h>
39 #include <X11/XKBlib.h>
40 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
41 #include <X11/extensions/Xrender.h>
42 #endif
44 #include "ntstatus.h"
45 #define WIN32_NO_STATUS
47 #define VK_NO_PROTOTYPES
48 #define WINE_VK_HOST
50 #include "x11drv.h"
51 #include "winreg.h"
52 #include "xcomposite.h"
53 #include "wine/server.h"
54 #include "wine/debug.h"
55 #include "wine/list.h"
56 #include "wine/vulkan.h"
57 #include "wine/vulkan_driver.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
60 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
61 WINE_DECLARE_DEBUG_CHANNEL(winediag);
63 XVisualInfo default_visual = { 0 };
64 XVisualInfo argb_visual = { 0 };
65 Colormap default_colormap = None;
66 XPixmapFormatValues **pixmap_formats;
67 Atom systray_atom = 0;
68 unsigned int screen_bpp;
69 Window root_window;
70 BOOL usexvidmode = TRUE;
71 BOOL usexrandr = TRUE;
72 BOOL usexcomposite = TRUE;
73 BOOL use_take_focus = TRUE;
74 BOOL use_primary_selection = FALSE;
75 BOOL use_system_cursors = TRUE;
76 BOOL show_systray = TRUE;
77 BOOL grab_pointer = TRUE;
78 BOOL grab_fullscreen = FALSE;
79 BOOL managed_mode = TRUE;
80 BOOL decorated_mode = TRUE;
81 BOOL private_color_map = FALSE;
82 int primary_monitor = 0;
83 BOOL client_side_graphics = TRUE;
84 BOOL client_side_with_render = TRUE;
85 BOOL shape_layered_windows = TRUE;
86 int copy_default_colors = 128;
87 int alloc_system_colors = 256;
88 int xrender_error_base = 0;
89 char *process_name = NULL;
90 WNDPROC client_foreign_window_proc = NULL;
92 static x11drv_error_callback err_callback; /* current callback for error */
93 static Display *err_callback_display; /* display callback is set for */
94 static void *err_callback_arg; /* error callback argument */
95 static int err_callback_result; /* error callback result */
96 static unsigned long err_serial; /* serial number of first request */
97 static int (*old_error_handler)( Display *, XErrorEvent * );
98 static BOOL use_xim = TRUE;
99 static WCHAR input_style[20];
101 static pthread_mutex_t d3dkmt_mutex = PTHREAD_MUTEX_INITIALIZER;
102 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
104 struct x11_d3dkmt_adapter
106 D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
107 VkPhysicalDevice vk_device; /* Vulkan physical device */
108 struct list entry; /* List entry */
111 struct d3dkmt_vidpn_source
113 D3DKMT_VIDPNSOURCEOWNER_TYPE type; /* VidPN source owner type */
114 D3DDDI_VIDEO_PRESENT_SOURCE_ID id; /* VidPN present source id */
115 D3DKMT_HANDLE device; /* Kernel mode device context */
116 struct list entry; /* List entry */
119 static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */
120 static struct list x11_d3dkmt_adapters = LIST_INIT( x11_d3dkmt_adapters );
121 static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
123 #define IS_OPTION_TRUE(ch) \
124 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
125 #define IS_OPTION_FALSE(ch) \
126 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
128 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
130 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
132 "CLIPBOARD",
133 "COMPOUND_TEXT",
134 "EDID",
135 "INCR",
136 "MANAGER",
137 "MULTIPLE",
138 "SELECTION_DATA",
139 "TARGETS",
140 "TEXT",
141 "TIMESTAMP",
142 "UTF8_STRING",
143 "RAW_ASCENT",
144 "RAW_DESCENT",
145 "RAW_CAP_HEIGHT",
146 "Rel X",
147 "Rel Y",
148 "WM_PROTOCOLS",
149 "WM_DELETE_WINDOW",
150 "WM_STATE",
151 "WM_TAKE_FOCUS",
152 "DndProtocol",
153 "DndSelection",
154 "_ICC_PROFILE",
155 "_KDE_NET_WM_STATE_SKIP_SWITCHER",
156 "_MOTIF_WM_HINTS",
157 "_NET_STARTUP_INFO_BEGIN",
158 "_NET_STARTUP_INFO",
159 "_NET_SUPPORTED",
160 "_NET_SYSTEM_TRAY_OPCODE",
161 "_NET_SYSTEM_TRAY_S0",
162 "_NET_SYSTEM_TRAY_VISUAL",
163 "_NET_WM_FULLSCREEN_MONITORS",
164 "_NET_WM_ICON",
165 "_NET_WM_MOVERESIZE",
166 "_NET_WM_NAME",
167 "_NET_WM_PID",
168 "_NET_WM_PING",
169 "_NET_WM_STATE",
170 "_NET_WM_STATE_ABOVE",
171 "_NET_WM_STATE_DEMANDS_ATTENTION",
172 "_NET_WM_STATE_FULLSCREEN",
173 "_NET_WM_STATE_MAXIMIZED_HORZ",
174 "_NET_WM_STATE_MAXIMIZED_VERT",
175 "_NET_WM_STATE_SKIP_PAGER",
176 "_NET_WM_STATE_SKIP_TASKBAR",
177 "_NET_WM_USER_TIME",
178 "_NET_WM_USER_TIME_WINDOW",
179 "_NET_WM_WINDOW_OPACITY",
180 "_NET_WM_WINDOW_TYPE",
181 "_NET_WM_WINDOW_TYPE_DIALOG",
182 "_NET_WM_WINDOW_TYPE_NORMAL",
183 "_NET_WM_WINDOW_TYPE_UTILITY",
184 "_NET_WORKAREA",
185 "_GTK_WORKAREAS_D0",
186 "_XEMBED",
187 "_XEMBED_INFO",
188 "XdndAware",
189 "XdndEnter",
190 "XdndPosition",
191 "XdndStatus",
192 "XdndLeave",
193 "XdndFinished",
194 "XdndDrop",
195 "XdndActionCopy",
196 "XdndActionMove",
197 "XdndActionLink",
198 "XdndActionAsk",
199 "XdndActionPrivate",
200 "XdndSelection",
201 "XdndTypeList",
202 "HTML Format",
203 "WCF_DIF",
204 "WCF_ENHMETAFILE",
205 "WCF_HDROP",
206 "WCF_PENDATA",
207 "WCF_RIFF",
208 "WCF_SYLK",
209 "WCF_TIFF",
210 "WCF_WAVE",
211 "image/bmp",
212 "image/gif",
213 "image/jpeg",
214 "image/png",
215 "text/html",
216 "text/plain",
217 "text/rtf",
218 "text/richtext",
219 "text/uri-list"
222 /***********************************************************************
223 * ignore_error
225 * Check if the X error is one we can ignore.
227 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
229 if ((event->request_code == X_SetInputFocus ||
230 event->request_code == X_ChangeWindowAttributes ||
231 event->request_code == X_SendEvent) &&
232 (event->error_code == BadMatch ||
233 event->error_code == BadWindow)) return TRUE;
235 /* the clipboard display interacts with external windows, ignore all errors */
236 if (display == clipboard_display) return TRUE;
238 /* ignore a number of errors on gdi display caused by creating/destroying windows */
239 if (display == gdi_display)
241 if (event->error_code == BadDrawable ||
242 event->error_code == BadGC ||
243 event->error_code == BadWindow)
244 return TRUE;
245 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
246 if (xrender_error_base) /* check for XRender errors */
248 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
250 #endif
252 return FALSE;
256 /***********************************************************************
257 * X11DRV_expect_error
259 * Setup a callback function that will be called on an X error. The
260 * callback must return non-zero if the error is the one it expected.
262 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
264 pthread_mutex_lock( &error_mutex );
265 XLockDisplay( display );
266 err_callback = callback;
267 err_callback_display = display;
268 err_callback_arg = arg;
269 err_callback_result = 0;
270 err_serial = NextRequest(display);
274 /***********************************************************************
275 * X11DRV_check_error
277 * Check if an expected X11 error occurred; return non-zero if yes.
278 * The caller is responsible for calling XSync first if necessary.
280 int X11DRV_check_error(void)
282 int res = err_callback_result;
283 err_callback = NULL;
284 XUnlockDisplay( err_callback_display );
285 pthread_mutex_unlock( &error_mutex );
286 return res;
290 /***********************************************************************
291 * error_handler
293 static int error_handler( Display *display, XErrorEvent *error_evt )
295 if (err_callback && display == err_callback_display &&
296 (!error_evt->serial || error_evt->serial >= err_serial))
298 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
300 TRACE( "got expected error %d req %d\n",
301 error_evt->error_code, error_evt->request_code );
302 return 0;
305 if (ignore_error( display, error_evt ))
307 TRACE( "got ignored error %d req %d\n",
308 error_evt->error_code, error_evt->request_code );
309 return 0;
311 if (TRACE_ON(synchronous))
313 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
314 error_evt->serial, error_evt->request_code );
315 assert( 0 );
317 old_error_handler( display, error_evt );
318 return 0;
321 /***********************************************************************
322 * init_pixmap_formats
324 static void init_pixmap_formats( Display *display )
326 int i, count, max = 32;
327 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
329 for (i = 0; i < count; i++)
331 TRACE( "depth %u, bpp %u, pad %u\n",
332 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
333 if (formats[i].depth > max) max = formats[i].depth;
335 pixmap_formats = calloc( 1, sizeof(*pixmap_formats) * (max + 1) );
336 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
340 HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
342 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
343 OBJECT_ATTRIBUTES attr;
344 HANDLE ret;
346 attr.Length = sizeof(attr);
347 attr.RootDirectory = root;
348 attr.ObjectName = &nameW;
349 attr.Attributes = 0;
350 attr.SecurityDescriptor = NULL;
351 attr.SecurityQualityOfService = NULL;
353 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
357 HKEY open_hkcu_key( const char *name )
359 WCHAR bufferW[256];
360 static HKEY hkcu;
362 if (!hkcu)
364 char buffer[256];
365 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
366 DWORD i, len = sizeof(sid_data);
367 SID *sid;
369 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
370 return 0;
372 sid = ((TOKEN_USER *)sid_data)->User.Sid;
373 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
374 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
375 sid->IdentifierAuthority.Value[4] ),
376 MAKEWORD( sid->IdentifierAuthority.Value[3],
377 sid->IdentifierAuthority.Value[2] )));
378 for (i = 0; i < sid->SubAuthorityCount; i++)
379 len += sprintf( buffer + len, "-%u", (int)sid->SubAuthority[i] );
381 ascii_to_unicode( bufferW, buffer, len );
382 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
385 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
389 ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
391 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
392 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
394 if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
395 info, size, &size ))
396 return 0;
398 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
402 /***********************************************************************
403 * get_config_key
405 * Get a config key from either the app-specific or the default config
407 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
408 WCHAR *buffer, DWORD size )
410 WCHAR nameW[128];
411 char buf[2048];
412 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
414 asciiz_to_unicode( nameW, name );
416 if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) ))
418 size = min( info->DataLength, size - sizeof(WCHAR) );
419 memcpy( buffer, info->Data, size );
420 buffer[size / sizeof(WCHAR)] = 0;
421 return 0;
424 if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) ))
426 size = min( info->DataLength, size - sizeof(WCHAR) );
427 memcpy( buffer, info->Data, size );
428 buffer[size / sizeof(WCHAR)] = 0;
429 return 0;
432 return ERROR_FILE_NOT_FOUND;
436 /***********************************************************************
437 * setup_options
439 * Setup the x11drv options.
441 static void setup_options(void)
443 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
444 WCHAR buffer[MAX_PATH+16], *p, *appname;
445 HKEY hkey, appkey = 0;
446 DWORD len;
448 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
449 hkey = open_hkcu_key( "Software\\Wine\\X11 Driver" );
451 /* open the app-specific key */
453 appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
454 if ((p = wcsrchr( appname, '/' ))) appname = p + 1;
455 if ((p = wcsrchr( appname, '\\' ))) appname = p + 1;
456 len = lstrlenW( appname );
458 if (len && len < MAX_PATH)
460 HKEY tmpkey;
461 int i;
462 for (i = 0; appname[i]; i++) buffer[i] = RtlDowncaseUnicodeChar( appname[i] );
463 buffer[i] = 0;
464 appname = buffer;
465 if ((process_name = malloc( len * 3 + 1 )))
466 ntdll_wcstoumbs( appname, len + 1, process_name, len * 3 + 1, FALSE );
467 memcpy( appname + i, x11driverW, sizeof(x11driverW) );
468 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
469 if ((tmpkey = open_hkcu_key( "Software\\Wine\\AppDefaults" )))
471 appkey = reg_open_key( tmpkey, appname, lstrlenW( appname ) * sizeof(WCHAR) );
472 NtClose( tmpkey );
476 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
477 managed_mode = IS_OPTION_TRUE( buffer[0] );
479 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
480 decorated_mode = IS_OPTION_TRUE( buffer[0] );
482 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
483 usexvidmode = IS_OPTION_TRUE( buffer[0] );
485 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
486 usexrandr = IS_OPTION_TRUE( buffer[0] );
488 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
489 use_take_focus = IS_OPTION_TRUE( buffer[0] );
491 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
492 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
494 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
495 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
497 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
498 show_systray = IS_OPTION_TRUE( buffer[0] );
500 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
501 grab_pointer = IS_OPTION_TRUE( buffer[0] );
503 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
504 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
506 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
507 default_visual.depth = wcstol( buffer, NULL, 0 );
509 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
510 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
512 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
513 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
515 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
516 use_xim = IS_OPTION_TRUE( buffer[0] );
518 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
519 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
521 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
522 private_color_map = IS_OPTION_TRUE( buffer[0] );
524 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
525 primary_monitor = wcstol( buffer, NULL, 0 );
527 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
528 copy_default_colors = wcstol( buffer, NULL, 0 );
530 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
531 alloc_system_colors = wcstol( buffer, NULL, 0 );
533 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
535 NtClose( appkey );
536 NtClose( hkey );
539 #ifdef SONAME_LIBXCOMPOSITE
541 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
542 MAKE_FUNCPTR(XCompositeQueryExtension)
543 MAKE_FUNCPTR(XCompositeQueryVersion)
544 MAKE_FUNCPTR(XCompositeVersion)
545 MAKE_FUNCPTR(XCompositeRedirectWindow)
546 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
547 MAKE_FUNCPTR(XCompositeUnredirectWindow)
548 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
549 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
550 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
551 #undef MAKE_FUNCPTR
553 static int xcomp_event_base;
554 static int xcomp_error_base;
556 static void X11DRV_XComposite_Init(void)
558 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
559 if (!xcomposite_handle)
561 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
562 usexcomposite = FALSE;
563 return;
566 #define LOAD_FUNCPTR(f) \
567 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
568 LOAD_FUNCPTR(XCompositeQueryExtension);
569 LOAD_FUNCPTR(XCompositeQueryVersion);
570 LOAD_FUNCPTR(XCompositeVersion);
571 LOAD_FUNCPTR(XCompositeRedirectWindow);
572 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
573 LOAD_FUNCPTR(XCompositeUnredirectWindow);
574 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
575 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
576 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
577 #undef LOAD_FUNCPTR
579 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
580 &xcomp_error_base)) {
581 TRACE("XComposite extension could not be queried; disabled\n");
582 dlclose(xcomposite_handle);
583 xcomposite_handle = NULL;
584 usexcomposite = FALSE;
585 return;
587 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
588 return;
590 sym_not_found:
591 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
592 dlclose(xcomposite_handle);
593 xcomposite_handle = NULL;
594 usexcomposite = FALSE;
596 #endif /* defined(SONAME_LIBXCOMPOSITE) */
598 static void init_visuals( Display *display, int screen )
600 int count;
601 XVisualInfo *info;
603 argb_visual.screen = screen;
604 argb_visual.class = TrueColor;
605 argb_visual.depth = 32;
606 argb_visual.red_mask = 0xff0000;
607 argb_visual.green_mask = 0x00ff00;
608 argb_visual.blue_mask = 0x0000ff;
610 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
611 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
612 &argb_visual, &count )))
614 argb_visual = *info;
615 XFree( info );
618 default_visual.screen = screen;
619 if (default_visual.depth) /* depth specified */
621 if (default_visual.depth == 32 && argb_visual.visual)
623 default_visual = argb_visual;
625 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
627 default_visual = *info;
628 XFree( info );
630 else WARN( "no visual found for depth %d\n", default_visual.depth );
633 if (!default_visual.visual)
635 default_visual.depth = DefaultDepth( display, screen );
636 default_visual.visual = DefaultVisual( display, screen );
637 default_visual.visualid = default_visual.visual->visualid;
638 default_visual.class = default_visual.visual->class;
639 default_visual.red_mask = default_visual.visual->red_mask;
640 default_visual.green_mask = default_visual.visual->green_mask;
641 default_visual.blue_mask = default_visual.visual->blue_mask;
642 default_visual.colormap_size = default_visual.visual->map_entries;
643 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
645 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
647 TRACE( "default visual %lx class %u argb %lx\n",
648 default_visual.visualid, default_visual.class, argb_visual.visualid );
651 /***********************************************************************
652 * X11DRV process initialisation routine
654 static NTSTATUS x11drv_init( void *arg )
656 struct init_params *params = arg;
657 Display *display;
658 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
660 if (!libx11)
662 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
663 return STATUS_UNSUCCESSFUL;
665 pXGetEventData = dlsym( libx11, "XGetEventData" );
666 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
667 #ifdef SONAME_LIBXEXT
668 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
669 #endif
671 setup_options();
673 /* Open display */
675 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
676 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
678 client_foreign_window_proc = params->foreign_window_proc;
680 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
681 root_window = DefaultRootWindow( display );
682 gdi_display = display;
683 old_error_handler = XSetErrorHandler( error_handler );
685 init_pixmap_formats( display );
686 init_visuals( display, DefaultScreen( display ));
687 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
689 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
691 init_win_context();
693 if (TRACE_ON(synchronous)) XSynchronize( display, True );
695 xinerama_init( DisplayWidth( display, default_visual.screen ),
696 DisplayHeight( display, default_visual.screen ));
697 X11DRV_Settings_Init();
699 /* initialize XVidMode */
700 X11DRV_XF86VM_Init();
701 /* initialize XRandR */
702 X11DRV_XRandR_Init();
703 #ifdef SONAME_LIBXCOMPOSITE
704 X11DRV_XComposite_Init();
705 #endif
706 X11DRV_XInput2_Init();
708 XkbUseExtension( gdi_display, NULL, NULL );
709 X11DRV_InitKeyboard( gdi_display );
710 if (use_xim) use_xim = xim_init( input_style );
712 init_user_driver();
713 X11DRV_DisplayDevices_Init(FALSE);
714 *params->show_systray = show_systray;
715 return STATUS_SUCCESS;
719 /***********************************************************************
720 * ThreadDetach (X11DRV.@)
722 void X11DRV_ThreadDetach(void)
724 struct x11drv_thread_data *data = x11drv_thread_data();
726 if (data)
728 vulkan_thread_detach();
729 if (data->xim) XCloseIM( data->xim );
730 if (data->font_set) XFreeFontSet( data->display, data->font_set );
731 XCloseDisplay( data->display );
732 free( data );
733 /* clear data in case we get re-entered from user32 before the thread is truly dead */
734 NtUserGetThreadInfo()->driver_data = 0;
739 /* store the display fd into the message queue */
740 static void set_queue_display_fd( Display *display )
742 HANDLE handle;
743 int ret;
745 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
747 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
748 NtTerminateProcess( 0, 1 );
750 SERVER_START_REQ( set_queue_fd )
752 req->handle = wine_server_obj_handle( handle );
753 ret = wine_server_call( req );
755 SERVER_END_REQ;
756 if (ret)
758 MESSAGE( "x11drv: Can't store handle for display fd\n" );
759 NtTerminateProcess( 0, 1 );
761 NtClose( handle );
765 /***********************************************************************
766 * X11DRV thread initialisation routine
768 struct x11drv_thread_data *x11drv_init_thread_data(void)
770 struct x11drv_thread_data *data = x11drv_thread_data();
772 if (data) return data;
774 if (!(data = calloc( 1, sizeof(*data) )))
776 ERR( "could not create data\n" );
777 NtTerminateProcess( 0, 1 );
779 if (!(data->display = XOpenDisplay(NULL)))
781 ERR_(winediag)( "x11drv: Can't open display: %s. Please ensure that your X server is running and that $DISPLAY is set correctly.\n", XDisplayName(NULL));
782 NtTerminateProcess( 0, 1 );
785 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
787 XkbUseExtension( data->display, NULL, NULL );
788 XkbSetDetectableAutoRepeat( data->display, True, NULL );
789 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
791 set_queue_display_fd( data->display );
792 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
794 if (use_xim) xim_thread_attach( data );
796 return data;
800 /***********************************************************************
801 * SystemParametersInfo (X11DRV.@)
803 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
805 switch (action)
807 case SPI_GETSCREENSAVEACTIVE:
808 if (ptr_param)
810 int timeout, temp;
811 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
812 *(BOOL *)ptr_param = timeout != 0;
813 return TRUE;
815 break;
816 case SPI_SETSCREENSAVEACTIVE:
818 int timeout, interval, prefer_blanking, allow_exposures;
819 static int last_timeout = 15 * 60;
821 XLockDisplay( gdi_display );
822 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
823 &allow_exposures);
824 if (timeout) last_timeout = timeout;
826 timeout = int_param ? last_timeout : 0;
827 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
828 allow_exposures);
829 XUnlockDisplay( gdi_display );
831 break;
833 return FALSE; /* let user32 handle it */
836 NTSTATUS CDECL X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
838 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
839 struct x11_d3dkmt_adapter *adapter;
841 if (!vulkan_funcs)
842 return STATUS_UNSUCCESSFUL;
844 pthread_mutex_lock(&d3dkmt_mutex);
845 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
847 if (adapter->handle == desc->hAdapter)
849 list_remove(&adapter->entry);
850 free(adapter);
851 break;
855 if (list_empty(&x11_d3dkmt_adapters))
857 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
858 d3dkmt_vk_instance = NULL;
860 pthread_mutex_unlock(&d3dkmt_mutex);
861 return STATUS_SUCCESS;
864 /**********************************************************************
865 * X11DRV_D3DKMTSetVidPnSourceOwner
867 NTSTATUS CDECL X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
869 struct d3dkmt_vidpn_source *source, *source2;
870 NTSTATUS status = STATUS_SUCCESS;
871 BOOL found;
872 UINT i;
874 TRACE("(%p)\n", desc);
876 pthread_mutex_lock( &d3dkmt_mutex );
878 /* Check parameters */
879 for (i = 0; i < desc->VidPnSourceCount; ++i)
881 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
883 if (source->id == desc->pVidPnSourceId[i])
885 /* Same device */
886 if (source->device == desc->hDevice)
888 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
889 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED
890 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
891 || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED
892 && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE))
894 status = STATUS_INVALID_PARAMETER;
895 goto done;
898 /* Different devices */
899 else
901 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
902 || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
903 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
904 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
906 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
907 goto done;
913 /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set
914 * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
915 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED)
917 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
918 goto done;
921 /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */
922 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED)
924 status = STATUS_INVALID_PARAMETER;
925 goto done;
929 /* Remove owner */
930 if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId)
932 LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
934 if (source->device == desc->hDevice)
936 list_remove( &source->entry );
937 free( source );
940 goto done;
943 /* Add owner */
944 for (i = 0; i < desc->VidPnSourceCount; ++i)
946 found = FALSE;
947 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
949 if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i])
951 found = TRUE;
952 break;
956 if (found)
957 source->type = desc->pType[i];
958 else
960 source = malloc( sizeof( *source ) );
961 if (!source)
963 status = STATUS_NO_MEMORY;
964 goto done;
967 source->id = desc->pVidPnSourceId[i];
968 source->type = desc->pType[i];
969 source->device = desc->hDevice;
970 list_add_tail( &d3dkmt_vidpn_sources, &source->entry );
974 done:
975 pthread_mutex_unlock( &d3dkmt_mutex );
976 return status;
979 /**********************************************************************
980 * X11DRV_D3DKMTCheckVidPnExclusiveOwnership
982 NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
984 struct d3dkmt_vidpn_source *source;
986 TRACE("(%p)\n", desc);
988 if (!desc || !desc->hAdapter)
989 return STATUS_INVALID_PARAMETER;
991 pthread_mutex_lock( &d3dkmt_mutex );
992 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
994 if (source->id == desc->VidPnSourceId && source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)
996 pthread_mutex_unlock( &d3dkmt_mutex );
997 return STATUS_GRAPHICS_PRESENT_OCCLUDED;
1000 pthread_mutex_unlock( &d3dkmt_mutex );
1001 return STATUS_SUCCESS;
1004 static HANDLE get_display_device_init_mutex(void)
1006 WCHAR bufferW[256];
1007 UNICODE_STRING name = {.Buffer = bufferW};
1008 OBJECT_ATTRIBUTES attr;
1009 char buffer[256];
1010 HANDLE mutex;
1012 snprintf( buffer, ARRAY_SIZE(buffer), "\\Sessions\\%u\\BaseNamedObjects\\display_device_init",
1013 (int)NtCurrentTeb()->Peb->SessionId );
1014 name.Length = name.MaximumLength = asciiz_to_unicode( bufferW, buffer );
1016 InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
1017 if (NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE ) < 0) return 0;
1018 NtWaitForSingleObject( mutex, FALSE, NULL );
1019 return mutex;
1022 static void release_display_device_init_mutex(HANDLE mutex)
1024 NtReleaseMutant( mutex, NULL );
1025 NtClose( mutex );
1028 /* Find the Vulkan device UUID corresponding to a LUID */
1029 static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
1031 static const WCHAR class_guidW[] = {'C','l','a','s','s','G','U','I','D',0};
1032 static const WCHAR devpropkey_gpu_vulkan_uuidW[] =
1034 'P','r','o','p','e','r','t','i','e','s',
1035 '\\','{','2','3','3','A','9','E','F','3','-','A','F','C','4','-','4','A','B','D',
1036 '-','B','5','6','4','-','C','3','2','F','2','1','F','1','5','3','5','C','}',
1037 '\\','0','0','0','2'
1039 static const WCHAR devpropkey_gpu_luidW[] =
1041 'P','r','o','p','e','r','t','i','e','s',
1042 '\\','{','6','0','B','1','9','3','C','B','-','5','2','7','6','-','4','D','0','F',
1043 '-','9','6','F','C','-','F','1','7','3','A','B','A','D','3','E','C','6','}',
1044 '\\','0','0','0','2'
1046 static const WCHAR guid_devclass_displayW[] =
1047 {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-',
1048 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
1049 static const WCHAR pci_keyW[] =
1051 '\\','R','e','g','i','s','t','r','y',
1052 '\\','M','a','c','h','i','n','e',
1053 '\\','S','y','s','t','e','m',
1054 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
1055 '\\','E','n','u','m',
1056 '\\','P','C','I'
1058 char buffer[4096];
1059 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
1060 HKEY subkey, device_key, prop_key, pci_key;
1061 KEY_NODE_INFORMATION *key = (void *)buffer;
1062 DWORD size, i = 0;
1063 HANDLE mutex;
1065 mutex = get_display_device_init_mutex();
1067 pci_key = reg_open_key(NULL, pci_keyW, sizeof(pci_keyW));
1068 while (!NtEnumerateKey(pci_key, i++, KeyNodeInformation, key, sizeof(buffer), &size))
1070 unsigned int j = 0;
1072 if (!(subkey = reg_open_key(pci_key, key->Name, key->NameLength)))
1073 continue;
1075 while (!NtEnumerateKey(subkey, j++, KeyNodeInformation, key, sizeof(buffer), &size))
1077 if (!(device_key = reg_open_key(subkey, key->Name, key->NameLength)))
1078 continue;
1080 size = query_reg_value(device_key, class_guidW, value, sizeof(buffer));
1081 if (size != sizeof(guid_devclass_displayW) ||
1082 wcscmp((WCHAR *)value->Data, guid_devclass_displayW))
1084 NtClose(device_key);
1085 continue;
1088 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_luidW,
1089 sizeof(devpropkey_gpu_luidW))))
1091 NtClose(device_key);
1092 continue;
1095 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1096 NtClose(prop_key);
1097 if (size != sizeof(LUID) || memcmp(value->Data, luid, sizeof(LUID)))
1099 NtClose(device_key);
1100 continue;
1103 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_vulkan_uuidW,
1104 sizeof(devpropkey_gpu_vulkan_uuidW))))
1106 NtClose(device_key);
1107 continue;
1110 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1111 NtClose(prop_key);
1112 if (size != sizeof(GUID))
1114 NtClose(device_key);
1115 continue;
1118 *uuid = *(const GUID *)value->Data;
1119 NtClose(device_key);
1120 NtClose(subkey);
1121 NtClose(pci_key);
1122 release_display_device_init_mutex(mutex);
1123 return TRUE;
1125 NtClose(subkey);
1127 NtClose(pci_key);
1129 release_display_device_init_mutex(mutex);
1130 return FALSE;
1133 NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1135 static const char *extensions[] =
1137 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
1138 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
1140 const struct vulkan_funcs *vulkan_funcs;
1141 PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
1142 PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
1143 VkPhysicalDevice *vk_physical_devices = NULL;
1144 VkPhysicalDeviceProperties2 properties2;
1145 NTSTATUS status = STATUS_UNSUCCESSFUL;
1146 UINT device_count, device_idx = 0;
1147 struct x11_d3dkmt_adapter *adapter;
1148 VkInstanceCreateInfo create_info;
1149 VkPhysicalDeviceIDProperties id;
1150 VkResult vr;
1151 GUID uuid;
1153 if (!get_vulkan_uuid_from_luid(&desc->AdapterLuid, &uuid))
1155 WARN("Failed to find Vulkan device with LUID %08x:%08x.\n",
1156 (int)desc->AdapterLuid.HighPart, (int)desc->AdapterLuid.LowPart);
1157 return STATUS_INVALID_PARAMETER;
1160 /* Find the Vulkan device with corresponding UUID */
1161 if (!(vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION)))
1163 WARN("Vulkan is unavailable.\n");
1164 return STATUS_UNSUCCESSFUL;
1167 pthread_mutex_lock(&d3dkmt_mutex);
1169 if (!d3dkmt_vk_instance)
1171 memset(&create_info, 0, sizeof(create_info));
1172 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1173 create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
1174 create_info.ppEnabledExtensionNames = extensions;
1176 vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &d3dkmt_vk_instance);
1177 if (vr != VK_SUCCESS)
1179 WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
1180 goto done;
1184 #define LOAD_VK_FUNC(f) \
1185 if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, #f))) \
1187 WARN("Failed to load " #f ".\n"); \
1188 goto done; \
1191 LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
1192 LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
1193 #undef LOAD_VK_FUNC
1195 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, NULL);
1196 if (vr != VK_SUCCESS || !device_count)
1198 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
1199 goto done;
1202 if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
1203 goto done;
1205 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
1206 if (vr != VK_SUCCESS)
1208 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
1209 goto done;
1212 for (device_idx = 0; device_idx < device_count; ++device_idx)
1214 memset(&id, 0, sizeof(id));
1215 id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1216 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1217 properties2.pNext = &id;
1219 pvkGetPhysicalDeviceProperties2KHR(vk_physical_devices[device_idx], &properties2);
1220 if (!IsEqualGUID(&uuid, id.deviceUUID))
1221 continue;
1223 if (!(adapter = malloc(sizeof(*adapter))))
1225 status = STATUS_NO_MEMORY;
1226 goto done;
1229 adapter->handle = desc->hAdapter;
1230 adapter->vk_device = vk_physical_devices[device_idx];
1231 list_add_head(&x11_d3dkmt_adapters, &adapter->entry);
1232 status = STATUS_SUCCESS;
1233 break;
1236 done:
1237 if (d3dkmt_vk_instance && list_empty(&x11_d3dkmt_adapters))
1239 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
1240 d3dkmt_vk_instance = NULL;
1242 pthread_mutex_unlock(&d3dkmt_mutex);
1243 free(vk_physical_devices);
1244 return status;
1247 NTSTATUS CDECL X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1249 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
1250 PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR;
1251 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget;
1252 VkPhysicalDeviceMemoryProperties2 properties2;
1253 NTSTATUS status = STATUS_INVALID_PARAMETER;
1254 struct x11_d3dkmt_adapter *adapter;
1255 unsigned int i;
1257 desc->Budget = 0;
1258 desc->CurrentUsage = 0;
1259 desc->CurrentReservation = 0;
1260 desc->AvailableForReservation = 0;
1262 if (!vulkan_funcs)
1264 WARN("Vulkan is unavailable.\n");
1265 return STATUS_UNSUCCESSFUL;
1268 pthread_mutex_lock(&d3dkmt_mutex);
1269 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
1271 if (adapter->handle != desc->hAdapter)
1272 continue;
1274 if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
1276 WARN("Failed to load vkGetPhysicalDeviceMemoryProperties2KHR.\n");
1277 status = STATUS_UNSUCCESSFUL;
1278 goto done;
1281 memset(&budget, 0, sizeof(budget));
1282 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1283 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
1284 properties2.pNext = &budget;
1285 pvkGetPhysicalDeviceMemoryProperties2KHR(adapter->vk_device, &properties2);
1286 for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i)
1288 if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL
1289 && properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1290 || (desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL
1291 && !(properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)))
1293 desc->Budget += budget.heapBudget[i];
1294 desc->CurrentUsage += budget.heapUsage[i];
1297 desc->AvailableForReservation = desc->Budget / 2;
1298 status = STATUS_SUCCESS;
1299 break;
1301 done:
1302 pthread_mutex_unlock(&d3dkmt_mutex);
1303 return status;
1306 NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
1308 void *ret_ptr;
1309 ULONG ret_len;
1310 return KeUserModeCallback( id, params, size, &ret_ptr, &ret_len );
1314 NTSTATUS x11drv_client_call( enum client_callback func, UINT arg )
1316 struct client_callback_params params = { .id = func, .arg = arg };
1317 return x11drv_client_func( client_func_callback, &params, sizeof(params) );
1321 const unixlib_entry_t __wine_unix_call_funcs[] =
1323 x11drv_create_desktop,
1324 x11drv_init,
1325 x11drv_systray_clear,
1326 x11drv_systray_dock,
1327 x11drv_systray_hide,
1328 x11drv_systray_init,
1329 x11drv_tablet_attach_queue,
1330 x11drv_tablet_get_packet,
1331 x11drv_tablet_info,
1332 x11drv_tablet_load_info,
1333 x11drv_xim_preedit_state,
1334 x11drv_xim_reset,
1338 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
1341 #ifdef _WIN64
1343 static NTSTATUS x11drv_wow64_init( void *arg )
1345 struct
1347 ULONG foreign_window_proc;
1348 ULONG show_systray;
1349 } *params32 = arg;
1350 struct init_params params;
1352 params.foreign_window_proc = UlongToPtr( params32->foreign_window_proc );
1353 params.show_systray = UlongToPtr( params32->show_systray );
1354 return x11drv_init( &params );
1357 static NTSTATUS x11drv_wow64_systray_clear( void *arg )
1359 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1360 return x11drv_systray_clear( &hwnd );
1363 static NTSTATUS x11drv_wow64_systray_dock( void *arg )
1365 struct
1367 UINT64 event_handle;
1368 ULONG icon;
1369 int cx;
1370 int cy;
1371 ULONG layered;
1372 } *params32 = arg;
1373 struct systray_dock_params params;
1375 params.event_handle = params32->event_handle;
1376 params.icon = UlongToPtr( params32->icon );
1377 params.cx = params32->cx;
1378 params.cy = params32->cy;
1379 params.layered = UlongToPtr( params32->layered );
1380 return x11drv_systray_dock( &params );
1383 static NTSTATUS x11drv_wow64_systray_hide( void *arg )
1385 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1386 return x11drv_systray_hide( &hwnd );
1389 static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg )
1391 FIXME( "%p\n", arg );
1392 return 0;
1395 static NTSTATUS x11drv_wow64_tablet_info( void *arg )
1397 struct
1399 UINT category;
1400 UINT index;
1401 ULONG output;
1402 } *params32 = arg;
1403 struct tablet_info_params params;
1405 params.category = params32->category;
1406 params.index = params32->index;
1407 params.output = UlongToPtr( params32->output );
1408 return x11drv_tablet_info( &params );
1411 static NTSTATUS x11drv_wow64_xim_preedit_state( void *arg )
1413 struct
1415 ULONG hwnd;
1416 BOOL open;
1417 } *params32 = arg;
1418 struct xim_preedit_state_params params;
1420 params.hwnd = UlongToHandle( params32->hwnd );
1421 params.open = params32->open;
1422 return x11drv_xim_preedit_state( &params );
1425 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
1427 x11drv_create_desktop,
1428 x11drv_wow64_init,
1429 x11drv_wow64_systray_clear,
1430 x11drv_wow64_systray_dock,
1431 x11drv_wow64_systray_hide,
1432 x11drv_systray_init,
1433 x11drv_tablet_attach_queue,
1434 x11drv_wow64_tablet_get_packet,
1435 x11drv_wow64_tablet_info,
1436 x11drv_tablet_load_info,
1437 x11drv_wow64_xim_preedit_state,
1438 x11drv_xim_reset,
1441 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
1443 #endif /* _WIN64 */