cmd: DIR command outputs free space for the path.
[wine.git] / dlls / winex11.drv / x11drv_main.c
blobc4d537d6ada0b5da575239ff7660988701e2d1f2
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_fullscreen = FALSE;
78 BOOL managed_mode = TRUE;
79 BOOL decorated_mode = TRUE;
80 BOOL private_color_map = FALSE;
81 int primary_monitor = 0;
82 BOOL client_side_graphics = TRUE;
83 BOOL client_side_with_render = TRUE;
84 BOOL shape_layered_windows = TRUE;
85 int copy_default_colors = 128;
86 int alloc_system_colors = 256;
87 int xrender_error_base = 0;
88 char *process_name = NULL;
89 WNDPROC client_foreign_window_proc = NULL;
91 static x11drv_error_callback err_callback; /* current callback for error */
92 static Display *err_callback_display; /* display callback is set for */
93 static void *err_callback_arg; /* error callback argument */
94 static int err_callback_result; /* error callback result */
95 static unsigned long err_serial; /* serial number of first request */
96 static int (*old_error_handler)( Display *, XErrorEvent * );
97 static BOOL use_xim = TRUE;
98 static WCHAR input_style[20];
100 static pthread_mutex_t d3dkmt_mutex = PTHREAD_MUTEX_INITIALIZER;
101 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
103 struct x11_d3dkmt_adapter
105 D3DKMT_HANDLE handle; /* Kernel mode graphics adapter handle */
106 VkPhysicalDevice vk_device; /* Vulkan physical device */
107 struct list entry; /* List entry */
110 struct d3dkmt_vidpn_source
112 D3DKMT_VIDPNSOURCEOWNER_TYPE type; /* VidPN source owner type */
113 D3DDDI_VIDEO_PRESENT_SOURCE_ID id; /* VidPN present source id */
114 D3DKMT_HANDLE device; /* Kernel mode device context */
115 struct list entry; /* List entry */
118 static VkInstance d3dkmt_vk_instance; /* Vulkan instance for D3DKMT functions */
119 static struct list x11_d3dkmt_adapters = LIST_INIT( x11_d3dkmt_adapters );
120 static struct list d3dkmt_vidpn_sources = LIST_INIT( d3dkmt_vidpn_sources ); /* VidPN source information list */
122 #define IS_OPTION_TRUE(ch) \
123 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
124 #define IS_OPTION_FALSE(ch) \
125 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
127 Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
129 static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
131 "CLIPBOARD",
132 "COMPOUND_TEXT",
133 "EDID",
134 "INCR",
135 "MANAGER",
136 "MULTIPLE",
137 "SELECTION_DATA",
138 "TARGETS",
139 "TEXT",
140 "TIMESTAMP",
141 "UTF8_STRING",
142 "RAW_ASCENT",
143 "RAW_DESCENT",
144 "RAW_CAP_HEIGHT",
145 "Rel X",
146 "Rel Y",
147 "WM_PROTOCOLS",
148 "WM_DELETE_WINDOW",
149 "WM_STATE",
150 "WM_TAKE_FOCUS",
151 "DndProtocol",
152 "DndSelection",
153 "_ICC_PROFILE",
154 "_KDE_NET_WM_STATE_SKIP_SWITCHER",
155 "_MOTIF_WM_HINTS",
156 "_NET_STARTUP_INFO_BEGIN",
157 "_NET_STARTUP_INFO",
158 "_NET_SUPPORTED",
159 "_NET_SYSTEM_TRAY_OPCODE",
160 "_NET_SYSTEM_TRAY_S0",
161 "_NET_SYSTEM_TRAY_VISUAL",
162 "_NET_WM_FULLSCREEN_MONITORS",
163 "_NET_WM_ICON",
164 "_NET_WM_MOVERESIZE",
165 "_NET_WM_NAME",
166 "_NET_WM_PID",
167 "_NET_WM_PING",
168 "_NET_WM_STATE",
169 "_NET_WM_STATE_ABOVE",
170 "_NET_WM_STATE_DEMANDS_ATTENTION",
171 "_NET_WM_STATE_FULLSCREEN",
172 "_NET_WM_STATE_MAXIMIZED_HORZ",
173 "_NET_WM_STATE_MAXIMIZED_VERT",
174 "_NET_WM_STATE_SKIP_PAGER",
175 "_NET_WM_STATE_SKIP_TASKBAR",
176 "_NET_WM_USER_TIME",
177 "_NET_WM_USER_TIME_WINDOW",
178 "_NET_WM_WINDOW_OPACITY",
179 "_NET_WM_WINDOW_TYPE",
180 "_NET_WM_WINDOW_TYPE_DIALOG",
181 "_NET_WM_WINDOW_TYPE_NORMAL",
182 "_NET_WM_WINDOW_TYPE_UTILITY",
183 "_NET_WORKAREA",
184 "_GTK_WORKAREAS_D0",
185 "_XEMBED",
186 "_XEMBED_INFO",
187 "XdndAware",
188 "XdndEnter",
189 "XdndPosition",
190 "XdndStatus",
191 "XdndLeave",
192 "XdndFinished",
193 "XdndDrop",
194 "XdndActionCopy",
195 "XdndActionMove",
196 "XdndActionLink",
197 "XdndActionAsk",
198 "XdndActionPrivate",
199 "XdndSelection",
200 "XdndTypeList",
201 "HTML Format",
202 "WCF_DIF",
203 "WCF_ENHMETAFILE",
204 "WCF_HDROP",
205 "WCF_PENDATA",
206 "WCF_RIFF",
207 "WCF_SYLK",
208 "WCF_TIFF",
209 "WCF_WAVE",
210 "image/bmp",
211 "image/gif",
212 "image/jpeg",
213 "image/png",
214 "text/html",
215 "text/plain",
216 "text/rtf",
217 "text/richtext",
218 "text/uri-list"
221 /***********************************************************************
222 * ignore_error
224 * Check if the X error is one we can ignore.
226 static inline BOOL ignore_error( Display *display, XErrorEvent *event )
228 if ((event->request_code == X_SetInputFocus ||
229 event->request_code == X_ChangeWindowAttributes ||
230 event->request_code == X_ConfigureWindow ||
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, "GrabFullscreen", buffer, sizeof(buffer) ))
501 grab_fullscreen = IS_OPTION_TRUE( buffer[0] );
503 if (!get_config_key( hkey, appkey, "ScreenDepth", buffer, sizeof(buffer) ))
504 default_visual.depth = wcstol( buffer, NULL, 0 );
506 if (!get_config_key( hkey, appkey, "ClientSideGraphics", buffer, sizeof(buffer) ))
507 client_side_graphics = IS_OPTION_TRUE( buffer[0] );
509 if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
510 client_side_with_render = IS_OPTION_TRUE( buffer[0] );
512 if (!get_config_key( hkey, appkey, "UseXIM", buffer, sizeof(buffer) ))
513 use_xim = IS_OPTION_TRUE( buffer[0] );
515 if (!get_config_key( hkey, appkey, "ShapeLayeredWindows", buffer, sizeof(buffer) ))
516 shape_layered_windows = IS_OPTION_TRUE( buffer[0] );
518 if (!get_config_key( hkey, appkey, "PrivateColorMap", buffer, sizeof(buffer) ))
519 private_color_map = IS_OPTION_TRUE( buffer[0] );
521 if (!get_config_key( hkey, appkey, "PrimaryMonitor", buffer, sizeof(buffer) ))
522 primary_monitor = wcstol( buffer, NULL, 0 );
524 if (!get_config_key( hkey, appkey, "CopyDefaultColors", buffer, sizeof(buffer) ))
525 copy_default_colors = wcstol( buffer, NULL, 0 );
527 if (!get_config_key( hkey, appkey, "AllocSystemColors", buffer, sizeof(buffer) ))
528 alloc_system_colors = wcstol( buffer, NULL, 0 );
530 get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
532 NtClose( appkey );
533 NtClose( hkey );
536 #ifdef SONAME_LIBXCOMPOSITE
538 #define MAKE_FUNCPTR(f) typeof(f) * p##f;
539 MAKE_FUNCPTR(XCompositeQueryExtension)
540 MAKE_FUNCPTR(XCompositeQueryVersion)
541 MAKE_FUNCPTR(XCompositeVersion)
542 MAKE_FUNCPTR(XCompositeRedirectWindow)
543 MAKE_FUNCPTR(XCompositeRedirectSubwindows)
544 MAKE_FUNCPTR(XCompositeUnredirectWindow)
545 MAKE_FUNCPTR(XCompositeUnredirectSubwindows)
546 MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip)
547 MAKE_FUNCPTR(XCompositeNameWindowPixmap)
548 #undef MAKE_FUNCPTR
550 static int xcomp_event_base;
551 static int xcomp_error_base;
553 static void X11DRV_XComposite_Init(void)
555 void *xcomposite_handle = dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW);
556 if (!xcomposite_handle)
558 TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
559 usexcomposite = FALSE;
560 return;
563 #define LOAD_FUNCPTR(f) \
564 if((p##f = dlsym(xcomposite_handle, #f)) == NULL) goto sym_not_found
565 LOAD_FUNCPTR(XCompositeQueryExtension);
566 LOAD_FUNCPTR(XCompositeQueryVersion);
567 LOAD_FUNCPTR(XCompositeVersion);
568 LOAD_FUNCPTR(XCompositeRedirectWindow);
569 LOAD_FUNCPTR(XCompositeRedirectSubwindows);
570 LOAD_FUNCPTR(XCompositeUnredirectWindow);
571 LOAD_FUNCPTR(XCompositeUnredirectSubwindows);
572 LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip);
573 LOAD_FUNCPTR(XCompositeNameWindowPixmap);
574 #undef LOAD_FUNCPTR
576 if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base,
577 &xcomp_error_base)) {
578 TRACE("XComposite extension could not be queried; disabled\n");
579 dlclose(xcomposite_handle);
580 xcomposite_handle = NULL;
581 usexcomposite = FALSE;
582 return;
584 TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base);
585 return;
587 sym_not_found:
588 TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE);
589 dlclose(xcomposite_handle);
590 xcomposite_handle = NULL;
591 usexcomposite = FALSE;
593 #endif /* defined(SONAME_LIBXCOMPOSITE) */
595 static void init_visuals( Display *display, int screen )
597 int count;
598 XVisualInfo *info;
600 argb_visual.screen = screen;
601 argb_visual.class = TrueColor;
602 argb_visual.depth = 32;
603 argb_visual.red_mask = 0xff0000;
604 argb_visual.green_mask = 0x00ff00;
605 argb_visual.blue_mask = 0x0000ff;
607 if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask | VisualClassMask |
608 VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
609 &argb_visual, &count )))
611 argb_visual = *info;
612 XFree( info );
615 default_visual.screen = screen;
616 if (default_visual.depth) /* depth specified */
618 if (default_visual.depth == 32 && argb_visual.visual)
620 default_visual = argb_visual;
622 else if ((info = XGetVisualInfo( display, VisualScreenMask | VisualDepthMask, &default_visual, &count )))
624 default_visual = *info;
625 XFree( info );
627 else WARN( "no visual found for depth %d\n", default_visual.depth );
630 if (!default_visual.visual)
632 default_visual.depth = DefaultDepth( display, screen );
633 default_visual.visual = DefaultVisual( display, screen );
634 default_visual.visualid = default_visual.visual->visualid;
635 default_visual.class = default_visual.visual->class;
636 default_visual.red_mask = default_visual.visual->red_mask;
637 default_visual.green_mask = default_visual.visual->green_mask;
638 default_visual.blue_mask = default_visual.visual->blue_mask;
639 default_visual.colormap_size = default_visual.visual->map_entries;
640 default_visual.bits_per_rgb = default_visual.visual->bits_per_rgb;
642 default_colormap = XCreateColormap( display, root_window, default_visual.visual, AllocNone );
644 TRACE( "default visual %lx class %u argb %lx\n",
645 default_visual.visualid, default_visual.class, argb_visual.visualid );
648 /***********************************************************************
649 * X11DRV process initialisation routine
651 static NTSTATUS x11drv_init( void *arg )
653 struct init_params *params = arg;
654 Display *display;
655 void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL );
657 if (!libx11)
659 ERR( "failed to load %s: %s\n", SONAME_LIBX11, dlerror() );
660 return STATUS_UNSUCCESSFUL;
662 pXGetEventData = dlsym( libx11, "XGetEventData" );
663 pXFreeEventData = dlsym( libx11, "XFreeEventData" );
664 #ifdef SONAME_LIBXEXT
665 dlopen( SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL );
666 #endif
668 setup_options();
670 /* Open display */
672 if (!XInitThreads()) ERR( "XInitThreads failed, trouble ahead\n" );
673 if (!(display = XOpenDisplay( NULL ))) return STATUS_UNSUCCESSFUL;
675 client_foreign_window_proc = params->foreign_window_proc;
677 fcntl( ConnectionNumber(display), F_SETFD, 1 ); /* set close on exec flag */
678 root_window = DefaultRootWindow( display );
679 gdi_display = display;
680 old_error_handler = XSetErrorHandler( error_handler );
682 init_pixmap_formats( display );
683 init_visuals( display, DefaultScreen( display ));
684 screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
686 XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
688 init_win_context();
690 if (TRACE_ON(synchronous)) XSynchronize( display, True );
692 xinerama_init( DisplayWidth( display, default_visual.screen ),
693 DisplayHeight( display, default_visual.screen ));
694 X11DRV_Settings_Init();
696 /* initialize XVidMode */
697 X11DRV_XF86VM_Init();
698 /* initialize XRandR */
699 X11DRV_XRandR_Init();
700 #ifdef SONAME_LIBXCOMPOSITE
701 X11DRV_XComposite_Init();
702 #endif
703 X11DRV_XInput2_Init();
705 XkbUseExtension( gdi_display, NULL, NULL );
706 X11DRV_InitKeyboard( gdi_display );
707 if (use_xim) use_xim = xim_init( input_style );
709 init_user_driver();
710 X11DRV_DisplayDevices_Init(FALSE);
711 *params->show_systray = show_systray;
712 return STATUS_SUCCESS;
716 /***********************************************************************
717 * ThreadDetach (X11DRV.@)
719 void X11DRV_ThreadDetach(void)
721 struct x11drv_thread_data *data = x11drv_thread_data();
723 if (data)
725 vulkan_thread_detach();
726 if (data->xim) XCloseIM( data->xim );
727 if (data->font_set) XFreeFontSet( data->display, data->font_set );
728 XCloseDisplay( data->display );
729 free( data );
730 /* clear data in case we get re-entered from user32 before the thread is truly dead */
731 NtUserGetThreadInfo()->driver_data = 0;
736 /* store the display fd into the message queue */
737 static void set_queue_display_fd( Display *display )
739 HANDLE handle;
740 int ret;
742 if (wine_server_fd_to_handle( ConnectionNumber(display), GENERIC_READ | SYNCHRONIZE, 0, &handle ))
744 MESSAGE( "x11drv: Can't allocate handle for display fd\n" );
745 NtTerminateProcess( 0, 1 );
747 SERVER_START_REQ( set_queue_fd )
749 req->handle = wine_server_obj_handle( handle );
750 ret = wine_server_call( req );
752 SERVER_END_REQ;
753 if (ret)
755 MESSAGE( "x11drv: Can't store handle for display fd\n" );
756 NtTerminateProcess( 0, 1 );
758 NtClose( handle );
762 /***********************************************************************
763 * X11DRV thread initialisation routine
765 struct x11drv_thread_data *x11drv_init_thread_data(void)
767 struct x11drv_thread_data *data = x11drv_thread_data();
769 if (data) return data;
771 if (!(data = calloc( 1, sizeof(*data) )))
773 ERR( "could not create data\n" );
774 NtTerminateProcess( 0, 1 );
776 if (!(data->display = XOpenDisplay(NULL)))
778 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));
779 NtTerminateProcess( 0, 1 );
782 fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
784 XkbUseExtension( data->display, NULL, NULL );
785 XkbSetDetectableAutoRepeat( data->display, True, NULL );
786 if (TRACE_ON(synchronous)) XSynchronize( data->display, True );
788 set_queue_display_fd( data->display );
789 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
791 if (use_xim) xim_thread_attach( data );
793 return data;
797 /***********************************************************************
798 * SystemParametersInfo (X11DRV.@)
800 BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
802 switch (action)
804 case SPI_GETSCREENSAVEACTIVE:
805 if (ptr_param)
807 int timeout, temp;
808 XGetScreenSaver(gdi_display, &timeout, &temp, &temp, &temp);
809 *(BOOL *)ptr_param = timeout != 0;
810 return TRUE;
812 break;
813 case SPI_SETSCREENSAVEACTIVE:
815 int timeout, interval, prefer_blanking, allow_exposures;
816 static int last_timeout = 15 * 60;
818 XLockDisplay( gdi_display );
819 XGetScreenSaver(gdi_display, &timeout, &interval, &prefer_blanking,
820 &allow_exposures);
821 if (timeout) last_timeout = timeout;
823 timeout = int_param ? last_timeout : 0;
824 XSetScreenSaver(gdi_display, timeout, interval, prefer_blanking,
825 allow_exposures);
826 XUnlockDisplay( gdi_display );
828 break;
830 return FALSE; /* let user32 handle it */
833 NTSTATUS X11DRV_D3DKMTCloseAdapter( const D3DKMT_CLOSEADAPTER *desc )
835 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
836 struct x11_d3dkmt_adapter *adapter;
838 if (!vulkan_funcs)
839 return STATUS_UNSUCCESSFUL;
841 pthread_mutex_lock(&d3dkmt_mutex);
842 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
844 if (adapter->handle == desc->hAdapter)
846 list_remove(&adapter->entry);
847 free(adapter);
848 break;
852 if (list_empty(&x11_d3dkmt_adapters))
854 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
855 d3dkmt_vk_instance = NULL;
857 pthread_mutex_unlock(&d3dkmt_mutex);
858 return STATUS_SUCCESS;
861 /**********************************************************************
862 * X11DRV_D3DKMTSetVidPnSourceOwner
864 NTSTATUS X11DRV_D3DKMTSetVidPnSourceOwner( const D3DKMT_SETVIDPNSOURCEOWNER *desc )
866 struct d3dkmt_vidpn_source *source, *source2;
867 NTSTATUS status = STATUS_SUCCESS;
868 BOOL found;
869 UINT i;
871 TRACE("(%p)\n", desc);
873 pthread_mutex_lock( &d3dkmt_mutex );
875 /* Check parameters */
876 for (i = 0; i < desc->VidPnSourceCount; ++i)
878 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
880 if (source->id == desc->pVidPnSourceId[i])
882 /* Same device */
883 if (source->device == desc->hDevice)
885 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
886 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED
887 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
888 || (source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED
889 && desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE))
891 status = STATUS_INVALID_PARAMETER;
892 goto done;
895 /* Different devices */
896 else
898 if ((source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
899 || source->type == D3DKMT_VIDPNSOURCEOWNER_EMULATED)
900 && (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE
901 || desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EMULATED))
903 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
904 goto done;
910 /* On Windows, it seems that all video present sources are owned by DMM clients, so any attempt to set
911 * D3DKMT_VIDPNSOURCEOWNER_SHARED come back STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE */
912 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_SHARED)
914 status = STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE;
915 goto done;
918 /* FIXME: D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI unsupported */
919 if (desc->pType[i] == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVEGDI || desc->pType[i] > D3DKMT_VIDPNSOURCEOWNER_EMULATED)
921 status = STATUS_INVALID_PARAMETER;
922 goto done;
926 /* Remove owner */
927 if (!desc->VidPnSourceCount && !desc->pType && !desc->pVidPnSourceId)
929 LIST_FOR_EACH_ENTRY_SAFE( source, source2, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
931 if (source->device == desc->hDevice)
933 list_remove( &source->entry );
934 free( source );
937 goto done;
940 /* Add owner */
941 for (i = 0; i < desc->VidPnSourceCount; ++i)
943 found = FALSE;
944 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
946 if (source->device == desc->hDevice && source->id == desc->pVidPnSourceId[i])
948 found = TRUE;
949 break;
953 if (found)
954 source->type = desc->pType[i];
955 else
957 source = malloc( sizeof( *source ) );
958 if (!source)
960 status = STATUS_NO_MEMORY;
961 goto done;
964 source->id = desc->pVidPnSourceId[i];
965 source->type = desc->pType[i];
966 source->device = desc->hDevice;
967 list_add_tail( &d3dkmt_vidpn_sources, &source->entry );
971 done:
972 pthread_mutex_unlock( &d3dkmt_mutex );
973 return status;
976 /**********************************************************************
977 * X11DRV_D3DKMTCheckVidPnExclusiveOwnership
979 NTSTATUS X11DRV_D3DKMTCheckVidPnExclusiveOwnership( const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *desc )
981 struct d3dkmt_vidpn_source *source;
983 TRACE("(%p)\n", desc);
985 if (!desc || !desc->hAdapter)
986 return STATUS_INVALID_PARAMETER;
988 pthread_mutex_lock( &d3dkmt_mutex );
989 LIST_FOR_EACH_ENTRY( source, &d3dkmt_vidpn_sources, struct d3dkmt_vidpn_source, entry )
991 if (source->id == desc->VidPnSourceId && source->type == D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE)
993 pthread_mutex_unlock( &d3dkmt_mutex );
994 return STATUS_GRAPHICS_PRESENT_OCCLUDED;
997 pthread_mutex_unlock( &d3dkmt_mutex );
998 return STATUS_SUCCESS;
1001 static HANDLE get_display_device_init_mutex(void)
1003 WCHAR bufferW[256];
1004 UNICODE_STRING name = {.Buffer = bufferW};
1005 OBJECT_ATTRIBUTES attr;
1006 char buffer[256];
1007 HANDLE mutex;
1009 snprintf( buffer, ARRAY_SIZE(buffer), "\\Sessions\\%u\\BaseNamedObjects\\display_device_init",
1010 (int)NtCurrentTeb()->Peb->SessionId );
1011 name.Length = name.MaximumLength = asciiz_to_unicode( bufferW, buffer );
1013 InitializeObjectAttributes( &attr, &name, OBJ_OPENIF, NULL, NULL );
1014 if (NtCreateMutant( &mutex, MUTEX_ALL_ACCESS, &attr, FALSE ) < 0) return 0;
1015 NtWaitForSingleObject( mutex, FALSE, NULL );
1016 return mutex;
1019 static void release_display_device_init_mutex(HANDLE mutex)
1021 NtReleaseMutant( mutex, NULL );
1022 NtClose( mutex );
1025 /* Find the Vulkan device UUID corresponding to a LUID */
1026 static BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid )
1028 static const WCHAR class_guidW[] = {'C','l','a','s','s','G','U','I','D',0};
1029 static const WCHAR devpropkey_gpu_vulkan_uuidW[] =
1031 'P','r','o','p','e','r','t','i','e','s',
1032 '\\','{','2','3','3','A','9','E','F','3','-','A','F','C','4','-','4','A','B','D',
1033 '-','B','5','6','4','-','C','3','2','F','2','1','F','1','5','3','5','C','}',
1034 '\\','0','0','0','2'
1036 static const WCHAR devpropkey_gpu_luidW[] =
1038 'P','r','o','p','e','r','t','i','e','s',
1039 '\\','{','6','0','B','1','9','3','C','B','-','5','2','7','6','-','4','D','0','F',
1040 '-','9','6','F','C','-','F','1','7','3','A','B','A','D','3','E','C','6','}',
1041 '\\','0','0','0','2'
1043 static const WCHAR guid_devclass_displayW[] =
1044 {'{','4','D','3','6','E','9','6','8','-','E','3','2','5','-','1','1','C','E','-',
1045 'B','F','C','1','-','0','8','0','0','2','B','E','1','0','3','1','8','}',0};
1046 static const WCHAR pci_keyW[] =
1048 '\\','R','e','g','i','s','t','r','y',
1049 '\\','M','a','c','h','i','n','e',
1050 '\\','S','y','s','t','e','m',
1051 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
1052 '\\','E','n','u','m',
1053 '\\','P','C','I'
1055 char buffer[4096];
1056 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
1057 HKEY subkey, device_key, prop_key, pci_key;
1058 KEY_NODE_INFORMATION *key = (void *)buffer;
1059 DWORD size, i = 0;
1060 HANDLE mutex;
1062 mutex = get_display_device_init_mutex();
1064 pci_key = reg_open_key(NULL, pci_keyW, sizeof(pci_keyW));
1065 while (!NtEnumerateKey(pci_key, i++, KeyNodeInformation, key, sizeof(buffer), &size))
1067 unsigned int j = 0;
1069 if (!(subkey = reg_open_key(pci_key, key->Name, key->NameLength)))
1070 continue;
1072 while (!NtEnumerateKey(subkey, j++, KeyNodeInformation, key, sizeof(buffer), &size))
1074 if (!(device_key = reg_open_key(subkey, key->Name, key->NameLength)))
1075 continue;
1077 size = query_reg_value(device_key, class_guidW, value, sizeof(buffer));
1078 if (size != sizeof(guid_devclass_displayW) ||
1079 wcscmp((WCHAR *)value->Data, guid_devclass_displayW))
1081 NtClose(device_key);
1082 continue;
1085 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_luidW,
1086 sizeof(devpropkey_gpu_luidW))))
1088 NtClose(device_key);
1089 continue;
1092 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1093 NtClose(prop_key);
1094 if (size != sizeof(LUID) || memcmp(value->Data, luid, sizeof(LUID)))
1096 NtClose(device_key);
1097 continue;
1100 if (!(prop_key = reg_open_key(device_key, devpropkey_gpu_vulkan_uuidW,
1101 sizeof(devpropkey_gpu_vulkan_uuidW))))
1103 NtClose(device_key);
1104 continue;
1107 size = query_reg_value(prop_key, NULL, value, sizeof(buffer));
1108 NtClose(prop_key);
1109 if (size != sizeof(GUID))
1111 NtClose(device_key);
1112 continue;
1115 *uuid = *(const GUID *)value->Data;
1116 NtClose(device_key);
1117 NtClose(subkey);
1118 NtClose(pci_key);
1119 release_display_device_init_mutex(mutex);
1120 return TRUE;
1122 NtClose(subkey);
1124 NtClose(pci_key);
1126 release_display_device_init_mutex(mutex);
1127 return FALSE;
1130 NTSTATUS X11DRV_D3DKMTOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc )
1132 static const char *extensions[] =
1134 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
1135 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
1137 const struct vulkan_funcs *vulkan_funcs;
1138 PFN_vkGetPhysicalDeviceProperties2KHR pvkGetPhysicalDeviceProperties2KHR;
1139 PFN_vkEnumeratePhysicalDevices pvkEnumeratePhysicalDevices;
1140 VkPhysicalDevice *vk_physical_devices = NULL;
1141 VkPhysicalDeviceProperties2 properties2;
1142 NTSTATUS status = STATUS_UNSUCCESSFUL;
1143 UINT device_count, device_idx = 0;
1144 struct x11_d3dkmt_adapter *adapter;
1145 VkInstanceCreateInfo create_info;
1146 VkPhysicalDeviceIDProperties id;
1147 VkResult vr;
1148 GUID uuid;
1150 if (!get_vulkan_uuid_from_luid(&desc->AdapterLuid, &uuid))
1152 WARN("Failed to find Vulkan device with LUID %08x:%08x.\n",
1153 (int)desc->AdapterLuid.HighPart, (int)desc->AdapterLuid.LowPart);
1154 return STATUS_INVALID_PARAMETER;
1157 /* Find the Vulkan device with corresponding UUID */
1158 if (!(vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION)))
1160 WARN("Vulkan is unavailable.\n");
1161 return STATUS_UNSUCCESSFUL;
1164 pthread_mutex_lock(&d3dkmt_mutex);
1166 if (!d3dkmt_vk_instance)
1168 memset(&create_info, 0, sizeof(create_info));
1169 create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
1170 create_info.enabledExtensionCount = ARRAY_SIZE(extensions);
1171 create_info.ppEnabledExtensionNames = extensions;
1173 vr = vulkan_funcs->p_vkCreateInstance(&create_info, NULL, &d3dkmt_vk_instance);
1174 if (vr != VK_SUCCESS)
1176 WARN("Failed to create a Vulkan instance, vr %d.\n", vr);
1177 goto done;
1181 #define LOAD_VK_FUNC(f) \
1182 if (!(p##f = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, #f))) \
1184 WARN("Failed to load " #f ".\n"); \
1185 goto done; \
1188 LOAD_VK_FUNC(vkEnumeratePhysicalDevices)
1189 LOAD_VK_FUNC(vkGetPhysicalDeviceProperties2KHR)
1190 #undef LOAD_VK_FUNC
1192 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, NULL);
1193 if (vr != VK_SUCCESS || !device_count)
1195 WARN("No Vulkan device found, vr %d, device_count %d.\n", vr, device_count);
1196 goto done;
1199 if (!(vk_physical_devices = calloc(device_count, sizeof(*vk_physical_devices))))
1200 goto done;
1202 vr = pvkEnumeratePhysicalDevices(d3dkmt_vk_instance, &device_count, vk_physical_devices);
1203 if (vr != VK_SUCCESS)
1205 WARN("vkEnumeratePhysicalDevices failed, vr %d.\n", vr);
1206 goto done;
1209 for (device_idx = 0; device_idx < device_count; ++device_idx)
1211 memset(&id, 0, sizeof(id));
1212 id.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1213 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1214 properties2.pNext = &id;
1216 pvkGetPhysicalDeviceProperties2KHR(vk_physical_devices[device_idx], &properties2);
1217 if (!IsEqualGUID(&uuid, id.deviceUUID))
1218 continue;
1220 if (!(adapter = malloc(sizeof(*adapter))))
1222 status = STATUS_NO_MEMORY;
1223 goto done;
1226 adapter->handle = desc->hAdapter;
1227 adapter->vk_device = vk_physical_devices[device_idx];
1228 list_add_head(&x11_d3dkmt_adapters, &adapter->entry);
1229 status = STATUS_SUCCESS;
1230 break;
1233 done:
1234 if (d3dkmt_vk_instance && list_empty(&x11_d3dkmt_adapters))
1236 vulkan_funcs->p_vkDestroyInstance(d3dkmt_vk_instance, NULL);
1237 d3dkmt_vk_instance = NULL;
1239 pthread_mutex_unlock(&d3dkmt_mutex);
1240 free(vk_physical_devices);
1241 return status;
1244 NTSTATUS X11DRV_D3DKMTQueryVideoMemoryInfo( D3DKMT_QUERYVIDEOMEMORYINFO *desc )
1246 const struct vulkan_funcs *vulkan_funcs = get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION);
1247 PFN_vkGetPhysicalDeviceMemoryProperties2KHR pvkGetPhysicalDeviceMemoryProperties2KHR;
1248 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget;
1249 VkPhysicalDeviceMemoryProperties2 properties2;
1250 NTSTATUS status = STATUS_INVALID_PARAMETER;
1251 struct x11_d3dkmt_adapter *adapter;
1252 unsigned int i;
1254 desc->Budget = 0;
1255 desc->CurrentUsage = 0;
1256 desc->CurrentReservation = 0;
1257 desc->AvailableForReservation = 0;
1259 if (!vulkan_funcs)
1261 WARN("Vulkan is unavailable.\n");
1262 return STATUS_UNSUCCESSFUL;
1265 pthread_mutex_lock(&d3dkmt_mutex);
1266 LIST_FOR_EACH_ENTRY(adapter, &x11_d3dkmt_adapters, struct x11_d3dkmt_adapter, entry)
1268 if (adapter->handle != desc->hAdapter)
1269 continue;
1271 if (!(pvkGetPhysicalDeviceMemoryProperties2KHR = (void *)vulkan_funcs->p_vkGetInstanceProcAddr(d3dkmt_vk_instance, "vkGetPhysicalDeviceMemoryProperties2KHR")))
1273 WARN("Failed to load vkGetPhysicalDeviceMemoryProperties2KHR.\n");
1274 status = STATUS_UNSUCCESSFUL;
1275 goto done;
1278 memset(&budget, 0, sizeof(budget));
1279 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
1280 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
1281 properties2.pNext = &budget;
1282 pvkGetPhysicalDeviceMemoryProperties2KHR(adapter->vk_device, &properties2);
1283 for (i = 0; i < properties2.memoryProperties.memoryHeapCount; ++i)
1285 if ((desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_LOCAL
1286 && properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
1287 || (desc->MemorySegmentGroup == D3DKMT_MEMORY_SEGMENT_GROUP_NON_LOCAL
1288 && !(properties2.memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)))
1290 desc->Budget += budget.heapBudget[i];
1291 desc->CurrentUsage += budget.heapUsage[i];
1294 desc->AvailableForReservation = desc->Budget / 2;
1295 status = STATUS_SUCCESS;
1296 break;
1298 done:
1299 pthread_mutex_unlock(&d3dkmt_mutex);
1300 return status;
1303 NTSTATUS x11drv_client_func( enum x11drv_client_funcs id, const void *params, ULONG size )
1305 void *ret_ptr;
1306 ULONG ret_len;
1307 return KeUserModeCallback( id, params, size, &ret_ptr, &ret_len );
1311 NTSTATUS x11drv_client_call( enum client_callback func, UINT arg )
1313 struct client_callback_params params = { .id = func, .arg = arg };
1314 return x11drv_client_func( client_func_callback, &params, sizeof(params) );
1318 const unixlib_entry_t __wine_unix_call_funcs[] =
1320 x11drv_init,
1321 x11drv_systray_clear,
1322 x11drv_systray_dock,
1323 x11drv_systray_hide,
1324 x11drv_systray_init,
1325 x11drv_tablet_attach_queue,
1326 x11drv_tablet_get_packet,
1327 x11drv_tablet_info,
1328 x11drv_tablet_load_info,
1332 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
1335 #ifdef _WIN64
1337 static NTSTATUS x11drv_wow64_init( void *arg )
1339 struct
1341 ULONG foreign_window_proc;
1342 ULONG show_systray;
1343 } *params32 = arg;
1344 struct init_params params;
1346 params.foreign_window_proc = UlongToPtr( params32->foreign_window_proc );
1347 params.show_systray = UlongToPtr( params32->show_systray );
1348 return x11drv_init( &params );
1351 static NTSTATUS x11drv_wow64_systray_clear( void *arg )
1353 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1354 return x11drv_systray_clear( &hwnd );
1357 static NTSTATUS x11drv_wow64_systray_dock( void *arg )
1359 struct
1361 UINT64 event_handle;
1362 ULONG icon;
1363 int cx;
1364 int cy;
1365 ULONG layered;
1366 } *params32 = arg;
1367 struct systray_dock_params params;
1369 params.event_handle = params32->event_handle;
1370 params.icon = UlongToPtr( params32->icon );
1371 params.cx = params32->cx;
1372 params.cy = params32->cy;
1373 params.layered = UlongToPtr( params32->layered );
1374 return x11drv_systray_dock( &params );
1377 static NTSTATUS x11drv_wow64_systray_hide( void *arg )
1379 HWND hwnd = UlongToPtr( *(ULONG *)arg );
1380 return x11drv_systray_hide( &hwnd );
1383 static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg )
1385 FIXME( "%p\n", arg );
1386 return 0;
1389 static NTSTATUS x11drv_wow64_tablet_info( void *arg )
1391 struct
1393 UINT category;
1394 UINT index;
1395 ULONG output;
1396 } *params32 = arg;
1397 struct tablet_info_params params;
1399 params.category = params32->category;
1400 params.index = params32->index;
1401 params.output = UlongToPtr( params32->output );
1402 return x11drv_tablet_info( &params );
1405 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
1407 x11drv_wow64_init,
1408 x11drv_wow64_systray_clear,
1409 x11drv_wow64_systray_dock,
1410 x11drv_wow64_systray_hide,
1411 x11drv_systray_init,
1412 x11drv_tablet_attach_queue,
1413 x11drv_wow64_tablet_get_packet,
1414 x11drv_wow64_tablet_info,
1415 x11drv_tablet_load_info,
1418 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
1420 #endif /* _WIN64 */