Merge commit 'dec0d4ec4153bf9fc2b78ae6c2df45b6ea8dde7a' as 'external/sdl/SDL'

This commit is contained in:
2023-07-25 22:27:55 +02:00
1663 changed files with 627495 additions and 0 deletions

View File

@ -0,0 +1,204 @@
/*
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_THREAD_VITA
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
implementation, written by Christopher Tate and Owen Smith. Thanks!
*/
struct SDL_Condition
{
SDL_Mutex *lock;
int waiting;
int signals;
SDL_Semaphore *wait_sem;
SDL_Semaphore *wait_done;
};
/* Create a condition variable */
SDL_Condition *SDL_CreateCondition(void)
{
SDL_Condition *cond;
cond = (SDL_Condition *)SDL_malloc(sizeof(SDL_Condition));
if (cond != NULL) {
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) {
SDL_DestroyCondition(cond);
cond = NULL;
}
} else {
SDL_OutOfMemory();
}
return cond;
}
/* Destroy a condition variable */
void SDL_DestroyCondition(SDL_Condition *cond)
{
if (cond != NULL) {
if (cond->wait_sem) {
SDL_DestroySemaphore(cond->wait_sem);
}
if (cond->wait_done) {
SDL_DestroySemaphore(cond->wait_done);
}
if (cond->lock) {
SDL_DestroyMutex(cond->lock);
}
SDL_free(cond);
}
}
/* Restart one of the threads that are waiting on the condition variable */
int SDL_SignalCondition(SDL_Condition *cond)
{
if (cond == NULL) {
return SDL_InvalidParamError("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_PostSemaphore(cond->wait_sem);
SDL_UnlockMutex(cond->lock);
SDL_WaitSemaphore(cond->wait_done);
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Restart all threads that are waiting on the condition variable */
int SDL_BroadcastCondition(SDL_Condition *cond)
{
if (cond == NULL) {
return SDL_InvalidParamError("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_PostSemaphore(cond->wait_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);
}
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Wait on the condition variable for at most 'timeoutNS' nanoseconds.
The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait.
Typical use:
Thread A:
SDL_LockMutex(lock);
while ( ! condition ) {
SDL_WaitCondition(cond, lock);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_SignalCondition(cond);
SDL_UnlockMutex(lock);
*/
int SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS)
{
int retval;
if (cond == NULL) {
return SDL_InvalidParamError("cond");
}
/* Obtain the protection mutex, and increment the number of waiters.
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);
/* Unlock the mutex, as is required by condition variable semantics */
SDL_UnlockMutex(mutex);
/* Wait for a signal */
retval = SDL_WaitSemaphoreTimeoutNS(cond->wait_sem, timeoutNS);
/* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore
if we are stopped between the mutex unlock and semaphore wait,
giving a deadlock. See the following URL for details:
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
*/
SDL_LockMutex(cond->lock);
if (cond->signals > 0) {
/* If we timed out, we need to eat a condition signal */
if (retval > 0) {
SDL_WaitSemaphore(cond->wait_sem);
}
/* We always notify the signal thread that we are done */
SDL_PostSemaphore(cond->wait_done);
/* Signal handshake complete */
--cond->signals;
}
--cond->waiting;
SDL_UnlockMutex(cond->lock);
/* Lock the mutex, as is required by condition variable semantics */
SDL_LockMutex(mutex);
return retval;
}
#endif /* SDL_THREAD_VITA */

View File

@ -0,0 +1,141 @@
/*
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_THREAD_VITA
#include "SDL_systhread_c.h"
#include <psp2/kernel/threadmgr.h>
#include <psp2/kernel/error.h>
struct SDL_Mutex
{
SceKernelLwMutexWork lock;
};
/* Create a mutex */
SDL_Mutex *SDL_CreateMutex(void)
{
SDL_Mutex *mutex = NULL;
SceInt32 res = 0;
/* Allocate mutex memory */
mutex = (SDL_Mutex *)SDL_malloc(sizeof(*mutex));
if (mutex != NULL) {
res = sceKernelCreateLwMutex(
&mutex->lock,
"SDL mutex",
SCE_KERNEL_MUTEX_ATTR_RECURSIVE,
0,
NULL);
if (res < 0) {
SDL_SetError("Error trying to create mutex: %x", res);
}
} else {
SDL_OutOfMemory();
}
return mutex;
}
/* Free the mutex */
void SDL_DestroyMutex(SDL_Mutex *mutex)
{
if (mutex != NULL) {
sceKernelDeleteLwMutex(&mutex->lock);
SDL_free(mutex);
}
}
/* Lock the mutex */
int SDL_LockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
{
#ifdef SDL_THREADS_DISABLED
return 0;
#else
SceInt32 res = 0;
if (mutex == NULL) {
return 0;
}
res = sceKernelLockLwMutex(&mutex->lock, 1, NULL);
if (res != SCE_KERNEL_OK) {
return SDL_SetError("Error trying to lock mutex: %x", res);
}
return 0;
#endif /* SDL_THREADS_DISABLED */
}
/* Try to lock the mutex */
int SDL_TryLockMutex(SDL_Mutex *mutex)
{
#ifdef SDL_THREADS_DISABLED
return 0;
#else
SceInt32 res = 0;
if (mutex == NULL) {
return 0;
}
res = sceKernelTryLockLwMutex(&mutex->lock, 1);
switch (res) {
case SCE_KERNEL_OK:
return 0;
break;
case SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN:
return SDL_MUTEX_TIMEDOUT;
break;
default:
return SDL_SetError("Error trying to lock mutex: %x", res);
break;
}
return -1;
#endif /* SDL_THREADS_DISABLED */
}
/* Unlock the mutex */
int SDL_UnlockMutex(SDL_Mutex *mutex) SDL_NO_THREAD_SAFETY_ANALYSIS /* clang doesn't know about NULL mutexes */
{
#ifdef SDL_THREADS_DISABLED
return 0;
#else
SceInt32 res = 0;
if (mutex == NULL) {
return 0;
}
res = sceKernelUnlockLwMutex(&mutex->lock, 1);
if (res != 0) {
return SDL_SetError("Error trying to unlock mutex: %x", res);
}
return 0;
#endif /* SDL_THREADS_DISABLED */
}
#endif /* SDL_THREAD_VITA */

View File

@ -0,0 +1,21 @@
/*
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"

View File

@ -0,0 +1,147 @@
/*
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_THREAD_VITA
/* Semaphore functions for the VITA. */
#include <stdio.h>
#include <stdlib.h>
#include <psp2/types.h>
#include <psp2/kernel/error.h>
#include <psp2/kernel/threadmgr.h>
struct SDL_Semaphore
{
SceUID semid;
};
/* Create a semaphore */
SDL_Semaphore *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_Semaphore *sem;
sem = (SDL_Semaphore *)SDL_malloc(sizeof(*sem));
if (sem != NULL) {
/* TODO: Figure out the limit on the maximum value. */
sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL);
if (sem->semid < 0) {
SDL_SetError("Couldn't create semaphore");
SDL_free(sem);
sem = NULL;
}
} else {
SDL_OutOfMemory();
}
return sem;
}
/* Free the semaphore */
void SDL_DestroySemaphore(SDL_Semaphore *sem)
{
if (sem != NULL) {
if (sem->semid > 0) {
sceKernelDeleteSema(sem->semid);
sem->semid = 0;
}
SDL_free(sem);
}
}
/* TODO: This routine is a bit overloaded.
* If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
* NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
* is specified, convert it to microseconds. */
int SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS)
{
SceUInt timeoutUS;
SceUInt *pTimeout;
int res;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
if (timeoutNS == 0) {
res = sceKernelPollSema(sem->semid, 1);
if (res < 0) {
return SDL_MUTEX_TIMEDOUT;
}
return 0;
}
if (timeoutNS < 0) {
pTimeout = NULL;
} else {
timeoutUS = (SceUInt)SDL_NS_TO_US(timeoutNS); /* Convert to microseconds. */
pTimeout = &timeoutUS;
}
res = sceKernelWaitSema(sem->semid, 1, pTimeout);
switch (res) {
case SCE_KERNEL_OK:
return 0;
case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
return SDL_MUTEX_TIMEDOUT;
default:
return SDL_SetError("sceKernelWaitSema() failed");
}
}
/* Returns the current count of the semaphore */
Uint32 SDL_GetSemaphoreValue(SDL_Semaphore *sem)
{
SceKernelSemaInfo info;
info.size = sizeof(info);
if (sem == NULL) {
SDL_InvalidParamError("sem");
return 0;
}
if (sceKernelGetSemaInfo(sem->semid, &info) >= 0) {
return info.currentCount;
}
return 0;
}
int SDL_PostSemaphore(SDL_Semaphore *sem)
{
int res;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
res = sceKernelSignalSema(sem->semid, 1);
if (res < 0) {
return SDL_SetError("sceKernelSignalSema() failed");
}
return 0;
}
#endif /* SDL_THREAD_VITA */

View File

@ -0,0 +1,133 @@
/*
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_THREAD_VITA
/* VITA thread management routines for SDL */
#include <stdio.h>
#include <stdlib.h>
#include "../SDL_systhread.h"
#include "../SDL_thread_c.h"
#include <psp2/types.h>
#include <psp2/kernel/threadmgr.h>
#define VITA_THREAD_STACK_SIZE_MIN 0x1000 // 4KiB
#define VITA_THREAD_STACK_SIZE_MAX 0x2000000 // 32MiB
#define VITA_THREAD_STACK_SIZE_DEFAULT 0x10000 // 64KiB
#define VITA_THREAD_NAME_MAX 32
#define VITA_THREAD_PRIORITY_LOW 191
#define VITA_THREAD_PRIORITY_NORMAL 160
#define VITA_THREAD_PRIORITY_HIGH 112
#define VITA_THREAD_PRIORITY_TIME_CRITICAL 64
static int ThreadEntry(SceSize args, void *argp)
{
SDL_RunThread(*(SDL_Thread **)argp);
return 0;
}
int SDL_SYS_CreateThread(SDL_Thread *thread)
{
char thread_name[VITA_THREAD_NAME_MAX];
size_t stack_size = VITA_THREAD_STACK_SIZE_DEFAULT;
SDL_strlcpy(thread_name, "SDL thread", VITA_THREAD_NAME_MAX);
if (thread->name) {
SDL_strlcpy(thread_name, thread->name, VITA_THREAD_NAME_MAX);
}
if (thread->stacksize) {
if (thread->stacksize < VITA_THREAD_STACK_SIZE_MIN) {
thread->stacksize = VITA_THREAD_STACK_SIZE_MIN;
}
if (thread->stacksize > VITA_THREAD_STACK_SIZE_MAX) {
thread->stacksize = VITA_THREAD_STACK_SIZE_MAX;
}
stack_size = thread->stacksize;
}
/* Create new thread with the same priority as the current thread */
thread->handle = sceKernelCreateThread(
thread_name, // name
ThreadEntry, // function to run
0, // priority. 0 means priority of calling thread
stack_size, // stack size
0, // attributes. always 0
0, // cpu affinity mask. 0 = all CPUs
NULL // opt. always NULL
);
if (thread->handle < 0) {
return SDL_SetError("sceKernelCreateThread() failed");
}
sceKernelStartThread(thread->handle, 4, &thread);
return 0;
}
void SDL_SYS_SetupThread(const char *name)
{
/* Do nothing. */
}
SDL_threadID SDL_ThreadID(void)
{
return (SDL_threadID)sceKernelGetThreadId();
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
sceKernelWaitThreadEnd(thread->handle, NULL, NULL);
sceKernelDeleteThread(thread->handle);
}
void SDL_SYS_DetachThread(SDL_Thread *thread)
{
/* Do nothing. */
}
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
{
int value = VITA_THREAD_PRIORITY_NORMAL;
switch (priority) {
case SDL_THREAD_PRIORITY_LOW:
value = VITA_THREAD_PRIORITY_LOW;
break;
case SDL_THREAD_PRIORITY_NORMAL:
value = VITA_THREAD_PRIORITY_NORMAL;
break;
case SDL_THREAD_PRIORITY_HIGH:
value = VITA_THREAD_PRIORITY_HIGH;
break;
case SDL_THREAD_PRIORITY_TIME_CRITICAL:
value = VITA_THREAD_PRIORITY_TIME_CRITICAL;
break;
}
return sceKernelChangeThreadPriority(0, value);
}
#endif /* SDL_THREAD_VITA */

View File

@ -0,0 +1,24 @@
/*
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 <psp2/types.h>
typedef SceUID SYS_ThreadHandle;