winex11: Avoid calling RtlInitUnicodeString on a static constant.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blob797e4f92d38f9259d0becf986fb1249d880e5e41
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 "_KDE_NET_WM_STATE_SKIP_SWITCHER",
159 "_MOTIF_WM_HINTS",
160 "_NET_STARTUP_INFO_BEGIN",
161 "_NET_STARTUP_INFO",
162 "_NET_SUPPORTED",
163 "_NET_SYSTEM_TRAY_OPCODE",
164 "_NET_SYSTEM_TRAY_S0",
165 "_NET_SYSTEM_TRAY_VISUAL",
166 "_NET_WM_FULLSCREEN_MONITORS",
167 "_NET_WM_ICON",
168 "_NET_WM_MOVERESIZE",
169 "_NET_WM_NAME",
170 "_NET_WM_PID",
171 "_NET_WM_PING",
172 "_NET_WM_STATE",
173 "_NET_WM_STATE_ABOVE",
174 "_NET_WM_STATE_DEMANDS_ATTENTION",
175 "_NET_WM_STATE_FULLSCREEN",
176 "_NET_WM_STATE_MAXIMIZED_HORZ",
177 "_NET_WM_STATE_MAXIMIZED_VERT",
178 "_NET_WM_STATE_SKIP_PAGER",
179 "_NET_WM_STATE_SKIP_TASKBAR",
180 "_NET_WM_USER_TIME",
181 "_NET_WM_USER_TIME_WINDOW",
182 "_NET_WM_WINDOW_OPACITY",
183 "_NET_WM_WINDOW_TYPE",
184 "_NET_WM_WINDOW_TYPE_DIALOG",
185 "_NET_WM_WINDOW_TYPE_NORMAL",
186 "_NET_WM_WINDOW_TYPE_UTILITY",
187 "_NET_WORKAREA",
188 "_GTK_WORKAREAS_D0",
189 "_XEMBED",
190 "_XEMBED_INFO",
191 "XdndAware",
192 "XdndEnter",
193 "XdndPosition",
194 "XdndStatus",
195 "XdndLeave",
196 "XdndFinished",
197 "XdndDrop",
198 "XdndActionCopy",
199 "XdndActionMove",
200 "XdndActionLink",
201 "XdndActionAsk",
202 "XdndActionPrivate",
203 "XdndSelection",
204 "XdndTypeList",
205 "HTML Format",
206 "WCF_DIF",
207 "WCF_ENHMETAFILE",
208 "WCF_HDROP",
209 "WCF_PENDATA",
210 "WCF_RIFF",
211 "WCF_SYLK",
212 "WCF_TIFF",
213 "WCF_WAVE",
214 "image/bmp",
215 "image/gif",
216 "image/jpeg",
217 "image/png",
218 "text/html",
219 "text/plain",
220 "text/rtf",
221 "text/richtext",
222 "text/uri-list"
225 /***********************************************************************
226 * ignore_error
228 * Check if the X error is one we can ignore.
230 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
232 if ((event->request_code == X_SetInputFocus ||
233 event->request_code == X_ChangeWindowAttributes ||
234 event->request_code == X_SendEvent) &&
235 (event->error_code == BadMatch ||
236 event->error_code == BadWindow)) return TRUE;
238 /* the clipboard display interacts with external windows, ignore all errors */
239 if (display == clipboard_display) return TRUE;
241 /* ignore a number of errors on gdi display caused by creating/destroying windows */
242 if (display == gdi_display)
244 if (event->error_code == BadDrawable ||
245 event->error_code == BadGC ||
246 event->error_code == BadWindow)
247 return TRUE;
248 #ifdef HAVE_X11_EXTENSIONS_XRENDER_H
249 if (xrender_error_base) /* check for XRender errors */
251 if (event->error_code == xrender_error_base + BadPicture) return TRUE;
253 #endif
255 return FALSE;
259 /***********************************************************************
260 * X11DRV_expect_error
262 * Setup a callback function that will be called on an X error. The
263 * callback must return non-zero if the error is the one it expected.
265 void X11DRV_expect_error( Display *display, x11drv_error_callback callback, void *arg )
267 pthread_mutex_lock( &error_mutex );
268 XLockDisplay( display );
269 err_callback = callback;
270 err_callback_display = display;
271 err_callback_arg = arg;
272 err_callback_result = 0;
273 err_serial = NextRequest(display);
277 /***********************************************************************
278 * X11DRV_check_error
280 * Check if an expected X11 error occurred; return non-zero if yes.
281 * The caller is responsible for calling XSync first if necessary.
283 int X11DRV_check_error(void)
285 int res = err_callback_result;
286 err_callback = NULL;
287 XUnlockDisplay( err_callback_display );
288 pthread_mutex_unlock( &error_mutex );
289 return res;
293 /***********************************************************************
294 * error_handler
296 static int error_handler( Display *display, XErrorEvent *error_evt )
298 if (err_callback && display == err_callback_display &&
299 (!error_evt->serial || error_evt->serial >= err_serial))
301 if ((err_callback_result = err_callback( display, error_evt, err_callback_arg )))
303 TRACE( "got expected error %d req %d\n",
304 error_evt->error_code, error_evt->request_code );
305 return 0;
308 if (ignore_error( display, error_evt ))
310 TRACE( "got ignored error %d req %d\n",
311 error_evt->error_code, error_evt->request_code );
312 return 0;
314 if (TRACE_ON(synchronous))
316 ERR( "X protocol error: serial=%ld, request_code=%d - breaking into debugger\n",
317 error_evt->serial, error_evt->request_code );
318 assert( 0 );
320 old_error_handler( display, error_evt );
321 return 0;
324 /***********************************************************************
325 * init_pixmap_formats
327 static void init_pixmap_formats( Display *display )
329 int i, count, max = 32;
330 XPixmapFormatValues *formats = XListPixmapFormats( display, &count );
332 for (i = 0; i < count; i++)
334 TRACE( "depth %u, bpp %u, pad %u\n",
335 formats[i].depth, formats[i].bits_per_pixel, formats[i].scanline_pad );
336 if (formats[i].depth > max) max = formats[i].depth;
338 pixmap_formats = calloc( 1, sizeof(*pixmap_formats) * (max + 1) );
339 for (i = 0; i < count; i++) pixmap_formats[formats[i].depth] = &formats[i];
343 HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
345 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
346 OBJECT_ATTRIBUTES attr;
347 HANDLE ret;
349 attr.Length = sizeof(attr);
350 attr.RootDirectory = root;
351 attr.ObjectName = &nameW;
352 attr.Attributes = 0;
353 attr.SecurityDescriptor = NULL;
354 attr.SecurityQualityOfService = NULL;
356 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
360 HKEY open_hkcu_key( const char *name )
362 WCHAR bufferW[256];
363 static HKEY hkcu;
365 if (!hkcu)
367 char buffer[256];
368 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
369 DWORD i, len = sizeof(sid_data);
370 SID *sid;
372 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
373 return 0;
375 sid = ((TOKEN_USER *)sid_data)->User.Sid;
376 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
377 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
378 sid->IdentifierAuthority.Value[4] ),
379 MAKEWORD( sid->IdentifierAuthority.Value[3],
380 sid->IdentifierAuthority.Value[2] )));
381 for (i = 0; i < sid->SubAuthorityCount; i++)
382 len += sprintf( buffer + len, "-%u", (int)sid->SubAuthority[i] );
384 ascii_to_unicode( bufferW, buffer, len );
385 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
388 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
392 ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
394 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
395 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
397 if (NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
398 info, size, &size ))
399 return 0;
401 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
405 /***********************************************************************
406 * get_config_key
408 * Get a config key from either the app-specific or the default config
410 static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
411 WCHAR *buffer, DWORD size )
413 WCHAR nameW[128];
414 char buf[2048];
415 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
417 asciiz_to_unicode( nameW, name );
419 if (appkey && query_reg_value( appkey, nameW, info, sizeof(buf) ))
421 size = min( info->DataLength, size - sizeof(WCHAR) );
422 memcpy( buffer, info->Data, size );
423 buffer[size / sizeof(WCHAR)] = 0;
424 return 0;
427 if (defkey && query_reg_value( defkey, nameW, info, sizeof(buf) ))
429 size = min( info->DataLength, size - sizeof(WCHAR) );
430 memcpy( buffer, info->Data, size );
431 buffer[size / sizeof(WCHAR)] = 0;
432 return 0;
435 return ERROR_FILE_NOT_FOUND;
439 /***********************************************************************
440 * setup_options
442 * Setup the x11drv options.
444 static void setup_options(void)
446 static const WCHAR x11driverW[] = {'\\','X','1','1',' ','D','r','i','v','e','r',0};
447 WCHAR buffer[MAX_PATH+16], *p, *appname;
448 HKEY hkey, appkey = 0;
449 DWORD len;
451 /* @@ Wine registry key: HKCU\Software\Wine\X11 Driver */
452 hkey = open_hkcu_key( "Software\\Wine\\X11 Driver" );
454 /* open the app-specific key */
456 appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
457 if ((p = wcsrchr( appname, '/' ))) appname = p + 1;
458 if ((p = wcsrchr( appname, '\\' ))) appname = p + 1;
459 len = lstrlenW( appname );
461 if (len && len < MAX_PATH)
463 HKEY tmpkey;
464 int i;
465 for (i = 0; appname[i]; i++) buffer[i] = RtlDowncaseUnicodeChar( appname[i] );
466 buffer[i] = 0;
467 appname = buffer;
468 if ((process_name = malloc( len * 3 + 1 )))
469 ntdll_wcstoumbs( appname, len + 1, process_name, len * 3 + 1, FALSE );
470 memcpy( appname + i, x11driverW, sizeof(x11driverW) );
471 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\X11 Driver */
472 if ((tmpkey = open_hkcu_key( "Software\\Wine\\AppDefaults" )))
474 appkey = reg_open_key( tmpkey, appname, lstrlenW( appname ) * sizeof(WCHAR) );
475 NtClose( tmpkey );
479 if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) ))
480 managed_mode = IS_OPTION_TRUE( buffer[0] );
482 if (!get_config_key( hkey, appkey, "Decorated", buffer, sizeof(buffer) ))
483 decorated_mode = IS_OPTION_TRUE( buffer[0] );
485 if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) ))
486 usexvidmode = IS_OPTION_TRUE( buffer[0] );
488 if (!get_config_key( hkey, appkey, "UseXRandR", buffer, sizeof(buffer) ))
489 usexrandr = IS_OPTION_TRUE( buffer[0] );
491 if (!get_config_key( hkey, appkey, "UseTakeFocus", buffer, sizeof(buffer) ))
492 use_take_focus = IS_OPTION_TRUE( buffer[0] );
494 if (!get_config_key( hkey, appkey, "UsePrimarySelection", buffer, sizeof(buffer) ))
495 use_primary_selection = IS_OPTION_TRUE( buffer[0] );
497 if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) ))
498 use_system_cursors = IS_OPTION_TRUE( buffer[0] );
500 if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) ))
501 show_systray = IS_OPTION_TRUE( buffer[0] );
503 if (!get_config_key( hkey, appkey, "GrabPointer", buffer, sizeof(buffer) ))
504 grab_pointer = IS_OPTION_TRUE( buffer[0] );
506 if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) ))
507 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
509 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
510 default_visual.depth = wcstol( buffer, NULL, 0 );
512 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
513 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
515 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
516 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
518 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
519 use_xim = IS_OPTION_TRUE( buffer[0] );
521 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
522 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
524 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
525 private_color_map = IS_OPTION_TRUE( buffer[0] );
527 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
528 primary_monitor = wcstol( buffer, NULL, 0 );
530 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
531 copy_default_colors = wcstol( buffer, NULL, 0 );
533 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
534 alloc_system_colors = wcstol( buffer, NULL, 0 );
536 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
538 NtClose( appkey );
539 NtClose( hkey );
542 #ifdef SONAME_LIBXCOMPOSITE
544 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
545 MAKE_FUNCPTR(XCompositeQueryExtension)
546 MAKE_FUNCPTR(XCompositeQueryVersion)
547 MAKE_FUNCPTR(XCompositeVersion)
548 MAKE_FUNCPTR(XCompositeRedirectWindow)
549 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
550 MAKE_FUNCPTR(XCompositeUnredirectWindow)
551 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
552 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
553 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
554 #undef MAKE_FUNCPTR
556 static int xcomp_event_base;
557 static int xcomp_error_base;
559 static void X11DRV_XComposite_Init(void)
561 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
562 if (!xcomposite_handle)
564 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
565 usexcomposite = FALSE;
566 return;
569 #define LOAD_FUNCPTR(f) \
570 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
571 LOAD_FUNCPTR(XCompositeQueryExtension);
572 LOAD_FUNCPTR(XCompositeQueryVersion);
573 LOAD_FUNCPTR(XCompositeVersion);
574 LOAD_FUNCPTR(XCompositeRedirectWindow);
575 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
576 LOAD_FUNCPTR(XCompositeUnredirectWindow);
577 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
578 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
579 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
580 #undef LOAD_FUNCPTR
582 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
583 &xcomp_error_base)) {
584 TRACE("XComposite extension could not be queried; disabled\n");
585 dlclose(xcomposite_handle);
586 xcomposite_handle = NULL;
587 usexcomposite = FALSE;
588 return;
590 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
591 return;
593 sym_not_found:
594 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
595 dlclose(xcomposite_handle);
596 xcomposite_handle = NULL;
597 usexcomposite = FALSE;
599 #endif /* defined(SONAME_LIBXCOMPOSITE) */
601 static void init_visuals( Display *display, int screen )
603 int count;
604 XVisualInfo *info;
606 argb_visual.screen = screen;
607 argb_visual.class = TrueColor;
608 argb_visual.depth = 32;
609 argb_visual.red_mask = 0xff0000;
610 argb_visual.green_mask = 0x00ff00;
611 argb_visual.blue_mask = 0x0000ff;
613 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
614 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
615 &argb_visual, &count )))
617 argb_visual = *info;
618 XFree( info );
621 default_visual.screen = screen;
622 if (default_visual.depth) /* depth specified */
624 if (default_visual.depth == 32 && argb_visual.visual)
626 default_visual = argb_visual;
628 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
630 default_visual = *info;
631 XFree( info );
633 else WARN( "no visual found for depth %d\n", default_visual.depth );
636 if (!default_visual.visual)
638 default_visual.depth = DefaultDepth( display, screen );
639 default_visual.visual = DefaultVisual( display, screen );
640 default_visual.visualid = default_visual.visual->visualid;
641 default_visual.class = default_visual.visual->class;
642 default_visual.red_mask = default_visual.visual->red_mask;
643 default_visual.green_mask = default_visual.visual->green_mask;
644 default_visual.blue_mask = default_visual.visual->blue_mask;
645 default_visual.colormap_size = default_visual.visual->map_entries;
646 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
648 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
650 TRACE( "default visual %lx class %u argb %lx\n",
651 default_visual.visualid, default_visual.class, argb_visual.visualid );
654 /***********************************************************************
655 * X11DRV process initialisation routine
657 static NTSTATUS x11drv_init( void *arg )
659 struct init_params *params = arg;
660 Display *display;
661 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
663 if (!libx11)
665 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
666 return STATUS_UNSUCCESSFUL;
668 pXGetEventData = dlsym( libx11, "XGetEventData" );
669 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
670 #ifdef SONAME_LIBXEXT
671 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
672 #endif
674 setup_options();
676 /* Open display */
678 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
679 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
681 client_foreign_window_proc = params->foreign_window_proc;
683 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
684 root_window = DefaultRootWindow( display );
685 gdi_display = display;
686 old_error_handler = XSetErrorHandler( error_handler );
688 init_pixmap_formats( display );
689 init_visuals( display, DefaultScreen( display ));
690 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
692 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
694 init_win_context();
696 if (TRACE_ON(synchronous)) XSynchronize( display, True );
698 xinerama_init( DisplayWidth( display, default_visual.screen ),
699 DisplayHeight( display, default_visual.screen ));
700 X11DRV_Settings_Init();
702 /* initialize XVidMode */
703 X11DRV_XF86VM_Init();
704 /* initialize XRandR */
705 X11DRV_XRandR_Init();
706 #ifdef SONAME_LIBXCOMPOSITE
707 X11DRV_XComposite_Init();
708 #endif
709 X11DRV_XInput2_Init();
711 #ifdef HAVE_XKB
712 if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL );
713 #endif
714 X11DRV_InitKeyboard( gdi_display );
715 if (use_xim) use_xim = X11DRV_InitXIM( input_style );
717 init_user_driver();
718 X11DRV_DisplayDevices_Init(FALSE);
719 *params->show_systray = show_systray;
720 return STATUS_SUCCESS;
724 /***********************************************************************
725 * ThreadDetach (X11DRV.@)
727 void X11DRV_ThreadDetach(void)
729 struct x11drv_thread_data *data = x11drv_thread_data();
731 if (data)
733 vulkan_thread_detach();
734 if (data->xim) XCloseIM( data->xim );
735 if (data->font_set) XFreeFontSet( data->display, data->font_set );
736 XCloseDisplay( data->display );
737 free( data );
738 /* clear data in case we get re-entered from user32 before the thread is truly dead */
739 NtUserGetThreadInfo()->driver_data = 0;
744 /* store the display fd into the message queue */
745 static void set_queue_display_fd( Display *display )
747 HANDLE handle;
748 int ret;
750 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
752 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
753 NtTerminateProcess( 0, 1 );
755 SERVER_START_REQ( set_queue_fd )
757 req->handle = wine_server_obj_handle( handle );
758 ret = wine_server_call( req );
760 SERVER_END_REQ;
761 if (ret)
763 MESSAGE( "x11drv: Can't store handle for display fd\n" );
764 NtTerminateProcess( 0, 1 );
766 NtClose( handle );
770 /***********************************************************************
771 * X11DRV thread initialisation routine
773 struct x11drv_thread_data *x11drv_init_thread_data(void)
775 struct x11drv_thread_data *data = x11drv_thread_data();
777 if (data) return data;
779 if (!(data = calloc( 1, sizeof(*data) )))
781 ERR( "could not create data\n" );
782 NtTerminateProcess( 0, 1 );
784 if (!(data->display = XOpenDisplay(NULL)))
786 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));
787 NtTerminateProcess( 0, 1 );
790 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
792 #ifdef HAVE_XKB
793 if (use_xkb && XkbUseExtension( data->display, NULL, NULL ))
794 XkbSetDetectableAutoRepeat( data->display, True, NULL );
795 #endif
797 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
799 set_queue_display_fd( data->display );
800 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
802 if (use_xim) X11DRV_SetupXIM();
804 return data;
808 /***********************************************************************
809 * SystemParametersInfo (X11DRV.@)
811 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
813 switch (action)
815 case SPI_GETSCREENSAVEACTIVE:
816 if (ptr_param)
818 int timeout, temp;
819 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
820 *(BOOL *)ptr_param = timeout != 0;
821 return TRUE;
823 break;
824 case SPI_SETSCREENSAVEACTIVE:
826 int timeout, interval, prefer_blanking, allow_exposures;
827 static int last_timeout = 15 * 60;
829 XLockDisplay( gdi_display );
830 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
831 &allow_exposures);
832 if (timeout) last_timeout = timeout;
834 timeout = int_param ? last_timeout : 0;
835 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
836 allow_exposures);
837 XUnlockDisplay( gdi_display );
839 break;
841 return FALSE; /* let user32 handle it */
844 NTSTATUS CDECL X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
846 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
847 struct x11_d3dkmt_adapter *adapter;
849 if (!vulkan_funcs)
850 return STATUS_UNSUCCESSFUL;
852 pthread_mutex_lock(&d3dkmt_mutex);
853 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
855 if (adapter->handle == desc->hAdapter)
857 list_remove(&adapter->entry);
858 free(adapter);
859 break;
863 if (list_empty(&x11_d3dkmt_adapters))
865 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
866 d3dkmt_vk_instance = NULL;
868 pthread_mutex_unlock(&d3dkmt_mutex);
869 return STATUS_SUCCESS;
872 /**********************************************************************
873 * X11DRV_D3DKMTSetVidPnSourceOwner
875 NTSTATUS CDECL X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
877 struct d3dkmt_vidpn_source *source, *source2;
878 NTSTATUS status = STATUS_SUCCESS;
879 BOOL found;
880 UINT i;
882 TRACE("(%p)\n", desc);
884 pthread_mutex_lock( &d3dkmt_mutex );
886 /* Check parameters */
887 for (i = 0; i < desc->VidPnSourceCount; ++i)
889 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
891 if (source->id == desc->pVidPnSourceId[i])
893 /* Same device */
894 if (source->device == desc->hDevice)
896 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
897 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED
898 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
899 || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED
900 && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE))
902 status = STATUS_INVALID_PARAMETER;
903 goto done;
906 /* Different devices */
907 else
909 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
910 || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
911 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
912 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
914 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
915 goto done;
921 /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set
922 * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
923 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED)
925 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
926 goto done;
929 /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */
930 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED)
932 status = STATUS_INVALID_PARAMETER;
933 goto done;
937 /* Remove owner */
938 if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId)
940 LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
942 if (source->device == desc->hDevice)
944 list_remove( &source->entry );
945 free( source );
948 goto done;
951 /* Add owner */
952 for (i = 0; i < desc->VidPnSourceCount; ++i)
954 found = FALSE;
955 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
957 if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i])
959 found = TRUE;
960 break;
964 if (found)
965 source->type = desc->pType[i];
966 else
968 source = malloc( sizeof( *source ) );
969 if (!source)
971 status = STATUS_NO_MEMORY;
972 goto done;
975 source->id = desc->pVidPnSourceId[i];
976 source->type = desc->pType[i];
977 source->device = desc->hDevice;
978 list_add_tail( &d3dkmt_vidpn_sources, &source->entry );
982 done:
983 pthread_mutex_unlock( &d3dkmt_mutex );
984 return status;
987 /**********************************************************************
988 * X11DRV_D3DKMTCheckVidPnExclusiveOwnership
990 NTSTATUS CDECL X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
992 struct d3dkmt_vidpn_source *source;
994 TRACE("(%p)\n", desc);
996 if (!desc || !desc->hAdapter)
997 return STATUS_INVALID_PARAMETER;
999 pthread_mutex_lock( &d3dkmt_mutex );
1000 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
1002 if (source->id == desc->VidPnSourceId && source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)
1004 pthread_mutex_unlock( &d3dkmt_mutex );
1005 return STATUS_GRAPHICS_PRESENT_OCCLUDED;
1008 pthread_mutex_unlock( &d3dkmt_mutex );
1009 return STATUS_SUCCESS;
1012 static HANDLE get_display_device_init_mutex(void)
1014 WCHAR bufferW[256];
1015 UNICODE_STRING name = {.Buffer = bufferW};
1016 OBJECT_ATTRIBUTES attr;
1017 char buffer[256];
1018 HANDLE mutex;
1020 snprintf( buffer, ARRAY_SIZE(buffer), "\\Sessions\\%u\\BaseNamedObjects\\display_device_init",
1021 (int)NtCurrentTeb()->Peb->SessionId );
1022 name.Length = name.MaximumLength = asciiz_to_unicode( bufferW, buffer );
1024 InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
1025 if (NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE ) < 0) return 0;
1026 NtWaitForSingleObject( mutex, FALSE, NULL );
1027 return mutex;
1030 static void release_display_device_init_mutex(HANDLE mutex)
1032 NtReleaseMutant( mutex, NULL );
1033 NtClose( mutex );
1036 /* Find the Vulkan device UUID corresponding to a LUID */
1037 static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
1039 static const WCHAR class_guidW[] = {'C','l','a','s','s','G','U','I','D',0};
1040 static const WCHAR devpropkey_gpu_vulkan_uuidW[] =
1042 'P','r','o','p','e','r','t','i','e','s',
1043 '\\','{','2','3','3','A','9','E','F','3','-','A','F','C','4','-','4','A','B','D',
1044 '-','B','5','6','4','-','C','3','2','F','2','1','F','1','5','3','5','C','}',
1045 '\\','0','0','0','2'
1047 static const WCHAR devpropkey_gpu_luidW[] =
1049 'P','r','o','p','e','r','t','i','e','s',
1050 '\\','{','6','0','B','1','9','3','C','B','-','5','2','7','6','-','4','D','0','F',
1051 '-','9','6','F','C','-','F','1','7','3','A','B','A','D','3','E','C','6','}',
1052 '\\','0','0','0','2'
1054 static const WCHAR guid_devclass_displayW[] =
1055 {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-',
1056 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
1057 static const WCHAR pci_keyW[] =
1059 '\\','R','e','g','i','s','t','r','y',
1060 '\\','M','a','c','h','i','n','e',
1061 '\\','S','y','s','t','e','m',
1062 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
1063 '\\','E','n','u','m',
1064 '\\','P','C','I'
1066 char buffer[4096];
1067 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
1068 HKEY subkey, device_key, prop_key, pci_key;
1069 KEY_NODE_INFORMATION *key = (void *)buffer;
1070 DWORD size, i = 0;
1071 HANDLE mutex;
1073 mutex = get_display_device_init_mutex();
1075 pci_key = reg_open_key(NULL, pci_keyW, sizeof(pci_keyW));
1076 while (!NtEnumerateKey(pci_key, i++, KeyNodeInformation, key, sizeof(buffer), &size))
1078 unsigned int j = 0;
1080 if (!(subkey = reg_open_key(pci_key, key->Name, key->NameLength)))
1081 continue;
1083 while (!NtEnumerateKey(subkey, j++, KeyNodeInformation, key, sizeof(buffer), &size))
1085 if (!(device_key = reg_open_key(subkey, key->Name, key->NameLength)))
1086 continue;
1088 size = query_reg_value(device_key, class_guidW, value, sizeof(buffer));
1089 if (size != sizeof(guid_devclass_displayW) ||
1090 wcscmp((WCHAR *)value->Data, guid_devclass_displayW))
1092 NtClose(device_key);
1093 continue;
1096 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_luidW,
1097 sizeof(devpropkey_gpu_luidW))))
1099 NtClose(device_key);
1100 continue;
1103 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1104 NtClose(prop_key);
1105 if (size != sizeof(LUID) || memcmp(value->Data, luid, sizeof(LUID)))
1107 NtClose(device_key);
1108 continue;
1111 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_vulkan_uuidW,
1112 sizeof(devpropkey_gpu_vulkan_uuidW))))
1114 NtClose(device_key);
1115 continue;
1118 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1119 NtClose(prop_key);
1120 if (size != sizeof(GUID))
1122 NtClose(device_key);
1123 continue;
1126 *uuid = *(const GUID *)value->Data;
1127 NtClose(device_key);
1128 NtClose(subkey);
1129 NtClose(pci_key);
1130 release_display_device_init_mutex(mutex);
1131 return TRUE;
1133 NtClose(subkey);
1135 NtClose(pci_key);
1137 release_display_device_init_mutex(mutex);
1138 return FALSE;
1141 NTSTATUS CDECL X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1143 static const char *extensions[] =
1145 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
1146 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
1148 const struct vulkan_funcs *vulkan_funcs;
1149 PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
1150 PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
1151 VkPhysicalDevice *vk_physical_devices = NULL;
1152 VkPhysicalDeviceProperties2 properties2;
1153 NTSTATUS status = STATUS_UNSUCCESSFUL;
1154 UINT device_count, device_idx = 0;
1155 struct x11_d3dkmt_adapter *adapter;
1156 VkInstanceCreateInfo create_info;
1157 VkPhysicalDeviceIDProperties id;
1158 VkResult vr;
1159 GUID uuid;
1161 if (!get_vulkan_uuid_from_luid(&desc->AdapterLuid, &uuid))
1163 WARN("Failed to find Vulkan device with LUID %08x:%08x.\n",
1164 (int)desc->AdapterLuid.HighPart, (int)desc->AdapterLuid.LowPart);
1165 return STATUS_INVALID_PARAMETER;
1168 /* Find the Vulkan device with corresponding UUID */
1169 if (!(vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION)))
1171 WARN("Vulkan is unavailable.\n");
1172 return STATUS_UNSUCCESSFUL;
1175 pthread_mutex_lock(&d3dkmt_mutex);
1177 if (!d3dkmt_vk_instance)
1179 memset(&create_info, 0, sizeof(create_info));
1180 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1181 create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
1182 create_info.ppEnabledExtensionNames = extensions;
1184 vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &d3dkmt_vk_instance);
1185 if (vr != VK_SUCCESS)
1187 WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
1188 goto done;
1192 #define LOAD_VK_FUNC(f) \
1193 if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, #f))) \
1195 WARN("Failed to load " #f ".\n"); \
1196 goto done; \
1199 LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
1200 LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
1201 #undef LOAD_VK_FUNC
1203 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, NULL);
1204 if (vr != VK_SUCCESS || !device_count)
1206 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
1207 goto done;
1210 if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
1211 goto done;
1213 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
1214 if (vr != VK_SUCCESS)
1216 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
1217 goto done;
1220 for (device_idx = 0; device_idx < device_count; ++device_idx)
1222 memset(&id, 0, sizeof(id));
1223 id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1224 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1225 properties2.pNext = &id;
1227 pvkGetPhysicalDeviceProperties2KHR(vk_physical_devices[device_idx], &properties2);
1228 if (!IsEqualGUID(&uuid, id.deviceUUID))
1229 continue;
1231 if (!(adapter = malloc(sizeof(*adapter))))
1233 status = STATUS_NO_MEMORY;
1234 goto done;
1237 adapter->handle = desc->hAdapter;
1238 adapter->vk_device = vk_physical_devices[device_idx];
1239 list_add_head(&x11_d3dkmt_adapters, &adapter->entry);
1240 status = STATUS_SUCCESS;
1241 break;
1244 done:
1245 if (d3dkmt_vk_instance && list_empty(&x11_d3dkmt_adapters))
1247 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
1248 d3dkmt_vk_instance = NULL;
1250 pthread_mutex_unlock(&d3dkmt_mutex);
1251 free(vk_physical_devices);
1252 return status;
1255 NTSTATUS CDECL X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1257 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
1258 PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR;
1259 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget;
1260 VkPhysicalDeviceMemoryProperties2 properties2;
1261 NTSTATUS status = STATUS_INVALID_PARAMETER;
1262 struct x11_d3dkmt_adapter *adapter;
1263 unsigned int i;
1265 desc->Budget = 0;
1266 desc->CurrentUsage = 0;
1267 desc->CurrentReservation = 0;
1268 desc->AvailableForReservation = 0;
1270 if (!vulkan_funcs)
1272 WARN("Vulkan is unavailable.\n");
1273 return STATUS_UNSUCCESSFUL;
1276 pthread_mutex_lock(&d3dkmt_mutex);
1277 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
1279 if (adapter->handle != desc->hAdapter)
1280 continue;
1282 if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
1284 WARN("Failed to load vkGetPhysicalDeviceMemoryProperties2KHR.\n");
1285 status = STATUS_UNSUCCESSFUL;
1286 goto done;
1289 memset(&budget, 0, sizeof(budget));
1290 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1291 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
1292 properties2.pNext = &budget;
1293 pvkGetPhysicalDeviceMemoryProperties2KHR(adapter->vk_device, &properties2);
1294 for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i)
1296 if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL
1297 && properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1298 || (desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL
1299 && !(properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)))
1301 desc->Budget += budget.heapBudget[i];
1302 desc->CurrentUsage += budget.heapUsage[i];
1305 desc->AvailableForReservation = desc->Budget / 2;
1306 status = STATUS_SUCCESS;
1307 break;
1309 done:
1310 pthread_mutex_unlock(&d3dkmt_mutex);
1311 return status;
1314 NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
1316 void *ret_ptr;
1317 ULONG ret_len;
1318 return KeUserModeCallback( id, params, size, &ret_ptr, &ret_len );
1322 NTSTATUS x11drv_client_call( enum client_callback func, UINT arg )
1324 struct client_callback_params params = { .id = func, .arg = arg };
1325 return x11drv_client_func( client_func_callback, &params, sizeof(params) );
1329 const unixlib_entry_t __wine_unix_call_funcs[] =
1331 x11drv_create_desktop,
1332 x11drv_init,
1333 x11drv_systray_clear,
1334 x11drv_systray_dock,
1335 x11drv_systray_hide,
1336 x11drv_systray_init,
1337 x11drv_tablet_attach_queue,
1338 x11drv_tablet_get_packet,
1339 x11drv_tablet_info,
1340 x11drv_tablet_load_info,
1341 x11drv_xim_preedit_state,
1342 x11drv_xim_reset,
1346 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
1349 #ifdef _WIN64
1351 static NTSTATUS x11drv_wow64_init( void *arg )
1353 struct
1355 ULONG foreign_window_proc;
1356 ULONG show_systray;
1357 } *params32 = arg;
1358 struct init_params params;
1360 params.foreign_window_proc = UlongToPtr( params32->foreign_window_proc );
1361 params.show_systray = UlongToPtr( params32->show_systray );
1362 return x11drv_init( &params );
1365 static NTSTATUS x11drv_wow64_systray_clear( void *arg )
1367 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1368 return x11drv_systray_clear( &hwnd );
1371 static NTSTATUS x11drv_wow64_systray_dock( void *arg )
1373 struct
1375 UINT64 event_handle;
1376 ULONG icon;
1377 int cx;
1378 int cy;
1379 ULONG layered;
1380 } *params32 = arg;
1381 struct systray_dock_params params;
1383 params.event_handle = params32->event_handle;
1384 params.icon = UlongToPtr( params32->icon );
1385 params.cx = params32->cx;
1386 params.cy = params32->cy;
1387 params.layered = UlongToPtr( params32->layered );
1388 return x11drv_systray_dock( &params );
1391 static NTSTATUS x11drv_wow64_systray_hide( void *arg )
1393 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1394 return x11drv_systray_hide( &hwnd );
1397 static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg )
1399 FIXME( "%p\n", arg );
1400 return 0;
1403 static NTSTATUS x11drv_wow64_tablet_info( void *arg )
1405 struct
1407 UINT category;
1408 UINT index;
1409 ULONG output;
1410 } *params32 = arg;
1411 struct tablet_info_params params;
1413 params.category = params32->category;
1414 params.index = params32->index;
1415 params.output = UlongToPtr( params32->output );
1416 return x11drv_tablet_info( &params );
1419 static NTSTATUS x11drv_wow64_xim_preedit_state( void *arg )
1421 struct
1423 ULONG hwnd;
1424 BOOL open;
1425 } *params32 = arg;
1426 struct xim_preedit_state_params params;
1428 params.hwnd = UlongToHandle( params32->hwnd );
1429 params.open = params32->open;
1430 return x11drv_xim_preedit_state( &params );
1433 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
1435 x11drv_create_desktop,
1436 x11drv_wow64_init,
1437 x11drv_wow64_systray_clear,
1438 x11drv_wow64_systray_dock,
1439 x11drv_wow64_systray_hide,
1440 x11drv_systray_init,
1441 x11drv_tablet_attach_queue,
1442 x11drv_wow64_tablet_get_packet,
1443 x11drv_wow64_tablet_info,
1444 x11drv_tablet_load_info,
1445 x11drv_wow64_xim_preedit_state,
1446 x11drv_xim_reset,
1449 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
1451 #endif /* _WIN64 */