mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 12:40:06 +02:00
update SDL3 to libsdl-org/SDL@186c6e5
This commit is contained in:
+60
-3
@@ -55,6 +55,9 @@
|
||||
#include "video/SDL_surface_c.h"
|
||||
#include "video/SDL_video_c.h"
|
||||
#include "filesystem/SDL_filesystem_c.h"
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
#include "core/android/SDL_android.h"
|
||||
#endif
|
||||
|
||||
#define SDL_INIT_EVERYTHING ~0U
|
||||
|
||||
@@ -251,10 +254,26 @@ void SDL_SetMainReady(void)
|
||||
// Initialize all the subsystems that require initialization before threads start
|
||||
void SDL_InitMainThread(void)
|
||||
{
|
||||
static bool done_info = false;
|
||||
|
||||
SDL_InitTLSData();
|
||||
SDL_InitEnvironment();
|
||||
SDL_InitTicks();
|
||||
SDL_InitFilesystem();
|
||||
|
||||
if (!done_info) {
|
||||
const char *value;
|
||||
|
||||
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App name: %s", value ? value : "<unspecified>");
|
||||
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App version: %s", value ? value : "<unspecified>");
|
||||
value = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "App ID: %s", value ? value : "<unspecified>");
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_SYSTEM, "SDL revision: %s", SDL_REVISION);
|
||||
|
||||
done_info = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_QuitMainThread(void)
|
||||
@@ -643,7 +662,9 @@ const char *SDL_GetRevision(void)
|
||||
// Get the name of the platform
|
||||
const char *SDL_GetPlatform(void)
|
||||
{
|
||||
#if defined(SDL_PLATFORM_AIX)
|
||||
#if defined(SDL_PLATFORM_PRIVATE)
|
||||
return SDL_PLATFORM_PRIVATE_NAME;
|
||||
#elif defined(SDL_PLATFORM_AIX)
|
||||
return "AIX";
|
||||
#elif defined(SDL_PLATFORM_ANDROID)
|
||||
return "Android";
|
||||
@@ -711,7 +732,6 @@ const char *SDL_GetPlatform(void)
|
||||
bool SDL_IsTablet(void)
|
||||
{
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
extern bool SDL_IsAndroidTablet(void);
|
||||
return SDL_IsAndroidTablet();
|
||||
#elif defined(SDL_PLATFORM_IOS)
|
||||
extern bool SDL_IsIPad(void);
|
||||
@@ -724,7 +744,6 @@ bool SDL_IsTablet(void)
|
||||
bool SDL_IsTV(void)
|
||||
{
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
extern bool SDL_IsAndroidTV(void);
|
||||
return SDL_IsAndroidTV();
|
||||
#elif defined(SDL_PLATFORM_IOS)
|
||||
extern bool SDL_IsAppleTV(void);
|
||||
@@ -734,6 +753,44 @@ bool SDL_IsTV(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static SDL_Sandbox SDL_DetectSandbox(void)
|
||||
{
|
||||
#if defined(SDL_PLATFORM_LINUX)
|
||||
if (access("/.flatpak-info", F_OK) == 0) {
|
||||
return SDL_SANDBOX_FLATPAK;
|
||||
}
|
||||
|
||||
/* For Snap, we check multiple variables because they might be set for
|
||||
* unrelated reasons. This is the same thing WebKitGTK does. */
|
||||
if (SDL_getenv("SNAP") && SDL_getenv("SNAP_NAME") && SDL_getenv("SNAP_REVISION")) {
|
||||
return SDL_SANDBOX_SNAP;
|
||||
}
|
||||
|
||||
if (access("/run/host/container-manager", F_OK) == 0) {
|
||||
return SDL_SANDBOX_UNKNOWN;
|
||||
}
|
||||
|
||||
#elif defined(SDL_PLATFORM_MACOS)
|
||||
if (SDL_getenv("APP_SANDBOX_CONTAINER_ID")) {
|
||||
return SDL_SANDBOX_MACOS;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SDL_SANDBOX_NONE;
|
||||
}
|
||||
|
||||
SDL_Sandbox SDL_GetSandbox(void)
|
||||
{
|
||||
static SDL_Sandbox sandbox;
|
||||
static bool sandbox_initialized;
|
||||
|
||||
if (!sandbox_initialized) {
|
||||
sandbox = SDL_DetectSandbox();
|
||||
sandbox_initialized = true;
|
||||
}
|
||||
return sandbox;
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_WIN32
|
||||
|
||||
#if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
|
||||
|
||||
@@ -245,7 +245,9 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
||||
state = (SDL_AssertState)selected;
|
||||
}
|
||||
} else {
|
||||
#ifdef SDL_PLATFORM_EMSCRIPTEN
|
||||
#ifdef SDL_PLATFORM_PRIVATE_ASSERT
|
||||
SDL_PRIVATE_PROMPTASSERTION();
|
||||
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
|
||||
// This is nasty, but we can't block on a custom UI.
|
||||
for (;;) {
|
||||
bool okay = true;
|
||||
@@ -283,7 +285,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_STDIO_H)
|
||||
#elif defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_3DS)
|
||||
// this is a little hacky.
|
||||
for (;;) {
|
||||
char buf[32];
|
||||
@@ -310,6 +312,8 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Assertion Failed", message, window);
|
||||
#endif // HAVE_STDIO_H
|
||||
}
|
||||
|
||||
|
||||
@@ -25,18 +25,29 @@
|
||||
#include "SDL_error_c.h"
|
||||
|
||||
bool SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
bool result;
|
||||
|
||||
va_start(ap, fmt);
|
||||
result = SDL_SetErrorV(fmt, ap);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SDL_SetErrorV(SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
|
||||
{
|
||||
// Ignore call if invalid format pointer was passed
|
||||
if (fmt) {
|
||||
va_list ap;
|
||||
int result;
|
||||
SDL_error *error = SDL_GetErrBuf(true);
|
||||
va_list ap2;
|
||||
|
||||
error->error = SDL_ErrorCodeGeneric;
|
||||
|
||||
va_start(ap, fmt);
|
||||
result = SDL_vsnprintf(error->str, error->len, fmt, ap);
|
||||
va_end(ap);
|
||||
va_copy(ap2, ap);
|
||||
result = SDL_vsnprintf(error->str, error->len, fmt, ap2);
|
||||
va_end(ap2);
|
||||
|
||||
if (result >= 0 && (size_t)result >= error->len && error->realloc_func) {
|
||||
size_t len = (size_t)result + 1;
|
||||
@@ -44,9 +55,9 @@ bool SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
||||
if (str) {
|
||||
error->str = str;
|
||||
error->len = len;
|
||||
va_start(ap, fmt);
|
||||
(void)SDL_vsnprintf(error->str, error->len, fmt, ap);
|
||||
va_end(ap);
|
||||
va_copy(ap2, ap);
|
||||
(void)SDL_vsnprintf(error->str, error->len, fmt, ap2);
|
||||
va_end(ap2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ SDL_HashTable *SDL_CreateHashTable(void *data,
|
||||
return table;
|
||||
}
|
||||
|
||||
static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *restrict table, const void *key)
|
||||
static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *table, const void *key)
|
||||
{
|
||||
const Uint32 BitMixer = 0x9E3779B1u;
|
||||
return table->hash(key, table->data) * BitMixer;
|
||||
@@ -112,7 +112,7 @@ static SDL_INLINE Uint32 get_probe_length(Uint32 zero_idx, Uint32 actual_idx, Ui
|
||||
return actual_idx - zero_idx;
|
||||
}
|
||||
|
||||
static SDL_HashItem *find_item(const SDL_HashTable *restrict ht, const void *key, Uint32 hash, Uint32 *restrict i, Uint32 *restrict probe_len)
|
||||
static SDL_HashItem *find_item(const SDL_HashTable *ht, const void *key, Uint32 hash, Uint32 *i, Uint32 *probe_len)
|
||||
{
|
||||
Uint32 hash_mask = ht->hash_mask;
|
||||
Uint32 max_probe_len = ht->max_probe_len;
|
||||
@@ -146,14 +146,14 @@ static SDL_HashItem *find_item(const SDL_HashTable *restrict ht, const void *key
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_HashItem *find_first_item(const SDL_HashTable *restrict ht, const void *key, Uint32 hash)
|
||||
static SDL_HashItem *find_first_item(const SDL_HashTable *ht, const void *key, Uint32 hash)
|
||||
{
|
||||
Uint32 i = hash & ht->hash_mask;
|
||||
Uint32 probe_len = 0;
|
||||
return find_item(ht, key, hash, &i, &probe_len);
|
||||
}
|
||||
|
||||
static SDL_HashItem *insert_item(SDL_HashItem *restrict item_to_insert, SDL_HashItem *restrict table, Uint32 hash_mask, Uint32 *max_probe_len_ptr)
|
||||
static SDL_HashItem *insert_item(SDL_HashItem *item_to_insert, SDL_HashItem *table, Uint32 hash_mask, Uint32 *max_probe_len_ptr)
|
||||
{
|
||||
Uint32 idx = item_to_insert->hash & hash_mask;
|
||||
SDL_HashItem temp_item, *target = NULL;
|
||||
@@ -213,7 +213,7 @@ static SDL_HashItem *insert_item(SDL_HashItem *restrict item_to_insert, SDL_Hash
|
||||
return target;
|
||||
}
|
||||
|
||||
static void delete_item(SDL_HashTable *restrict ht, SDL_HashItem *item)
|
||||
static void delete_item(SDL_HashTable *ht, SDL_HashItem *item)
|
||||
{
|
||||
Uint32 hash_mask = ht->hash_mask;
|
||||
SDL_HashItem *table = ht->table;
|
||||
@@ -241,7 +241,7 @@ static void delete_item(SDL_HashTable *restrict ht, SDL_HashItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
static bool resize(SDL_HashTable *restrict ht, Uint32 new_size)
|
||||
static bool resize(SDL_HashTable *ht, Uint32 new_size)
|
||||
{
|
||||
SDL_HashItem *old_table = ht->table;
|
||||
Uint32 old_size = ht->hash_mask + 1;
|
||||
@@ -267,7 +267,7 @@ static bool resize(SDL_HashTable *restrict ht, Uint32 new_size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool maybe_resize(SDL_HashTable *restrict ht)
|
||||
static bool maybe_resize(SDL_HashTable *ht)
|
||||
{
|
||||
Uint32 capacity = ht->hash_mask + 1;
|
||||
|
||||
@@ -276,7 +276,7 @@ static bool maybe_resize(SDL_HashTable *restrict ht)
|
||||
}
|
||||
|
||||
Uint32 max_load_factor = 217; // range: 0-255; 217 is roughly 85%
|
||||
Uint32 resize_threshold = (max_load_factor * (Uint64)capacity) >> 8;
|
||||
Uint32 resize_threshold = (Uint32)((max_load_factor * (Uint64)capacity) >> 8);
|
||||
|
||||
if (ht->num_occupied_slots > resize_threshold) {
|
||||
return resize(ht, capacity * 2);
|
||||
@@ -285,7 +285,7 @@ static bool maybe_resize(SDL_HashTable *restrict ht)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_InsertIntoHashTable(SDL_HashTable *restrict table, const void *key, const void *value)
|
||||
bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value)
|
||||
{
|
||||
SDL_HashItem *item;
|
||||
Uint32 hash;
|
||||
@@ -307,6 +307,7 @@ bool SDL_InsertIntoHashTable(SDL_HashTable *restrict table, const void *key, con
|
||||
new_item.value = value;
|
||||
new_item.hash = hash;
|
||||
new_item.live = true;
|
||||
new_item.probe_len = 0;
|
||||
|
||||
table->num_occupied_slots++;
|
||||
|
||||
@@ -455,7 +456,7 @@ bool SDL_HashTableEmpty(SDL_HashTable *table)
|
||||
return !(table && table->num_occupied_slots);
|
||||
}
|
||||
|
||||
static void nuke_all(SDL_HashTable *restrict table)
|
||||
static void nuke_all(SDL_HashTable *table)
|
||||
{
|
||||
void *data = table->data;
|
||||
SDL_HashItem *end = table->table + (table->hash_mask + 1);
|
||||
@@ -468,7 +469,7 @@ static void nuke_all(SDL_HashTable *restrict table)
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_EmptyHashTable(SDL_HashTable *restrict table)
|
||||
void SDL_EmptyHashTable(SDL_HashTable *table)
|
||||
{
|
||||
if (table) {
|
||||
if (table->nuke) {
|
||||
|
||||
@@ -83,13 +83,28 @@ static void SDLCALL CleanupHintProperty(void *userdata, void *value)
|
||||
SDL_free(hint);
|
||||
}
|
||||
|
||||
static const char* GetHintEnvironmentVariable(const char *name)
|
||||
{
|
||||
const char *result = SDL_getenv(name);
|
||||
if (!result && name && *name) {
|
||||
// fall back to old (SDL2) names of environment variables that
|
||||
// are important to users (e.g. many use SDL_VIDEODRIVER=wayland)
|
||||
if (SDL_strcmp(name, SDL_HINT_VIDEO_DRIVER) == 0) {
|
||||
result = SDL_getenv("SDL_VIDEODRIVER");
|
||||
} else if (SDL_strcmp(name, SDL_HINT_AUDIO_DRIVER) == 0) {
|
||||
result = SDL_getenv("SDL_AUDIODRIVER");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
|
||||
{
|
||||
if (!name || !*name) {
|
||||
return SDL_InvalidParamError("name");
|
||||
}
|
||||
|
||||
const char *env = SDL_getenv(name);
|
||||
const char *env = GetHintEnvironmentVariable(name);
|
||||
if (env && (priority < SDL_HINT_OVERRIDE)) {
|
||||
return SDL_SetError("An environment variable is taking priority");
|
||||
}
|
||||
@@ -143,7 +158,7 @@ bool SDL_ResetHint(const char *name)
|
||||
return SDL_InvalidParamError("name");
|
||||
}
|
||||
|
||||
const char *env = SDL_getenv(name);
|
||||
const char *env = GetHintEnvironmentVariable(name);
|
||||
|
||||
const SDL_PropertiesID hints = GetHintProperties(false);
|
||||
if (!hints) {
|
||||
@@ -182,7 +197,7 @@ static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, c
|
||||
return; // uh...okay.
|
||||
}
|
||||
|
||||
const char *env = SDL_getenv(name);
|
||||
const char *env = GetHintEnvironmentVariable(name);
|
||||
if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) {
|
||||
SDL_HintWatch *entry = hint->callbacks;
|
||||
while (entry) {
|
||||
@@ -213,7 +228,7 @@ const char *SDL_GetHint(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *result = SDL_getenv(name);
|
||||
const char *result = GetHintEnvironmentVariable(name);
|
||||
|
||||
const SDL_PropertiesID hints = GetHintProperties(false);
|
||||
if (hints) {
|
||||
@@ -237,10 +252,10 @@ int SDL_GetStringInteger(const char *value, int default_value)
|
||||
if (!value || !*value) {
|
||||
return default_value;
|
||||
}
|
||||
if (*value == '0' || SDL_strcasecmp(value, "false") == 0) {
|
||||
if (SDL_strcasecmp(value, "false") == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (*value == '1' || SDL_strcasecmp(value, "true") == 0) {
|
||||
if (SDL_strcasecmp(value, "true") == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (*value == '-' || SDL_isdigit(*value)) {
|
||||
|
||||
@@ -696,6 +696,9 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
#endif // !defined(SDL_PLATFORM_GDK)
|
||||
length = SDL_strlen(GetLogPriorityPrefix(priority)) + SDL_strlen(message) + 1 + 1 + 1;
|
||||
output = SDL_small_alloc(char, length, &isstack);
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
(void)SDL_snprintf(output, length, "%s%s\r\n", GetLogPriorityPrefix(priority), message);
|
||||
tstr = WIN_UTF8ToString(output);
|
||||
|
||||
@@ -772,6 +775,11 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_LogOutputFunction SDL_GetDefaultLogOutputFunction(void)
|
||||
{
|
||||
return SDL_LogOutput;
|
||||
}
|
||||
|
||||
void SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
|
||||
{
|
||||
SDL_LockMutex(SDL_log_function_lock);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE)
|
||||
#if defined(HAVE_GETHOSTNAME) && !defined(SDL_PLATFORM_WINDOWS)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
@@ -299,7 +299,7 @@ int SDL_URIToLocal(const char *src, char *dst)
|
||||
const size_t src_len = hostname_end - (src + 1);
|
||||
size_t hostname_len;
|
||||
|
||||
#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE)
|
||||
#if defined(HAVE_GETHOSTNAME) && !defined(SDL_PLATFORM_WINDOWS)
|
||||
char hostname[257];
|
||||
if (gethostname(hostname, 255) == 0) {
|
||||
hostname[256] = '\0';
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
// Available audio drivers
|
||||
static const AudioBootStrap *const bootstrap[] = {
|
||||
#ifdef SDL_AUDIO_DRIVER_PRIVATE
|
||||
&PRIVATEAUDIO_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
#ifdef SDL_AUDIO_DRIVER_PIPEWIRE
|
||||
&PIPEWIRE_PREFERRED_bootstrap,
|
||||
|
||||
@@ -353,6 +353,7 @@ typedef struct AudioBootStrap
|
||||
} AudioBootStrap;
|
||||
|
||||
// Not all of these are available in a given build. Use #ifdefs, etc.
|
||||
extern AudioBootStrap PRIVATEAUDIO_bootstrap;
|
||||
extern AudioBootStrap PIPEWIRE_PREFERRED_bootstrap;
|
||||
extern AudioBootStrap PIPEWIRE_bootstrap;
|
||||
extern AudioBootStrap PULSEAUDIO_bootstrap;
|
||||
|
||||
@@ -2093,7 +2093,8 @@ bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8
|
||||
|
||||
// Make sure we are passed a valid data source
|
||||
if (!src) {
|
||||
goto done; // Error may come from SDL_IOStream.
|
||||
SDL_InvalidParamError("src");
|
||||
goto done;
|
||||
} else if (!spec) {
|
||||
SDL_InvalidParamError("spec");
|
||||
goto done;
|
||||
@@ -2132,6 +2133,19 @@ done:
|
||||
|
||||
bool SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
|
||||
{
|
||||
return SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
|
||||
SDL_IOStream *stream = SDL_IOFromFile(path, "rb");
|
||||
if (!stream) {
|
||||
if (spec) {
|
||||
SDL_zerop(spec);
|
||||
}
|
||||
if (audio_buf) {
|
||||
*audio_buf = NULL;
|
||||
}
|
||||
if (audio_len) {
|
||||
*audio_len = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return SDL_LoadWAV_IO(stream, true, spec, audio_buf, audio_len);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ static bool EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buf
|
||||
{
|
||||
const int framelen = SDL_AUDIO_FRAMESIZE(device->spec);
|
||||
MAIN_THREAD_EM_ASM({
|
||||
/* Convert incoming buf pointer to a HEAPF32 offset. */
|
||||
#ifdef __wasm64__
|
||||
var buf = $0 / 4;
|
||||
#else
|
||||
var buf = $0 >>> 2;
|
||||
#endif
|
||||
|
||||
var SDL3 = Module['SDL3'];
|
||||
var numChannels = SDL3.audio_playback.currentPlaybackBuffer['numberOfChannels'];
|
||||
for (var c = 0; c < numChannels; ++c) {
|
||||
@@ -49,7 +56,7 @@ static bool EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buf
|
||||
}
|
||||
|
||||
for (var j = 0; j < $1; ++j) {
|
||||
channelData[j] = HEAPF32[$0 + ((j*numChannels + c) << 2) >> 2]; // !!! FIXME: why are these shifts here?
|
||||
channelData[j] = HEAPF32[buf + (j*numChannels + c)];
|
||||
}
|
||||
}
|
||||
}, buffer, buffer_size / framelen);
|
||||
|
||||
@@ -50,6 +50,9 @@ static const CameraBootStrap *const bootstrap[] = {
|
||||
#ifdef SDL_CAMERA_DRIVER_MEDIAFOUNDATION
|
||||
&MEDIAFOUNDATION_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_CAMERA_DRIVER_VITA
|
||||
&VITACAMERA_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_CAMERA_DRIVER_DUMMY
|
||||
&DUMMYCAMERA_bootstrap,
|
||||
#endif
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
|
||||
#define DEBUG_CAMERA 0
|
||||
|
||||
typedef struct SDL_Camera SDL_Camera;
|
||||
|
||||
/* Backends should call this as devices are added to the system (such as
|
||||
a USB camera being plugged in), and should also be called for
|
||||
for every device found during DetectDevices(). */
|
||||
@@ -217,5 +215,6 @@ extern CameraBootStrap COREMEDIA_bootstrap;
|
||||
extern CameraBootStrap ANDROIDCAMERA_bootstrap;
|
||||
extern CameraBootStrap EMSCRIPTENCAMERA_bootstrap;
|
||||
extern CameraBootStrap MEDIAFOUNDATION_bootstrap;
|
||||
extern CameraBootStrap VITACAMERA_bootstrap;
|
||||
|
||||
#endif // SDL_syscamera_h_
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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_CAMERA_DRIVER_VITA
|
||||
|
||||
#include "../SDL_syscamera.h"
|
||||
#include <psp2/camera.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
|
||||
static struct {
|
||||
Sint32 w;
|
||||
Sint32 h;
|
||||
Sint32 res;
|
||||
} resolutions[] = {
|
||||
{640, 480, SCE_CAMERA_RESOLUTION_640_480},
|
||||
{320, 240, SCE_CAMERA_RESOLUTION_320_240},
|
||||
{160, 120, SCE_CAMERA_RESOLUTION_160_120},
|
||||
{352, 288, SCE_CAMERA_RESOLUTION_352_288},
|
||||
{176, 144, SCE_CAMERA_RESOLUTION_176_144},
|
||||
{480, 272, SCE_CAMERA_RESOLUTION_480_272},
|
||||
{640, 360, SCE_CAMERA_RESOLUTION_640_360},
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static Sint32 fps[] = {5, 10, 15, 20, 24, 25, 30, 60, 0};
|
||||
|
||||
static void GatherCameraSpecs(Sint32 devid, CameraFormatAddData *add_data, char **fullname, SDL_CameraPosition *position)
|
||||
{
|
||||
SDL_zerop(add_data);
|
||||
|
||||
if (devid == SCE_CAMERA_DEVICE_FRONT) {
|
||||
*position = SDL_CAMERA_POSITION_FRONT_FACING;
|
||||
*fullname = SDL_strdup("Front-facing camera");
|
||||
} else if (devid == SCE_CAMERA_DEVICE_BACK) {
|
||||
*position = SDL_CAMERA_POSITION_BACK_FACING;
|
||||
*fullname = SDL_strdup("Back-facing camera");
|
||||
}
|
||||
|
||||
if (!*fullname) {
|
||||
*fullname = SDL_strdup("Generic camera");
|
||||
}
|
||||
|
||||
// Note: there are actually more fps and pixelformats. Planar YUV is fastest. Support only YUV and integer fps for now
|
||||
Sint32 idx = 0;
|
||||
while (resolutions[idx].res > 0) {
|
||||
Sint32 fps_idx = 0;
|
||||
while (fps[fps_idx] > 0) {
|
||||
SDL_AddCameraFormat(add_data, SDL_PIXELFORMAT_IYUV, SDL_COLORSPACE_BT601_LIMITED, resolutions[idx].w, resolutions[idx].h, fps[fps_idx], 1); /* SCE_CAMERA_FORMAT_ARGB */
|
||||
fps_idx++;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool FindVitaCameraByID(SDL_Camera *device, void *userdata)
|
||||
{
|
||||
Sint32 devid = (Sint32) userdata;
|
||||
return (devid == (Sint32)device->handle);
|
||||
}
|
||||
|
||||
static void MaybeAddDevice(Sint32 devid)
|
||||
{
|
||||
#if DEBUG_CAMERA
|
||||
SDL_Log("CAMERA: MaybeAddDevice('%d')", devid);
|
||||
#endif
|
||||
|
||||
if (SDL_FindPhysicalCameraByCallback(FindVitaCameraByID, (void *) devid)) {
|
||||
return; // already have this one.
|
||||
}
|
||||
|
||||
SDL_CameraPosition position = SDL_CAMERA_POSITION_UNKNOWN;
|
||||
char *fullname = NULL;
|
||||
CameraFormatAddData add_data;
|
||||
GatherCameraSpecs(devid, &add_data, &fullname, &position);
|
||||
|
||||
if (add_data.num_specs > 0) {
|
||||
SDL_AddCamera(fullname, position, add_data.num_specs, add_data.specs, (void*)devid);
|
||||
}
|
||||
|
||||
SDL_free(fullname);
|
||||
SDL_free(add_data.specs);
|
||||
}
|
||||
|
||||
static SceUID imbUid = -1;
|
||||
|
||||
static void freeBuffers(SceCameraInfo* info)
|
||||
{
|
||||
if (imbUid != -1) {
|
||||
sceKernelFreeMemBlock(imbUid);
|
||||
info->pIBase = NULL;
|
||||
imbUid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool VITACAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec)
|
||||
{
|
||||
// we can't open more than one camera, so error-out early
|
||||
if (imbUid != -1) {
|
||||
return SDL_SetError("Only one camera can be active");
|
||||
}
|
||||
|
||||
SceCameraInfo* info = (SceCameraInfo*)SDL_calloc(1, sizeof(SceCameraInfo));
|
||||
|
||||
info->size = sizeof(SceCameraInfo);
|
||||
info->priority = SCE_CAMERA_PRIORITY_SHARE;
|
||||
info->buffer = 0; // target buffer set by sceCameraOpen
|
||||
|
||||
info->framerate = spec->framerate_numerator / spec->framerate_denominator;
|
||||
|
||||
Sint32 idx = 0;
|
||||
while (resolutions[idx].res > 0) {
|
||||
if (spec->width == resolutions[idx].w && spec->height == resolutions[idx].h) {
|
||||
info->resolution = resolutions[idx].res;
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
info->range = 1;
|
||||
info->format = SCE_CAMERA_FORMAT_YUV420_PLANE;
|
||||
info->pitch = 0; // same size surface
|
||||
|
||||
info->sizeIBase = spec->width*spec->height;;
|
||||
info->sizeUBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
|
||||
info->sizeVBase = ((spec->width+1)/2) * ((spec->height+1) / 2);
|
||||
|
||||
// PHYCONT memory size *must* be a multiple of 1MB, we can just always spend 2MB, since we don't use PHYCONT anywhere else
|
||||
imbUid = sceKernelAllocMemBlock("CameraI", SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW, 2*1024*1024 , NULL);
|
||||
if (imbUid < 0)
|
||||
{
|
||||
return SDL_SetError("sceKernelAllocMemBlock error: 0x%08X", imbUid);
|
||||
}
|
||||
sceKernelGetMemBlockBase(imbUid, &(info->pIBase));
|
||||
|
||||
info->pUBase = info->pIBase + info->sizeIBase;
|
||||
info->pVBase = info->pIBase + (info->sizeIBase + info->sizeUBase);
|
||||
|
||||
device->hidden = (struct SDL_PrivateCameraData *)info;
|
||||
|
||||
int ret = sceCameraOpen((int)device->handle, info);
|
||||
if (ret == 0) {
|
||||
ret = sceCameraStart((int)device->handle);
|
||||
if (ret == 0) {
|
||||
SDL_CameraPermissionOutcome(device, true);
|
||||
return true;
|
||||
} else {
|
||||
SDL_SetError("sceCameraStart error: 0x%08X", imbUid);
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("sceCameraOpen error: 0x%08X", imbUid);
|
||||
}
|
||||
|
||||
freeBuffers(info);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void VITACAMERA_CloseDevice(SDL_Camera *device)
|
||||
{
|
||||
if (device->hidden) {
|
||||
sceCameraStop((int)device->handle);
|
||||
sceCameraClose((int)device->handle);
|
||||
freeBuffers((SceCameraInfo*)device->hidden);
|
||||
SDL_free(device->hidden);
|
||||
}
|
||||
}
|
||||
|
||||
static bool VITACAMERA_WaitDevice(SDL_Camera *device)
|
||||
{
|
||||
while(!sceCameraIsActive((int)device->handle)) {}
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_CameraFrameResult VITACAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
|
||||
{
|
||||
SceCameraRead read = {0};
|
||||
read.size = sizeof(SceCameraRead);
|
||||
read.mode = 1; // don't wait next frame
|
||||
|
||||
int ret = sceCameraRead((int)device->handle, &read);
|
||||
|
||||
if (ret < 0) {
|
||||
SDL_SetError("sceCameraRead error: 0x%08X", ret);
|
||||
return SDL_CAMERA_FRAME_ERROR;
|
||||
}
|
||||
|
||||
*timestampNS = read.timestamp;
|
||||
|
||||
SceCameraInfo* info = (SceCameraInfo*)(device->hidden);
|
||||
|
||||
frame->pitch = info->width;
|
||||
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), info->sizeIBase + info->sizeUBase + info->sizeVBase);
|
||||
|
||||
if (frame->pixels) {
|
||||
SDL_memcpy(frame->pixels, info->pIBase, info->sizeIBase + info->sizeUBase + info->sizeVBase);
|
||||
return SDL_CAMERA_FRAME_READY;
|
||||
}
|
||||
|
||||
return SDL_CAMERA_FRAME_ERROR;
|
||||
}
|
||||
|
||||
static void VITACAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame)
|
||||
{
|
||||
SDL_aligned_free(frame->pixels);
|
||||
}
|
||||
|
||||
static void VITACAMERA_DetectDevices(void)
|
||||
{
|
||||
MaybeAddDevice(SCE_CAMERA_DEVICE_FRONT);
|
||||
MaybeAddDevice(SCE_CAMERA_DEVICE_BACK);
|
||||
}
|
||||
|
||||
static void VITACAMERA_FreeDeviceHandle(SDL_Camera *device)
|
||||
{
|
||||
}
|
||||
|
||||
static void VITACAMERA_Deinitialize(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool VITACAMERA_Init(SDL_CameraDriverImpl *impl)
|
||||
{
|
||||
impl->DetectDevices = VITACAMERA_DetectDevices;
|
||||
impl->OpenDevice = VITACAMERA_OpenDevice;
|
||||
impl->CloseDevice = VITACAMERA_CloseDevice;
|
||||
impl->WaitDevice = VITACAMERA_WaitDevice;
|
||||
impl->AcquireFrame = VITACAMERA_AcquireFrame;
|
||||
impl->ReleaseFrame = VITACAMERA_ReleaseFrame;
|
||||
impl->FreeDeviceHandle = VITACAMERA_FreeDeviceHandle;
|
||||
impl->Deinitialize = VITACAMERA_Deinitialize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CameraBootStrap VITACAMERA_bootstrap = {
|
||||
"vita", "SDL PSVita camera driver", VITACAMERA_Init, false
|
||||
};
|
||||
|
||||
#endif // SDL_CAMERA_DRIVER_VITA
|
||||
@@ -146,8 +146,8 @@ const char *SDL_GetAndroidInternalStoragePath(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_DECLSPEC void *SDLCALL SDL_GetAndroidJNIEnv(void);
|
||||
void *SDL_GetAndroidJNIEnv(void)
|
||||
SDL_DECLSPEC JNIEnv *SDLCALL SDL_GetAndroidJNIEnv(void);
|
||||
JNIEnv *SDL_GetAndroidJNIEnv(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
|
||||
@@ -2177,7 +2177,7 @@ bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *b
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
void *SDL_GetAndroidJNIEnv(void)
|
||||
JNIEnv *SDL_GetAndroidJNIEnv(void)
|
||||
{
|
||||
return Android_JNI_GetEnv();
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ bool Android_JNI_OpenURL(const char *url);
|
||||
int SDL_GetAndroidSDKVersion(void);
|
||||
|
||||
bool SDL_IsAndroidTablet(void);
|
||||
bool SDL_IsAndroidTV(void);
|
||||
|
||||
// File Dialogs
|
||||
bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void* userdata,
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "SDL_sandbox.h"
|
||||
#include "../../stdlib/SDL_vacopy.h"
|
||||
|
||||
#ifdef SDL_USE_LIBDBUS
|
||||
@@ -443,7 +442,7 @@ bool SDL_DBus_ScreensaverInhibit(bool inhibit)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
|
||||
if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
|
||||
const char *bus_name = "org.freedesktop.portal.Desktop";
|
||||
const char *path = "/org/freedesktop/portal/desktop";
|
||||
const char *interface = "org.freedesktop.portal.Inhibit";
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 2022 Collabora Ltd.
|
||||
|
||||
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"
|
||||
|
||||
#include "SDL_sandbox.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
SDL_Sandbox SDL_DetectSandbox(void)
|
||||
{
|
||||
if (access("/.flatpak-info", F_OK) == 0) {
|
||||
return SDL_SANDBOX_FLATPAK;
|
||||
}
|
||||
|
||||
/* For Snap, we check multiple variables because they might be set for
|
||||
* unrelated reasons. This is the same thing WebKitGTK does. */
|
||||
if (SDL_getenv("SNAP") != NULL &&
|
||||
SDL_getenv("SNAP_NAME") != NULL &&
|
||||
SDL_getenv("SNAP_REVISION") != NULL) {
|
||||
return SDL_SANDBOX_SNAP;
|
||||
}
|
||||
|
||||
if (access("/run/host/container-manager", F_OK) == 0) {
|
||||
return SDL_SANDBOX_UNKNOWN_CONTAINER;
|
||||
}
|
||||
|
||||
return SDL_SANDBOX_NONE;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 2022 Collabora Ltd.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef SDL_SANDBOX_H
|
||||
#define SDL_SANDBOX_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SDL_SANDBOX_NONE = 0,
|
||||
SDL_SANDBOX_UNKNOWN_CONTAINER,
|
||||
SDL_SANDBOX_FLATPAK,
|
||||
SDL_SANDBOX_SNAP,
|
||||
} SDL_Sandbox;
|
||||
|
||||
// Return the sandbox type currently in use, if any
|
||||
SDL_Sandbox SDL_DetectSandbox(void);
|
||||
|
||||
#endif // SDL_SANDBOX_H
|
||||
@@ -119,7 +119,7 @@ extern "C" {
|
||||
// Sets an error message based on a given HRESULT
|
||||
extern bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
|
||||
|
||||
// Sets an error message based on GetLastError(). Always return -1.
|
||||
// Sets an error message based on GetLastError(). Always returns false.
|
||||
extern bool WIN_SetError(const char *prefix);
|
||||
|
||||
// Load a function from combase.dll
|
||||
|
||||
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,1,3,0
|
||||
PRODUCTVERSION 3,1,3,0
|
||||
FILEVERSION 3,1,5,0
|
||||
PRODUCTVERSION 3,1,5,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS 0x40004L
|
||||
@@ -23,12 +23,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "SDL\0"
|
||||
VALUE "FileVersion", "3, 1, 3, 0\0"
|
||||
VALUE "FileVersion", "3, 1, 5, 0\0"
|
||||
VALUE "InternalName", "SDL\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0"
|
||||
VALUE "OriginalFilename", "SDL3.dll\0"
|
||||
VALUE "ProductName", "Simple DirectMedia Layer\0"
|
||||
VALUE "ProductVersion", "3, 1, 3, 0\0"
|
||||
VALUE "ProductVersion", "3, 1, 5, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "SDL_internal.h"
|
||||
#include "../SDL_dialog_utils.h"
|
||||
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <UniformTypeIdentifiers/UTType.h>
|
||||
|
||||
@@ -33,10 +35,6 @@ typedef enum
|
||||
|
||||
void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
|
||||
{
|
||||
#if defined(SDL_PLATFORM_TVOS) || defined(SDL_PLATFORM_IOS)
|
||||
SDL_SetError("tvOS and iOS don't support path-based file dialogs");
|
||||
callback(userdata, NULL, -1);
|
||||
#else
|
||||
if (filters) {
|
||||
const char *msg = validate_filters(filters, nfilters);
|
||||
|
||||
@@ -175,7 +173,6 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback
|
||||
callback(userdata, files, -1);
|
||||
}
|
||||
}
|
||||
#endif // defined(SDL_PLATFORM_TVOS) || defined(SDL_PLATFORM_IOS)
|
||||
}
|
||||
|
||||
void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
|
||||
@@ -192,3 +189,5 @@ void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, S
|
||||
{
|
||||
show_file_dialog(FDT_OPENFOLDER, callback, userdata, window, NULL, 0, default_location, allow_many);
|
||||
}
|
||||
|
||||
#endif // SDL_PLATFORM_MACOS
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_DIALOG_DUMMY
|
||||
|
||||
void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
@@ -37,3 +39,5 @@ void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, S
|
||||
SDL_Unsupported();
|
||||
callback(userdata, NULL, -1);
|
||||
}
|
||||
|
||||
#endif // SDL_DIALOG_DUMMY
|
||||
|
||||
@@ -194,11 +194,6 @@ typedef struct
|
||||
#undef SDL_DYNAPI_PROC
|
||||
} SDL_DYNAPI_jump_table;
|
||||
|
||||
// Predeclare the default functions for initializing the jump table.
|
||||
#define SDL_DYNAPI_PROC(rc, fn, params, args, ret) static rc SDLCALL fn##_DEFAULT params;
|
||||
#include "SDL_dynapi_procs.h"
|
||||
#undef SDL_DYNAPI_PROC
|
||||
|
||||
// The actual jump table.
|
||||
static SDL_DYNAPI_jump_table jump_table = {
|
||||
#define SDL_DYNAPI_PROC(rc, fn, params, args, ret) fn##_DEFAULT,
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE // probably not useful on iOS.
|
||||
#if defined(SDL_PLATFORM_PRIVATE) // probably not useful on private platforms.
|
||||
#define SDL_DYNAMIC_API 0
|
||||
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE // probably not useful on iOS.
|
||||
#define SDL_DYNAMIC_API 0
|
||||
#elif defined(SDL_PLATFORM_ANDROID) // probably not useful on Android.
|
||||
#define SDL_DYNAMIC_API 0
|
||||
|
||||
@@ -1176,6 +1176,13 @@ SDL3_0.0.0 {
|
||||
SDL_wcsnstr;
|
||||
SDL_wcsstr;
|
||||
SDL_wcstol;
|
||||
SDL_StepBackUTF8;
|
||||
SDL_DelayPrecise;
|
||||
SDL_CalculateGPUTextureFormatSize;
|
||||
SDL_SetErrorV;
|
||||
SDL_GetDefaultLogOutputFunction;
|
||||
SDL_RenderDebugText;
|
||||
SDL_GetSandbox;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -1201,3 +1201,10 @@
|
||||
#define SDL_wcsnstr SDL_wcsnstr_REAL
|
||||
#define SDL_wcsstr SDL_wcsstr_REAL
|
||||
#define SDL_wcstol SDL_wcstol_REAL
|
||||
#define SDL_StepBackUTF8 SDL_StepBackUTF8_REAL
|
||||
#define SDL_DelayPrecise SDL_DelayPrecise_REAL
|
||||
#define SDL_CalculateGPUTextureFormatSize SDL_CalculateGPUTextureFormatSize_REAL
|
||||
#define SDL_SetErrorV SDL_SetErrorV_REAL
|
||||
#define SDL_GetDefaultLogOutputFunction SDL_GetDefaultLogOutputFunction_REAL
|
||||
#define SDL_RenderDebugText SDL_RenderDebugText_REAL
|
||||
#define SDL_GetSandbox SDL_GetSandbox_REAL
|
||||
|
||||
@@ -255,7 +255,7 @@ SDL_DYNAPI_PROC(const char*,SDL_GetAndroidCachePath,(void),(),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetAndroidExternalStoragePath,(void),(),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetAndroidExternalStorageState,(void),(),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetAndroidInternalStoragePath,(void),(),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_GetAndroidJNIEnv,(void),(),return)
|
||||
SDL_DYNAPI_PROC(JNIEnv*,SDL_GetAndroidJNIEnv,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetAppMetadataProperty,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return)
|
||||
@@ -1207,3 +1207,10 @@ SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_StepBackUTF8,(const char *a, const char **b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_DelayPrecise,(Uint64 a),(a),)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_CalculateGPUTextureFormatSize,(SDL_GPUTextureFormat a, Uint32 b, Uint32 c, Uint32 d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_SetErrorV,(SDL_PRINTF_FORMAT_STRING const char *a,va_list b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_LogOutputFunction,SDL_GetDefaultLogOutputFunction,(void),(),return)
|
||||
SDL_DYNAPI_PROC(bool,SDL_RenderDebugText,(SDL_Renderer *a,float b,float c,const char *d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(SDL_Sandbox,SDL_GetSandbox,(void),(),return)
|
||||
|
||||
+223
-265
@@ -24,60 +24,68 @@
|
||||
# output looks sane (git diff, it adds to existing files), and commit it.
|
||||
# It keeps the dynamic API jump table operating correctly.
|
||||
#
|
||||
# OS-specific API:
|
||||
# Platform-specific API:
|
||||
# After running the script, you have to manually add #ifdef SDL_PLATFORM_WIN32
|
||||
# or similar around the function in 'SDL_dynapi_procs.h'
|
||||
# or similar around the function in 'SDL_dynapi_procs.h'.
|
||||
#
|
||||
|
||||
import argparse
|
||||
import dataclasses
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
from pathlib import Path
|
||||
import pprint
|
||||
import re
|
||||
|
||||
|
||||
SDL_ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||
SDL_ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3"
|
||||
SDL_DYNAPI_PROCS_H = SDL_ROOT / "src/dynapi/SDL_dynapi_procs.h"
|
||||
SDL_DYNAPI_OVERRIDES_H = SDL_ROOT / "src/dynapi/SDL_dynapi_overrides.h"
|
||||
SDL_DYNAPI_SYM = SDL_ROOT / "src/dynapi/SDL_dynapi.sym"
|
||||
|
||||
full_API = []
|
||||
RE_EXTERN_C = re.compile(r'.*extern[ "]*C[ "].*')
|
||||
RE_COMMENT_REMOVE_CONTENT = re.compile(r'\/\*.*\*/')
|
||||
RE_PARSING_FUNCTION = re.compile(r'(.*SDLCALL[^\(\)]*) ([a-zA-Z0-9_]+) *\((.*)\) *;.*')
|
||||
|
||||
#eg:
|
||||
# void (SDLCALL *callback)(void*, int)
|
||||
# \1(\2)\3
|
||||
RE_PARSING_CALLBACK = re.compile(r'([^\(\)]*)\(([^\(\)]+)\)(.*)')
|
||||
|
||||
|
||||
def main():
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Parse 'sdl_dynapi_procs_h' file to find existing functions
|
||||
existing_procs = find_existing_procs()
|
||||
|
||||
# Get list of SDL headers
|
||||
sdl_list_includes = get_header_list()
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class SdlProcedure:
|
||||
retval: str
|
||||
name: str
|
||||
parameter: list[str]
|
||||
parameter_name: list[str]
|
||||
header: str
|
||||
comment: str
|
||||
|
||||
reg_externC = re.compile(r'.*extern[ "]*C[ "].*')
|
||||
reg_comment_remove_content = re.compile(r'\/\*.*\*/')
|
||||
reg_parsing_function = re.compile(r'(.*SDLCALL[^\(\)]*) ([a-zA-Z0-9_]+) *\((.*)\) *;.*')
|
||||
@property
|
||||
def variadic(self) -> bool:
|
||||
return "..." in self.parameter
|
||||
|
||||
#eg:
|
||||
# void (SDLCALL *callback)(void*, int)
|
||||
# \1(\2)\3
|
||||
reg_parsing_callback = re.compile(r'([^\(\)]*)\(([^\(\)]+)\)(.*)')
|
||||
|
||||
for filename in sdl_list_includes:
|
||||
if args.debug:
|
||||
print("Parse header: %s" % filename)
|
||||
def parse_header(header_path: Path) -> list[SdlProcedure]:
|
||||
logger.debug("Parse header: %s", header_path)
|
||||
|
||||
input = open(filename)
|
||||
header_procedures = []
|
||||
|
||||
parsing_function = False
|
||||
current_func = ""
|
||||
parsing_comment = False
|
||||
current_comment = ""
|
||||
parsing_function = False
|
||||
current_func = ""
|
||||
parsing_comment = False
|
||||
current_comment = ""
|
||||
ignore_wiki_documentation = False
|
||||
|
||||
ignore_wiki_documentation = False
|
||||
|
||||
for line in input:
|
||||
with header_path.open() as f:
|
||||
for line in f:
|
||||
|
||||
# Skip lines if we're in a wiki documentation block.
|
||||
if ignore_wiki_documentation:
|
||||
@@ -95,13 +103,13 @@ def main():
|
||||
continue
|
||||
|
||||
# Discard "extern C" line
|
||||
match = reg_externC.match(line)
|
||||
match = RE_EXTERN_C.match(line)
|
||||
if match:
|
||||
continue
|
||||
|
||||
# Remove one line comment // ...
|
||||
# eg: extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */);
|
||||
line = reg_comment_remove_content.sub('', line)
|
||||
# eg: extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */)
|
||||
line = RE_COMMENT_REMOVE_CONTENT.sub('', line)
|
||||
|
||||
# Get the comment block /* ... */ across several lines
|
||||
match_start = "/*" in line
|
||||
@@ -131,14 +139,14 @@ def main():
|
||||
continue
|
||||
# Start grabbing the new function
|
||||
current_func = line.strip()
|
||||
parsing_function = True;
|
||||
parsing_function = True
|
||||
|
||||
# If it contains ';', then the function is complete
|
||||
if ";" not in current_func:
|
||||
continue
|
||||
|
||||
# Got function/comment, reset vars
|
||||
parsing_function = False;
|
||||
parsing_function = False
|
||||
func = current_func
|
||||
comment = current_comment
|
||||
current_func = ""
|
||||
@@ -146,47 +154,48 @@ def main():
|
||||
|
||||
# Discard if it doesn't contain 'SDLCALL'
|
||||
if "SDLCALL" not in func:
|
||||
if args.debug:
|
||||
print(" Discard, doesn't have SDLCALL: " + func)
|
||||
logger.debug(" Discard, doesn't have SDLCALL: %r", func)
|
||||
continue
|
||||
|
||||
# Discard if it contains 'SDLMAIN_DECLSPEC' (these are not SDL symbols).
|
||||
if "SDLMAIN_DECLSPEC" in func:
|
||||
if args.debug:
|
||||
print(" Discard, has SDLMAIN_DECLSPEC: " + func)
|
||||
logger.debug(" Discard, has SDLMAIN_DECLSPEC: %r", func)
|
||||
continue
|
||||
|
||||
if args.debug:
|
||||
print(" Raw data: " + func);
|
||||
logger.debug("Raw data: %r", func)
|
||||
|
||||
# Replace unusual stuff...
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(1)", "");
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(2)", "");
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(3)", "");
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(1)", "");
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(2)", "");
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(3)", "");
|
||||
func = func.replace(" SDL_WPRINTF_VARARG_FUNC(3)", "");
|
||||
func = func.replace(" SDL_WPRINTF_VARARG_FUNCV(3)", "");
|
||||
func = func.replace(" SDL_SCANF_VARARG_FUNC(2)", "");
|
||||
func = func.replace(" SDL_SCANF_VARARG_FUNCV(2)", "");
|
||||
func = func.replace(" SDL_ANALYZER_NORETURN", "");
|
||||
func = func.replace(" SDL_MALLOC", "");
|
||||
func = func.replace(" SDL_ALLOC_SIZE2(1, 2)", "");
|
||||
func = func.replace(" SDL_ALLOC_SIZE(2)", "");
|
||||
func = re.sub(r" SDL_ACQUIRE\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_ACQUIRE_SHARED\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_TRY_ACQUIRE\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_TRY_ACQUIRE_SHARED\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_RELEASE\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_RELEASE_SHARED\(.*\)", "", func);
|
||||
func = re.sub(r" SDL_RELEASE_GENERIC\(.*\)", "", func);
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(1)", "")
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(2)", "")
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNC(3)", "")
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(1)", "")
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(2)", "")
|
||||
func = func.replace(" SDL_PRINTF_VARARG_FUNCV(3)", "")
|
||||
func = func.replace(" SDL_WPRINTF_VARARG_FUNC(3)", "")
|
||||
func = func.replace(" SDL_WPRINTF_VARARG_FUNCV(3)", "")
|
||||
func = func.replace(" SDL_SCANF_VARARG_FUNC(2)", "")
|
||||
func = func.replace(" SDL_SCANF_VARARG_FUNCV(2)", "")
|
||||
func = func.replace(" SDL_ANALYZER_NORETURN", "")
|
||||
func = func.replace(" SDL_MALLOC", "")
|
||||
func = func.replace(" SDL_ALLOC_SIZE2(1, 2)", "")
|
||||
func = func.replace(" SDL_ALLOC_SIZE(2)", "")
|
||||
func = re.sub(r" SDL_ACQUIRE\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_ACQUIRE_SHARED\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_TRY_ACQUIRE\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_TRY_ACQUIRE_SHARED\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_RELEASE\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_RELEASE_SHARED\(.*\)", "", func)
|
||||
func = re.sub(r" SDL_RELEASE_GENERIC\(.*\)", "", func)
|
||||
func = re.sub(r"([ (),])(SDL_IN_BYTECAP\([^)]*\))", r"\1", func)
|
||||
func = re.sub(r"([ (),])(SDL_OUT_BYTECAP\([^)]*\))", r"\1", func)
|
||||
func = re.sub(r"([ (),])(SDL_INOUT_Z_CAP\([^)]*\))", r"\1", func)
|
||||
func = re.sub(r"([ (),])(SDL_OUT_Z_CAP\([^)]*\))", r"\1", func)
|
||||
|
||||
# Should be a valid function here
|
||||
match = reg_parsing_function.match(func)
|
||||
match = RE_PARSING_FUNCTION.match(func)
|
||||
if not match:
|
||||
print("Cannot parse: "+ func)
|
||||
exit(-1)
|
||||
logger.error("Cannot parse: %s", func)
|
||||
raise ValueError(func)
|
||||
|
||||
func_ret = match.group(1)
|
||||
func_name = match.group(2)
|
||||
@@ -198,11 +207,8 @@ def main():
|
||||
func_ret = func_ret.replace('extern', ' ')
|
||||
func_ret = func_ret.replace('SDLCALL', ' ')
|
||||
func_ret = func_ret.replace('SDL_DECLSPEC', ' ')
|
||||
func_ret, _ = re.subn('([ ]{2,})', ' ', func_ret)
|
||||
# Remove trailing spaces in front of '*'
|
||||
tmp = ""
|
||||
while func_ret != tmp:
|
||||
tmp = func_ret
|
||||
func_ret = func_ret.replace(' ', ' ')
|
||||
func_ret = func_ret.replace(' *', '*')
|
||||
func_ret = func_ret.strip()
|
||||
|
||||
@@ -246,10 +252,10 @@ def main():
|
||||
|
||||
# parameter is a callback
|
||||
if '(' in t:
|
||||
match = reg_parsing_callback.match(t)
|
||||
match = RE_PARSING_CALLBACK.match(t)
|
||||
if not match:
|
||||
print("cannot parse callback: " + t);
|
||||
exit(-1)
|
||||
logger.error("cannot parse callback: %s", t)
|
||||
raise ValueError(t)
|
||||
a = match.group(1).strip()
|
||||
b = match.group(2).strip()
|
||||
c = match.group(3).strip()
|
||||
@@ -257,7 +263,7 @@ def main():
|
||||
try:
|
||||
(param_type, param_name) = b.rsplit('*', 1)
|
||||
except:
|
||||
param_type = t;
|
||||
param_type = t
|
||||
param_name = "param_name_not_specified"
|
||||
|
||||
# bug rsplit ??
|
||||
@@ -281,7 +287,7 @@ def main():
|
||||
try:
|
||||
(param_type, param_name) = t.rsplit('*', 1)
|
||||
except:
|
||||
param_type = t;
|
||||
param_type = t
|
||||
param_name = "param_name_not_specified"
|
||||
|
||||
# bug rsplit ??
|
||||
@@ -305,7 +311,7 @@ def main():
|
||||
try:
|
||||
(param_type, param_name) = t.rsplit(' ', 1)
|
||||
except:
|
||||
param_type = t;
|
||||
param_type = t
|
||||
param_name = "param_name_not_specified"
|
||||
|
||||
val = param_type.strip() + " REWRITE_NAME"
|
||||
@@ -317,268 +323,220 @@ def main():
|
||||
func_param_type.append(val)
|
||||
func_param_name.append(param_name.strip())
|
||||
|
||||
new_proc = {}
|
||||
# Return value type
|
||||
new_proc['retval'] = func_ret
|
||||
# List of parameters (type + anonymized param name 'REWRITE_NAME')
|
||||
new_proc['parameter'] = func_param_type
|
||||
# Real parameter name, or 'param_name_not_specified'
|
||||
new_proc['parameter_name'] = func_param_name
|
||||
# Function name
|
||||
new_proc['name'] = func_name
|
||||
# Header file
|
||||
new_proc['header'] = os.path.basename(filename)
|
||||
# Function comment
|
||||
new_proc['comment'] = comment
|
||||
new_proc = SdlProcedure(
|
||||
retval=func_ret, # Return value type
|
||||
name=func_name, # Function name
|
||||
comment=comment, # Function comment
|
||||
header=header_path.name, # Header file
|
||||
parameter=func_param_type, # List of parameters (type + anonymized param name 'REWRITE_NAME')
|
||||
parameter_name=func_param_name, # Real parameter name, or 'param_name_not_specified'
|
||||
)
|
||||
|
||||
full_API.append(new_proc)
|
||||
header_procedures.append(new_proc)
|
||||
|
||||
if args.debug:
|
||||
pprint.pprint(new_proc);
|
||||
print("\n")
|
||||
if logger.getEffectiveLevel() <= logging.DEBUG:
|
||||
logger.debug("%s", pprint.pformat(new_proc))
|
||||
|
||||
if func_name not in existing_procs:
|
||||
print("NEW " + func)
|
||||
add_dyn_api(new_proc)
|
||||
return header_procedures
|
||||
|
||||
# For-End line in input
|
||||
|
||||
input.close()
|
||||
# For-End parsing all files of sdl_list_includes
|
||||
|
||||
# Dump API into a json file
|
||||
full_API_json()
|
||||
|
||||
# Check comment formatting
|
||||
check_comment();
|
||||
|
||||
# Dump API into a json file
|
||||
def full_API_json():
|
||||
if args.dump:
|
||||
filename = 'sdl.json'
|
||||
with open(filename, 'w', newline='') as f:
|
||||
json.dump(full_API, f, indent=4, sort_keys=True)
|
||||
print("dump API to '%s'" % filename);
|
||||
def full_API_json(path: Path, procedures: list[SdlProcedure]):
|
||||
with path.open('w', newline='') as f:
|
||||
json.dump([dataclasses.asdict(proc) for proc in procedures], f, indent=4, sort_keys=True)
|
||||
logger.info("dump API to '%s'", path)
|
||||
|
||||
|
||||
class CallOnce:
|
||||
def __init__(self, cb):
|
||||
self._cb = cb
|
||||
self._called = False
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self._called:
|
||||
return
|
||||
self._called = True
|
||||
self._cb(*args, **kwargs)
|
||||
|
||||
|
||||
# Check public function comments are correct
|
||||
def check_comment_header():
|
||||
if not check_comment_header.done:
|
||||
check_comment_header.done = True
|
||||
print("")
|
||||
print("Please fix following warning(s):")
|
||||
print("-------------------------------")
|
||||
def print_check_comment_header():
|
||||
logger.warning("")
|
||||
logger.warning("Please fix following warning(s):")
|
||||
logger.warning("--------------------------------")
|
||||
|
||||
|
||||
def check_comment():
|
||||
def check_documentations(procedures: list[SdlProcedure]) -> None:
|
||||
|
||||
check_comment_header.done = False
|
||||
check_comment_header = CallOnce(print_check_comment_header)
|
||||
|
||||
warning_header_printed = False
|
||||
|
||||
# Check \param
|
||||
for i in full_API:
|
||||
comment = i['comment']
|
||||
name = i['name']
|
||||
retval = i['retval']
|
||||
header = i['header']
|
||||
|
||||
expected = len(i['parameter'])
|
||||
for proc in procedures:
|
||||
expected = len(proc.parameter)
|
||||
if expected == 1:
|
||||
if i['parameter'][0] == 'void':
|
||||
expected = 0;
|
||||
count = comment.count("\\param")
|
||||
if proc.parameter[0] == 'void':
|
||||
expected = 0
|
||||
count = proc.comment.count("\\param")
|
||||
if count != expected:
|
||||
# skip SDL_stdinc.h
|
||||
if header != 'SDL_stdinc.h':
|
||||
if proc.header != 'SDL_stdinc.h':
|
||||
# Warning mismatch \param and function prototype
|
||||
check_comment_header()
|
||||
print(" In file %s: function %s() has %d '\\param' but expected %d" % (header, name, count, expected));
|
||||
logger.warning(" In file %s: function %s() has %d '\\param' but expected %d", proc.header, proc.name, count, expected)
|
||||
|
||||
# Warning check \param uses the correct parameter name
|
||||
# skip SDL_stdinc.h
|
||||
if header != 'SDL_stdinc.h':
|
||||
parameter_name = i['parameter_name']
|
||||
for n in parameter_name:
|
||||
if n != "" and "\\param " + n not in comment and "\\param[out] " + n not in comment:
|
||||
if proc.header != 'SDL_stdinc.h':
|
||||
for n in proc.parameter_name:
|
||||
if n != "" and "\\param " + n not in proc.comment and "\\param[out] " + n not in proc.comment:
|
||||
check_comment_header()
|
||||
print(" In file %s: function %s() missing '\\param %s'" % (header, name, n));
|
||||
|
||||
logger.warning(" In file %s: function %s() missing '\\param %s'", proc.header, proc.name, n)
|
||||
|
||||
# Check \returns
|
||||
for i in full_API:
|
||||
comment = i['comment']
|
||||
name = i['name']
|
||||
retval = i['retval']
|
||||
header = i['header']
|
||||
|
||||
for proc in procedures:
|
||||
expected = 1
|
||||
if retval == 'void':
|
||||
expected = 0;
|
||||
if proc.retval == 'void':
|
||||
expected = 0
|
||||
|
||||
count = comment.count("\\returns")
|
||||
count = proc.comment.count("\\returns")
|
||||
if count != expected:
|
||||
# skip SDL_stdinc.h
|
||||
if header != 'SDL_stdinc.h':
|
||||
if proc.header != 'SDL_stdinc.h':
|
||||
# Warning mismatch \param and function prototype
|
||||
check_comment_header()
|
||||
print(" In file %s: function %s() has %d '\\returns' but expected %d" % (header, name, count, expected));
|
||||
logger.warning(" In file %s: function %s() has %d '\\returns' but expected %d" % (proc.header, proc.name, count, expected))
|
||||
|
||||
# Check \since
|
||||
for i in full_API:
|
||||
comment = i['comment']
|
||||
name = i['name']
|
||||
retval = i['retval']
|
||||
header = i['header']
|
||||
|
||||
for proc in procedures:
|
||||
expected = 1
|
||||
count = comment.count("\\since")
|
||||
count = proc.comment.count("\\since")
|
||||
if count != expected:
|
||||
# skip SDL_stdinc.h
|
||||
if header != 'SDL_stdinc.h':
|
||||
if proc.header != 'SDL_stdinc.h':
|
||||
# Warning mismatch \param and function prototype
|
||||
check_comment_header()
|
||||
print(" In file %s: function %s() has %d '\\since' but expected %d" % (header, name, count, expected));
|
||||
|
||||
logger.warning(" In file %s: function %s() has %d '\\since' but expected %d" % (proc.header, proc.name, count, expected))
|
||||
|
||||
|
||||
# Parse 'sdl_dynapi_procs_h' file to find existing functions
|
||||
def find_existing_procs():
|
||||
def find_existing_proc_names() -> list[str]:
|
||||
reg = re.compile(r'SDL_DYNAPI_PROC\([^,]*,([^,]*),.*\)')
|
||||
ret = []
|
||||
input = open(SDL_DYNAPI_PROCS_H)
|
||||
|
||||
for line in input:
|
||||
match = reg.match(line)
|
||||
if not match:
|
||||
continue
|
||||
existing_func = match.group(1)
|
||||
ret.append(existing_func);
|
||||
# print(existing_func)
|
||||
input.close()
|
||||
|
||||
with SDL_DYNAPI_PROCS_H.open() as f:
|
||||
for line in f:
|
||||
match = reg.match(line)
|
||||
if not match:
|
||||
continue
|
||||
existing_func = match.group(1)
|
||||
ret.append(existing_func)
|
||||
return ret
|
||||
|
||||
# Get list of SDL headers
|
||||
def get_header_list():
|
||||
reg = re.compile(r'^.*\.h$')
|
||||
def get_header_list() -> list[Path]:
|
||||
ret = []
|
||||
tmp = os.listdir(SDL_INCLUDE_DIR)
|
||||
|
||||
for f in tmp:
|
||||
for f in SDL_INCLUDE_DIR.iterdir():
|
||||
# Only *.h files
|
||||
match = reg.match(f)
|
||||
if not match:
|
||||
if args.debug:
|
||||
print("Skip %s" % f)
|
||||
continue
|
||||
ret.append(SDL_INCLUDE_DIR / f)
|
||||
if f.is_file() and f.suffix == ".h":
|
||||
ret.append(f)
|
||||
else:
|
||||
logger.debug("Skip %s", f)
|
||||
|
||||
return ret
|
||||
|
||||
# Write the new API in files: _procs.h _overrivides.h and .sym
|
||||
def add_dyn_api(proc):
|
||||
func_name = proc['name']
|
||||
func_ret = proc['retval']
|
||||
func_argtype = proc['parameter']
|
||||
def add_dyn_api(proc: SdlProcedure) -> None:
|
||||
decl_args: list[str] = []
|
||||
call_args = []
|
||||
for i, argtype in enumerate(proc.parameter):
|
||||
# Special case, void has no parameter name
|
||||
if argtype == "void":
|
||||
assert len(decl_args) == 0
|
||||
assert len(proc.parameter) == 1
|
||||
decl_args.append("void")
|
||||
continue
|
||||
|
||||
# Var name: a, b, c, ...
|
||||
varname = chr(ord('a') + i)
|
||||
|
||||
decl_args.append(argtype.replace("REWRITE_NAME", varname))
|
||||
if argtype != "...":
|
||||
call_args.append(varname)
|
||||
|
||||
macro_args = (
|
||||
proc.retval,
|
||||
proc.name,
|
||||
"({})".format(",".join(decl_args)),
|
||||
"({})".format(",".join(call_args)),
|
||||
"" if proc.retval == "void" else "return",
|
||||
)
|
||||
|
||||
# File: SDL_dynapi_procs.h
|
||||
#
|
||||
# Add at last
|
||||
# SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentConfig,(void),(),return)
|
||||
f = open(SDL_DYNAPI_PROCS_H, "a", newline="")
|
||||
dyn_proc = "SDL_DYNAPI_PROC(" + func_ret + "," + func_name + ",("
|
||||
|
||||
i = ord('a')
|
||||
remove_last = False
|
||||
for argtype in func_argtype:
|
||||
|
||||
# Special case, void has no parameter name
|
||||
if argtype == "void":
|
||||
dyn_proc += "void"
|
||||
continue
|
||||
|
||||
# Var name: a, b, c, ...
|
||||
varname = chr(i)
|
||||
i += 1
|
||||
|
||||
tmp = argtype.replace("REWRITE_NAME", varname)
|
||||
dyn_proc += tmp + ", "
|
||||
remove_last = True
|
||||
|
||||
# remove last 2 char ', '
|
||||
if remove_last:
|
||||
dyn_proc = dyn_proc[:-1]
|
||||
dyn_proc = dyn_proc[:-1]
|
||||
|
||||
dyn_proc += "),("
|
||||
|
||||
i = ord('a')
|
||||
remove_last = False
|
||||
for argtype in func_argtype:
|
||||
|
||||
# Special case, void has no parameter name
|
||||
if argtype == "void":
|
||||
continue
|
||||
|
||||
# Special case, '...' has no parameter name
|
||||
if argtype == "...":
|
||||
continue
|
||||
|
||||
# Var name: a, b, c, ...
|
||||
varname = chr(i)
|
||||
i += 1
|
||||
|
||||
dyn_proc += varname + ","
|
||||
remove_last = True
|
||||
|
||||
# remove last char ','
|
||||
if remove_last:
|
||||
dyn_proc = dyn_proc[:-1]
|
||||
|
||||
dyn_proc += "),"
|
||||
|
||||
if func_ret != "void":
|
||||
dyn_proc += "return"
|
||||
dyn_proc += ")"
|
||||
f.write(dyn_proc + "\n")
|
||||
f.close()
|
||||
with SDL_DYNAPI_PROCS_H.open("a", newline="") as f:
|
||||
if proc.variadic:
|
||||
f.write("#ifndef SDL_DYNAPI_PROC_NO_VARARGS\n")
|
||||
f.write(f"SDL_DYNAPI_PROC({','.join(macro_args)})\n")
|
||||
if proc.variadic:
|
||||
f.write("#endif\n")
|
||||
|
||||
# File: SDL_dynapi_overrides.h
|
||||
#
|
||||
# Add at last
|
||||
# "#define SDL_DelayNS SDL_DelayNS_REAL
|
||||
f = open(SDL_DYNAPI_OVERRIDES_H, "a", newline="")
|
||||
f.write("#define " + func_name + " " + func_name + "_REAL\n")
|
||||
f.write(f"#define {proc.name} {proc.name}_REAL\n")
|
||||
f.close()
|
||||
|
||||
# File: SDL_dynapi.sym
|
||||
#
|
||||
# Add before "extra symbols go here" line
|
||||
input = open(SDL_DYNAPI_SYM)
|
||||
new_input = []
|
||||
for line in input:
|
||||
if "extra symbols go here" in line:
|
||||
new_input.append(" " + func_name + ";\n")
|
||||
new_input.append(line)
|
||||
input.close()
|
||||
f = open(SDL_DYNAPI_SYM, 'w', newline='')
|
||||
for line in new_input:
|
||||
f.write(line)
|
||||
f.close()
|
||||
with SDL_DYNAPI_SYM.open() as f:
|
||||
new_input = []
|
||||
for line in f:
|
||||
if "extra symbols go here" in line:
|
||||
new_input.append(f" {proc.name};\n")
|
||||
new_input.append(line)
|
||||
|
||||
with SDL_DYNAPI_SYM.open('w', newline='') as f:
|
||||
for line in new_input:
|
||||
f.write(line)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.set_defaults(loglevel=logging.INFO)
|
||||
parser.add_argument('--dump', nargs='?', default=None, const="sdl.json", metavar="JSON", help='output all SDL API into a .json file')
|
||||
parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help='add debug traces')
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.basicConfig(level=args.loglevel, format='[%(levelname)s] %(message)s')
|
||||
|
||||
# Get list of SDL headers
|
||||
sdl_list_includes = get_header_list()
|
||||
procedures = []
|
||||
for filename in sdl_list_includes:
|
||||
header_procedures = parse_header(filename)
|
||||
procedures.extend(header_procedures)
|
||||
|
||||
# Parse 'sdl_dynapi_procs_h' file to find existing functions
|
||||
existing_proc_names = find_existing_proc_names()
|
||||
for procedure in procedures:
|
||||
if procedure.name not in existing_proc_names:
|
||||
logger.info("NEW %s", procedure.name)
|
||||
add_dyn_api(procedure)
|
||||
|
||||
if args.dump:
|
||||
# Dump API into a json file
|
||||
full_API_json(path=Path(args.dump), procedures=procedures)
|
||||
|
||||
# Check comment formatting
|
||||
check_documentations(procedures)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--dump', help='output all SDL API into a .json file', action='store_true')
|
||||
parser.add_argument('--debug', help='add debug traces', action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
exit(-1)
|
||||
|
||||
print("done!")
|
||||
exit(0)
|
||||
|
||||
raise SystemExit(main())
|
||||
|
||||
@@ -637,7 +637,12 @@ void SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
SDL_Keymod modstate = SDL_KMOD_NONE;
|
||||
SDL_Scancode scancode = SDL_GetKeymapScancode(keyboard->keymap, ch, &modstate);
|
||||
SDL_Scancode scancode;
|
||||
|
||||
if (ch == '\n') {
|
||||
ch = SDLK_RETURN;
|
||||
}
|
||||
scancode = SDL_GetKeymapScancode(keyboard->keymap, ch, &modstate);
|
||||
|
||||
// Make sure we have this keycode in our keymap
|
||||
if (scancode == SDL_SCANCODE_UNKNOWN && ch < SDLK_SCANCODE_MASK) {
|
||||
|
||||
@@ -133,7 +133,13 @@ static HANDLE SDLCALL windows_file_open(const char *filename, const char *mode)
|
||||
#endif
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
SDL_SetError("Couldn't open %s", filename);
|
||||
char *error;
|
||||
if (SDL_asprintf(&error, "Couldn't open %s", filename) > 0) {
|
||||
WIN_SetError(error);
|
||||
SDL_free(error);
|
||||
} else {
|
||||
SDL_SetError("Couldn't open %s", filename);
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
@@ -370,10 +376,8 @@ static int SDL_fdatasync(int fd)
|
||||
result = fcntl(fd, F_FULLFSYNC);
|
||||
#elif defined(SDL_PLATFORM_HAIKU)
|
||||
result = fsync(fd);
|
||||
#elif defined(_POSIX_SYNCHRONIZED_IO) // POSIX defines this if fdatasync() exists, so we don't need a CMake test.
|
||||
#ifndef SDL_PLATFORM_RISCOS // !!! FIXME: however, RISCOS doesn't have the symbol...maybe we need to link to an extra library or something?
|
||||
#elif defined(HAVE_FDATASYNC)
|
||||
result = fdatasync(fd);
|
||||
#endif
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@@ -1204,7 +1208,14 @@ done:
|
||||
|
||||
void *SDL_LoadFile(const char *file, size_t *datasize)
|
||||
{
|
||||
return SDL_LoadFile_IO(SDL_IOFromFile(file, "rb"), datasize, true);
|
||||
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
|
||||
if (!stream) {
|
||||
if (datasize) {
|
||||
*datasize = 0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return SDL_LoadFile_IO(stream, datasize, true);
|
||||
}
|
||||
|
||||
SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context)
|
||||
|
||||
+77
-15
@@ -386,22 +386,22 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_PRIVATE;
|
||||
}
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_SPIRV;
|
||||
}
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_DXBC;
|
||||
}
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_DXIL;
|
||||
}
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_MSL;
|
||||
}
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOL, false)) {
|
||||
if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN, false)) {
|
||||
format_flags |= SDL_GPU_SHADERFORMAT_METALLIB;
|
||||
}
|
||||
|
||||
@@ -449,24 +449,24 @@ static void SDL_GPU_FillProperties(
|
||||
const char *name)
|
||||
{
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_PRIVATE) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN, true);
|
||||
}
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_SPIRV) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, true);
|
||||
}
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_DXBC) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN, true);
|
||||
}
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_DXIL) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, true);
|
||||
}
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_MSL) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, true);
|
||||
}
|
||||
if (format_flags & SDL_GPU_SHADERFORMAT_METALLIB) {
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOL, true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN, true);
|
||||
}
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, debug_mode);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, debug_mode);
|
||||
SDL_SetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, name);
|
||||
}
|
||||
#endif // SDL_GPU_DISABLED
|
||||
@@ -526,8 +526,8 @@ SDL_GPUDevice *SDL_CreateGPUDeviceWithProperties(SDL_PropertiesID props)
|
||||
|
||||
selectedBackend = SDL_GPUSelectBackend(props);
|
||||
if (selectedBackend != NULL) {
|
||||
debug_mode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, true);
|
||||
preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOL, false);
|
||||
debug_mode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, true);
|
||||
preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, false);
|
||||
|
||||
result = selectedBackend->CreateDevice(debug_mode, preferLowPower, props);
|
||||
if (result != NULL) {
|
||||
@@ -619,6 +619,7 @@ Uint32 SDL_GPUTextureFormatTexelBlockSize(
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D16_UNORM:
|
||||
return 2;
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
|
||||
@@ -633,7 +634,12 @@ Uint32 SDL_GPUTextureFormatTexelBlockSize(
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
|
||||
return 4;
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT:
|
||||
return 5;
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM:
|
||||
@@ -642,6 +648,49 @@ Uint32 SDL_GPUTextureFormatTexelBlockSize(
|
||||
return 8;
|
||||
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
|
||||
return 16;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
|
||||
return 16;
|
||||
default:
|
||||
SDL_assert_release(!"Unrecognized TextureFormat!");
|
||||
return 0;
|
||||
@@ -2753,3 +2802,16 @@ void SDL_ReleaseGPUFence(
|
||||
device->driverData,
|
||||
fence);
|
||||
}
|
||||
|
||||
Uint32 SDL_CalculateGPUTextureFormatSize(
|
||||
SDL_GPUTextureFormat format,
|
||||
Uint32 width,
|
||||
Uint32 height,
|
||||
Uint32 depth_or_layer_count)
|
||||
{
|
||||
Uint32 blockWidth = SDL_max(Texture_GetBlockWidth(format), 1);
|
||||
Uint32 blockHeight = SDL_max(Texture_GetBlockHeight(format), 1);
|
||||
Uint32 blocksPerRow = (width + blockWidth - 1) / blockWidth;
|
||||
Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight;
|
||||
return depth_or_layer_count * blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format);
|
||||
}
|
||||
|
||||
+170
-21
@@ -69,7 +69,7 @@ typedef struct BlitPipelineCacheEntry
|
||||
|
||||
// Internal Helper Utilities
|
||||
|
||||
#define SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE (SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT + 1)
|
||||
#define SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE (SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT + 1)
|
||||
#define SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE (SDL_GPU_VERTEXELEMENTFORMAT_HALF4 + 1)
|
||||
#define SDL_GPU_COMPAREOP_MAX_ENUM_VALUE (SDL_GPU_COMPAREOP_ALWAYS + 1)
|
||||
#define SDL_GPU_STENCILOP_MAX_ENUM_VALUE (SDL_GPU_STENCILOP_DECREMENT_AND_WRAP + 1)
|
||||
@@ -78,10 +78,54 @@ typedef struct BlitPipelineCacheEntry
|
||||
#define SDL_GPU_SWAPCHAINCOMPOSITION_MAX_ENUM_VALUE (SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048 + 1)
|
||||
#define SDL_GPU_PRESENTMODE_MAX_ENUM_VALUE (SDL_GPU_PRESENTMODE_MAILBOX + 1)
|
||||
|
||||
static inline Sint32 Texture_GetBlockSize(
|
||||
static inline Sint32 Texture_GetBlockWidth(
|
||||
SDL_GPUTextureFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
|
||||
return 12;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
|
||||
return 10;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
|
||||
return 8;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
|
||||
return 6;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
|
||||
return 5;
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM:
|
||||
@@ -93,6 +137,9 @@ static inline Sint32 Texture_GetBlockSize(
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
|
||||
return 4;
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
|
||||
@@ -133,6 +180,125 @@ static inline Sint32 Texture_GetBlockSize(
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_D16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT:
|
||||
return 1;
|
||||
default:
|
||||
SDL_assert_release(!"Unrecognized TextureFormat!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Sint32 Texture_GetBlockHeight(
|
||||
SDL_GPUTextureFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
|
||||
return 12;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
|
||||
return 10;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
|
||||
return 8;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
|
||||
return 6;
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
|
||||
return 5;
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
|
||||
return 4;
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_A8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT:
|
||||
case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_D16_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
|
||||
case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT:
|
||||
return 1;
|
||||
default:
|
||||
SDL_assert_release(!"Unrecognized TextureFormat!");
|
||||
@@ -201,28 +367,11 @@ static inline Uint32 BytesPerRow(
|
||||
Sint32 width,
|
||||
SDL_GPUTextureFormat format)
|
||||
{
|
||||
Uint32 blocksPerRow = width;
|
||||
Uint32 pixelRowsPerBlock = Texture_GetBlockSize(format);
|
||||
|
||||
blocksPerRow = (width + pixelRowsPerBlock - 1) / pixelRowsPerBlock;
|
||||
Uint32 blockWidth = Texture_GetBlockWidth(format);
|
||||
Uint32 blocksPerRow = (width + blockWidth - 1) / blockWidth;
|
||||
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
|
||||
}
|
||||
|
||||
static inline Sint32 BytesPerImage(
|
||||
Uint32 width,
|
||||
Uint32 height,
|
||||
SDL_GPUTextureFormat format)
|
||||
{
|
||||
Uint32 blocksPerRow = width;
|
||||
Uint32 blocksPerColumn = height;
|
||||
Uint32 pixelRowsPerBlock = Texture_GetBlockSize(format);
|
||||
Uint32 pixelColumnsPerBlock = pixelRowsPerBlock;
|
||||
|
||||
blocksPerRow = (width + pixelRowsPerBlock - 1) / pixelRowsPerBlock;
|
||||
blocksPerColumn = (height + pixelColumnsPerBlock - 1) / pixelColumnsPerBlock;
|
||||
return blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format);
|
||||
}
|
||||
|
||||
// GraphicsDevice Limits
|
||||
|
||||
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
|
||||
|
||||
@@ -237,6 +237,48 @@ static DXGI_FORMAT SDLToD3D11_TextureFormat[] = {
|
||||
DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
|
||||
DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(SDLToD3D11_TextureFormat, SDL_arraysize(SDLToD3D11_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||
|
||||
@@ -2656,10 +2698,11 @@ static void D3D11_UploadToTexture(
|
||||
destination->mip_level,
|
||||
cycle);
|
||||
|
||||
Sint32 blockSize = Texture_GetBlockSize(dstFormat);
|
||||
if (blockSize > 1) {
|
||||
w = (w + blockSize - 1) & ~(blockSize - 1);
|
||||
h = (h + blockSize - 1) & ~(blockSize - 1);
|
||||
Sint32 blockWidth = Texture_GetBlockWidth(dstFormat);
|
||||
Sint32 blockHeight = Texture_GetBlockHeight(dstFormat);
|
||||
if (blockWidth > 1 && blockHeight > 1) {
|
||||
w = (w + blockWidth - 1) & ~(blockWidth - 1);
|
||||
h = (h + blockHeight - 1) & ~(blockHeight - 1);
|
||||
}
|
||||
|
||||
if (bufferStride == 0) {
|
||||
@@ -5227,9 +5270,8 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
||||
return false;
|
||||
}
|
||||
|
||||
int w, h;
|
||||
SDL_SyncWindow(windowData->window);
|
||||
SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
|
||||
res = IDXGISwapChain_GetDesc(swapchain, &swapchainDesc);
|
||||
CHECK_D3D11_ERROR_AND_RETURN("Failed to get swapchain descriptor!", false);
|
||||
|
||||
// Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
|
||||
SDL_zerop(&windowData->textureContainer);
|
||||
@@ -5246,14 +5288,14 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
||||
windowData->textureContainer.header.info.num_levels = 1;
|
||||
windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||
windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
windowData->textureContainer.header.info.width = w;
|
||||
windowData->textureContainer.header.info.height = h;
|
||||
windowData->textureContainer.header.info.width = swapchainDesc.BufferDesc.Width;
|
||||
windowData->textureContainer.header.info.height = swapchainDesc.BufferDesc.Height;
|
||||
|
||||
windowData->texture.container = &windowData->textureContainer;
|
||||
windowData->texture.containerIndex = 0;
|
||||
|
||||
windowData->width = w;
|
||||
windowData->height = h;
|
||||
windowData->width = swapchainDesc.BufferDesc.Width;
|
||||
windowData->height = swapchainDesc.BufferDesc.Height;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5268,16 +5310,12 @@ static bool D3D11_INTERNAL_ResizeSwapchain(
|
||||
SDL_free(windowData->texture.subresources[0].colorTargetViews);
|
||||
SDL_free(windowData->texture.subresources);
|
||||
|
||||
int w, h;
|
||||
SDL_SyncWindow(windowData->window);
|
||||
SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
|
||||
|
||||
// Resize the swapchain
|
||||
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
||||
windowData->swapchain,
|
||||
0, // Keep buffer count the same
|
||||
w,
|
||||
h,
|
||||
0, // Use client window width
|
||||
0, // Use client window height
|
||||
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
||||
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||
CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
|
||||
@@ -5290,10 +5328,14 @@ static bool D3D11_INTERNAL_ResizeSwapchain(
|
||||
(windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
|
||||
&windowData->texture);
|
||||
|
||||
windowData->textureContainer.header.info.width = w;
|
||||
windowData->textureContainer.header.info.height = h;
|
||||
windowData->width = w;
|
||||
windowData->height = h;
|
||||
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
||||
res = IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
|
||||
CHECK_D3D11_ERROR_AND_RETURN("Failed to get swapchain descriptor!", false);
|
||||
|
||||
windowData->textureContainer.header.info.width = swapchainDesc.BufferDesc.Width;
|
||||
windowData->textureContainer.header.info.height = swapchainDesc.BufferDesc.Height;
|
||||
windowData->width = swapchainDesc.BufferDesc.Width;
|
||||
windowData->height = swapchainDesc.BufferDesc.Height;
|
||||
windowData->needsSwapchainRecreate = !result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -312,6 +312,48 @@ static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
|
||||
DXGI_FORMAT_D32_FLOAT, // D32_FLOAT
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
|
||||
DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_UNORM_SRGB
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_4x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x4_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_5x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_6x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_8x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x5_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x6_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x8_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_10x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x10_FLOAT
|
||||
DXGI_FORMAT_UNKNOWN, // ASTC_12x12_FLOAT
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||
|
||||
@@ -6105,6 +6147,8 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
||||
windowData->swapchainComposition = swapchain_composition;
|
||||
windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||
windowData->frameCounter = 0;
|
||||
windowData->width = width;
|
||||
windowData->height = height;
|
||||
|
||||
// Precache blit pipelines for the swapchain format
|
||||
for (Uint32 i = 0; i < 5; i += 1) {
|
||||
@@ -6303,19 +6347,12 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
|
||||
SDL_free(windowData->textureContainers[i].textures);
|
||||
}
|
||||
|
||||
int w, h;
|
||||
SDL_SyncWindow(windowData->window);
|
||||
SDL_GetWindowSizeInPixels(
|
||||
windowData->window,
|
||||
&w,
|
||||
&h);
|
||||
|
||||
// Resize the swapchain
|
||||
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
||||
windowData->swapchain,
|
||||
0, // Keep buffer count the same
|
||||
w,
|
||||
h,
|
||||
0, // use client window width
|
||||
0, // use client window height
|
||||
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
||||
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
|
||||
@@ -6332,8 +6369,12 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
|
||||
}
|
||||
}
|
||||
|
||||
windowData->width = w;
|
||||
windowData->height = h;
|
||||
DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
|
||||
IDXGISwapChain3_GetDesc1(windowData->swapchain, &swapchainDesc);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Failed to retrieve swapchain descriptor!", false)
|
||||
|
||||
windowData->width = swapchainDesc.Width;
|
||||
windowData->height = swapchainDesc.Height;
|
||||
windowData->needsSwapchainRecreate = false;
|
||||
return true;
|
||||
}
|
||||
@@ -6385,12 +6426,9 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
||||
|
||||
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
||||
|
||||
int w, h;
|
||||
SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
|
||||
|
||||
// Initialize the swapchain buffer descriptor
|
||||
swapchainDesc.Width = 0;
|
||||
swapchainDesc.Height = 0;
|
||||
swapchainDesc.Width = 0; // use client window width
|
||||
swapchainDesc.Height = 0; // use client window height
|
||||
swapchainDesc.Format = swapchainFormat;
|
||||
swapchainDesc.SampleDesc.Count = 1;
|
||||
swapchainDesc.SampleDesc.Quality = 0;
|
||||
@@ -6477,14 +6515,17 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
||||
IDXGIFactory1_Release(pParent);
|
||||
}
|
||||
|
||||
IDXGISwapChain3_GetDesc1(swapchain3, &swapchainDesc);
|
||||
CHECK_D3D12_ERROR_AND_RETURN("Failed to retrieve swapchain descriptor!", false)
|
||||
|
||||
// Initialize the swapchain data
|
||||
windowData->swapchain = swapchain3;
|
||||
windowData->present_mode = presentMode;
|
||||
windowData->swapchainComposition = swapchainComposition;
|
||||
windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
|
||||
windowData->frameCounter = 0;
|
||||
windowData->width = w;
|
||||
windowData->height = h;
|
||||
windowData->width = swapchainDesc.Width;
|
||||
windowData->height = swapchainDesc.Height;
|
||||
|
||||
// Precache blit pipelines for the swapchain format
|
||||
for (Uint32 i = 0; i < 5; i += 1) {
|
||||
|
||||
@@ -166,6 +166,48 @@ static MTLPixelFormat SDLToMetal_SurfaceFormat[] = {
|
||||
MTLPixelFormatInvalid, // D24_UNORM_S8_UINT
|
||||
#endif
|
||||
MTLPixelFormatDepth32Float_Stencil8, // D32_FLOAT_S8_UINT
|
||||
MTLPixelFormatASTC_4x4_LDR, // ASTC_4x4_UNORM
|
||||
MTLPixelFormatASTC_5x4_LDR, // ASTC_5x4_UNORM
|
||||
MTLPixelFormatASTC_5x5_LDR, // ASTC_5x5_UNORM
|
||||
MTLPixelFormatASTC_6x5_LDR, // ASTC_6x5_UNORM
|
||||
MTLPixelFormatASTC_6x6_LDR, // ASTC_6x6_UNORM
|
||||
MTLPixelFormatASTC_8x5_LDR, // ASTC_8x5_UNORM
|
||||
MTLPixelFormatASTC_8x6_LDR, // ASTC_8x6_UNORM
|
||||
MTLPixelFormatASTC_8x8_LDR, // ASTC_8x8_UNORM
|
||||
MTLPixelFormatASTC_10x5_LDR, // ASTC_10x5_UNORM
|
||||
MTLPixelFormatASTC_10x6_LDR, // ASTC_10x6_UNORM
|
||||
MTLPixelFormatASTC_10x8_LDR, // ASTC_10x8_UNORM
|
||||
MTLPixelFormatASTC_10x10_LDR, // ASTC_10x10_UNORM
|
||||
MTLPixelFormatASTC_12x10_LDR, // ASTC_12x10_UNORM
|
||||
MTLPixelFormatASTC_12x12_LDR, // ASTC_12x12_UNORM
|
||||
MTLPixelFormatASTC_4x4_sRGB, // ASTC_4x4_UNORM_SRGB
|
||||
MTLPixelFormatASTC_5x4_sRGB, // ASTC_5x4_UNORM_SRGB
|
||||
MTLPixelFormatASTC_5x5_sRGB, // ASTC_5x5_UNORM_SRGB
|
||||
MTLPixelFormatASTC_6x5_sRGB, // ASTC_6x5_UNORM_SRGB
|
||||
MTLPixelFormatASTC_6x6_sRGB, // ASTC_6x6_UNORM_SRGB
|
||||
MTLPixelFormatASTC_8x5_sRGB, // ASTC_8x5_UNORM_SRGB
|
||||
MTLPixelFormatASTC_8x6_sRGB, // ASTC_8x6_UNORM_SRGB
|
||||
MTLPixelFormatASTC_8x8_sRGB, // ASTC_8x8_UNORM_SRGB
|
||||
MTLPixelFormatASTC_10x5_sRGB, // ASTC_10x5_UNORM_SRGB
|
||||
MTLPixelFormatASTC_10x6_sRGB, // ASTC_10x6_UNORM_SRGB
|
||||
MTLPixelFormatASTC_10x8_sRGB, // ASTC_10x8_UNORM_SRGB
|
||||
MTLPixelFormatASTC_10x10_sRGB, // ASTC_10x10_UNORM_SRGB
|
||||
MTLPixelFormatASTC_12x10_sRGB, // ASTC_12x10_UNORM_SRGB
|
||||
MTLPixelFormatASTC_12x12_sRGB, // ASTC_12x12_UNORM_SRGB
|
||||
MTLPixelFormatASTC_4x4_HDR, // ASTC_4x4_FLOAT
|
||||
MTLPixelFormatASTC_5x4_HDR, // ASTC_5x4_FLOAT
|
||||
MTLPixelFormatASTC_5x5_HDR, // ASTC_5x5_FLOAT
|
||||
MTLPixelFormatASTC_6x5_HDR, // ASTC_6x5_FLOAT
|
||||
MTLPixelFormatASTC_6x6_HDR, // ASTC_6x6_FLOAT
|
||||
MTLPixelFormatASTC_8x5_HDR, // ASTC_8x5_FLOAT
|
||||
MTLPixelFormatASTC_8x6_HDR, // ASTC_8x6_FLOAT
|
||||
MTLPixelFormatASTC_8x8_HDR, // ASTC_8x8_FLOAT
|
||||
MTLPixelFormatASTC_10x5_HDR, // ASTC_10x5_FLOAT
|
||||
MTLPixelFormatASTC_10x6_HDR, // ASTC_10x6_FLOAT
|
||||
MTLPixelFormatASTC_10x8_HDR, // ASTC_10x8_FLOAT
|
||||
MTLPixelFormatASTC_10x10_HDR, // ASTC_10x10_FLOAT
|
||||
MTLPixelFormatASTC_12x10_HDR, // ASTC_12x10_FLOAT
|
||||
MTLPixelFormatASTC_12x12_HDR // ASTC_12x12_FLOAT
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(SDLToMetal_SurfaceFormat, SDL_arraysize(SDLToMetal_SurfaceFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||
|
||||
@@ -1289,9 +1331,9 @@ static SDL_GPUSampler *METAL_CreateSampler(
|
||||
id<MTLSamplerState> sampler;
|
||||
MetalSampler *metalSampler;
|
||||
|
||||
samplerDesc.rAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_u];
|
||||
samplerDesc.sAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_v];
|
||||
samplerDesc.tAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_w];
|
||||
samplerDesc.sAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_u];
|
||||
samplerDesc.tAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_v];
|
||||
samplerDesc.rAddressMode = SDLToMetal_SamplerAddressMode[createinfo->address_mode_w];
|
||||
samplerDesc.minFilter = SDLToMetal_MinMagFilter[createinfo->min_filter];
|
||||
samplerDesc.magFilter = SDLToMetal_MinMagFilter[createinfo->mag_filter];
|
||||
samplerDesc.mipFilter = SDLToMetal_MipFilter[createinfo->mipmap_mode]; // FIXME: Is this right with non-mipmapped samplers?
|
||||
@@ -1710,7 +1752,7 @@ static void METAL_UploadToTexture(
|
||||
copyFromBuffer:bufferContainer->activeBuffer->handle
|
||||
sourceOffset:source->offset
|
||||
sourceBytesPerRow:BytesPerRow(destination->w, textureContainer->header.info.format)
|
||||
sourceBytesPerImage:BytesPerImage(destination->w, destination->h, textureContainer->header.info.format)
|
||||
sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, destination->d)
|
||||
sourceSize:MTLSizeMake(destination->w, destination->h, destination->d)
|
||||
toTexture:metalTexture->handle
|
||||
destinationSlice:destination->layer
|
||||
@@ -3877,7 +3919,58 @@ static bool METAL_SupportsTextureFormat(
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB:
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT:
|
||||
case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT:
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
return [renderer->device supportsFamily:MTLGPUFamilyApple7];
|
||||
#else
|
||||
return [renderer->device supportsFamily:MTLGPUFamilyApple6];
|
||||
#endif
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ typedef struct VulkanExtensions
|
||||
Uint8 EXT_vertex_attribute_divisor;
|
||||
// Only required for special implementations (i.e. MoltenVK)
|
||||
Uint8 KHR_portability_subset;
|
||||
// Only required for decoding HDR ASTC textures
|
||||
Uint8 EXT_texture_compression_astc_hdr;
|
||||
} VulkanExtensions;
|
||||
|
||||
// Defines
|
||||
@@ -135,69 +137,111 @@ static VkPresentModeKHR SDLToVK_PresentMode[] = {
|
||||
};
|
||||
|
||||
static VkFormat SDLToVK_TextureFormat[] = {
|
||||
VK_FORMAT_UNDEFINED, // INVALID
|
||||
VK_FORMAT_R8_UNORM, // A8_UNORM
|
||||
VK_FORMAT_R8_UNORM, // R8_UNORM
|
||||
VK_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
VK_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
VK_FORMAT_R16_UNORM, // R16_UNORM
|
||||
VK_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
VK_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
|
||||
VK_FORMAT_R5G6B5_UNORM_PACK16, // B5G6R5_UNORM
|
||||
VK_FORMAT_A1R5G5B5_UNORM_PACK16, // B5G5R5A1_UNORM
|
||||
VK_FORMAT_B4G4R4A4_UNORM_PACK16, // B4G4R4A4_UNORM
|
||||
VK_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1_UNORM
|
||||
VK_FORMAT_BC2_UNORM_BLOCK, // BC2_UNORM
|
||||
VK_FORMAT_BC3_UNORM_BLOCK, // BC3_UNORM
|
||||
VK_FORMAT_BC4_UNORM_BLOCK, // BC4_UNORM
|
||||
VK_FORMAT_BC5_UNORM_BLOCK, // BC5_UNORM
|
||||
VK_FORMAT_BC7_UNORM_BLOCK, // BC7_UNORM
|
||||
VK_FORMAT_BC6H_SFLOAT_BLOCK, // BC6H_FLOAT
|
||||
VK_FORMAT_BC6H_UFLOAT_BLOCK, // BC6H_UFLOAT
|
||||
VK_FORMAT_R8_SNORM, // R8_SNORM
|
||||
VK_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
VK_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
VK_FORMAT_R16_SNORM, // R16_SNORM
|
||||
VK_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
VK_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
VK_FORMAT_R16_SFLOAT, // R16_FLOAT
|
||||
VK_FORMAT_R16G16_SFLOAT, // R16G16_FLOAT
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT, // R16G16B16A16_FLOAT
|
||||
VK_FORMAT_R32_SFLOAT, // R32_FLOAT
|
||||
VK_FORMAT_R32G32_SFLOAT, // R32G32_FLOAT
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT, // R32G32B32A32_FLOAT
|
||||
VK_FORMAT_B10G11R11_UFLOAT_PACK32, // R11G11B10_UFLOAT
|
||||
VK_FORMAT_R8_UINT, // R8_UINT
|
||||
VK_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
VK_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
VK_FORMAT_R16_UINT, // R16_UINT
|
||||
VK_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
VK_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
VK_FORMAT_R32_UINT, // R32_UINT
|
||||
VK_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
VK_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
VK_FORMAT_R8_SINT, // R8_INT
|
||||
VK_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
VK_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
VK_FORMAT_R16_SINT, // R16_INT
|
||||
VK_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
VK_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
VK_FORMAT_R32_SINT, // R32_INT
|
||||
VK_FORMAT_R32G32_SINT, // R32G32_INT
|
||||
VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
|
||||
VK_FORMAT_R8G8B8A8_SRGB, // R8G8B8A8_UNORM_SRGB
|
||||
VK_FORMAT_B8G8R8A8_SRGB, // B8G8R8A8_UNORM_SRGB
|
||||
VK_FORMAT_BC1_RGBA_SRGB_BLOCK, // BC1_UNORM_SRGB
|
||||
VK_FORMAT_BC2_SRGB_BLOCK, // BC3_UNORM_SRGB
|
||||
VK_FORMAT_BC3_SRGB_BLOCK, // BC3_UNORM_SRGB
|
||||
VK_FORMAT_BC7_SRGB_BLOCK, // BC7_UNORM_SRGB
|
||||
VK_FORMAT_D16_UNORM, // D16_UNORM
|
||||
VK_FORMAT_X8_D24_UNORM_PACK32, // D24_UNORM
|
||||
VK_FORMAT_D32_SFLOAT, // D32_FLOAT
|
||||
VK_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT, // D32_FLOAT_S8_UINT
|
||||
VK_FORMAT_UNDEFINED, // INVALID
|
||||
VK_FORMAT_R8_UNORM, // A8_UNORM
|
||||
VK_FORMAT_R8_UNORM, // R8_UNORM
|
||||
VK_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
VK_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
VK_FORMAT_R16_UNORM, // R16_UNORM
|
||||
VK_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
VK_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
|
||||
VK_FORMAT_R5G6B5_UNORM_PACK16, // B5G6R5_UNORM
|
||||
VK_FORMAT_A1R5G5B5_UNORM_PACK16, // B5G5R5A1_UNORM
|
||||
VK_FORMAT_B4G4R4A4_UNORM_PACK16, // B4G4R4A4_UNORM
|
||||
VK_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1_UNORM
|
||||
VK_FORMAT_BC2_UNORM_BLOCK, // BC2_UNORM
|
||||
VK_FORMAT_BC3_UNORM_BLOCK, // BC3_UNORM
|
||||
VK_FORMAT_BC4_UNORM_BLOCK, // BC4_UNORM
|
||||
VK_FORMAT_BC5_UNORM_BLOCK, // BC5_UNORM
|
||||
VK_FORMAT_BC7_UNORM_BLOCK, // BC7_UNORM
|
||||
VK_FORMAT_BC6H_SFLOAT_BLOCK, // BC6H_FLOAT
|
||||
VK_FORMAT_BC6H_UFLOAT_BLOCK, // BC6H_UFLOAT
|
||||
VK_FORMAT_R8_SNORM, // R8_SNORM
|
||||
VK_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
VK_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
VK_FORMAT_R16_SNORM, // R16_SNORM
|
||||
VK_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
VK_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
VK_FORMAT_R16_SFLOAT, // R16_FLOAT
|
||||
VK_FORMAT_R16G16_SFLOAT, // R16G16_FLOAT
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT, // R16G16B16A16_FLOAT
|
||||
VK_FORMAT_R32_SFLOAT, // R32_FLOAT
|
||||
VK_FORMAT_R32G32_SFLOAT, // R32G32_FLOAT
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT, // R32G32B32A32_FLOAT
|
||||
VK_FORMAT_B10G11R11_UFLOAT_PACK32, // R11G11B10_UFLOAT
|
||||
VK_FORMAT_R8_UINT, // R8_UINT
|
||||
VK_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
VK_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
VK_FORMAT_R16_UINT, // R16_UINT
|
||||
VK_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
VK_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
VK_FORMAT_R32_UINT, // R32_UINT
|
||||
VK_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
VK_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
VK_FORMAT_R8_SINT, // R8_INT
|
||||
VK_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
VK_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
VK_FORMAT_R16_SINT, // R16_INT
|
||||
VK_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
VK_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
VK_FORMAT_R32_SINT, // R32_INT
|
||||
VK_FORMAT_R32G32_SINT, // R32G32_INT
|
||||
VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
|
||||
VK_FORMAT_R8G8B8A8_SRGB, // R8G8B8A8_UNORM_SRGB
|
||||
VK_FORMAT_B8G8R8A8_SRGB, // B8G8R8A8_UNORM_SRGB
|
||||
VK_FORMAT_BC1_RGBA_SRGB_BLOCK, // BC1_UNORM_SRGB
|
||||
VK_FORMAT_BC2_SRGB_BLOCK, // BC3_UNORM_SRGB
|
||||
VK_FORMAT_BC3_SRGB_BLOCK, // BC3_UNORM_SRGB
|
||||
VK_FORMAT_BC7_SRGB_BLOCK, // BC7_UNORM_SRGB
|
||||
VK_FORMAT_D16_UNORM, // D16_UNORM
|
||||
VK_FORMAT_X8_D24_UNORM_PACK32, // D24_UNORM
|
||||
VK_FORMAT_D32_SFLOAT, // D32_FLOAT
|
||||
VK_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT, // D32_FLOAT_S8_UINT
|
||||
VK_FORMAT_ASTC_4x4_UNORM_BLOCK, // ASTC_4x4_UNORM
|
||||
VK_FORMAT_ASTC_5x4_UNORM_BLOCK, // ASTC_5x4_UNORM
|
||||
VK_FORMAT_ASTC_5x5_UNORM_BLOCK, // ASTC_5x5_UNORM
|
||||
VK_FORMAT_ASTC_6x5_UNORM_BLOCK, // ASTC_6x5_UNORM
|
||||
VK_FORMAT_ASTC_6x6_UNORM_BLOCK, // ASTC_6x6_UNORM
|
||||
VK_FORMAT_ASTC_8x5_UNORM_BLOCK, // ASTC_8x5_UNORM
|
||||
VK_FORMAT_ASTC_8x6_UNORM_BLOCK, // ASTC_8x6_UNORM
|
||||
VK_FORMAT_ASTC_8x8_UNORM_BLOCK, // ASTC_8x8_UNORM
|
||||
VK_FORMAT_ASTC_10x5_UNORM_BLOCK, // ASTC_10x5_UNORM
|
||||
VK_FORMAT_ASTC_10x6_UNORM_BLOCK, // ASTC_10x6_UNORM
|
||||
VK_FORMAT_ASTC_10x8_UNORM_BLOCK, // ASTC_10x8_UNORM
|
||||
VK_FORMAT_ASTC_10x10_UNORM_BLOCK, // ASTC_10x10_UNORM
|
||||
VK_FORMAT_ASTC_12x10_UNORM_BLOCK, // ASTC_12x10_UNORM
|
||||
VK_FORMAT_ASTC_12x12_UNORM_BLOCK, // ASTC_12x12_UNORM
|
||||
VK_FORMAT_ASTC_4x4_SRGB_BLOCK, // ASTC_4x4_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_5x4_SRGB_BLOCK, // ASTC_5x4_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_5x5_SRGB_BLOCK, // ASTC_5x5_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_6x5_SRGB_BLOCK, // ASTC_6x5_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_6x6_SRGB_BLOCK, // ASTC_6x6_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_8x5_SRGB_BLOCK, // ASTC_8x5_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_8x6_SRGB_BLOCK, // ASTC_8x6_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_8x8_SRGB_BLOCK, // ASTC_8x8_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_10x5_SRGB_BLOCK, // ASTC_10x5_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_10x6_SRGB_BLOCK, // ASTC_10x6_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_10x8_SRGB_BLOCK, // ASTC_10x8_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_10x10_SRGB_BLOCK, // ASTC_10x10_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_12x10_SRGB_BLOCK, // ASTC_12x10_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_12x12_SRGB_BLOCK, // ASTC_12x12_UNORM_SRGB
|
||||
VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, // ASTC_4x4_FLOAT
|
||||
VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, // ASTC_5x4_FLOAT
|
||||
VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, // ASTC_5x5_FLOAT
|
||||
VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, // ASTC_6x5_FLOAT
|
||||
VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, // ASTC_6x6_FLOAT
|
||||
VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, // ASTC_8x5_FLOAT
|
||||
VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, // ASTC_8x6_FLOAT
|
||||
VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, // ASTC_8x8_FLOAT
|
||||
VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, // ASTC_10x5_FLOAT
|
||||
VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, // ASTC_10x6_FLOAT
|
||||
VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, // ASTC_10x8_FLOAT
|
||||
VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, // ASTC_10x10_FLOAT
|
||||
VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, // ASTC_12x10_FLOAT
|
||||
VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK // ASTC_12x12_FLOAT
|
||||
};
|
||||
SDL_COMPILE_TIME_ASSERT(SDLToVK_TextureFormat, SDL_arraysize(SDLToVK_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE);
|
||||
|
||||
@@ -670,6 +714,8 @@ typedef struct WindowData
|
||||
SDL_GPUSwapchainComposition swapchainComposition;
|
||||
SDL_GPUPresentMode presentMode;
|
||||
bool needsSwapchainRecreate;
|
||||
Uint32 swapchainCreateWidth;
|
||||
Uint32 swapchainCreateHeight;
|
||||
|
||||
// Window surface
|
||||
VkSurfaceKHR surface;
|
||||
@@ -2941,6 +2987,9 @@ static void VULKAN_INTERNAL_DestroyTexture(
|
||||
}
|
||||
|
||||
if (texture->subresources[subresourceIndex].depthStencilView != VK_NULL_HANDLE) {
|
||||
VULKAN_INTERNAL_RemoveFramebuffersContainingView(
|
||||
renderer,
|
||||
texture->subresources[subresourceIndex].depthStencilView);
|
||||
renderer->vkDestroyImageView(
|
||||
renderer->logicalDevice,
|
||||
texture->subresources[subresourceIndex].depthStencilView,
|
||||
@@ -4381,14 +4430,13 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo;
|
||||
SwapchainSupportDetails swapchainSupportDetails;
|
||||
bool hasValidSwapchainComposition, hasValidPresentMode;
|
||||
Sint32 drawableWidth, drawableHeight;
|
||||
Uint32 i;
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
SDL_assert(_this && _this->Vulkan_CreateSurface);
|
||||
|
||||
windowData->frameCounter = 0;
|
||||
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
SDL_assert(_this && _this->Vulkan_CreateSurface);
|
||||
|
||||
// Each swapchain must have its own surface.
|
||||
if (!_this->Vulkan_CreateSurface(
|
||||
_this,
|
||||
@@ -4491,16 +4539,20 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
||||
return VULKAN_INTERNAL_TRY_AGAIN;
|
||||
}
|
||||
|
||||
// Sync now to be sure that our swapchain size is correct
|
||||
SDL_SyncWindow(windowData->window);
|
||||
SDL_GetWindowSizeInPixels(
|
||||
windowData->window,
|
||||
&drawableWidth,
|
||||
&drawableHeight);
|
||||
|
||||
windowData->imageCount = MAX_FRAMES_IN_FLIGHT;
|
||||
windowData->width = drawableWidth;
|
||||
windowData->height = drawableHeight;
|
||||
|
||||
#ifdef SDL_PLATFORM_APPLE
|
||||
windowData->width = swapchainSupportDetails.capabilities.currentExtent.width;
|
||||
windowData->height = swapchainSupportDetails.capabilities.currentExtent.height;
|
||||
#else
|
||||
windowData->width = SDL_clamp(
|
||||
windowData->swapchainCreateWidth,
|
||||
swapchainSupportDetails.capabilities.minImageExtent.width,
|
||||
swapchainSupportDetails.capabilities.maxImageExtent.width);
|
||||
windowData->height = SDL_clamp(windowData->swapchainCreateHeight,
|
||||
swapchainSupportDetails.capabilities.minImageExtent.height,
|
||||
swapchainSupportDetails.capabilities.maxImageExtent.height);
|
||||
#endif
|
||||
|
||||
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
|
||||
windowData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
|
||||
@@ -4528,8 +4580,8 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
||||
swapchainCreateInfo.minImageCount = windowData->imageCount;
|
||||
swapchainCreateInfo.imageFormat = windowData->format;
|
||||
swapchainCreateInfo.imageColorSpace = windowData->colorSpace;
|
||||
swapchainCreateInfo.imageExtent.width = drawableWidth;
|
||||
swapchainCreateInfo.imageExtent.height = drawableHeight;
|
||||
swapchainCreateInfo.imageExtent.width = windowData->width;
|
||||
swapchainCreateInfo.imageExtent.height = windowData->height;
|
||||
swapchainCreateInfo.imageArrayLayers = 1;
|
||||
swapchainCreateInfo.imageUsage =
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||
@@ -4603,8 +4655,8 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
||||
// Initialize dummy container
|
||||
SDL_zero(windowData->textureContainers[i]);
|
||||
windowData->textureContainers[i].canBeCycled = false;
|
||||
windowData->textureContainers[i].header.info.width = drawableWidth;
|
||||
windowData->textureContainers[i].header.info.height = drawableHeight;
|
||||
windowData->textureContainers[i].header.info.width = windowData->width;
|
||||
windowData->textureContainers[i].header.info.height = windowData->height;
|
||||
windowData->textureContainers[i].header.info.layer_count_or_depth = 1;
|
||||
windowData->textureContainers[i].header.info.format = SwapchainCompositionToSDLFormat(
|
||||
windowData->swapchainComposition,
|
||||
@@ -8900,6 +8952,7 @@ static void VULKAN_Blit(
|
||||
// Using BeginRenderPass to clear because vkCmdClearColorImage requires barriers anyway
|
||||
if (info->load_op == SDL_GPU_LOADOP_CLEAR) {
|
||||
SDL_GPUColorTargetInfo targetInfo;
|
||||
SDL_zero(targetInfo);
|
||||
targetInfo.texture = info->destination.texture;
|
||||
targetInfo.mip_level = info->destination.mip_level;
|
||||
targetInfo.layer_or_depth_plane = info->destination.layer_or_depth_plane;
|
||||
@@ -9367,6 +9420,8 @@ static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
|
||||
if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
|
||||
data = VULKAN_INTERNAL_FetchWindowData(w);
|
||||
data->needsSwapchainRecreate = true;
|
||||
data->swapchainCreateWidth = e->window.data1;
|
||||
data->swapchainCreateHeight = e->window.data2;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -9465,6 +9520,16 @@ static bool VULKAN_ClaimWindow(
|
||||
windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
|
||||
windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
|
||||
|
||||
// On non-Apple platforms the swapchain capability currentExtent can be different from the window,
|
||||
// so we have to query the window size.
|
||||
#ifndef SDL_PLATFORM_APPLE
|
||||
int w, h;
|
||||
SDL_SyncWindow(window);
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
windowData->swapchainCreateWidth = w;
|
||||
windowData->swapchainCreateHeight = h;
|
||||
#endif
|
||||
|
||||
Uint32 createSwapchainResult = VULKAN_INTERNAL_CreateSwapchain(renderer, windowData);
|
||||
if (createSwapchainResult == 1) {
|
||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
||||
@@ -10232,20 +10297,21 @@ static bool VULKAN_Submit(
|
||||
renderer->unifiedQueue,
|
||||
&presentInfo);
|
||||
|
||||
presentData->windowData->frameCounter =
|
||||
(presentData->windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
if (presentResult == VK_SUCCESS || presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
if (presentResult == VK_SUCCESS || presentResult == VK_SUBOPTIMAL_KHR || presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
// If presenting, the swapchain is using the in-flight fence
|
||||
presentData->windowData->inFlightFences[presentData->windowData->frameCounter] = (SDL_GPUFence*)vulkanCommandBuffer->inFlightFence;
|
||||
(void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
|
||||
|
||||
if (presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
if (presentResult == VK_SUBOPTIMAL_KHR || presentResult == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
presentData->windowData->needsSwapchainRecreate = true;
|
||||
}
|
||||
} else {
|
||||
CHECK_VULKAN_ERROR_AND_RETURN(presentResult, vkQueuePresentKHR, false)
|
||||
}
|
||||
|
||||
presentData->windowData->frameCounter =
|
||||
(presentData->windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
|
||||
}
|
||||
|
||||
// Check if we can perform any cleanups
|
||||
@@ -10568,7 +10634,7 @@ static inline Uint8 CheckDeviceExtensions(
|
||||
supports->ext = 1; \
|
||||
}
|
||||
CHECK(KHR_swapchain)
|
||||
else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(EXT_vertex_attribute_divisor) else CHECK(KHR_portability_subset)
|
||||
else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(EXT_vertex_attribute_divisor) else CHECK(KHR_portability_subset) else CHECK(EXT_texture_compression_astc_hdr)
|
||||
#undef CHECK
|
||||
}
|
||||
|
||||
@@ -10583,7 +10649,8 @@ static inline Uint32 GetDeviceExtensionCount(VulkanExtensions *supports)
|
||||
supports->KHR_maintenance1 +
|
||||
supports->KHR_driver_properties +
|
||||
supports->EXT_vertex_attribute_divisor +
|
||||
supports->KHR_portability_subset);
|
||||
supports->KHR_portability_subset +
|
||||
supports->EXT_texture_compression_astc_hdr);
|
||||
}
|
||||
|
||||
static inline void CreateDeviceExtensionArray(
|
||||
@@ -10600,6 +10667,7 @@ static inline void CreateDeviceExtensionArray(
|
||||
CHECK(KHR_driver_properties)
|
||||
CHECK(EXT_vertex_attribute_divisor)
|
||||
CHECK(KHR_portability_subset)
|
||||
CHECK(EXT_texture_compression_astc_hdr)
|
||||
#undef CHECK
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
#include "../core/linux/SDL_udev.h"
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
#include <poll.h>
|
||||
#include "../core/linux/SDL_sandbox.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
@@ -1144,7 +1143,7 @@ int SDL_hid_init(void)
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"udev disabled by SDL_HINT_HIDAPI_UDEV");
|
||||
linux_enumeration_method = ENUMERATION_FALLBACK;
|
||||
} else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
|
||||
} else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"Container detected, disabling HIDAPI udev integration");
|
||||
linux_enumeration_method = ENUMERATION_FALLBACK;
|
||||
|
||||
@@ -98,9 +98,6 @@ struct hid_device_
|
||||
int m_nDeviceRefCount;
|
||||
};
|
||||
|
||||
static JavaVM *g_JVM;
|
||||
static pthread_key_t g_ThreadKey;
|
||||
|
||||
template<class T>
|
||||
class hid_device_ref
|
||||
{
|
||||
@@ -495,10 +492,7 @@ public:
|
||||
|
||||
bool BOpen()
|
||||
{
|
||||
// Make sure thread is attached to JVM/env
|
||||
JNIEnv *env;
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
if ( !g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
@@ -506,46 +500,38 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bIsWaitingForOpen = false;
|
||||
m_bOpenResult = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerOpen, m_nId );
|
||||
ExceptionCheck( env, "BOpen" );
|
||||
|
||||
if ( m_bIsWaitingForOpen )
|
||||
{
|
||||
hid_mutex_guard cvl( &m_cvLock );
|
||||
|
||||
const int OPEN_TIMEOUT_SECONDS = 60;
|
||||
struct timespec ts, endtime;
|
||||
clock_gettime( CLOCK_REALTIME, &ts );
|
||||
endtime = ts;
|
||||
endtime.tv_sec += OPEN_TIMEOUT_SECONDS;
|
||||
do
|
||||
{
|
||||
if ( pthread_cond_timedwait( &m_cv, &m_cvLock, &endtime ) != 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ( m_bIsWaitingForOpen && get_timespec_ms( ts ) < get_timespec_ms( endtime ) );
|
||||
SDL_SetError( "Waiting for permission" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !m_bOpenResult )
|
||||
{
|
||||
m_bOpenResult = env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerOpen, m_nId );
|
||||
ExceptionCheck( env, "BOpen" );
|
||||
|
||||
if ( m_bIsWaitingForOpen )
|
||||
{
|
||||
LOGV( "Device open failed - timed out waiting for device permission" );
|
||||
LOGV( "Device open waiting for permission" );
|
||||
SDL_SetError( "Waiting for permission" );
|
||||
m_bWasOpenPending = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
if ( !m_bOpenResult )
|
||||
{
|
||||
LOGV( "Device open failed" );
|
||||
SDL_SetError( "Device open failed" );
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pDevice = new hid_device;
|
||||
m_pDevice->m_nId = m_nId;
|
||||
m_pDevice->m_nDeviceRefCount = 1;
|
||||
LOGD("Creating device %d (%p), refCount = 1\n", m_pDevice->m_nId, m_pDevice);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -554,16 +540,44 @@ public:
|
||||
m_bIsWaitingForOpen = true;
|
||||
}
|
||||
|
||||
bool BOpenPending() const
|
||||
{
|
||||
return m_bIsWaitingForOpen;
|
||||
}
|
||||
|
||||
void SetWasOpenPending( bool bState )
|
||||
{
|
||||
m_bWasOpenPending = bState;
|
||||
}
|
||||
|
||||
bool BWasOpenPending() const
|
||||
{
|
||||
return m_bWasOpenPending;
|
||||
}
|
||||
|
||||
void SetOpenResult( bool bResult )
|
||||
{
|
||||
if ( m_bIsWaitingForOpen )
|
||||
{
|
||||
m_bOpenResult = bResult;
|
||||
m_bIsWaitingForOpen = false;
|
||||
pthread_cond_signal( &m_cv );
|
||||
|
||||
if ( m_bOpenResult )
|
||||
{
|
||||
LOGV( "Device open succeeded" );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGV( "Device open failed" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BOpenResult() const
|
||||
{
|
||||
return m_bOpenResult;
|
||||
}
|
||||
|
||||
void ProcessInput( const uint8_t *pBuf, size_t nBufSize )
|
||||
{
|
||||
hid_mutex_guard l( &m_dataLock );
|
||||
@@ -610,23 +624,18 @@ public:
|
||||
|
||||
int WriteReport( const unsigned char *pData, size_t nDataLen, bool bFeature )
|
||||
{
|
||||
// Make sure thread is attached to JVM/env
|
||||
JNIEnv *env;
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
int nRet = -1;
|
||||
if ( g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
|
||||
nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerWriteReport, m_nId, pBuf, bFeature );
|
||||
ExceptionCheck( env, "WriteReport" );
|
||||
env->DeleteLocalRef( pBuf );
|
||||
}
|
||||
else
|
||||
if ( !g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
LOGV( "WriteReport without callback handler" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
jbyteArray pBuf = NewByteArray( env, pData, nDataLen );
|
||||
int nRet = env->CallIntMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerWriteReport, m_nId, pBuf, bFeature );
|
||||
ExceptionCheck( env, "WriteReport" );
|
||||
env->DeleteLocalRef( pBuf );
|
||||
return nRet;
|
||||
}
|
||||
|
||||
@@ -645,10 +654,7 @@ public:
|
||||
|
||||
int ReadReport( unsigned char *pData, size_t nDataLen, bool bFeature )
|
||||
{
|
||||
// Make sure thread is attached to JVM/env
|
||||
JNIEnv *env;
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
if ( !g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
@@ -721,15 +727,15 @@ public:
|
||||
|
||||
void Close( bool bDeleteDevice )
|
||||
{
|
||||
// Make sure thread is attached to JVM/env
|
||||
JNIEnv *env;
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
if ( g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
env->CallVoidMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerClose, m_nId );
|
||||
ExceptionCheck( env, "Close" );
|
||||
if ( !m_bIsWaitingForOpen && m_bOpenResult )
|
||||
{
|
||||
env->CallVoidMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerClose, m_nId );
|
||||
ExceptionCheck( env, "Close" );
|
||||
}
|
||||
}
|
||||
|
||||
hid_mutex_guard dataLock( &m_dataLock );
|
||||
@@ -764,6 +770,7 @@ private:
|
||||
pthread_mutex_t m_cvLock = PTHREAD_MUTEX_INITIALIZER; // This lock has to be held to access any variables below
|
||||
pthread_cond_t m_cv = PTHREAD_COND_INITIALIZER;
|
||||
bool m_bIsWaitingForOpen = false;
|
||||
bool m_bWasOpenPending = false;
|
||||
bool m_bOpenResult = false;
|
||||
bool m_bIsWaitingForReportResponse = false;
|
||||
int m_nReportResponseError = 0;
|
||||
@@ -793,16 +800,6 @@ static hid_device_ref<CHIDDevice> FindDevice( int nDeviceId )
|
||||
return pDevice;
|
||||
}
|
||||
|
||||
static void ThreadDestroyed(void* value)
|
||||
{
|
||||
/* The thread is being destroyed, detach it from the Java VM and set the g_ThreadKey value to NULL as required */
|
||||
JNIEnv *env = (JNIEnv*) value;
|
||||
if (env != NULL) {
|
||||
g_JVM->DetachCurrentThread();
|
||||
pthread_setspecific(g_ThreadKey, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz);
|
||||
@@ -834,16 +831,6 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallba
|
||||
{
|
||||
LOGV( "HIDDeviceRegisterCallback()");
|
||||
|
||||
env->GetJavaVM( &g_JVM );
|
||||
|
||||
/*
|
||||
* Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
|
||||
* Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
|
||||
*/
|
||||
if (pthread_key_create(&g_ThreadKey, ThreadDestroyed) != 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, TAG, "Error initializing pthread key");
|
||||
}
|
||||
|
||||
if ( g_HIDDeviceManagerCallbackHandler != NULL )
|
||||
{
|
||||
env->DeleteGlobalRef( g_HIDDeviceManagerCallbackClass );
|
||||
@@ -1029,51 +1016,43 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReportResponse
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// !!! FIXME: make this non-blocking!
|
||||
static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted)
|
||||
static void SDLCALL RequestBluetoothPermissionCallback( void *userdata, const char *permission, bool granted )
|
||||
{
|
||||
SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1);
|
||||
SDL_Log( "Bluetooth permission %s\n", granted ? "granted" : "denied" );
|
||||
|
||||
if ( granted && g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, false, true );
|
||||
}
|
||||
}
|
||||
|
||||
static bool RequestBluetoothPermissions(const char *permission)
|
||||
{
|
||||
// !!! FIXME: make this non-blocking!
|
||||
SDL_AtomicInt permission_response;
|
||||
SDL_SetAtomicInt(&permission_response, 0);
|
||||
if (!SDL_RequestAndroidPermission(permission, RequestAndroidPermissionBlockingCallback, &permission_response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (SDL_GetAtomicInt(&permission_response) == 0) {
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
return SDL_GetAtomicInt(&permission_response) > 0;
|
||||
}
|
||||
|
||||
|
||||
int hid_init(void)
|
||||
{
|
||||
if ( !g_initialized && g_HIDDeviceManagerCallbackHandler )
|
||||
{
|
||||
// HIDAPI doesn't work well with Android < 4.3
|
||||
if (SDL_GetAndroidSDKVersion() >= 18) {
|
||||
// Make sure thread is attached to JVM/env
|
||||
JNIEnv *env;
|
||||
g_JVM->AttachCurrentThread( &env, NULL );
|
||||
pthread_setspecific( g_ThreadKey, (void*)env );
|
||||
if ( SDL_GetAndroidSDKVersion() >= 18 )
|
||||
{
|
||||
JNIEnv *env = SDL_GetAndroidJNIEnv();
|
||||
|
||||
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, true, false );
|
||||
|
||||
// Bluetooth is currently only used for Steam Controllers, so check that hint
|
||||
// before initializing Bluetooth, which will prompt the user for permission.
|
||||
bool init_usb = true;
|
||||
bool init_bluetooth = false;
|
||||
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_STEAM, false)) {
|
||||
if (SDL_GetAndroidSDKVersion() < 31 ||
|
||||
RequestBluetoothPermissions("android.permission.BLUETOOTH_CONNECT")) {
|
||||
init_bluetooth = true;
|
||||
if ( SDL_GetHintBoolean( SDL_HINT_JOYSTICK_HIDAPI_STEAM, false ) )
|
||||
{
|
||||
if ( SDL_GetAndroidSDKVersion() < 31 )
|
||||
{
|
||||
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, false, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Log( "Requesting Bluetooth permission" );
|
||||
SDL_RequestAndroidPermission( "android.permission.BLUETOOTH_CONNECT", RequestBluetoothPermissionCallback, NULL );
|
||||
}
|
||||
}
|
||||
env->CallBooleanMethod( g_HIDDeviceManagerCallbackHandler, g_midHIDDeviceManagerInitialize, init_usb, init_bluetooth );
|
||||
ExceptionCheck( env, NULL, "hid_init" );
|
||||
}
|
||||
g_initialized = true; // Regardless of result, so it's only called once
|
||||
@@ -1088,6 +1067,18 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor
|
||||
hid_mutex_guard l( &g_DevicesMutex );
|
||||
for ( hid_device_ref<CHIDDevice> pDevice = g_Devices; pDevice; pDevice = pDevice->next )
|
||||
{
|
||||
// Don't enumerate devices that are currently being opened, we'll re-enumerate them when we're done
|
||||
// Make sure we skip them at least once, so they get removed and then re-added to the caller's device list
|
||||
if ( pDevice->BWasOpenPending() )
|
||||
{
|
||||
// Don't enumerate devices that failed to open, otherwise the application might try to keep prompting for access
|
||||
if ( !pDevice->BOpenPending() && pDevice->BOpenResult() )
|
||||
{
|
||||
pDevice->SetWasOpenPending( false );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const hid_device_info *info = pDevice->GetDeviceInfo();
|
||||
|
||||
/* See if there are any devices we should skip in enumeration */
|
||||
@@ -1148,7 +1139,12 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pDevice && pDevice->BOpen() )
|
||||
if ( !pDevice )
|
||||
{
|
||||
SDL_SetError( "Couldn't find device with path %s", path );
|
||||
return NULL;
|
||||
}
|
||||
if ( pDevice->BOpen() )
|
||||
{
|
||||
return pDevice->GetDevice();
|
||||
}
|
||||
@@ -1159,7 +1155,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned ch
|
||||
{
|
||||
if ( device )
|
||||
{
|
||||
LOGV( "hid_write id=%d length=%zu", device->m_nId, length );
|
||||
// LOGV( "hid_write id=%d length=%zu", device->m_nId, length );
|
||||
hid_device_ref<CHIDDevice> pDevice = FindDevice( device->m_nId );
|
||||
if ( pDevice )
|
||||
{
|
||||
@@ -1223,7 +1219,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *device, unsigned ch
|
||||
// TODO: Implement blocking
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length)
|
||||
{
|
||||
LOGV( "hid_read id=%d length=%zu", device->m_nId, length );
|
||||
// LOGV( "hid_read id=%d length=%zu", device->m_nId, length );
|
||||
return hid_read_timeout( device, data, length, 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -2595,12 +2595,8 @@ bool SDL_IsGamepad(SDL_JoystickID instance_id)
|
||||
/*
|
||||
* Return 1 if the gamepad should be ignored by SDL
|
||||
*/
|
||||
bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid)
|
||||
bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
Uint16 vendor;
|
||||
Uint16 product;
|
||||
Uint16 version;
|
||||
|
||||
#ifdef SDL_PLATFORM_LINUX
|
||||
if (SDL_endswith(name, " Motion Sensors")) {
|
||||
// Don't treat the PS3 and PS4 motion controls as a separate gamepad
|
||||
@@ -2624,37 +2620,17 @@ bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SDL_allowed_gamepads.num_included_entries == 0 &&
|
||||
SDL_ignored_gamepads.num_included_entries == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version, NULL);
|
||||
|
||||
if (SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", false)) {
|
||||
// We shouldn't ignore Steam's virtual gamepad since it's using the hints to filter out the real gamepads so it can remap input for the virtual gamepad
|
||||
// https://partner.steamgames.com/doc/features/steam_gamepad/steam_input_gamepad_emulation_bestpractices
|
||||
bool bSteamVirtualGamepad = false;
|
||||
#ifdef SDL_PLATFORM_LINUX
|
||||
bSteamVirtualGamepad = (vendor == USB_VENDOR_VALVE && product == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD);
|
||||
#elif defined(SDL_PLATFORM_MACOS)
|
||||
bSteamVirtualGamepad = (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0);
|
||||
#elif defined(SDL_PLATFORM_WIN32)
|
||||
// We can't tell on Windows, but Steam will block others in input hooks
|
||||
bSteamVirtualGamepad = true;
|
||||
#endif
|
||||
if (bSteamVirtualGamepad) {
|
||||
return false;
|
||||
}
|
||||
if (SDL_IsJoystickSteamVirtualGamepad(vendor_id, product_id, version)) {
|
||||
return !SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", false);
|
||||
}
|
||||
|
||||
if (SDL_allowed_gamepads.num_included_entries > 0) {
|
||||
if (SDL_VIDPIDInList(vendor, product, &SDL_allowed_gamepads)) {
|
||||
if (SDL_VIDPIDInList(vendor_id, product_id, &SDL_allowed_gamepads)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (SDL_VIDPIDInList(vendor, product, &SDL_ignored_gamepads)) {
|
||||
if (SDL_VIDPIDInList(vendor_id, product_id, &SDL_ignored_gamepads)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -39,7 +39,7 @@ extern void SDL_PrivateGamepadRemoved(SDL_JoystickID instance_id);
|
||||
extern bool SDL_IsGamepadNameAndGUID(const char *name, SDL_GUID guid);
|
||||
|
||||
// Function to return whether a gamepad should be ignored
|
||||
extern bool SDL_ShouldIgnoreGamepad(const char *name, SDL_GUID guid);
|
||||
extern bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
|
||||
|
||||
// Handle delayed guide button on a gamepad
|
||||
extern void SDL_GamepadHandleDelayedGuideButton(SDL_Joystick *joystick);
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
Alternatively, you can use the app located in test/controllermap
|
||||
*/
|
||||
static const char *s_GamepadMappings[] = {
|
||||
#ifdef SDL_JOYSTICK_PRIVATE
|
||||
SDL_PRIVATE_GAMEPAD_DEFINITIONS
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_XINPUT
|
||||
"xinput,*,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
#endif
|
||||
@@ -732,7 +735,7 @@ static const char *s_GamepadMappings[] = {
|
||||
"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
|
||||
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
|
||||
"05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
|
||||
"03000000de2800000512000000016800,Steam Deck,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||
"03000000de2800000512000000016800,Steam Deck Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b11,paddle1:b12,paddle2:b13,paddle3:b14,paddle4:b15,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
|
||||
"03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,",
|
||||
"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
|
||||
|
||||
@@ -52,6 +52,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
|
||||
#ifdef SDL_JOYSTICK_HIDAPI // Highest priority driver for supported devices
|
||||
&SDL_HIDAPI_JoystickDriver,
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_PRIVATE
|
||||
&SDL_PRIVATE_JoystickDriver,
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_GAMEINPUT // Higher priority than other Windows drivers
|
||||
&SDL_GAMEINPUT_JoystickDriver,
|
||||
#endif
|
||||
@@ -888,9 +891,6 @@ static bool IsROGAlly(SDL_Joystick *joystick)
|
||||
|
||||
static bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, bool *invert_sensors)
|
||||
{
|
||||
const char *hint;
|
||||
int hint_value;
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
*invert_sensors = false;
|
||||
@@ -905,30 +905,26 @@ static bool ShouldAttemptSensorFusion(SDL_Joystick *joystick, bool *invert_senso
|
||||
return false;
|
||||
}
|
||||
|
||||
hint = SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION);
|
||||
hint_value = SDL_GetStringInteger(hint, -1);
|
||||
if (hint_value > 0) {
|
||||
return true;
|
||||
}
|
||||
if (hint_value == 0) {
|
||||
return false;
|
||||
}
|
||||
const char *hint = SDL_GetHint(SDL_HINT_GAMECONTROLLER_SENSOR_FUSION);
|
||||
if (hint && *hint) {
|
||||
if (*hint == '@' || SDL_strncmp(hint, "0x", 2) == 0) {
|
||||
SDL_vidpid_list gamepads;
|
||||
SDL_GUID guid;
|
||||
Uint16 vendor, product;
|
||||
bool enabled;
|
||||
SDL_zero(gamepads);
|
||||
|
||||
if (hint) {
|
||||
SDL_vidpid_list gamepads;
|
||||
SDL_GUID guid;
|
||||
Uint16 vendor, product;
|
||||
bool enabled;
|
||||
SDL_zero(gamepads);
|
||||
|
||||
// See if the gamepad is in our list of devices to enable
|
||||
guid = SDL_GetJoystickGUID(joystick);
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
SDL_LoadVIDPIDListFromHints(&gamepads, hint, NULL);
|
||||
enabled = SDL_VIDPIDInList(vendor, product, &gamepads);
|
||||
SDL_FreeVIDPIDList(&gamepads);
|
||||
if (enabled) {
|
||||
return true;
|
||||
// See if the gamepad is in our list of devices to enable
|
||||
guid = SDL_GetJoystickGUID(joystick);
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
SDL_LoadVIDPIDListFromHints(&gamepads, hint, NULL);
|
||||
enabled = SDL_VIDPIDInList(vendor, product, &gamepads);
|
||||
SDL_FreeVIDPIDList(&gamepads);
|
||||
if (enabled) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return SDL_GetStringBoolean(hint, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3094,6 +3090,15 @@ bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_id)
|
||||
product_id == USB_PRODUCT_NVIDIA_SHIELD_CONTROLLER_V104));
|
||||
}
|
||||
|
||||
bool SDL_IsJoystickSteamVirtualGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version)
|
||||
{
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
return (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0);
|
||||
#else
|
||||
return (vendor_id == USB_VENDOR_VALVE && product_id == USB_PRODUCT_STEAM_VIRTUAL_GAMEPAD);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
EControllerType eType = GuessControllerType(vendor_id, product_id);
|
||||
@@ -3231,24 +3236,19 @@ static SDL_JoystickType SDL_GetJoystickGUIDType(SDL_GUID guid)
|
||||
return SDL_JOYSTICK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool SDL_ShouldIgnoreJoystick(const char *name, SDL_GUID guid)
|
||||
bool SDL_ShouldIgnoreJoystick(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
Uint16 vendor;
|
||||
Uint16 product;
|
||||
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
|
||||
// Check the joystick blacklist
|
||||
if (SDL_VIDPIDInList(vendor, product, &blacklist_devices)) {
|
||||
if (SDL_VIDPIDInList(vendor_id, product_id, &blacklist_devices)) {
|
||||
return true;
|
||||
}
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_ROG_CHAKRAM, false)) {
|
||||
if (SDL_VIDPIDInList(vendor, product, &rog_gamepad_mice)) {
|
||||
if (SDL_VIDPIDInList(vendor_id, product_id, &rog_gamepad_mice)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreGamepad(name, guid)) {
|
||||
if (SDL_ShouldIgnoreGamepad(vendor_id, product_id, version, name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,9 @@ extern bool SDL_IsJoystickGoogleStadiaController(Uint16 vendor_id, Uint16 produc
|
||||
// Function to return whether a joystick is an NVIDIA SHIELD controller
|
||||
extern bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_id);
|
||||
|
||||
// Function to return whether a joystick is a Steam Virtual Gamepad
|
||||
extern bool SDL_IsJoystickSteamVirtualGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version);
|
||||
|
||||
// Function to return whether a joystick is a Steam Controller
|
||||
extern bool SDL_IsJoystickSteamController(Uint16 vendor_id, Uint16 product_id);
|
||||
|
||||
@@ -154,7 +157,7 @@ extern bool SDL_IsJoystickRAWINPUT(SDL_GUID guid);
|
||||
extern bool SDL_IsJoystickVIRTUAL(SDL_GUID guid);
|
||||
|
||||
// Function to return whether a joystick should be ignored
|
||||
extern bool SDL_ShouldIgnoreJoystick(const char *name, SDL_GUID guid);
|
||||
extern bool SDL_ShouldIgnoreJoystick(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
|
||||
|
||||
// Internal event queueing functions
|
||||
extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers);
|
||||
|
||||
@@ -127,6 +127,11 @@ void SDL_InitSteamVirtualGamepadInfo(void)
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
|
||||
// The file isn't available inside the macOS sandbox
|
||||
if (SDL_GetSandbox() == SDL_SANDBOX_MACOS) {
|
||||
return;
|
||||
}
|
||||
|
||||
file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE);
|
||||
if (file && *file) {
|
||||
SDL_steam_virtual_gamepad_info_file = SDL_strdup(file);
|
||||
|
||||
@@ -240,6 +240,7 @@ typedef struct SDL_JoystickDriver
|
||||
#define SDL_LED_MIN_REPEAT_MS 5000
|
||||
|
||||
// The available joystick drivers
|
||||
extern SDL_JoystickDriver SDL_PRIVATE_JoystickDriver;
|
||||
extern SDL_JoystickDriver SDL_ANDROID_JoystickDriver;
|
||||
extern SDL_JoystickDriver SDL_BSD_JoystickDriver;
|
||||
extern SDL_JoystickDriver SDL_DARWIN_JoystickDriver;
|
||||
|
||||
@@ -392,7 +392,8 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
device->is_switch_joyconL = IsControllerSwitchJoyConL(controller);
|
||||
device->is_switch_joyconR = IsControllerSwitchJoyConR(controller);
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
if ((device->is_xbox && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE)) ||
|
||||
if ((device->is_xbox && (HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOXONE) ||
|
||||
HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_XBOX360))) ||
|
||||
(device->is_ps4 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS4)) ||
|
||||
(device->is_ps5 && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_PS5)) ||
|
||||
(device->is_switch_pro && HIDAPI_IsDeviceTypePresent(SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO)) ||
|
||||
@@ -404,6 +405,10 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (device->is_xbox && SDL_strncmp(name, "GamePad-", 8) == 0) {
|
||||
// This is a Steam Virtual Gamepad, which isn't supported by GCController
|
||||
return false;
|
||||
}
|
||||
CheckControllerSiriRemote(controller, &device->is_siri_remote);
|
||||
|
||||
if (device->is_siri_remote && !SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, true)) {
|
||||
@@ -493,6 +498,10 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(vendor, product, 0, name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PHYSICAL_INPUT_PROFILE
|
||||
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
|
||||
NSDictionary<NSString *, GCControllerElement *> *elements = controller.physicalInputProfile.elements;
|
||||
@@ -661,10 +670,6 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
}
|
||||
device->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, signature, NULL, name, 'm', subtype);
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(name, device->guid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This will be set when the first button press of the controller is
|
||||
* detected. */
|
||||
controller.playerIndex = -1;
|
||||
|
||||
@@ -426,7 +426,7 @@ static bool MaybeAddDevice(const char *path)
|
||||
name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
|
||||
guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, di.udi_vendor, di.udi_product, 0, 0);
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(name, guid) ||
|
||||
if (SDL_ShouldIgnoreJoystick(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name) ||
|
||||
SDL_JoystickHandledByAnotherDriver(&SDL_BSD_JoystickDriver, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
|
||||
SDL_free(name);
|
||||
FreeHwData(hw);
|
||||
|
||||
@@ -475,6 +475,11 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
CFNumberGetValue(refCF, kCFNumberSInt32Type, &version);
|
||||
}
|
||||
|
||||
if (SDL_IsJoystickXboxOne(vendor, product)) {
|
||||
// We can't actually use this API for Xbox controllers
|
||||
return false;
|
||||
}
|
||||
|
||||
// get device name
|
||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDManufacturerKey));
|
||||
if ((!refCF) || (!CFStringGetCString(refCF, manufacturer_string, sizeof(manufacturer_string), kCFStringEncodingUTF8))) {
|
||||
@@ -490,6 +495,10 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
SDL_free(name);
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(vendor, product, version, pDevice->product)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SDL_JoystickHandledByAnotherDriver(&SDL_DARWIN_JoystickDriver, vendor, product, version, pDevice->product)) {
|
||||
return false;
|
||||
}
|
||||
@@ -548,11 +557,6 @@ static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender
|
||||
return; // not a device we care about, probably.
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(device->product, device->guid)) {
|
||||
FreeDevice(device);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get notified when this device is disconnected.
|
||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
#define COBJMACROS
|
||||
#include <gameinput.h>
|
||||
|
||||
// Default value for SDL_HINT_JOYSTICK_GAMEINPUT
|
||||
#if defined(SDL_PLATFORM_GDK)
|
||||
#define SDL_GAMEINPUT_DEFAULT true
|
||||
#else
|
||||
#define SDL_GAMEINPUT_DEFAULT false
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE = 11
|
||||
@@ -234,7 +241,7 @@ static bool GAMEINPUT_JoystickInit(void)
|
||||
{
|
||||
HRESULT hR;
|
||||
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, false)) {
|
||||
if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1154,6 +1154,9 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_STEAM_RIGHT_PADDLE,
|
||||
((ctx->m_state.ulButtons & STEAM_BUTTON_BACK_RIGHT_MASK) != 0));
|
||||
|
||||
SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_STICK,
|
||||
((ctx->m_state.ulButtons & STEAM_BUTTON_RIGHTPAD_CLICKED_MASK) != 0));
|
||||
|
||||
if (ctx->m_state.ulButtons & STEAM_DPAD_UP_MASK) {
|
||||
hat |= SDL_HAT_UP;
|
||||
}
|
||||
|
||||
@@ -80,21 +80,15 @@ static bool HIDAPI_DriverXbox360_IsSupportedDevice(SDL_HIDAPI_Device *device, co
|
||||
// This is the chatpad or other input interface, not the Xbox 360 interface
|
||||
return false;
|
||||
}
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
if (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX360_WIRED_CONTROLLER && version == 0) {
|
||||
// This is the Steam Virtual Gamepad, which isn't supported by this driver
|
||||
#if defined(SDL_PLATFORM_MACOS) && defined(SDL_JOYSTICK_MFI)
|
||||
if (SDL_IsJoystickSteamVirtualGamepad(vendor_id, product_id, version)) {
|
||||
// GCController support doesn't work with the Steam Virtual Gamepad
|
||||
return true;
|
||||
} else {
|
||||
// On macOS you can't write output reports to wired XBox controllers,
|
||||
// so we'll just use the GCController support instead.
|
||||
return false;
|
||||
}
|
||||
/* Wired Xbox One controllers are handled by this driver, interfacing with
|
||||
the 360Controller driver available from:
|
||||
https://github.com/360Controller/360Controller/releases
|
||||
|
||||
Bluetooth Xbox One controllers are handled by the SDL Xbox One driver
|
||||
*/
|
||||
if (SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) {
|
||||
return false;
|
||||
}
|
||||
return (type == SDL_GAMEPAD_TYPE_XBOX360 || type == SDL_GAMEPAD_TYPE_XBOXONE);
|
||||
#else
|
||||
return (type == SDL_GAMEPAD_TYPE_XBOX360);
|
||||
#endif
|
||||
@@ -149,6 +143,13 @@ static bool HIDAPI_DriverXbox360_InitDevice(SDL_HIDAPI_Device *device)
|
||||
|
||||
device->type = SDL_GAMEPAD_TYPE_XBOX360;
|
||||
|
||||
if (SDL_IsJoystickSteamVirtualGamepad(device->vendor_id, device->product_id, device->version) &&
|
||||
device->product_string && SDL_strncmp(device->product_string, "GamePad-", 8) == 0) {
|
||||
int slot = 0;
|
||||
SDL_sscanf(device->product_string, "GamePad-%d", &slot);
|
||||
device->steam_virtual_gamepad_slot = (slot - 1);
|
||||
}
|
||||
|
||||
return HIDAPI_JoystickConnected(device, NULL);
|
||||
}
|
||||
|
||||
@@ -197,30 +198,6 @@ static bool HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
|
||||
static bool HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||
{
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
if (SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id)) {
|
||||
Uint8 rumble_packet[] = { 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 };
|
||||
|
||||
rumble_packet[4] = (low_frequency_rumble >> 8);
|
||||
rumble_packet[5] = (high_frequency_rumble >> 8);
|
||||
|
||||
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
} else {
|
||||
/* On macOS the 360Controller driver uses this short report,
|
||||
and we need to prefix it with a magic token so hidapi passes it through untouched
|
||||
*/
|
||||
Uint8 rumble_packet[] = { 'M', 'A', 'G', 'I', 'C', '0', 0x00, 0x04, 0x00, 0x00 };
|
||||
|
||||
rumble_packet[6 + 2] = (low_frequency_rumble >> 8);
|
||||
rumble_packet[6 + 3] = (high_frequency_rumble >> 8);
|
||||
|
||||
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
}
|
||||
#else
|
||||
Uint8 rumble_packet[] = { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
rumble_packet[3] = (low_frequency_rumble >> 8);
|
||||
@@ -229,7 +206,6 @@ static bool HIDAPI_DriverXbox360_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_J
|
||||
if (SDL_HIDAPI_SendRumble(device, rumble_packet, sizeof(rumble_packet)) != sizeof(rumble_packet)) {
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -350,9 +350,11 @@ static bool HIDAPI_DriverXboxOne_IsEnabled(void)
|
||||
|
||||
static bool HIDAPI_DriverXboxOne_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)
|
||||
{
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
// Wired Xbox One controllers are handled by the 360Controller driver
|
||||
#if defined(SDL_PLATFORM_MACOS) && defined(SDL_JOYSTICK_MFI)
|
||||
if (!SDL_IsJoystickBluetoothXboxOne(vendor_id, product_id)) {
|
||||
// On macOS we get a shortened version of the real report and
|
||||
// you can't write output reports for wired controllers, so
|
||||
// we'll just use the GCController support instead.
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -1552,8 +1554,9 @@ static bool HIDAPI_GIP_ProcessData(SDL_Joystick *joystick, SDL_DriverXboxOne_Con
|
||||
|
||||
while (size > GIP_HEADER_MIN_LENGTH) {
|
||||
hdr_len = HIDAPI_GIP_DecodeHeader(&hdr, data, size);
|
||||
if ((hdr_len + hdr.packet_length) > (size_t)size) {
|
||||
return false;
|
||||
if ((hdr_len + hdr.packet_length) > (Uint32)size) {
|
||||
// On macOS we get a shortened version of the real report
|
||||
hdr.packet_length = (Uint32)(size - hdr_len);
|
||||
}
|
||||
|
||||
if (!HIDAPI_GIP_ProcessPacket(joystick, ctx, &hdr, data + hdr_len)) {
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
#include "../windows/SDL_rawinputjoystick_c.h"
|
||||
#endif
|
||||
|
||||
#ifdef SDL_USE_LIBUDEV
|
||||
#include "../../core/linux/SDL_sandbox.h"
|
||||
#endif
|
||||
|
||||
struct joystick_hwdata
|
||||
{
|
||||
@@ -331,7 +328,7 @@ static SDL_HIDAPI_DeviceDriver *HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device
|
||||
return &SDL_HIDAPI_DriverCombined;
|
||||
}
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
|
||||
if (SDL_ShouldIgnoreJoystick(device->vendor_id, device->product_id, device->version, device->name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -457,57 +454,7 @@ static void HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device, bool *removed) S
|
||||
// Wait a little bit for the device to initialize
|
||||
SDL_Delay(10);
|
||||
|
||||
#ifdef SDL_PLATFORM_ANDROID
|
||||
/* On Android we need to leave joysticks unlocked because it calls
|
||||
* out to the main thread for permissions and the main thread can
|
||||
* be in the process of handling controller input.
|
||||
*
|
||||
* See https://github.com/libsdl-org/SDL/issues/6347 for details
|
||||
*/
|
||||
{
|
||||
SDL_HIDAPI_Device *curr;
|
||||
int lock_count = 0;
|
||||
char *path = SDL_strdup(device->path);
|
||||
|
||||
SDL_AssertJoysticksLocked();
|
||||
while (SDL_JoysticksLocked()) {
|
||||
++lock_count;
|
||||
SDL_UnlockJoysticks();
|
||||
}
|
||||
|
||||
dev = SDL_hid_open_path(path);
|
||||
|
||||
while (lock_count > 0) {
|
||||
--lock_count;
|
||||
SDL_LockJoysticks();
|
||||
}
|
||||
SDL_free(path);
|
||||
|
||||
// Make sure the device didn't get removed while opening the HID path
|
||||
for (curr = SDL_HIDAPI_devices; curr && curr != device; curr = curr->next) {
|
||||
continue;
|
||||
}
|
||||
if (curr == NULL) {
|
||||
*removed = true;
|
||||
if (dev) {
|
||||
SDL_hid_close(dev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* On other platforms we want to keep the lock so other threads wait for
|
||||
* us to finish opening the controller before checking to see whether the
|
||||
* HIDAPI driver is handling the device.
|
||||
*
|
||||
* On Windows, for example, the main thread can be enumerating DirectInput
|
||||
* devices while the Windows.Gaming.Input thread is calling back with a new
|
||||
* controller available.
|
||||
*
|
||||
* See https://github.com/libsdl-org/SDL/issues/7304 for details.
|
||||
*/
|
||||
dev = SDL_hid_open_path(device->path);
|
||||
#endif
|
||||
|
||||
if (dev == NULL) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
@@ -586,7 +533,7 @@ static bool HIDAPI_JoystickInit(void)
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"udev disabled by SDL_HINT_HIDAPI_UDEV");
|
||||
linux_enumeration_method = ENUMERATION_FALLBACK;
|
||||
} else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
|
||||
} else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"Container detected, disabling HIDAPI udev integration");
|
||||
linux_enumeration_method = ENUMERATION_FALLBACK;
|
||||
@@ -983,6 +930,7 @@ static SDL_HIDAPI_Device *HIDAPI_AddDevice(const struct SDL_hid_device_info *inf
|
||||
device->guid = SDL_CreateJoystickGUID(bus, device->vendor_id, device->product_id, device->version, device->manufacturer_string, device->product_string, 'h', 0);
|
||||
device->joystick_type = SDL_JOYSTICK_TYPE_GAMEPAD;
|
||||
device->type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
|
||||
device->steam_virtual_gamepad_slot = -1;
|
||||
|
||||
if (num_children > 0) {
|
||||
int i;
|
||||
@@ -1440,6 +1388,12 @@ static const char *HIDAPI_JoystickGetDevicePath(int device_index)
|
||||
|
||||
static int HIDAPI_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
|
||||
device = HIDAPI_GetDeviceByIndex(device_index, NULL);
|
||||
if (device) {
|
||||
return device->steam_virtual_gamepad_slot;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ typedef struct SDL_HIDAPI_Device
|
||||
bool is_bluetooth;
|
||||
SDL_JoystickType joystick_type;
|
||||
SDL_GamepadType type;
|
||||
int steam_virtual_gamepad_slot;
|
||||
|
||||
struct SDL_HIDAPI_DeviceDriver *driver;
|
||||
void *context;
|
||||
|
||||
@@ -124,7 +124,6 @@
|
||||
|
||||
#include "../../core/linux/SDL_evdev_capabilities.h"
|
||||
#include "../../core/linux/SDL_udev.h"
|
||||
#include "../../core/linux/SDL_sandbox.h"
|
||||
|
||||
#if 0
|
||||
#define DEBUG_INPUT_EVENTS 1
|
||||
@@ -330,15 +329,14 @@ static bool IsJoystick(const char *path, int *fd, char **name_return, Uint16 *ve
|
||||
SDL_Log("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
|
||||
#endif
|
||||
|
||||
*guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(name, *guid)) {
|
||||
if (SDL_ShouldIgnoreJoystick(inpid.vendor, inpid.product, inpid.version, name)) {
|
||||
SDL_free(name);
|
||||
return false;
|
||||
}
|
||||
*name_return = name;
|
||||
*vendor_return = inpid.vendor;
|
||||
*product_return = inpid.product;
|
||||
*guid = SDL_CreateJoystickGUID(inpid.bustype, inpid.vendor, inpid.product, inpid.version, NULL, product_string, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1069,7 +1067,7 @@ static bool LINUX_JoystickInit(void)
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
|
||||
enumeration_method = ENUMERATION_FALLBACK;
|
||||
} else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
|
||||
} else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
"Container detected, disabling udev integration");
|
||||
enumeration_method = ENUMERATION_FALLBACK;
|
||||
|
||||
@@ -472,6 +472,8 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
|
||||
CHECK(QueryDeviceInfo(device, &vendor, &product));
|
||||
|
||||
CHECK(!SDL_IsXInputDevice(vendor, product, hidPath));
|
||||
CHECK(!SDL_ShouldIgnoreJoystick(vendor, product, version, name));
|
||||
CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, name));
|
||||
|
||||
pNewJoystick = *(JoyStick_DeviceData **)pContext;
|
||||
while (pNewJoystick) {
|
||||
@@ -514,10 +516,6 @@ static BOOL CALLBACK EnumJoystickDetectCallback(LPCDIDEVICEINSTANCE pDeviceInsta
|
||||
pNewJoystick->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_BLUETOOTH, vendor, product, version, NULL, name, 0, 0);
|
||||
}
|
||||
|
||||
CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
|
||||
|
||||
CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname));
|
||||
|
||||
WINDOWS_AddJoystickDevice(pNewJoystick);
|
||||
pNewJoystick = NULL;
|
||||
|
||||
|
||||
@@ -881,7 +881,9 @@ static void RAWINPUT_AddDevice(HANDLE hDevice)
|
||||
CHECK(GetRawInputDeviceInfoA(hDevice, RIDI_DEVICENAME, dev_name, &size) != (UINT)-1);
|
||||
// Only take XInput-capable devices
|
||||
CHECK(SDL_strstr(dev_name, "IG_") != NULL);
|
||||
CHECK(!SDL_ShouldIgnoreJoystick((Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
|
||||
CHECK(!SDL_JoystickHandledByAnotherDriver(&SDL_RAWINPUT_JoystickDriver, (Uint16)rdi.hid.dwVendorId, (Uint16)rdi.hid.dwProductId, (Uint16)rdi.hid.dwVersionNumber, ""));
|
||||
|
||||
device = (SDL_RAWINPUT_Device *)SDL_calloc(1, sizeof(SDL_RAWINPUT_Device));
|
||||
CHECK(device);
|
||||
device->hDevice = hDevice;
|
||||
|
||||
@@ -399,7 +399,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
|
||||
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(e, &IID___x_ABI_CWindows_CGaming_CInput_CIRawGameController, (void **)&controller);
|
||||
if (SUCCEEDED(hr)) {
|
||||
char *name = NULL;
|
||||
SDL_GUID guid = { 0 };
|
||||
Uint16 bus = SDL_HARDWARE_BUS_USB;
|
||||
Uint16 vendor = 0;
|
||||
Uint16 product = 0;
|
||||
@@ -446,6 +445,10 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
|
||||
name = SDL_strdup("");
|
||||
}
|
||||
|
||||
if (!ignore_joystick && SDL_ShouldIgnoreJoystick(vendor, product, version, name)) {
|
||||
ignore_joystick = true;
|
||||
}
|
||||
|
||||
if (!ignore_joystick && SDL_JoystickHandledByAnotherDriver(&SDL_WGI_JoystickDriver, vendor, product, version, name)) {
|
||||
ignore_joystick = true;
|
||||
}
|
||||
@@ -455,18 +458,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
|
||||
ignore_joystick = true;
|
||||
}
|
||||
|
||||
if (!ignore_joystick) {
|
||||
if (game_controller) {
|
||||
type = GetGameControllerType(game_controller);
|
||||
}
|
||||
|
||||
guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(name, guid)) {
|
||||
ignore_joystick = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignore_joystick) {
|
||||
// New device, add it
|
||||
WindowsGamingInputControllerState *controllers = SDL_realloc(wgi.controllers, sizeof(wgi.controllers[0]) * (wgi.controller_count + 1));
|
||||
@@ -474,11 +465,15 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
|
||||
WindowsGamingInputControllerState *state = &controllers[wgi.controller_count];
|
||||
SDL_JoystickID joystickID = SDL_GetNextObjectID();
|
||||
|
||||
if (game_controller) {
|
||||
type = GetGameControllerType(game_controller);
|
||||
}
|
||||
|
||||
SDL_zerop(state);
|
||||
state->instance_id = joystickID;
|
||||
state->controller = controller;
|
||||
state->name = name;
|
||||
state->guid = guid;
|
||||
state->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, name, 'w', (Uint8)type);
|
||||
state->type = type;
|
||||
state->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(controller, vendor, product);
|
||||
|
||||
|
||||
@@ -185,13 +185,18 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
|
||||
pNewJoystick = pNewJoystick->pNext;
|
||||
}
|
||||
|
||||
name = GetXInputName(userid, SubType);
|
||||
GetXInputDeviceInfo(userid, &vendor, &product, &version);
|
||||
if (SDL_ShouldIgnoreJoystick(vendor, product, version, name) ||
|
||||
SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pNewJoystick = (JoyStick_DeviceData *)SDL_calloc(1, sizeof(JoyStick_DeviceData));
|
||||
if (!pNewJoystick) {
|
||||
return; // better luck next time?
|
||||
}
|
||||
|
||||
name = GetXInputName(userid, SubType);
|
||||
GetXInputDeviceInfo(userid, &vendor, &product, &version);
|
||||
pNewJoystick->bXInputDevice = true;
|
||||
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
|
||||
if (!pNewJoystick->joystickname) {
|
||||
@@ -203,16 +208,6 @@ static void AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pC
|
||||
pNewJoystick->SubType = SubType;
|
||||
pNewJoystick->XInputUserId = userid;
|
||||
|
||||
if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
|
||||
SDL_free(pNewJoystick);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_JoystickHandledByAnotherDriver(&SDL_WINDOWS_JoystickDriver, vendor, product, version, pNewJoystick->joystickname)) {
|
||||
SDL_free(pNewJoystick);
|
||||
return;
|
||||
}
|
||||
|
||||
WINDOWS_AddJoystickDevice(pNewJoystick);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ union {
|
||||
Uint64 u64;
|
||||
double d;
|
||||
} inf_union = {
|
||||
0x7ff0000000000000 /* Binary representation of a 64-bit infinite double (sign=0, exponent=2047, mantissa=0) */
|
||||
SDL_UINT64_C(0x7ff0000000000000) /* Binary representation of a 64-bit infinite double (sign=0, exponent=2047, mantissa=0) */
|
||||
};
|
||||
|
||||
double __ieee754_exp(double x) /* default IEEE double exp */
|
||||
|
||||
@@ -75,6 +75,11 @@ static bool SDLCALL SDL_MainCallbackEventWatcher(void *userdata, SDL_Event *even
|
||||
// Make sure any currently queued events are processed then dispatch this before continuing
|
||||
SDL_DispatchMainCallbackEvents();
|
||||
SDL_DispatchMainCallbackEvent(event);
|
||||
|
||||
// Make sure that we quit if we get a terminating event
|
||||
if (event->type == SDL_EVENT_TERMINATING) {
|
||||
SDL_CompareAndSwapAtomicInt(&apprc, SDL_APP_CONTINUE, SDL_APP_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
// We'll process this event later from the main event queue
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ int SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit,
|
||||
} else {
|
||||
const Uint64 now = SDL_GetTicksNS();
|
||||
if (next_iteration > now) { // Running faster than the limit, sleep a little.
|
||||
SDL_DelayNS(next_iteration - now);
|
||||
SDL_DelayPrecise(next_iteration - now);
|
||||
} else {
|
||||
next_iteration = now; // running behind (or just lost the window)...reset the timer.
|
||||
}
|
||||
|
||||
@@ -73,6 +73,14 @@ static bool SetupRedirect(SDL_PropertiesID props, const char *property, HANDLE *
|
||||
WIN_SetError("DuplicateHandle()");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetFileType(*result) == FILE_TYPE_PIPE) {
|
||||
DWORD wait_mode = PIPE_WAIT;
|
||||
if (!SetNamedPipeHandleState(*result, &wait_mode, NULL, NULL)) {
|
||||
WIN_SetError("SetNamedPipeHandleState()");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
// The SDL 2D rendering system
|
||||
|
||||
#include "SDL_sysrender.h"
|
||||
#include "SDL_render_debug_font.h"
|
||||
#include "software/SDL_render_sw_c.h"
|
||||
#include "../video/SDL_pixels_c.h"
|
||||
#include "../video/SDL_video_c.h"
|
||||
@@ -3578,8 +3579,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
|
||||
bool isstack1;
|
||||
bool isstack2;
|
||||
float *xy = SDL_small_alloc(float, 4 * 2 * count, &isstack1);
|
||||
int *indices = SDL_small_alloc(int,
|
||||
(4) * 3 * (count - 1) + (2) * 3 * (count), &isstack2);
|
||||
int *indices = SDL_small_alloc(int, (4) * 3 * (count - 1) + (2) * 3 * (count), &isstack2);
|
||||
|
||||
if (xy && indices) {
|
||||
int i;
|
||||
@@ -4389,7 +4389,7 @@ bool SDL_RenderGeometry(SDL_Renderer *renderer,
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_RENDER_SW
|
||||
static bool remap_one_indice(
|
||||
static int remap_one_indice(
|
||||
int prev,
|
||||
int k,
|
||||
SDL_Texture *texture,
|
||||
@@ -4427,7 +4427,7 @@ static bool remap_one_indice(
|
||||
return prev;
|
||||
}
|
||||
|
||||
static bool remap_indices(
|
||||
static int remap_indices(
|
||||
int prev[3],
|
||||
int k,
|
||||
SDL_Texture *texture,
|
||||
@@ -4948,7 +4948,7 @@ static void SDL_SimulateRenderVSync(SDL_Renderer *renderer)
|
||||
elapsed = (now - renderer->last_present);
|
||||
if (elapsed < interval) {
|
||||
Uint64 duration = (interval - elapsed);
|
||||
SDL_DelayNS(duration);
|
||||
SDL_DelayPrecise(duration);
|
||||
now = SDL_GetTicksNS();
|
||||
}
|
||||
|
||||
@@ -5098,6 +5098,11 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
|
||||
|
||||
SDL_DiscardAllCommands(renderer);
|
||||
|
||||
if (renderer->debug_char_texture_atlas) {
|
||||
SDL_DestroyTexture(renderer->debug_char_texture_atlas);
|
||||
renderer->debug_char_texture_atlas = NULL;
|
||||
}
|
||||
|
||||
// Free existing textures for this renderer
|
||||
while (renderer->textures) {
|
||||
SDL_Texture *tex = renderer->textures;
|
||||
@@ -5347,3 +5352,119 @@ bool SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define SDL_DEBUG_FONT_GLYPHS_PER_ROW 14
|
||||
|
||||
static bool CreateDebugTextAtlas(SDL_Renderer *renderer)
|
||||
{
|
||||
SDL_assert(renderer->debug_char_texture_atlas == NULL); // don't double-create it!
|
||||
|
||||
const int charWidth = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
const int charHeight = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
|
||||
// actually make each glyph two pixels taller/wider, to prevent scaling artifacts.
|
||||
const int rows = (SDL_DEBUG_FONT_NUM_GLYPHS / SDL_DEBUG_FONT_GLYPHS_PER_ROW) + 1;
|
||||
SDL_Surface *atlas = SDL_CreateSurface((charWidth + 2) * SDL_DEBUG_FONT_GLYPHS_PER_ROW, rows * (charHeight + 2), SDL_PIXELFORMAT_RGBA8888);
|
||||
if (!atlas) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int pitch = atlas->pitch;
|
||||
SDL_memset(atlas->pixels, '\0', atlas->h * atlas->pitch);
|
||||
|
||||
int column = 0;
|
||||
int row = 0;
|
||||
for (int glyph = 0; glyph < SDL_DEBUG_FONT_NUM_GLYPHS; glyph++) {
|
||||
// find top-left of this glyph in destination surface. The +2's account for glyph padding.
|
||||
Uint8 *linepos = (((Uint8 *)atlas->pixels) + ((row * (charHeight + 2) + 1) * pitch)) + ((column * (charWidth + 2) + 1) * sizeof (Uint32));
|
||||
const Uint8 *charpos = SDL_RenderDebugTextFontData + (glyph * 8);
|
||||
|
||||
// Draw the glyph to the surface...
|
||||
for (int iy = 0; iy < charHeight; iy++) {
|
||||
Uint32 *curpos = (Uint32 *)linepos;
|
||||
for (int ix = 0; ix < charWidth; ix++) {
|
||||
if ((*charpos) & (1 << ix)) {
|
||||
*curpos = 0xffffffff;
|
||||
} else {
|
||||
*curpos = 0;
|
||||
}
|
||||
++curpos;
|
||||
}
|
||||
linepos += pitch;
|
||||
++charpos;
|
||||
}
|
||||
|
||||
// move to next position (and if too far, start the next row).
|
||||
column++;
|
||||
if (column >= SDL_DEBUG_FONT_GLYPHS_PER_ROW) {
|
||||
row++;
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert((row < rows) || ((row == rows) && (column == 0))); // make sure we didn't overflow the surface.
|
||||
|
||||
// Convert temp surface into texture
|
||||
renderer->debug_char_texture_atlas = SDL_CreateTextureFromSurface(renderer, atlas);
|
||||
SDL_DestroySurface(atlas);
|
||||
|
||||
return (renderer->debug_char_texture_atlas != NULL);
|
||||
}
|
||||
|
||||
static bool DrawDebugCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c)
|
||||
{
|
||||
SDL_assert(renderer->debug_char_texture_atlas != NULL); // should have been created by now!
|
||||
|
||||
const int charWidth = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
const int charHeight = SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
|
||||
// Character index in cache
|
||||
Uint32 ci = c;
|
||||
if ((ci <= 32) || ((ci >= 127) && (ci <= 160))) {
|
||||
return true; // these are just completely blank chars, don't bother doing anything.
|
||||
} else if (ci >= SDL_DEBUG_FONT_NUM_GLYPHS) {
|
||||
ci = SDL_DEBUG_FONT_NUM_GLYPHS - 1; // use our "not a valid/supported character" glyph.
|
||||
} else if (ci < 127) {
|
||||
ci -= 33; // adjust for the 33 blank glyphs at the start
|
||||
} else {
|
||||
ci -= 67; // adjust for the 33 blank glyphs at the start AND the 34 gap in the middle.
|
||||
}
|
||||
|
||||
const float src_x = (float) (((ci % SDL_DEBUG_FONT_GLYPHS_PER_ROW) * (charWidth + 2)) + 1);
|
||||
const float src_y = (float) (((ci / SDL_DEBUG_FONT_GLYPHS_PER_ROW) * (charHeight + 2)) + 1);
|
||||
|
||||
// Draw texture onto destination
|
||||
const SDL_FRect srect = { src_x, src_y, (float) charWidth, (float) charHeight };
|
||||
const SDL_FRect drect = { x, y, (float) charWidth, (float) charHeight };
|
||||
return SDL_RenderTexture(renderer, renderer->debug_char_texture_atlas, &srect, &drect);
|
||||
}
|
||||
|
||||
bool SDL_RenderDebugText(SDL_Renderer *renderer, float x, float y, const char *s)
|
||||
{
|
||||
CHECK_RENDERER_MAGIC(renderer, false);
|
||||
|
||||
// Allocate a texture atlas for this renderer if needed.
|
||||
if (!renderer->debug_char_texture_atlas) {
|
||||
if (!CreateDebugTextAtlas(renderer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
Uint8 r, g, b, a;
|
||||
result &= SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
|
||||
result &= SDL_SetTextureColorMod(renderer->debug_char_texture_atlas, r, g, b);
|
||||
result &= SDL_SetTextureAlphaMod(renderer->debug_char_texture_atlas, a);
|
||||
|
||||
float curx = x;
|
||||
Uint32 ch;
|
||||
|
||||
while (result && ((ch = SDL_StepUTF8(&s, NULL)) != 0)) {
|
||||
result &= DrawDebugCharacter(renderer, curx, y, ch);
|
||||
curx += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -305,6 +305,8 @@ struct SDL_Renderer
|
||||
|
||||
SDL_PropertiesID props;
|
||||
|
||||
SDL_Texture *debug_char_texture_atlas;
|
||||
|
||||
bool destroyed; // already destroyed by SDL_DestroyWindow; just free this struct in SDL_DestroyRenderer.
|
||||
|
||||
void *internal;
|
||||
|
||||
@@ -1215,15 +1215,15 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
||||
renderer->window = window;
|
||||
renderer->name = GPU_RenderDriver.name;
|
||||
|
||||
bool debug = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, false);
|
||||
bool lowpower = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOL, false);
|
||||
bool debug = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, false);
|
||||
bool lowpower = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, false);
|
||||
|
||||
// Prefer environment variables/hints if they exist, otherwise defer to properties
|
||||
debug = SDL_GetHintBoolean(SDL_HINT_RENDER_GPU_DEBUG, debug);
|
||||
lowpower = SDL_GetHintBoolean(SDL_HINT_RENDER_GPU_LOW_POWER, lowpower);
|
||||
|
||||
SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, debug);
|
||||
SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOL, lowpower);
|
||||
SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, debug);
|
||||
SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, lowpower);
|
||||
|
||||
GPU_FillSupportedShaderFormats(create_props);
|
||||
data->device = SDL_CreateGPUDeviceWithProperties(create_props);
|
||||
|
||||
@@ -247,10 +247,10 @@ SDL_GPUShader *GPU_GetFragmentShader(GPU_Shaders *shaders, GPU_FragmentShaderID
|
||||
|
||||
void GPU_FillSupportedShaderFormats(SDL_PropertiesID props)
|
||||
{
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOL, HAVE_SPIRV_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOL, HAVE_DXBC50_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOL, HAVE_DXIL60_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOL, HAVE_METAL_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, HAVE_SPIRV_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN, HAVE_DXBC50_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, HAVE_DXIL60_SHADERS);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, HAVE_METAL_SHADERS);
|
||||
}
|
||||
|
||||
#endif // SDL_VIDEO_RENDER_GPU
|
||||
|
||||
@@ -1497,20 +1497,7 @@ static SDL_Surface *GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *
|
||||
|
||||
// Flip the rows to be top-down if necessary
|
||||
if (!renderer->target) {
|
||||
bool isstack;
|
||||
int length = rect->w * SDL_BYTESPERPIXEL(format);
|
||||
Uint8 *src = (Uint8 *)surface->pixels + (rect->h - 1) * surface->pitch;
|
||||
Uint8 *dst = (Uint8 *)surface->pixels;
|
||||
Uint8 *tmp = SDL_small_alloc(Uint8, length, &isstack);
|
||||
int rows = rect->h / 2;
|
||||
while (rows--) {
|
||||
SDL_memcpy(tmp, dst, length);
|
||||
SDL_memcpy(dst, src, length);
|
||||
SDL_memcpy(src, tmp, length);
|
||||
dst += surface->pitch;
|
||||
src -= surface->pitch;
|
||||
}
|
||||
SDL_small_free(tmp, isstack);
|
||||
SDL_FlipSurface(surface, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@@ -348,15 +348,11 @@ static bool CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char
|
||||
|
||||
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
|
||||
info = SDL_small_alloc(char, length + 1, &isstack);
|
||||
ctx->glGetInfoLogARB(shader, length, NULL, info);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER,
|
||||
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
|
||||
#ifdef DEBUG_SHADERS
|
||||
fprintf(stderr,
|
||||
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
|
||||
#endif
|
||||
SDL_small_free(info, isstack);
|
||||
|
||||
if (info) {
|
||||
ctx->glGetInfoLogARB(shader, length, NULL, info);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to compile shader:\n%s%s\n%s", defines, source, info);
|
||||
SDL_small_free(info, isstack);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@@ -2014,20 +2014,7 @@ static SDL_Surface *GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rec
|
||||
|
||||
// Flip the rows to be top-down if necessary
|
||||
if (!renderer->target) {
|
||||
bool isstack;
|
||||
int length = rect->w * SDL_BYTESPERPIXEL(format);
|
||||
Uint8 *src = (Uint8 *)surface->pixels + (rect->h - 1) * surface->pitch;
|
||||
Uint8 *dst = (Uint8 *)surface->pixels;
|
||||
Uint8 *tmp = SDL_small_alloc(Uint8, length, &isstack);
|
||||
int rows = rect->h / 2;
|
||||
while (rows--) {
|
||||
SDL_memcpy(tmp, dst, length);
|
||||
SDL_memcpy(dst, src, length);
|
||||
SDL_memcpy(src, tmp, length);
|
||||
dst += surface->pitch;
|
||||
src -= surface->pitch;
|
||||
}
|
||||
SDL_small_free(tmp, isstack);
|
||||
SDL_FlipSurface(surface, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@@ -349,6 +349,7 @@ static bool VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
|
||||
if (length == pitch && length == dpitch) {
|
||||
SDL_memcpy(dst, pixels, length * rect->h);
|
||||
pixels += pitch * rect->h;
|
||||
} else {
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, pixels, length);
|
||||
@@ -376,6 +377,7 @@ static bool VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
// U plane
|
||||
if (length == uv_src_pitch && length == uv_pitch) {
|
||||
SDL_memcpy(Udst, pixels, length * UVrect.h);
|
||||
pixels += uv_src_pitch * UVrect.h;
|
||||
} else {
|
||||
for (row = 0; row < UVrect.h; ++row) {
|
||||
SDL_memcpy(Udst, pixels, length);
|
||||
@@ -1103,22 +1105,8 @@ static SDL_Surface *VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_
|
||||
read_pixels(rect->x, y, rect->w, rect->h, surface->pixels);
|
||||
|
||||
// Flip the rows to be top-down if necessary
|
||||
|
||||
if (!renderer->target) {
|
||||
bool isstack;
|
||||
int length = rect->w * SDL_BYTESPERPIXEL(format);
|
||||
Uint8 *src = (Uint8 *)surface->pixels + (rect->h - 1) * surface->pitch;
|
||||
Uint8 *dst = (Uint8 *)surface->pixels;
|
||||
Uint8 *tmp = SDL_small_alloc(Uint8, length, &isstack);
|
||||
int rows = rect->h / 2;
|
||||
while (rows--) {
|
||||
SDL_memcpy(tmp, dst, length);
|
||||
SDL_memcpy(dst, src, length);
|
||||
SDL_memcpy(src, tmp, length);
|
||||
dst += surface->pitch;
|
||||
src -= surface->pitch;
|
||||
}
|
||||
SDL_small_free(tmp, isstack);
|
||||
SDL_FlipSurface(surface, SDL_FLIP_VERTICAL);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
@@ -740,10 +740,10 @@ int gxm_init(SDL_Renderer *renderer)
|
||||
colorVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
colorVertexAttributes[0].componentCount = 2; // (x, y)
|
||||
colorVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorPositionAttribute);
|
||||
// color: 4 unsigned char = 32 bits
|
||||
// color: 4 floats = 4*32 bits
|
||||
colorVertexAttributes[1].streamIndex = 0;
|
||||
colorVertexAttributes[1].offset = 8; // (x, y) * 4 = 8 bytes
|
||||
colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
|
||||
colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
colorVertexAttributes[1].componentCount = 4; // (color)
|
||||
colorVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorColorAttribute);
|
||||
// 16 bit (short) indices
|
||||
@@ -785,10 +785,10 @@ int gxm_init(SDL_Renderer *renderer)
|
||||
textureVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
textureVertexAttributes[1].componentCount = 2; // (u, v)
|
||||
textureVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTexcoordAttribute);
|
||||
// r,g,b,a: 4 unsigned chars 32 bits
|
||||
// r,g,b,a: 4 floats 4*32 bits
|
||||
textureVertexAttributes[2].streamIndex = 0;
|
||||
textureVertexAttributes[2].offset = 16; // (x, y, u, v) * 4 = 16 bytes
|
||||
textureVertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
|
||||
textureVertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
textureVertexAttributes[2].componentCount = 4; // (r, g, b, a)
|
||||
textureVertexAttributes[2].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureColorAttribute);
|
||||
// 16 bit (short) indices
|
||||
|
||||
@@ -2054,6 +2054,89 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
return result;
|
||||
}
|
||||
|
||||
// clean up previous swapchain resources
|
||||
if (rendererData->swapchainImageViews) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
vkDestroyImageView(rendererData->device, rendererData->swapchainImageViews[i], NULL);
|
||||
}
|
||||
SDL_free(rendererData->swapchainImageViews);
|
||||
rendererData->swapchainImageViews = NULL;
|
||||
}
|
||||
if (rendererData->fences) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
if (rendererData->fences[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyFence(rendererData->device, rendererData->fences[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->fences);
|
||||
rendererData->fences = NULL;
|
||||
}
|
||||
if (rendererData->framebuffers) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
if (rendererData->framebuffers[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyFramebuffer(rendererData->device, rendererData->framebuffers[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->framebuffers);
|
||||
rendererData->framebuffers = NULL;
|
||||
}
|
||||
if (rendererData->descriptorPools) {
|
||||
SDL_assert(rendererData->numDescriptorPools);
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
for (uint32_t j = 0; j < rendererData->numDescriptorPools[i]; j++) {
|
||||
if (rendererData->descriptorPools[i][j] != VK_NULL_HANDLE) {
|
||||
vkDestroyDescriptorPool(rendererData->device, rendererData->descriptorPools[i][j], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->descriptorPools[i]);
|
||||
}
|
||||
SDL_free(rendererData->descriptorPools);
|
||||
rendererData->descriptorPools = NULL;
|
||||
SDL_free(rendererData->numDescriptorPools);
|
||||
rendererData->numDescriptorPools = NULL;
|
||||
}
|
||||
if (rendererData->imageAvailableSemaphores) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
if (rendererData->imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
|
||||
vkDestroySemaphore(rendererData->device, rendererData->imageAvailableSemaphores[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->imageAvailableSemaphores);
|
||||
rendererData->imageAvailableSemaphores = NULL;
|
||||
}
|
||||
if (rendererData->renderingFinishedSemaphores) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
if (rendererData->renderingFinishedSemaphores[i] != VK_NULL_HANDLE) {
|
||||
vkDestroySemaphore(rendererData->device, rendererData->renderingFinishedSemaphores[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->renderingFinishedSemaphores);
|
||||
rendererData->renderingFinishedSemaphores = NULL;
|
||||
}
|
||||
if (rendererData->uploadBuffers) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
for (uint32_t j = 0; j < SDL_VULKAN_NUM_UPLOAD_BUFFERS; j++) {
|
||||
VULKAN_DestroyBuffer(rendererData, &rendererData->uploadBuffers[i][j]);
|
||||
}
|
||||
SDL_free(rendererData->uploadBuffers[i]);
|
||||
}
|
||||
SDL_free(rendererData->uploadBuffers);
|
||||
rendererData->uploadBuffers = NULL;
|
||||
}
|
||||
if (rendererData->constantBuffers) {
|
||||
SDL_assert(rendererData->numConstantBuffers);
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
for (uint32_t j = 0; j < rendererData->numConstantBuffers[i]; j++) {
|
||||
VULKAN_DestroyBuffer(rendererData, &rendererData->constantBuffers[i][j]);
|
||||
}
|
||||
SDL_free(rendererData->constantBuffers[i]);
|
||||
}
|
||||
SDL_free(rendererData->constantBuffers);
|
||||
rendererData->constantBuffers = NULL;
|
||||
SDL_free(rendererData->numConstantBuffers);
|
||||
rendererData->numConstantBuffers = NULL;
|
||||
}
|
||||
|
||||
// pick an image count
|
||||
rendererData->swapchainDesiredImageCount = rendererData->surfaceCapabilities.minImageCount + SDL_VULKAN_FRAME_QUEUE_DEPTH;
|
||||
if ((rendererData->swapchainDesiredImageCount > rendererData->surfaceCapabilities.maxImageCount) &&
|
||||
@@ -2217,12 +2300,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
||||
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
if (rendererData->swapchainImageViews) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
vkDestroyImageView(rendererData->device, rendererData->swapchainImageViews[i], NULL);
|
||||
}
|
||||
SDL_free(rendererData->swapchainImageViews);
|
||||
}
|
||||
rendererData->swapchainImageViews = (VkImageView *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkImageView));
|
||||
SDL_free(rendererData->swapchainImageLayouts);
|
||||
rendererData->swapchainImageLayouts = (VkImageLayout *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkImageLayout));
|
||||
@@ -2259,14 +2336,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
|
||||
// Create fences
|
||||
if (rendererData->fences) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
if (rendererData->fences[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyFence(rendererData->device, rendererData->fences[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->fences);
|
||||
}
|
||||
rendererData->fences = (VkFence *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkFence));
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
VkFenceCreateInfo fenceCreateInfo = { 0 };
|
||||
@@ -2281,14 +2350,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
|
||||
// Create renderpasses and framebuffer
|
||||
if (rendererData->framebuffers) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
if (rendererData->framebuffers[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyFramebuffer(rendererData->device, rendererData->framebuffers[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->framebuffers);
|
||||
}
|
||||
for (uint32_t i = 0; i < SDL_arraysize(rendererData->renderPasses); i++) {
|
||||
if (rendererData->renderPasses[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyRenderPass(rendererData->device, rendererData->renderPasses[i], NULL);
|
||||
@@ -2311,19 +2372,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
|
||||
// Create descriptor pools - start by allocating one per swapchain image, let it grow if more are needed
|
||||
if (rendererData->descriptorPools) {
|
||||
SDL_assert(rendererData->numDescriptorPools);
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
for (uint32_t j = 0; j < rendererData->numDescriptorPools[i]; j++) {
|
||||
if (rendererData->descriptorPools[i][j] != VK_NULL_HANDLE) {
|
||||
vkDestroyDescriptorPool(rendererData->device, rendererData->descriptorPools[i][j], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->descriptorPools[i]);
|
||||
}
|
||||
SDL_free(rendererData->descriptorPools);
|
||||
SDL_free(rendererData->numDescriptorPools);
|
||||
}
|
||||
rendererData->descriptorPools = (VkDescriptorPool **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkDescriptorPool*));
|
||||
rendererData->numDescriptorPools = (uint32_t *)SDL_calloc(rendererData->swapchainImageCount, sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
@@ -2338,22 +2386,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
|
||||
// Create semaphores
|
||||
if (rendererData->imageAvailableSemaphores) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
if (rendererData->imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
|
||||
vkDestroySemaphore(rendererData->device, rendererData->imageAvailableSemaphores[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->imageAvailableSemaphores);
|
||||
}
|
||||
if (rendererData->renderingFinishedSemaphores) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
if (rendererData->renderingFinishedSemaphores[i] != VK_NULL_HANDLE) {
|
||||
vkDestroySemaphore(rendererData->device, rendererData->renderingFinishedSemaphores[i], NULL);
|
||||
}
|
||||
}
|
||||
SDL_free(rendererData->renderingFinishedSemaphores);
|
||||
}
|
||||
rendererData->imageAvailableSemaphores = (VkSemaphore *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkSemaphore));
|
||||
rendererData->renderingFinishedSemaphores = (VkSemaphore *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkSemaphore));
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
@@ -2370,15 +2402,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
|
||||
// Upload buffers
|
||||
if (rendererData->uploadBuffers) {
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
for (uint32_t j = 0; j < SDL_VULKAN_NUM_UPLOAD_BUFFERS; j++) {
|
||||
VULKAN_DestroyBuffer(rendererData, &rendererData->uploadBuffers[i][j]);
|
||||
}
|
||||
SDL_free(rendererData->uploadBuffers[i]);
|
||||
}
|
||||
SDL_free(rendererData->uploadBuffers);
|
||||
}
|
||||
rendererData->uploadBuffers = (VULKAN_Buffer **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VULKAN_Buffer*));
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
rendererData->uploadBuffers[i] = (VULKAN_Buffer *)SDL_calloc(SDL_VULKAN_NUM_UPLOAD_BUFFERS, sizeof(VULKAN_Buffer));
|
||||
@@ -2387,18 +2410,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
rendererData->currentUploadBuffer = (int *)SDL_calloc(rendererData->swapchainImageCount, sizeof(int));
|
||||
|
||||
// Constant buffers
|
||||
if (rendererData->constantBuffers) {
|
||||
SDL_assert(rendererData->numConstantBuffers);
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; ++i) {
|
||||
for (uint32_t j = 0; j < rendererData->numConstantBuffers[i]; j++) {
|
||||
VULKAN_DestroyBuffer(rendererData, &rendererData->constantBuffers[i][j]);
|
||||
}
|
||||
SDL_free(rendererData->constantBuffers[i]);
|
||||
}
|
||||
SDL_free(rendererData->constantBuffers);
|
||||
SDL_free(rendererData->numConstantBuffers);
|
||||
rendererData->constantBuffers = NULL;
|
||||
}
|
||||
rendererData->constantBuffers = (VULKAN_Buffer **)SDL_calloc(rendererData->swapchainImageCount, sizeof(VULKAN_Buffer*));
|
||||
rendererData->numConstantBuffers = (uint32_t *)SDL_calloc(rendererData->swapchainImageCount, sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
|
||||
|
||||
@@ -265,6 +265,26 @@ Uint32 SDL_StepUTF8(const char **pstr, size_t *pslen)
|
||||
return result;
|
||||
}
|
||||
|
||||
Uint32 SDL_StepBackUTF8(const char *start, const char **pstr)
|
||||
{
|
||||
if (!pstr || *pstr <= start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Step back over the previous UTF-8 character
|
||||
const char *str = *pstr;
|
||||
do {
|
||||
if (str == start) {
|
||||
break;
|
||||
}
|
||||
--str;
|
||||
} while ((*str & 0xC0) == 0x80);
|
||||
|
||||
size_t length = (*pstr - str);
|
||||
*pstr = str;
|
||||
return StepUTF8(&str, length);
|
||||
}
|
||||
|
||||
#if (SDL_SIZEOF_WCHAR_T == 2)
|
||||
static Uint32 StepUTF16(const Uint16 **_str, const size_t slen)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,11 +41,11 @@
|
||||
|
||||
typedef struct SDL_cond_generic
|
||||
{
|
||||
SDL_Mutex *lock;
|
||||
int waiting;
|
||||
int signals;
|
||||
SDL_Semaphore *wait_sem;
|
||||
SDL_Semaphore *wait_done;
|
||||
SDL_Semaphore *sem;
|
||||
SDL_Semaphore *handshake_sem;
|
||||
SDL_Semaphore *signal_sem;
|
||||
int num_waiting;
|
||||
int num_signals;
|
||||
} SDL_cond_generic;
|
||||
|
||||
// Create a condition variable
|
||||
@@ -55,11 +55,10 @@ SDL_Condition *SDL_CreateCondition_generic(void)
|
||||
|
||||
#ifndef SDL_THREADS_DISABLED
|
||||
if (cond) {
|
||||
cond->lock = SDL_CreateMutex();
|
||||
cond->wait_sem = SDL_CreateSemaphore(0);
|
||||
cond->wait_done = SDL_CreateSemaphore(0);
|
||||
cond->waiting = cond->signals = 0;
|
||||
if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
|
||||
cond->sem = SDL_CreateSemaphore(0);
|
||||
cond->handshake_sem = SDL_CreateSemaphore(0);
|
||||
cond->signal_sem = SDL_CreateSemaphore(1);
|
||||
if (!cond->sem || !cond->handshake_sem || !cond->signal_sem) {
|
||||
SDL_DestroyCondition_generic((SDL_Condition *)cond);
|
||||
cond = NULL;
|
||||
}
|
||||
@@ -74,14 +73,14 @@ void SDL_DestroyCondition_generic(SDL_Condition *_cond)
|
||||
{
|
||||
SDL_cond_generic *cond = (SDL_cond_generic *)_cond;
|
||||
if (cond) {
|
||||
if (cond->wait_sem) {
|
||||
SDL_DestroySemaphore(cond->wait_sem);
|
||||
if (cond->sem) {
|
||||
SDL_DestroySemaphore(cond->sem);
|
||||
}
|
||||
if (cond->wait_done) {
|
||||
SDL_DestroySemaphore(cond->wait_done);
|
||||
if (cond->handshake_sem) {
|
||||
SDL_DestroySemaphore(cond->handshake_sem);
|
||||
}
|
||||
if (cond->lock) {
|
||||
SDL_DestroyMutex(cond->lock);
|
||||
if (cond->signal_sem) {
|
||||
SDL_DestroySemaphore(cond->signal_sem);
|
||||
}
|
||||
SDL_free(cond);
|
||||
}
|
||||
@@ -99,14 +98,14 @@ void SDL_SignalCondition_generic(SDL_Condition *_cond)
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
++cond->signals;
|
||||
SDL_SignalSemaphore(cond->wait_sem);
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_WaitSemaphore(cond->wait_done);
|
||||
SDL_WaitSemaphore(cond->signal_sem);
|
||||
if (cond->num_waiting > cond->num_signals) {
|
||||
cond->num_signals++;
|
||||
SDL_SignalSemaphore(cond->sem);
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
SDL_WaitSemaphore(cond->handshake_sem);
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -123,24 +122,22 @@ void SDL_BroadcastCondition_generic(SDL_Condition *_cond)
|
||||
/* If there are waiting threads not already signalled, then
|
||||
signal the condition and wait for the thread to respond.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->waiting > cond->signals) {
|
||||
int i, num_waiting;
|
||||
|
||||
num_waiting = (cond->waiting - cond->signals);
|
||||
cond->signals = cond->waiting;
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_SignalSemaphore(cond->wait_sem);
|
||||
SDL_WaitSemaphore(cond->signal_sem);
|
||||
if (cond->num_waiting > cond->num_signals) {
|
||||
const int num_waiting = (cond->num_waiting - cond->num_signals);
|
||||
cond->num_signals = cond->num_waiting;
|
||||
for (int i = 0; i < num_waiting; i++) {
|
||||
SDL_SignalSemaphore(cond->sem);
|
||||
}
|
||||
/* Now all released threads are blocked here, waiting for us.
|
||||
Collect them all (and win fabulous prizes!) :-)
|
||||
*/
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
for (i = 0; i < num_waiting; ++i) {
|
||||
SDL_WaitSemaphore(cond->wait_done);
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
for (int i = 0; i < num_waiting; i++) {
|
||||
SDL_WaitSemaphore(cond->handshake_sem);
|
||||
}
|
||||
} else {
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -180,15 +177,15 @@ bool SDL_WaitConditionTimeoutNS_generic(SDL_Condition *_cond, SDL_Mutex *mutex,
|
||||
This allows the signal mechanism to only perform a signal if there
|
||||
are waiting threads.
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
++cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
SDL_WaitSemaphore(cond->signal_sem);
|
||||
cond->num_waiting++;
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
|
||||
// Unlock the mutex, as is required by condition variable semantics
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
// Wait for a signal
|
||||
result = SDL_WaitSemaphoreTimeoutNS(cond->wait_sem, timeoutNS);
|
||||
result = SDL_WaitSemaphoreTimeoutNS(cond->sem, timeoutNS);
|
||||
|
||||
/* Let the signaler know we have completed the wait, otherwise
|
||||
the signaler can race ahead and get the condition semaphore
|
||||
@@ -196,20 +193,13 @@ bool SDL_WaitConditionTimeoutNS_generic(SDL_Condition *_cond, SDL_Mutex *mutex,
|
||||
giving a deadlock. See the following URL for details:
|
||||
http://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
|
||||
*/
|
||||
SDL_LockMutex(cond->lock);
|
||||
if (cond->signals > 0) {
|
||||
// If we timed out, we need to eat a condition signal
|
||||
if (!result) {
|
||||
SDL_WaitSemaphore(cond->wait_sem);
|
||||
}
|
||||
// We always notify the signal thread that we are done
|
||||
SDL_SignalSemaphore(cond->wait_done);
|
||||
|
||||
// Signal handshake complete
|
||||
--cond->signals;
|
||||
SDL_WaitSemaphore(cond->signal_sem);
|
||||
if (cond->num_signals > 0) {
|
||||
SDL_SignalSemaphore(cond->handshake_sem);
|
||||
cond->num_signals--;
|
||||
}
|
||||
--cond->waiting;
|
||||
SDL_UnlockMutex(cond->lock);
|
||||
cond->num_waiting--;
|
||||
SDL_SignalSemaphore(cond->signal_sem);
|
||||
|
||||
// Lock the mutex, as is required by condition variable semantics
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef SDL_PLATFORM_LINUX
|
||||
@@ -55,11 +57,13 @@
|
||||
#include <kernel/OS.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
// List of signals to mask in the subthreads
|
||||
static const int sig_list[] = {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
|
||||
SIGVTALRM, SIGPROF, 0
|
||||
};
|
||||
#endif
|
||||
|
||||
static void *RunThread(void *data)
|
||||
{
|
||||
@@ -117,8 +121,10 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
|
||||
void SDL_SYS_SetupThread(const char *name)
|
||||
{
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
int i;
|
||||
sigset_t mask;
|
||||
#endif
|
||||
|
||||
if (name) {
|
||||
#if (defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_LINUX)) && defined(HAVE_DLOPEN)
|
||||
@@ -154,12 +160,14 @@ void SDL_SYS_SetupThread(const char *name)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
// Mask asynchronous signals for this thread
|
||||
sigemptyset(&mask);
|
||||
for (i = 0; sig_list[i]; ++i) {
|
||||
sigaddset(&mask, sig_list[i]);
|
||||
}
|
||||
pthread_sigmask(SIG_BLOCK, &mask, 0);
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
|
||||
// Allow ourselves to be asynchronously cancelled
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
|
||||
#endif
|
||||
|
||||
#define SDL_DEBUGGER_NAME_EXCEPTION_CODE 0x406D1388
|
||||
|
||||
typedef void (__cdecl * SDL_EndThreadExCallback) (unsigned retval);
|
||||
typedef uintptr_t (__cdecl * SDL_BeginThreadExCallback)
|
||||
(void *security, unsigned stacksize, unsigned (__stdcall *startaddr)(void *),
|
||||
@@ -97,10 +99,13 @@ typedef struct tagTHREADNAME_INFO
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
static LONG NTAPI EmptyVectoredExceptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
static LONG NTAPI EmptyVectoredExceptionHandler(EXCEPTION_POINTERS *info)
|
||||
{
|
||||
(void)ExceptionInfo;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
if (info != NULL && info->ExceptionRecord != NULL && info->ExceptionRecord->ExceptionCode == SDL_DEBUGGER_NAME_EXCEPTION_CODE) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
} else {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}
|
||||
|
||||
typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
|
||||
@@ -148,7 +153,7 @@ void SDL_SYS_SetupThread(const char *name)
|
||||
inf.dwFlags = 0;
|
||||
|
||||
// The debugger catches this, renames the thread, continues on.
|
||||
RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR *)&inf);
|
||||
RaiseException(SDL_DEBUGGER_NAME_EXCEPTION_CODE, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR *)&inf);
|
||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,21 +658,77 @@ void SDL_Delay(Uint32 ms)
|
||||
|
||||
void SDL_DelayNS(Uint64 ns)
|
||||
{
|
||||
Uint64 current_value = SDL_GetTicksNS();
|
||||
Uint64 target_value = current_value + ns;
|
||||
SDL_SYS_DelayNS(ns);
|
||||
}
|
||||
|
||||
// Sleep for a short number of cycles
|
||||
// We'll use 1 ms as a scheduling timeslice, it's a good value for modern operating systems
|
||||
const int SCHEDULING_TIMESLICE_NS = 1 * SDL_NS_PER_MS;
|
||||
while (current_value < target_value) {
|
||||
Uint64 remaining_ns = (target_value - current_value);
|
||||
if (remaining_ns > (SCHEDULING_TIMESLICE_NS + SDL_NS_PER_US)) {
|
||||
// Sleep for a short time, less than the scheduling timeslice
|
||||
SDL_SYS_DelayNS(SCHEDULING_TIMESLICE_NS - SDL_NS_PER_US);
|
||||
} else {
|
||||
// Spin for any remaining time
|
||||
SDL_CPUPauseInstruction();
|
||||
void SDL_DelayPrecise(Uint64 ns)
|
||||
{
|
||||
Uint64 current_value = SDL_GetTicksNS();
|
||||
const Uint64 target_value = current_value + ns;
|
||||
|
||||
// Sleep for a short number of cycles when real sleeps are desired.
|
||||
// We'll use 1 ms, it's the minimum guaranteed to produce real sleeps across
|
||||
// all platforms.
|
||||
const Uint64 SHORT_SLEEP_NS = 1 * SDL_NS_PER_MS;
|
||||
|
||||
// Try to sleep short of target_value. If for some crazy reason
|
||||
// a particular platform sleeps for less than 1 ms when 1 ms was requested,
|
||||
// that's fine, the code below can cope with that, but in practice no
|
||||
// platforms behave that way.
|
||||
Uint64 max_sleep_ns = SHORT_SLEEP_NS;
|
||||
while (current_value + max_sleep_ns < target_value) {
|
||||
// Sleep for a short time
|
||||
SDL_SYS_DelayNS(SHORT_SLEEP_NS);
|
||||
|
||||
const Uint64 now = SDL_GetTicksNS();
|
||||
const Uint64 next_sleep_ns = (now - current_value);
|
||||
if (next_sleep_ns > max_sleep_ns) {
|
||||
max_sleep_ns = next_sleep_ns;
|
||||
}
|
||||
current_value = now;
|
||||
}
|
||||
|
||||
// Do a shorter sleep of the remaining time here, less the max overshoot in
|
||||
// the first loop. Due to maintaining max_sleep_ns as
|
||||
// greater-than-or-equal-to-1 ms, we can always subtract off 1 ms to get
|
||||
// the duration overshot beyond a 1 ms sleep request; if the system never
|
||||
// overshot, great, it's zero duration. By choosing the max overshoot
|
||||
// amount, we're likely to not overshoot here. If the sleep here ends up
|
||||
// functioning like SDL_DelayNS(0) internally, that's fine, we just don't
|
||||
// get to do a more-precise-than-1 ms-resolution sleep to undershoot by a
|
||||
// small amount on the current system, but SDL_DelayNS(0) does at least
|
||||
// introduce a small, yielding delay on many platforms, better than an
|
||||
// unyielding busyloop.
|
||||
//
|
||||
// Note that we'll always do at least one sleep in this function, so the
|
||||
// minimum resolution will be that of SDL_SYS_DelayNS()
|
||||
if (current_value < target_value && (target_value - current_value) > (max_sleep_ns - SHORT_SLEEP_NS)) {
|
||||
const Uint64 delay_ns = (target_value - current_value) - (max_sleep_ns - SHORT_SLEEP_NS);
|
||||
SDL_SYS_DelayNS(delay_ns);
|
||||
current_value = SDL_GetTicksNS();
|
||||
}
|
||||
|
||||
// We've likely undershot target_value at this point by a pretty small
|
||||
// amount, but maybe not. The footgun case if not handled here is where
|
||||
// we've undershot by a large amount, like several ms, but still smaller
|
||||
// than the amount max_sleep_ns overshot by; in such a situation, the above
|
||||
// shorter-sleep block didn't do any delay, the if-block wasn't entered.
|
||||
// Also, maybe the shorter-sleep undershot by several ms, so we still don't
|
||||
// want to spin a lot then. In such a case, we accept the possibility of
|
||||
// overshooting to not spin much, or if overshot here, not at all, keeping
|
||||
// CPU/power usage down in any case. Due to scheduler sloppiness, it's
|
||||
// entirely possible to end up undershooting/overshooting here by much less
|
||||
// than 1 ms even if the current system's sleep function is only 1
|
||||
// ms-resolution, as SDL_GetTicksNS() generally is better resolution than 1
|
||||
// ms on the systems SDL supports.
|
||||
while (current_value + SHORT_SLEEP_NS < target_value) {
|
||||
SDL_SYS_DelayNS(SHORT_SLEEP_NS);
|
||||
current_value = SDL_GetTicksNS();
|
||||
}
|
||||
|
||||
// Spin for any remaining time
|
||||
while (current_value < target_value) {
|
||||
SDL_CPUPauseInstruction();
|
||||
current_value = SDL_GetTicksNS();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
|
||||
#ifdef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||
static void SDL_CleanupWaitableTimer(void *timer)
|
||||
static void SDL_CleanupWaitableHandle(void *handle)
|
||||
{
|
||||
CloseHandle(timer);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
HANDLE SDL_GetWaitableTimer(void)
|
||||
#ifdef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||
static HANDLE SDL_GetWaitableTimer(void)
|
||||
{
|
||||
static SDL_TLSID TLS_timer_handle;
|
||||
HANDLE timer;
|
||||
@@ -40,13 +40,28 @@ HANDLE SDL_GetWaitableTimer(void)
|
||||
if (!timer) {
|
||||
timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
|
||||
if (timer) {
|
||||
SDL_SetTLS(&TLS_timer_handle, timer, SDL_CleanupWaitableTimer);
|
||||
SDL_SetTLS(&TLS_timer_handle, timer, SDL_CleanupWaitableHandle);
|
||||
}
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
#endif // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||
|
||||
static HANDLE SDL_GetWaitableEvent(void)
|
||||
{
|
||||
static SDL_TLSID TLS_event_handle;
|
||||
HANDLE event;
|
||||
|
||||
event = SDL_GetTLS(&TLS_event_handle);
|
||||
if (!event) {
|
||||
event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (event) {
|
||||
SDL_SetTLS(&TLS_event_handle, event, SDL_CleanupWaitableHandle);
|
||||
}
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
Uint64 SDL_GetPerformanceCounter(void)
|
||||
{
|
||||
LARGE_INTEGER counter;
|
||||
@@ -81,22 +96,19 @@ void SDL_SYS_DelayNS(Uint64 ns)
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
const Uint64 max_delay = 0xffffffffLL * SDL_NS_PER_MS;
|
||||
if (ns > max_delay) {
|
||||
ns = max_delay;
|
||||
}
|
||||
|
||||
#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER <= 180030723)
|
||||
static HANDLE mutex = 0;
|
||||
if (!mutex) {
|
||||
mutex = CreateEventEx(0, 0, 0, EVENT_ALL_ACCESS);
|
||||
}
|
||||
WaitForSingleObjectEx(mutex, (DWORD)SDL_NS_TO_MS(ns), FALSE);
|
||||
#else
|
||||
Sleep((DWORD)SDL_NS_TO_MS(ns));
|
||||
#endif
|
||||
const Uint64 max_delay = 0xffffffffLL * SDL_NS_PER_MS;
|
||||
if (ns > max_delay) {
|
||||
ns = max_delay;
|
||||
}
|
||||
const DWORD delay = (DWORD)SDL_NS_TO_MS(ns);
|
||||
|
||||
HANDLE event = SDL_GetWaitableEvent();
|
||||
if (event) {
|
||||
WaitForSingleObjectEx(event, delay, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
Sleep(delay);
|
||||
}
|
||||
|
||||
#endif // SDL_TIMER_WINDOWS
|
||||
|
||||
@@ -1064,7 +1064,7 @@ static bool RLEAlphaSurface(SDL_Surface *surface)
|
||||
return false;
|
||||
}
|
||||
// save the destination format so we can undo the encoding later
|
||||
*(SDL_PixelFormat *)rlebuf = df->format;
|
||||
*(SDL_PixelFormat *)rlebuf = dest->format;
|
||||
dst = rlebuf + sizeof(SDL_PixelFormat);
|
||||
|
||||
// Do the actual encoding
|
||||
@@ -1232,6 +1232,7 @@ static const getpix_func getpixes[4] = {
|
||||
|
||||
static bool RLEColorkeySurface(SDL_Surface *surface)
|
||||
{
|
||||
SDL_Surface *dest;
|
||||
Uint8 *rlebuf, *dst;
|
||||
int maxn;
|
||||
int y;
|
||||
@@ -1242,6 +1243,11 @@ static bool RLEColorkeySurface(SDL_Surface *surface)
|
||||
Uint32 ckey, rgbmask;
|
||||
int w, h;
|
||||
|
||||
dest = surface->map.info.dst_surface;
|
||||
if (!dest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate the worst case size for the compressed surface
|
||||
switch (bpp) {
|
||||
case 1:
|
||||
@@ -1263,15 +1269,18 @@ static bool RLEColorkeySurface(SDL_Surface *surface)
|
||||
return false;
|
||||
}
|
||||
|
||||
maxsize += sizeof(SDL_PixelFormat);
|
||||
rlebuf = (Uint8 *)SDL_malloc(maxsize);
|
||||
if (!rlebuf) {
|
||||
return false;
|
||||
}
|
||||
// save the destination format so we can undo the encoding later
|
||||
*(SDL_PixelFormat *)rlebuf = dest->format;
|
||||
|
||||
// Set up the conversion
|
||||
srcbuf = (Uint8 *)surface->pixels;
|
||||
maxn = bpp == 4 ? 65535 : 255;
|
||||
dst = rlebuf;
|
||||
dst = rlebuf + sizeof(SDL_PixelFormat);
|
||||
rgbmask = ~surface->fmt->Amask;
|
||||
ckey = surface->map.info.colorkey & rgbmask;
|
||||
lastline = dst;
|
||||
|
||||
@@ -610,6 +610,15 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
#else
|
||||
#define USE_DUFFS_LOOP
|
||||
#endif
|
||||
|
||||
#define DUFFS_LOOP1(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n; \
|
||||
for (n = width; n > 0; --n) { \
|
||||
pixel_copy_increment; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
|
||||
// 8-times unrolled loop
|
||||
@@ -666,8 +675,26 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
} \
|
||||
}
|
||||
|
||||
// Use the 8-times version of the loop by default
|
||||
// 2-times unrolled loop
|
||||
#define DUFFS_LOOP2(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n = (width + 1) / 2; \
|
||||
switch (width & 1) { \
|
||||
case 0: \
|
||||
do { \
|
||||
pixel_copy_increment; \
|
||||
SDL_FALLTHROUGH; \
|
||||
case 1: \
|
||||
pixel_copy_increment; \
|
||||
} while (--n > 0); \
|
||||
} \
|
||||
}
|
||||
|
||||
// Use the 4-times version of the loop by default
|
||||
#define DUFFS_LOOP(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP4(pixel_copy_increment, width)
|
||||
// Use the 8-times version of the loop for simple routines
|
||||
#define DUFFS_LOOP_TRIVIAL(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP8(pixel_copy_increment, width)
|
||||
|
||||
// Special version of Duff's device for even more optimization
|
||||
@@ -701,20 +728,19 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
|
||||
// Don't use Duff's device to unroll loops
|
||||
#define DUFFS_LOOP(pixel_copy_increment, width) \
|
||||
{ \
|
||||
int n; \
|
||||
for (n = width; n > 0; --n) { \
|
||||
pixel_copy_increment; \
|
||||
} \
|
||||
}
|
||||
DUFFS_LOOP1(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP_TRIVIAL(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP1(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP8(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment, width)
|
||||
DUFFS_LOOP1(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP4(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment, width)
|
||||
DUFFS_LOOP1(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP2(pixel_copy_increment, width) \
|
||||
DUFFS_LOOP1(pixel_copy_increment, width)
|
||||
#define DUFFS_LOOP_124(pixel_copy_increment1, \
|
||||
pixel_copy_increment2, \
|
||||
pixel_copy_increment4, width) \
|
||||
DUFFS_LOOP(pixel_copy_increment1, width)
|
||||
DUFFS_LOOP1(pixel_copy_increment1, width)
|
||||
|
||||
#endif // USE_DUFFS_LOOP
|
||||
|
||||
|
||||
@@ -604,11 +604,8 @@ SDL_FORCE_INLINE void BlitBto4Key(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_FORCE_INLINE void BlitBtoNAlpha(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
static void BlitBtoNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
const Uint32 mask = (1 << srcbpp) - 1;
|
||||
const Uint32 align = (8 / srcbpp) - 1;
|
||||
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
@@ -616,15 +613,17 @@ SDL_FORCE_INLINE void BlitBtoNAlpha(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
const SDL_Color *srcpal = info->src_pal->colors;
|
||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||
int dstbpp;
|
||||
int srcbpp, dstbpp;
|
||||
int c;
|
||||
Uint32 pixel;
|
||||
Uint32 pixel, mask, align;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
|
||||
// Set up some basic variables
|
||||
srcbpp = srcfmt->bytes_per_pixel;
|
||||
dstbpp = dstfmt->bytes_per_pixel;
|
||||
if (srcbpp == 4)
|
||||
srcskip += width - (width + 1) / 2;
|
||||
@@ -632,6 +631,8 @@ SDL_FORCE_INLINE void BlitBtoNAlpha(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
srcskip += width - (width + 3) / 4;
|
||||
else if (srcbpp == 1)
|
||||
srcskip += width - (width + 7) / 8;
|
||||
mask = (1 << srcbpp) - 1;
|
||||
align = (8 / srcbpp) - 1;
|
||||
|
||||
if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
|
||||
while (height--) {
|
||||
@@ -680,28 +681,27 @@ SDL_FORCE_INLINE void BlitBtoNAlpha(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_FORCE_INLINE void BlitBtoNAlphaKey(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
static void BlitBtoNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
const Uint32 mask = (1 << srcbpp) - 1;
|
||||
const Uint32 align = (8 / srcbpp) - 1;
|
||||
|
||||
int width = info->dst_w;
|
||||
int height = info->dst_h;
|
||||
Uint8 *src = info->src;
|
||||
Uint8 *dst = info->dst;
|
||||
int srcskip = info->src_skip;
|
||||
int dstskip = info->dst_skip;
|
||||
const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
|
||||
const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
|
||||
const SDL_Color *srcpal = info->src_pal->colors;
|
||||
int dstbpp;
|
||||
int srcbpp, dstbpp;
|
||||
int c;
|
||||
Uint32 pixel;
|
||||
Uint32 pixel, mask, align;
|
||||
unsigned sR, sG, sB;
|
||||
unsigned dR, dG, dB, dA;
|
||||
const unsigned A = info->a;
|
||||
Uint32 ckey = info->colorkey;
|
||||
|
||||
// Set up some basic variables
|
||||
srcbpp = srcfmt->bytes_per_pixel;
|
||||
dstbpp = dstfmt->bytes_per_pixel;
|
||||
if (srcbpp == 4)
|
||||
srcskip += width - (width + 1) / 2;
|
||||
@@ -709,6 +709,8 @@ SDL_FORCE_INLINE void BlitBtoNAlphaKey(SDL_BlitInfo *info, const Uint32 srcbpp)
|
||||
srcskip += width - (width + 3) / 4;
|
||||
else if (srcbpp == 1)
|
||||
srcskip += width - (width + 7) / 8;
|
||||
mask = (1 << srcbpp) - 1;
|
||||
align = (8 / srcbpp) - 1;
|
||||
|
||||
if (SDL_PIXELORDER(info->src_fmt->format) == SDL_BITMAPORDER_4321) {
|
||||
while (height--) {
|
||||
@@ -799,16 +801,6 @@ static const SDL_BlitFunc colorkey_blit_1b[] = {
|
||||
(SDL_BlitFunc)NULL, Blit1bto1Key, Blit1bto2Key, Blit1bto3Key, Blit1bto4Key
|
||||
};
|
||||
|
||||
static void Blit1btoNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlpha(info, 1);
|
||||
}
|
||||
|
||||
static void Blit1btoNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlphaKey(info, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Blit2bto1(SDL_BlitInfo *info) {
|
||||
@@ -851,16 +843,6 @@ static const SDL_BlitFunc colorkey_blit_2b[] = {
|
||||
(SDL_BlitFunc)NULL, Blit2bto1Key, Blit2bto2Key, Blit2bto3Key, Blit2bto4Key
|
||||
};
|
||||
|
||||
static void Blit2btoNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlpha(info, 2);
|
||||
}
|
||||
|
||||
static void Blit2btoNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlphaKey(info, 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Blit4bto1(SDL_BlitInfo *info) {
|
||||
@@ -903,16 +885,6 @@ static const SDL_BlitFunc colorkey_blit_4b[] = {
|
||||
(SDL_BlitFunc)NULL, Blit4bto1Key, Blit4bto2Key, Blit4bto3Key, Blit4bto4Key
|
||||
};
|
||||
|
||||
static void Blit4btoNAlpha(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlpha(info, 4);
|
||||
}
|
||||
|
||||
static void Blit4btoNAlphaKey(SDL_BlitInfo *info)
|
||||
{
|
||||
BlitBtoNAlphaKey(info, 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface)
|
||||
@@ -940,10 +912,10 @@ SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface)
|
||||
break;
|
||||
|
||||
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit1btoNAlpha : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit1btoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -963,10 +935,10 @@ SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface)
|
||||
break;
|
||||
|
||||
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit2btoNAlpha : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit2btoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -986,10 +958,10 @@ SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface *surface)
|
||||
break;
|
||||
|
||||
case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit4btoNAlpha : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlpha : (SDL_BlitFunc)NULL;
|
||||
|
||||
case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
|
||||
return which >= 2 ? Blit4btoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
return which >= 2 ? BlitBtoNAlphaKey : (SDL_BlitFunc)NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ static void Blit1to1(SDL_BlitInfo *info)
|
||||
while (height--) {
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
*dst = map[*src];
|
||||
}
|
||||
@@ -100,7 +100,7 @@ static void Blit1to2(SDL_BlitInfo *info)
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
*(Uint16 *)dst = map[*src++];
|
||||
dst += 2;
|
||||
@@ -256,7 +256,7 @@ static void Blit1to4(SDL_BlitInfo *info)
|
||||
while (height--) {
|
||||
#ifdef USE_DUFFS_LOOP
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
*dst++ = map[*src++];
|
||||
, width);
|
||||
/* *INDENT-ON* */ // clang-format on
|
||||
@@ -297,7 +297,7 @@ static void Blit1to1Key(SDL_BlitInfo *info)
|
||||
if (palmap) {
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dst = palmap[*src];
|
||||
@@ -313,7 +313,7 @@ static void Blit1to1Key(SDL_BlitInfo *info)
|
||||
} else {
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dst = *src;
|
||||
@@ -345,7 +345,7 @@ static void Blit1to2Key(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dstp=palmap[*src];
|
||||
@@ -408,7 +408,7 @@ static void Blit1to4Key(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ( *src != ckey ) {
|
||||
*dstp = palmap[*src];
|
||||
@@ -444,7 +444,7 @@ static void Blit1toNAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
sR = srcpal[*src].r;
|
||||
sG = srcpal[*src].g;
|
||||
|
||||
@@ -46,7 +46,7 @@ static void BlitNto1SurfaceAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB);
|
||||
dR = dstpal[*dst].r;
|
||||
@@ -91,7 +91,7 @@ static void BlitNto1PixelAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
DISEMBLE_RGBA(src,srcbpp,srcfmt,Pixel,sR,sG,sB,sA);
|
||||
dR = dstpal[*dst].r;
|
||||
@@ -253,7 +253,7 @@ static void BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
Uint32 s = *srcp++;
|
||||
Uint32 d = *dstp;
|
||||
*dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1)
|
||||
@@ -283,7 +283,7 @@ static void BlitRGBtoRGBSurfaceAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
s = *srcp;
|
||||
d = *dstp;
|
||||
|
||||
@@ -705,7 +705,7 @@ static void Blit565to565SurfaceAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
Uint32 s = *srcp++;
|
||||
Uint32 d = *dstp;
|
||||
/*
|
||||
@@ -743,7 +743,7 @@ static void Blit555to555SurfaceAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
Uint32 s = *srcp++;
|
||||
Uint32 d = *dstp;
|
||||
/*
|
||||
@@ -776,7 +776,7 @@ static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
Uint32 s = *srcp;
|
||||
unsigned alpha = s >> 27; // downscale alpha to 5 bits
|
||||
/* Here we special-case opaque alpha since the
|
||||
@@ -819,7 +819,7 @@ static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4({
|
||||
DUFFS_LOOP({
|
||||
unsigned alpha;
|
||||
Uint32 s = *srcp;
|
||||
alpha = s >> 27; // downscale alpha to 5 bits
|
||||
@@ -872,7 +872,7 @@ static void BlitNtoNSurfaceAlpha(SDL_BlitInfo *info)
|
||||
if (sA) {
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB);
|
||||
DISEMBLE_RGBA(dst, dstbpp, dstfmt, Pixel, dR, dG, dB, dA);
|
||||
@@ -910,7 +910,7 @@ static void BlitNtoNSurfaceAlphaKey(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel);
|
||||
if (sA && Pixel != ckey) {
|
||||
@@ -1302,7 +1302,7 @@ static void BlitNtoNPixelAlpha(SDL_BlitInfo *info)
|
||||
dstbpp = dstfmt->bytes_per_pixel;
|
||||
|
||||
while (height--) {
|
||||
DUFFS_LOOP4(
|
||||
DUFFS_LOOP(
|
||||
{
|
||||
DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA);
|
||||
if (sA) {
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#define BLIT_FEATURE_HAS_MMX 0x01
|
||||
#define BLIT_FEATURE_HAS_ALTIVEC 0x02
|
||||
#define BLIT_FEATURE_ALTIVEC_DONT_USE_PREFETCH 0x04
|
||||
#define BLIT_FEATURE_HAS_ARM_SIMD 0x08
|
||||
|
||||
#ifdef SDL_ALTIVEC_BLITTERS
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
@@ -891,37 +890,7 @@ static Uint32 GetBlitFeatures(void)
|
||||
#endif
|
||||
#else
|
||||
// Feature 1 is has-MMX
|
||||
#define GetBlitFeatures() ((SDL_HasMMX() ? BLIT_FEATURE_HAS_MMX : 0) | (SDL_HasARMSIMD() ? BLIT_FEATURE_HAS_ARM_SIMD : 0))
|
||||
#endif
|
||||
|
||||
#ifdef SDL_ARM_SIMD_BLITTERS
|
||||
void Blit_XBGR8888_XRGB8888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint32_t *src, int32_t src_stride);
|
||||
|
||||
static void Blit_XBGR8888_XRGB8888ARMSIMD(SDL_BlitInfo *info)
|
||||
{
|
||||
int32_t width = info->dst_w;
|
||||
int32_t height = info->dst_h;
|
||||
uint32_t *dstp = (uint32_t *)info->dst;
|
||||
int32_t dststride = width + (info->dst_skip >> 2);
|
||||
uint32_t *srcp = (uint32_t *)info->src;
|
||||
int32_t srcstride = width + (info->src_skip >> 2);
|
||||
|
||||
Blit_XBGR8888_XRGB8888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
|
||||
}
|
||||
|
||||
void Blit_RGB444_XRGB8888ARMSIMDAsm(int32_t w, int32_t h, uint32_t *dst, int32_t dst_stride, uint16_t *src, int32_t src_stride);
|
||||
|
||||
static void Blit_RGB444_XRGB8888ARMSIMD(SDL_BlitInfo *info)
|
||||
{
|
||||
int32_t width = info->dst_w;
|
||||
int32_t height = info->dst_h;
|
||||
uint32_t *dstp = (uint32_t *)info->dst;
|
||||
int32_t dststride = width + (info->dst_skip >> 2);
|
||||
uint16_t *srcp = (uint16_t *)info->src;
|
||||
int32_t srcstride = width + (info->src_skip >> 1);
|
||||
|
||||
Blit_RGB444_XRGB8888ARMSIMDAsm(width, height, dstp, dststride, srcp, srcstride);
|
||||
}
|
||||
#define GetBlitFeatures() ((SDL_HasMMX() ? BLIT_FEATURE_HAS_MMX : 0))
|
||||
#endif
|
||||
|
||||
// This is now endian dependent
|
||||
@@ -1831,7 +1800,7 @@ static void Blit_RGB555_ARGB1555(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
*dst = *src | mask;
|
||||
++dst;
|
||||
@@ -1862,7 +1831,7 @@ static void Blit4to4MaskAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
*dst = *src | mask;
|
||||
++dst;
|
||||
@@ -1879,7 +1848,7 @@ static void Blit4to4MaskAlpha(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
*dst = *src & mask;
|
||||
++dst;
|
||||
@@ -2173,7 +2142,7 @@ static void Blit2to2Key(SDL_BlitInfo *info)
|
||||
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ( (*srcp & rgbmask) != ckey ) {
|
||||
*dstp = *srcp;
|
||||
@@ -2219,7 +2188,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info)
|
||||
Uint32 mask = ((Uint32)info->a) << dstfmt->Ashift;
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ((*src32 & rgbmask) != ckey) {
|
||||
*dst32 = *src32 | mask;
|
||||
@@ -2237,7 +2206,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info)
|
||||
Uint32 mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask;
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ((*src32 & rgbmask) != ckey) {
|
||||
*dst32 = *src32 & mask;
|
||||
@@ -2494,7 +2463,7 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
|
||||
Uint32 *dst32 = (Uint32 *)dst;
|
||||
while (height--) {
|
||||
/* *INDENT-OFF* */ // clang-format off
|
||||
DUFFS_LOOP(
|
||||
DUFFS_LOOP_TRIVIAL(
|
||||
{
|
||||
if ((*src32 & rgbmask) != ckey) {
|
||||
*dst32 = *src32;
|
||||
@@ -2825,10 +2794,6 @@ static const struct blit_table normal_blit_2[] = {
|
||||
{ 0x00007C00, 0x000003E0, 0x0000001F, 4, 0x00000000, 0x00000000, 0x00000000,
|
||||
BLIT_FEATURE_HAS_ALTIVEC, Blit_RGB555_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA },
|
||||
#endif
|
||||
#ifdef SDL_ARM_SIMD_BLITTERS
|
||||
{ 0x00000F00, 0x000000F0, 0x0000000F, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
|
||||
BLIT_FEATURE_HAS_ARM_SIMD, Blit_RGB444_XRGB8888ARMSIMD, NO_ALPHA | COPY_ALPHA },
|
||||
#endif
|
||||
#if SDL_HAVE_BLIT_N_RGB565
|
||||
{ 0x0000F800, 0x000007E0, 0x0000001F, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
|
||||
0, Blit_RGB565_ARGB8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA },
|
||||
@@ -2895,10 +2860,6 @@ static const struct blit_table normal_blit_4[] = {
|
||||
// has-altivec
|
||||
{ 0x00000000, 0x00000000, 0x00000000, 2, 0x0000F800, 0x000007E0, 0x0000001F,
|
||||
BLIT_FEATURE_HAS_ALTIVEC, Blit_XRGB8888_RGB565Altivec, NO_ALPHA },
|
||||
#endif
|
||||
#ifdef SDL_ARM_SIMD_BLITTERS
|
||||
{ 0x000000FF, 0x0000FF00, 0x00FF0000, 4, 0x00FF0000, 0x0000FF00, 0x000000FF,
|
||||
BLIT_FEATURE_HAS_ARM_SIMD, Blit_XBGR8888_XRGB8888ARMSIMD, NO_ALPHA | COPY_ALPHA },
|
||||
#endif
|
||||
// 4->3 with same rgb triplet
|
||||
{ 0x000000FF, 0x0000FF00, 0x00FF0000, 3, 0x000000FF, 0x0000FF00, 0x00FF0000,
|
||||
|
||||
@@ -589,7 +589,11 @@ done:
|
||||
|
||||
SDL_Surface *SDL_LoadBMP(const char *file)
|
||||
{
|
||||
return SDL_LoadBMP_IO(SDL_IOFromFile(file, "rb"), 1);
|
||||
SDL_IOStream *stream = SDL_IOFromFile(file, "rb");
|
||||
if (!stream) {
|
||||
return NULL;
|
||||
}
|
||||
return SDL_LoadBMP_IO(stream, true);
|
||||
}
|
||||
|
||||
bool SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
|
||||
@@ -597,7 +601,7 @@ bool SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
|
||||
bool was_error = true;
|
||||
Sint64 fp_offset, new_offset;
|
||||
int i, pad;
|
||||
SDL_Surface *intermediate_surface;
|
||||
SDL_Surface *intermediate_surface = NULL;
|
||||
Uint8 *bits;
|
||||
bool save32bit = false;
|
||||
bool saveLegacyBMP = false;
|
||||
@@ -634,63 +638,60 @@ bool SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio)
|
||||
Uint32 bV4GammaBlue = 0;
|
||||
|
||||
// Make sure we have somewhere to save
|
||||
intermediate_surface = NULL;
|
||||
if (dst) {
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
SDL_InvalidParamError("surface");
|
||||
goto done;
|
||||
}
|
||||
if (!SDL_SurfaceValid(surface)) {
|
||||
SDL_InvalidParamError("surface");
|
||||
goto done;
|
||||
}
|
||||
if (!dst) {
|
||||
SDL_InvalidParamError("dst");
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef SAVE_32BIT_BMP
|
||||
// We can save alpha information in a 32-bit BMP
|
||||
if (SDL_BITSPERPIXEL(surface->format) >= 8 &&
|
||||
(SDL_ISPIXELFORMAT_ALPHA(surface->format) ||
|
||||
surface->map.info.flags & SDL_COPY_COLORKEY)) {
|
||||
save32bit = true;
|
||||
}
|
||||
// We can save alpha information in a 32-bit BMP
|
||||
if (SDL_BITSPERPIXEL(surface->format) >= 8 &&
|
||||
(SDL_ISPIXELFORMAT_ALPHA(surface->format) ||
|
||||
surface->map.info.flags & SDL_COPY_COLORKEY)) {
|
||||
save32bit = true;
|
||||
}
|
||||
#endif // SAVE_32BIT_BMP
|
||||
|
||||
if (surface->palette && !save32bit) {
|
||||
if (SDL_BITSPERPIXEL(surface->format) == 8) {
|
||||
intermediate_surface = surface;
|
||||
} else {
|
||||
SDL_SetError("%u bpp BMP files not supported",
|
||||
SDL_BITSPERPIXEL(surface->format));
|
||||
goto done;
|
||||
}
|
||||
} else if ((SDL_BITSPERPIXEL(surface->format) == 24) && !save32bit &&
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
(surface->fmt->Rmask == 0x00FF0000) &&
|
||||
(surface->fmt->Gmask == 0x0000FF00) &&
|
||||
(surface->fmt->Bmask == 0x000000FF)
|
||||
#else
|
||||
(surface->fmt->Rmask == 0x000000FF) &&
|
||||
(surface->fmt->Gmask == 0x0000FF00) &&
|
||||
(surface->fmt->Bmask == 0x00FF0000)
|
||||
#endif
|
||||
) {
|
||||
if (surface->palette && !save32bit) {
|
||||
if (SDL_BITSPERPIXEL(surface->format) == 8) {
|
||||
intermediate_surface = surface;
|
||||
} else {
|
||||
SDL_PixelFormat pixel_format;
|
||||
|
||||
/* If the surface has a colorkey or alpha channel we'll save a
|
||||
32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
|
||||
if (save32bit) {
|
||||
pixel_format = SDL_PIXELFORMAT_BGRA32;
|
||||
} else {
|
||||
pixel_format = SDL_PIXELFORMAT_BGR24;
|
||||
}
|
||||
intermediate_surface = SDL_ConvertSurface(surface, pixel_format);
|
||||
if (!intermediate_surface) {
|
||||
SDL_SetError("Couldn't convert image to %d bpp",
|
||||
(int)SDL_BITSPERPIXEL(pixel_format));
|
||||
goto done;
|
||||
}
|
||||
SDL_SetError("%u bpp BMP files not supported",
|
||||
SDL_BITSPERPIXEL(surface->format));
|
||||
goto done;
|
||||
}
|
||||
} else if ((SDL_BITSPERPIXEL(surface->format) == 24) && !save32bit &&
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
(surface->fmt->Rmask == 0x00FF0000) &&
|
||||
(surface->fmt->Gmask == 0x0000FF00) &&
|
||||
(surface->fmt->Bmask == 0x000000FF)
|
||||
#else
|
||||
(surface->fmt->Rmask == 0x000000FF) &&
|
||||
(surface->fmt->Gmask == 0x0000FF00) &&
|
||||
(surface->fmt->Bmask == 0x00FF0000)
|
||||
#endif
|
||||
) {
|
||||
intermediate_surface = surface;
|
||||
} else {
|
||||
/* Set no error here because it may overwrite a more useful message from
|
||||
SDL_IOFromFile() if SDL_SaveBMP_IO() is called from SDL_SaveBMP(). */
|
||||
goto done;
|
||||
SDL_PixelFormat pixel_format;
|
||||
|
||||
/* If the surface has a colorkey or alpha channel we'll save a
|
||||
32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
|
||||
if (save32bit) {
|
||||
pixel_format = SDL_PIXELFORMAT_BGRA32;
|
||||
} else {
|
||||
pixel_format = SDL_PIXELFORMAT_BGR24;
|
||||
}
|
||||
intermediate_surface = SDL_ConvertSurface(surface, pixel_format);
|
||||
if (!intermediate_surface) {
|
||||
SDL_SetError("Couldn't convert image to %d bpp",
|
||||
(int)SDL_BITSPERPIXEL(pixel_format));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (save32bit) {
|
||||
@@ -873,5 +874,9 @@ done:
|
||||
|
||||
bool SDL_SaveBMP(SDL_Surface *surface, const char *file)
|
||||
{
|
||||
return SDL_SaveBMP_IO(surface, SDL_IOFromFile(file, "wb"), true);
|
||||
SDL_IOStream *stream = SDL_IOFromFile(file, "wb");
|
||||
if (!stream) {
|
||||
return false;
|
||||
}
|
||||
return SDL_SaveBMP_IO(surface, stream, true);
|
||||
}
|
||||
|
||||
@@ -196,9 +196,13 @@ void *SDL_GetClipboardData(const char *mime_type, size_t *size)
|
||||
return _this->GetClipboardData(_this, mime_type, size);
|
||||
} else if (_this->GetClipboardText && SDL_IsTextMimeType(mime_type)) {
|
||||
char *text = _this->GetClipboardText(_this);
|
||||
if (text && *text == '\0') {
|
||||
SDL_free(text);
|
||||
text = NULL;
|
||||
if (text) {
|
||||
if (*text == '\0') {
|
||||
SDL_free(text);
|
||||
text = NULL;
|
||||
} else {
|
||||
*size = SDL_strlen(text);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
} else {
|
||||
|
||||
@@ -300,7 +300,9 @@ void SDL_EGL_UnloadLibrary(SDL_VideoDevice *_this)
|
||||
static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_path)
|
||||
{
|
||||
SDL_SharedObject *egl_dll_handle = NULL;
|
||||
#if !defined(SDL_VIDEO_STATIC_ANGLE) && !defined(SDL_VIDEO_DRIVER_VITA)
|
||||
SDL_SharedObject *opengl_dll_handle = NULL;
|
||||
#endif
|
||||
const char *path = NULL;
|
||||
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
|
||||
const char *d3dcompiler;
|
||||
@@ -426,9 +428,6 @@ static bool SDL_EGL_LoadLibraryInternal(SDL_VideoDevice *_this, const char *egl_
|
||||
#endif
|
||||
|
||||
_this->egl_data->egl_dll_handle = egl_dll_handle;
|
||||
#ifdef SDL_VIDEO_DRIVER_VITA
|
||||
_this->egl_data->opengl_dll_handle = opengl_dll_handle;
|
||||
#endif
|
||||
|
||||
// Load new function pointers
|
||||
LOAD_FUNC(PFNEGLGETDISPLAYPROC, eglGetDisplay);
|
||||
|
||||
@@ -772,9 +772,9 @@ static const float mat_BT601_Limited_8bit[] = {
|
||||
|
||||
static const float mat_BT601_Full_8bit[] = {
|
||||
0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset
|
||||
1.0000f, 0.0000f, 1.4020f, 0.0f, // Rcoeff
|
||||
1.0000f, -0.3441f, -0.7141f, 0.0f, // Gcoeff
|
||||
1.0000f, 1.7720f, 0.0000f, 0.0f, // Bcoeff
|
||||
1.0000f, 0.0000f, 1.4075f, 0.0f, // Rcoeff
|
||||
1.0000f, -0.3455f, -0.7169f, 0.0f, // Gcoeff
|
||||
1.0000f, 1.7790f, 0.0000f, 0.0f, // Bcoeff
|
||||
};
|
||||
|
||||
static const float mat_BT709_Limited_8bit[] = {
|
||||
@@ -786,9 +786,9 @@ static const float mat_BT709_Limited_8bit[] = {
|
||||
|
||||
static const float mat_BT709_Full_8bit[] = {
|
||||
0.0f, -0.501960814f, -0.501960814f, 0.0f, // offset
|
||||
1.0000f, 0.0000f, 1.5748f, 0.0f, // Rcoeff
|
||||
1.0000f, -0.1873f, -0.4681f, 0.0f, // Gcoeff
|
||||
1.0000f, 1.8556f, 0.0000f, 0.0f, // Bcoeff
|
||||
1.0000f, 0.0000f, 1.5810f, 0.0f, // Rcoeff
|
||||
1.0000f, -0.1881f, -0.4700f, 0.0f, // Gcoeff
|
||||
1.0000f, 1.8629f, 0.0000f, 0.0f, // Bcoeff
|
||||
};
|
||||
|
||||
static const float mat_BT2020_Limited_10bit[] = {
|
||||
|
||||
@@ -297,12 +297,12 @@ static int COMPUTEOUTCODE(const RECTTYPE *rect, SCALARTYPE x, SCALARTYPE y)
|
||||
int code = 0;
|
||||
if (y < rect->y) {
|
||||
code |= CODE_TOP;
|
||||
} else if (y >= rect->y + rect->h) {
|
||||
} else if (y > (rect->y + rect->h - ENCLOSEPOINTS_EPSILON)) {
|
||||
code |= CODE_BOTTOM;
|
||||
}
|
||||
if (x < rect->x) {
|
||||
code |= CODE_LEFT;
|
||||
} else if (x >= rect->x + rect->w) {
|
||||
} else if (x > (rect->x + rect->w - ENCLOSEPOINTS_EPSILON)) {
|
||||
code |= CODE_RIGHT;
|
||||
}
|
||||
return code;
|
||||
|
||||
@@ -1786,6 +1786,9 @@ static bool SDL_FlipSurfaceHorizontal(SDL_Surface *surface)
|
||||
bpp = SDL_BYTESPERPIXEL(surface->format);
|
||||
row = (Uint8 *)surface->pixels;
|
||||
tmp = SDL_small_alloc(Uint8, surface->pitch, &isstack);
|
||||
if (!tmp) {
|
||||
return false;
|
||||
}
|
||||
for (i = surface->h; i--; ) {
|
||||
a = row;
|
||||
b = a + (surface->w - 1) * bpp;
|
||||
@@ -1815,6 +1818,9 @@ static bool SDL_FlipSurfaceVertical(SDL_Surface *surface)
|
||||
a = (Uint8 *)surface->pixels;
|
||||
b = a + (surface->h - 1) * surface->pitch;
|
||||
tmp = SDL_small_alloc(Uint8, surface->pitch, &isstack);
|
||||
if (!tmp) {
|
||||
return false;
|
||||
}
|
||||
for (i = surface->h / 2; i--; ) {
|
||||
SDL_memcpy(tmp, a, surface->pitch);
|
||||
SDL_memcpy(a, b, surface->pitch);
|
||||
|
||||
@@ -498,6 +498,7 @@ typedef struct VideoBootStrap
|
||||
} VideoBootStrap;
|
||||
|
||||
// Not all of these are available in a given build. Use #ifdefs, etc.
|
||||
extern VideoBootStrap PRIVATE_bootstrap;
|
||||
extern VideoBootStrap COCOA_bootstrap;
|
||||
extern VideoBootStrap X11_bootstrap;
|
||||
extern VideoBootStrap WINDOWS_bootstrap;
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDL_PLATFORM_3DS
|
||||
#include <3ds.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDL_PLATFORM_LINUX
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -67,6 +71,9 @@
|
||||
|
||||
// Available video drivers
|
||||
static VideoBootStrap *bootstrap[] = {
|
||||
#ifdef SDL_VIDEO_DRIVER_PRIVATE
|
||||
&PRIVATE_bootstrap,
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_DRIVER_COCOA
|
||||
&COCOA_bootstrap,
|
||||
#endif
|
||||
@@ -258,7 +265,7 @@ typedef struct
|
||||
|
||||
static Uint32 SDL_DefaultGraphicsBackends(SDL_VideoDevice *_this)
|
||||
{
|
||||
#if (defined(SDL_VIDEO_OPENGL) && defined(SDL_PLATFORM_MACOS)) || (defined(SDL_PLATFORM_IOS) && !TARGET_OS_MACCATALYST) || defined(SDL_PLATFORM_ANDROID)
|
||||
#if (defined(SDL_VIDEO_OPENGL) && defined(SDL_PLATFORM_MACOS)) || (defined(SDL_PLATFORM_IOS) && !TARGET_OS_MACCATALYST)
|
||||
if (_this->GL_CreateContext) {
|
||||
return SDL_WINDOW_OPENGL;
|
||||
}
|
||||
@@ -5518,6 +5525,23 @@ bool SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char *title, cons
|
||||
},
|
||||
title, message);
|
||||
return true;
|
||||
#elif defined(SDL_PLATFORM_3DS)
|
||||
errorConf errCnf;
|
||||
bool hasGpuRight;
|
||||
|
||||
// If the video subsystem has not been initialised, set up graphics temporarily
|
||||
hasGpuRight = gspHasGpuRight();
|
||||
if (!hasGpuRight)
|
||||
gfxInitDefault();
|
||||
|
||||
errorInit(&errCnf, ERROR_TEXT_WORD_WRAP, CFG_LANGUAGE_EN);
|
||||
errorText(&errCnf, message);
|
||||
errorDisp(&errCnf);
|
||||
|
||||
if (!hasGpuRight)
|
||||
gfxExit();
|
||||
|
||||
return true;
|
||||
#else
|
||||
SDL_MessageBoxData data;
|
||||
SDL_MessageBoxButtonData button;
|
||||
|
||||
@@ -171,8 +171,10 @@ static bool GetYUVConversionType(SDL_Colorspace colorspace, YCbCrType *yuv_type)
|
||||
if (SDL_ISCOLORSPACE_MATRIX_BT709(colorspace)) {
|
||||
if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
|
||||
*yuv_type = YCBCR_709_LIMITED;
|
||||
return true;
|
||||
} else {
|
||||
*yuv_type = YCBCR_709_FULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (SDL_ISCOLORSPACE_MATRIX_BT2020_NCL(colorspace)) {
|
||||
@@ -691,6 +693,13 @@ static struct RGB2YUVFactors RGB2YUVFactorTables[] = {
|
||||
{ -0.1482f, -0.2910f, 0.4392f },
|
||||
{ 0.4392f, -0.3678f, -0.0714f },
|
||||
},
|
||||
// ITU-R BT.709-6 full range
|
||||
{
|
||||
0,
|
||||
{ 0.2126f, 0.7152f, 0.0722f },
|
||||
{ -0.1141f, -0.3839f, 0.498f },
|
||||
{ 0.498f, -0.4524f, -0.0457f },
|
||||
},
|
||||
// ITU-R BT.709-6
|
||||
{
|
||||
16,
|
||||
@@ -707,7 +716,7 @@ static struct RGB2YUVFactors RGB2YUVFactorTables[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static bool SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, YCbCrType yuv_type)
|
||||
static bool SDL_ConvertPixels_XRGB8888_to_YUV(int width, int height, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, YCbCrType yuv_type)
|
||||
{
|
||||
const int src_pitch_x_2 = src_pitch * 2;
|
||||
const int height_half = height / 2;
|
||||
@@ -718,9 +727,9 @@ static bool SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void
|
||||
|
||||
const struct RGB2YUVFactors *cvt = &RGB2YUVFactorTables[yuv_type];
|
||||
|
||||
#define MAKE_Y(r, g, b) (Uint8)((int)(cvt->y[0] * (r) + cvt->y[1] * (g) + cvt->y[2] * (b) + 0.5f) + cvt->y_offset)
|
||||
#define MAKE_U(r, g, b) (Uint8)((int)(cvt->u[0] * (r) + cvt->u[1] * (g) + cvt->u[2] * (b) + 0.5f) + 128)
|
||||
#define MAKE_V(r, g, b) (Uint8)((int)(cvt->v[0] * (r) + cvt->v[1] * (g) + cvt->v[2] * (b) + 0.5f) + 128)
|
||||
#define MAKE_Y(r, g, b) (Uint8)SDL_clamp(((int)(cvt->y[0] * (r) + cvt->y[1] * (g) + cvt->y[2] * (b) + 0.5f) + cvt->y_offset), 0, 255)
|
||||
#define MAKE_U(r, g, b) (Uint8)SDL_clamp(((int)(cvt->u[0] * (r) + cvt->u[1] * (g) + cvt->u[2] * (b) + 0.5f) + 128), 0, 255)
|
||||
#define MAKE_V(r, g, b) (Uint8)SDL_clamp(((int)(cvt->v[0] * (r) + cvt->v[1] * (g) + cvt->v[2] * (b) + 0.5f) + 128), 0, 255)
|
||||
|
||||
#define READ_2x2_PIXELS \
|
||||
const Uint32 p1 = ((const Uint32 *)curr_row)[2 * i]; \
|
||||
@@ -1149,9 +1158,9 @@ bool SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
||||
#endif
|
||||
|
||||
// ARGB8888 to FOURCC
|
||||
if (src_format == SDL_PIXELFORMAT_ARGB8888 &&
|
||||
if ((src_format == SDL_PIXELFORMAT_ARGB8888 || src_format == SDL_PIXELFORMAT_XRGB8888) &&
|
||||
SDL_COLORSPACEPRIMARIES(src_colorspace) == SDL_COLORSPACEPRIMARIES(dst_colorspace)) {
|
||||
return SDL_ConvertPixels_ARGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
return SDL_ConvertPixels_XRGB8888_to_YUV(width, height, src, src_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
}
|
||||
|
||||
if (dst_format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -1194,15 +1203,15 @@ bool SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert src/src_format to tmp/ARGB8888
|
||||
result = SDL_ConvertPixelsAndColorspace(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, dst_colorspace, dst_properties, tmp, tmp_pitch);
|
||||
// convert src/src_format to tmp/XRGB8888
|
||||
result = SDL_ConvertPixelsAndColorspace(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_XRGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch);
|
||||
if (!result) {
|
||||
SDL_free(tmp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert tmp/ARGB8888 to dst/FOURCC
|
||||
result = SDL_ConvertPixels_ARGB8888_to_YUV(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
// convert tmp/XRGB8888 to dst/FOURCC
|
||||
result = SDL_ConvertPixels_XRGB8888_to_YUV(width, height, tmp, tmp_pitch, dst_format, dst, dst_pitch, yuv_type);
|
||||
SDL_free(tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ SDL_GLContext Cocoa_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
_this->GL_SwapWindow = Cocoa_GLES_SwapWindow;
|
||||
_this->GL_DestroyContext = Cocoa_GLES_DestroyContext;
|
||||
|
||||
if (Cocoa_GLES_LoadLibrary(_this, NULL) != 0) {
|
||||
if (!Cocoa_GLES_LoadLibrary(_this, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
return Cocoa_GLES_CreateContext(_this, window);
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
|
||||
". [SDL] In performDragOperation, draggingSourceOperationMask %lx, "
|
||||
"expected Generic %lx, others Copy %lx, Link %lx, Private %lx, Move %lx, Delete %lx\n",
|
||||
(unsigned long)[sender draggingSourceOperationMask],
|
||||
@@ -210,7 +210,7 @@
|
||||
(unsigned long)NSDragOperationMove,
|
||||
(unsigned long)NSDragOperationDelete);
|
||||
if ([sender draggingPasteboard]) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
|
||||
". [SDL] In performDragOperation, valid draggingPasteboard, "
|
||||
"name [%s] '%s', changeCount %ld\n",
|
||||
[[[[sender draggingPasteboard] name] className] UTF8String],
|
||||
@@ -229,7 +229,7 @@
|
||||
|
||||
for (NSString *supportedType in [pasteboard types]) {
|
||||
NSString *typeString = [pasteboard stringForType:supportedType];
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
|
||||
". [SDL] In performDragOperation, Pasteboard type '%s', stringForType (%lu) '%s'\n",
|
||||
[[supportedType description] UTF8String],
|
||||
(unsigned long)[[typeString description] length],
|
||||
@@ -281,7 +281,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
|
||||
". [SDL] In performDragOperation, desiredType '%s', "
|
||||
"Submitting DropFile as (%lu) '%s'\n",
|
||||
[[desiredType description] UTF8String],
|
||||
@@ -296,7 +296,7 @@
|
||||
char *saveptr = NULL;
|
||||
char *token = SDL_strtok_r(buffer, "\r\n", &saveptr);
|
||||
while (token) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
|
||||
SDL_LogTrace(SDL_LOG_CATEGORY_INPUT,
|
||||
". [SDL] In performDragOperation, desiredType '%s', "
|
||||
"Submitting DropText as (%lu) '%s'\n",
|
||||
[[desiredType description] UTF8String],
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user