- explicitly use UNICODE versions of DrawText, EnumDisplaySettings,
EnumDisplayDevices, and CreateDC: the underlying structures have
WCHAR strings.
- change WIN_UpdateDisplayMode and WIN_GetDisplayMode() to accept
LPCWSTR instead of LPCTSTR for the same reason.
- change WIN_StringToUTF8 and WIN_UTF8ToString to the explicit 'W'
versions where appropriate.
i.e. where the string is known guaranteed to be WCHAR*, in:
- SDL_dinputjoystick.c (WIN_IsXInputDevice): VARIANT->var is BSTR (WCHAR*)
- SDL_rawinputjoystick.c (RAWINPUT_AddDevice): string is WCHAR*
- SDL_windows_gaming_input.c (IEventHandler_CRawGameControllerVtbl_InvokeAdded):
string is WCHAR*
There should be more of these..
_InterlockedExchange_rel() is required for correctness on ARM because
the _ReadWriteBarrier() macro is only a compiler memory barrier, not a
hardware memory barrier. Due to ARM's relaxed memory model, this means
the '*lock = 0' write may be observed before the operations inside the
lock, causing possible corruption of data protected by the lock.
_InterlockedExchange_acq() is more efficient on ARM because it avoids an
expensive full memory barrier that _InterlockedExchange() does.
C.W. Betts
I tested building commit http://hg.libsdl.org/SDL/rev/7adf3fdc19f3 on Mac Catalyst and found some issues:
* MTLFeatureSet_iOS_* enums aren't available under Mac Catalyst.
* OpenGL ES is unavailable under Mac Catalyst.
* Some Metal features are available under Catalyst but not iOS, such as displaySyncEnabled.
* Set Metal as the default renderer on Mac Catalyst
Attaching a patch that will make SDL2 build for Mac Catalyst.
This is unsafe because the event is auto-reset, therefore the call to
WaitForSingleObject() resets the event which GetOverlappedResult() will
try to wait on.
Even though the overlapped operation is guaranteed to be completed at
the point we call GetOverlappedResult(), it will still wait on the event
handle for a short time to trigger the reset for auto-reset events. This
amounts to roughly a 100 ms sleep each time GetOverlappedResult() is called
for a completed I/O with a non-signalled event.
In the context of HIDAPI, this extra sleep means that callers that loop
on hid_read_timeout() with timeout=0 will loop forever, since the 100 ms
sleep each iteration ensures ReadFile() will always have new data.
Caleb Cornett
For a window created with SDL_WINDOW_ALLOW_HIGHDPI, SDL_GL_GetDrawableSize will return the high-dpi drawable size even before any GL context creation happens. But SDL_Metal_GetDrawableSize will return the size of the window if the Metal view has not been created. This is confusing and inconsistent behavior.
An easy way to test this is to build testgl2 and testvulkan on macOS with the SDL_WINDOW_ALLOW_HIGHDPI flag enabled during window creation. The GL2 program will report a drawable size of 2x window width and 2x window height, while the Vulkan program will report the window size.
This patch addresses the issue by falling back to using the content view dimensions if no Metal view exists in the window. (The code for this was taken directly from Cocoa_GL_GetDrawableSize.) With this change, the testvulkan behavior matches that of testgl2.
Note that I haven't tested for this issue on UIKit. It's possible a similar change will need to be made there too.
David Carlier
This form of 'or' provides a hint that performance
will probably be improved if shared resources dedicated
to the executing processor are released for use by other
processors
- hidapi already called CancelIo on hid_close but that only cancels pending IO for the current thread. Controller read/writes originate from multiple
threads (serialized, but on a different thread nonetheless) but device destruction was always done on the main device thread which left any
pending overlapped reads still running after hidapi's internal read buffer is deallocated leading to intermittent free list corruption.
Ivan Kuzmenko
MCST Elbrus 2000 (E2K, https://en.wikipedia.org/wiki/Elbrus_2000) is a russian processor architecture based on VLIW/EPIC instruction set (like Intel Itanium (IA-64) architecture). Architecture has half native / half software support of most Intel/AMD SIMD (e.g. MMX/SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2/AES/AVX/AVX2 & 3DNow!/SSE4a/XOP/FMA4).
It also has built-in x86/x86_64 <-> e2k binary translators (RTC, http://www.mcst.ru/rtc and Lintel, http://www.mcst.ru/lintel) that can run code for x86/x86_64 architecture (Transmeta did something similiar with their Crusoe series) with SIMD extensions support.
Attached patch allows SDL2 to detect extensions supported by E2K like MMX, 3dNOW!, AVX etc. (test/testplatform log: https://termbin.com/7qs3).
wahil1976
This patch adds support for OpenBSD to KMSDRM_LEGACY. Note that the patch won't be ported to the atomic KMSDRM backend because OpenBSD does not support atomic KMS properly yet.
Is automatically used when the SRW SDL_mutex implementation is active.
Otherwise falls back to the generic implementation.
v2: - Rebase onto master fa3ea1051a4b
https://bugzilla.libsdl.org/show_bug.cgi?id=5308
The udev code labels devices that are found by this code with
ID_INPUT_KEY which in turn gets used by SDL to label the devices as
SDL_UDEV_DEVICE_KEYBOARD.
This was missing for the code path when udev is not running and as such
devices such as the power button of a phone was not detected as keyboard
input and no devices were emitted.
Cameron Cawley
stdlib: Added SDL_round, SDL_roundf, SDL_lround and SDL_lroundf
The default implementation is based on the one used in the Windows RT video driver.
Keep Semaphore Kernel Object impl for Windows 7 and older - choose at runtime
v2: - Fix mixed int/LONG types
- Reorder definitions
- Add missing include
v3: - Use `GetModuleHandle()` to load the API Set
v2: - Add SRW definitions as suggested by Ozkan Sezer
Allows building against older platform headers.
- Rename "hidden" function parameter `mutex_` to `_mutex`
v3: - Use GetModuleHandle instead of LoadLibrary
- Fix typo in comment
SDL_systhread.c and SDL_syslocale.c used to call LoadLibrary() without
calling FreeLibrary() later. GetModuleHandleW() should always succeed
because GetModuleHandleW() itself is imported from kernel32.dll and we
don't need to bother releasing it.
.. so that KMSDRM_CreateDevice() can fail and SDL_VideoInit() would
move on to next bootstrap member which is kmsdrm_legacy. hopefully
fixes bug #5393.
Substring
I was trying the KMSDRM video backend with some very simple programs that were working ok on 2.0.12. The same code won?t work on the current dev branch and I get:
DEBUG: check_modesetting: probing ?/dev/dri/card0?
DEBUG: /dev/dri/card0 connector, encoder and CRTC counts are: 4 5 6
DEBUG: check_modesetting: probing ?/dev/dri/card0?
DEBUG: /dev/dri/card0 connector, encoder and CRTC counts are: 4 5 6
DEBUG: KMSDRM_VideoInit()
DEBUG: Opening device /dev/dri/card0
DEBUG: Opened DRM FD (3)
DEBUG: no atomic modesetting support.
DEBUG: Video subsystem has not been initialized
INFO: Using SDL video driver: (null)
DEBUG: Video subsystem has not been initialized
After carefully checking, the radeon driver doesn?t support atomic modesetting. That?s not the only problem : the same happens with the amdgpu driver if we disable Display Core (kernel parameter amdgpu.dc=0, which is required to get analogue outputs working).
This is a major regression in the KMSDRM driver.
Using atomic mode setting is great, but having no fallback to the "standard KMS" is bad.
pj5085
I added some printf to verify the math being done. Of the three joysticks I have, it works correctly for at least two, and seems to work correctly for the third. I say "seems to" because, for the third joystick, the values never go through the AxisCorrect function, and thus never hit my printf statements, even though they did in the version I wrote my patch against. I'm not sure what's going on there, but it at least seems to be working correctly in as much as I can tell.
I note this result in particular, for an SNES Gamepad (min=0, max=255):
Joystick value 0 becomes -32768
Joystick value 127 becomes 0
Joystick value 255 becomes 32767
Without the code that forces a zero point, the 127 input value would become -129, so I think you see why I added that code to turn it into zero. However, I think Kai Krakow has a point about how SDL shouldn't assume that there should be a center.
Obviously in the majority of cases there actually should be a center, and the code that turns that 127 into an actual 0 is creating only a 0.2% error over 0.4% of this joystick's range. However, what if there is an axis that is some kind of special control, like a 4-position switch, and, for whatever reason, the joystick reports it as an axis with 4 possible values, 0 to 3? In that case, mutilating the two center values to the same value is much more of an error and and turns that 4-position switch into a 3-position switch. If any joystick does this with a 2-position switch, then this code would render that control entirely useless as it would report the same value with the switch in either position. Obviously the code could require that there be at least N possible values, to guess whether something is a proper axis or just some kind of switch, but the choice of N would be arbitrary and that's ugly.
I guess the real problem here is that my gamepad is just kind of broken. It should be reporting a range of -1 to +1 since that's what it actually does. Also, as Kai Krakow points out, it's probably not SDL's place to fix broken hardware. I'll add that, if SDL does fix broken hardware, it should probably actually know that it's broken rather than be merely guessing that it is.
So, to the extent that SDL is able to do stuff like this, perhaps it's something better left for the user to configure in some kind of config file.
pj5085
It occurred to me that my simple patch that comments out a few lines of code does not correctly remove the dead zone since the calculation presumably assumes the dead zone has been cut out of the range. Then, while looking into how to make it output the correct range of values, I realized SDL wasn't returning the correct range of values to begin with.
This line of code was already present:
printf("Values = { %d, %d, %d, %d, %d }\n", absinfo.value, absinfo.minimum, absinfo.maximum, absinfo.fuzz, absinfo.flat);
For my joystick this yeilds:
Values = { 0, -127, 127, 0, 15 }
Then this code calculates the coefficients:
In SDL1:
joystick->hwdata->abs_correct[i].coef[0] = (absinfo.maximum + absinfo.minimum) / 2 - absinfo.flat;
joystick->hwdata->abs_correct[i].coef[1] = (absinfo.maximum + absinfo.minimum) / 2 + absinfo.flat;
t = ((absinfo.maximum - absinfo.minimum) / 2 - 2 * absinfo.flat);
if ( t != 0 ) {
joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t;
} else {
joystick->hwdata->abs_correct[i].coef[2] = 0;
}
In SDL2:
joystick->hwdata->abs_correct[i].coef[0] = (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
joystick->hwdata->abs_correct[i].coef[1] = (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
if (t != 0) {
joystick->hwdata->abs_correct[i].coef[2] = (1 << 28) / t;
} else {
joystick->hwdata->abs_correct[i].coef[2] = 0;
}
Neither calculates the correct coefficients for the code in the AxisCorrect function.
In SDL1:
if ( value > correct->coef[0] ) {
if ( value < correct->coef[1] ) {
return 0;
}
value -= correct->coef[1];
} else {
value -= correct->coef[0];
}
value *= correct->coef[2];
value >>= 14;
In SDL2:
value *= 2;
if (value > correct->coef[0]) {
if (value < correct->coef[1]) {
return 0;
}
value -= correct->coef[1];
} else {
value -= correct->coef[0];
}
In SDL1, the calculated coefficients are coef[0]=15, coef[1]=-15 and coef[2]=5534751. So with a full-scale input of 127, it calculates an output value of 37835, which is considerably out of range.
In SDL2, the calculated coefficients are coef[0]=30, coef[1]=-30, and coef[2]=1383687. So with a full-scale input of 127, it calculates the same output value of 37835.
I tested it with the 3 joysticks I have, and it produces out-of-range values for all of them.
Anyway, since dead zones are garbage, I just deleted all of that junk and wrote some code that takes the absinfo.minimum and absinfo.maximum values and uses them to scale the axis range to -32767 through +32767.
I also made it detect when a range doesn't have an integer center point, e.g. the center of -128 to + 127 is -0.5. In such cases, if either value to the side of the center is provided, it zeros it, but it otherwise doesn't implement any kind of dead zone. This seemed important with my gamepad which provides only the values of 0, 127, and 255, since without this hack it would never be centered.
Also, the previous minimum output value was -32768, but as that creates an output range that has no true center, I changed the minimum value to -32767.
I tested it with the 3 joystick devices I have and it seems to create correct values for all of them.
Added a hint to control whether a separate thread should be used for joystick events.
This is off by default because dispatching messages in other threads appears to cause problems on some versions of Windows.
- SDL_video.c (SDL_ShowMessageBox): replace messageboxdata, set title
or message field to "" if either of them is NULL.
- SDL_video.c (SDL_ShowSimpleMessageBox): set title or message to ""
if either of them is NULL for EMSCRIPTEN builds.
- SDL_bmessagebox.cc: add empty string check along with NULL check for
title and message fields.
- SDL_windowsmessagebox.c (AddDialogString): remove NULL string check
- SDL_windowsmessagebox.c (AddDialogControl): add empty string check
along with the NULL check.
- SDL_x11messagebox.c: revert commit 677c4cd68069
- SDL_os2messagebox.c: revert commit 2c2a489d76e7
- test/testmessage.c: Add NULL title and NULL message tests.
Joel Linn
TLDR; https://godbolt.org/z/43fd8G
Let's deduce this from C++ reference code:
https://docs.microsoft.com/en-us/cpp/cppcx/wrl/how-to-activate-and-use-a-windows-runtime-component-using-wrl?view=msvc-160
At the bottom of the page there is this snippet:
```
int wmain()
{
/* ... more code ... */
// Get the domain part of the URI.
HString domainName;
hr = uri->get_Domain(domainName.GetAddressOf());
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Print the domain name and return.
wprintf_s(L"Domain name: %s\n", domainName.GetRawBuffer(nullptr));
// All smart pointers and RAII objects go out of scope here.
}
```
`HString` is defined in `corewrappers.h` and the call chain for the destructor is:
`~HString() -> Release() -> ::WindowsDeleteString()`
QED
Vincent Hamm
Xcode11 and ios13 added support for metal simulator.
Here is a quick and dirty patch to enable it. Pretty early and only tested on a few samples for now. Required mostly to enable metal support on correct version of ios, generate simulator compatible shaders and enforce buffer alignments on simulator (same as osx).
If we fail to connect to the the pa server, we have an assigned context
and mainloop that isn't connected. So, when PULSEAUDIO_pa_context_disconnect
is called, pa asserts and crashes the application.
Assertion 'pa_atomic_load(&(c)->_ref) >= 1' failed at pulse/context.c:1055, function pa_context_disconnect(). Aborting.
Joel Linn
Eliminate additional heap allocation for short-lived HSTRINGs.
Uses `WindowsCreateStringReference()` to disable reference counting and memory management by the Window Runtime.
Ivan Mogilko
With SDL 2.0.12 under MS Windows, if the window is partially offscreen calling SDL_SetWindowGrab(w, SDL_TRUE) works, but subsequent call to SDL_SetWindowGrab(w, SDL_FALSE) does not work.
I tested this in both real program, and a small test app, where unlocking cursor worked perfectly while window is fully in desktop bounds, but did not work if it was at least few pixels outside.
For the reference, following code is enough to reproduce the issue:
#include <windows.h>
#include <SDL.h>
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* w = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 400, 0);
bool grabbed = false;
bool want_quit = false;
while (!want_quit)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT: want_quit = true; break;
case SDL_KEYDOWN:
if (event.key.keysym.scancode == SDL_SCANCODE_SPACE)
{
SDL_SetWindowGrab(w, static_cast<SDL_bool>(!grabbed));
grabbed = !grabbed;
}
}
}
}
SDL_DestroyWindow(w);
SDL_Quit();
return 0;
}
Mathieu Eyraud
SDL dynamically loads libusb but does not check the return value of 'SDL_LoadFunction'.
Also libusb is loaded and initialized several time because 'SDL_hidapi_wasinit' is never set to true.
I made a patch if you want to test:
- check that 'hid_init' is called once and only once,
- check return value of 'hid_init',
- check return value of 'SDL_LoadFunction',
- check return value of 'SDL_malloc',
- add some debug logging.
On older mac, where METAL Renderer METAL fails to create, it allows to switch back to OpenGL SDL_Renderer
by re-creating the window (METAL flags was previously persistent).
This can happen if the application has not yet processed SDL_JOYDEVICEADD when
the same joystick is removed. It may also happen if two joysticks are added
and the second joystick is removed before the first joystick's SDL_JOYDEVICEADD
has been processed by the application.
Joel Linn
Currently the rawinput driver always reports a device as "wired". This changes that to "unknown" and updates it once the device is correlated with xinput.
Most of the raw input events are dispatched in the main windows message loop. We only dispatch device change messages separately when we need them to be completely up to date.
It's legitimate to have a surface with 0 width or height (null 'pixels' pointer).
But calling SDL_FillRects would wrongly set the error "You must lock the surface".
src/joystick/windows/SDL_rawinputjoystick.c: In function 'RAWINPUT_HandleStatePacket':
src/joystick/windows/SDL_rawinputjoystick.c:1343:9: warning: suggest explicit braces to avoid ambiguous 'else'