sdl2-compat: syncing with latest SDL2 and SDL3

From f14eda4a503d1260fbcd653942c8efc348ce4185 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Sun, 28 Jan 2024 11:50:04 +0300
Subject: [PATCH] syncing with latest SDL2 and SDL3

---
 include/SDL2/SDL_blendmode.h |   4 +-
 include/SDL2/SDL_hints.h     |  16 +++
 include/SDL2/SDL_log.h       |   2 +-
 src/sdl3_include_wrapper.h   |  15 ---
 test/testautomation_log.c    | 209 +++++++++++++++++++++++++++++++++++
 test/testautomation_suites.h |   2 +
 6 files changed, 230 insertions(+), 18 deletions(-)
 create mode 100644 test/testautomation_log.c

diff --git a/include/SDL2/SDL_blendmode.h b/include/SDL2/SDL_blendmode.h
index 1a1261d..09d0147 100644
--- a/include/SDL2/SDL_blendmode.h
+++ b/include/SDL2/SDL_blendmode.h
@@ -65,8 +65,8 @@ typedef enum
 typedef enum
 {
     SDL_BLENDOPERATION_ADD              = 0x1,  /**< dst + src: supported by all renderers */
-    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
-    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
     SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D9, D3D11 */
     SDL_BLENDOPERATION_MAXIMUM          = 0x5   /**< max(dst, src) : supported by D3D9, D3D11 */
 } SDL_BlendOperation;
