Wine-Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2019
- 66 participants
- 557 discussions
Aug. 29, 2019
From: Zhiyi Zhang <zzhang(a)codeweavers.com>
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
Signed-off-by: Ken Thomases <ken(a)codeweavers.com>
---
v3: Supersede 169138~169143
Minor style changes
v2: Supersede 167500~167504.
Split GPU initialization patch.
Add DriverDateData registry property to display adapters.
dlls/winemac.drv/Makefile.in | 2 +-
dlls/winemac.drv/cocoa_display.m | 258 +++++++++++++++++++++++++++++++
dlls/winemac.drv/display.c | 206 ++++++++++++++++++++++++
dlls/winemac.drv/macdrv.h | 1 +
dlls/winemac.drv/macdrv_cocoa.h | 17 ++
5 files changed, 483 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 3ffb7d666c6..c6ae9733bdd 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -1,5 +1,5 @@
MODULE = winemac.drv
-IMPORTS = uuid user32 gdi32 advapi32
+IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32
DELAYIMPORTS = ole32 shell32 imm32
EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo $(METAL_LIBS)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 93a0fbca353..b8f27309790 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -103,3 +103,261 @@ void macdrv_free_displays(struct macdrv_display* displays)
{
free(displays);
}
+
+/***********************************************************************
+ * get_entry_property_uint32
+ *
+ * Get an io registry entry property of type uint32 and store it in value parameter.
+ *
+ * Returns non-zero value on failure.
+ */
+static int get_entry_property_uint32(io_registry_entry_t entry, CFStringRef property_name, uint32_t* value)
+{
+ CFDataRef data = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0);
+ if (!data)
+ return -1;
+
+ if (CFGetTypeID(data) != CFDataGetTypeID() || CFDataGetLength(data) != sizeof(uint32_t))
+ {
+ CFRelease(data);
+ return -1;
+ }
+
+ CFDataGetBytes(data, CFRangeMake(0, sizeof(uint32_t)), (UInt8*)value);
+ CFRelease(data);
+ return 0;
+}
+
+/***********************************************************************
+ * get_entry_property_string
+ *
+ * Get an io registry entry property of type string and write it in buffer parameter.
+ *
+ * Returns non-zero value on failure.
+ */
+static int get_entry_property_string(io_registry_entry_t entry, CFStringRef property_name, char* buffer,
+ size_t buffer_size)
+{
+ CFTypeRef type_ref;
+ CFDataRef data_ref;
+ CFStringRef string_ref;
+ size_t length;
+ int ret = -1;
+
+ type_ref = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0);
+ if (!type_ref)
+ goto done;
+
+ if (CFGetTypeID(type_ref) == CFDataGetTypeID())
+ {
+ data_ref = type_ref;
+ length = CFDataGetLength(data_ref);
+ if (length + 1 > buffer_size)
+ goto done;
+ CFDataGetBytes(data_ref, CFRangeMake(0, length), (UInt8*)buffer);
+ buffer[length] = 0;
+ }
+ else if (CFGetTypeID(type_ref) == CFStringGetTypeID())
+ {
+ string_ref = type_ref;
+ if (!CFStringGetCString(string_ref, buffer, buffer_size, kCFStringEncodingUTF8))
+ goto done;
+ }
+ else
+ goto done;
+
+ ret = 0;
+done:
+ if (type_ref)
+ CFRelease(type_ref);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpu_info_from_entry
+ *
+ * Starting from entry, search upwards to find the PCI GPU. And get GPU information from the PCI GPU entry.
+ *
+ * Returns non-zero value on failure.
+ */
+static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_entry_t entry)
+{
+ io_registry_entry_t parent_entry;
+ io_registry_entry_t gpu_entry;
+ kern_return_t result;
+ int ret = -1;
+ char buffer[64];
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ gpu_entry = entry;
+ while (![@"IOPCIDevice" isEqualToString:[(NSString*)IOObjectCopyClass(gpu_entry) autorelease]]
+ || get_entry_property_string(gpu_entry, CFSTR("IOName"), buffer, sizeof(buffer))
+ || strcmp(buffer, "display"))
+ {
+ result = IORegistryEntryGetParentEntry(gpu_entry, kIOServicePlane, &parent_entry);
+ if (gpu_entry != entry)
+ IOObjectRelease(gpu_entry);
+ if (result != kIOReturnSuccess)
+ {
+ [pool release];
+ return ret;
+ }
+
+ gpu_entry = parent_entry;
+ }
+
+ if (IORegistryEntryGetRegistryEntryID(gpu_entry, &gpu->id) != kIOReturnSuccess)
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("vendor-id"), &gpu->vendor_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("device-id"), &gpu->device_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("subsystem-id"), &gpu->subsys_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("revision-id"), &gpu->revision_id))
+ goto done;
+ if (get_entry_property_string(gpu_entry, CFSTR("model"), gpu->name, sizeof(gpu->name)))
+ goto done;
+
+ ret = 0;
+done:
+ if (gpu_entry != entry)
+ IOObjectRelease(gpu_entry);
+ [pool release];
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpu_info_from_display_id
+ *
+ * Get GPU information from a display id.
+ * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable.
+ *
+ * Returns non-zero value on failure.
+ */
+static int macdrv_get_gpu_info_from_display_id(struct macdrv_gpu* gpu, CGDirectDisplayID display_id)
+{
+ io_registry_entry_t entry = CGDisplayIOServicePort(display_id);
+ return macdrv_get_gpu_info_from_entry(gpu, entry);
+}
+
+/***********************************************************************
+ * macdrv_get_gpus_from_iokit
+ *
+ * Get a list of GPUs from IOKit.
+ * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
+{
+ static const int MAX_GPUS = 4;
+ struct macdrv_gpu primary_gpu = {0};
+ io_registry_entry_t entry;
+ io_iterator_t iterator;
+ struct macdrv_gpu* gpus;
+ int integrated_index = -1;
+ int primary_index = 0;
+ int gpu_count = 0;
+ int ret = -1;
+ int i;
+
+ gpus = calloc(MAX_GPUS, sizeof(*gpus));
+ if (!gpus)
+ goto done;
+
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOPCIDevice"), &iterator)
+ != kIOReturnSuccess)
+ goto done;
+
+ while ((entry = IOIteratorNext(iterator)))
+ {
+ if (!macdrv_get_gpu_info_from_entry(&gpus[gpu_count], entry))
+ {
+ gpu_count++;
+ assert(gpu_count < MAX_GPUS);
+ }
+ IOObjectRelease(entry);
+ }
+ IOObjectRelease(iterator);
+
+ macdrv_get_gpu_info_from_display_id(&primary_gpu, CGMainDisplayID());
+
+ /* If there are more than two GPUs and an Intel card exists,
+ * assume an automatic graphics pair exists and hide the integrated GPU */
+ if (gpu_count > 1)
+ {
+ for (i = 0; i < gpu_count; i++)
+ {
+ /* FIXME:
+ * Find integrated GPU without Metal support.
+ * Assuming integrated GPU vendor is Intel for now */
+ if (gpus[i].vendor_id == 0x8086)
+ {
+ integrated_index = i;
+ }
+
+ if (gpus[i].id == primary_gpu.id)
+ {
+ primary_index = i;
+ }
+ }
+
+ if (integrated_index != -1)
+ {
+ if (integrated_index != gpu_count - 1)
+ gpus[integrated_index] = gpus[gpu_count - 1];
+
+ /* FIXME:
+ * Find the dedicated GPU in an automatic graphics switching pair and use that as primary GPU.
+ * Choose the first dedicated GPU as primary */
+ if (primary_index == integrated_index)
+ primary_index = 0;
+ else if (primary_index == gpu_count - 1)
+ primary_index = integrated_index;
+
+ gpu_count--;
+ }
+ }
+
+ /* Make sure the first GPU is primary */
+ if (primary_index)
+ {
+ struct macdrv_gpu tmp;
+ tmp = gpus[0];
+ gpus[0] = gpus[primary_index];
+ gpus[primary_index] = tmp;
+ }
+
+ *new_gpus = gpus;
+ *count = gpu_count;
+ ret = 0;
+done:
+ if (ret)
+ macdrv_free_gpus(gpus);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpus
+ *
+ * Get a list of GPUs currently in the system. The first GPU is primary.
+ * Call macdrv_free_gpus() when you are done using the data.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count)
+{
+ return macdrv_get_gpus_from_iokit(new_gpus, count);
+}
+
+/***********************************************************************
+ * macdrv_free_gpus
+ *
+ * Frees a GPU list allocated from macdrv_get_gpus()
+ */
+void macdrv_free_gpus(struct macdrv_gpu* gpus)
+{
+ if (gpus)
+ free(gpus);
+}
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index ed7766d1d4e..88f8f8f4f33 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -25,6 +25,13 @@
#include "winuser.h"
#include "winreg.h"
#include "ddrawi.h"
+#include "rpc.h"
+#include "initguid.h"
+#include "devguid.h"
+#include "devpkey.h"
+#include "setupapi.h"
+#define WIN32_NO_STATUS
+#include "winternl.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(display);
@@ -47,6 +54,30 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW
static const char initial_mode_key[] = "Initial Display Mode";
static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
+static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
+static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
+static const WCHAR pciW[] = {'P','C','I',0};
+static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
+static const WCHAR guid_fmtW[] = {
+ '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
+ '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
+static const WCHAR gpu_instance_fmtW[] = {
+ 'P','C','I','\\',
+ 'V','E','N','_','%','0','4','X','&',
+ 'D','E','V','_','%','0','4','X','&',
+ 'S','U','B','S','Y','S','_','%','0','8','X','&',
+ 'R','E','V','_','%','0','2','X','\\',
+ '%','0','8','X',0};
+static const WCHAR gpu_hardware_id_fmtW[] = {
+ 'P','C','I','\\',
+ 'V','E','N','_','%','0','4','X','&',
+ 'D','E','V','_','%','0','4','X','&',
+ 'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
+ 'R','E','V','_','0','0',0};
+static const WCHAR video_keyW[] = {
+ 'H','A','R','D','W','A','R','E','\\',
+ 'D','E','V','I','C','E','M','A','P','\\',
+ 'V','I','D','E','O',0};
static CFArrayRef modes;
@@ -1397,3 +1428,178 @@ void macdrv_displays_changed(const macdrv_event *event)
MAKELPARAM(width, height));
}
}
+
+/***********************************************************************
+ * macdrv_init_gpu
+ *
+ * Initialize a GPU instance.
+ *
+ * Return FALSE on failure and TRUE on success.
+ */
+static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index)
+{
+ static const BOOL present = TRUE;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ WCHAR instanceW[MAX_PATH];
+ WCHAR nameW[MAX_PATH];
+ WCHAR bufferW[1024];
+ FILETIME filetime;
+ HKEY hkey = NULL;
+ GUID guid;
+ INT written;
+ DWORD size;
+ BOOL ret = FALSE;
+
+ sprintfW(instanceW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index);
+ MultiByteToWideChar(CP_UTF8, 0, gpu->name, -1, nameW, ARRAY_SIZE(nameW));
+ if (!SetupDiOpenDeviceInfoW(devinfo, instanceW, NULL, 0, &device_data))
+ {
+ SetupDiCreateDeviceInfoW(devinfo, instanceW, &GUID_DEVCLASS_DISPLAY, nameW, NULL, 0, &device_data);
+ if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
+ goto done;
+ }
+
+ /* Write HardwareID registry property, REG_MULTI_SZ */
+ written = sprintfW(bufferW, gpu_hardware_id_fmtW, gpu->vendor_id, gpu->device_id);
+ bufferW[written + 1] = 0;
+ if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)bufferW,
+ (written + 2) * sizeof(WCHAR)))
+ goto done;
+
+ /* Write DEVPKEY_Device_IsPresent property */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
+ (const BYTE *)&present, sizeof(present), 0))
+ goto done;
+
+ /* Open driver key.
+ * This is where HKLM\System\CurrentControlSet\Control\Video\{GPU GUID}\{Adapter Index} links to */
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+
+ /* Write DriverDesc value */
+ if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)nameW, (lstrlenW(nameW) + 1) * sizeof(WCHAR)))
+ goto done;
+ /* Write DriverDateData value, using current time as driver date, needed by Evoland */
+ GetSystemTimeAsFileTime(&filetime);
+ if (RegSetValueExW(hkey, driver_date_dataW, 0, REG_BINARY, (BYTE *)&filetime, sizeof(filetime)))
+ goto done;
+ RegCloseKey(hkey);
+
+ /* Write GUID in VideoID in .../instance/Device Parameters, reuse the GUID if it's existent */
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL);
+
+ size = sizeof(bufferW);
+ if (RegQueryValueExW(hkey, video_idW, 0, NULL, (BYTE *)bufferW, &size))
+ {
+ UuidCreate(&guid);
+ sprintfW(bufferW, guid_fmtW, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
+ guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ if (RegSetValueExW(hkey, video_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto done;
+ }
+
+ ret = TRUE;
+done:
+ RegCloseKey(hkey);
+ if (!ret)
+ ERR("Failed to initialize GPU\n");
+ return ret;
+}
+
+static void prepare_devices(void)
+{
+ static const BOOL not_present = FALSE;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HDEVINFO devinfo;
+ DWORD i = 0;
+
+ /* FIXME:
+ * Currently SetupDiGetClassDevsW with DIGCF_PRESENT is unsupported, So we need to clean up not present devices in
+ * case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
+ * of prefix copying or having devices unplugged. But then we couldn't simply delete GPUs because we need to retain
+ * the same GUID for the same GPU. */
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
+ (const BYTE *)¬_present, sizeof(not_present), 0))
+ ERR("Failed to set GPU present property\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+}
+
+static void cleanup_devices(void)
+{
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HDEVINFO devinfo;
+ DWORD type;
+ DWORD i = 0;
+ BOOL present;
+
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ present = FALSE;
+ SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, &type, (BYTE *)&present,
+ sizeof(present), NULL, 0);
+ if (!present && !SetupDiRemoveDevice(devinfo, &device_data))
+ ERR("Failed to remove GPU\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+}
+
+/***********************************************************************
+ * macdrv_init_display_devices
+ *
+ * Initialize display device registry data.
+ */
+void macdrv_init_display_devices(void)
+{
+ static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
+ HANDLE mutex;
+ struct macdrv_gpu *gpus = NULL;
+ INT gpu_count;
+ INT gpu;
+ HDEVINFO gpu_devinfo = NULL;
+ HKEY video_hkey = NULL;
+ DWORD disposition = 0;
+
+ mutex = CreateMutexW(NULL, FALSE, init_mutexW);
+ WaitForSingleObject(mutex, INFINITE);
+
+ if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey,
+ &disposition))
+ {
+ ERR("Failed to create video device key\n");
+ goto done;
+ }
+
+ /* Avoid unnecessary reinit */
+ if (disposition != REG_CREATED_NEW_KEY)
+ goto done;
+
+ TRACE("\n");
+
+ prepare_devices();
+
+ gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
+
+ /* Initialize GPUs */
+ if (macdrv_get_gpus(&gpus, &gpu_count))
+ goto done;
+
+ for (gpu = 0; gpu < gpu_count; gpu++)
+ {
+ if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu))
+ goto done;
+ }
+
+done:
+ cleanup_devices();
+ SetupDiDestroyDeviceInfoList(gpu_devinfo);
+ RegCloseKey(video_hkey);
+
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+
+ macdrv_free_gpus(gpus);
+}
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 8b2f2cb5a38..b9f58b90da7 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -223,6 +223,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP
extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN;
+extern void macdrv_init_display_devices(void) DECLSPEC_HIDDEN;
/**************************************************************************
* Mac IME driver
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 8ca9b9afa0a..513746fa0ee 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -257,10 +257,27 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
/* display */
+
+/* Represent a physical GPU in the PCI slots */
+struct macdrv_gpu
+{
+ /* PCI GPU io registry entry id */
+ uint64_t id;
+ /* Name, in UTF-8 encoding */
+ char name[128];
+ /* PCI ID */
+ uint32_t vendor_id;
+ uint32_t device_id;
+ uint32_t subsys_id;
+ uint32_t revision_id;
+};
+
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
extern int macdrv_set_display_mode(const struct macdrv_display* display,
CGDisplayModeRef display_mode) DECLSPEC_HIDDEN;
+extern int macdrv_get_gpus(struct macdrv_gpu** gpus, int* count) DECLSPEC_HIDDEN;
+extern void macdrv_free_gpus(struct macdrv_gpu* gpus) DECLSPEC_HIDDEN;
/* event */
--
2.21.0
1
5
[PATCH 1/2 v2] winemac.drv: Translate the WM_DROPFILES point into client coordinates whenever possible.
by Ken Thomases Aug. 29, 2019
by Ken Thomases Aug. 29, 2019
Aug. 29, 2019
From: Akihiro Sagawa <sagawa.aki(a)gmail.com>
This is winemac.drv port of 846a8f6c8dcf7ad0bc72437d7ea79cc9e00c8ab7.
Signed-off-by: Akihiro Sagawa <sagawa.aki(a)gmail.com>
Signed-off-by: Ken Thomases <ken(a)codeweavers.com>
---
v2: Fixed order of arguments in TRACE() to match format string
dlls/winemac.drv/dragdrop.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/winemac.drv/dragdrop.c b/dlls/winemac.drv/dragdrop.c
index 788cb002303..7de50e5881c 100644
--- a/dlls/winemac.drv/dragdrop.c
+++ b/dlls/winemac.drv/dragdrop.c
@@ -455,9 +455,10 @@ BOOL query_drag_drop(macdrv_query* query)
{
dropfiles->pt.x = pt.x;
dropfiles->pt.y = pt.y;
- dropfiles->fNC = FALSE;
+ dropfiles->fNC = !ScreenToClient(hwnd, &dropfiles->pt);
- TRACE("sending WM_DROPFILES: hwnd %p pt %s %s\n", hwnd, wine_dbgstr_point(&pt),
+ TRACE("sending WM_DROPFILES: hwnd %p nc %d pt %s %s\n", hwnd,
+ dropfiles->fNC, wine_dbgstr_point(&dropfiles->pt),
debugstr_w((WCHAR*)((char*)dropfiles + dropfiles->pFiles)));
GlobalUnlock(hdrop);
--
2.21.0
1
1
Aug. 29, 2019
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
configure | 1 +
configure.ac | 1 +
dlls/mfmediaengine/Makefile.in | 3 +
dlls/mfmediaengine/main.c | 141 +++++++++++++++++++++
dlls/mfmediaengine/mediaengine.idl | 26 ++++
dlls/mfmediaengine/mediaengine_classes.idl | 26 ++++
dlls/mfmediaengine/mfmediaengine.spec | 4 +-
dlls/mfmediaengine/tests/Makefile.in | 5 +
dlls/mfmediaengine/tests/mfmediaengine.c | 65 ++++++++++
9 files changed, 270 insertions(+), 2 deletions(-)
create mode 100644 dlls/mfmediaengine/mediaengine.idl
create mode 100644 dlls/mfmediaengine/mediaengine_classes.idl
create mode 100644 dlls/mfmediaengine/tests/Makefile.in
create mode 100644 dlls/mfmediaengine/tests/mfmediaengine.c
diff --git a/configure b/configure
index 82c3611b40..db7db910c0 100755
--- a/configure
+++ b/configure
@@ -20380,6 +20380,7 @@ wine_fn_config_makefile dlls/mf/tests enable_tests
wine_fn_config_makefile dlls/mf3216 enable_mf3216
wine_fn_config_makefile dlls/mferror enable_mferror
wine_fn_config_makefile dlls/mfmediaengine enable_mfmediaengine
+wine_fn_config_makefile dlls/mfmediaengine/tests enable_tests
wine_fn_config_makefile dlls/mfplat enable_mfplat
wine_fn_config_makefile dlls/mfplat/tests enable_tests
wine_fn_config_makefile dlls/mfplay enable_mfplay
diff --git a/configure.ac b/configure.ac
index ef41e94df6..2dbcaebed4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3359,6 +3359,7 @@ WINE_CONFIG_MAKEFILE(dlls/mf/tests)
WINE_CONFIG_MAKEFILE(dlls/mf3216)
WINE_CONFIG_MAKEFILE(dlls/mferror)
WINE_CONFIG_MAKEFILE(dlls/mfmediaengine)
+WINE_CONFIG_MAKEFILE(dlls/mfmediaengine/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplat)
WINE_CONFIG_MAKEFILE(dlls/mfplat/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplay)
diff --git a/dlls/mfmediaengine/Makefile.in b/dlls/mfmediaengine/Makefile.in
index 1654130574..fc84c48a7e 100644
--- a/dlls/mfmediaengine/Makefile.in
+++ b/dlls/mfmediaengine/Makefile.in
@@ -1,7 +1,10 @@
MODULE = mfmediaengine.dll
IMPORTLIB = mfmediaengine
+IMPORTS = mfuuid uuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
main.c
+
+IDL_SRCS = mediaengine_classes.idl
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index 81aaf77e2c..4bca0fe0ba 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -16,11 +16,19 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
+
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
+#include "mfmediaengine.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
switch (reason)
@@ -34,3 +42,136 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
return TRUE;
}
+
+static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactory *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IMFMediaEngineClassFactory) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFMediaEngineClassFactory_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI media_engine_factory_AddRef(IMFMediaEngineClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI media_engine_factory_Release(IMFMediaEngineClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFactory *iface, DWORD flags,
+ IMFAttributes *attributes, IMFMediaEngine **engine)
+{
+ FIXME("(%p, %#x, %p, %p): stub.\n", iface, flags, attributes, engine);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface,
+ IMFMediaTimeRange **range)
+{
+ FIXME("(%p, %p): stub.\n", iface, range);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactory *iface, IMFMediaError **error)
+{
+ FIXME("(%p, %p): stub.\n", iface, error);
+
+ return E_NOTIMPL;
+}
+
+static const IMFMediaEngineClassFactoryVtbl media_engine_factory_vtbl =
+{
+ media_engine_factory_QueryInterface,
+ media_engine_factory_AddRef,
+ media_engine_factory_Release,
+ media_engine_factory_CreateInstance,
+ media_engine_factory_CreateTimeRange,
+ media_engine_factory_CreateError,
+};
+
+static IMFMediaEngineClassFactory media_engine_factory = { &media_engine_factory_vtbl };
+
+static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
+{
+ TRACE("(%s, %p).\n", debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(riid, &IID_IClassFactory) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ IClassFactory_AddRef(iface);
+ *obj = iface;
+ return S_OK;
+ }
+
+ WARN("interface %s not implemented.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI classfactory_Release(IClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
+{
+ TRACE("(%p, %s, %p).\n", outer, debugstr_guid(riid), obj);
+
+ *obj = NULL;
+
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ return IMFMediaEngineClassFactory_QueryInterface(&media_engine_factory, riid, obj);
+}
+
+static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)
+{
+ FIXME("(%d): stub.\n", dolock);
+ return S_OK;
+}
+
+static const struct IClassFactoryVtbl class_factory_vtbl =
+{
+ classfactory_QueryInterface,
+ classfactory_AddRef,
+ classfactory_Release,
+ classfactory_CreateInstance,
+ classfactory_LockServer,
+};
+
+static IClassFactory classfactory = { &class_factory_vtbl };
+
+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **obj)
+{
+ TRACE("(%s, %s, %p).\n", debugstr_guid(clsid), debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(clsid, &CLSID_MFMediaEngineClassFactory))
+ return IClassFactory_QueryInterface(&classfactory, riid, obj);
+
+ WARN("Unsupported class %s.\n", debugstr_guid(clsid));
+ *obj = NULL;
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+ return S_FALSE;
+}
diff --git a/dlls/mfmediaengine/mediaengine.idl b/dlls/mfmediaengine/mediaengine.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mediaengine_classes.idl b/dlls/mfmediaengine/mediaengine_classes.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine_classes.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mfmediaengine.spec b/dlls/mfmediaengine/mfmediaengine.spec
index a7e7cb9036..f216d235a3 100644
--- a/dlls/mfmediaengine/mfmediaengine.spec
+++ b/dlls/mfmediaengine/mfmediaengine.spec
@@ -1,3 +1,3 @@
-@ stub DllCanUnloadNow
+@ stdcall -private DllCanUnloadNow()
@ stub DllGetActivationFactory
-@ stub DllGetClassObject
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
diff --git a/dlls/mfmediaengine/tests/Makefile.in b/dlls/mfmediaengine/tests/Makefile.in
new file mode 100644
index 0000000000..3f2bb5a094
--- /dev/null
+++ b/dlls/mfmediaengine/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = mfmediaengine.dll
+IMPORTS = ole32 mfplat mfmediaengine mfuuid
+
+C_SRCS = \
+ mfmediaengine.c
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c
new file mode 100644
index 0000000000..c7fc89f2b1
--- /dev/null
+++ b/dlls/mfmediaengine/tests/mfmediaengine.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "mfapi.h"
+#include "mfmediaengine.h"
+
+#include "wine/heap.h"
+#include "wine/test.h"
+
+static void test_factory(void)
+{
+ IMFMediaEngineClassFactory *factory, *factory2;
+ HRESULT hr;
+
+ CoInitialize(NULL);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory);
+ ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Failed to create class factory, hr %#x.\n", hr);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, (IUnknown *)factory, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory2);
+ ok(hr == CLASS_E_NOAGGREGATION || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Unexpected hr %#x.\n", hr);
+
+ if (factory)
+ IMFMediaEngineClassFactory_Release(factory);
+
+ CoUninitialize();
+}
+
+START_TEST(mfmediaengine)
+{
+ HRESULT hr;
+
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ ok(hr == S_OK, "MFStartup failed: %#x.\n", hr);
+
+ test_factory();
+
+ MFShutdown();
+}
--
2.23.0.rc1
2
1
[PATCH resend 1/2] wineserver: Implement thread priorities with sched_setscheduler / setpriority
by Rémi Bernon Aug. 29, 2019
by Rémi Bernon Aug. 29, 2019
Aug. 29, 2019
This does not report permission errors in order to avoid any breaking
change, only the parameter checks that were already there are returning
errors.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
configure.ac | 19 ++++++
include/config.h.in | 6 ++
server/process.c | 20 +++++-
server/thread.c | 152 ++++++++++++++++++++++++++++++++++++++++----
server/thread.h | 1 +
5 files changed, 184 insertions(+), 14 deletions(-)
diff --git a/configure.ac b/configure.ac
index e58a9242397..f7b85e27f7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2233,6 +2233,25 @@ then
AC_DEFINE(HAVE_SCHED_SETAFFINITY, 1, [Define to 1 if you have the `sched_setaffinity' function.])
fi
+AC_CACHE_CHECK([for sched_setscheduler],wine_cv_have_sched_setscheduler,
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[#define _GNU_SOURCE
+#include <sched.h>]], [[sched_setscheduler(0, 0, 0);]])],[wine_cv_have_sched_setscheduler=yes],[wine_cv_have_sched_setscheduler=no]))
+if test "$wine_cv_have_sched_setscheduler" = "yes"
+then
+ AC_DEFINE(HAVE_SCHED_SETSCHEDULER, 1, [Define to 1 if you have the `sched_setscheduler' function.])
+fi
+
+AC_CACHE_CHECK([for setpriority],wine_cv_have_setpriority,
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[#define _GNU_SOURCE
+#include <sys/resource.h>
+#include <sys/time.h>]], [[setpriority(0, 0, 0);]])],[wine_cv_have_setpriority=yes],[wine_cv_have_setpriority=no]))
+if test "$wine_cv_have_setpriority" = "yes"
+then
+ AC_DEFINE(HAVE_SETPRIORITY, 1, [Define to 1 if you have the `setpriority' function.])
+fi
+
AC_CACHE_CHECK([for fallocate],wine_cv_have_fallocate,
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[#define _GNU_SOURCE
diff --git a/include/config.h.in b/include/config.h.in
index 29ea6f06636..3e10d352856 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -788,6 +788,9 @@
/* Define to 1 if you have the `sched_setaffinity' function. */
#undef HAVE_SCHED_SETAFFINITY
+/* Define to 1 if you have the `sched_setscheduler' function. */
+#undef HAVE_SCHED_SETSCHEDULER
+
/* Define to 1 if you have the `sched_yield' function. */
#undef HAVE_SCHED_YIELD
@@ -812,6 +815,9 @@
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
+/* Define to 1 if you have the `setpriority' function. */
+#undef HAVE_SETPRIORITY
+
/* Define to 1 if you have the `setproctitle' function. */
#undef HAVE_SETPROCTITLE
diff --git a/server/process.c b/server/process.c
index 16bb5d57e72..0c544b46096 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1465,6 +1465,24 @@ DECL_HANDLER(get_process_vm_counters)
release_object( process );
}
+static void set_process_priority( struct process *process, int priority )
+{
+ struct thread *thread;
+
+ if (!process->running_threads)
+ {
+ set_error( STATUS_PROCESS_IS_TERMINATING );
+ return;
+ }
+
+ LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
+ {
+ set_thread_priority( thread, priority, thread->priority );
+ }
+
+ process->priority = priority;
+}
+
static void set_process_affinity( struct process *process, affinity_t affinity )
{
struct thread *thread;
@@ -1490,7 +1508,7 @@ DECL_HANDLER(set_process_info)
if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
{
- if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority;
+ if (req->mask & SET_PROCESS_INFO_PRIORITY) set_process_priority( process, req->priority );
if (req->mask & SET_PROCESS_INFO_AFFINITY) set_process_affinity( process, req->affinity );
release_object( process );
}
diff --git a/server/thread.c b/server/thread.c
index e753c8d0dda..a807f19a42b 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -38,6 +38,12 @@
#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -515,28 +521,147 @@ affinity_t get_thread_affinity( struct thread *thread )
return mask;
}
+#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SETPRIORITY)
+static int get_unix_priority( int priority_class, int priority )
+{
+ switch (priority_class) {
+ case PROCESS_PRIOCLASS_IDLE:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 15;
+ case THREAD_PRIORITY_LOWEST: return 10;
+ case THREAD_PRIORITY_BELOW_NORMAL: return 8;
+ case THREAD_PRIORITY_NORMAL: return 6;
+ case THREAD_PRIORITY_ABOVE_NORMAL: return 4;
+ case THREAD_PRIORITY_HIGHEST: return 2;
+ case THREAD_PRIORITY_TIME_CRITICAL: return -15;
+ }
+ case PROCESS_PRIOCLASS_BELOW_NORMAL:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 15;
+ case THREAD_PRIORITY_LOWEST: return 8;
+ case THREAD_PRIORITY_BELOW_NORMAL: return 6;
+ case THREAD_PRIORITY_NORMAL: return 4;
+ case THREAD_PRIORITY_ABOVE_NORMAL: return 2;
+ case THREAD_PRIORITY_HIGHEST: return 0;
+ case THREAD_PRIORITY_TIME_CRITICAL: return -15;
+ }
+ case PROCESS_PRIOCLASS_NORMAL:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 15;
+ case THREAD_PRIORITY_LOWEST: return 4;
+ case THREAD_PRIORITY_BELOW_NORMAL: return 2;
+ case THREAD_PRIORITY_NORMAL: return 0;
+ case THREAD_PRIORITY_ABOVE_NORMAL: return -2;
+ case THREAD_PRIORITY_HIGHEST: return -4;
+ case THREAD_PRIORITY_TIME_CRITICAL: return -15;
+ }
+ case PROCESS_PRIOCLASS_ABOVE_NORMAL:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 15;
+ case THREAD_PRIORITY_LOWEST: return 0;
+ case THREAD_PRIORITY_BELOW_NORMAL: return -2;
+ case THREAD_PRIORITY_NORMAL: return -4;
+ case THREAD_PRIORITY_ABOVE_NORMAL: return -6;
+ case THREAD_PRIORITY_HIGHEST: return -8;
+ case THREAD_PRIORITY_TIME_CRITICAL: return -15;
+ }
+ case PROCESS_PRIOCLASS_HIGH:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 15;
+ case THREAD_PRIORITY_LOWEST: return -2;
+ case THREAD_PRIORITY_BELOW_NORMAL: return -4;
+ case THREAD_PRIORITY_NORMAL: return -6;
+ case THREAD_PRIORITY_ABOVE_NORMAL: return -8;
+ case THREAD_PRIORITY_HIGHEST: return -10;
+ case THREAD_PRIORITY_TIME_CRITICAL: return -15;
+ }
+ case PROCESS_PRIOCLASS_REALTIME:
+ switch (priority) {
+ case THREAD_PRIORITY_IDLE: return 1;
+ case -7:
+ case -6:
+ case -5:
+ case -4:
+ case -3:
+ case THREAD_PRIORITY_LOWEST:
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ case THREAD_PRIORITY_NORMAL:
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ case THREAD_PRIORITY_HIGHEST:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ return priority + 9;
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ return 16;
+ }
+ }
+ return 0;
+}
+#endif
+
#define THREAD_PRIORITY_REALTIME_HIGHEST 6
#define THREAD_PRIORITY_REALTIME_LOWEST -7
+int set_thread_priority( struct thread* thread, int priority_class, int priority )
+{
+ int max = THREAD_PRIORITY_HIGHEST;
+ int min = THREAD_PRIORITY_LOWEST;
+ if (priority_class == PROCESS_PRIOCLASS_REALTIME)
+ {
+ max = THREAD_PRIORITY_REALTIME_HIGHEST;
+ min = THREAD_PRIORITY_REALTIME_LOWEST;
+ }
+
+ if ((priority < min || priority > max) &&
+ priority != THREAD_PRIORITY_IDLE &&
+ priority != THREAD_PRIORITY_TIME_CRITICAL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (thread->process->priority == priority_class &&
+ thread->priority == priority)
+ return 0;
+
+ thread->priority = priority;
+ if (thread->unix_tid == -1)
+ return 0;
+
+ if (priority_class == PROCESS_PRIOCLASS_REALTIME)
+ {
+#ifdef HAVE_SCHED_SETSCHEDULER
+ struct sched_param param;
+ if (sched_getparam( thread->unix_tid, ¶m ) != 0)
+ return 0; /* ignore errors for now */
+
+ param.sched_priority = get_unix_priority( priority_class, priority );
+ if (sched_setscheduler( thread->unix_tid, SCHED_RR|SCHED_RESET_ON_FORK, ¶m ) == 0)
+ return 0;
+#endif
+ }
+ else
+ {
+#ifdef HAVE_SETPRIORITY
+ if (setpriority( PRIO_PROCESS, thread->unix_tid,
+ get_unix_priority( priority_class, priority ) ) == 0)
+ return 0;
+#endif
+ }
+
+ return 0; /* ignore errors for now */
+}
+
/* set all information about a thread */
static void set_thread_info( struct thread *thread,
const struct set_thread_info_request *req )
{
if (req->mask & SET_THREAD_INFO_PRIORITY)
{
- int max = THREAD_PRIORITY_HIGHEST;
- int min = THREAD_PRIORITY_LOWEST;
- if (thread->process->priority == PROCESS_PRIOCLASS_REALTIME)
- {
- max = THREAD_PRIORITY_REALTIME_HIGHEST;
- min = THREAD_PRIORITY_REALTIME_LOWEST;
- }
- if ((req->priority >= min && req->priority <= max) ||
- req->priority == THREAD_PRIORITY_IDLE ||
- req->priority == THREAD_PRIORITY_TIME_CRITICAL)
- thread->priority = req->priority;
- else
- set_error( STATUS_INVALID_PARAMETER );
+ if (set_thread_priority( thread, thread->process->priority, req->priority ))
+ file_set_error();
}
if (req->mask & SET_THREAD_INFO_AFFINITY)
{
@@ -1367,6 +1492,7 @@ DECL_HANDLER(init_thread)
process->unix_pid = -1; /* can happen with linuxthreads */
init_thread_context( current );
generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, &req->entry );
+ set_thread_priority( current, current->process->priority, current->priority );
set_thread_affinity( current, current->affinity );
}
debug_level = max( debug_level, req->debug_level );
diff --git a/server/thread.h b/server/thread.h
index e10120dcf6e..b81061aea11 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -125,6 +125,7 @@ extern int thread_add_inflight_fd( struct thread *thread, int client, int server
extern int thread_get_inflight_fd( struct thread *thread, int client );
extern struct thread_snapshot *thread_snap( int *count );
extern struct token *thread_get_impersonation_token( struct thread *thread );
+extern int set_thread_priority( struct thread *thread, int priority_class, int priority );
extern int set_thread_affinity( struct thread *thread, affinity_t affinity );
extern int is_cpu_supported( enum cpu_type cpu );
extern unsigned int get_supported_cpu_mask(void);
--
2.23.0.rc1
2
2
Aug. 29, 2019
Sorry for the spam! This series fix a build failure in v2.
Superseded patch 169204 to 169209.
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfplat/main.c | 144 +++++++++++++++++++++++++++++++++++++
dlls/mfplat/mfplat.spec | 1 +
dlls/mfplat/tests/mfplat.c | 41 +++++++++++
include/mfapi.h | 1 +
include/mfobjects.idl | 17 +++++
5 files changed, 204 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index f8f4b502a5..590a19521e 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -7617,3 +7617,147 @@ HRESULT WINAPI CreatePropertyStore(IPropertyStore **store)
return S_OK;
}
+
+struct dxgi_device_manager
+{
+ IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
+ LONG refcount;
+ UINT token;
+};
+
+static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
+{
+ return CONTAINING_RECORD(iface, struct dxgi_device_manager, IMFDXGIDeviceManager_iface);
+}
+
+static HRESULT WINAPI dxgi_device_manager_QueryInterface(IMFDXGIDeviceManager *iface, REFIID riid, void **obj)
+{
+ TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
+
+ if (IsEqualIID(riid, &IID_IMFDXGIDeviceManager) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFDXGIDeviceManager_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dxgi_device_manager_AddRef(IMFDXGIDeviceManager *iface)
+{
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ ULONG refcount = InterlockedIncrement(&manager->refcount);
+
+ TRACE("(%p) ref=%u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
+{
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ ULONG refcount = InterlockedDecrement(&manager->refcount);
+
+ TRACE("(%p) ref=%u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ heap_free(manager);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI dxgi_device_manager_CloseDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_GetVideoService(IMFDXGIDeviceManager *iface, HANDLE device,
+ REFIID riid, void **service)
+{
+ FIXME("(%p, %p, %s, %p): stub.\n", iface, device, debugstr_guid(riid), service);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_LockDevice(IMFDXGIDeviceManager *iface, HANDLE device,
+ REFIID riid, void **ppv, BOOL block)
+{
+ FIXME("(%p, %p, %s, %p, %d): stub.\n", iface, device, wine_dbgstr_guid(riid), ppv, block);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager *iface, HANDLE *device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
+{
+ FIXME("(%p, %p, %u): stub.\n", iface, device, token);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
+{
+ FIXME("(%p, %p): stub.\n", iface, device);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dxgi_device_manager_UnlockDevice(IMFDXGIDeviceManager *iface, HANDLE device, BOOL state)
+{
+ FIXME("(%p, %p, %d): stub.\n", iface, device, state);
+
+ return E_NOTIMPL;
+}
+
+static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
+{
+ dxgi_device_manager_QueryInterface,
+ dxgi_device_manager_AddRef,
+ dxgi_device_manager_Release,
+ dxgi_device_manager_CloseDeviceHandle,
+ dxgi_device_manager_GetVideoService,
+ dxgi_device_manager_LockDevice,
+ dxgi_device_manager_OpenDeviceHandle,
+ dxgi_device_manager_ResetDevice,
+ dxgi_device_manager_TestDevice,
+ dxgi_device_manager_UnlockDevice,
+};
+
+HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
+{
+ struct dxgi_device_manager *object;
+
+ TRACE("(%p, %p).\n", token, manager);
+
+ if (!token || !manager)
+ return E_POINTER;
+
+ object = heap_alloc(sizeof(*object));
+ if (!object)
+ return E_OUTOFMEMORY;
+
+ object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
+ object->refcount = 1;
+ object->token = MFGetSystemTime() >> 16;
+
+ TRACE("Created device manager: %p, token: %u.\n", object, object->token);
+
+ *token = object->token;
+ *manager = &object->IMFDXGIDeviceManager_iface;
+
+ return S_OK;
+}
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 2f16bbd197..cc440c5ee0 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -42,6 +42,7 @@
@ stdcall MFCreateAttributes(ptr long)
@ stub MFCreateAudioMediaType
@ stdcall MFCreateCollection(ptr)
+@ stdcall MFCreateDXGIDeviceManager(ptr ptr)
@ stdcall MFCreateEventQueue(ptr)
@ stdcall MFCreateFile(long long long wstr ptr)
@ stub MFCreateLegacyMediaBufferOnMFMediaBuffer
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index b4ba6b6c57..e0029ab4ff 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -58,6 +58,7 @@ static void _expect_ref(IUnknown *obj, ULONG ref, int line)
static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride,
DWORD width, DWORD lines);
+static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager);
static HRESULT (WINAPI *pMFCreateSourceResolver)(IMFSourceResolver **resolver);
static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream);
static void* (WINAPI *pMFHeapAlloc)(SIZE_T size, ULONG flags, char *file, int line, EAllocationType type);
@@ -510,6 +511,7 @@ static void init_functions(void)
X(MFAddPeriodicCallback);
X(MFAllocateSerialWorkQueue);
X(MFCopyImage);
+ X(MFCreateDXGIDeviceManager);
X(MFCreateSourceResolver);
X(MFCreateMFByteStreamOnStream);
X(MFHeapAlloc);
@@ -3704,6 +3706,44 @@ if (0)
ok(!refcount, "Unexpected refcount %u.\n", refcount);
}
+static void test_dxgi_device_manager(void)
+{
+ IMFDXGIDeviceManager *manager, *manager2;
+ UINT token, token2;
+ HRESULT hr;
+
+ if (!pMFCreateDXGIDeviceManager)
+ {
+ win_skip("MFCreateDXGIDeviceManager not found.\n");
+ return;
+ }
+
+ hr = pMFCreateDXGIDeviceManager(NULL, &manager);
+ ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr);
+
+ token = 0;
+ hr = pMFCreateDXGIDeviceManager(&token, NULL);
+ ok(hr == E_POINTER, "MFCreateDXGIDeviceManager should failed: %#x.\n", hr);
+ ok(!token, "got wrong token: %u.\n", token);
+
+ hr = pMFCreateDXGIDeviceManager(&token, &manager);
+ ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ ok(!!token, "got wrong token: %u.\n", token);
+
+ Sleep(50);
+ token2 = 0;
+ hr = pMFCreateDXGIDeviceManager(&token2, &manager2);
+ ok(hr == S_OK, "MFCreateDXGIDeviceManager failed: %#x.\n", hr);
+ EXPECT_REF(manager2, 1);
+ ok(token2 && token2 != token, "got wrong token: %u, %u.\n", token2, token);
+ ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
+ EXPECT_REF(manager, 1);
+
+ IMFDXGIDeviceManager_Release(manager);
+ IMFDXGIDeviceManager_Release(manager2);
+}
+
START_TEST(mfplat)
{
CoInitialize(NULL);
@@ -3741,6 +3781,7 @@ START_TEST(mfplat)
test_async_create_file();
test_local_handlers();
test_create_property_store();
+ test_dxgi_device_manager();
CoUninitialize();
}
diff --git a/include/mfapi.h b/include/mfapi.h
index 957fb0df9f..f84c051792 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -384,6 +384,7 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
HRESULT WINAPI MFCreateCollection(IMFCollection **collection);
+HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager);
HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
LPCWSTR url, IMFByteStream **bytestream);
diff --git a/include/mfobjects.idl b/include/mfobjects.idl
index 0cc8f422da..203acc770f 100644
--- a/include/mfobjects.idl
+++ b/include/mfobjects.idl
@@ -727,3 +727,20 @@ interface IMFMediaEventQueue : IUnknown
[in] HRESULT status, [in, unique] IUnknown *unk);
HRESULT Shutdown();
}
+
+[
+ object,
+ uuid(eb533d5d-2db6-40f8-97a9-494692014f07),
+ local,
+ pointer_default(unique)
+]
+interface IMFDXGIDeviceManager : IUnknown
+{
+ HRESULT CloseDeviceHandle([in] HANDLE device);
+ HRESULT GetVideoService([in] HANDLE device, [in] REFIID riid, [out] void **service);
+ HRESULT LockDevice([in] HANDLE device, [in] REFIID riid, [out] void **ppv, [in] BOOL block);
+ HRESULT OpenDeviceHandle([out] HANDLE *device);
+ HRESULT ResetDevice([in] IUnknown *device, [in] UINT token);
+ HRESULT TestDevice([in] HANDLE device);
+ HRESULT UnlockDevice([in] HANDLE device, [in] BOOL state);
+}
--
2.23.0.rc1
2
2
Aug. 29, 2019
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
configure | 1 +
configure.ac | 1 +
dlls/mfmediaengine/Makefile.in | 3 +
dlls/mfmediaengine/main.c | 141 +++++++++++++++++++++
dlls/mfmediaengine/mediaengine.idl | 26 ++++
dlls/mfmediaengine/mediaengine_classes.idl | 26 ++++
dlls/mfmediaengine/mfmediaengine.spec | 4 +-
dlls/mfmediaengine/tests/Makefile.in | 5 +
dlls/mfmediaengine/tests/mfmediaengine.c | 65 ++++++++++
9 files changed, 270 insertions(+), 2 deletions(-)
create mode 100644 dlls/mfmediaengine/mediaengine.idl
create mode 100644 dlls/mfmediaengine/mediaengine_classes.idl
create mode 100644 dlls/mfmediaengine/tests/Makefile.in
create mode 100644 dlls/mfmediaengine/tests/mfmediaengine.c
diff --git a/configure b/configure
index 82c3611b40..db7db910c0 100755
--- a/configure
+++ b/configure
@@ -20380,6 +20380,7 @@ wine_fn_config_makefile dlls/mf/tests enable_tests
wine_fn_config_makefile dlls/mf3216 enable_mf3216
wine_fn_config_makefile dlls/mferror enable_mferror
wine_fn_config_makefile dlls/mfmediaengine enable_mfmediaengine
+wine_fn_config_makefile dlls/mfmediaengine/tests enable_tests
wine_fn_config_makefile dlls/mfplat enable_mfplat
wine_fn_config_makefile dlls/mfplat/tests enable_tests
wine_fn_config_makefile dlls/mfplay enable_mfplay
diff --git a/configure.ac b/configure.ac
index ef41e94df6..2dbcaebed4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3359,6 +3359,7 @@ WINE_CONFIG_MAKEFILE(dlls/mf/tests)
WINE_CONFIG_MAKEFILE(dlls/mf3216)
WINE_CONFIG_MAKEFILE(dlls/mferror)
WINE_CONFIG_MAKEFILE(dlls/mfmediaengine)
+WINE_CONFIG_MAKEFILE(dlls/mfmediaengine/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplat)
WINE_CONFIG_MAKEFILE(dlls/mfplat/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplay)
diff --git a/dlls/mfmediaengine/Makefile.in b/dlls/mfmediaengine/Makefile.in
index 1654130574..fc84c48a7e 100644
--- a/dlls/mfmediaengine/Makefile.in
+++ b/dlls/mfmediaengine/Makefile.in
@@ -1,7 +1,10 @@
MODULE = mfmediaengine.dll
IMPORTLIB = mfmediaengine
+IMPORTS = mfuuid uuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
main.c
+
+IDL_SRCS = mediaengine_classes.idl
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index 81aaf77e2c..4bca0fe0ba 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -16,11 +16,19 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
+
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
+#include "mfmediaengine.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
switch (reason)
@@ -34,3 +42,136 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
return TRUE;
}
+
+static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactory *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IMFMediaEngineClassFactory) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFMediaEngineClassFactory_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI media_engine_factory_AddRef(IMFMediaEngineClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI media_engine_factory_Release(IMFMediaEngineClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFactory *iface, DWORD flags,
+ IMFAttributes *attributes, IMFMediaEngine **engine)
+{
+ FIXME("(%p, %#x, %p, %p): stub.\n", iface, flags, attributes, engine);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface,
+ IMFMediaTimeRange **range)
+{
+ FIXME("(%p, %p): stub.\n", iface, range);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactory *iface, IMFMediaError **error)
+{
+ FIXME("(%p, %p): stub.\n", iface, error);
+
+ return E_NOTIMPL;
+}
+
+static const IMFMediaEngineClassFactoryVtbl media_engine_factory_vtbl =
+{
+ media_engine_factory_QueryInterface,
+ media_engine_factory_AddRef,
+ media_engine_factory_Release,
+ media_engine_factory_CreateInstance,
+ media_engine_factory_CreateTimeRange,
+ media_engine_factory_CreateError,
+};
+
+static IMFMediaEngineClassFactory media_engine_factory = { &media_engine_factory_vtbl };
+
+static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
+{
+ TRACE("(%s, %p).\n", debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(riid, &IID_IClassFactory) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ IClassFactory_AddRef(iface);
+ *obj = iface;
+ return S_OK;
+ }
+
+ WARN("interface %s not implemented.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI classfactory_Release(IClassFactory *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
+{
+ TRACE("(%p, %s, %p).\n", outer, debugstr_guid(riid), obj);
+
+ *obj = NULL;
+
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ return IMFMediaEngineClassFactory_QueryInterface(&media_engine_factory, riid, obj);
+}
+
+static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)
+{
+ FIXME("(%d): stub.\n", dolock);
+ return S_OK;
+}
+
+static const struct IClassFactoryVtbl class_factory_vtbl =
+{
+ classfactory_QueryInterface,
+ classfactory_AddRef,
+ classfactory_Release,
+ classfactory_CreateInstance,
+ classfactory_LockServer,
+};
+
+static IClassFactory classfactory = { &class_factory_vtbl };
+
+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **obj)
+{
+ TRACE("(%s, %s, %p).\n", debugstr_guid(clsid), debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(clsid, &CLSID_MFMediaEngineClassFactory))
+ return IClassFactory_QueryInterface(&classfactory, riid, obj);
+
+ WARN("Unsupported class %s.\n", debugstr_guid(clsid));
+ *obj = NULL;
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT WINAPI DllCanUnloadNow(void)
+{
+ return S_FALSE;
+}
diff --git a/dlls/mfmediaengine/mediaengine.idl b/dlls/mfmediaengine/mediaengine.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mediaengine_classes.idl b/dlls/mfmediaengine/mediaengine_classes.idl
new file mode 100644
index 0000000000..a04dabe6a8
--- /dev/null
+++ b/dlls/mfmediaengine/mediaengine_classes.idl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#pragma makedep register
+
+[
+ helpstring("Media Engine Class Factory"),
+ threading(both),
+ uuid(b44392da-499b-446b-a4cb-005fead0e6d5)
+]
+coclass MFMediaEngineClassFactory { interface IMFMediaEngineClassFactory; }
diff --git a/dlls/mfmediaengine/mfmediaengine.spec b/dlls/mfmediaengine/mfmediaengine.spec
index a7e7cb9036..f216d235a3 100644
--- a/dlls/mfmediaengine/mfmediaengine.spec
+++ b/dlls/mfmediaengine/mfmediaengine.spec
@@ -1,3 +1,3 @@
-@ stub DllCanUnloadNow
+@ stdcall -private DllCanUnloadNow()
@ stub DllGetActivationFactory
-@ stub DllGetClassObject
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
diff --git a/dlls/mfmediaengine/tests/Makefile.in b/dlls/mfmediaengine/tests/Makefile.in
new file mode 100644
index 0000000000..3f2bb5a094
--- /dev/null
+++ b/dlls/mfmediaengine/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = mfmediaengine.dll
+IMPORTS = ole32 mfplat mfmediaengine mfuuid
+
+C_SRCS = \
+ mfmediaengine.c
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c
new file mode 100644
index 0000000000..c7fc89f2b1
--- /dev/null
+++ b/dlls/mfmediaengine/tests/mfmediaengine.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "mfapi.h"
+#include "mfmediaengine.h"
+
+#include "wine/heap.h"
+#include "wine/test.h"
+
+static void test_factory(void)
+{
+ IMFMediaEngineClassFactory *factory, *factory2;
+ HRESULT hr;
+
+ CoInitialize(NULL);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory);
+ ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Failed to create class factory, hr %#x.\n", hr);
+
+ hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, (IUnknown *)factory, CLSCTX_INPROC_SERVER,
+ &IID_IMFMediaEngineClassFactory, (void **)&factory2);
+ ok(hr == CLASS_E_NOAGGREGATION || broken(hr == REGDB_E_CLASSNOTREG) /* pre-win8 */,
+ "Unexpected hr %#x.\n", hr);
+
+ if (factory)
+ IMFMediaEngineClassFactory_Release(factory);
+
+ CoUninitialize();
+}
+
+START_TEST(mfmediaengine)
+{
+ HRESULT hr;
+
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ ok(hr == S_OK, "MFStartup failed: %#x.\n", hr);
+
+ test_factory();
+
+ MFShutdown();
+}
--
2.23.0.rc1
2
1
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfuuid/mfuuid.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/mfuuid/mfuuid.c b/dlls/mfuuid/mfuuid.c
index 5bfd521aec..c4976d7dc9 100644
--- a/dlls/mfuuid/mfuuid.c
+++ b/dlls/mfuuid/mfuuid.c
@@ -31,3 +31,4 @@
#include "mfapi.h"
#include "mfidl.h"
#include "mfreadwrite.h"
+#include "mfmediaengine.h"
--
2.23.0.rc1
1
0
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
include/Makefile.in | 1 +
include/mfmediaengine.idl | 168 ++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 include/mfmediaengine.idl
diff --git a/include/Makefile.in b/include/Makefile.in
index 94dd8a0425..47a36ff91d 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -371,6 +371,7 @@ SOURCES = \
mfapi.h \
mferror.h \
mfidl.idl \
+ mfmediaengine.idl \
mfobjects.idl \
mfplay.idl \
mfreadwrite.idl \
diff --git a/include/mfmediaengine.idl b/include/mfmediaengine.idl
new file mode 100644
index 0000000000..8a654f0b59
--- /dev/null
+++ b/include/mfmediaengine.idl
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "mfidl.idl";
+
+cpp_quote("EXTERN_GUID(CLSID_MFMediaEngineClassFactory, 0xb44392da, 0x499b, 0x446b, 0xa4, 0xcb, 0x00, 0x5f, 0xea, 0xd0, 0xe6, 0xd5);")
+
+typedef enum MF_MEDIA_ENGINE_ERR
+{
+ MF_MEDIA_ENGINE_ERR_NOERROR = 0,
+ MF_MEDIA_ENGINE_ERR_ABORTED = 1,
+ MF_MEDIA_ENGINE_ERR_NETWORK = 2,
+ MF_MEDIA_ENGINE_ERR_DECODE = 3,
+ MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED = 4,
+ MF_MEDIA_ENGINE_ERR_ENCRYPTED = 5
+} MF_MEDIA_ENGINE_ERR;
+
+typedef enum MF_MEDIA_ENGINE_PRELOAD
+{
+ MF_MEDIA_ENGINE_PRELOAD_MISSING = 0,
+ MF_MEDIA_ENGINE_PRELOAD_EMPTY = 1,
+ MF_MEDIA_ENGINE_PRELOAD_NONE = 2,
+ MF_MEDIA_ENGINE_PRELOAD_METADATA = 3,
+ MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC = 4
+} MF_MEDIA_ENGINE_PRELOAD;
+
+typedef enum MF_MEDIA_ENGINE_CANPLAY
+{
+ MF_MEDIA_ENGINE_CANPLAY_NOT_SUPPORTED = 0,
+ MF_MEDIA_ENGINE_CANPLAY_MAYBE = 1,
+ MF_MEDIA_ENGINE_CANPLAY_PROBABLY = 2,
+} MF_MEDIA_ENGINE_CANPLAY;
+
+typedef struct MFVideoNormalizedRect
+{
+ float left;
+ float top;
+ float right;
+ float bottom;
+} MFVideoNormalizedRect;
+
+[
+ object,
+ uuid(fc0e10d2-ab2a-4501-a951-06bb1075184c),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaError : IUnknown
+{
+ USHORT GetErrorCode();
+ HRESULT GetExtendedErrorCode();
+ HRESULT SetErrorCode([in] MF_MEDIA_ENGINE_ERR error);
+ HRESULT SetExtendedErrorCode([in] HRESULT error);
+}
+
+[
+ object,
+ uuid(7a5e5354-b114-4c72-b991-3131d75032ea),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngineSrcElements : IUnknown
+{
+ DWORD GetLength();
+ HRESULT GetURL([in] DWORD index, [out] BSTR *url);
+ HRESULT GetType([in] DWORD index, [out] BSTR *type);
+ HRESULT GetMedia([in] DWORD index, [out] BSTR *media);
+ HRESULT AddElement([in] BSTR url, [in] BSTR type, [in] BSTR media);
+ HRESULT RemoveAllElements();
+}
+
+[
+ object,
+ uuid(db71a2fc-078a-414e-9df9-8c2531b0aa6c),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaTimeRange : IUnknown
+{
+ DWORD GetLength();
+ HRESULT GetStart([in] DWORD index, [out] double *start);
+ HRESULT GetEnd([in] DWORD index, [out] double *end);
+ BOOL ContainsTime([in] double time);
+ HRESULT AddRange([in] double start, [in] double end);
+ HRESULT Clear();
+}
+
+[
+ object,
+ uuid(98a1b0bb-03eb-4935-ae7c-93c1fa0e1c93),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngine : IUnknown
+{
+ HRESULT GetError([out] IMFMediaError **error);
+ HRESULT SetErrorCode([in] MF_MEDIA_ENGINE_ERR error);
+ HRESULT SetSourceElements([in] IMFMediaEngineSrcElements *elements);
+ HRESULT SetSource([in] BSTR url);
+ HRESULT GetCurrentSource([out] BSTR *url);
+ USHORT GetNetworkState();
+ MF_MEDIA_ENGINE_PRELOAD GetPreload();
+ HRESULT SetPreload([in] MF_MEDIA_ENGINE_PRELOAD preload);
+ HRESULT GetBuffered([out] IMFMediaTimeRange **buffered);
+ HRESULT Load();
+ HRESULT CanPlayType([in] BSTR type, [out] MF_MEDIA_ENGINE_CANPLAY *answer);
+ USHORT GetReadyState();
+ BOOL IsSeeking();
+ cpp_quote("#undef GetCurrentTime")
+ double GetCurrentTime();
+ HRESULT SetCurrentTime([in] double time);
+ double GetStartTime();
+ double GetDuration();
+ BOOL IsPaused();
+ double GetDefaultPlaybackRate();
+ HRESULT SetDefaultPlaybackRate([in] double rate);
+ double GetPlaybackRate();
+ HRESULT SetPlaybackRate([in] double rate);
+ HRESULT GetPlayed([out] IMFMediaTimeRange **played);
+ HRESULT GetSeekable([out] IMFMediaTimeRange **seekable);
+ BOOL IsEnded();
+ BOOL GetAutoPlay();
+ HRESULT SetAutoPlay([in] BOOL autoplay);
+ BOOL GetLoop();
+ HRESULT SetLoop([in] BOOL loop);
+ HRESULT Play();
+ HRESULT Pause();
+ BOOL GetMuted();
+ HRESULT SetMuted([in] BOOL muted);
+ double GetVolume();
+ HRESULT SetVolume([in] double volume);
+ BOOL HasVideo();
+ BOOL HasAudio();
+ HRESULT GetNativeVideoSize([out] DWORD *cx, [out] DWORD *cy);
+ HRESULT GetVideoAspectRatio([out] DWORD *cx, [out] DWORD *cy);
+ HRESULT Shutdown();
+ HRESULT TransferVideoFrame([in] IUnknown *surface, [in] const MFVideoNormalizedRect *src,
+ [in] const RECT *dst, [in] const MFARGB *color);
+ HRESULT OnVideoStreamTick([out] LONGLONG *time);
+}
+
+[
+ object,
+ uuid(4d645ace-26aa-4688-9be1-df3516990b93),
+ local,
+ pointer_default(unique)
+]
+interface IMFMediaEngineClassFactory : IUnknown
+{
+ HRESULT CreateInstance([in] DWORD flags, [in] IMFAttributes *attributes, [out] IMFMediaEngine **engine);
+ HRESULT CreateTimeRange([out] IMFMediaTimeRange **range);
+ HRESULT CreateError([out] IMFMediaError **error);
+}
--
2.23.0.rc1
1
0
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
configure | 2 ++
configure.ac | 1 +
dlls/mfmediaengine/Makefile.in | 7 ++++++
dlls/mfmediaengine/main.c | 36 +++++++++++++++++++++++++++
dlls/mfmediaengine/mfmediaengine.spec | 3 +++
5 files changed, 49 insertions(+)
create mode 100644 dlls/mfmediaengine/Makefile.in
create mode 100644 dlls/mfmediaengine/main.c
create mode 100644 dlls/mfmediaengine/mfmediaengine.spec
diff --git a/configure b/configure
index c06bc4f079..82c3611b40 100755
--- a/configure
+++ b/configure
@@ -1385,6 +1385,7 @@ enable_mciwave
enable_mf
enable_mf3216
enable_mferror
+enable_mfmediaengine
enable_mfplat
enable_mfplay
enable_mfreadwrite
@@ -20378,6 +20379,7 @@ wine_fn_config_makefile dlls/mf enable_mf
wine_fn_config_makefile dlls/mf/tests enable_tests
wine_fn_config_makefile dlls/mf3216 enable_mf3216
wine_fn_config_makefile dlls/mferror enable_mferror
+wine_fn_config_makefile dlls/mfmediaengine enable_mfmediaengine
wine_fn_config_makefile dlls/mfplat enable_mfplat
wine_fn_config_makefile dlls/mfplat/tests enable_tests
wine_fn_config_makefile dlls/mfplay enable_mfplay
diff --git a/configure.ac b/configure.ac
index e58a924239..ef41e94df6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3358,6 +3358,7 @@ WINE_CONFIG_MAKEFILE(dlls/mf)
WINE_CONFIG_MAKEFILE(dlls/mf/tests)
WINE_CONFIG_MAKEFILE(dlls/mf3216)
WINE_CONFIG_MAKEFILE(dlls/mferror)
+WINE_CONFIG_MAKEFILE(dlls/mfmediaengine)
WINE_CONFIG_MAKEFILE(dlls/mfplat)
WINE_CONFIG_MAKEFILE(dlls/mfplat/tests)
WINE_CONFIG_MAKEFILE(dlls/mfplay)
diff --git a/dlls/mfmediaengine/Makefile.in b/dlls/mfmediaengine/Makefile.in
new file mode 100644
index 0000000000..1654130574
--- /dev/null
+++ b/dlls/mfmediaengine/Makefile.in
@@ -0,0 +1,7 @@
+MODULE = mfmediaengine.dll
+IMPORTLIB = mfmediaengine
+
+EXTRADLLFLAGS = -mno-cygwin
+
+C_SRCS = \
+ main.c
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
new file mode 100644
index 0000000000..81aaf77e2c
--- /dev/null
+++ b/dlls/mfmediaengine/main.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(instance);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/dlls/mfmediaengine/mfmediaengine.spec b/dlls/mfmediaengine/mfmediaengine.spec
new file mode 100644
index 0000000000..a7e7cb9036
--- /dev/null
+++ b/dlls/mfmediaengine/mfmediaengine.spec
@@ -0,0 +1,3 @@
+@ stub DllCanUnloadNow
+@ stub DllGetActivationFactory
+@ stub DllGetClassObject
--
2.23.0.rc1
1
0
Aug. 29, 2019
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/mfplat/main.c | 26 +++++++++++++++++++--
dlls/mfplat/tests/Makefile.in | 2 +-
dlls/mfplat/tests/mfplat.c | 44 +++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 590a19521e..5c1d3817bb 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -31,6 +31,7 @@
#include "initguid.h"
#include "ole2.h"
#include "propsys.h"
+#include "dxgi.h"
#include "wine/debug.h"
#include "wine/list.h"
@@ -7623,6 +7624,7 @@ struct dxgi_device_manager
IMFDXGIDeviceManager IMFDXGIDeviceManager_iface;
LONG refcount;
UINT token;
+ IDXGIDevice *device;
};
static struct dxgi_device_manager *impl_from_IMFDXGIDeviceManager(IMFDXGIDeviceManager *iface)
@@ -7666,6 +7668,8 @@ static ULONG WINAPI dxgi_device_manager_Release(IMFDXGIDeviceManager *iface)
if (!refcount)
{
+ if (manager->device)
+ IDXGIDevice_Release(manager->device);
heap_free(manager);
}
@@ -7704,9 +7708,26 @@ static HRESULT WINAPI dxgi_device_manager_OpenDeviceHandle(IMFDXGIDeviceManager
static HRESULT WINAPI dxgi_device_manager_ResetDevice(IMFDXGIDeviceManager *iface, IUnknown *device, UINT token)
{
- FIXME("(%p, %p, %u): stub.\n", iface, device, token);
+ struct dxgi_device_manager *manager = impl_from_IMFDXGIDeviceManager(iface);
+ IDXGIDevice *dxgi_device;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("(%p, %p, %u).\n", iface, device, token);
+
+ if (!device || token != manager->token)
+ return E_INVALIDARG;
+
+ hr = IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
+ if (SUCCEEDED(hr))
+ {
+ if (manager->device)
+ IDXGIDevice_Release(manager->device);
+ manager->device = dxgi_device;
+ }
+ else
+ hr = E_INVALIDARG;
+
+ return hr;
}
static HRESULT WINAPI dxgi_device_manager_TestDevice(IMFDXGIDeviceManager *iface, HANDLE device)
@@ -7753,6 +7774,7 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man
object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
object->refcount = 1;
object->token = MFGetSystemTime() >> 16;
+ object->device = NULL;
TRACE("Created device manager: %p, token: %u.\n", object, object->token);
diff --git a/dlls/mfplat/tests/Makefile.in b/dlls/mfplat/tests/Makefile.in
index c58a0463e5..dafb429142 100644
--- a/dlls/mfplat/tests/Makefile.in
+++ b/dlls/mfplat/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = mfplat.dll
-IMPORTS = ole32 mfplat mfuuid propsys uuid
+IMPORTS = ole32 mfplat mfuuid propsys uuid d3d11
C_SRCS = \
mfplat.c
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index e0029ab4ff..721ec120ef 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -38,7 +38,10 @@
#include "wine/test.h"
#include "wine/heap.h"
+#define D3D11_INIT_GUID
#include "initguid.h"
+#include "d3d11_4.h"
+
DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19);
DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21);
DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22);
@@ -3709,6 +3712,7 @@ if (0)
static void test_dxgi_device_manager(void)
{
IMFDXGIDeviceManager *manager, *manager2;
+ ID3D11Device *d3d11_dev, *d3d11_dev2;
UINT token, token2;
HRESULT hr;
@@ -3740,7 +3744,47 @@ static void test_dxgi_device_manager(void)
ok(manager != manager2, "got wrong pointer: %p.\n", manager2);
EXPECT_REF(manager, 1);
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
+ NULL, 0, D3D11_SDK_VERSION, &d3d11_dev, NULL, NULL);
+ ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev, 1);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token - 1);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev, 1);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, NULL, token);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)manager2, token);
+ ok(hr == E_INVALIDARG, "IMFDXGIDeviceManager_ResetDevice should failed: %#x.\n", hr);
+ EXPECT_REF(manager2, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev, 2);
+
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0,
+ NULL, 0, D3D11_SDK_VERSION, &d3d11_dev2, NULL, NULL);
+ ok(hr == S_OK, "D3D11CreateDevice failed: %#x.\n", hr);
+ EXPECT_REF(d3d11_dev2, 1);
+ hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11_dev2, token);
+ ok(hr == S_OK, "IMFDXGIDeviceManager_ResetDevice failed: %#x.\n", hr);
+ EXPECT_REF(manager, 1);
+ EXPECT_REF(d3d11_dev2, 2);
+ EXPECT_REF(d3d11_dev, 1);
+
IMFDXGIDeviceManager_Release(manager);
+ EXPECT_REF(d3d11_dev2, 1);
+ ID3D11Device_Release(d3d11_dev);
+ ID3D11Device_Release(d3d11_dev2);
IMFDXGIDeviceManager_Release(manager2);
}
--
2.23.0.rc1
1
0