N3DS port (squashed)

A dedicated renderer using Citro3D would likely allow for better
much better graphical performances.
This commit is contained in:
Pierre Wendling
2021-03-30 04:32:39 -04:00
committed by Sam Lantinga
parent 61b5360e17
commit 655275378d
50 changed files with 2663 additions and 5 deletions

View File

@@ -38,6 +38,8 @@
#include "psp/SDL_systhread_c.h"
#elif SDL_THREAD_VITA
#include "vita/SDL_systhread_c.h"
#elif SDL_THREAD_N3DS
#include "n3ds/SDL_systhread_c.h"
#elif SDL_THREAD_STDCPP
#include "stdcpp/SDL_systhread_c.h"
#elif SDL_THREAD_OS2

View File

@@ -0,0 +1,133 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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_N3DS
/* An implementation of condition variables using libctru's CondVar */
#include "SDL_sysmutex_c.h"
struct SDL_cond
{
CondVar cond_variable;
};
/* Create a condition variable */
SDL_cond *
SDL_CreateCond(void)
{
SDL_cond *cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
if (cond) {
CondVar_Init(&cond->cond_variable);
} else {
SDL_OutOfMemory();
}
return cond;
}
/* Destroy a condition variable */
void
SDL_DestroyCond(SDL_cond *cond)
{
if (cond) {
SDL_free(cond);
}
}
/* Restart one of the threads that are waiting on the condition variable */
int
SDL_CondSignal(SDL_cond *cond)
{
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
CondVar_Signal(&cond->cond_variable);
return 0;
}
/* Restart all threads that are waiting on the condition variable */
int
SDL_CondBroadcast(SDL_cond *cond)
{
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
CondVar_Broadcast(&cond->cond_variable);
return 0;
}
/* Wait on the condition variable for at most 'ms' milliseconds.
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_CondWait(cond, lock);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_CondSignal(cond);
SDL_UnlockMutex(lock);
*/
int
SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{
Result res;
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
if (!mutex) {
return SDL_SetError("Passed a NULL mutex");
}
res = 0;
if (ms == SDL_MUTEX_MAXWAIT) {
CondVar_Wait(&cond->cond_variable, &mutex->lock.lock);
} else {
res = CondVar_WaitTimeout(&cond->cond_variable, &mutex->lock.lock,
(s64) ms * 1000000LL);
}
return R_SUCCEEDED(res) ? 0 : SDL_MUTEX_TIMEDOUT;
}
/* Wait on the condition variable forever */
int
SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
#endif /* SDL_THREAD_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,93 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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_N3DS
/* An implementation of mutexes using libctru's RecursiveLock */
#include "SDL_sysmutex_c.h"
/* Create a mutex */
SDL_mutex *
SDL_CreateMutex(void)
{
SDL_mutex *mutex;
/* Allocate mutex memory */
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
if (mutex) {
RecursiveLock_Init(&mutex->lock);
} else {
SDL_OutOfMemory();
}
return mutex;
}
/* Free the mutex */
void
SDL_DestroyMutex(SDL_mutex *mutex)
{
if (mutex) {
SDL_free(mutex);
}
}
/* Lock the mutex */
int
SDL_LockMutex(SDL_mutex *mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
RecursiveLock_Lock(&mutex->lock);
return 0;
}
/* try Lock the mutex */
int
SDL_TryLockMutex(SDL_mutex *mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
return RecursiveLock_TryLock(&mutex->lock);
}
/* Unlock the mutex */
int
SDL_mutexV(SDL_mutex *mutex)
{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
RecursiveLock_Unlock(&mutex->lock);
return 0;
}
#endif /* SDL_THREAD_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,37 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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"
#ifndef SDL_sysmutex_c_h_
#define SDL_sysmutex_c_h_
#include <3ds.h>
#include "SDL_mutex.h"
struct SDL_mutex
{
RecursiveLock lock;
};
#endif /* SDL_sysmutex_c_h */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,134 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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_N3DS
/* An implementation of semaphores using libctru's LightSemaphore */
#include <3ds.h>
#include "SDL_thread.h"
struct SDL_semaphore
{
LightSemaphore semaphore;
};
SDL_sem *
SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_sem *sem;
if (initial_value > SDL_MAX_SINT16) {
SDL_SetError("Initial semaphore value too high for this platform");
return NULL;
}
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
if (!sem) {
SDL_OutOfMemory();
return NULL;
}
LightSemaphore_Init(&sem->semaphore, initial_value, SDL_MAX_SINT16);
return sem;
}
/* WARNING:
You cannot call this function when another thread is using the semaphore.
*/
void
SDL_DestroySemaphore(SDL_sem *sem)
{
if (sem) {
SDL_free(sem);
}
}
int
SDL_SemTryWait(SDL_sem *sem)
{
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
return SDL_SemWaitTimeout(sem, 0);
}
int
SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
if (timeout == SDL_MUTEX_MAXWAIT) {
LightSemaphore_Acquire(&sem->semaphore, 1);
retval = 0;
} else {
int return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
if (return_code != 0) {
for (u32 i = 0; i < timeout; i++) {
svcSleepThread(1000000LL);
return_code = LightSemaphore_TryAcquire(&sem->semaphore, 1);
if (return_code == 0) {
break;
}
}
}
retval = return_code != 0 ? SDL_MUTEX_TIMEDOUT : 0;
}
return retval;
}
int
SDL_SemWait(SDL_sem *sem)
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
}
Uint32
SDL_SemValue(SDL_sem *sem)
{
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
return sem->semaphore.current_count;
}
int
SDL_SemPost(SDL_sem *sem)
{
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
LightSemaphore_Release(&sem->semaphore, 1);
return 0;
}
#endif /* SDL_THREAD_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,148 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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_N3DS
/* Thread management routines for SDL */
#include "../SDL_systhread.h"
/* N3DS has very limited RAM (128MB), so we put a limit on thread stack size. */
#define N3DS_THREAD_STACK_SIZE_MAX (16 * 1024)
#define N3DS_THREAD_STACK_SIZE_DEFAULT (4 * 1024)
#define N3DS_THREAD_PRIORITY_LOW 0x3F /**< Minimum priority */
#define N3DS_THREAD_PRIORITY_MEDIUM 0x2F /**< Slightly higher than main thread (0x30) */
#define N3DS_THREAD_PRIORITY_HIGH 0x19 /**< High priority for non-video work */
#define N3DS_THREAD_PRIORITY_TIME_CRITICAL 0x18 /**< Highest priority */
static size_t GetStackSize(size_t requested_size);
static void
ThreadEntry(void *arg)
{
SDL_RunThread((SDL_Thread *) arg);
threadExit(0);
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
#error "SDL_PASSED_BEGINTHREAD_ENDTHREAD is not supported on N3DS"
#endif
int
SDL_SYS_CreateThread(SDL_Thread *thread)
{
s32 priority = N3DS_THREAD_PRIORITY_MEDIUM;
size_t stack_size = GetStackSize(thread->stacksize);
thread->handle = threadCreate(ThreadEntry,
thread,
stack_size,
priority,
-1,
false);
if (thread->handle == NULL) {
return SDL_SetError("Couldn't create thread");
}
return 0;
}
static size_t
GetStackSize(size_t requested_size)
{
if (requested_size == 0) {
return N3DS_THREAD_STACK_SIZE_DEFAULT;
}
if (requested_size > N3DS_THREAD_STACK_SIZE_MAX) {
SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM,
"Requested a thread size of %zu,"
" falling back to the maximum supported of %zu\n",
requested_size,
N3DS_THREAD_STACK_SIZE_MAX);
requested_size = N3DS_THREAD_STACK_SIZE_MAX;
}
return requested_size;
}
void
SDL_SYS_SetupThread(const char *name)
{
return;
}
SDL_threadID
SDL_ThreadID(void)
{
u32 thread_ID = 0;
svcGetThreadId(&thread_ID, CUR_THREAD_HANDLE);
return (SDL_threadID) thread_ID;
}
int
SDL_SYS_SetThreadPriority(SDL_ThreadPriority sdl_priority)
{
s32 svc_priority;
switch (sdl_priority) {
case SDL_THREAD_PRIORITY_LOW:
svc_priority = N3DS_THREAD_PRIORITY_LOW;
break;
case SDL_THREAD_PRIORITY_NORMAL:
svc_priority = N3DS_THREAD_PRIORITY_MEDIUM;
break;
case SDL_THREAD_PRIORITY_HIGH:
svc_priority = N3DS_THREAD_PRIORITY_HIGH;
break;
case SDL_THREAD_PRIORITY_TIME_CRITICAL:
svc_priority = N3DS_THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
svc_priority = N3DS_THREAD_PRIORITY_MEDIUM;
}
return (int) svcSetThreadPriority(CUR_THREAD_HANDLE, svc_priority);
}
void
SDL_SYS_WaitThread(SDL_Thread *thread)
{
Result res = threadJoin(thread->handle, U64_MAX);
/*
Detached threads can be waited on, but should NOT be cleaned manually
as it would result in a fatal error.
*/
if (R_SUCCEEDED(res) && SDL_AtomicGet(&thread->state) != SDL_THREAD_STATE_DETACHED) {
threadFree(thread->handle);
}
}
void
SDL_SYS_DetachThread(SDL_Thread *thread)
{
threadDetach(thread->handle);
}
#endif /* SDL_THREAD_N3DS */
/* vi: set sts=4 ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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"
#ifndef SDL_systhread_c_h_
#define SDL_systhread_c_h_
#include <3ds.h>
typedef Thread SYS_ThreadHandle;
#endif /* SDL_systhread_c_h_ */
/* vi: set sts=4 ts=4 sw=4 expandtab: */