diff --git a/include/SDL2/SDL_hints.h b/include/SDL2/SDL_hints.h
index 7356bf4..e775a65 100644
--- a/include/SDL2/SDL_hints.h
+++ b/include/SDL2/SDL_hints.h
@@ -1282,6 +1282,22 @@ extern "C" {
   */
 #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
 
+/**
+ *  \brief A variable controlling the default SDL log levels.
+ *
+ *  This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications.
+ *
+ *  The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category.
+ *
+ *  The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category.
+ *
+ *  You can omit the category if you want to set the logging level for all categories.
+ *
+ *  If this hint isn't set, the default log levels are equivalent to:
+ *  "app=info,assert=warn,test=verbose,*=error"
+ */
+#define SDL_HINT_LOGGING   "SDL_LOGGING"
+
 /**
 *  \brief  When set don't force the SDL app to become a foreground process
 *
diff --git a/include/SDL2/SDL_log.h b/include/SDL2/SDL_log.h
index 1564dd0..bd030c6 100644
--- a/include/SDL2/SDL_log.h
+++ b/include/SDL2/SDL_log.h
@@ -59,7 +59,7 @@ extern "C" {
  *  By default the application category is enabled at the INFO level,
  *  the assert category is enabled at the WARN level, test is enabled
  *  at the VERBOSE level and all other categories are enabled at the
- *  CRITICAL level.
+ *  ERROR level.
  */
 typedef enum
 {
diff --git a/src/sdl3_include_wrapper.h b/src/sdl3_include_wrapper.h
index f665cda..8531197 100644
--- a/src/sdl3_include_wrapper.h
+++ b/src/sdl3_include_wrapper.h
@@ -440,9 +440,6 @@
 #define SDL_IsTablet IGNORE_THIS_VERSION_OF_SDL_IsTablet
 #define SDL_JoystickConnected IGNORE_THIS_VERSION_OF_SDL_JoystickConnected
 #define SDL_JoystickEventsEnabled IGNORE_THIS_VERSION_OF_SDL_JoystickEventsEnabled
-#define SDL_JoystickHasLED IGNORE_THIS_VERSION_OF_SDL_JoystickHasLED
-#define SDL_JoystickHasRumble IGNORE_THIS_VERSION_OF_SDL_JoystickHasRumble
-#define SDL_JoystickHasRumbleTriggers IGNORE_THIS_VERSION_OF_SDL_JoystickHasRumbleTriggers
 #define SDL_IsJoystickHaptic IGNORE_THIS_VERSION_OF_SDL_IsJoystickHaptic
 #define SDL_LinuxSetThreadPriority IGNORE_THIS_VERSION_OF_SDL_LinuxSetThreadPriority
 #define SDL_LinuxSetThreadPriorityAndPolicy IGNORE_THIS_VERSION_OF_SDL_LinuxSetThreadPriorityAndPolicy
@@ -2645,18 +2642,6 @@
 #undef SDL_JoystickEventsEnabled
 #endif
 
-#ifdef SDL_JoystickHasLED
-#undef SDL_JoystickHasLED
-#endif
-
-#ifdef SDL_JoystickHasRumble
-#undef SDL_JoystickHasRumble
-#endif
-
-#ifdef SDL_JoystickHasRumbleTriggers
-#undef SDL_JoystickHasRumbleTriggers
-#endif
-
 #ifdef SDL_IsJoystickHaptic
 #undef SDL_IsJoystickHaptic
 #endif
diff --git a/test/testautomation_log.c b/test/testautomation_log.c
new file mode 100644
index 0000000..4edb487
--- /dev/null
+++ b/test/testautomation_log.c
@@ -0,0 +1,209 @@
+/**
+ * Log test suite
+ */
+#include "SDL.h"
+#include "SDL_test.h"
+
+
+static SDL_LogOutputFunction original_function;
+static void *original_userdata;
+
+static void SDLCALL TestLogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message)
+{
+    int *message_count = (int *)userdata;
+    ++(*message_count);
+}
+
+static void EnableTestLog(int *message_count)
+{
+    *message_count = 0;
+    SDL_LogGetOutputFunction(&original_function, &original_userdata);
+    SDL_LogSetOutputFunction(TestLogOutput, message_count);
+}
+
+static void DisableTestLog()
+{
+    SDL_LogSetOutputFunction(original_function, original_userdata);
+}
+
+/* Fixture */
+
+/* Test case functions */
+
+/**
+ * Check SDL_HINT_LOGGING functionality
+ */
+static int log_testHint(void *arg)
+{
+    int count;
+
+    SDL_SetHint(SDL_HINT_LOGGING, NULL);
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, NULL)");
+    {
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+    }
+
+    SDL_SetHint(SDL_HINT_LOGGING, "debug");
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"debug\")");
+    {
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+    }
+
+    SDL_SetHint(SDL_HINT_LOGGING, "system=debug");
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"system=debug\")");
+    {
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+    }
+
+    SDL_SetHint(SDL_HINT_LOGGING, "app=warn,system=debug,assert=quiet,*=info");
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"app=warn,system=debug,assert=quiet,*=info\")");
+    {
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+    }
+
+    SDL_SetHint(SDL_HINT_LOGGING, "0=4,3=2,2=0,*=3");
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"0=4,3=2,2=0,*=3\")");
+    {
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, \"test\")");
+        SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count);
+
+        EnableTestLog(&count);
+        SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, "test");
+        DisableTestLog();
+        SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, \"test\")");
+        SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count);
+
+    }
+
+    return TEST_COMPLETED;
+}
+
+/* ================= Test References ================== */
+
+/* Log test cases */
+static const SDLTest_TestCaseReference logTestHint = {
+    (SDLTest_TestCaseFp)log_testHint, "log_testHint", "Check SDL_HINT_LOGGING functionality", TEST_ENABLED
+};
+
+/* Sequence of Log test cases */
+static const SDLTest_TestCaseReference *logTests[] = {
+    &logTestHint, NULL
+};
+
+/* Timer test suite (global) */
+SDLTest_TestSuiteReference logTestSuite = {
+    "Log",
+    NULL,
+    logTests,
+    NULL
+};
diff --git a/test/testautomation_suites.h b/test/testautomation_suites.h
index 24909db..95528f2 100644
--- a/test/testautomation_suites.h
+++ b/test/testautomation_suites.h
@@ -16,6 +16,7 @@ extern SDLTest_TestSuiteReference guidTestSuite;
 extern SDLTest_TestSuiteReference hintsTestSuite;
 extern SDLTest_TestSuiteReference joystickTestSuite;
 extern SDLTest_TestSuiteReference keyboardTestSuite;
+extern SDLTest_TestSuiteReference logTestSuite;
 extern SDLTest_TestSuiteReference mainTestSuite;
 extern SDLTest_TestSuiteReference mathTestSuite;
 extern SDLTest_TestSuiteReference mouseTestSuite;
@@ -41,6 +42,7 @@ SDLTest_TestSuiteReference *testSuites[] = {
     &hintsTestSuite,
     &joystickTestSuite,
     &keyboardTestSuite,
+    &logTestSuite,
     &mainTestSuite,
     &mathTestSuite,
     &mouseTestSuite,