Wine-devel
Threads by month
- ----- 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 2021
- 78 participants
- 929 discussions
06 Aug '21
It doesn't seem very useful to keep things separate, the files are
pretty much dependent from each other anyway and it's only 1k LoC.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
I'm going for more refactoring instead, I understand the intent with the
hid separation but I don't think it's doing anything useful currently.
I doubt we'll ever need something else than an HID backend for this, but
even if we do, it's most likely going to be device based too, and the
only difference will be how we'll read the state from the device file,
which is overall not going to be very different from HID.
dlls/xinput1_1/Makefile.in | 3 +-
dlls/xinput1_2/Makefile.in | 3 +-
dlls/xinput1_3/Makefile.in | 3 +-
dlls/xinput1_3/hid.c | 510 -----------------
dlls/xinput1_3/main.c | 935 ++++++++++++++++++++++++++++++++
dlls/xinput1_3/xinput_main.c | 470 ----------------
dlls/xinput1_3/xinput_private.h | 37 --
dlls/xinput1_4/Makefile.in | 3 +-
dlls/xinput9_1_0/Makefile.in | 3 +-
9 files changed, 940 insertions(+), 1027 deletions(-)
delete mode 100644 dlls/xinput1_3/hid.c
create mode 100644 dlls/xinput1_3/main.c
delete mode 100644 dlls/xinput1_3/xinput_main.c
delete mode 100644 dlls/xinput1_3/xinput_private.h
diff --git a/dlls/xinput1_1/Makefile.in b/dlls/xinput1_1/Makefile.in
index a2b17a248cd..25572e18b21 100644
--- a/dlls/xinput1_1/Makefile.in
+++ b/dlls/xinput1_1/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = hid setupapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- hid.c \
- xinput_main.c
+ main.c
RC_SRCS = version.rc
diff --git a/dlls/xinput1_2/Makefile.in b/dlls/xinput1_2/Makefile.in
index fd38c6f6cc5..3358c2cd3c8 100644
--- a/dlls/xinput1_2/Makefile.in
+++ b/dlls/xinput1_2/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = hid setupapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- hid.c \
- xinput_main.c
+ main.c
RC_SRCS = version.rc
diff --git a/dlls/xinput1_3/Makefile.in b/dlls/xinput1_3/Makefile.in
index 3b4968fb6d8..93281d4e853 100644
--- a/dlls/xinput1_3/Makefile.in
+++ b/dlls/xinput1_3/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = hid setupapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- hid.c \
- xinput_main.c
+ main.c
RC_SRCS = version.rc
diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c
deleted file mode 100644
index 00907b54bed..00000000000
--- a/dlls/xinput1_3/hid.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * The Wine project - Xinput Joystick HID interface
- * Copyright 2018 Aric Stewart
- *
- * 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 <assert.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "wine/debug.h"
-#include "windef.h"
-#include "winbase.h"
-#include "winuser.h"
-#include "winerror.h"
-#include "winreg.h"
-#include "wingdi.h"
-#include "winnls.h"
-#include "winternl.h"
-
-#include "setupapi.h"
-#include "devpkey.h"
-#include "hidusage.h"
-#include "ddk/hidsdi.h"
-#include "initguid.h"
-#include "devguid.h"
-
-#include "xinput.h"
-#include "xinput_private.h"
-
-
-WINE_DEFAULT_DEBUG_CHANNEL(xinput);
-
-#define XINPUT_GAMEPAD_GUIDE 0x0400
-
-struct axis_info
-{
- LONG min;
- LONG range;
- USHORT bits;
-};
-
-struct hid_platform_private {
- PHIDP_PREPARSED_DATA ppd;
- HIDP_CAPS caps;
-
- HANDLE device;
- WCHAR *device_path;
- BOOL enabled;
-
- char *input_report_buf[2];
- char *output_report_buf;
-
- struct axis_info lx, ly, ltrigger, rx, ry, rtrigger;
-};
-
-static DWORD last_check = 0;
-
-static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *free_slot)
-{
- struct hid_platform_private *private;
- int i;
-
- *free_slot = XUSER_MAX_COUNT;
- for (i = XUSER_MAX_COUNT; i > 0; i--)
- {
- if (!(private = controllers[i - 1].platform_private)) *free_slot = i - 1;
- else if (!wcscmp(detail->DevicePath, private->device_path)) return TRUE;
- }
- return FALSE;
-}
-
-static void MarkUsage(struct hid_platform_private *private, WORD usage, LONG min, LONG max, USHORT bits)
-{
- struct axis_info info = {min, max-min, bits};
-
- switch (usage)
- {
- case HID_USAGE_GENERIC_X: private->lx = info; break;
- case HID_USAGE_GENERIC_Y: private->ly = info; break;
- case HID_USAGE_GENERIC_Z: private->ltrigger = info; break;
- case HID_USAGE_GENERIC_RX: private->rx = info; break;
- case HID_USAGE_GENERIC_RY: private->ry = info; break;
- case HID_USAGE_GENERIC_RZ: private->rtrigger = info; break;
- }
-}
-
-static BOOL VerifyGamepad(PHIDP_PREPARSED_DATA ppd, XINPUT_CAPABILITIES *xinput_caps, struct hid_platform_private *private)
-{
- HIDP_BUTTON_CAPS *button_caps;
- HIDP_VALUE_CAPS *value_caps;
- NTSTATUS status;
-
- int i;
- int button_count = 0;
-
- /* Count buttons */
- memset(xinput_caps, 0, sizeof(XINPUT_CAPABILITIES));
-
- if (!(button_caps = malloc(sizeof(*button_caps) * private->caps.NumberInputButtonCaps))) return FALSE;
- status = HidP_GetButtonCaps(HidP_Input, button_caps, &private->caps.NumberInputButtonCaps, ppd);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetButtonCaps returned %#x\n", status);
- else for (i = 0; i < private->caps.NumberInputButtonCaps; i++)
- {
- if (button_caps[i].UsagePage != HID_USAGE_PAGE_BUTTON)
- continue;
- if (button_caps[i].IsRange)
- button_count = max(button_count, button_caps[i].Range.UsageMax);
- else
- button_count = max(button_count, button_caps[i].NotRange.Usage);
- }
- free(button_caps);
- if (button_count < 11)
- WARN("Too few buttons, continuing anyway\n");
- xinput_caps->Gamepad.wButtons = 0xffff;
-
- if (!(value_caps = malloc(sizeof(*value_caps) * private->caps.NumberInputValueCaps))) return FALSE;
- status = HidP_GetValueCaps(HidP_Input, value_caps, &private->caps.NumberInputValueCaps, ppd);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetValueCaps returned %#x\n", status);
- else for (i = 0; i < private->caps.NumberInputValueCaps; i++)
- {
- if (value_caps[i].UsagePage != HID_USAGE_PAGE_GENERIC)
- continue;
- if (value_caps[i].IsRange)
- {
- int u;
- for (u = value_caps[i].Range.UsageMin; u <=value_caps[i].Range.UsageMax; u++)
- MarkUsage(private, u, value_caps[i].LogicalMin, value_caps[i].LogicalMax, value_caps[i].BitSize);
- }
- else
- MarkUsage(private, value_caps[i].NotRange.Usage, value_caps[i].LogicalMin, value_caps[i].LogicalMax, value_caps[i].BitSize);
- }
- free(value_caps);
-
- if (private->ltrigger.bits)
- xinput_caps->Gamepad.bLeftTrigger = (1u << (sizeof(xinput_caps->Gamepad.bLeftTrigger) + 1)) - 1;
- else
- WARN("Missing axis LeftTrigger\n");
- if (private->rtrigger.bits)
- xinput_caps->Gamepad.bRightTrigger = (1u << (sizeof(xinput_caps->Gamepad.bRightTrigger) + 1)) - 1;
- else
- WARN("Missing axis RightTrigger\n");
- if (private->lx.bits)
- xinput_caps->Gamepad.sThumbLX = (1u << (sizeof(xinput_caps->Gamepad.sThumbLX) + 1)) - 1;
- else
- WARN("Missing axis ThumbLX\n");
- if (private->ly.bits)
- xinput_caps->Gamepad.sThumbLY = (1u << (sizeof(xinput_caps->Gamepad.sThumbLY) + 1)) - 1;
- else
- WARN("Missing axis ThumbLY\n");
- if (private->rx.bits)
- xinput_caps->Gamepad.sThumbRX = (1u << (sizeof(xinput_caps->Gamepad.sThumbRX) + 1)) - 1;
- else
- WARN("Missing axis ThumbRX\n");
- if (private->ry.bits)
- xinput_caps->Gamepad.sThumbRY = (1u << (sizeof(xinput_caps->Gamepad.sThumbRY) + 1)) - 1;
- else
- WARN("Missing axis ThumbRY\n");
-
- xinput_caps->Type = XINPUT_DEVTYPE_GAMEPAD;
- xinput_caps->SubType = XINPUT_DEVSUBTYPE_GAMEPAD;
-
- if (private->caps.NumberOutputValueCaps > 0)
- {
- xinput_caps->Flags |= XINPUT_CAPS_FFB_SUPPORTED;
- xinput_caps->Vibration.wLeftMotorSpeed = 255;
- xinput_caps->Vibration.wRightMotorSpeed = 255;
- }
-
- return TRUE;
-}
-
-static BOOL init_controller(xinput_controller *controller, PHIDP_PREPARSED_DATA ppd, HIDP_CAPS *caps, HANDLE device, WCHAR *device_path)
-{
- size_t size;
- struct hid_platform_private *private;
-
- if (!(private = calloc(1, sizeof(struct hid_platform_private)))) return FALSE;
- private->caps = *caps;
- if (!VerifyGamepad(ppd, &controller->caps, private)) goto failed;
-
- TRACE("Found gamepad %s\n", debugstr_w(device_path));
-
- private->ppd = ppd;
- private->device = device;
- if (!(private->input_report_buf[0] = calloc(1, private->caps.InputReportByteLength))) goto failed;
- if (!(private->input_report_buf[1] = calloc(1, private->caps.InputReportByteLength))) goto failed;
- if (!(private->output_report_buf = calloc(1, private->caps.OutputReportByteLength))) goto failed;
- size = (lstrlenW(device_path) + 1) * sizeof(WCHAR);
- if (!(private->device_path = malloc(size))) goto failed;
- memcpy(private->device_path, device_path, size);
- private->enabled = TRUE;
-
- memset(&controller->state, 0, sizeof(controller->state));
- memset(&controller->vibration, 0, sizeof(controller->vibration));
-
- controller->platform_private = private;
- return TRUE;
-
-failed:
- free(private->device_path);
- free(private->input_report_buf[0]);
- free(private->input_report_buf[1]);
- free(private->output_report_buf);
- free(private);
- return FALSE;
-}
-
-void HID_find_gamepads(void)
-{
- char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
- SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
- HDEVINFO device_info_set;
- GUID hid_guid;
- SP_DEVICE_INTERFACE_DATA interface_data;
- PHIDP_PREPARSED_DATA ppd;
- HANDLE device;
- HIDP_CAPS caps;
- NTSTATUS status;
- DWORD idx;
- int i;
-
- idx = GetTickCount();
- if ((idx - last_check) < 2000)
- return;
-
- EnterCriticalSection(&xinput_crit);
-
- if ((idx - last_check) < 2000)
- {
- LeaveCriticalSection(&xinput_crit);
- return;
- }
- last_check = idx;
-
- HidD_GetHidGuid(&hid_guid);
-
- device_info_set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
- detail->cbSize = sizeof(*detail);
-
- ZeroMemory(&interface_data, sizeof(interface_data));
- interface_data.cbSize = sizeof(interface_data);
-
- idx = 0;
- while (SetupDiEnumDeviceInterfaces(device_info_set, NULL, &hid_guid, idx++,
- &interface_data))
- {
- if (!SetupDiGetDeviceInterfaceDetailW(device_info_set, &interface_data, detail, sizeof(buffer), NULL, NULL))
- continue;
-
- if (!wcsstr(detail->DevicePath, L"IG_"))
- continue;
-
- if (find_opened_device(detail, &i)) continue; /* already opened */
- if (i == XUSER_MAX_COUNT) break; /* no more slots */
-
- device = CreateFileW(detail->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
- if (device == INVALID_HANDLE_VALUE)
- continue;
-
- ppd = NULL;
- if (!HidD_GetPreparsedData(device, &ppd))
- WARN("ignoring HID device, HidD_GetPreparsedData failed with error %u\n", GetLastError());
- else if ((status = HidP_GetCaps(ppd, &caps)) != HIDP_STATUS_SUCCESS)
- WARN("ignoring HID device, HidP_GetCaps returned %#x\n", status);
- else if (caps.UsagePage != HID_USAGE_PAGE_GENERIC)
- WARN("ignoring HID device, unsupported usage page %04x\n", caps.UsagePage);
- else if (caps.Usage != HID_USAGE_GENERIC_GAMEPAD && caps.Usage != HID_USAGE_GENERIC_JOYSTICK && caps.Usage != HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER)
- WARN("ignoring HID device, unsupported usage %04x:%04x\n", caps.UsagePage, caps.Usage);
- else if (!init_controller(&controllers[i], ppd, &caps, device, detail->DevicePath))
- WARN("ignoring HID device, failed to initialize\n");
- else
- continue;
-
- CloseHandle(device);
- HidD_FreePreparsedData(ppd);
- }
-
- SetupDiDestroyDeviceInfoList(device_info_set);
- LeaveCriticalSection(&xinput_crit);
-}
-
-static void remove_gamepad(xinput_controller *device)
-{
- EnterCriticalSection(&device->crit);
-
- if (device->platform_private)
- {
- struct hid_platform_private *private = device->platform_private;
-
- device->platform_private = NULL;
-
- CloseHandle(private->device);
- free(private->input_report_buf[0]);
- free(private->input_report_buf[1]);
- free(private->output_report_buf);
- free(private->device_path);
- HidD_FreePreparsedData(private->ppd);
- free(private);
- }
-
- LeaveCriticalSection(&device->crit);
-}
-
-void HID_destroy_gamepads(void)
-{
- int i;
- for (i = 0; i < XUSER_MAX_COUNT; i++)
- remove_gamepad(&controllers[i]);
-}
-
-static SHORT scale_short(LONG value, const struct axis_info *axis)
-{
- return ((((ULONGLONG)(value - axis->min)) * 0xffff) / axis->range) - 32768;
-}
-
-static BYTE scale_byte(LONG value, const struct axis_info *axis)
-{
- return (((ULONGLONG)(value - axis->min)) * 0xff) / axis->range;
-}
-
-void HID_update_state(xinput_controller *device, XINPUT_STATE *state)
-{
- struct hid_platform_private *private = device->platform_private;
- int i;
- char **report_buf = private->input_report_buf, *tmp;
- ULONG report_len = private->caps.InputReportByteLength;
- NTSTATUS status;
-
- USAGE buttons[11];
- ULONG button_length, hat_value;
- LONG value;
-
- if (!private->enabled)
- return;
-
- if (!HidD_GetInputReport(private->device, report_buf[0], report_len))
- {
- if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_HANDLE)
- {
- EnterCriticalSection(&xinput_crit);
- remove_gamepad(device);
- LeaveCriticalSection(&xinput_crit);
- }
- else ERR("Failed to get input report, HidD_GetInputReport failed with error %u\n", GetLastError());
- return;
- }
-
- if (memcmp(report_buf[0], report_buf[1], report_len) != 0)
- {
- device->state.dwPacketNumber++;
- button_length = ARRAY_SIZE(buttons);
- status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, buttons, &button_length, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsages HID_USAGE_PAGE_BUTTON returned %#x\n", status);
-
- device->state.Gamepad.wButtons = 0;
- for (i = 0; i < button_length; i++)
- {
- switch (buttons[i])
- {
- case 1: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
- case 2: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
- case 3: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
- case 4: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
- case 5: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
- case 6: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
- case 7: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
- case 8: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
- case 9: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
- case 10: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
- case 11: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break;
- }
- }
-
- status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, &hat_value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_HATSWITCH returned %#x\n", status);
- else
- {
- switch(hat_value){
- /* 8 1 2
- * 7 0 3
- * 6 5 4 */
- case 0:
- break;
- case 1:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;
- break;
- case 2:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT;
- break;
- case 3:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT;
- break;
- case 4:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN;
- break;
- case 5:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;
- break;
- case 6:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT;
- break;
- case 7:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT;
- break;
- case 8:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP;
- break;
- }
- }
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_X returned %#x\n", status);
- else device->state.Gamepad.sThumbLX = scale_short(value, &private->lx);
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Y returned %#x\n", status);
- else device->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1;
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RX returned %#x\n", status);
- else device->state.Gamepad.sThumbRX = scale_short(value, &private->rx);
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RY returned %#x\n", status);
- else device->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1;
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RZ returned %#x\n", status);
- else device->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger);
-
- status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, private->ppd, report_buf[0], report_len);
- if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Z returned %#x\n", status);
- else device->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger);
- }
-
- tmp = report_buf[0];
- report_buf[0] = report_buf[1];
- report_buf[1] = tmp;
- memcpy(state, &device->state, sizeof(*state));
-}
-
-DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state)
-{
- struct hid_platform_private *private = device->platform_private;
- char *output_report_buf = private->output_report_buf;
- ULONG output_report_len = private->caps.OutputReportByteLength;
-
- if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
- {
- device->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed;
- device->vibration.wRightMotorSpeed = state->wRightMotorSpeed;
-
- if (private->enabled)
- {
- memset(output_report_buf, 0, output_report_len);
- output_report_buf[0] = /* report id */ 0;
- output_report_buf[1] = 0x8;
- output_report_buf[3] = (BYTE)(state->wLeftMotorSpeed / 256);
- output_report_buf[4] = (BYTE)(state->wRightMotorSpeed / 256);
-
- if (!HidD_SetOutputReport(private->device, output_report_buf, output_report_len))
- {
- WARN("unable to set output report, HidD_SetOutputReport failed with error %u\n", GetLastError());
- return GetLastError();
- }
-
- return ERROR_SUCCESS;
- }
- }
-
- return ERROR_SUCCESS;
-}
-
-void HID_enable(xinput_controller* device, BOOL enable)
-{
- struct hid_platform_private *private = device->platform_private;
-
- if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
- {
- if (private->enabled && !enable)
- {
- XINPUT_VIBRATION state;
- state.wLeftMotorSpeed = 0;
- state.wRightMotorSpeed = 0;
- HID_set_state(device, &state);
- }
- else if (!private->enabled && enable)
- {
- HID_set_state(device, &device->vibration);
- }
- }
-
- private->enabled = enable;
-}
diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
new file mode 100644
index 00000000000..6badd74851c
--- /dev/null
+++ b/dlls/xinput1_3/main.c
@@ -0,0 +1,935 @@
+/*
+ * The Wine project - Xinput Joystick Library
+ * Copyright 2008 Andrew Fenn
+ * Copyright 2018 Aric Stewart
+ * Copyright 2021 Rémi Bernon 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 <assert.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winnls.h"
+#include "winternl.h"
+
+#include "setupapi.h"
+#include "devpkey.h"
+#include "hidusage.h"
+#include "ddk/hidsdi.h"
+#include "initguid.h"
+#include "devguid.h"
+#include "xinput.h"
+
+#include "wine/debug.h"
+
+/* Not defined in the headers, used only by XInputGetStateEx */
+#define XINPUT_GAMEPAD_GUIDE 0x0400
+
+WINE_DEFAULT_DEBUG_CHANNEL(xinput);
+
+typedef struct _xinput_controller
+{
+ CRITICAL_SECTION crit;
+ XINPUT_CAPABILITIES caps;
+ void *platform_private; /* non-NULL when device is valid; validity may be read without holding crit */
+ XINPUT_STATE state;
+ XINPUT_GAMEPAD last_keystroke;
+ XINPUT_VIBRATION vibration;
+} xinput_controller;
+
+/* xinput_crit guards controllers array */
+static CRITICAL_SECTION xinput_crit;
+static CRITICAL_SECTION_DEBUG xinput_critsect_debug =
+{
+ 0, 0, &xinput_crit,
+ { &xinput_critsect_debug.ProcessLocksList, &xinput_critsect_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": xinput_crit") }
+};
+static CRITICAL_SECTION xinput_crit = { &xinput_critsect_debug, -1, 0, 0, 0, 0 };
+
+static xinput_controller controllers[XUSER_MAX_COUNT];
+static CRITICAL_SECTION_DEBUG controller_critsect_debug[XUSER_MAX_COUNT] =
+{
+ {
+ 0, 0, &controllers[0].crit,
+ { &controller_critsect_debug[0].ProcessLocksList, &controller_critsect_debug[0].ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[0].crit") }
+ },
+ {
+ 0, 0, &controllers[1].crit,
+ { &controller_critsect_debug[1].ProcessLocksList, &controller_critsect_debug[1].ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[1].crit") }
+ },
+ {
+ 0, 0, &controllers[2].crit,
+ { &controller_critsect_debug[2].ProcessLocksList, &controller_critsect_debug[2].ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[2].crit") }
+ },
+ {
+ 0, 0, &controllers[3].crit,
+ { &controller_critsect_debug[3].ProcessLocksList, &controller_critsect_debug[3].ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[3].crit") }
+ },
+};
+
+static xinput_controller controllers[XUSER_MAX_COUNT] =
+{
+ {{ &controller_critsect_debug[0], -1, 0, 0, 0, 0 }},
+ {{ &controller_critsect_debug[1], -1, 0, 0, 0, 0 }},
+ {{ &controller_critsect_debug[2], -1, 0, 0, 0, 0 }},
+ {{ &controller_critsect_debug[3], -1, 0, 0, 0, 0 }},
+};
+
+struct axis_info
+{
+ LONG min;
+ LONG range;
+ USHORT bits;
+};
+
+struct hid_platform_private
+{
+ PHIDP_PREPARSED_DATA preparsed;
+ HIDP_CAPS caps;
+
+ HANDLE device;
+ WCHAR *device_path;
+ BOOL enabled;
+
+ char *input_report_buf[2];
+ char *output_report_buf;
+
+ struct axis_info lx, ly, ltrigger, rx, ry, rtrigger;
+};
+
+static DWORD last_check = 0;
+
+static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *free_slot)
+{
+ struct hid_platform_private *private;
+ int i;
+
+ *free_slot = XUSER_MAX_COUNT;
+ for (i = XUSER_MAX_COUNT; i > 0; i--)
+ {
+ if (!(private = controllers[i - 1].platform_private)) *free_slot = i - 1;
+ else if (!wcscmp(detail->DevicePath, private->device_path)) return TRUE;
+ }
+ return FALSE;
+}
+
+static void MarkUsage(struct hid_platform_private *private, WORD usage, LONG min, LONG max, USHORT bits)
+{
+ struct axis_info info = {min, max - min, bits};
+
+ switch (usage)
+ {
+ case HID_USAGE_GENERIC_X: private->lx = info; break;
+ case HID_USAGE_GENERIC_Y: private->ly = info; break;
+ case HID_USAGE_GENERIC_Z: private->ltrigger = info; break;
+ case HID_USAGE_GENERIC_RX: private->rx = info; break;
+ case HID_USAGE_GENERIC_RY: private->ry = info; break;
+ case HID_USAGE_GENERIC_RZ: private->rtrigger = info; break;
+ }
+}
+
+static BOOL VerifyGamepad(PHIDP_PREPARSED_DATA preparsed, XINPUT_CAPABILITIES *xinput_caps,
+ struct hid_platform_private *private)
+{
+ HIDP_BUTTON_CAPS *button_caps;
+ HIDP_VALUE_CAPS *value_caps;
+ NTSTATUS status;
+
+ int i;
+ int button_count = 0;
+
+ /* Count buttons */
+ memset(xinput_caps, 0, sizeof(XINPUT_CAPABILITIES));
+
+ if (!(button_caps = malloc(sizeof(*button_caps) * private->caps.NumberInputButtonCaps))) return FALSE;
+ status = HidP_GetButtonCaps(HidP_Input, button_caps, &private->caps.NumberInputButtonCaps, preparsed);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetButtonCaps returned %#x\n", status);
+ else for (i = 0; i < private->caps.NumberInputButtonCaps; i++)
+ {
+ if (button_caps[i].UsagePage != HID_USAGE_PAGE_BUTTON)
+ continue;
+ if (button_caps[i].IsRange)
+ button_count = max(button_count, button_caps[i].Range.UsageMax);
+ else
+ button_count = max(button_count, button_caps[i].NotRange.Usage);
+ }
+ free(button_caps);
+ if (button_count < 11)
+ WARN("Too few buttons, continuing anyway\n");
+ xinput_caps->Gamepad.wButtons = 0xffff;
+
+ if (!(value_caps = malloc(sizeof(*value_caps) * private->caps.NumberInputValueCaps))) return FALSE;
+ status = HidP_GetValueCaps(HidP_Input, value_caps, &private->caps.NumberInputValueCaps, preparsed);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetValueCaps returned %#x\n", status);
+ else for (i = 0; i < private->caps.NumberInputValueCaps; i++)
+ {
+ if (value_caps[i].UsagePage != HID_USAGE_PAGE_GENERIC)
+ continue;
+ if (value_caps[i].IsRange)
+ {
+ int u;
+ for (u = value_caps[i].Range.UsageMin; u <=value_caps[i].Range.UsageMax; u++)
+ MarkUsage(private, u, value_caps[i].LogicalMin, value_caps[i].LogicalMax, value_caps[i].BitSize);
+ }
+ else
+ MarkUsage(private, value_caps[i].NotRange.Usage, value_caps[i].LogicalMin, value_caps[i].LogicalMax, value_caps[i].BitSize);
+ }
+ free(value_caps);
+
+ if (private->ltrigger.bits)
+ xinput_caps->Gamepad.bLeftTrigger = (1u << (sizeof(xinput_caps->Gamepad.bLeftTrigger) + 1)) - 1;
+ else
+ WARN("Missing axis LeftTrigger\n");
+ if (private->rtrigger.bits)
+ xinput_caps->Gamepad.bRightTrigger = (1u << (sizeof(xinput_caps->Gamepad.bRightTrigger) + 1)) - 1;
+ else
+ WARN("Missing axis RightTrigger\n");
+ if (private->lx.bits)
+ xinput_caps->Gamepad.sThumbLX = (1u << (sizeof(xinput_caps->Gamepad.sThumbLX) + 1)) - 1;
+ else
+ WARN("Missing axis ThumbLX\n");
+ if (private->ly.bits)
+ xinput_caps->Gamepad.sThumbLY = (1u << (sizeof(xinput_caps->Gamepad.sThumbLY) + 1)) - 1;
+ else
+ WARN("Missing axis ThumbLY\n");
+ if (private->rx.bits)
+ xinput_caps->Gamepad.sThumbRX = (1u << (sizeof(xinput_caps->Gamepad.sThumbRX) + 1)) - 1;
+ else
+ WARN("Missing axis ThumbRX\n");
+ if (private->ry.bits)
+ xinput_caps->Gamepad.sThumbRY = (1u << (sizeof(xinput_caps->Gamepad.sThumbRY) + 1)) - 1;
+ else
+ WARN("Missing axis ThumbRY\n");
+
+ xinput_caps->Type = XINPUT_DEVTYPE_GAMEPAD;
+ xinput_caps->SubType = XINPUT_DEVSUBTYPE_GAMEPAD;
+
+ if (private->caps.NumberOutputValueCaps > 0)
+ {
+ xinput_caps->Flags |= XINPUT_CAPS_FFB_SUPPORTED;
+ xinput_caps->Vibration.wLeftMotorSpeed = 255;
+ xinput_caps->Vibration.wRightMotorSpeed = 255;
+ }
+
+ return TRUE;
+}
+
+static BOOL init_controller(xinput_controller *controller, PHIDP_PREPARSED_DATA preparsed,
+ HIDP_CAPS *caps, HANDLE device, WCHAR *device_path)
+{
+ size_t size;
+ struct hid_platform_private *private;
+
+ if (!(private = calloc(1, sizeof(struct hid_platform_private)))) return FALSE;
+ private->caps = *caps;
+ if (!VerifyGamepad(preparsed, &controller->caps, private)) goto failed;
+
+ TRACE("Found gamepad %s\n", debugstr_w(device_path));
+
+ private->preparsed = preparsed;
+ private->device = device;
+ if (!(private->input_report_buf[0] = calloc(1, private->caps.InputReportByteLength))) goto failed;
+ if (!(private->input_report_buf[1] = calloc(1, private->caps.InputReportByteLength))) goto failed;
+ if (!(private->output_report_buf = calloc(1, private->caps.OutputReportByteLength))) goto failed;
+ size = (lstrlenW(device_path) + 1) * sizeof(WCHAR);
+ if (!(private->device_path = malloc(size))) goto failed;
+ memcpy(private->device_path, device_path, size);
+ private->enabled = TRUE;
+
+ memset(&controller->state, 0, sizeof(controller->state));
+ memset(&controller->vibration, 0, sizeof(controller->vibration));
+
+ controller->platform_private = private;
+ return TRUE;
+
+failed:
+ free(private->device_path);
+ free(private->input_report_buf[0]);
+ free(private->input_report_buf[1]);
+ free(private->output_report_buf);
+ free(private);
+ return FALSE;
+}
+
+static void HID_find_gamepads(void)
+{
+ char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
+ SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
+ SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
+ PHIDP_PREPARSED_DATA preparsed;
+ HIDP_CAPS caps;
+ NTSTATUS status;
+ HDEVINFO set;
+ HANDLE device;
+ DWORD idx;
+ GUID guid;
+ int i;
+
+ idx = GetTickCount();
+ if ((idx - last_check) < 2000) return;
+
+ EnterCriticalSection(&xinput_crit);
+
+ if ((idx - last_check) < 2000)
+ {
+ LeaveCriticalSection(&xinput_crit);
+ return;
+ }
+ last_check = idx;
+
+ HidD_GetHidGuid(&guid);
+
+ set = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+ detail->cbSize = sizeof(*detail);
+
+ idx = 0;
+ while (SetupDiEnumDeviceInterfaces(set, NULL, &guid, idx++, &iface))
+ {
+ if (!SetupDiGetDeviceInterfaceDetailW(set, &iface, detail, sizeof(buffer), NULL, NULL))
+ continue;
+
+ if (!wcsstr(detail->DevicePath, L"IG_")) continue;
+
+ if (find_opened_device(detail, &i)) continue; /* already opened */
+ if (i == XUSER_MAX_COUNT) break; /* no more slots */
+
+ device = CreateFileW(detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+ if (device == INVALID_HANDLE_VALUE) continue;
+
+ preparsed = NULL;
+ if (!HidD_GetPreparsedData(device, &preparsed))
+ WARN("ignoring HID device, HidD_GetPreparsedData failed with error %u\n", GetLastError());
+ else if ((status = HidP_GetCaps(preparsed, &caps)) != HIDP_STATUS_SUCCESS)
+ WARN("ignoring HID device, HidP_GetCaps returned %#x\n", status);
+ else if (caps.UsagePage != HID_USAGE_PAGE_GENERIC)
+ WARN("ignoring HID device, unsupported usage page %04x\n", caps.UsagePage);
+ else if (caps.Usage != HID_USAGE_GENERIC_GAMEPAD && caps.Usage != HID_USAGE_GENERIC_JOYSTICK &&
+ caps.Usage != HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER)
+ WARN("ignoring HID device, unsupported usage %04x:%04x\n", caps.UsagePage, caps.Usage);
+ else if (!init_controller(&controllers[i], preparsed, &caps, device, detail->DevicePath))
+ WARN("ignoring HID device, failed to initialize\n");
+ else
+ continue;
+
+ CloseHandle(device);
+ HidD_FreePreparsedData(preparsed);
+ }
+
+ SetupDiDestroyDeviceInfoList(set);
+ LeaveCriticalSection(&xinput_crit);
+}
+
+static void remove_gamepad(xinput_controller *device)
+{
+ EnterCriticalSection(&device->crit);
+
+ if (device->platform_private)
+ {
+ struct hid_platform_private *private = device->platform_private;
+
+ device->platform_private = NULL;
+
+ CloseHandle(private->device);
+ free(private->input_report_buf[0]);
+ free(private->input_report_buf[1]);
+ free(private->output_report_buf);
+ free(private->device_path);
+ HidD_FreePreparsedData(private->preparsed);
+ free(private);
+ }
+
+ LeaveCriticalSection(&device->crit);
+}
+
+static void HID_destroy_gamepads(void)
+{
+ int i;
+ for (i = 0; i < XUSER_MAX_COUNT; i++) remove_gamepad(&controllers[i]);
+}
+
+static SHORT scale_short(LONG value, const struct axis_info *axis)
+{
+ return ((((ULONGLONG)(value - axis->min)) * 0xffff) / axis->range) - 32768;
+}
+
+static BYTE scale_byte(LONG value, const struct axis_info *axis)
+{
+ return (((ULONGLONG)(value - axis->min)) * 0xff) / axis->range;
+}
+
+static void HID_update_state(xinput_controller *device, XINPUT_STATE *state)
+{
+ struct hid_platform_private *private = device->platform_private;
+ int i;
+ char **report_buf = private->input_report_buf, *tmp;
+ ULONG report_len = private->caps.InputReportByteLength;
+ NTSTATUS status;
+
+ USAGE buttons[11];
+ ULONG button_length, hat_value;
+ LONG value;
+
+ if (!private->enabled) return;
+
+ if (!HidD_GetInputReport(private->device, report_buf[0], report_len))
+ {
+ if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_HANDLE)
+ {
+ EnterCriticalSection(&xinput_crit);
+ remove_gamepad(device);
+ LeaveCriticalSection(&xinput_crit);
+ }
+ else ERR("Failed to get input report, HidD_GetInputReport failed with error %u\n", GetLastError());
+ return;
+ }
+
+ if (memcmp(report_buf[0], report_buf[1], report_len) != 0)
+ {
+ device->state.dwPacketNumber++;
+ button_length = ARRAY_SIZE(buttons);
+ status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, buttons, &button_length, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsages HID_USAGE_PAGE_BUTTON returned %#x\n", status);
+
+ device->state.Gamepad.wButtons = 0;
+ for (i = 0; i < button_length; i++)
+ {
+ switch (buttons[i])
+ {
+ case 1: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
+ case 2: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
+ case 3: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
+ case 4: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
+ case 5: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
+ case 6: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
+ case 7: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
+ case 8: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
+ case 9: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
+ case 10: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
+ case 11: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break;
+ }
+ }
+
+ status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, &hat_value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_HATSWITCH returned %#x\n", status);
+ else
+ {
+ switch(hat_value){
+ /* 8 1 2
+ * 7 0 3
+ * 6 5 4 */
+ case 0:
+ break;
+ case 1:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;
+ break;
+ case 2:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT;
+ break;
+ case 3:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT;
+ break;
+ case 4:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN;
+ break;
+ case 5:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;
+ break;
+ case 6:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT;
+ break;
+ case 7:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT;
+ break;
+ case 8:
+ device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP;
+ break;
+ }
+ }
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_X returned %#x\n", status);
+ else device->state.Gamepad.sThumbLX = scale_short(value, &private->lx);
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Y returned %#x\n", status);
+ else device->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1;
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RX returned %#x\n", status);
+ else device->state.Gamepad.sThumbRX = scale_short(value, &private->rx);
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RY returned %#x\n", status);
+ else device->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1;
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RZ returned %#x\n", status);
+ else device->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger);
+
+ status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, private->preparsed, report_buf[0], report_len);
+ if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Z returned %#x\n", status);
+ else device->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger);
+ }
+
+ tmp = report_buf[0];
+ report_buf[0] = report_buf[1];
+ report_buf[1] = tmp;
+ memcpy(state, &device->state, sizeof(*state));
+}
+
+static DWORD HID_set_state(xinput_controller *device, XINPUT_VIBRATION *state)
+{
+ struct hid_platform_private *private = device->platform_private;
+ char *output_report_buf = private->output_report_buf;
+ ULONG output_report_len = private->caps.OutputReportByteLength;
+
+ if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
+ {
+ device->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed;
+ device->vibration.wRightMotorSpeed = state->wRightMotorSpeed;
+
+ if (private->enabled)
+ {
+ memset(output_report_buf, 0, output_report_len);
+ output_report_buf[0] = /* report id */ 0;
+ output_report_buf[1] = 0x8;
+ output_report_buf[3] = (BYTE)(state->wLeftMotorSpeed / 256);
+ output_report_buf[4] = (BYTE)(state->wRightMotorSpeed / 256);
+
+ if (!HidD_SetOutputReport(private->device, output_report_buf, output_report_len))
+ {
+ WARN("unable to set output report, HidD_SetOutputReport failed with error %u\n", GetLastError());
+ return GetLastError();
+ }
+
+ return ERROR_SUCCESS;
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+static void HID_enable(xinput_controller *device, BOOL enable)
+{
+ struct hid_platform_private *private = device->platform_private;
+
+ if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
+ {
+ if (private->enabled && !enable)
+ {
+ XINPUT_VIBRATION state;
+ state.wLeftMotorSpeed = 0;
+ state.wRightMotorSpeed = 0;
+ HID_set_state(device, &state);
+ }
+ else if (!private->enabled && enable)
+ {
+ HID_set_state(device, &device->vibration);
+ }
+ }
+
+ private->enabled = enable;
+}
+
+static BOOL verify_and_lock_device(xinput_controller *device)
+{
+ if (!device->platform_private) return FALSE;
+
+ EnterCriticalSection(&device->crit);
+
+ if (!device->platform_private)
+ {
+ LeaveCriticalSection(&device->crit);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void unlock_device(xinput_controller *device)
+{
+ LeaveCriticalSection(&device->crit);
+}
+
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(inst);
+ break;
+ case DLL_PROCESS_DETACH:
+ if (reserved) break;
+ HID_destroy_gamepads();
+ break;
+ }
+ return TRUE;
+}
+
+void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
+{
+ int index;
+
+ TRACE("(enable %d)\n", enable);
+
+ /* Setting to false will stop messages from XInputSetState being sent
+ to the controllers. Setting to true will send the last vibration
+ value (sent to XInputSetState) to the controller and allow messages to
+ be sent */
+ HID_find_gamepads();
+
+ for (index = 0; index < XUSER_MAX_COUNT; index++)
+ {
+ if (!verify_and_lock_device(&controllers[index])) continue;
+ HID_enable(&controllers[index], enable);
+ unlock_device(&controllers[index]);
+ }
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION *vibration)
+{
+ DWORD ret;
+
+ TRACE("(index %u, vibration %p)\n", index, vibration);
+
+ HID_find_gamepads();
+
+ if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
+ if (!verify_and_lock_device(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
+
+ ret = HID_set_state(&controllers[index], vibration);
+
+ unlock_device(&controllers[index]);
+
+ return ret;
+}
+
+/* Some versions of SteamOverlayRenderer hot-patch XInputGetStateEx() and call
+ * XInputGetState() in the hook, so we need a wrapper. */
+static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
+{
+ if (!state) return ERROR_BAD_ARGUMENTS;
+
+ HID_find_gamepads();
+
+ if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
+ if (!verify_and_lock_device(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
+
+ HID_update_state(&controllers[index], state);
+
+ if (!controllers[index].platform_private)
+ {
+ /* update_state may have disconnected the controller */
+ unlock_device(&controllers[index]);
+ return ERROR_DEVICE_NOT_CONNECTED;
+ }
+
+ unlock_device(&controllers[index]);
+
+ return ERROR_SUCCESS;
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetState(DWORD index, XINPUT_STATE *state)
+{
+ DWORD ret;
+
+ TRACE("(index %u, state %p)!\n", index, state);
+
+ ret = xinput_get_state(index, state);
+ if (ret != ERROR_SUCCESS) return ret;
+
+ /* The main difference between this and the Ex version is the media guide button */
+ state->Gamepad.wButtons &= ~XINPUT_GAMEPAD_GUIDE;
+
+ return ERROR_SUCCESS;
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetStateEx(DWORD index, XINPUT_STATE *state)
+{
+ TRACE("(index %u, state %p)!\n", index, state);
+
+ return xinput_get_state(index, state);
+}
+
+static const int JS_STATE_OFF = 0;
+static const int JS_STATE_LOW = 1;
+static const int JS_STATE_HIGH = 2;
+
+static int joystick_state(const SHORT value)
+{
+ if (value > 20000) return JS_STATE_HIGH;
+ if (value < -20000) return JS_STATE_LOW;
+ return JS_STATE_OFF;
+}
+
+static WORD js_vk_offs(const int x, const int y)
+{
+ if (y == JS_STATE_OFF)
+ {
+ /*if (x == JS_STATE_OFF) shouldn't get here */
+ if (x == JS_STATE_LOW) return 3; /* LEFT */
+ /*if (x == JS_STATE_HIGH)*/ return 2; /* RIGHT */
+ }
+ if (y == JS_STATE_HIGH)
+ {
+ if (x == JS_STATE_OFF) return 0; /* UP */
+ if (x == JS_STATE_LOW) return 4; /* UPLEFT */
+ /*if (x == JS_STATE_HIGH)*/ return 5; /* UPRIGHT */
+ }
+ /*if (y == JS_STATE_LOW)*/
+ {
+ if (x == JS_STATE_OFF) return 1; /* DOWN */
+ if (x == JS_STATE_LOW) return 7; /* DOWNLEFT */
+ /*if (x == JS_STATE_HIGH)*/ return 6; /* DOWNRIGHT */
+ }
+}
+
+static DWORD check_joystick_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke, const SHORT *cur_x,
+ const SHORT *cur_y, SHORT *last_x, SHORT *last_y, const WORD base_vk)
+{
+ int cur_vk = 0, cur_x_st, cur_y_st;
+ int last_vk = 0, last_x_st, last_y_st;
+
+ cur_x_st = joystick_state(*cur_x);
+ cur_y_st = joystick_state(*cur_y);
+ if (cur_x_st || cur_y_st)
+ cur_vk = base_vk + js_vk_offs(cur_x_st, cur_y_st);
+
+ last_x_st = joystick_state(*last_x);
+ last_y_st = joystick_state(*last_y);
+ if (last_x_st || last_y_st)
+ last_vk = base_vk + js_vk_offs(last_x_st, last_y_st);
+
+ if (cur_vk != last_vk)
+ {
+ if (last_vk)
+ {
+ /* joystick was set, and now different. send a KEYUP event, and set
+ * last pos to centered, so the appropriate KEYDOWN event will be
+ * sent on the next call. */
+ keystroke->VirtualKey = last_vk;
+ keystroke->Unicode = 0; /* unused */
+ keystroke->Flags = XINPUT_KEYSTROKE_KEYUP;
+ keystroke->UserIndex = index;
+ keystroke->HidCode = 0;
+
+ *last_x = 0;
+ *last_y = 0;
+
+ return ERROR_SUCCESS;
+ }
+
+ /* joystick was unset, send KEYDOWN. */
+ keystroke->VirtualKey = cur_vk;
+ keystroke->Unicode = 0; /* unused */
+ keystroke->Flags = XINPUT_KEYSTROKE_KEYDOWN;
+ keystroke->UserIndex = index;
+ keystroke->HidCode = 0;
+
+ *last_x = *cur_x;
+ *last_y = *cur_y;
+
+ return ERROR_SUCCESS;
+ }
+
+ *last_x = *cur_x;
+ *last_y = *cur_y;
+
+ return ERROR_EMPTY;
+}
+
+static BOOL trigger_is_on(const BYTE value)
+{
+ return value > 30;
+}
+
+static DWORD check_for_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke)
+{
+ xinput_controller *device = &controllers[index];
+ const XINPUT_GAMEPAD *cur;
+ DWORD ret = ERROR_EMPTY;
+ int i;
+
+ static const struct
+ {
+ int mask;
+ WORD vk;
+ } buttons[] = {
+ { XINPUT_GAMEPAD_DPAD_UP, VK_PAD_DPAD_UP },
+ { XINPUT_GAMEPAD_DPAD_DOWN, VK_PAD_DPAD_DOWN },
+ { XINPUT_GAMEPAD_DPAD_LEFT, VK_PAD_DPAD_LEFT },
+ { XINPUT_GAMEPAD_DPAD_RIGHT, VK_PAD_DPAD_RIGHT },
+ { XINPUT_GAMEPAD_START, VK_PAD_START },
+ { XINPUT_GAMEPAD_BACK, VK_PAD_BACK },
+ { XINPUT_GAMEPAD_LEFT_THUMB, VK_PAD_LTHUMB_PRESS },
+ { XINPUT_GAMEPAD_RIGHT_THUMB, VK_PAD_RTHUMB_PRESS },
+ { XINPUT_GAMEPAD_LEFT_SHOULDER, VK_PAD_LSHOULDER },
+ { XINPUT_GAMEPAD_RIGHT_SHOULDER, VK_PAD_RSHOULDER },
+ { XINPUT_GAMEPAD_A, VK_PAD_A },
+ { XINPUT_GAMEPAD_B, VK_PAD_B },
+ { XINPUT_GAMEPAD_X, VK_PAD_X },
+ { XINPUT_GAMEPAD_Y, VK_PAD_Y },
+ /* note: guide button does not send an event */
+ };
+
+ if (!verify_and_lock_device(device)) return ERROR_DEVICE_NOT_CONNECTED;
+
+ cur = &device->state.Gamepad;
+
+ /*** buttons ***/
+ for (i = 0; i < ARRAY_SIZE(buttons); ++i)
+ {
+ if ((cur->wButtons & buttons[i].mask) ^ (device->last_keystroke.wButtons & buttons[i].mask))
+ {
+ keystroke->VirtualKey = buttons[i].vk;
+ keystroke->Unicode = 0; /* unused */
+ if (cur->wButtons & buttons[i].mask)
+ {
+ keystroke->Flags = XINPUT_KEYSTROKE_KEYDOWN;
+ device->last_keystroke.wButtons |= buttons[i].mask;
+ }
+ else
+ {
+ keystroke->Flags = XINPUT_KEYSTROKE_KEYUP;
+ device->last_keystroke.wButtons &= ~buttons[i].mask;
+ }
+ keystroke->UserIndex = index;
+ keystroke->HidCode = 0;
+ ret = ERROR_SUCCESS;
+ goto done;
+ }
+ }
+
+ /*** triggers ***/
+ if (trigger_is_on(cur->bLeftTrigger) ^ trigger_is_on(device->last_keystroke.bLeftTrigger))
+ {
+ keystroke->VirtualKey = VK_PAD_LTRIGGER;
+ keystroke->Unicode = 0; /* unused */
+ keystroke->Flags = trigger_is_on(cur->bLeftTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
+ keystroke->UserIndex = index;
+ keystroke->HidCode = 0;
+ device->last_keystroke.bLeftTrigger = cur->bLeftTrigger;
+ ret = ERROR_SUCCESS;
+ goto done;
+ }
+
+ if (trigger_is_on(cur->bRightTrigger) ^ trigger_is_on(device->last_keystroke.bRightTrigger))
+ {
+ keystroke->VirtualKey = VK_PAD_RTRIGGER;
+ keystroke->Unicode = 0; /* unused */
+ keystroke->Flags = trigger_is_on(cur->bRightTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
+ keystroke->UserIndex = index;
+ keystroke->HidCode = 0;
+ device->last_keystroke.bRightTrigger = cur->bRightTrigger;
+ ret = ERROR_SUCCESS;
+ goto done;
+ }
+
+ /*** joysticks ***/
+ ret = check_joystick_keystroke(index, keystroke, &cur->sThumbLX, &cur->sThumbLY,
+ &device->last_keystroke.sThumbLX,
+ &device->last_keystroke.sThumbLY, VK_PAD_LTHUMB_UP);
+ if (ret == ERROR_SUCCESS)
+ goto done;
+
+ ret = check_joystick_keystroke(index, keystroke, &cur->sThumbRX, &cur->sThumbRY,
+ &device->last_keystroke.sThumbRX,
+ &device->last_keystroke.sThumbRY, VK_PAD_RTHUMB_UP);
+ if (ret == ERROR_SUCCESS)
+ goto done;
+
+done:
+ unlock_device(device);
+
+ return ret;
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetKeystroke(DWORD index, DWORD reserved, PXINPUT_KEYSTROKE keystroke)
+{
+ TRACE("(index %u, reserved %u, keystroke %p)\n", index, reserved, keystroke);
+
+ if (index >= XUSER_MAX_COUNT && index != XUSER_INDEX_ANY) return ERROR_BAD_ARGUMENTS;
+
+ if (index == XUSER_INDEX_ANY)
+ {
+ int i;
+ for (i = 0; i < XUSER_MAX_COUNT; ++i)
+ if (check_for_keystroke(i, keystroke) == ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+ return ERROR_EMPTY;
+ }
+
+ return check_for_keystroke(index, keystroke);
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, XINPUT_CAPABILITIES *capabilities)
+{
+ TRACE("(index %u, flags 0x%x, capabilities %p)\n", index, flags, capabilities);
+
+ HID_find_gamepads();
+
+ if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
+
+ if (!verify_and_lock_device(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
+
+ if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
+ {
+ unlock_device(&controllers[index]);
+ return ERROR_DEVICE_NOT_CONNECTED;
+ }
+
+ memcpy(capabilities, &controllers[index].caps, sizeof(*capabilities));
+
+ unlock_device(&controllers[index]);
+
+ return ERROR_SUCCESS;
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetDSoundAudioDeviceGuids(DWORD index, GUID *render_guid, GUID *capture_guid)
+{
+ FIXME("(index %u, render guid %p, capture guid %p) Stub!\n", index, render_guid, capture_guid);
+
+ if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
+ if (!controllers[index].platform_private) return ERROR_DEVICE_NOT_CONNECTED;
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+DWORD WINAPI DECLSPEC_HOTPATCH XInputGetBatteryInformation(DWORD index, BYTE type, XINPUT_BATTERY_INFORMATION* battery)
+{
+ static int once;
+
+ if (!once++) FIXME("(index %u, type %u, battery %p) Stub!\n", index, type, battery);
+
+ if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
+ if (!controllers[index].platform_private) return ERROR_DEVICE_NOT_CONNECTED;
+
+ return ERROR_NOT_SUPPORTED;
+}
diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c
deleted file mode 100644
index 2d9f54c83f2..00000000000
--- a/dlls/xinput1_3/xinput_main.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * The Wine project - Xinput Joystick Library
- * Copyright 2008 Andrew Fenn
- *
- * 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 <assert.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "wine/debug.h"
-#include "windef.h"
-#include "winbase.h"
-#include "winerror.h"
-
-#include "xinput.h"
-#include "xinput_private.h"
-
-/* Not defined in the headers, used only by XInputGetStateEx */
-#define XINPUT_GAMEPAD_GUIDE 0x0400
-
-WINE_DEFAULT_DEBUG_CHANNEL(xinput);
-
-/* xinput_crit guards controllers array */
-static CRITICAL_SECTION_DEBUG xinput_critsect_debug =
-{
- 0, 0, &xinput_crit,
- { &xinput_critsect_debug.ProcessLocksList, &xinput_critsect_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": xinput_crit") }
-};
-CRITICAL_SECTION xinput_crit = { &xinput_critsect_debug, -1, 0, 0, 0, 0 };
-
-static CRITICAL_SECTION_DEBUG controller_critsect_debug[XUSER_MAX_COUNT] =
-{
- {
- 0, 0, &controllers[0].crit,
- { &controller_critsect_debug[0].ProcessLocksList, &controller_critsect_debug[0].ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[0].crit") }
- },
- {
- 0, 0, &controllers[1].crit,
- { &controller_critsect_debug[1].ProcessLocksList, &controller_critsect_debug[1].ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[1].crit") }
- },
- {
- 0, 0, &controllers[2].crit,
- { &controller_critsect_debug[2].ProcessLocksList, &controller_critsect_debug[2].ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[2].crit") }
- },
- {
- 0, 0, &controllers[3].crit,
- { &controller_critsect_debug[3].ProcessLocksList, &controller_critsect_debug[3].ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": controllers[3].crit") }
- },
-};
-
-xinput_controller controllers[XUSER_MAX_COUNT] = {
- {{ &controller_critsect_debug[0], -1, 0, 0, 0, 0 }},
- {{ &controller_critsect_debug[1], -1, 0, 0, 0, 0 }},
- {{ &controller_critsect_debug[2], -1, 0, 0, 0, 0 }},
- {{ &controller_critsect_debug[3], -1, 0, 0, 0, 0 }},
-};
-
-static BOOL verify_and_lock_device(xinput_controller *device)
-{
- if (!device->platform_private)
- return FALSE;
-
- EnterCriticalSection(&device->crit);
-
- if (!device->platform_private)
- {
- LeaveCriticalSection(&device->crit);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void unlock_device(xinput_controller *device)
-{
- LeaveCriticalSection(&device->crit);
-}
-
-BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
-{
- switch(reason)
- {
- case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(inst);
- break;
- case DLL_PROCESS_DETACH:
- if (reserved) break;
- HID_destroy_gamepads();
- break;
- }
- return TRUE;
-}
-
-void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
-{
- int index;
-
- TRACE("(enable %d)\n", enable);
-
- /* Setting to false will stop messages from XInputSetState being sent
- to the controllers. Setting to true will send the last vibration
- value (sent to XInputSetState) to the controller and allow messages to
- be sent */
- HID_find_gamepads();
-
- for (index = 0; index < XUSER_MAX_COUNT; index ++)
- {
- if (!verify_and_lock_device(&controllers[index])) continue;
- HID_enable(&controllers[index], enable);
- unlock_device(&controllers[index]);
- }
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION* vibration)
-{
- DWORD ret;
-
- TRACE("(index %u, vibration %p)\n", index, vibration);
-
- HID_find_gamepads();
-
- if (index >= XUSER_MAX_COUNT)
- return ERROR_BAD_ARGUMENTS;
- if (!verify_and_lock_device(&controllers[index]))
- return ERROR_DEVICE_NOT_CONNECTED;
-
- ret = HID_set_state(&controllers[index], vibration);
-
- unlock_device(&controllers[index]);
-
- return ret;
-}
-
-/* Some versions of SteamOverlayRenderer hot-patch XInputGetStateEx() and call
- * XInputGetState() in the hook, so we need a wrapper. */
-static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
-{
- if (!state)
- return ERROR_BAD_ARGUMENTS;
-
- HID_find_gamepads();
-
- if (index >= XUSER_MAX_COUNT)
- return ERROR_BAD_ARGUMENTS;
- if (!verify_and_lock_device(&controllers[index]))
- return ERROR_DEVICE_NOT_CONNECTED;
-
- HID_update_state(&controllers[index], state);
-
- if (!controllers[index].platform_private)
- {
- /* update_state may have disconnected the controller */
- unlock_device(&controllers[index]);
- return ERROR_DEVICE_NOT_CONNECTED;
- }
-
- unlock_device(&controllers[index]);
-
- return ERROR_SUCCESS;
-}
-
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetState(DWORD index, XINPUT_STATE* state)
-{
- DWORD ret;
-
- TRACE("(index %u, state %p)!\n", index, state);
-
- ret = xinput_get_state(index, state);
- if (ret != ERROR_SUCCESS)
- return ret;
-
- /* The main difference between this and the Ex version is the media guide button */
- state->Gamepad.wButtons &= ~XINPUT_GAMEPAD_GUIDE;
-
- return ERROR_SUCCESS;
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetStateEx(DWORD index, XINPUT_STATE* state)
-{
- TRACE("(index %u, state %p)!\n", index, state);
-
- return xinput_get_state(index, state);
-}
-
-static const int JS_STATE_OFF = 0;
-static const int JS_STATE_LOW = 1;
-static const int JS_STATE_HIGH = 2;
-
-static int joystick_state(const SHORT value)
-{
- if (value > 20000)
- return JS_STATE_HIGH;
- if (value < -20000)
- return JS_STATE_LOW;
- return JS_STATE_OFF;
-}
-
-static WORD js_vk_offs(const int x, const int y)
-{
- if (y == JS_STATE_OFF)
- {
- /*if (x == JS_STATE_OFF) shouldn't get here */
- if (x == JS_STATE_LOW) return 3; /* LEFT */
- /*if (x == JS_STATE_HIGH)*/ return 2; /* RIGHT */
- }
- if (y == JS_STATE_HIGH)
- {
- if (x == JS_STATE_OFF) return 0; /* UP */
- if (x == JS_STATE_LOW) return 4; /* UPLEFT */
- /*if (x == JS_STATE_HIGH)*/ return 5; /* UPRIGHT */
- }
- /*if (y == JS_STATE_LOW)*/
- {
- if (x == JS_STATE_OFF) return 1; /* DOWN */
- if (x == JS_STATE_LOW) return 7; /* DOWNLEFT */
- /*if (x == JS_STATE_HIGH)*/ return 6; /* DOWNRIGHT */
- }
-}
-
-static DWORD check_joystick_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke,
- const SHORT *cur_x, const SHORT *cur_y, SHORT *last_x, SHORT *last_y,
- const WORD base_vk)
-{
- int cur_vk = 0, cur_x_st, cur_y_st;
- int last_vk = 0, last_x_st, last_y_st;
-
- cur_x_st = joystick_state(*cur_x);
- cur_y_st = joystick_state(*cur_y);
- if (cur_x_st || cur_y_st)
- cur_vk = base_vk + js_vk_offs(cur_x_st, cur_y_st);
-
- last_x_st = joystick_state(*last_x);
- last_y_st = joystick_state(*last_y);
- if (last_x_st || last_y_st)
- last_vk = base_vk + js_vk_offs(last_x_st, last_y_st);
-
- if (cur_vk != last_vk)
- {
- if (last_vk)
- {
- /* joystick was set, and now different. send a KEYUP event, and set
- * last pos to centered, so the appropriate KEYDOWN event will be
- * sent on the next call. */
- keystroke->VirtualKey = last_vk;
- keystroke->Unicode = 0; /* unused */
- keystroke->Flags = XINPUT_KEYSTROKE_KEYUP;
- keystroke->UserIndex = index;
- keystroke->HidCode = 0;
-
- *last_x = 0;
- *last_y = 0;
-
- return ERROR_SUCCESS;
- }
-
- /* joystick was unset, send KEYDOWN. */
- keystroke->VirtualKey = cur_vk;
- keystroke->Unicode = 0; /* unused */
- keystroke->Flags = XINPUT_KEYSTROKE_KEYDOWN;
- keystroke->UserIndex = index;
- keystroke->HidCode = 0;
-
- *last_x = *cur_x;
- *last_y = *cur_y;
-
- return ERROR_SUCCESS;
- }
-
- *last_x = *cur_x;
- *last_y = *cur_y;
-
- return ERROR_EMPTY;
-}
-
-static BOOL trigger_is_on(const BYTE value)
-{
- return value > 30;
-}
-
-static DWORD check_for_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke)
-{
- xinput_controller *device = &controllers[index];
- const XINPUT_GAMEPAD *cur;
- DWORD ret = ERROR_EMPTY;
- int i;
-
- static const struct {
- int mask;
- WORD vk;
- } buttons[] = {
- { XINPUT_GAMEPAD_DPAD_UP, VK_PAD_DPAD_UP },
- { XINPUT_GAMEPAD_DPAD_DOWN, VK_PAD_DPAD_DOWN },
- { XINPUT_GAMEPAD_DPAD_LEFT, VK_PAD_DPAD_LEFT },
- { XINPUT_GAMEPAD_DPAD_RIGHT, VK_PAD_DPAD_RIGHT },
- { XINPUT_GAMEPAD_START, VK_PAD_START },
- { XINPUT_GAMEPAD_BACK, VK_PAD_BACK },
- { XINPUT_GAMEPAD_LEFT_THUMB, VK_PAD_LTHUMB_PRESS },
- { XINPUT_GAMEPAD_RIGHT_THUMB, VK_PAD_RTHUMB_PRESS },
- { XINPUT_GAMEPAD_LEFT_SHOULDER, VK_PAD_LSHOULDER },
- { XINPUT_GAMEPAD_RIGHT_SHOULDER, VK_PAD_RSHOULDER },
- { XINPUT_GAMEPAD_A, VK_PAD_A },
- { XINPUT_GAMEPAD_B, VK_PAD_B },
- { XINPUT_GAMEPAD_X, VK_PAD_X },
- { XINPUT_GAMEPAD_Y, VK_PAD_Y },
- /* note: guide button does not send an event */
- };
-
- if (!verify_and_lock_device(device))
- return ERROR_DEVICE_NOT_CONNECTED;
-
- cur = &device->state.Gamepad;
-
- /*** buttons ***/
- for (i = 0; i < ARRAY_SIZE(buttons); ++i)
- {
- if ((cur->wButtons & buttons[i].mask) ^ (device->last_keystroke.wButtons & buttons[i].mask))
- {
- keystroke->VirtualKey = buttons[i].vk;
- keystroke->Unicode = 0; /* unused */
- if (cur->wButtons & buttons[i].mask)
- {
- keystroke->Flags = XINPUT_KEYSTROKE_KEYDOWN;
- device->last_keystroke.wButtons |= buttons[i].mask;
- }
- else
- {
- keystroke->Flags = XINPUT_KEYSTROKE_KEYUP;
- device->last_keystroke.wButtons &= ~buttons[i].mask;
- }
- keystroke->UserIndex = index;
- keystroke->HidCode = 0;
- ret = ERROR_SUCCESS;
- goto done;
- }
- }
-
- /*** triggers ***/
- if (trigger_is_on(cur->bLeftTrigger) ^ trigger_is_on(device->last_keystroke.bLeftTrigger))
- {
- keystroke->VirtualKey = VK_PAD_LTRIGGER;
- keystroke->Unicode = 0; /* unused */
- keystroke->Flags = trigger_is_on(cur->bLeftTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
- keystroke->UserIndex = index;
- keystroke->HidCode = 0;
- device->last_keystroke.bLeftTrigger = cur->bLeftTrigger;
- ret = ERROR_SUCCESS;
- goto done;
- }
-
- if (trigger_is_on(cur->bRightTrigger) ^ trigger_is_on(device->last_keystroke.bRightTrigger))
- {
- keystroke->VirtualKey = VK_PAD_RTRIGGER;
- keystroke->Unicode = 0; /* unused */
- keystroke->Flags = trigger_is_on(cur->bRightTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
- keystroke->UserIndex = index;
- keystroke->HidCode = 0;
- device->last_keystroke.bRightTrigger = cur->bRightTrigger;
- ret = ERROR_SUCCESS;
- goto done;
- }
-
- /*** joysticks ***/
- ret = check_joystick_keystroke(index, keystroke, &cur->sThumbLX, &cur->sThumbLY,
- &device->last_keystroke.sThumbLX,
- &device->last_keystroke.sThumbLY, VK_PAD_LTHUMB_UP);
- if (ret == ERROR_SUCCESS)
- goto done;
-
- ret = check_joystick_keystroke(index, keystroke, &cur->sThumbRX, &cur->sThumbRY,
- &device->last_keystroke.sThumbRX,
- &device->last_keystroke.sThumbRY, VK_PAD_RTHUMB_UP);
- if (ret == ERROR_SUCCESS)
- goto done;
-
-done:
- unlock_device(device);
-
- return ret;
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetKeystroke(DWORD index, DWORD reserved, PXINPUT_KEYSTROKE keystroke)
-{
- TRACE("(index %u, reserved %u, keystroke %p)\n", index, reserved, keystroke);
-
- if (index >= XUSER_MAX_COUNT && index != XUSER_INDEX_ANY)
- return ERROR_BAD_ARGUMENTS;
-
- if (index == XUSER_INDEX_ANY)
- {
- int i;
- for (i = 0; i < XUSER_MAX_COUNT; ++i)
- if (check_for_keystroke(i, keystroke) == ERROR_SUCCESS)
- return ERROR_SUCCESS;
- return ERROR_EMPTY;
- }
-
- return check_for_keystroke(index, keystroke);
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, XINPUT_CAPABILITIES* capabilities)
-{
- TRACE("(index %u, flags 0x%x, capabilities %p)\n", index, flags, capabilities);
-
- HID_find_gamepads();
-
- if (index >= XUSER_MAX_COUNT)
- return ERROR_BAD_ARGUMENTS;
-
- if (!verify_and_lock_device(&controllers[index]))
- return ERROR_DEVICE_NOT_CONNECTED;
-
- if (flags & XINPUT_FLAG_GAMEPAD && controllers[index].caps.SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
- {
- unlock_device(&controllers[index]);
- return ERROR_DEVICE_NOT_CONNECTED;
- }
-
- memcpy(capabilities, &controllers[index].caps, sizeof(*capabilities));
-
- unlock_device(&controllers[index]);
-
- return ERROR_SUCCESS;
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetDSoundAudioDeviceGuids(DWORD index, GUID* render_guid, GUID* capture_guid)
-{
- FIXME("(index %u, render guid %p, capture guid %p) Stub!\n", index, render_guid, capture_guid);
-
- if (index >= XUSER_MAX_COUNT)
- return ERROR_BAD_ARGUMENTS;
- if (!controllers[index].platform_private)
- return ERROR_DEVICE_NOT_CONNECTED;
-
- return ERROR_NOT_SUPPORTED;
-}
-
-DWORD WINAPI DECLSPEC_HOTPATCH XInputGetBatteryInformation(DWORD index, BYTE type, XINPUT_BATTERY_INFORMATION* battery)
-{
- static int once;
-
- if (!once++)
- FIXME("(index %u, type %u, battery %p) Stub!\n", index, type, battery);
-
- if (index >= XUSER_MAX_COUNT)
- return ERROR_BAD_ARGUMENTS;
- if (!controllers[index].platform_private)
- return ERROR_DEVICE_NOT_CONNECTED;
-
- return ERROR_NOT_SUPPORTED;
-}
diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h
deleted file mode 100644
index 2bf16c0ffce..00000000000
--- a/dlls/xinput1_3/xinput_private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * The Wine project - Xinput Joystick Library
- * Copyright 2018 Aric Stewart
- *
- * 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
- */
-
-typedef struct _xinput_controller
-{
- CRITICAL_SECTION crit;
- XINPUT_CAPABILITIES caps;
- void *platform_private; /* non-NULL when device is valid; validity may be read without holding crit */
- XINPUT_STATE state;
- XINPUT_GAMEPAD last_keystroke;
- XINPUT_VIBRATION vibration;
-} xinput_controller;
-
-extern CRITICAL_SECTION xinput_crit;
-extern xinput_controller controllers[XUSER_MAX_COUNT];
-
-void HID_find_gamepads(void) DECLSPEC_HIDDEN;
-void HID_destroy_gamepads(void) DECLSPEC_HIDDEN;
-void HID_update_state(xinput_controller* device, XINPUT_STATE *state) DECLSPEC_HIDDEN;
-DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) DECLSPEC_HIDDEN;
-void HID_enable(xinput_controller* device, BOOL enable) DECLSPEC_HIDDEN;
diff --git a/dlls/xinput1_4/Makefile.in b/dlls/xinput1_4/Makefile.in
index cdf4b4fed05..24b10b1e848 100644
--- a/dlls/xinput1_4/Makefile.in
+++ b/dlls/xinput1_4/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = hid setupapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- hid.c \
- xinput_main.c
+ main.c
RC_SRCS = version.rc
diff --git a/dlls/xinput9_1_0/Makefile.in b/dlls/xinput9_1_0/Makefile.in
index dc8739c4640..0142c95c44f 100644
--- a/dlls/xinput9_1_0/Makefile.in
+++ b/dlls/xinput9_1_0/Makefile.in
@@ -5,7 +5,6 @@ DELAYIMPORTS = hid setupapi
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- hid.c \
- xinput_main.c
+ main.c
RC_SRCS = version.rc
--
2.32.0
1
4
[PATCH 2/4] gdi32: Use NtGdiScaleViewportExtEx for ScaleViewportExtEx implementation.
by Jacek Caban 06 Aug '21
by Jacek Caban 06 Aug '21
06 Aug '21
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/dc.c | 20 ++++--------
dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 2 --
dlls/gdi32/enhmfdrv/init.c | 2 +-
dlls/gdi32/gdi_private.h | 4 +++
dlls/gdi32/gdidc.c | 14 ++++++++
dlls/gdi32/mapping.c | 48 ++++++++++++++--------------
dlls/gdi32/mfdrv/dc.c | 4 +--
dlls/gdi32/mfdrv/init.c | 2 +-
dlls/gdi32/mfdrv/metafiledrv.h | 1 -
9 files changed, 52 insertions(+), 45 deletions(-)
2
1
06 Aug '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/dibdrv/dc.c | 4 ----
dlls/gdi32/driver.c | 2 --
dlls/gdi32/enhmfdrv/init.c | 2 --
dlls/gdi32/font.c | 2 --
dlls/gdi32/mapping.c | 10 ----------
dlls/gdi32/mfdrv/init.c | 2 --
dlls/gdi32/ntgdi_private.h | 2 --
dlls/gdi32/path.c | 2 --
dlls/wineandroid.drv/init.c | 2 --
dlls/winemac.drv/gdi.c | 2 --
dlls/wineps.drv/init.c | 2 --
dlls/winex11.drv/init.c | 2 --
dlls/winex11.drv/xrender.c | 2 --
include/wine/gdi_driver.h | 4 +---
14 files changed, 1 insertion(+), 39 deletions(-)
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 7a9296d58c0..467cdb144e6 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -700,8 +700,6 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
dibdrv_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
dibdrv_SelectBitmap, /* pSelectBitmap */
dibdrv_SelectBrush, /* pSelectBrush */
NULL, /* pSelectClipPath */
@@ -1282,8 +1280,6 @@ static const struct gdi_dc_funcs window_driver =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
windrv_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 1cefbfc3a44..21e066630fc 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -916,8 +916,6 @@ const struct gdi_dc_funcs null_driver =
nulldrv_ResetDC, /* pResetDC */
nulldrv_RestoreDC, /* pRestoreDC */
nulldrv_RoundRect, /* pRoundRect */
- nulldrv_ScaleViewportExtEx, /* pScaleViewportExt */
- nulldrv_ScaleWindowExtEx, /* pScaleWindowExt */
nulldrv_SelectBitmap, /* pSelectBitmap */
nulldrv_SelectBrush, /* pSelectBrush */
nulldrv_SelectClipPath, /* pSelectClipPath */
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index b104d58b6be..433c0be6c0c 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -114,8 +114,6 @@ static const struct gdi_dc_funcs emfdrv_driver =
NULL, /* pResetDC */
EMFDRV_RestoreDC, /* pRestoreDC */
EMFDRV_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExtEx */
- NULL, /* pScaleWindowExtEx */
EMFDRV_SelectBitmap, /* pSelectBitmap */
EMFDRV_SelectBrush, /* pSelectBrush */
EMFDRV_SelectClipPath, /* pSelectClipPath */
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index ea49815b579..b8dc2cc4b1f 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3891,8 +3891,6 @@ const struct gdi_dc_funcs font_driver =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
NULL, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/gdi32/mapping.c b/dlls/gdi32/mapping.c
index 189481c2e3e..0c440908beb 100644
--- a/dlls/gdi32/mapping.c
+++ b/dlls/gdi32/mapping.c
@@ -111,16 +111,6 @@ BOOL CDECL nulldrv_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
return TRUE;
}
-BOOL CDECL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size )
-{
- return TRUE;
-}
-
-BOOL CDECL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size )
-{
- return TRUE;
-}
-
BOOL set_map_mode( DC *dc, int mode )
{
SIZE virtual_size, virtual_res;
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index a860932d012..d606fccc84e 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -179,8 +179,6 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
NULL, /* pResetDC */
MFDRV_RestoreDC, /* pRestoreDC */
NULL, /* pRoundRect */
- NULL, /* pScaleViewportExtEx */
- NULL, /* pScaleWindowExtEx */
MFDRV_SelectBitmap, /* pSelectBitmap */
MFDRV_SelectBrush, /* pSelectBrush */
MFDRV_SelectClipPath, /* pSelectClipPath */
diff --git a/dlls/gdi32/ntgdi_private.h b/dlls/gdi32/ntgdi_private.h
index 07b761f272f..9af4aa3d61f 100644
--- a/dlls/gdi32/ntgdi_private.h
+++ b/dlls/gdi32/ntgdi_private.h
@@ -588,8 +588,6 @@ extern BOOL CDECL nulldrv_PolyBezierTo( PHYSDEV dev, const POINT *points, DWORD
extern BOOL CDECL nulldrv_PolyDraw( PHYSDEV dev, const POINT *points, const BYTE *types, DWORD count ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_PolylineTo( PHYSDEV dev, const POINT *points, INT count ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN;
-extern BOOL CDECL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN;
-extern BOOL CDECL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN;
extern BOOL CDECL nulldrv_SelectClipPath( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
extern INT CDECL nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height,
INT x_src, INT y_src, UINT start, UINT lines,
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index 51ab7a3dab9..57a93658abd 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -2152,8 +2152,6 @@ const struct gdi_dc_funcs path_driver =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
pathdrv_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c
index e055828af1c..b3d4f945993 100644
--- a/dlls/wineandroid.drv/init.c
+++ b/dlls/wineandroid.drv/init.c
@@ -361,8 +361,6 @@ static const struct gdi_dc_funcs android_drv_funcs =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
NULL, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c
index 4259ecc8b0b..b657afd5943 100644
--- a/dlls/winemac.drv/gdi.c
+++ b/dlls/winemac.drv/gdi.c
@@ -341,8 +341,6 @@ static const struct gdi_dc_funcs macdrv_funcs =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
NULL, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c
index 4d6e70a126f..e71e82e092f 100644
--- a/dlls/wineps.drv/init.c
+++ b/dlls/wineps.drv/init.c
@@ -855,8 +855,6 @@ static const struct gdi_dc_funcs psdrv_funcs =
PSDRV_ResetDC, /* pResetDC */
NULL, /* pRestoreDC */
PSDRV_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
PSDRV_SelectBrush, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 1b51da43423..937286b8601 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -420,8 +420,6 @@ static const struct gdi_dc_funcs x11drv_funcs =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
X11DRV_RoundRect, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
X11DRV_SelectBrush, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c
index 045f0c5f64b..3ab576ea8d5 100644
--- a/dlls/winex11.drv/xrender.c
+++ b/dlls/winex11.drv/xrender.c
@@ -2232,8 +2232,6 @@ static const struct gdi_dc_funcs xrender_funcs =
NULL, /* pResetDC */
NULL, /* pRestoreDC */
NULL, /* pRoundRect */
- NULL, /* pScaleViewportExt */
- NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
xrenderdrv_SelectBrush, /* pSelectBrush */
NULL, /* pSelectClipPath */
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 2f6fd4ff734..ffa730f9105 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -145,8 +145,6 @@ struct gdi_dc_funcs
HDC (CDECL *pResetDC)(PHYSDEV,const DEVMODEW*);
BOOL (CDECL *pRestoreDC)(PHYSDEV,INT);
BOOL (CDECL *pRoundRect)(PHYSDEV,INT,INT,INT,INT,INT,INT);
- BOOL (CDECL *pScaleViewportExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
- BOOL (CDECL *pScaleWindowExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
HBITMAP (CDECL *pSelectBitmap)(PHYSDEV,HBITMAP);
HBRUSH (CDECL *pSelectBrush)(PHYSDEV,HBRUSH,const struct brush_pattern*);
BOOL (CDECL *pSelectClipPath)(PHYSDEV,INT);
@@ -185,7 +183,7 @@ struct gdi_dc_funcs
};
/* increment this when you change the DC function table */
-#define WINE_GDI_DRIVER_VERSION 57
+#define WINE_GDI_DRIVER_VERSION 58
#define GDI_PRIORITY_NULL_DRV 0 /* null driver */
#define GDI_PRIORITY_FONT_DRV 100 /* any font driver */
--
2.23.0
1
0
[PATCH v2 3/4] gdi32: Use NtGdiScaleWindowExtEx for ScaleWindowExtEx implementation.
by Huw Davies 06 Aug '21
by Huw Davies 06 Aug '21
06 Aug '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/dc.c | 15 +++++-------
dlls/gdi32/enhmfdrv/init.c | 2 +-
dlls/gdi32/gdi_private.h | 4 ++++
dlls/gdi32/gdidc.c | 15 ++++++++++++
dlls/gdi32/mapping.c | 48 +++++++++++++++++++-------------------
dlls/gdi32/mfdrv/dc.c | 4 ++--
dlls/gdi32/mfdrv/init.c | 2 +-
7 files changed, 53 insertions(+), 37 deletions(-)
diff --git a/dlls/gdi32/enhmfdrv/dc.c b/dlls/gdi32/enhmfdrv/dc.c
index f544a5ab998..6b843b5a641 100644
--- a/dlls/gdi32/enhmfdrv/dc.c
+++ b/dlls/gdi32/enhmfdrv/dc.c
@@ -309,20 +309,17 @@ BOOL EMFDC_ScaleViewportExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_n
return EMFDRV_WriteRecord( dc_attr->emf, &emr.emr );
}
-BOOL CDECL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
+BOOL EMFDC_ScaleWindowExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_num, INT y_denom )
{
- PHYSDEV next = GET_NEXT_PHYSDEV( dev, pScaleWindowExtEx );
EMRSCALEWINDOWEXTEX emr;
emr.emr.iType = EMR_SCALEWINDOWEXTEX;
emr.emr.nSize = sizeof(emr);
- emr.xNum = xNum;
- emr.xDenom = xDenom;
- emr.yNum = yNum;
- emr.yDenom = yDenom;
-
- if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE;
- return next->funcs->pScaleWindowExtEx( next, xNum, xDenom, yNum, yDenom, size );
+ emr.xNum = x_num;
+ emr.xDenom = x_denom;
+ emr.yNum = y_num;
+ emr.yDenom = y_denom;
+ return EMFDRV_WriteRecord( dc_attr->emf, &emr.emr );
}
BOOL EMFDC_SetLayout( DC_ATTR *dc_attr, DWORD layout )
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 5b7c27f5fe1..b104d58b6be 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -115,7 +115,7 @@ static const struct gdi_dc_funcs emfdrv_driver =
EMFDRV_RestoreDC, /* pRestoreDC */
EMFDRV_RoundRect, /* pRoundRect */
NULL, /* pScaleViewportExtEx */
- EMFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */
+ NULL, /* pScaleWindowExtEx */
EMFDRV_SelectBitmap, /* pSelectBitmap */
EMFDRV_SelectBrush, /* pSelectBrush */
EMFDRV_SelectClipPath, /* pSelectClipPath */
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 895525317cc..ebea5565725 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -77,6 +77,8 @@ extern BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right, INT bottom,
extern BOOL METADC_SaveDC( HDC hdc ) DECLSPEC_HIDDEN;
extern BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num,
INT y_denom ) DECLSPEC_HIDDEN;
+extern BOOL METADC_ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num,
+ INT y_denom ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetBkMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetLayout( HDC hdc, DWORD layout ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra ) DECLSPEC_HIDDEN;
@@ -140,6 +142,8 @@ extern BOOL EMFDC_RoundRect( DC_ATTR *dc_attr, INT left, INT top, INT right, INT
extern BOOL EMFDC_SaveDC( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_ScaleViewportExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_num,
INT y_denom ) DECLSPEC_HIDDEN;
+extern BOOL EMFDC_ScaleWindowExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_num,
+ INT y_denom ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetArcDirection( DC_ATTR *dc_attr, INT dir ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetBkMode( DC_ATTR *dc_attr, INT mode ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetLayout( DC_ATTR *dc_attr, DWORD layout ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c
index 341944c70da..f3afb75a67e 100644
--- a/dlls/gdi32/gdidc.c
+++ b/dlls/gdi32/gdidc.c
@@ -1247,6 +1247,21 @@ BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom,
return NtGdiScaleViewportExtEx( hdc, x_num, x_denom, y_num, y_denom, size );
}
+/***********************************************************************
+ * ScaleWindowExtEx (GDI32.@)
+ */
+BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom,
+ INT y_num, INT y_denom, SIZE *size )
+{
+ DC_ATTR *dc_attr;
+
+ if (is_meta_dc( hdc )) return METADC_ScaleWindowExtEx( hdc, x_num, x_denom, y_num, y_denom );
+ if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
+ if (dc_attr->emf && !EMFDC_ScaleWindowExtEx( dc_attr, x_num, x_denom, y_num, y_denom ))
+ return FALSE;
+ return NtGdiScaleWindowExtEx( hdc, x_num, x_denom, y_num, y_denom, size );
+}
+
/***********************************************************************
* GdiSetPixelFormat (GDI32.@)
*/
diff --git a/dlls/gdi32/mapping.c b/dlls/gdi32/mapping.c
index 09ecec4f717..189481c2e3e 100644
--- a/dlls/gdi32/mapping.c
+++ b/dlls/gdi32/mapping.c
@@ -118,20 +118,6 @@ BOOL CDECL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT
BOOL CDECL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size )
{
- DC *dc = get_nulldrv_dc( dev );
-
- if (size)
- *size = dc->attr->wnd_ext;
-
- if (dc->attr->map_mode != MM_ISOTROPIC && dc->attr->map_mode != MM_ANISOTROPIC) return TRUE;
- if (!x_num || !x_denom || !y_num || !y_denom) return FALSE;
-
- dc->attr->wnd_ext.cx = (dc->attr->wnd_ext.cx * x_num) / x_denom;
- dc->attr->wnd_ext.cy = (dc->attr->wnd_ext.cy * y_num) / y_denom;
- if (dc->attr->wnd_ext.cx == 0) dc->attr->wnd_ext.cx = 1;
- if (dc->attr->wnd_ext.cy == 0) dc->attr->wnd_ext.cy = 1;
- if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
- DC_UpdateXforms( dc );
return TRUE;
}
@@ -535,21 +521,35 @@ BOOL WINAPI NtGdiScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom,
/***********************************************************************
- * ScaleWindowExtEx (GDI32.@)
+ * NtGdiScaleWindowExtEx (win32u.@)
*/
-BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom,
- INT yNum, INT yDenom, LPSIZE size )
+BOOL WINAPI NtGdiScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom,
+ INT y_num, INT y_denom, SIZE *size )
{
- BOOL ret = FALSE;
- DC * dc = get_dc_ptr( hdc );
+ DC *dc;
- if (dc)
+ if ((!(dc = get_dc_ptr( hdc )))) return FALSE;
+
+ if (size) *size = dc->attr->wnd_ext;
+
+ if (dc->attr->map_mode == MM_ISOTROPIC || dc->attr->map_mode == MM_ANISOTROPIC)
{
- PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleWindowExtEx );
- ret = physdev->funcs->pScaleWindowExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
- release_dc_ptr( dc );
+ if (!x_num || !x_denom || !y_num || !y_denom)
+ {
+ release_dc_ptr( dc );
+ return FALSE;
+ }
+
+ dc->attr->wnd_ext.cx = (dc->attr->wnd_ext.cx * x_num) / x_denom;
+ dc->attr->wnd_ext.cy = (dc->attr->wnd_ext.cy * y_num) / y_denom;
+ if (dc->attr->wnd_ext.cx == 0) dc->attr->wnd_ext.cx = 1;
+ if (dc->attr->wnd_ext.cy == 0) dc->attr->wnd_ext.cy = 1;
+ if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
+ DC_UpdateXforms( dc );
}
- return ret;
+
+ release_dc_ptr( dc );
+ return TRUE;
}
diff --git a/dlls/gdi32/mfdrv/dc.c b/dlls/gdi32/mfdrv/dc.c
index c96b1053eb5..fe89b0b6d5e 100644
--- a/dlls/gdi32/mfdrv/dc.c
+++ b/dlls/gdi32/mfdrv/dc.c
@@ -130,9 +130,9 @@ BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT
return metadc_param4( hdc, META_SCALEVIEWPORTEXT, x_num, x_denom, y_num, y_denom );
}
-BOOL CDECL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
+BOOL METADC_ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom )
{
- return MFDRV_MetaParam4( dev, META_SCALEWINDOWEXT, xNum, xDenom, yNum, yDenom );
+ return metadc_param4( hdc, META_SCALEWINDOWEXT, x_num, x_denom, y_num, y_denom );
}
BOOL METADC_SetTextJustification( HDC hdc, INT extra, INT breaks )
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index 9641887cb23..a860932d012 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -180,7 +180,7 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
MFDRV_RestoreDC, /* pRestoreDC */
NULL, /* pRoundRect */
NULL, /* pScaleViewportExtEx */
- MFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */
+ NULL, /* pScaleWindowExtEx */
MFDRV_SelectBitmap, /* pSelectBitmap */
MFDRV_SelectBrush, /* pSelectBrush */
MFDRV_SelectClipPath, /* pSelectClipPath */
--
2.23.0
1
0
[PATCH v2 2/4] gdi32: Use NtGdiScaleViewportExtEx for ScaleViewportExtEx implementation.
by Huw Davies 06 Aug '21
by Huw Davies 06 Aug '21
06 Aug '21
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/dc.c | 20 ++++--------
dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 2 --
dlls/gdi32/enhmfdrv/init.c | 2 +-
dlls/gdi32/gdi_private.h | 4 +++
dlls/gdi32/gdidc.c | 14 ++++++++
dlls/gdi32/mapping.c | 48 ++++++++++++++--------------
dlls/gdi32/mfdrv/dc.c | 4 +--
dlls/gdi32/mfdrv/init.c | 2 +-
dlls/gdi32/mfdrv/metafiledrv.h | 1 -
9 files changed, 52 insertions(+), 45 deletions(-)
diff --git a/dlls/gdi32/enhmfdrv/dc.c b/dlls/gdi32/enhmfdrv/dc.c
index 521d529728f..f544a5ab998 100644
--- a/dlls/gdi32/enhmfdrv/dc.c
+++ b/dlls/gdi32/enhmfdrv/dc.c
@@ -296,25 +296,17 @@ BOOL CDECL EMFDRV_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
return ret;
}
-BOOL CDECL EMFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
+BOOL EMFDC_ScaleViewportExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_num, INT y_denom )
{
- PHYSDEV next = GET_NEXT_PHYSDEV( dev, pScaleViewportExtEx );
- EMFDRV_PDEVICE *physDev = get_emf_physdev( dev );
EMRSCALEVIEWPORTEXTEX emr;
- BOOL ret;
emr.emr.iType = EMR_SCALEVIEWPORTEXTEX;
emr.emr.nSize = sizeof(emr);
- emr.xNum = xNum;
- emr.xDenom = xDenom;
- emr.yNum = yNum;
- emr.yDenom = yDenom;
-
- if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE;
- physDev->modifying_transform++;
- ret = next->funcs->pScaleViewportExtEx( next, xNum, xDenom, yNum, yDenom, size );
- physDev->modifying_transform--;
- return ret;
+ emr.xNum = x_num;
+ emr.xDenom = x_denom;
+ emr.yNum = y_num;
+ emr.yDenom = y_denom;
+ return EMFDRV_WriteRecord( dc_attr->emf, &emr.emr );
}
BOOL CDECL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
index d165f153a22..1cb580dfc36 100644
--- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
+++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
@@ -98,8 +98,6 @@ extern BOOL CDECL EMFDRV_Rectangle( PHYSDEV dev, INT left, INT top, INT righ
extern BOOL CDECL EMFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN;
extern BOOL CDECL EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
-extern BOOL CDECL EMFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom,
- INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
extern BOOL CDECL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom,
INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
extern HBITMAP CDECL EMFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 63784f62841..5b7c27f5fe1 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -114,7 +114,7 @@ static const struct gdi_dc_funcs emfdrv_driver =
NULL, /* pResetDC */
EMFDRV_RestoreDC, /* pRestoreDC */
EMFDRV_RoundRect, /* pRoundRect */
- EMFDRV_ScaleViewportExtEx, /* pScaleViewportExtEx */
+ NULL, /* pScaleViewportExtEx */
EMFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */
EMFDRV_SelectBitmap, /* pSelectBitmap */
EMFDRV_SelectBrush, /* pSelectBrush */
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 53a4ba267d4..895525317cc 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -75,6 +75,8 @@ extern BOOL METADC_Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom)
extern BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right, INT bottom,
INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
extern BOOL METADC_SaveDC( HDC hdc ) DECLSPEC_HIDDEN;
+extern BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num,
+ INT y_denom ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetBkMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetLayout( HDC hdc, DWORD layout ) DECLSPEC_HIDDEN;
extern BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra ) DECLSPEC_HIDDEN;
@@ -136,6 +138,8 @@ extern BOOL EMFDC_Rectangle( DC_ATTR *dc_attr, INT left, INT top, INT right,
extern BOOL EMFDC_RoundRect( DC_ATTR *dc_attr, INT left, INT top, INT right, INT bottom,
INT ell_width, INT ell_height ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SaveDC( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
+extern BOOL EMFDC_ScaleViewportExtEx( DC_ATTR *dc_attr, INT x_num, INT x_denom, INT y_num,
+ INT y_denom ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetArcDirection( DC_ATTR *dc_attr, INT dir ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetBkMode( DC_ATTR *dc_attr, INT mode ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_SetLayout( DC_ATTR *dc_attr, DWORD layout ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c
index 69e59c580f0..341944c70da 100644
--- a/dlls/gdi32/gdidc.c
+++ b/dlls/gdi32/gdidc.c
@@ -1232,6 +1232,20 @@ BOOL WINAPI LPtoDP( HDC hdc, POINT *points, INT count )
return NtGdiTransformPoints( hdc, points, points, count, NtGdiLPtoDP );
}
+/***********************************************************************
+ * ScaleViewportExtEx (GDI32.@)
+ */
+BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom,
+ INT y_num, INT y_denom, SIZE *size )
+{
+ DC_ATTR *dc_attr;
+
+ if (is_meta_dc( hdc )) return METADC_ScaleViewportExtEx( hdc, x_num, x_denom, y_num, y_denom );
+ if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
+ if (dc_attr->emf && !EMFDC_ScaleViewportExtEx( dc_attr, x_num, x_denom, y_num, y_denom ))
+ return FALSE;
+ return NtGdiScaleViewportExtEx( hdc, x_num, x_denom, y_num, y_denom, size );
+}
/***********************************************************************
* GdiSetPixelFormat (GDI32.@)
diff --git a/dlls/gdi32/mapping.c b/dlls/gdi32/mapping.c
index 7ec20957e92..09ecec4f717 100644
--- a/dlls/gdi32/mapping.c
+++ b/dlls/gdi32/mapping.c
@@ -113,20 +113,6 @@ BOOL CDECL nulldrv_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
BOOL CDECL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size )
{
- DC *dc = get_nulldrv_dc( dev );
-
- if (size)
- *size = dc->attr->vport_ext;
-
- if (dc->attr->map_mode != MM_ISOTROPIC && dc->attr->map_mode != MM_ANISOTROPIC) return TRUE;
- if (!x_num || !x_denom || !y_num || !y_denom) return FALSE;
-
- dc->attr->vport_ext.cx = (dc->attr->vport_ext.cx * x_num) / x_denom;
- dc->attr->vport_ext.cy = (dc->attr->vport_ext.cy * y_num) / y_denom;
- if (dc->attr->vport_ext.cx == 0) dc->attr->vport_ext.cx = 1;
- if (dc->attr->vport_ext.cy == 0) dc->attr->vport_ext.cy = 1;
- if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
- DC_UpdateXforms( dc );
return TRUE;
}
@@ -516,21 +502,35 @@ BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
/***********************************************************************
- * ScaleViewportExtEx (GDI32.@)
+ * NtGdiScaleViewportExtEx (win32u.@)
*/
-BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom,
- INT yNum, INT yDenom, LPSIZE size )
+BOOL WINAPI NtGdiScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom,
+ INT y_num, INT y_denom, SIZE *size )
{
- BOOL ret = FALSE;
- DC * dc = get_dc_ptr( hdc );
+ DC *dc;
- if (dc)
+ if ((!(dc = get_dc_ptr( hdc )))) return FALSE;
+
+ if (size) *size = dc->attr->vport_ext;
+
+ if (dc->attr->map_mode == MM_ISOTROPIC || dc->attr->map_mode == MM_ANISOTROPIC)
{
- PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleViewportExtEx );
- ret = physdev->funcs->pScaleViewportExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
- release_dc_ptr( dc );
+ if (!x_num || !x_denom || !y_num || !y_denom)
+ {
+ release_dc_ptr( dc );
+ return FALSE;
+ }
+
+ dc->attr->vport_ext.cx = (dc->attr->vport_ext.cx * x_num) / x_denom;
+ dc->attr->vport_ext.cy = (dc->attr->vport_ext.cy * y_num) / y_denom;
+ if (dc->attr->vport_ext.cx == 0) dc->attr->vport_ext.cx = 1;
+ if (dc->attr->vport_ext.cy == 0) dc->attr->vport_ext.cy = 1;
+ if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
+ DC_UpdateXforms( dc );
}
- return ret;
+
+ release_dc_ptr( dc );
+ return TRUE;
}
diff --git a/dlls/gdi32/mfdrv/dc.c b/dlls/gdi32/mfdrv/dc.c
index 7172d74ebb8..c96b1053eb5 100644
--- a/dlls/gdi32/mfdrv/dc.c
+++ b/dlls/gdi32/mfdrv/dc.c
@@ -125,9 +125,9 @@ BOOL CDECL MFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
return MFDRV_MetaParam2( dev, META_OFFSETWINDOWORG, x, y );
}
-BOOL CDECL MFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
+BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom )
{
- return MFDRV_MetaParam4( dev, META_SCALEVIEWPORTEXT, xNum, xDenom, yNum, yDenom );
+ return metadc_param4( hdc, META_SCALEVIEWPORTEXT, x_num, x_denom, y_num, y_denom );
}
BOOL CDECL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size )
diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c
index 6af270c709e..9641887cb23 100644
--- a/dlls/gdi32/mfdrv/init.c
+++ b/dlls/gdi32/mfdrv/init.c
@@ -179,7 +179,7 @@ static const struct gdi_dc_funcs MFDRV_Funcs =
NULL, /* pResetDC */
MFDRV_RestoreDC, /* pRestoreDC */
NULL, /* pRoundRect */
- MFDRV_ScaleViewportExtEx, /* pScaleViewportExtEx */
+ NULL, /* pScaleViewportExtEx */
MFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */
MFDRV_SelectBitmap, /* pSelectBitmap */
MFDRV_SelectBrush, /* pSelectBrush */
diff --git a/dlls/gdi32/mfdrv/metafiledrv.h b/dlls/gdi32/mfdrv/metafiledrv.h
index fb3326af36e..9610a2fb17d 100644
--- a/dlls/gdi32/mfdrv/metafiledrv.h
+++ b/dlls/gdi32/mfdrv/metafiledrv.h
@@ -91,7 +91,6 @@ extern BOOL CDECL MFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt
extern BOOL CDECL MFDRV_PolyBezier( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN;
extern BOOL CDECL MFDRV_PolyBezierTo( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN;
extern BOOL CDECL MFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN;
-extern BOOL CDECL MFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
extern BOOL CDECL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN;
extern HBITMAP CDECL MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN;
extern HBRUSH CDECL MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN;
--
2.23.0
1
0
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/gdi32/gdiobj.c | 14 ++++++++++++--
dlls/gdi32/tests/gdiobj.c | 1 -
include/ntgdi.h | 5 +++--
3 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c
index 16a7b897e30..326414372e6 100644
--- a/dlls/gdi32/gdiobj.c
+++ b/dlls/gdi32/gdiobj.c
@@ -613,6 +613,16 @@ static void set_gdi_shared(void)
NtCurrentTeb()->Peb->GdiSharedHandleTable = &gdi_shared;
}
+static HGDIOBJ make_stock_object( HGDIOBJ obj )
+{
+ GDI_HANDLE_ENTRY *entry;
+
+ if (!(entry = handle_entry( obj ))) return 0;
+ entry_obj( entry )->system = TRUE;
+ entry->StockFlag = 1;
+ return entry_to_handle( entry );
+}
+
/***********************************************************************
* DllMain
*
@@ -668,8 +678,8 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
/* clear the NOSYSTEM bit on all stock objects*/
for (i = 0; i < NB_STOCK_OBJECTS; i++)
{
- if (stock_objects[i]) __wine_make_gdi_object_system( stock_objects[i], TRUE );
- if (scaled_stock_objects[i]) __wine_make_gdi_object_system( scaled_stock_objects[i], TRUE );
+ stock_objects[i] = make_stock_object( stock_objects[i] );
+ scaled_stock_objects[i] = make_stock_object( scaled_stock_objects[i] );
}
return TRUE;
}
diff --git a/dlls/gdi32/tests/gdiobj.c b/dlls/gdi32/tests/gdiobj.c
index 789c9ecb0f8..64d37e39ab6 100644
--- a/dlls/gdi32/tests/gdiobj.c
+++ b/dlls/gdi32/tests/gdiobj.c
@@ -396,7 +396,6 @@ static void test_shared_handle_entry( HGDIOBJ obj, unsigned int type, BOOL is_st
todo_wine
ok(entry->ExtType == NTGDI_OBJ_DC, "ExtType = %x, expected NTGDI_OBJ_DC\n", entry->ExtType);
}
- todo_wine_if(is_stock)
ok(entry->StockFlag == is_stock, "StockFlag = %x\n", entry->StockFlag);
ok(entry->Type == (type & 0x1f), "Type = %x, expected %x\n", entry->Type, type & 0x1f);
ok(entry->Object, "Object = NULL\n");
diff --git a/include/ntgdi.h b/include/ntgdi.h
index d023d10bfc6..d6d7a5572d1 100644
--- a/include/ntgdi.h
+++ b/include/ntgdi.h
@@ -67,8 +67,9 @@ typedef struct _GDI_HANDLE_ENTRY
/* Wine extension, native uses NTGDI_OBJ_DC */
#define NTGDI_OBJ_MEMDC 0x41
-#define NTGDI_HANDLE_TYPE_SHIFT 16
-#define NTGDI_HANDLE_TYPE_MASK 0x007f0000
+#define NTGDI_HANDLE_TYPE_SHIFT 16
+#define NTGDI_HANDLE_TYPE_MASK 0x007f0000
+#define NTGDI_HANDLE_STOCK_OBJECT 0x00800000
typedef struct _GDI_SHARED_MEMORY
{
--
2.23.0
1
0
From: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/jscript/json.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
1
0
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
v3: Add a "default_input_count" field to effect_test.
Remove off_limit_tests variable.
Add winetest_push_context() to loop.
Split a loop into two loops.
Use individual todo_wine rather than todo_wine block.
dlls/d2d1/tests/d2d1.c | 82 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 78 insertions(+), 4 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 629bbd65523..146952d7418 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -9680,13 +9680,16 @@ static void test_mt_factory(BOOL d3d11)
static void test_effect(BOOL d3d11)
{
- unsigned int i, min_inputs, max_inputs, str_size;
+ unsigned int i, j, min_inputs, max_inputs, str_size, input_count;
+ D2D1_BITMAP_PROPERTIES bitmap_desc;
D2D1_BUFFER_PRECISION precision;
ID2D1Image *image_a, *image_b;
struct d2d1_test_context ctx;
ID2D1DeviceContext *context;
ID2D1Factory1 *factory;
+ ID2D1Bitmap *bitmap;
ID2D1Effect *effect;
+ D2D1_SIZE_U size;
BYTE buffer[64];
BOOL cached;
CLSID clsid;
@@ -9695,14 +9698,15 @@ static void test_effect(BOOL d3d11)
const struct effect_test
{
const CLSID *clsid;
+ UINT32 default_input_count;
UINT32 min_inputs;
UINT32 max_inputs;
}
effect_tests[] =
{
- {&CLSID_D2D12DAffineTransform, 1, 1},
- {&CLSID_D2D13DPerspectiveTransform, 1, 1},
- {&CLSID_D2D1Composite, 1, 0xffffffff},
+ {&CLSID_D2D12DAffineTransform, 1, 1, 1},
+ {&CLSID_D2D13DPerspectiveTransform, 1, 1, 1},
+ {&CLSID_D2D1Composite, 2, 1, 0xffffffff},
};
if (!init_test_context(&ctx, d3d11))
@@ -9797,6 +9801,76 @@ static void test_effect(BOOL d3d11)
max_inputs, test->max_inputs);
}
+ input_count = ID2D1Effect_GetInputCount(effect);
+ todo_wine
+ ok (input_count == test->default_input_count, "Got unexpected input count %u, expected %u.\n",
+ input_count, test->default_input_count);
+
+ input_count = (test->max_inputs < 16 ? test->max_inputs : 16);
+ for (j = 0; j < input_count + 4; ++j)
+ {
+ winetest_push_context("Input %u", j);
+ hr = ID2D1Effect_SetInputCount(effect, j);
+ if (j < test->min_inputs || j > test->max_inputs)
+ todo_wine
+ ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+ else
+ todo_wine
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ winetest_pop_context();
+ }
+
+ input_count = ID2D1Effect_GetInputCount(effect);
+ for (j = 0; j < input_count + 4; ++j)
+ {
+ winetest_push_context("Input %u", j);
+ ID2D1Effect_GetInput(effect, j, &image_a);
+ todo_wine
+ ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
+ winetest_pop_context();
+ }
+
+ set_size_u(&size, 1, 1);
+ bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
+ bitmap_desc.dpiX = 96.0f;
+ bitmap_desc.dpiY = 96.0f;
+ hr = ID2D1RenderTarget_CreateBitmap(ctx.rt, size, NULL, 4, &bitmap_desc, &bitmap);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
+ for (j = 0; j < input_count + 4; ++j)
+ {
+ winetest_push_context("Input %u", j);
+ image_a = (ID2D1Image *)0xdeadbeef;
+ ID2D1Effect_GetInput(effect, j, &image_a);
+ if (j == 0)
+ {
+ todo_wine
+ ok(image_a == (ID2D1Image *)bitmap, "Got unexpected image_a %p.\n", image_a);
+ if (image_a == (ID2D1Image *)bitmap)
+ ID2D1Image_Release(image_a);
+ }
+ else
+ {
+ todo_wine
+ ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
+ }
+ winetest_pop_context();
+ }
+
+ for (j = input_count; j < input_count + 4; ++j)
+ {
+ winetest_push_context("Input %u", j);
+ image_a = (ID2D1Image *)0xdeadbeef;
+ ID2D1Effect_SetInput(effect, j, (ID2D1Image *)bitmap, FALSE);
+ ID2D1Effect_GetInput(effect, j, &image_a);
+ todo_wine
+ ok(image_a == NULL, "Got unexpected image_a %p.\n", image_a);
+ winetest_pop_context();
+ }
+ ID2D1Bitmap_Release(bitmap);
+
ID2D1Effect_Release(effect);
winetest_pop_context();
}
--
2.25.1
3
8
[PATCH] wined3d: Don't try to reset query pools if we don't have a command buffer.
by Jan Sikorski 06 Aug '21
by Jan Sikorski 06 Aug '21
06 Aug '21
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51419
Signed-off-by: Jan Sikorski <jsikorski(a)codeweavers.com>
---
dlls/wined3d/context_vk.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index eac4eacff5a..8df416851f2 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1314,12 +1314,15 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte
context_vk->vk_framebuffer = VK_NULL_HANDLE;
}
- LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
- struct wined3d_query_pool_vk, completed_entry)
+ if (vk_command_buffer)
{
- list_remove(&pool_vk->completed_entry);
- list_init(&pool_vk->completed_entry);
- wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
+ LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
+ struct wined3d_query_pool_vk, completed_entry)
+ {
+ list_remove(&pool_vk->completed_entry);
+ list_init(&pool_vk->completed_entry);
+ wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
+ }
}
}
--
2.30.2
2
3
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/jscript/json.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c
index a8014f95b4f..20234807727 100644
--- a/dlls/jscript/json.c
+++ b/dlls/jscript/json.c
@@ -291,16 +291,21 @@ static HRESULT JSON_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsign
parse_ctx.end = buf + jsstr_length(str);
parse_ctx.ctx = ctx;
hres = parse_json_value(&parse_ctx, &ret);
- jsstr_release(str);
if(FAILED(hres))
+ {
+ jsstr_release(str);
return hres;
+ }
if(skip_spaces(&parse_ctx)) {
FIXME("syntax error\n");
+ jsstr_release(str);
jsval_release(ret);
return E_FAIL;
}
+ jsstr_release(str);
+
if(r)
*r = ret;
else
--
2.31.1
1
0