win32u: Use platform-independent layout for ntuser_thread_info.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobe94977f8cafaafc7eb3f40152cbd7cfda53577e3
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 #ifdef HAVE_XKB
40 #include <X11/XKBlib.h>
41 #endif
42 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
43 #include <X11/extensions/Xrender.h>
44 #endif
46 #include "ntstatus.h"
47 #define WIN32_NO_STATUS
49 #define VK_NO_PROTOTYPES
50 #define WINE_VK_HOST
52 #include "x11drv.h"
53 #include "winreg.h"
54 #include "xcomposite.h"
55 #include "wine/server.h"
56 #include "wine/debug.h"
57 #include "wine/list.h"
58 #include "wine/vulkan.h"
59 #include "wine/vulkan_driver.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
62 WINE_DECLARE_DEBUG_CHANNEL(synchronous);
63 WINE_DECLARE_DEBUG_CHANNEL(winediag);
65 XVisualInfo default_visual = { 0 };
66 XVisualInfo argb_visual = { 0 };
67 Colormap default_colormap = None;
68 XPixmapFormatValues **pixmap_formats;
69 Atom systray_atom = 0;
70 unsigned int screen_bpp;
71 Window root_window;
72 BOOL usexvidmode = TRUE;
73 BOOL usexrandr = TRUE;
74 BOOL usexcomposite = TRUE;
75 BOOL use_xkb = TRUE;
76 BOOL use_take_focus = TRUE;
77 BOOL use_primary_selection = FALSE;
78 BOOL use_system_cursors = TRUE;
79 BOOL show_systray = TRUE;
80 BOOL grab_pointer = TRUE;
81 BOOL grab_fullscreen = FALSE;
82 BOOL managed_mode = TRUE;
83 BOOL decorated_mode = TRUE;
84 BOOL private_color_map = FALSE;
85 int primary_monitor = 0;
86 BOOL client_side_graphics = TRUE;
87 BOOL client_side_with_render = TRUE;
88 BOOL shape_layered_windows = TRUE;
89 int copy_default_colors = 128;
90 int alloc_system_colors = 256;
91 int xrender_error_base = 0;
92 char *process_name = NULL;
93 WNDPROC client_foreign_window_proc = NULL;
95 static x11drv_error_callback err_callback; /* current callback for error */
96 static Display *err_callback_display; /* display callback is set for */
97 static void *err_callback_arg; /* error callback argument */
98 static int err_callback_result; /* error callback result */
99 static unsigned long err_serial; /* serial number of first request */
100 static int (*old_error_handler)( Display *, XErrorEvent * );
101 static BOOL use_xim = TRUE;
102 static WCHAR input_style[20];
104 static pthread_mutex_t d3dkmt_mutex = PTHREAD_MUTEX_INITIALIZER;
105 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
107 struct x11_d3dkmt_adapter
109 D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
110 VkPhysicalDevice vk_device; /* Vulkan physical device */
111 struct list entry; /* List entry */
114 struct d3dkmt_vidpn_source
116 D3DKMT_VIDPNSOURCEOWNER_TYPE type; /* VidPN source owner type */
117 D3DDDI_VIDEO_PRESENT_SOURCE_ID id; /* VidPN present source id */
118 D3DKMT_HANDLE device; /* Kernel mode device context */
119 struct list entry; /* List entry */
122 static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */
123 static struct list x11_d3dkmt_adapters = LIST_INIT( x11_d3dkmt_adapters );
124 static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
126 #define IS_OPTION_TRUE(ch) \
127 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
128 #define IS_OPTION_FALSE(ch) \
129 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
131 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
133 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
135 "CLIPBOARD",
136 "COMPOUND_TEXT",
137 "EDID",
138 "INCR",
139 "MANAGER",
140 "MULTIPLE",
141 "SELECTION_DATA",
142 "TARGETS",
143 "TEXT",
144 "TIMESTAMP",
145 "UTF8_STRING",
146 "RAW_ASCENT",
147 "RAW_DESCENT",
148 "RAW_CAP_HEIGHT",
149 "Rel X",
150 "Rel Y",
151 "WM_PROTOCOLS",
152 "WM_DELETE_WINDOW",
153 "WM_STATE",
154 "WM_TAKE_FOCUS",
155 "DndProtocol",
156 "DndSelection",
157 "_ICC_PROFILE",
158 "_MOTIF_WM_HINTS",
159 "_NET_STARTUP_INFO_BEGIN",
160 "_NET_STARTUP_INFO",
161 "_NET_SUPPORTED",
162 "_NET_SYSTEM_TRAY_OPCODE",
163 "_NET_SYSTEM_TRAY_S0",
164 "_NET_SYSTEM_TRAY_VISUAL",
165 "_NET_WM_ICON",
166 "_NET_WM_MOVERESIZE",
167 "_NET_WM_NAME",
168 "_NET_WM_PID",
169 "_NET_WM_PING",
170 "_NET_WM_STATE",
171 "_NET_WM_STATE_ABOVE",
172 "_NET_WM_STATE_DEMANDS_ATTENTION",
173 "_NET_WM_STATE_FULLSCREEN",
174 "_NET_WM_STATE_MAXIMIZED_HORZ",
175 "_NET_WM_STATE_MAXIMIZED_VERT",
176 "_NET_WM_STATE_SKIP_PAGER",
177 "_NET_WM_STATE_SKIP_TASKBAR",
178 "_NET_WM_USER_TIME",
179 "_NET_WM_USER_TIME_WINDOW",
180 "_NET_WM_WINDOW_OPACITY",
181 "_NET_WM_WINDOW_TYPE",
182 "_NET_WM_WINDOW_TYPE_DIALOG",
183 "_NET_WM_WINDOW_TYPE_NORMAL",
184 "_NET_WM_WINDOW_TYPE_UTILITY",
185 "_NET_WORKAREA",
186 "_GTK_WORKAREAS_D0",
187 "_XEMBED",
188 "_XEMBED_INFO",
189 "XdndAware",
190 "XdndEnter",
191 "XdndPosition",
192 "XdndStatus",
193 "XdndLeave",
194 "XdndFinished",
195 "XdndDrop",
196 "XdndActionCopy",
197 "XdndActionMove",
198 "XdndActionLink",
199 "XdndActionAsk",
200 "XdndActionPrivate",
201 "XdndSelection",
202 "XdndTypeList",
203 "HTML Format",
204 "WCF_DIF",
205 "WCF_ENHMETAFILE",
206 "WCF_HDROP",
207 "WCF_PENDATA",
208 "WCF_RIFF",
209 "WCF_SYLK",
210 "WCF_TIFF",
211 "WCF_WAVE",
212 "image/bmp",
213 "image/gif",
214 "image/jpeg",
215 "image/png",
216 "text/html",
217 "text/plain",
218 "text/rtf",
219 "text/richtext",
220 "text/uri-list"
223 /***********************************************************************
224 * ignore_error
226 * Check if the X error is one we can ignore.
228 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
230 if ((event->request_code == X_SetInputFocus ||
231 event->request_code == X_ChangeWindowAttributes ||
232 event->request_code == X_SendEvent) &&
233 (event->error_code == BadMatch ||
234 event->error_code == BadWindow)) return TRUE;
236 /* the clipboard display interacts with external windows, ignore all errors */
237 if (display == clipboard_display) return TRUE;
239 /* ignore a number of errors on gdi display caused by creating/destroying windows */
240 if (display == gdi_display)
242 if (event->error_code == BadDrawable ||
243 event->error_code == BadGC ||
244 event->error_code == BadWindow)
245 return TRUE;
246 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
247 if (xrender_error_base) /* check for XRender errors */
249 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
251 #endif
253 return FALSE;
257 /***********************************************************************
258 * X11DRV_expect_error
260 * Setup a callback function that will be called on an X error. The
261 * callback must return non-zero if the error is the one it expected.
263 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
265 pthread_mutex_lock( &error_mutex );
266 XLockDisplay( display );
267 err_callback = callback;
268 err_callback_display = display;
269 err_callback_arg = arg;
270 err_callback_result = 0;
271 err_serial = NextRequest(display);
275 /***********************************************************************
276 * X11DRV_check_error
278 * Check if an expected X11 error occurred; return non-zero if yes.
279 * The caller is responsible for calling XSync first if necessary.
281 int X11DRV_check_error(void)
283 int res = err_callback_result;
284 err_callback = NULL;
285 XUnlockDisplay( err_callback_display );
286 pthread_mutex_unlock( &error_mutex );
287 return res;
291 /***********************************************************************
292 * error_handler
294 static int error_handler( Display *display, XErrorEvent *error_evt )
296 if (err_callback && display == err_callback_display &&
297 (!error_evt->serial || error_evt->serial >= err_serial))
299 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
301 TRACE( "got expected error %d req %d\n",
302 error_evt->error_code, error_evt->request_code );
303 return 0;
306 if (ignore_error( display, error_evt ))
308 TRACE( "got ignored error %d req %d\n",
309 error_evt->error_code, error_evt->request_code );
310 return 0;
312 if (TRACE_ON(synchronous))
314 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
315 error_evt->serial, error_evt->request_code );
316 assert( 0 );
318 old_error_handler( display, error_evt );
319 return 0;
322 /***********************************************************************
323 * init_pixmap_formats
325 static void init_pixmap_formats( Display *display )
327 int i, count, max = 32;
328 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
330 for (i = 0; i < count; i++)
332 TRACE( "depth %u, bpp %u, pad %u\n",
333 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
334 if (formats[i].depth > max) max = formats[i].depth;
336 pixmap_formats = calloc( 1, sizeof(*pixmap_formats) * (max + 1) );
337 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
341 HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
343 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
344 OBJECT_ATTRIBUTES attr;
345 HANDLE ret;
347 attr.Length = sizeof(attr);
348 attr.RootDirectory = root;
349 attr.ObjectName = &nameW;
350 attr.Attributes = 0;
351 attr.SecurityDescriptor = NULL;
352 attr.SecurityQualityOfService = NULL;
354 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
358 HKEY open_hkcu_key( const char *name )
360 WCHAR bufferW[256];
361 static HKEY hkcu;
363 if (!hkcu)
365 char buffer[256];
366 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
367 DWORD i, len = sizeof(sid_data);
368 SID *sid;
370 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
371 return 0;
373 sid = ((TOKEN_USER *)sid_data)->User.Sid;
374 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
375 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
376 sid->IdentifierAuthority.Value[4] ),
377 MAKEWORD( sid->IdentifierAuthority.Value[3],
378 sid->IdentifierAuthority.Value[2] )));
379 for (i = 0; i < sid->SubAuthorityCount; i++)
380 len += sprintf( buffer + len, "-%u", sid->SubAuthority[i] );
382 ascii_to_unicode( bufferW, buffer, len );
383 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
386 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
390 ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
392 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
393 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
395 if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
396 info, size, &size ))
397 return 0;
399 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
403 /***********************************************************************
404 * get_config_key
406 * Get a config key from either the app-specific or the default config
408 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
409 WCHAR *buffer, DWORD size )
411 WCHAR nameW[128];
412 char buf[2048];
413 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
415 asciiz_to_unicode( nameW, name );
417 if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) ))
419 size = min( info->DataLength, size - sizeof(WCHAR) );
420 memcpy( buffer, info->Data, size );
421 buffer[size / sizeof(WCHAR)] = 0;
422 return 0;
425 if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) ))
427 size = min( info->DataLength, size - sizeof(WCHAR) );
428 memcpy( buffer, info->Data, size );
429 buffer[size / sizeof(WCHAR)] = 0;
430 return 0;
433 return ERROR_FILE_NOT_FOUND;
437 /***********************************************************************
438 * setup_options
440 * Setup the x11drv options.
442 static void setup_options(void)
444 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
445 WCHAR buffer[MAX_PATH+16], *p, *appname;
446 HKEY hkey, appkey = 0;
447 DWORD len;
449 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
450 hkey = open_hkcu_key( "Software\\Wine\\X11 Driver" );
452 /* open the app-specific key */
454 appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
455 if ((p = wcsrchr( appname, '/' ))) appname = p + 1;
456 if ((p = wcsrchr( appname, '\\' ))) appname = p + 1;
457 len = lstrlenW( appname );
459 if (len && len < MAX_PATH)
461 HKEY tmpkey;
462 int i;
463 for (i = 0; appname[i]; i++) buffer[i] = RtlDowncaseUnicodeChar( appname[i] );
464 buffer[i] = 0;
465 appname = buffer;
466 if ((process_name = malloc( len * 3 + 1 )))
467 ntdll_wcstoumbs( appname, len + 1, process_name, len * 3 + 1, FALSE );
468 memcpy( appname + i, x11driverW, sizeof(x11driverW) );
469 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
470 if ((tmpkey = open_hkcu_key( "Software\\Wine\\AppDefaults" )))
472 appkey = reg_open_key( tmpkey, appname, lstrlenW( appname ) * sizeof(WCHAR) );
473 NtClose( tmpkey );
477 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
478 managed_mode = IS_OPTION_TRUE( buffer[0] );
480 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
481 decorated_mode = IS_OPTION_TRUE( buffer[0] );
483 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
484 usexvidmode = IS_OPTION_TRUE( buffer[0] );
486 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
487 usexrandr = IS_OPTION_TRUE( buffer[0] );
489 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
490 use_take_focus = IS_OPTION_TRUE( buffer[0] );
492 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
493 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
495 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
496 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
498 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
499 show_systray = IS_OPTION_TRUE( buffer[0] );
501 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
502 grab_pointer = IS_OPTION_TRUE( buffer[0] );
504 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
505 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
507 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
508 default_visual.depth = wcstol( buffer, NULL, 0 );
510 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
511 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
513 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
514 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
516 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
517 use_xim = IS_OPTION_TRUE( buffer[0] );
519 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
520 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
522 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
523 private_color_map = IS_OPTION_TRUE( buffer[0] );
525 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
526 primary_monitor = wcstol( buffer, NULL, 0 );
528 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
529 copy_default_colors = wcstol( buffer, NULL, 0 );
531 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
532 alloc_system_colors = wcstol( buffer, NULL, 0 );
534 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
536 NtClose( appkey );
537 NtClose( hkey );
540 #ifdef SONAME_LIBXCOMPOSITE
542 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
543 MAKE_FUNCPTR(XCompositeQueryExtension)
544 MAKE_FUNCPTR(XCompositeQueryVersion)
545 MAKE_FUNCPTR(XCompositeVersion)
546 MAKE_FUNCPTR(XCompositeRedirectWindow)
547 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
548 MAKE_FUNCPTR(XCompositeUnredirectWindow)
549 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
550 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
551 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
552 #undef MAKE_FUNCPTR
554 static int xcomp_event_base;
555 static int xcomp_error_base;
557 static void X11DRV_XComposite_Init(void)
559 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
560 if (!xcomposite_handle)
562 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
563 usexcomposite = FALSE;
564 return;
567 #define LOAD_FUNCPTR(f) \
568 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
569 LOAD_FUNCPTR(XCompositeQueryExtension);
570 LOAD_FUNCPTR(XCompositeQueryVersion);
571 LOAD_FUNCPTR(XCompositeVersion);
572 LOAD_FUNCPTR(XCompositeRedirectWindow);
573 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
574 LOAD_FUNCPTR(XCompositeUnredirectWindow);
575 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
576 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
577 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
578 #undef LOAD_FUNCPTR
580 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
581 &xcomp_error_base)) {
582 TRACE("XComposite extension could not be queried; disabled\n");
583 dlclose(xcomposite_handle);
584 xcomposite_handle = NULL;
585 usexcomposite = FALSE;
586 return;
588 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
589 return;
591 sym_not_found:
592 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
593 dlclose(xcomposite_handle);
594 xcomposite_handle = NULL;
595 usexcomposite = FALSE;
597 #endif /* defined(SONAME_LIBXCOMPOSITE) */
599 static void init_visuals( Display *display, int screen )
601 int count;
602 XVisualInfo *info;
604 argb_visual.screen = screen;
605 argb_visual.class = TrueColor;
606 argb_visual.depth = 32;
607 argb_visual.red_mask = 0xff0000;
608 argb_visual.green_mask = 0x00ff00;
609 argb_visual.blue_mask = 0x0000ff;
611 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
612 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
613 &argb_visual, &count )))
615 argb_visual = *info;
616 XFree( info );
619 default_visual.screen = screen;
620 if (default_visual.depth) /* depth specified */
622 if (default_visual.depth == 32 && argb_visual.visual)
624 default_visual = argb_visual;
626 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
628 default_visual = *info;
629 XFree( info );
631 else WARN( "no visual found for depth %d\n", default_visual.depth );
634 if (!default_visual.visual)
636 default_visual.depth = DefaultDepth( display, screen );
637 default_visual.visual = DefaultVisual( display, screen );
638 default_visual.visualid = default_visual.visual->visualid;
639 default_visual.class = default_visual.visual->class;
640 default_visual.red_mask = default_visual.visual->red_mask;
641 default_visual.green_mask = default_visual.visual->green_mask;
642 default_visual.blue_mask = default_visual.visual->blue_mask;
643 default_visual.colormap_size = default_visual.visual->map_entries;
644 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
646 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
648 TRACE( "default visual %lx class %u argb %lx\n",
649 default_visual.visualid, default_visual.class, argb_visual.visualid );
652 /***********************************************************************
653 * X11DRV process initialisation routine
655 static NTSTATUS x11drv_init( void *arg )
657 struct init_params *params = arg;
658 Display *display;
659 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
661 if (!libx11)
663 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
664 return STATUS_UNSUCCESSFUL;
666 pXGetEventData = dlsym( libx11, "XGetEventData" );
667 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
668 #ifdef SONAME_LIBXEXT
669 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
670 #endif
672 setup_options();
674 /* Open display */
676 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
677 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
679 client_foreign_window_proc = params->foreign_window_proc;
681 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
682 root_window = DefaultRootWindow( display );
683 gdi_display = display;
684 old_error_handler = XSetErrorHandler( error_handler );
686 init_pixmap_formats( display );
687 init_visuals( display, DefaultScreen( display ));
688 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
690 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
692 init_win_context();
694 if (TRACE_ON(synchronous)) XSynchronize( display, True );
696 xinerama_init( DisplayWidth( display, default_visual.screen ),
697 DisplayHeight( display, default_visual.screen ));
698 X11DRV_Settings_Init();
700 /* initialize XVidMode */
701 X11DRV_XF86VM_Init();
702 /* initialize XRandR */
703 X11DRV_XRandR_Init();
704 #ifdef SONAME_LIBXCOMPOSITE
705 X11DRV_XComposite_Init();
706 #endif
707 X11DRV_XInput2_Init();
709 #ifdef HAVE_XKB
710 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
711 #endif
712 X11DRV_InitKeyboard( gdi_display );
713 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
715 init_user_driver();
716 X11DRV_DisplayDevices_Init(FALSE);
717 params->show_systray = show_systray;
718 return STATUS_SUCCESS;
722 /***********************************************************************
723 * ThreadDetach (X11DRV.@)
725 void X11DRV_ThreadDetach(void)
727 struct x11drv_thread_data *data = x11drv_thread_data();
729 if (data)
731 vulkan_thread_detach();
732 if (data->xim) XCloseIM( data->xim );
733 if (data->font_set) XFreeFontSet( data->display, data->font_set );
734 XCloseDisplay( data->display );
735 free( data );
736 /* clear data in case we get re-entered from user32 before the thread is truly dead */
737 NtUserGetThreadInfo()->driver_data = 0;
742 /* store the display fd into the message queue */
743 static void set_queue_display_fd( Display *display )
745 HANDLE handle;
746 int ret;
748 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
750 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
751 NtTerminateProcess( 0, 1 );
753 SERVER_START_REQ( set_queue_fd )
755 req->handle = wine_server_obj_handle( handle );
756 ret = wine_server_call( req );
758 SERVER_END_REQ;
759 if (ret)
761 MESSAGE( "x11drv: Can't store handle for display fd\n" );
762 NtTerminateProcess( 0, 1 );
764 NtClose( handle );
768 /***********************************************************************
769 * X11DRV thread initialisation routine
771 struct x11drv_thread_data *x11drv_init_thread_data(void)
773 struct x11drv_thread_data *data = x11drv_thread_data();
775 if (data) return data;
777 if (!(data = calloc( 1, sizeof(*data) )))
779 ERR( "could not create data\n" );
780 NtTerminateProcess( 0, 1 );
782 if (!(data->display = XOpenDisplay(NULL)))
784 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));
785 NtTerminateProcess( 0, 1 );
788 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
790 #ifdef HAVE_XKB
791 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
792 XkbSetDetectableAutoRepeat( data->display, True, NULL );
793 #endif
795 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
797 set_queue_display_fd( data->display );
798 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
800 if (use_xim) X11DRV_SetupXIM();
802 return data;
806 /***********************************************************************
807 * SystemParametersInfo (X11DRV.@)
809 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
811 switch (action)
813 case SPI_GETSCREENSAVEACTIVE:
814 if (ptr_param)
816 int timeout, temp;
817 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
818 *(BOOL *)ptr_param = timeout != 0;
819 return TRUE;
821 break;
822 case SPI_SETSCREENSAVEACTIVE:
824 int timeout, interval, prefer_blanking, allow_exposures;
825 static int last_timeout = 15 * 60;
827 XLockDisplay( gdi_display );
828 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
829 &allow_exposures);
830 if (timeout) last_timeout = timeout;
832 timeout = int_param ? last_timeout : 0;
833 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
834 allow_exposures);
835 XUnlockDisplay( gdi_display );
837 break;
839 return FALSE; /* let user32 handle it */
842 NTSTATUS CDECL X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
844 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
845 struct x11_d3dkmt_adapter *adapter;
847 if (!vulkan_funcs)
848 return STATUS_UNSUCCESSFUL;
850 pthread_mutex_lock(&d3dkmt_mutex);
851 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
853 if (adapter->handle == desc->hAdapter)
855 list_remove(&adapter->entry);
856 free(adapter);
857 break;
861 if (list_empty(&x11_d3dkmt_adapters))
863 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
864 d3dkmt_vk_instance = NULL;
866 pthread_mutex_unlock(&d3dkmt_mutex);
867 return STATUS_SUCCESS;
870 /**********************************************************************
871 * X11DRV_D3DKMTSetVidPnSourceOwner
873 NTSTATUS CDECL X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
875 struct d3dkmt_vidpn_source *source, *source2;
876 NTSTATUS status = STATUS_SUCCESS;
877 BOOL found;
878 UINT i;
880 TRACE("(%p)\n", desc);
882 pthread_mutex_lock( &d3dkmt_mutex );
884 /* Check parameters */
885 for (i = 0; i < desc->VidPnSourceCount; ++i)
887 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
889 if (source->id == desc->pVidPnSourceId[i])
891 /* Same device */
892 if (source->device == desc->hDevice)
894 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
895 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED
896 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
897 || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED
898 && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE))
900 status = STATUS_INVALID_PARAMETER;
901 goto done;
904 /* Different devices */
905 else
907 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
908 || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
909 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
910 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
912 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
913 goto done;
919 /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set
920 * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
921 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED)
923 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
924 goto done;
927 /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */
928 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED)
930 status = STATUS_INVALID_PARAMETER;
931 goto done;
935 /* Remove owner */
936 if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId)
938 LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
940 if (source->device == desc->hDevice)
942 list_remove( &source->entry );
943 free( source );
946 goto done;
949 /* Add owner */
950 for (i = 0; i < desc->VidPnSourceCount; ++i)
952 found = FALSE;
953 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
955 if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i])
957 found = TRUE;
958 break;
962 if (found)
963 source->type = desc->pType[i];
964 else
966 source = malloc( sizeof( *source ) );
967 if (!source)
969 status = STATUS_NO_MEMORY;
970 goto done;
973 source->id = desc->pVidPnSourceId[i];
974 source->type = desc->pType[i];
975 source->device = desc->hDevice;
976 list_add_tail( &d3dkmt_vidpn_sources, &source->entry );
980 done:
981 pthread_mutex_unlock( &d3dkmt_mutex );
982 return status;
985 /**********************************************************************
986 * X11DRV_D3DKMTCheckVidPnExclusiveOwnership
988 NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
990 struct d3dkmt_vidpn_source *source;
992 TRACE("(%p)\n", desc);
994 if (!desc || !desc->hAdapter)
995 return STATUS_INVALID_PARAMETER;
997 pthread_mutex_lock( &d3dkmt_mutex );
998 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
1000 if (source->id == desc->VidPnSourceId && source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)
1002 pthread_mutex_unlock( &d3dkmt_mutex );
1003 return STATUS_GRAPHICS_PRESENT_OCCLUDED;
1006 pthread_mutex_unlock( &d3dkmt_mutex );
1007 return STATUS_SUCCESS;
1010 static HANDLE get_display_device_init_mutex(void)
1012 static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t'};
1013 UNICODE_STRING name = { sizeof(init_mutexW), sizeof(init_mutexW), (WCHAR *)init_mutexW };
1014 OBJECT_ATTRIBUTES attr;
1015 HANDLE mutex = 0;
1017 InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
1018 NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE );
1019 if (mutex) NtWaitForSingleObject( mutex, FALSE, NULL );
1020 return mutex;
1023 static void release_display_device_init_mutex(HANDLE mutex)
1025 NtReleaseMutant( mutex, NULL );
1026 NtClose( mutex );
1029 /* Find the Vulkan device UUID corresponding to a LUID */
1030 static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
1032 static const WCHAR class_guidW[] = {'C','l','a','s','s','G','U','I','D',0};
1033 static const WCHAR devpropkey_gpu_vulkan_uuidW[] =
1035 'P','r','o','p','e','r','t','i','e','s',
1036 '\\','{','2','3','3','A','9','E','F','3','-','A','F','C','4','-','4','A','B','D',
1037 '-','B','5','6','4','-','C','3','2','F','2','1','F','1','5','3','5','C','}',
1038 '\\','0','0','0','2'
1040 static const WCHAR devpropkey_gpu_luidW[] =
1042 'P','r','o','p','e','r','t','i','e','s',
1043 '\\','{','6','0','B','1','9','3','C','B','-','5','2','7','6','-','4','D','0','F',
1044 '-','9','6','F','C','-','F','1','7','3','A','B','A','D','3','E','C','6','}',
1045 '\\','0','0','0','2'
1047 static const WCHAR guid_devclass_displayW[] =
1048 {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-',
1049 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
1050 static const WCHAR pci_keyW[] =
1052 '\\','R','e','g','i','s','t','r','y',
1053 '\\','M','a','c','h','i','n','e',
1054 '\\','S','y','s','t','e','m',
1055 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
1056 '\\','E','n','u','m',
1057 '\\','P','C','I'
1059 char buffer[4096];
1060 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
1061 HKEY subkey, device_key, prop_key, pci_key;
1062 KEY_NODE_INFORMATION *key = (void *)buffer;
1063 DWORD size, i = 0;
1064 HANDLE mutex;
1066 mutex = get_display_device_init_mutex();
1068 pci_key = reg_open_key(NULL, pci_keyW, sizeof(pci_keyW));
1069 while (!NtEnumerateKey(pci_key, i++, KeyNodeInformation, key, sizeof(buffer), &size))
1071 unsigned int j = 0;
1073 if (!(subkey = reg_open_key(pci_key, key->Name, key->NameLength)))
1074 continue;
1076 while (!NtEnumerateKey(subkey, j++, KeyNodeInformation, key, sizeof(buffer), &size))
1078 if (!(device_key = reg_open_key(subkey, key->Name, key->NameLength)))
1079 continue;
1081 size = query_reg_value(device_key, class_guidW, value, sizeof(buffer));
1082 if (size != sizeof(guid_devclass_displayW) ||
1083 wcscmp((WCHAR *)value->Data, guid_devclass_displayW))
1085 NtClose(device_key);
1086 continue;
1089 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_luidW,
1090 sizeof(devpropkey_gpu_luidW))))
1092 NtClose(device_key);
1093 continue;
1096 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1097 NtClose(prop_key);
1098 if (size != sizeof(LUID) || memcmp(value->Data, luid, sizeof(LUID)))
1100 NtClose(device_key);
1101 continue;
1104 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_vulkan_uuidW,
1105 sizeof(devpropkey_gpu_vulkan_uuidW))))
1107 NtClose(device_key);
1108 continue;
1111 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1112 NtClose(prop_key);
1113 if (size != sizeof(GUID))
1115 NtClose(device_key);
1116 continue;
1119 *uuid = *(const GUID *)value->Data;
1120 NtClose(device_key);
1121 NtClose(subkey);
1122 NtClose(pci_key);
1123 release_display_device_init_mutex(mutex);
1124 return TRUE;
1126 NtClose(subkey);
1128 NtClose(pci_key);
1130 release_display_device_init_mutex(mutex);
1131 return FALSE;
1134 NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1136 static const char *extensions[] =
1138 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
1139 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
1141 const struct vulkan_funcs *vulkan_funcs;
1142 PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
1143 PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
1144 VkPhysicalDevice *vk_physical_devices = NULL;
1145 VkPhysicalDeviceProperties2 properties2;
1146 NTSTATUS status = STATUS_UNSUCCESSFUL;
1147 DWORD device_count, device_idx = 0;
1148 struct x11_d3dkmt_adapter *adapter;
1149 VkInstanceCreateInfo create_info;
1150 VkPhysicalDeviceIDProperties id;
1151 VkResult vr;
1152 GUID uuid;
1154 if (!get_vulkan_uuid_from_luid(&desc->AdapterLuid, &uuid))
1156 WARN("Failed to find Vulkan device with LUID %08x:%08x.\n", desc->AdapterLuid.HighPart,
1157 desc->AdapterLuid.LowPart);
1158 return STATUS_INVALID_PARAMETER;
1161 /* Find the Vulkan device with corresponding UUID */
1162 if (!(vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION)))
1164 WARN("Vulkan is unavailable.\n");
1165 return STATUS_UNSUCCESSFUL;
1168 pthread_mutex_lock(&d3dkmt_mutex);
1170 if (!d3dkmt_vk_instance)
1172 memset(&create_info, 0, sizeof(create_info));
1173 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1174 create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
1175 create_info.ppEnabledExtensionNames = extensions;
1177 vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &d3dkmt_vk_instance);
1178 if (vr != VK_SUCCESS)
1180 WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
1181 goto done;
1185 #define LOAD_VK_FUNC(f) \
1186 if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, #f))) \
1188 WARN("Failed to load " #f ".\n"); \
1189 goto done; \
1192 LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
1193 LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
1194 #undef LOAD_VK_FUNC
1196 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, NULL);
1197 if (vr != VK_SUCCESS || !device_count)
1199 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
1200 goto done;
1203 if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
1204 goto done;
1206 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
1207 if (vr != VK_SUCCESS)
1209 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
1210 goto done;
1213 for (device_idx = 0; device_idx < device_count; ++device_idx)
1215 memset(&id, 0, sizeof(id));
1216 id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1217 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1218 properties2.pNext = &id;
1220 pvkGetPhysicalDeviceProperties2KHR(vk_physical_devices[device_idx], &properties2);
1221 if (!IsEqualGUID(&uuid, id.deviceUUID))
1222 continue;
1224 if (!(adapter = malloc(sizeof(*adapter))))
1226 status = STATUS_NO_MEMORY;
1227 goto done;
1230 adapter->handle = desc->hAdapter;
1231 adapter->vk_device = vk_physical_devices[device_idx];
1232 list_add_head(&x11_d3dkmt_adapters, &adapter->entry);
1233 status = STATUS_SUCCESS;
1234 break;
1237 done:
1238 if (d3dkmt_vk_instance && list_empty(&x11_d3dkmt_adapters))
1240 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
1241 d3dkmt_vk_instance = NULL;
1243 pthread_mutex_unlock(&d3dkmt_mutex);
1244 free(vk_physical_devices);
1245 return status;
1248 NTSTATUS CDECL X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1250 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
1251 PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR;
1252 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget;
1253 VkPhysicalDeviceMemoryProperties2 properties2;
1254 NTSTATUS status = STATUS_INVALID_PARAMETER;
1255 struct x11_d3dkmt_adapter *adapter;
1256 unsigned int i;
1258 desc->Budget = 0;
1259 desc->CurrentUsage = 0;
1260 desc->CurrentReservation = 0;
1261 desc->AvailableForReservation = 0;
1263 if (!vulkan_funcs)
1265 WARN("Vulkan is unavailable.\n");
1266 return STATUS_UNSUCCESSFUL;
1269 pthread_mutex_lock(&d3dkmt_mutex);
1270 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
1272 if (adapter->handle != desc->hAdapter)
1273 continue;
1275 if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
1277 WARN("Failed to load vkGetPhysicalDeviceMemoryProperties2KHR.\n");
1278 status = STATUS_UNSUCCESSFUL;
1279 goto done;
1282 memset(&budget, 0, sizeof(budget));
1283 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1284 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
1285 properties2.pNext = &budget;
1286 pvkGetPhysicalDeviceMemoryProperties2KHR(adapter->vk_device, &properties2);
1287 for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i)
1289 if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL
1290 && properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1291 || (desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL
1292 && !(properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)))
1294 desc->Budget += budget.heapBudget[i];
1295 desc->CurrentUsage += budget.heapUsage[i];
1298 desc->AvailableForReservation = desc->Budget / 2;
1299 status = STATUS_SUCCESS;
1300 break;
1302 done:
1303 pthread_mutex_unlock(&d3dkmt_mutex);
1304 return status;
1307 NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
1309 void *ret_ptr;
1310 ULONG ret_len;
1311 return KeUserModeCallback( id, params, size, &ret_ptr, &ret_len );
1315 NTSTATUS x11drv_client_call( enum client_callback func, UINT arg )
1317 struct client_callback_params params = { .id = func, .arg = arg };
1318 return x11drv_client_func( client_func_callback, &params, sizeof(params) );
1322 const unixlib_entry_t __wine_unix_call_funcs[] =
1324 x11drv_create_desktop,
1325 x11drv_init,
1326 x11drv_systray_clear,
1327 x11drv_systray_dock,
1328 x11drv_systray_hide,
1329 x11drv_systray_init,
1330 x11drv_tablet_attach_queue,
1331 x11drv_tablet_get_packet,
1332 x11drv_tablet_info,
1333 x11drv_tablet_load_info,
1334 x11drv_xim_preedit_state,
1335 x11drv_xim_reset,
1339 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );