Merge commit 'a22ac9e1c8e7b1cd78aa197bf1727a9f97f74b5e' into dev

This commit is contained in:
SimoneN64
2024-09-22 15:30:30 +02:00
60 changed files with 2597 additions and 1126 deletions

View File

@@ -1525,7 +1525,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)(
const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL);
// This is only called at startup, to initialize the environment
SDL_setenv_unsafe(utfname, utfvalue, 1);
// Note that we call setenv() directly to avoid affecting SDL environments
setenv(utfname, utfvalue, 1);
(*env)->ReleaseStringUTFChars(env, name, utfname);
(*env)->ReleaseStringUTFChars(env, value, utfvalue);

View File

@@ -33,6 +33,8 @@
#include <limits.h>
#endif
#include "SDL_iostream_c.h"
/* This file provides a general interface for SDL to read and write
data sources. It can easily be extended to files, memory, etc.
*/

View File

@@ -155,12 +155,12 @@ static const SDL_GPUBootstrap *backends[] = {
#ifdef SDL_GPU_METAL
&MetalDriver,
#endif
#ifdef SDL_GPU_D3D12
&D3D12Driver,
#endif
#ifdef SDL_GPU_VULKAN
&VulkanDriver,
#endif
#ifdef SDL_GPU_D3D12
&D3D12Driver,
#endif
#ifdef SDL_GPU_D3D11
&D3D11Driver,
#endif
@@ -959,6 +959,10 @@ SDL_GPUTexture *SDL_CreateGPUTexture(
SDL_assert_release(!"For array textures: usage must not contain DEPTH_STENCIL_TARGET");
failed = true;
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) {
SDL_assert_release(!"For array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1");
failed = true;
}
}
if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) {
SDL_assert_release(!"For 2D multisample textures: num_levels must be 1");
@@ -1378,6 +1382,9 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) {
SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!");
}
if (!(resolveTextureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) {
SDL_assert_release(!"Resolve texture usage must include COLOR_TARGET!");
}
}
}
}

View File

@@ -2081,29 +2081,21 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
if (isMultisample) {
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else if (isMultisample) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else {
if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
} else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
}
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
}
res = ID3D11Device_CreateRenderTargetView(

View File

@@ -2957,31 +2957,23 @@ static D3D12Texture *D3D12_INTERNAL_CreateTexture(
rtvDesc.Format = SDLToD3D12_TextureFormat[createinfo->format];
if (isMultisample) {
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
rtvDesc.Texture2DArray.PlaneSlice = 0;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else if (isMultisample) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
} else {
if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE || createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = levelIndex;
rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
rtvDesc.Texture2DArray.ArraySize = 1;
rtvDesc.Texture2DArray.PlaneSlice = 0;
} else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = levelIndex;
rtvDesc.Texture3D.FirstWSlice = depthIndex;
rtvDesc.Texture3D.WSize = 1;
} else {
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
rtvDesc.Texture2D.PlaneSlice = 0;
}
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = levelIndex;
rtvDesc.Texture2D.PlaneSlice = 0;
}
ID3D12Device_CreateRenderTargetView(

View File

@@ -313,14 +313,6 @@ static NSUInteger SDLToMetal_SampleCount[] = {
8 // SDL_GPU_SAMPLECOUNT_8
};
static MTLTextureType SDLToMetal_TextureType[] = {
MTLTextureType2D, // SDL_GPU_TEXTURETYPE_2D
MTLTextureType2DArray, // SDL_GPU_TEXTURETYPE_2D_ARRAY
MTLTextureType3D, // SDL_GPU_TEXTURETYPE_3D
MTLTextureTypeCube, // SDL_GPU_TEXTURETYPE_CUBE
MTLTextureTypeCubeArray // SDL_GPU_TEXTURETYPE_CUBE_ARRAY
};
static SDL_GPUTextureFormat SwapchainCompositionToFormat[] = {
SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, // SDR
SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_LINEAR
@@ -330,6 +322,24 @@ static SDL_GPUTextureFormat SwapchainCompositionToFormat[] = {
static CFStringRef SwapchainCompositionToColorSpace[4]; // initialized on device creation
static MTLTextureType SDLToMetal_TextureType(SDL_GPUTextureType textureType, bool isMSAA)
{
switch (textureType) {
case SDL_GPU_TEXTURETYPE_2D:
return isMSAA ? MTLTextureType2DMultisample : MTLTextureType2D;
case SDL_GPU_TEXTURETYPE_2D_ARRAY:
return MTLTextureType2DArray;
case SDL_GPU_TEXTURETYPE_3D:
return MTLTextureType3D;
case SDL_GPU_TEXTURETYPE_CUBE:
return MTLTextureTypeCube;
case SDL_GPU_TEXTURETYPE_CUBE_ARRAY:
return MTLTextureTypeCubeArray;
default:
return MTLTextureType2D;
}
}
static MTLColorWriteMask SDLToMetal_ColorWriteMask(
SDL_GPUColorComponentFlags mask)
{
@@ -1198,8 +1208,10 @@ static void METAL_InsertDebugLabel(
[metalCommandBuffer->computeEncoder insertDebugSignpost:label];
} else {
// Metal doesn't have insertDebugSignpost for command buffers...
[metalCommandBuffer->handle pushDebugGroup:label];
[metalCommandBuffer->handle popDebugGroup];
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
[metalCommandBuffer->handle popDebugGroup];
}
}
}
}
@@ -1219,7 +1231,9 @@ static void METAL_PushDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder pushDebugGroup:label];
} else {
[metalCommandBuffer->handle pushDebugGroup:label];
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle pushDebugGroup:label];
}
}
}
}
@@ -1237,7 +1251,9 @@ static void METAL_PopDebugGroup(
} else if (metalCommandBuffer->computeEncoder) {
[metalCommandBuffer->computeEncoder popDebugGroup];
} else {
[metalCommandBuffer->handle popDebugGroup];
if (@available(macOS 10.13, *)) {
[metalCommandBuffer->handle popDebugGroup];
}
}
}
}
@@ -1317,15 +1333,19 @@ static MetalTexture *METAL_INTERNAL_CreateTexture(
id<MTLTexture> texture;
MetalTexture *metalTexture;
textureDescriptor.textureType = SDLToMetal_TextureType[createinfo->type];
textureDescriptor.textureType = SDLToMetal_TextureType(createinfo->type, createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1);
textureDescriptor.pixelFormat = SDLToMetal_SurfaceFormat[createinfo->format];
// This format isn't natively supported so let's swizzle!
if (createinfo->format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(
MTLTextureSwizzleBlue,
MTLTextureSwizzleGreen,
MTLTextureSwizzleRed,
MTLTextureSwizzleAlpha);
if (@available(macOS 10.15, *)) {
textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(MTLTextureSwizzleBlue,
MTLTextureSwizzleGreen,
MTLTextureSwizzleRed,
MTLTextureSwizzleAlpha);
} else {
SDL_SetError("SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM is not supported");
return NULL;
}
}
textureDescriptor.width = createinfo->width;
@@ -2955,7 +2975,7 @@ static void METAL_BeginComputePass(
METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
textureView = [texture->handle newTextureViewWithPixelFormat:SDLToMetal_SurfaceFormat[textureContainer->header.info.format]
textureType:SDLToMetal_TextureType[textureContainer->header.info.type]
textureType:SDLToMetal_TextureType(textureContainer->header.info.type, false)
levels:NSMakeRange(storageTextureBindings[i].mip_level, 1)
slices:NSMakeRange(storageTextureBindings[i].layer, 1)];
@@ -3409,7 +3429,9 @@ static Uint8 METAL_INTERNAL_CreateSwapchain(
windowData->layer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(windowData->view));
windowData->layer.device = renderer->device;
#ifdef SDL_PLATFORM_MACOS
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
#ifndef SDL_PLATFORM_TVOS
@@ -3632,7 +3654,9 @@ static bool METAL_SetSwapchainParameters(
METAL_Wait(driverData);
#ifdef SDL_PLATFORM_MACOS
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
if (@available(macOS 10.13, *)) {
windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
}
#endif
windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
#ifndef SDL_PLATFORM_TVOS
@@ -3763,8 +3787,12 @@ static bool METAL_SupportsTextureFormat(
// Cube arrays are not supported on older iOS devices
if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
if (!([renderer->device supportsFamily:MTLGPUFamilyCommon2] ||
[renderer->device supportsFamily:MTLGPUFamilyApple4])) {
if (@available(macOS 10.15, *)) {
if (!([renderer->device supportsFamily:MTLGPUFamilyCommon2] ||
[renderer->device supportsFamily:MTLGPUFamilyApple4])) {
return false;
}
} else {
return false;
}
}
@@ -3774,7 +3802,11 @@ static bool METAL_SupportsTextureFormat(
case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
return [renderer->device supportsFamily:MTLGPUFamilyApple1];
if (@available(macOS 10.15, *)) {
return [renderer->device supportsFamily:MTLGPUFamilyApple1];
} else {
return false;
}
// Requires BC compression support
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:

File diff suppressed because it is too large Load Diff

View File

@@ -1572,7 +1572,7 @@ int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char
}
memcpy(buf, descriptor_buf, copy_len);
return copy_len;
return (int)copy_len;
}
else {
register_device_error(dev, "Failed to get kIOHIDReportDescriptorKey property");

View File

@@ -806,6 +806,9 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
// The original SHIELD controller has a touchpad and plus/minus buttons as well
SDL_strlcat(mapping_string, "touchpad:b12,misc2:b13,misc3:b14", sizeof(mapping_string));
}
} else if (SDL_IsJoystickHoriSteamController(vendor, product)) {
/* The Wireless HORIPad for Steam has QAM, Steam, Capsense L/R Sticks, 2 rear buttons, and 2 misc buttons */
SDL_strlcat(mapping_string, "paddle1:b13,paddle2:b12,paddle3:b15,paddle4:b14,misc2:b11,misc3:b16,misc4:b17", sizeof(mapping_string));
} else {
switch (SDL_GetGamepadTypeFromGUID(guid, NULL)) {
case SDL_GAMEPAD_TYPE_PS4:

View File

@@ -366,6 +366,7 @@ static Uint32 initial_wheel_devices[] = {
MAKE_VIDPID(0x044f, 0xb65e), // Thrustmaster T500RS
MAKE_VIDPID(0x044f, 0xb664), // Thrustmaster TX (initial mode)
MAKE_VIDPID(0x044f, 0xb669), // Thrustmaster TX (active mode)
MAKE_VIDPID(0x044f, 0xb67f), // Thrustmaster TMX
MAKE_VIDPID(0x044f, 0xb691), // Thrustmaster TS-XW (initial mode)
MAKE_VIDPID(0x044f, 0xb692), // Thrustmaster TS-XW (active mode)
MAKE_VIDPID(0x0483, 0x0522), // Simagic Wheelbase (including M10, Alpha Mini, Alpha, Alpha U)
@@ -3099,6 +3100,11 @@ bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id)
return eType == k_eControllerType_SteamController || eType == k_eControllerType_SteamControllerV2;
}
bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id)
{
return vendor_id == USB_VENDOR_HORI && (product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER || product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER_BT);
}
bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id)
{
EControllerType eType = GuessControllerType(vendor_id, product_id);

View File

@@ -129,6 +129,9 @@ extern bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 produc
// Function to return whether a joystick is a Steam Controller
extern bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id);
// Function to return whether a joystick is a HORI Steam controller
extern bool SDL_IsJoystickHoriSteamController(Uint16 vendor_id, Uint16 product_id);
// Function to return whether a joystick is a Steam Deck
extern bool SDL_IsJoystickSteamDeck(Uint16 vendor_id, Uint16 product_id);

View File

@@ -0,0 +1,415 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_JOYSTICK_HIDAPI
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../SDL_joystick_c.h"
#ifdef SDL_JOYSTICK_HIDAPI_STEAM_HORI
/* Define this if you want to log all packets from the controller */
/*#define DEBUG_HORI_PROTOCOL*/
#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
enum
{
SDL_GAMEPAD_BUTTON_HORI_QAM = 11,
SDL_GAMEPAD_BUTTON_HORI_FR,
SDL_GAMEPAD_BUTTON_HORI_FL,
SDL_GAMEPAD_BUTTON_HORI_M1,
SDL_GAMEPAD_BUTTON_HORI_M2,
SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_L,
SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_R,
SDL_GAMEPAD_NUM_HORI_BUTTONS
};
typedef struct
{
Uint8 last_state[USB_PACKET_LENGTH];
Uint64 sensor_ticks;
Uint32 last_tick;
bool wireless;
bool serial_needs_init;
} SDL_DriverSteamHori_Context;
static bool HIDAPI_DriverSteamHori_UpdateDevice(SDL_HIDAPI_Device *device);
static void HIDAPI_DriverSteamHori_RegisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, callback, userdata);
}
static void HIDAPI_DriverSteamHori_UnregisterHints(SDL_HintCallback callback, void *userdata)
{
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, callback, userdata);
}
static bool HIDAPI_DriverSteamHori_IsEnabled(void)
{
return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI, SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI, SDL_HIDAPI_DEFAULT));
}
static bool HIDAPI_DriverSteamHori_IsSupportedDevice(SDL_HIDAPI_Device *device, const char *name, SDL_GamepadType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
{
return SDL_IsJoystickHoriSteamController(vendor_id, product_id);
}
static bool HIDAPI_DriverSteamHori_InitDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteamHori_Context *ctx;
ctx = (SDL_DriverSteamHori_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
return false;
}
device->context = ctx;
ctx->serial_needs_init = true;
HIDAPI_SetDeviceName(device, "Wireless HORIPAD For Steam");
return HIDAPI_JoystickConnected(device, NULL);
}
static int HIDAPI_DriverSteamHori_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id)
{
return -1;
}
static void HIDAPI_DriverSteamHori_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
{
}
static bool HIDAPI_DriverSteamHori_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteamHori_Context *ctx = (SDL_DriverSteamHori_Context *)device->context;
SDL_AssertJoysticksLocked();
SDL_zeroa(ctx->last_state);
/* Initialize the joystick capabilities */
joystick->nbuttons = SDL_GAMEPAD_NUM_HORI_BUTTONS;
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
joystick->nhats = 1;
ctx->wireless = device->product_id == USB_PRODUCT_HORI_STEAM_CONTROLLER_BT;
if (ctx->wireless && device->serial) {
joystick->serial = SDL_strdup(device->serial);
ctx->serial_needs_init = false;
} else if (!ctx->wireless) {
// Need to actual read from the device to init the serial
HIDAPI_DriverSteamHori_UpdateDevice(device);
}
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f);
return true;
}
static bool HIDAPI_DriverSteamHori_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
// Device doesn't support rumble
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
{
return SDL_Unsupported();
}
static Uint32 HIDAPI_DriverSteamHori_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return 0;
}
static bool HIDAPI_DriverSteamHori_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size)
{
return SDL_Unsupported();
}
static bool HIDAPI_DriverSteamHori_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
{
return true;
}
#undef clamp
#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
#ifndef DEG2RAD
#define DEG2RAD(x) ((float)(x) * (float)(SDL_PI_F / 180.f))
#endif
//---------------------------------------------------------------------------
// Scale and clamp values to a range
//---------------------------------------------------------------------------
static float RemapValClamped(float val, float A, float B, float C, float D)
{
if (A == B) {
return (val - B) >= 0.0f ? D : C;
} else {
float cVal = (val - A) / (B - A);
cVal = clamp(cVal, 0.0f, 1.0f);
return C + (D - C) * cVal;
}
}
#define REPORT_HEADER_USB 0x07
#define REPORT_HEADER_BT 0x00
static void HIDAPI_DriverSteamHori_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverSteamHori_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
Uint64 timestamp = SDL_GetTicksNS();
// Make sure it's gamepad state and not OTA FW update info
if (data[0] != REPORT_HEADER_USB && data[0] != REPORT_HEADER_BT) {
/* We don't know how to handle this report */
return;
}
#define READ_STICK_AXIS(offset) \
(data[offset] == 0x80 ? 0 : (Sint16)HIDAPI_RemapVal((float)((int)data[offset] - 0x80), -0x80, 0xff - 0x80, SDL_MIN_SINT16, SDL_MAX_SINT16))
{
axis = READ_STICK_AXIS(1);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, axis);
axis = READ_STICK_AXIS(2);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, axis);
axis = READ_STICK_AXIS(3);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, axis);
axis = READ_STICK_AXIS(4);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, axis);
}
#undef READ_STICK_AXIS
if (ctx->last_state[5] != data[5]) {
Uint8 hat;
switch (data[5] & 0xF) {
case 0:
hat = SDL_HAT_UP;
break;
case 1:
hat = SDL_HAT_RIGHTUP;
break;
case 2:
hat = SDL_HAT_RIGHT;
break;
case 3:
hat = SDL_HAT_RIGHTDOWN;
break;
case 4:
hat = SDL_HAT_DOWN;
break;
case 5:
hat = SDL_HAT_LEFTDOWN;
break;
case 6:
hat = SDL_HAT_LEFT;
break;
case 7:
hat = SDL_HAT_LEFTUP;
break;
default:
hat = SDL_HAT_CENTERED;
break;
}
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_SOUTH, ((data[5] & 0x10) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_EAST, ((data[5] & 0x20) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_QAM, ((data[5] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_WEST, ((data[5] & 0x80) != 0));
}
if (ctx->last_state[6] != data[6]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_NORTH, ((data[6] & 0x01) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_M1 /* M1 */, ((data[6] & 0x02) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, ((data[6] & 0x04) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, ((data[6] & 0x08) != 0));
// TODO: can we handle the digital trigger mode? The data seems to come through analog regardless of the trigger state
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_BACK, ((data[6] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_START, ((data[6] & 0x80) != 0));
}
if (ctx->last_state[7] != data[7]) {
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_GUIDE, ((data[7] & 0x01) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_LEFT_STICK, ((data[7] & 0x02) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK, ((data[7] & 0x04) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_M2, ((data[7] & 0x08) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_L, ((data[7] & 0x10) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_JOYSTICK_TOUCH_R, ((data[7] & 0x20) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_FR, ((data[7] & 0x40) != 0));
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_HORI_FL, ((data[7] & 0x80) != 0));
}
if (!ctx->wireless && ctx->serial_needs_init) {
char serial[18];
(void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
data[38], data[39], data[40], data[41], data[42], data[43]);
joystick->serial = SDL_strdup(serial);
ctx->serial_needs_init = false;
}
#define READ_TRIGGER_AXIS(offset) \
(Sint16)(((int)data[offset] * 257) - 32768)
{
axis = READ_TRIGGER_AXIS(8);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, axis);
axis = READ_TRIGGER_AXIS(9);
SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, axis);
}
#undef READ_TRIGGER_AXIS
if (1) {
Uint64 sensor_timestamp;
float imu_data[3];
/* 16-bit timestamp */
Uint32 delta;
Uint16 tick = LOAD16(data[10],
data[11]);
if (ctx->last_tick < tick) {
delta = (tick - ctx->last_tick);
} else {
delta = (SDL_MAX_UINT16 - ctx->last_tick + tick + 1);
}
ctx->last_tick = tick;
ctx->sensor_ticks += delta;
/* Sensor timestamp is in 1us units, but there seems to be some issues with the values reported from the device */
sensor_timestamp = timestamp; // if the values were good we woudl call SDL_US_TO_NS(ctx->sensor_ticks);
const float accelScale = SDL_STANDARD_GRAVITY * 8 / 32768.0f;
const float gyroScale = DEG2RAD(2048);
imu_data[1] = RemapValClamped(-1.0f * LOAD16(data[12], data[13]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
imu_data[2] = RemapValClamped(-1.0f * LOAD16(data[14], data[15]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
imu_data[0] = RemapValClamped(-1.0f * LOAD16(data[16], data[17]), INT16_MIN, INT16_MAX, -gyroScale, gyroScale);
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, imu_data, 3);
// SDL_Log("%u %f, %f, %f \n", data[0], imu_data[0], imu_data[1], imu_data[2] );
imu_data[2] = LOAD16(data[18], data[19]) * accelScale;
imu_data[1] = -1 * LOAD16(data[20], data[21]) * accelScale;
imu_data[0] = LOAD16(data[22], data[23]) * accelScale;
SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, imu_data, 3);
}
if (ctx->last_state[24] != data[24]) {
bool bCharging = (data[24] & 0x10) != 0;
int percent = (data[24] & 0xF) * 10;
SDL_PowerState state;
if (bCharging) {
state = SDL_POWERSTATE_CHARGING;
} else if (ctx->wireless) {
state = SDL_POWERSTATE_ON_BATTERY;
} else {
state = SDL_POWERSTATE_CHARGED;
}
SDL_SendJoystickPowerInfo(joystick, state, percent);
}
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static bool HIDAPI_DriverSteamHori_UpdateDevice(SDL_HIDAPI_Device *device)
{
SDL_DriverSteamHori_Context *ctx = (SDL_DriverSteamHori_Context *)device->context;
SDL_Joystick *joystick = NULL;
Uint8 data[USB_PACKET_LENGTH];
int size = 0;
if (device->num_joysticks > 0) {
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
} else {
return false;
}
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_HORI_PROTOCOL
HIDAPI_DumpPacket("Google Hori packet: size = %d", data, size);
#endif
if (!joystick) {
continue;
}
HIDAPI_DriverSteamHori_HandleStatePacket(joystick, ctx, data, size);
}
if (size < 0) {
/* Read error, device is disconnected */
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
return (size >= 0);
}
static void HIDAPI_DriverSteamHori_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
}
static void HIDAPI_DriverSteamHori_FreeDevice(SDL_HIDAPI_Device *device)
{
}
SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamHori = {
SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI,
true,
HIDAPI_DriverSteamHori_RegisterHints,
HIDAPI_DriverSteamHori_UnregisterHints,
HIDAPI_DriverSteamHori_IsEnabled,
HIDAPI_DriverSteamHori_IsSupportedDevice,
HIDAPI_DriverSteamHori_InitDevice,
HIDAPI_DriverSteamHori_GetDevicePlayerIndex,
HIDAPI_DriverSteamHori_SetDevicePlayerIndex,
HIDAPI_DriverSteamHori_UpdateDevice,
HIDAPI_DriverSteamHori_OpenJoystick,
HIDAPI_DriverSteamHori_RumbleJoystick,
HIDAPI_DriverSteamHori_RumbleJoystickTriggers,
HIDAPI_DriverSteamHori_GetJoystickCapabilities,
HIDAPI_DriverSteamHori_SetJoystickLED,
HIDAPI_DriverSteamHori_SendJoystickEffect,
HIDAPI_DriverSteamHori_SetJoystickSensorsEnabled,
HIDAPI_DriverSteamHori_CloseJoystick,
HIDAPI_DriverSteamHori_FreeDevice,
};
#endif /* SDL_JOYSTICK_HIDAPI_STEAM_HORI */
#endif /* SDL_JOYSTICK_HIDAPI */

View File

@@ -67,6 +67,9 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
#ifdef SDL_JOYSTICK_HIDAPI_STEAM
&SDL_HIDAPI_DriverSteam,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAM_HORI
&SDL_HIDAPI_DriverSteamHori,
#endif
#ifdef SDL_JOYSTICK_HIDAPI_STEAMDECK
&SDL_HIDAPI_DriverSteamDeck,
#endif

View File

@@ -39,6 +39,7 @@
#define SDL_JOYSTICK_HIDAPI_XBOX360
#define SDL_JOYSTICK_HIDAPI_XBOXONE
#define SDL_JOYSTICK_HIDAPI_SHIELD
#define SDL_JOYSTICK_HIDAPI_STEAM_HORI
// Joystick capability definitions
#define SDL_JOYSTICK_CAP_MONO_LED 0x00000001
@@ -150,6 +151,7 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverWii;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne;
extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteamHori;
// Return true if a HID device is present and supported as a joystick of the given type
extern bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type);

View File

@@ -74,6 +74,8 @@
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS4 0x011c
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_HORI_FIGHTING_STICK_ALPHA_PS5 0x0184
#define USB_PRODUCT_HORI_STEAM_CONTROLLER 0x01AB
#define USB_PRODUCT_HORI_STEAM_CONTROLLER_BT 0x0196
#define USB_PRODUCT_LOGITECH_F310 0xc216
#define USB_PRODUCT_LOGITECH_CHILLSTREAM 0xcad1
#define USB_PRODUCT_MADCATZ_SAITEK_SIDE_PANEL_CONTROL_DECK 0x2218

View File

@@ -143,7 +143,7 @@ static bool AddFileDescriptorCloseActions(posix_spawn_file_actions_t *fa)
}
closedir(dir);
} else {
for (int fd = sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; --fd) {
for (int fd = (int)(sysconf(_SC_OPEN_MAX) - 1); fd > STDERR_FILENO; --fd) {
int flags = fcntl(fd, F_GETFD);
if (flags < 0 || (flags & FD_CLOEXEC)) {
continue;

View File

@@ -21,6 +21,7 @@
#include "SDL_internal.h"
#include "../SDL_hashtable.h"
#include "SDL_getenv_c.h"
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
#include "../core/windows/SDL_windows.h"

View File

@@ -115,7 +115,7 @@ static void Cocoa_HandlePenProximityEvent(SDL_CocoaWindowData *_data, NSEvent *e
static void Cocoa_HandlePenPointEvent(SDL_CocoaWindowData *_data, NSEvent *event)
{
const Uint32 timestamp = Cocoa_GetEventTimestamp([event timestamp]);
const Uint64 timestamp = Cocoa_GetEventTimestamp([event timestamp]);
Cocoa_PenHandle *handle = Cocoa_FindPenByDeviceID([event deviceID], [event pointingDeviceID]);
if (!handle) {
return;

View File

@@ -404,7 +404,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_USERNAME:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypeUsername;
} else {
textField.textContentType = nil;
@@ -412,7 +412,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypePassword;
} else {
textField.textContentType = nil;
@@ -421,7 +421,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE:
textField.keyboardType = UIKeyboardTypeDefault;
if (@available(iOS 11.0, *)) {
if (@available(iOS 11.0, tvOS 11.0, *)) {
textField.textContentType = UITextContentTypePassword;
} else {
textField.textContentType = nil;
@@ -433,7 +433,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN:
textField.keyboardType = UIKeyboardTypeNumberPad;
if (@available(iOS 12.0, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
textField.textContentType = UITextContentTypeOneTimeCode;
} else {
textField.textContentType = nil;
@@ -442,7 +442,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char
break;
case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE:
textField.keyboardType = UIKeyboardTypeNumberPad;
if (@available(iOS 12.0, *)) {
if (@available(iOS 12.0, tvOS 12.0, *)) {
textField.textContentType = UITextContentTypeOneTimeCode;
} else {
textField.textContentType = nil;

View File

@@ -72,7 +72,8 @@ typedef struct
{
Wayland_SystemCursorFrame *frames;
struct wl_callback *frame_callback;
Uint64 last_frame_time_ms;
Uint64 last_frame_callback_time_ms;
Uint64 current_frame_time_ms;
Uint32 total_duration;
int num_frames;
int current_frame;
@@ -304,16 +305,20 @@ static void cursor_frame_done(void *data, struct wl_callback *cb, uint32_t time)
SDL_CursorData *c = (SDL_CursorData *)data;
const Uint64 now = SDL_GetTicks();
const Uint64 elapsed = (now - c->cursor_data.system.last_frame_time_ms) % c->cursor_data.system.total_duration;
const Uint64 elapsed = (now - c->cursor_data.system.last_frame_callback_time_ms) % c->cursor_data.system.total_duration;
Uint64 advance = 0;
int next = c->cursor_data.system.current_frame;
wl_callback_destroy(cb);
c->cursor_data.system.frame_callback = wl_surface_frame(c->surface);
wl_callback_add_listener(c->cursor_data.system.frame_callback, &cursor_frame_listener, data);
c->cursor_data.system.current_frame_time_ms += elapsed;
// Calculate the next frame based on the elapsed duration.
for (Uint64 t = c->cursor_data.system.frames[next].duration; t <= elapsed; t += c->cursor_data.system.frames[next].duration) {
for (Uint64 t = c->cursor_data.system.frames[next].duration; t <= c->cursor_data.system.current_frame_time_ms; t += c->cursor_data.system.frames[next].duration) {
next = (next + 1) % c->cursor_data.system.num_frames;
advance = t;
// Make sure we don't end up in an infinite loop if a cursor has frame durations of 0.
if (!c->cursor_data.system.frames[next].duration) {
@@ -321,7 +326,8 @@ static void cursor_frame_done(void *data, struct wl_callback *cb, uint32_t time)
}
}
c->cursor_data.system.last_frame_time_ms = now;
c->cursor_data.system.current_frame_time_ms -= advance;
c->cursor_data.system.last_frame_callback_time_ms = now;
c->cursor_data.system.current_frame = next;
wl_surface_attach(c->surface, c->cursor_data.system.frames[next].wl_buffer, 0, 0);
if (wl_surface_get_version(c->surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
@@ -711,7 +717,8 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor)
// If more than one frame is available, create a frame callback to run the animation.
if (data->cursor_data.system.num_frames > 1) {
data->cursor_data.system.last_frame_time_ms = SDL_GetTicks();
data->cursor_data.system.last_frame_callback_time_ms = SDL_GetTicks();
data->cursor_data.system.current_frame_time_ms = 0;
data->cursor_data.system.current_frame = 0;
data->cursor_data.system.frame_callback = wl_surface_frame(data->surface);
wl_callback_add_listener(data->cursor_data.system.frame_callback, &cursor_frame_listener, data);