diff options
Diffstat (limited to '3rdparty/SDL/src')
631 files changed, 178303 insertions, 0 deletions
diff --git a/3rdparty/SDL/src/SDL.c b/3rdparty/SDL/src/SDL.c new file mode 100644 index 0000000..87f1b1a --- /dev/null +++ b/3rdparty/SDL/src/SDL.c @@ -0,0 +1,350 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Initialization code for SDL */ + +#include "SDL.h" +#include "SDL_fatal.h" +#if !SDL_VIDEO_DISABLED +#include "video/SDL_leaks.h" +#endif + +#if SDL_THREAD_PTH +#include <pth.h> +#endif + +/* Initialization/Cleanup routines */ +#if !SDL_JOYSTICK_DISABLED +extern int SDL_JoystickInit(void); +extern void SDL_JoystickQuit(void); +#endif +#if !SDL_CDROM_DISABLED +extern int SDL_CDROMInit(void); +extern void SDL_CDROMQuit(void); +#endif +#if !SDL_TIMERS_DISABLED +extern void SDL_StartTicks(void); +extern int SDL_TimerInit(void); +extern void SDL_TimerQuit(void); +#endif + +/* The current SDL version */ +static SDL_version version = + { SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL }; + +/* The initialized subsystems */ +static Uint32 SDL_initialized = 0; +#if !SDL_TIMERS_DISABLED +static Uint32 ticks_started = 0; +#endif + +#ifdef CHECK_LEAKS +int surfaces_allocated = 0; +#endif + +int SDL_InitSubSystem(Uint32 flags) +{ +#if !SDL_TIMERS_DISABLED + /* Initialize the timer subsystem */ + if ( ! ticks_started ) { + SDL_StartTicks(); + ticks_started = 1; + } + if ( (flags & SDL_INIT_TIMER) && !(SDL_initialized & SDL_INIT_TIMER) ) { + if ( SDL_TimerInit() < 0 ) { + return(-1); + } + SDL_initialized |= SDL_INIT_TIMER; + } +#else + if ( flags & SDL_INIT_TIMER ) { + SDL_SetError("SDL not built with timer support"); + return(-1); + } +#endif + +#if !SDL_VIDEO_DISABLED + /* Initialize the video/event subsystem */ + if ( (flags & SDL_INIT_VIDEO) && !(SDL_initialized & SDL_INIT_VIDEO) ) { + if ( SDL_VideoInit(SDL_getenv("SDL_VIDEODRIVER"), + (flags&SDL_INIT_EVENTTHREAD)) < 0 ) { + return(-1); + } + SDL_initialized |= SDL_INIT_VIDEO; + } +#else + if ( flags & SDL_INIT_VIDEO ) { + SDL_SetError("SDL not built with video support"); + return(-1); + } +#endif + +#if !SDL_AUDIO_DISABLED + /* Initialize the audio subsystem */ + if ( (flags & SDL_INIT_AUDIO) && !(SDL_initialized & SDL_INIT_AUDIO) ) { + if ( SDL_AudioInit(SDL_getenv("SDL_AUDIODRIVER")) < 0 ) { + return(-1); + } + SDL_initialized |= SDL_INIT_AUDIO; + } +#else + if ( flags & SDL_INIT_AUDIO ) { + SDL_SetError("SDL not built with audio support"); + return(-1); + } +#endif + +#if !SDL_JOYSTICK_DISABLED + /* Initialize the joystick subsystem */ + if ( (flags & SDL_INIT_JOYSTICK) && + !(SDL_initialized & SDL_INIT_JOYSTICK) ) { + if ( SDL_JoystickInit() < 0 ) { + return(-1); + } + SDL_initialized |= SDL_INIT_JOYSTICK; + } +#else + if ( flags & SDL_INIT_JOYSTICK ) { + SDL_SetError("SDL not built with joystick support"); + return(-1); + } +#endif + +#if !SDL_CDROM_DISABLED + /* Initialize the CD-ROM subsystem */ + if ( (flags & SDL_INIT_CDROM) && !(SDL_initialized & SDL_INIT_CDROM) ) { + if ( SDL_CDROMInit() < 0 ) { + return(-1); + } + SDL_initialized |= SDL_INIT_CDROM; + } +#else + if ( flags & SDL_INIT_CDROM ) { + SDL_SetError("SDL not built with cdrom support"); + return(-1); + } +#endif + return(0); +} + +int SDL_Init(Uint32 flags) +{ +#if !SDL_THREADS_DISABLED && SDL_THREAD_PTH + if (!pth_init()) { + return -1; + } +#endif + + /* Clear the error message */ + SDL_ClearError(); + + /* Initialize the desired subsystems */ + if ( SDL_InitSubSystem(flags) < 0 ) { + return(-1); + } + + /* Everything is initialized */ + if ( !(flags & SDL_INIT_NOPARACHUTE) ) { + SDL_InstallParachute(); + } + return(0); +} + +void SDL_QuitSubSystem(Uint32 flags) +{ + /* Shut down requested initialized subsystems */ +#if !SDL_CDROM_DISABLED + if ( (flags & SDL_initialized & SDL_INIT_CDROM) ) { + SDL_CDROMQuit(); + SDL_initialized &= ~SDL_INIT_CDROM; + } +#endif +#if !SDL_JOYSTICK_DISABLED + if ( (flags & SDL_initialized & SDL_INIT_JOYSTICK) ) { + SDL_JoystickQuit(); + SDL_initialized &= ~SDL_INIT_JOYSTICK; + } +#endif +#if !SDL_AUDIO_DISABLED + if ( (flags & SDL_initialized & SDL_INIT_AUDIO) ) { + SDL_AudioQuit(); + SDL_initialized &= ~SDL_INIT_AUDIO; + } +#endif +#if !SDL_VIDEO_DISABLED + if ( (flags & SDL_initialized & SDL_INIT_VIDEO) ) { + SDL_VideoQuit(); + SDL_initialized &= ~SDL_INIT_VIDEO; + } +#endif +#if !SDL_TIMERS_DISABLED + if ( (flags & SDL_initialized & SDL_INIT_TIMER) ) { + SDL_TimerQuit(); + SDL_initialized &= ~SDL_INIT_TIMER; + } +#endif +} + +Uint32 SDL_WasInit(Uint32 flags) +{ + if ( ! flags ) { + flags = SDL_INIT_EVERYTHING; + } + return (SDL_initialized&flags); +} + +void SDL_Quit(void) +{ + /* Quit all subsystems */ +#ifdef DEBUG_BUILD + printf("[SDL_Quit] : Enter! Calling QuitSubSystem()\n"); fflush(stdout); +#endif + SDL_QuitSubSystem(SDL_INIT_EVERYTHING); + +#ifdef CHECK_LEAKS +#ifdef DEBUG_BUILD + printf("[SDL_Quit] : CHECK_LEAKS\n"); fflush(stdout); +#endif + + /* Print the number of surfaces not freed */ + if ( surfaces_allocated != 0 ) { + fprintf(stderr, "SDL Warning: %d SDL surfaces extant\n", + surfaces_allocated); + } +#endif +#ifdef DEBUG_BUILD + printf("[SDL_Quit] : SDL_UninstallParachute()\n"); fflush(stdout); +#endif + + /* Uninstall any parachute signal handlers */ + SDL_UninstallParachute(); + +#if !SDL_THREADS_DISABLED && SDL_THREAD_PTH + pth_kill(); +#endif +#ifdef DEBUG_BUILD + printf("[SDL_Quit] : Returning!\n"); fflush(stdout); +#endif + +} + +/* Return the library version number */ +const SDL_version * SDL_Linked_Version(void) +{ + return(&version); +} + +#if defined(__OS2__) +/* Building for OS/2 */ +#ifdef __WATCOMC__ + +#define INCL_DOSERRORS +#define INCL_DOSEXCEPTIONS +#include <os2.h> + +/* Exception handler to prevent the Audio thread hanging, making a zombie process! */ +ULONG _System SDL_Main_ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec, + PEXCEPTIONREGISTRATIONRECORD pERegRec, + PCONTEXTRECORD pCtxRec, + PVOID p) +{ + if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND) + return XCPT_CONTINUE_SEARCH; + if (pERepRec->fHandlerFlags & EH_UNWINDING) + return XCPT_CONTINUE_SEARCH; + if (pERepRec->fHandlerFlags & EH_NESTED_CALL) + return XCPT_CONTINUE_SEARCH; + + /* Do cleanup at every fatal exception! */ + if (((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION) && + (pERepRec->ExceptionNum != XCPT_BREAKPOINT) && + (pERepRec->ExceptionNum != XCPT_SINGLE_STEP) + ) + { + if (SDL_initialized & SDL_INIT_AUDIO) + { + /* This removes the zombie audio thread in case of emergency. */ +#ifdef DEBUG_BUILD + printf("[SDL_Main_ExceptionHandler] : Calling SDL_CloseAudio()!\n"); +#endif + SDL_CloseAudio(); + } + } + return (XCPT_CONTINUE_SEARCH); +} + + +EXCEPTIONREGISTRATIONRECORD SDL_Main_xcpthand = {0, SDL_Main_ExceptionHandler}; + +/* The main DLL entry for DLL Initialization and Uninitialization: */ +unsigned _System LibMain(unsigned hmod, unsigned termination) +{ + if (termination) + { +#ifdef DEBUG_BUILD +/* printf("[SDL DLL Unintialization] : Removing exception handler\n"); */ +#endif + DosUnsetExceptionHandler(&SDL_Main_xcpthand); + return 1; + } else + { +#ifdef DEBUG_BUILD + /* Make stdout and stderr unbuffered! */ + setbuf(stdout, NULL); + setbuf(stderr, NULL); +#endif + /* Fire up exception handler */ +#ifdef DEBUG_BUILD +/* printf("[SDL DLL Initialization] : Setting exception handler\n"); */ +#endif + /* Set exception handler */ + DosSetExceptionHandler(&SDL_Main_xcpthand); + + return 1; + } +} +#endif /* __WATCOMC__ */ + +#elif defined(__WIN32__) && !defined(__SYMBIAN32__) + +#if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL)) +/* Need to include DllMain() on Watcom C for some reason.. */ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +BOOL APIENTRY _DllMainCRTStartup( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved ) +{ + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#endif /* building DLL with Watcom C */ + +#endif /* OS/2 elif __WIN32__ */ diff --git a/3rdparty/SDL/src/SDL_error.c b/3rdparty/SDL/src/SDL_error.c new file mode 100644 index 0000000..0f06bd5 --- /dev/null +++ b/3rdparty/SDL/src/SDL_error.c @@ -0,0 +1,238 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Simple error handling in SDL */ + +#include "SDL_error.h" +#include "SDL_error_c.h" + +/* Routine to get the thread-specific error variable */ +#if SDL_THREADS_DISABLED +/* The SDL_arraysize(The ),default (non-thread-safe) global error variable */ +static SDL_error SDL_global_error; +#define SDL_GetErrBuf() (&SDL_global_error) +#else +extern SDL_error *SDL_GetErrBuf(void); +#endif /* SDL_THREADS_DISABLED */ + +#define SDL_ERRBUFIZE 1024 + +/* Private functions */ + +static const char *SDL_LookupString(const char *key) +{ + /* FIXME: Add code to lookup key in language string hash-table */ + return key; +} + +/* Public functions */ + +void SDL_SetError (const char *fmt, ...) +{ + va_list ap; + SDL_error *error; + + /* Copy in the key, mark error as valid */ + error = SDL_GetErrBuf(); + error->error = 1; + SDL_strlcpy((char *)error->key, fmt, sizeof(error->key)); + + va_start(ap, fmt); + error->argc = 0; + while ( *fmt ) { + if ( *fmt++ == '%' ) { + while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') ) { + ++fmt; + } + switch (*fmt++) { + case 0: /* Malformed format string.. */ + --fmt; + break; + case 'c': + case 'i': + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': + error->args[error->argc++].value_i = + va_arg(ap, int); + break; + case 'f': + error->args[error->argc++].value_f = + va_arg(ap, double); + break; + case 'p': + error->args[error->argc++].value_ptr = + va_arg(ap, void *); + break; + case 's': + { + int i = error->argc; + const char *str = va_arg(ap, const char *); + if (str == NULL) + str = "(null)"; + SDL_strlcpy((char *)error->args[i].buf, str, ERR_MAX_STRLEN); + error->argc++; + } + break; + default: + break; + } + if ( error->argc >= ERR_MAX_ARGS ) { + break; + } + } + } + va_end(ap); + + /* If we are in debug mode, print out an error message */ +#ifdef DEBUG_ERROR + fprintf(stderr, "SDL_SetError: %s\n", SDL_GetError()); +#endif +} + +/* This function has a bit more overhead than most error functions + so that it supports internationalization and thread-safe errors. +*/ +char *SDL_GetErrorMsg(char *errstr, unsigned int maxlen) +{ + SDL_error *error; + + /* Clear the error string */ + *errstr = '\0'; --maxlen; + + /* Get the thread-safe error, and print it out */ + error = SDL_GetErrBuf(); + if ( error->error ) { + const char *fmt; + char *msg = errstr; + int len; + int argi; + + fmt = SDL_LookupString(error->key); + argi = 0; + while ( *fmt && (maxlen > 0) ) { + if ( *fmt == '%' ) { + char tmp[32], *spot = tmp; + *spot++ = *fmt++; + while ( (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) && spot < (tmp+SDL_arraysize(tmp)-2) ) { + *spot++ = *fmt++; + } + *spot++ = *fmt++; + *spot++ = '\0'; + switch (spot[-2]) { + case '%': + *msg++ = '%'; + maxlen -= 1; + break; + case 'c': + case 'i': + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': + len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_i); + msg += len; + maxlen -= len; + break; + case 'f': + len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_f); + msg += len; + maxlen -= len; + break; + case 'p': + len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_ptr); + msg += len; + maxlen -= len; + break; + case 's': + len = SDL_snprintf(msg, maxlen, tmp, SDL_LookupString(error->args[argi++].buf)); + msg += len; + maxlen -= len; + break; + } + } else { + *msg++ = *fmt++; + maxlen -= 1; + } + } + *msg = 0; /* NULL terminate the string */ + } + return(errstr); +} + +/* Available for backwards compatibility */ +char *SDL_GetError (void) +{ + static char errmsg[SDL_ERRBUFIZE]; + + return((char *)SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE)); +} + +void SDL_ClearError(void) +{ + SDL_error *error; + + error = SDL_GetErrBuf(); + error->error = 0; +} + +/* Very common errors go here */ +void SDL_Error(SDL_errorcode code) +{ + switch (code) { + case SDL_ENOMEM: + SDL_SetError("Out of memory"); + break; + case SDL_EFREAD: + SDL_SetError("Error reading from datastream"); + break; + case SDL_EFWRITE: + SDL_SetError("Error writing to datastream"); + break; + case SDL_EFSEEK: + SDL_SetError("Error seeking in datastream"); + break; + default: + SDL_SetError("Unknown SDL error"); + break; + } +} + +#ifdef TEST_ERROR +int main(int argc, char *argv[]) +{ + char buffer[BUFSIZ+1]; + + SDL_SetError("Hi there!"); + printf("Error 1: %s\n", SDL_GetError()); + SDL_ClearError(); + SDL_memset(buffer, '1', BUFSIZ); + buffer[BUFSIZ] = 0; + SDL_SetError("This is the error: %s (%f)", buffer, 1.0); + printf("Error 2: %s\n", SDL_GetError()); + exit(0); +} +#endif diff --git a/3rdparty/SDL/src/SDL_error_c.h b/3rdparty/SDL/src/SDL_error_c.h new file mode 100644 index 0000000..8e54e42 --- /dev/null +++ b/3rdparty/SDL/src/SDL_error_c.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file defines a structure that carries language-independent + error messages +*/ + +#ifndef _SDL_error_c_h +#define _SDL_error_c_h + +#define ERR_MAX_STRLEN 128 +#define ERR_MAX_ARGS 5 + +typedef struct SDL_error { + /* This is a numeric value corresponding to the current error */ + int error; + + /* This is a key used to index into a language hashtable containing + internationalized versions of the SDL error messages. If the key + is not in the hashtable, or no hashtable is available, the key is + used directly as an error message format string. + */ + char key[ERR_MAX_STRLEN]; + + /* These are the arguments for the error functions */ + int argc; + union { + void *value_ptr; +#if 0 /* What is a character anyway? (UNICODE issues) */ + unsigned char value_c; +#endif + int value_i; + double value_f; + char buf[ERR_MAX_STRLEN]; + } args[ERR_MAX_ARGS]; +} SDL_error; + +#endif /* _SDL_error_c_h */ diff --git a/3rdparty/SDL/src/SDL_fatal.c b/3rdparty/SDL/src/SDL_fatal.c new file mode 100644 index 0000000..d422a01 --- /dev/null +++ b/3rdparty/SDL/src/SDL_fatal.c @@ -0,0 +1,134 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General fatal signal handling code for SDL */ + +#ifdef HAVE_SIGNAL_H + +#include <signal.h> + +#include "SDL.h" +#include "SDL_fatal.h" + +/* This installs some signal handlers for the more common fatal signals, + so that if the programmer is lazy, the app doesn't die so horribly if + the program crashes. +*/ + +static void SDL_Parachute(int sig) +{ + signal(sig, SIG_DFL); + SDL_Quit(); + raise(sig); +} + +static int SDL_fatal_signals[] = { + SIGSEGV, +#ifdef SIGBUS + SIGBUS, +#endif +#ifdef SIGFPE + SIGFPE, +#endif +#ifdef SIGQUIT + SIGQUIT, +#endif + 0 +}; + +void SDL_InstallParachute(void) +{ + /* Set a handler for any fatal signal not already handled */ + int i; +#ifdef HAVE_SIGACTION + struct sigaction action; + + for ( i=0; SDL_fatal_signals[i]; ++i ) { + sigaction(SDL_fatal_signals[i], NULL, &action); + if ( action.sa_handler == SIG_DFL ) { + action.sa_handler = SDL_Parachute; + sigaction(SDL_fatal_signals[i], &action, NULL); + } + } +#ifdef SIGALRM + /* Set SIGALRM to be ignored -- necessary on Solaris */ + sigaction(SIGALRM, NULL, &action); + if ( action.sa_handler == SIG_DFL ) { + action.sa_handler = SIG_IGN; + sigaction(SIGALRM, &action, NULL); + } +#endif +#else + void (*ohandler)(int); + + for ( i=0; SDL_fatal_signals[i]; ++i ) { + ohandler = signal(SDL_fatal_signals[i], SDL_Parachute); + if ( ohandler != SIG_DFL ) { + signal(SDL_fatal_signals[i], ohandler); + } + } +#endif /* HAVE_SIGACTION */ + return; +} + +void SDL_UninstallParachute(void) +{ + /* Remove a handler for any fatal signal handled */ + int i; +#ifdef HAVE_SIGACTION + struct sigaction action; + + for ( i=0; SDL_fatal_signals[i]; ++i ) { + sigaction(SDL_fatal_signals[i], NULL, &action); + if ( action.sa_handler == SDL_Parachute ) { + action.sa_handler = SIG_DFL; + sigaction(SDL_fatal_signals[i], &action, NULL); + } + } +#else + void (*ohandler)(int); + + for ( i=0; SDL_fatal_signals[i]; ++i ) { + ohandler = signal(SDL_fatal_signals[i], SIG_DFL); + if ( ohandler != SDL_Parachute ) { + signal(SDL_fatal_signals[i], ohandler); + } + } +#endif /* HAVE_SIGACTION */ +} + +#else + +/* No signals on this platform, nothing to do.. */ + +void SDL_InstallParachute(void) +{ + return; +} + +void SDL_UninstallParachute(void) +{ + return; +} + +#endif /* HAVE_SIGNAL_H */ diff --git a/3rdparty/SDL/src/SDL_fatal.h b/3rdparty/SDL/src/SDL_fatal.h new file mode 100644 index 0000000..6789784 --- /dev/null +++ b/3rdparty/SDL/src/SDL_fatal.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General fatal signal handling code for SDL */ + +extern void SDL_InstallParachute(void); +extern void SDL_UninstallParachute(void); + diff --git a/3rdparty/SDL/src/audio/SDL_audio.c b/3rdparty/SDL/src/audio/SDL_audio.c new file mode 100644 index 0000000..beb26e0 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audio.c @@ -0,0 +1,703 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include "SDL.h" +#include "SDL_audio_c.h" +#include "SDL_audiomem.h" +#include "SDL_sysaudio.h" + +#ifdef __OS2__ +/* We'll need the DosSetPriority() API! */ +#define INCL_DOSPROCESS +#include <os2.h> +#endif + +/* Available audio drivers */ +static AudioBootStrap *bootstrap[] = { +#if SDL_AUDIO_DRIVER_PULSE + &PULSE_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_ALSA + &ALSA_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_BSD + &BSD_AUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_OSS + &DSP_bootstrap, + &DMA_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_QNXNTO + &QNXNTOAUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_SUNAUDIO + &SUNAUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DMEDIA + &DMEDIA_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_ARTS + &ARTS_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_ESD + &ESD_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_NAS + &NAS_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DSOUND + &DSOUND_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_WAVEOUT + &WAVEOUT_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_PAUD + &Paud_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_BAUDIO + &BAUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_COREAUDIO + &COREAUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_SNDMGR + &SNDMGR_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_MINT + &MINTAUDIO_GSXB_bootstrap, + &MINTAUDIO_MCSN_bootstrap, + &MINTAUDIO_STFA_bootstrap, + &MINTAUDIO_XBIOS_bootstrap, + &MINTAUDIO_DMA8_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DISK + &DISKAUD_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DUMMY + &DUMMYAUD_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DC + &DCAUD_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_NDS + &NDSAUD_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_MMEAUDIO + &MMEAUDIO_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_DART + &DART_bootstrap, +#endif +#if SDL_AUDIO_DRIVER_EPOCAUDIO + &EPOCAudio_bootstrap, +#endif + NULL +}; +SDL_AudioDevice *current_audio = NULL; + +/* Various local functions */ +int SDL_AudioInit(const char *driver_name); +void SDL_AudioQuit(void); + +/* The general mixing thread function */ +int SDLCALL SDL_RunAudio(void *audiop) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *)audiop; + Uint8 *stream; + int stream_len; + void *udata; + void (SDLCALL *fill)(void *userdata,Uint8 *stream, int len); + int silence; + + /* Perform any thread setup */ + if ( audio->ThreadInit ) { + audio->ThreadInit(audio); + } + audio->threadid = SDL_ThreadID(); + + /* Set up the mixing function */ + fill = audio->spec.callback; + udata = audio->spec.userdata; + + if ( audio->convert.needed ) { + if ( audio->convert.src_format == AUDIO_U8 ) { + silence = 0x80; + } else { + silence = 0; + } + stream_len = audio->convert.len; + } else { + silence = audio->spec.silence; + stream_len = audio->spec.size; + } + +#ifdef __OS2__ + /* Increase the priority of this thread to make sure that + the audio will be continuous all the time! */ +#ifdef USE_DOSSETPRIORITY + if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) + { +#ifdef DEBUG_BUILD + printf("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", SDL_ThreadID()); +#endif + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); + } + else + { +#ifdef DEBUG_BUILD + printf("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID()); +#endif + DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0); + } +#endif +#endif + + /* Loop, filling the audio buffers */ + while ( audio->enabled ) { + + /* Fill the current buffer with sound */ + if ( audio->convert.needed ) { + if ( audio->convert.buf ) { + stream = audio->convert.buf; + } else { + continue; + } + } else { + stream = audio->GetAudioBuf(audio); + if ( stream == NULL ) { + stream = audio->fake_stream; + } + } + + SDL_memset(stream, silence, stream_len); + + if ( ! audio->paused ) { + SDL_mutexP(audio->mixer_lock); + (*fill)(udata, stream, stream_len); + SDL_mutexV(audio->mixer_lock); + } + + /* Convert the audio if necessary */ + if ( audio->convert.needed ) { + SDL_ConvertAudio(&audio->convert); + stream = audio->GetAudioBuf(audio); + if ( stream == NULL ) { + stream = audio->fake_stream; + } + SDL_memcpy(stream, audio->convert.buf, + audio->convert.len_cvt); + } + + /* Ready current buffer for play and change current buffer */ + if ( stream != audio->fake_stream ) { + audio->PlayAudio(audio); + } + + /* Wait for an audio buffer to become available */ + if ( stream == audio->fake_stream ) { + SDL_Delay((audio->spec.samples*1000)/audio->spec.freq); + } else { + audio->WaitAudio(audio); + } + } + + /* Wait for the audio to drain.. */ + if ( audio->WaitDone ) { + audio->WaitDone(audio); + } + +#ifdef __OS2__ +#ifdef DEBUG_BUILD + printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID()); +#endif +#endif + return(0); +} + +static void SDL_LockAudio_Default(SDL_AudioDevice *audio) +{ + if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) { + return; + } + SDL_mutexP(audio->mixer_lock); +} + +static void SDL_UnlockAudio_Default(SDL_AudioDevice *audio) +{ + if ( audio->thread && (SDL_ThreadID() == audio->threadid) ) { + return; + } + SDL_mutexV(audio->mixer_lock); +} + +static Uint16 SDL_ParseAudioFormat(const char *string) +{ + Uint16 format = 0; + + switch (*string) { + case 'U': + ++string; + format |= 0x0000; + break; + case 'S': + ++string; + format |= 0x8000; + break; + default: + return 0; + } + switch (SDL_atoi(string)) { + case 8: + string += 1; + format |= 8; + break; + case 16: + string += 2; + format |= 16; + if ( SDL_strcmp(string, "LSB") == 0 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + || SDL_strcmp(string, "SYS") == 0 +#endif + ) { + format |= 0x0000; + } + if ( SDL_strcmp(string, "MSB") == 0 +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + || SDL_strcmp(string, "SYS") == 0 +#endif + ) { + format |= 0x1000; + } + break; + default: + return 0; + } + return format; +} + +int SDL_AudioInit(const char *driver_name) +{ + SDL_AudioDevice *audio; + int i = 0, idx; + + /* Check to make sure we don't overwrite 'current_audio' */ + if ( current_audio != NULL ) { + SDL_AudioQuit(); + } + + /* Select the proper audio driver */ + audio = NULL; + idx = 0; +#if SDL_AUDIO_DRIVER_ESD + if ( (driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL) ) { + /* Ahem, we know that if ESPEAKER is set, user probably wants + to use ESD, but don't start it if it's not already running. + This probably isn't the place to do this, but... Shh! :) + */ + for ( i=0; bootstrap[i]; ++i ) { + if ( SDL_strcasecmp(bootstrap[i]->name, "esd") == 0 ) { +#ifdef HAVE_PUTENV + const char *esd_no_spawn; + + /* Don't start ESD if it's not running */ + esd_no_spawn = getenv("ESD_NO_SPAWN"); + if ( esd_no_spawn == NULL ) { + putenv("ESD_NO_SPAWN=1"); + } +#endif + if ( bootstrap[i]->available() ) { + audio = bootstrap[i]->create(0); + break; + } +#ifdef HAVE_UNSETENV + if ( esd_no_spawn == NULL ) { + unsetenv("ESD_NO_SPAWN"); + } +#endif + } + } + } +#endif /* SDL_AUDIO_DRIVER_ESD */ + if ( audio == NULL ) { + if ( driver_name != NULL ) { +#if 0 /* This will be replaced with a better driver selection API */ + if ( SDL_strrchr(driver_name, ':') != NULL ) { + idx = atoi(SDL_strrchr(driver_name, ':')+1); + } +#endif + for ( i=0; bootstrap[i]; ++i ) { + if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) { + if ( bootstrap[i]->available() ) { + audio=bootstrap[i]->create(idx); + break; + } + } + } + } else { + for ( i=0; bootstrap[i]; ++i ) { + if ( bootstrap[i]->available() ) { + audio = bootstrap[i]->create(idx); + if ( audio != NULL ) { + break; + } + } + } + } + if ( audio == NULL ) { + SDL_SetError("No available audio device"); +#if 0 /* Don't fail SDL_Init() if audio isn't available. + SDL_OpenAudio() will handle it at that point. *sigh* + */ + return(-1); +#endif + } + } + current_audio = audio; + if ( current_audio ) { + current_audio->name = bootstrap[i]->name; + if ( !current_audio->LockAudio && !current_audio->UnlockAudio ) { + current_audio->LockAudio = SDL_LockAudio_Default; + current_audio->UnlockAudio = SDL_UnlockAudio_Default; + } + } + return(0); +} + +char *SDL_AudioDriverName(char *namebuf, int maxlen) +{ + if ( current_audio != NULL ) { + SDL_strlcpy(namebuf, current_audio->name, maxlen); + return(namebuf); + } + return(NULL); +} + +int SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained) +{ + SDL_AudioDevice *audio; + const char *env; + + /* Start up the audio driver, if necessary */ + if ( ! current_audio ) { + if ( (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) || + (current_audio == NULL) ) { + return(-1); + } + } + audio = current_audio; + + if (audio->opened) { + SDL_SetError("Audio device is already opened"); + return(-1); + } + + /* Verify some parameters */ + if ( desired->freq == 0 ) { + env = SDL_getenv("SDL_AUDIO_FREQUENCY"); + if ( env ) { + desired->freq = SDL_atoi(env); + } + } + if ( desired->freq == 0 ) { + /* Pick some default audio frequency */ + desired->freq = 22050; + } + if ( desired->format == 0 ) { + env = SDL_getenv("SDL_AUDIO_FORMAT"); + if ( env ) { + desired->format = SDL_ParseAudioFormat(env); + } + } + if ( desired->format == 0 ) { + /* Pick some default audio format */ + desired->format = AUDIO_S16; + } + if ( desired->channels == 0 ) { + env = SDL_getenv("SDL_AUDIO_CHANNELS"); + if ( env ) { + desired->channels = (Uint8)SDL_atoi(env); + } + } + if ( desired->channels == 0 ) { + /* Pick a default number of channels */ + desired->channels = 2; + } + switch ( desired->channels ) { + case 1: /* Mono */ + case 2: /* Stereo */ + case 4: /* surround */ + case 6: /* surround with center and lfe */ + break; + default: + SDL_SetError("1 (mono) and 2 (stereo) channels supported"); + return(-1); + } + if ( desired->samples == 0 ) { + env = SDL_getenv("SDL_AUDIO_SAMPLES"); + if ( env ) { + desired->samples = (Uint16)SDL_atoi(env); + } + } + if ( desired->samples == 0 ) { + /* Pick a default of ~46 ms at desired frequency */ + int samples = (desired->freq / 1000) * 46; + int power2 = 1; + while ( power2 < samples ) { + power2 *= 2; + } + desired->samples = power2; + } + if ( desired->callback == NULL ) { + SDL_SetError("SDL_OpenAudio() passed a NULL callback"); + return(-1); + } + +#if SDL_THREADS_DISABLED + /* Uses interrupt driven audio, without thread */ +#else + /* Create a semaphore for locking the sound buffers */ + audio->mixer_lock = SDL_CreateMutex(); + if ( audio->mixer_lock == NULL ) { + SDL_SetError("Couldn't create mixer lock"); + SDL_CloseAudio(); + return(-1); + } +#endif /* SDL_THREADS_DISABLED */ + + /* Calculate the silence and size of the audio specification */ + SDL_CalculateAudioSpec(desired); + + /* Open the audio subsystem */ + SDL_memcpy(&audio->spec, desired, sizeof(audio->spec)); + audio->convert.needed = 0; + audio->enabled = 1; + audio->paused = 1; + + audio->opened = audio->OpenAudio(audio, &audio->spec)+1; + + if ( ! audio->opened ) { + SDL_CloseAudio(); + return(-1); + } + + /* If the audio driver changes the buffer size, accept it */ + if ( audio->spec.samples != desired->samples ) { + desired->samples = audio->spec.samples; + SDL_CalculateAudioSpec(desired); + } + + /* Allocate a fake audio memory buffer */ + audio->fake_stream = SDL_AllocAudioMem(audio->spec.size); + if ( audio->fake_stream == NULL ) { + SDL_CloseAudio(); + SDL_OutOfMemory(); + return(-1); + } + + /* See if we need to do any conversion */ + if ( obtained != NULL ) { + SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec)); + } else if ( desired->freq != audio->spec.freq || + desired->format != audio->spec.format || + desired->channels != audio->spec.channels ) { + /* Build an audio conversion block */ + if ( SDL_BuildAudioCVT(&audio->convert, + desired->format, desired->channels, + desired->freq, + audio->spec.format, audio->spec.channels, + audio->spec.freq) < 0 ) { + SDL_CloseAudio(); + return(-1); + } + if ( audio->convert.needed ) { + audio->convert.len = (int) ( ((double) audio->spec.size) / + audio->convert.len_ratio ); + audio->convert.buf =(Uint8 *)SDL_AllocAudioMem( + audio->convert.len*audio->convert.len_mult); + if ( audio->convert.buf == NULL ) { + SDL_CloseAudio(); + SDL_OutOfMemory(); + return(-1); + } + } + } + + /* Start the audio thread if necessary */ + switch (audio->opened) { + case 1: + /* Start the audio thread */ +#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__) +#undef SDL_CreateThread + audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL); +#else + audio->thread = SDL_CreateThread(SDL_RunAudio, audio); +#endif + if ( audio->thread == NULL ) { + SDL_CloseAudio(); + SDL_SetError("Couldn't create audio thread"); + return(-1); + } + break; + + default: + /* The audio is now playing */ + break; + } + + return(0); +} + +SDL_audiostatus SDL_GetAudioStatus(void) +{ + SDL_AudioDevice *audio = current_audio; + SDL_audiostatus status; + + status = SDL_AUDIO_STOPPED; + if ( audio && audio->enabled ) { + if ( audio->paused ) { + status = SDL_AUDIO_PAUSED; + } else { + status = SDL_AUDIO_PLAYING; + } + } + return(status); +} + +void SDL_PauseAudio (int pause_on) +{ + SDL_AudioDevice *audio = current_audio; + + if ( audio ) { + audio->paused = pause_on; + } +} + +void SDL_LockAudio (void) +{ + SDL_AudioDevice *audio = current_audio; + + /* Obtain a lock on the mixing buffers */ + if ( audio && audio->LockAudio ) { + audio->LockAudio(audio); + } +} + +void SDL_UnlockAudio (void) +{ + SDL_AudioDevice *audio = current_audio; + + /* Release lock on the mixing buffers */ + if ( audio && audio->UnlockAudio ) { + audio->UnlockAudio(audio); + } +} + +void SDL_CloseAudio (void) +{ + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +void SDL_AudioQuit(void) +{ + SDL_AudioDevice *audio = current_audio; + + if ( audio ) { + audio->enabled = 0; + if ( audio->thread != NULL ) { + SDL_WaitThread(audio->thread, NULL); + } + if ( audio->mixer_lock != NULL ) { + SDL_DestroyMutex(audio->mixer_lock); + } + if ( audio->fake_stream != NULL ) { + SDL_FreeAudioMem(audio->fake_stream); + } + if ( audio->convert.needed ) { + SDL_FreeAudioMem(audio->convert.buf); + + } + if ( audio->opened ) { + audio->CloseAudio(audio); + audio->opened = 0; + } + /* Free the driver data */ + audio->free(audio); + current_audio = NULL; + } +} + +#define NUM_FORMATS 6 +static int format_idx; +static int format_idx_sub; +static Uint16 format_list[NUM_FORMATS][NUM_FORMATS] = { + { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB }, + { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB }, + { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 }, + { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 }, + { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 }, + { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 }, +}; + +Uint16 SDL_FirstAudioFormat(Uint16 format) +{ + for ( format_idx=0; format_idx < NUM_FORMATS; ++format_idx ) { + if ( format_list[format_idx][0] == format ) { + break; + } + } + format_idx_sub = 0; + return(SDL_NextAudioFormat()); +} + +Uint16 SDL_NextAudioFormat(void) +{ + if ( (format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS) ) { + return(0); + } + return(format_list[format_idx][format_idx_sub++]); +} + +void SDL_CalculateAudioSpec(SDL_AudioSpec *spec) +{ + switch (spec->format) { + case AUDIO_U8: + spec->silence = 0x80; + break; + default: + spec->silence = 0x00; + break; + } + spec->size = (spec->format&0xFF)/8; + spec->size *= spec->channels; + spec->size *= spec->samples; +} + +void SDL_Audio_SetCaption(const char *caption) +{ + if ((current_audio) && (current_audio->SetCaption)) { + current_audio->SetCaption(current_audio, caption); + } +} + diff --git a/3rdparty/SDL/src/audio/SDL_audio_c.h b/3rdparty/SDL/src/audio/SDL_audio_c.h new file mode 100644 index 0000000..5fcf202 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audio_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Functions and variables exported from SDL_audio.c for SDL_sysaudio.c */ + +/* Functions to get a list of "close" audio formats */ +extern Uint16 SDL_FirstAudioFormat(Uint16 format); +extern Uint16 SDL_NextAudioFormat(void); + +/* Function to calculate the size and silence for a SDL_AudioSpec */ +extern void SDL_CalculateAudioSpec(SDL_AudioSpec *spec); + +/* The actual mixing thread function */ +extern int SDLCALL SDL_RunAudio(void *audiop); + diff --git a/3rdparty/SDL/src/audio/SDL_audiocvt.c b/3rdparty/SDL/src/audio/SDL_audiocvt.c new file mode 100644 index 0000000..9b8fbcd --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audiocvt.c @@ -0,0 +1,1510 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Functions for audio drivers to perform runtime conversion of audio format */ + +#include "SDL_audio.h" + + +/* Effectively mix right and left channels into a single channel */ +void SDLCALL SDL_ConvertMono(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Sint32 sample; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting to mono\n"); +#endif + switch (format&0x8018) { + + case AUDIO_U8: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + for ( i=cvt->len_cvt/2; i; --i ) { + sample = src[0] + src[1]; + *dst = (Uint8)(sample / 2); + src += 2; + dst += 1; + } + } + break; + + case AUDIO_S8: { + Sint8 *src, *dst; + + src = (Sint8 *)cvt->buf; + dst = (Sint8 *)cvt->buf; + for ( i=cvt->len_cvt/2; i; --i ) { + sample = src[0] + src[1]; + *dst = (Sint8)(sample / 2); + src += 2; + dst += 1; + } + } + break; + + case AUDIO_U16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + sample = (Uint16)((src[0]<<8)|src[1])+ + (Uint16)((src[2]<<8)|src[3]); + sample /= 2; + dst[1] = (sample&0xFF); + sample >>= 8; + dst[0] = (sample&0xFF); + src += 4; + dst += 2; + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + sample = (Uint16)((src[1]<<8)|src[0])+ + (Uint16)((src[3]<<8)|src[2]); + sample /= 2; + dst[0] = (sample&0xFF); + sample >>= 8; + dst[1] = (sample&0xFF); + src += 4; + dst += 2; + } + } + } + break; + + case AUDIO_S16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + sample = (Sint16)((src[0]<<8)|src[1])+ + (Sint16)((src[2]<<8)|src[3]); + sample /= 2; + dst[1] = (sample&0xFF); + sample >>= 8; + dst[0] = (sample&0xFF); + src += 4; + dst += 2; + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + sample = (Sint16)((src[1]<<8)|src[0])+ + (Sint16)((src[3]<<8)|src[2]); + sample /= 2; + dst[0] = (sample&0xFF); + sample >>= 8; + dst[1] = (sample&0xFF); + src += 4; + dst += 2; + } + } + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Discard top 4 channels */ +void SDLCALL SDL_ConvertStrip(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Sint32 lsample, rsample; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting down to stereo\n"); +#endif + switch (format&0x8018) { + + case AUDIO_U8: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + for ( i=cvt->len_cvt/6; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 6; + dst += 2; + } + } + break; + + case AUDIO_S8: { + Sint8 *src, *dst; + + src = (Sint8 *)cvt->buf; + dst = (Sint8 *)cvt->buf; + for ( i=cvt->len_cvt/6; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 6; + dst += 2; + } + } + break; + + case AUDIO_U16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/12; i; --i ) { + lsample = (Uint16)((src[0]<<8)|src[1]); + rsample = (Uint16)((src[2]<<8)|src[3]); + dst[1] = (lsample&0xFF); + lsample >>= 8; + dst[0] = (lsample&0xFF); + dst[3] = (rsample&0xFF); + rsample >>= 8; + dst[2] = (rsample&0xFF); + src += 12; + dst += 4; + } + } else { + for ( i=cvt->len_cvt/12; i; --i ) { + lsample = (Uint16)((src[1]<<8)|src[0]); + rsample = (Uint16)((src[3]<<8)|src[2]); + dst[0] = (lsample&0xFF); + lsample >>= 8; + dst[1] = (lsample&0xFF); + dst[2] = (rsample&0xFF); + rsample >>= 8; + dst[3] = (rsample&0xFF); + src += 12; + dst += 4; + } + } + } + break; + + case AUDIO_S16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/12; i; --i ) { + lsample = (Sint16)((src[0]<<8)|src[1]); + rsample = (Sint16)((src[2]<<8)|src[3]); + dst[1] = (lsample&0xFF); + lsample >>= 8; + dst[0] = (lsample&0xFF); + dst[3] = (rsample&0xFF); + rsample >>= 8; + dst[2] = (rsample&0xFF); + src += 12; + dst += 4; + } + } else { + for ( i=cvt->len_cvt/12; i; --i ) { + lsample = (Sint16)((src[1]<<8)|src[0]); + rsample = (Sint16)((src[3]<<8)|src[2]); + dst[0] = (lsample&0xFF); + lsample >>= 8; + dst[1] = (lsample&0xFF); + dst[2] = (rsample&0xFF); + rsample >>= 8; + dst[3] = (rsample&0xFF); + src += 12; + dst += 4; + } + } + } + break; + } + cvt->len_cvt /= 3; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Discard top 2 channels of 6 */ +void SDLCALL SDL_ConvertStrip_2(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Sint32 lsample, rsample; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting 6 down to quad\n"); +#endif + switch (format&0x8018) { + + case AUDIO_U8: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + for ( i=cvt->len_cvt/4; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 4; + dst += 2; + } + } + break; + + case AUDIO_S8: { + Sint8 *src, *dst; + + src = (Sint8 *)cvt->buf; + dst = (Sint8 *)cvt->buf; + for ( i=cvt->len_cvt/4; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 4; + dst += 2; + } + } + break; + + case AUDIO_U16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/8; i; --i ) { + lsample = (Uint16)((src[0]<<8)|src[1]); + rsample = (Uint16)((src[2]<<8)|src[3]); + dst[1] = (lsample&0xFF); + lsample >>= 8; + dst[0] = (lsample&0xFF); + dst[3] = (rsample&0xFF); + rsample >>= 8; + dst[2] = (rsample&0xFF); + src += 8; + dst += 4; + } + } else { + for ( i=cvt->len_cvt/8; i; --i ) { + lsample = (Uint16)((src[1]<<8)|src[0]); + rsample = (Uint16)((src[3]<<8)|src[2]); + dst[0] = (lsample&0xFF); + lsample >>= 8; + dst[1] = (lsample&0xFF); + dst[2] = (rsample&0xFF); + rsample >>= 8; + dst[3] = (rsample&0xFF); + src += 8; + dst += 4; + } + } + } + break; + + case AUDIO_S16: { + Uint8 *src, *dst; + + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/8; i; --i ) { + lsample = (Sint16)((src[0]<<8)|src[1]); + rsample = (Sint16)((src[2]<<8)|src[3]); + dst[1] = (lsample&0xFF); + lsample >>= 8; + dst[0] = (lsample&0xFF); + dst[3] = (rsample&0xFF); + rsample >>= 8; + dst[2] = (rsample&0xFF); + src += 8; + dst += 4; + } + } else { + for ( i=cvt->len_cvt/8; i; --i ) { + lsample = (Sint16)((src[1]<<8)|src[0]); + rsample = (Sint16)((src[3]<<8)|src[2]); + dst[0] = (lsample&0xFF); + lsample >>= 8; + dst[1] = (lsample&0xFF); + dst[2] = (rsample&0xFF); + rsample >>= 8; + dst[3] = (rsample&0xFF); + src += 8; + dst += 4; + } + } + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Duplicate a mono channel to both stereo channels */ +void SDLCALL SDL_ConvertStereo(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting to stereo\n"); +#endif + if ( (format & 0xFF) == 16 ) { + Uint16 *src, *dst; + + src = (Uint16 *)(cvt->buf+cvt->len_cvt); + dst = (Uint16 *)(cvt->buf+cvt->len_cvt*2); + for ( i=cvt->len_cvt/2; i; --i ) { + dst -= 2; + src -= 1; + dst[0] = src[0]; + dst[1] = src[0]; + } + } else { + Uint8 *src, *dst; + + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + for ( i=cvt->len_cvt; i; --i ) { + dst -= 2; + src -= 1; + dst[0] = src[0]; + dst[1] = src[0]; + } + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Duplicate a stereo channel to a pseudo-5.1 stream */ +void SDLCALL SDL_ConvertSurround(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting stereo to surround\n"); +#endif + switch (format&0x8018) { + + case AUDIO_U8: { + Uint8 *src, *dst, lf, rf, ce; + + src = (Uint8 *)(cvt->buf+cvt->len_cvt); + dst = (Uint8 *)(cvt->buf+cvt->len_cvt*3); + for ( i=cvt->len_cvt; i; --i ) { + dst -= 6; + src -= 2; + lf = src[0]; + rf = src[1]; + ce = (lf/2) + (rf/2); + dst[0] = lf; + dst[1] = rf; + dst[2] = lf - ce; + dst[3] = rf - ce; + dst[4] = ce; + dst[5] = ce; + } + } + break; + + case AUDIO_S8: { + Sint8 *src, *dst, lf, rf, ce; + + src = (Sint8 *)cvt->buf+cvt->len_cvt; + dst = (Sint8 *)cvt->buf+cvt->len_cvt*3; + for ( i=cvt->len_cvt; i; --i ) { + dst -= 6; + src -= 2; + lf = src[0]; + rf = src[1]; + ce = (lf/2) + (rf/2); + dst[0] = lf; + dst[1] = rf; + dst[2] = lf - ce; + dst[3] = rf - ce; + dst[4] = ce; + dst[5] = ce; + } + } + break; + + case AUDIO_U16: { + Uint8 *src, *dst; + Uint16 lf, rf, ce, lr, rr; + + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*3; + + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 12; + src -= 4; + lf = (Uint16)((src[0]<<8)|src[1]); + rf = (Uint16)((src[2]<<8)|src[3]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[1] = (lf&0xFF); + dst[0] = ((lf>>8)&0xFF); + dst[3] = (rf&0xFF); + dst[2] = ((rf>>8)&0xFF); + + dst[1+4] = (lr&0xFF); + dst[0+4] = ((lr>>8)&0xFF); + dst[3+4] = (rr&0xFF); + dst[2+4] = ((rr>>8)&0xFF); + + dst[1+8] = (ce&0xFF); + dst[0+8] = ((ce>>8)&0xFF); + dst[3+8] = (ce&0xFF); + dst[2+8] = ((ce>>8)&0xFF); + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 12; + src -= 4; + lf = (Uint16)((src[1]<<8)|src[0]); + rf = (Uint16)((src[3]<<8)|src[2]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[0] = (lf&0xFF); + dst[1] = ((lf>>8)&0xFF); + dst[2] = (rf&0xFF); + dst[3] = ((rf>>8)&0xFF); + + dst[0+4] = (lr&0xFF); + dst[1+4] = ((lr>>8)&0xFF); + dst[2+4] = (rr&0xFF); + dst[3+4] = ((rr>>8)&0xFF); + + dst[0+8] = (ce&0xFF); + dst[1+8] = ((ce>>8)&0xFF); + dst[2+8] = (ce&0xFF); + dst[3+8] = ((ce>>8)&0xFF); + } + } + } + break; + + case AUDIO_S16: { + Uint8 *src, *dst; + Sint16 lf, rf, ce, lr, rr; + + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*3; + + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 12; + src -= 4; + lf = (Sint16)((src[0]<<8)|src[1]); + rf = (Sint16)((src[2]<<8)|src[3]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[1] = (lf&0xFF); + dst[0] = ((lf>>8)&0xFF); + dst[3] = (rf&0xFF); + dst[2] = ((rf>>8)&0xFF); + + dst[1+4] = (lr&0xFF); + dst[0+4] = ((lr>>8)&0xFF); + dst[3+4] = (rr&0xFF); + dst[2+4] = ((rr>>8)&0xFF); + + dst[1+8] = (ce&0xFF); + dst[0+8] = ((ce>>8)&0xFF); + dst[3+8] = (ce&0xFF); + dst[2+8] = ((ce>>8)&0xFF); + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 12; + src -= 4; + lf = (Sint16)((src[1]<<8)|src[0]); + rf = (Sint16)((src[3]<<8)|src[2]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[0] = (lf&0xFF); + dst[1] = ((lf>>8)&0xFF); + dst[2] = (rf&0xFF); + dst[3] = ((rf>>8)&0xFF); + + dst[0+4] = (lr&0xFF); + dst[1+4] = ((lr>>8)&0xFF); + dst[2+4] = (rr&0xFF); + dst[3+4] = ((rr>>8)&0xFF); + + dst[0+8] = (ce&0xFF); + dst[1+8] = ((ce>>8)&0xFF); + dst[2+8] = (ce&0xFF); + dst[3+8] = ((ce>>8)&0xFF); + } + } + } + break; + } + cvt->len_cvt *= 3; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Duplicate a stereo channel to a pseudo-4.0 stream */ +void SDLCALL SDL_ConvertSurround_4(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting stereo to quad\n"); +#endif + switch (format&0x8018) { + + case AUDIO_U8: { + Uint8 *src, *dst, lf, rf, ce; + + src = (Uint8 *)(cvt->buf+cvt->len_cvt); + dst = (Uint8 *)(cvt->buf+cvt->len_cvt*2); + for ( i=cvt->len_cvt; i; --i ) { + dst -= 4; + src -= 2; + lf = src[0]; + rf = src[1]; + ce = (lf/2) + (rf/2); + dst[0] = lf; + dst[1] = rf; + dst[2] = lf - ce; + dst[3] = rf - ce; + } + } + break; + + case AUDIO_S8: { + Sint8 *src, *dst, lf, rf, ce; + + src = (Sint8 *)cvt->buf+cvt->len_cvt; + dst = (Sint8 *)cvt->buf+cvt->len_cvt*2; + for ( i=cvt->len_cvt; i; --i ) { + dst -= 4; + src -= 2; + lf = src[0]; + rf = src[1]; + ce = (lf/2) + (rf/2); + dst[0] = lf; + dst[1] = rf; + dst[2] = lf - ce; + dst[3] = rf - ce; + } + } + break; + + case AUDIO_U16: { + Uint8 *src, *dst; + Uint16 lf, rf, ce, lr, rr; + + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 8; + src -= 4; + lf = (Uint16)((src[0]<<8)|src[1]); + rf = (Uint16)((src[2]<<8)|src[3]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[1] = (lf&0xFF); + dst[0] = ((lf>>8)&0xFF); + dst[3] = (rf&0xFF); + dst[2] = ((rf>>8)&0xFF); + + dst[1+4] = (lr&0xFF); + dst[0+4] = ((lr>>8)&0xFF); + dst[3+4] = (rr&0xFF); + dst[2+4] = ((rr>>8)&0xFF); + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 8; + src -= 4; + lf = (Uint16)((src[1]<<8)|src[0]); + rf = (Uint16)((src[3]<<8)|src[2]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[0] = (lf&0xFF); + dst[1] = ((lf>>8)&0xFF); + dst[2] = (rf&0xFF); + dst[3] = ((rf>>8)&0xFF); + + dst[0+4] = (lr&0xFF); + dst[1+4] = ((lr>>8)&0xFF); + dst[2+4] = (rr&0xFF); + dst[3+4] = ((rr>>8)&0xFF); + } + } + } + break; + + case AUDIO_S16: { + Uint8 *src, *dst; + Sint16 lf, rf, ce, lr, rr; + + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + + if ( (format & 0x1000) == 0x1000 ) { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 8; + src -= 4; + lf = (Sint16)((src[0]<<8)|src[1]); + rf = (Sint16)((src[2]<<8)|src[3]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[1] = (lf&0xFF); + dst[0] = ((lf>>8)&0xFF); + dst[3] = (rf&0xFF); + dst[2] = ((rf>>8)&0xFF); + + dst[1+4] = (lr&0xFF); + dst[0+4] = ((lr>>8)&0xFF); + dst[3+4] = (rr&0xFF); + dst[2+4] = ((rr>>8)&0xFF); + } + } else { + for ( i=cvt->len_cvt/4; i; --i ) { + dst -= 8; + src -= 4; + lf = (Sint16)((src[1]<<8)|src[0]); + rf = (Sint16)((src[3]<<8)|src[2]); + ce = (lf/2) + (rf/2); + rr = lf - ce; + lr = rf - ce; + dst[0] = (lf&0xFF); + dst[1] = ((lf>>8)&0xFF); + dst[2] = (rf&0xFF); + dst[3] = ((rf>>8)&0xFF); + + dst[0+4] = (lr&0xFF); + dst[1+4] = ((lr>>8)&0xFF); + dst[2+4] = (rr&0xFF); + dst[3+4] = ((rr>>8)&0xFF); + } + } + } + break; + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Convert 8-bit to 16-bit - LSB */ +void SDLCALL SDL_Convert16LSB(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting to 16-bit LSB\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + for ( i=cvt->len_cvt; i; --i ) { + src -= 1; + dst -= 2; + dst[1] = *src; + dst[0] = 0; + } + format = ((format & ~0x0008) | AUDIO_U16LSB); + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} +/* Convert 8-bit to 16-bit - MSB */ +void SDLCALL SDL_Convert16MSB(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting to 16-bit MSB\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + for ( i=cvt->len_cvt; i; --i ) { + src -= 1; + dst -= 2; + dst[0] = *src; + dst[1] = 0; + } + format = ((format & ~0x0008) | AUDIO_U16MSB); + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Convert 16-bit to 8-bit */ +void SDLCALL SDL_Convert8(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting to 8-bit\n"); +#endif + src = cvt->buf; + dst = cvt->buf; + if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ + ++src; + } + for ( i=cvt->len_cvt/2; i; --i ) { + *dst = *src; + src += 2; + dst += 1; + } + format = ((format & ~0x9010) | AUDIO_U8); + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Toggle signed/unsigned */ +void SDLCALL SDL_ConvertSign(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *data; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio signedness\n"); +#endif + data = cvt->buf; + if ( (format & 0xFF) == 16 ) { + if ( (format & 0x1000) != 0x1000 ) { /* Little endian */ + ++data; + } + for ( i=cvt->len_cvt/2; i; --i ) { + *data ^= 0x80; + data += 2; + } + } else { + for ( i=cvt->len_cvt; i; --i ) { + *data++ ^= 0x80; + } + } + format = (format ^ 0x8000); + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Toggle endianness */ +void SDLCALL SDL_ConvertEndian(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *data, tmp; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio endianness\n"); +#endif + data = cvt->buf; + for ( i=cvt->len_cvt/2; i; --i ) { + tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; + data += 2; + } + format = (format ^ 0x1000); + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Convert rate up by multiple of 2 */ +void SDLCALL SDL_RateMUL2(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate * 2\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt; i; --i ) { + src -= 1; + dst -= 2; + dst[0] = src[0]; + dst[1] = src[0]; + } + break; + case 16: + for ( i=cvt->len_cvt/2; i; --i ) { + src -= 2; + dst -= 4; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[1]; + } + break; + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Convert rate up by multiple of 2, for stereo */ +void SDLCALL SDL_RateMUL2_c2(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate * 2\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/2; i; --i ) { + src -= 2; + dst -= 4; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[1]; + } + break; + case 16: + for ( i=cvt->len_cvt/4; i; --i ) { + src -= 4; + dst -= 8; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[0]; + dst[5] = src[1]; + dst[6] = src[2]; + dst[7] = src[3]; + } + break; + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Convert rate up by multiple of 2, for quad */ +void SDLCALL SDL_RateMUL2_c4(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate * 2\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/4; i; --i ) { + src -= 4; + dst -= 8; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[0]; + dst[5] = src[1]; + dst[6] = src[2]; + dst[7] = src[3]; + } + break; + case 16: + for ( i=cvt->len_cvt/8; i; --i ) { + src -= 8; + dst -= 16; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; + dst[8] = src[0]; + dst[9] = src[1]; + dst[10] = src[2]; + dst[11] = src[3]; + dst[12] = src[4]; + dst[13] = src[5]; + dst[14] = src[6]; + dst[15] = src[7]; + } + break; + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Convert rate up by multiple of 2, for 5.1 */ +void SDLCALL SDL_RateMUL2_c6(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate * 2\n"); +#endif + src = cvt->buf+cvt->len_cvt; + dst = cvt->buf+cvt->len_cvt*2; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/6; i; --i ) { + src -= 6; + dst -= 12; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[0]; + dst[7] = src[1]; + dst[8] = src[2]; + dst[9] = src[3]; + dst[10] = src[4]; + dst[11] = src[5]; + } + break; + case 16: + for ( i=cvt->len_cvt/12; i; --i ) { + src -= 12; + dst -= 24; + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; + dst[8] = src[8]; + dst[9] = src[9]; + dst[10] = src[10]; + dst[11] = src[11]; + dst[12] = src[0]; + dst[13] = src[1]; + dst[14] = src[2]; + dst[15] = src[3]; + dst[16] = src[4]; + dst[17] = src[5]; + dst[18] = src[6]; + dst[19] = src[7]; + dst[20] = src[8]; + dst[21] = src[9]; + dst[22] = src[10]; + dst[23] = src[11]; + } + break; + } + cvt->len_cvt *= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Convert rate down by multiple of 2 */ +void SDLCALL SDL_RateDIV2(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate / 2\n"); +#endif + src = cvt->buf; + dst = cvt->buf; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/2; i; --i ) { + dst[0] = src[0]; + src += 2; + dst += 1; + } + break; + case 16: + for ( i=cvt->len_cvt/4; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 4; + dst += 2; + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Convert rate down by multiple of 2, for stereo */ +void SDLCALL SDL_RateDIV2_c2(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate / 2\n"); +#endif + src = cvt->buf; + dst = cvt->buf; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/4; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + src += 4; + dst += 2; + } + break; + case 16: + for ( i=cvt->len_cvt/8; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + src += 8; + dst += 4; + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + + +/* Convert rate down by multiple of 2, for quad */ +void SDLCALL SDL_RateDIV2_c4(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate / 2\n"); +#endif + src = cvt->buf; + dst = cvt->buf; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/8; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + src += 8; + dst += 4; + } + break; + case 16: + for ( i=cvt->len_cvt/16; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; + src += 16; + dst += 8; + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Convert rate down by multiple of 2, for 5.1 */ +void SDLCALL SDL_RateDIV2_c6(SDL_AudioCVT *cvt, Uint16 format) +{ + int i; + Uint8 *src, *dst; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate / 2\n"); +#endif + src = cvt->buf; + dst = cvt->buf; + switch (format & 0xFF) { + case 8: + for ( i=cvt->len_cvt/12; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + src += 12; + dst += 6; + } + break; + case 16: + for ( i=cvt->len_cvt/24; i; --i ) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; + dst[8] = src[8]; + dst[9] = src[9]; + dst[10] = src[10]; + dst[11] = src[11]; + src += 24; + dst += 12; + } + break; + } + cvt->len_cvt /= 2; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +/* Very slow rate conversion routine */ +void SDLCALL SDL_RateSLOW(SDL_AudioCVT *cvt, Uint16 format) +{ + double ipos; + int i, clen; + +#ifdef DEBUG_CONVERT + fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0/cvt->rate_incr); +#endif + clen = (int)((double)cvt->len_cvt / cvt->rate_incr); + if ( cvt->rate_incr > 1.0 ) { + switch (format & 0xFF) { + case 8: { + Uint8 *output; + + output = cvt->buf; + ipos = 0.0; + for ( i=clen; i; --i ) { + *output = cvt->buf[(int)ipos]; + ipos += cvt->rate_incr; + output += 1; + } + } + break; + + case 16: { + Uint16 *output; + + clen &= ~1; + output = (Uint16 *)cvt->buf; + ipos = 0.0; + for ( i=clen/2; i; --i ) { + *output=((Uint16 *)cvt->buf)[(int)ipos]; + ipos += cvt->rate_incr; + output += 1; + } + } + break; + } + } else { + switch (format & 0xFF) { + case 8: { + Uint8 *output; + + output = cvt->buf+clen; + ipos = (double)cvt->len_cvt; + for ( i=clen; i; --i ) { + ipos -= cvt->rate_incr; + output -= 1; + *output = cvt->buf[(int)ipos]; + } + } + break; + + case 16: { + Uint16 *output; + + clen &= ~1; + output = (Uint16 *)(cvt->buf+clen); + ipos = (double)cvt->len_cvt/2; + for ( i=clen/2; i; --i ) { + ipos -= cvt->rate_incr; + output -= 1; + *output=((Uint16 *)cvt->buf)[(int)ipos]; + } + } + break; + } + } + cvt->len_cvt = clen; + if ( cvt->filters[++cvt->filter_index] ) { + cvt->filters[cvt->filter_index](cvt, format); + } +} + +int SDL_ConvertAudio(SDL_AudioCVT *cvt) +{ + /* Make sure there's data to convert */ + if ( cvt->buf == NULL ) { + SDL_SetError("No buffer allocated for conversion"); + return(-1); + } + /* Return okay if no conversion is necessary */ + cvt->len_cvt = cvt->len; + if ( cvt->filters[0] == NULL ) { + return(0); + } + + /* Set up the conversion and go! */ + cvt->filter_index = 0; + cvt->filters[0](cvt, cvt->src_format); + return(0); +} + +/* Creates a set of audio filters to convert from one format to another. + Returns -1 if the format conversion is not supported, or 1 if the + audio filter is set up. +*/ + +int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, + Uint16 src_format, Uint8 src_channels, int src_rate, + Uint16 dst_format, Uint8 dst_channels, int dst_rate) +{ +/*printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n", + src_format, dst_format, src_channels, dst_channels, src_rate, dst_rate);*/ + /* Start off with no conversion necessary */ + cvt->needed = 0; + cvt->filter_index = 0; + cvt->filters[0] = NULL; + cvt->len_mult = 1; + cvt->len_ratio = 1.0; + + /* First filter: Endian conversion from src to dst */ + if ( (src_format & 0x1000) != (dst_format & 0x1000) + && ((src_format & 0xff) == 16) && ((dst_format & 0xff) == 16)) { + cvt->filters[cvt->filter_index++] = SDL_ConvertEndian; + } + + /* Second filter: Sign conversion -- signed/unsigned */ + if ( (src_format & 0x8000) != (dst_format & 0x8000) ) { + cvt->filters[cvt->filter_index++] = SDL_ConvertSign; + } + + /* Next filter: Convert 16 bit <--> 8 bit PCM */ + if ( (src_format & 0xFF) != (dst_format & 0xFF) ) { + switch (dst_format&0x10FF) { + case AUDIO_U8: + cvt->filters[cvt->filter_index++] = + SDL_Convert8; + cvt->len_ratio /= 2; + break; + case AUDIO_U16LSB: + cvt->filters[cvt->filter_index++] = + SDL_Convert16LSB; + cvt->len_mult *= 2; + cvt->len_ratio *= 2; + break; + case AUDIO_U16MSB: + cvt->filters[cvt->filter_index++] = + SDL_Convert16MSB; + cvt->len_mult *= 2; + cvt->len_ratio *= 2; + break; + } + } + + /* Last filter: Mono/Stereo conversion */ + if ( src_channels != dst_channels ) { + if ( (src_channels == 1) && (dst_channels > 1) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertStereo; + cvt->len_mult *= 2; + src_channels = 2; + cvt->len_ratio *= 2; + } + if ( (src_channels == 2) && + (dst_channels == 6) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertSurround; + src_channels = 6; + cvt->len_mult *= 3; + cvt->len_ratio *= 3; + } + if ( (src_channels == 2) && + (dst_channels == 4) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertSurround_4; + src_channels = 4; + cvt->len_mult *= 2; + cvt->len_ratio *= 2; + } + while ( (src_channels*2) <= dst_channels ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertStereo; + cvt->len_mult *= 2; + src_channels *= 2; + cvt->len_ratio *= 2; + } + if ( (src_channels == 6) && + (dst_channels <= 2) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertStrip; + src_channels = 2; + cvt->len_ratio /= 3; + } + if ( (src_channels == 6) && + (dst_channels == 4) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertStrip_2; + src_channels = 4; + cvt->len_ratio /= 2; + } + /* This assumes that 4 channel audio is in the format: + Left {front/back} + Right {front/back} + so converting to L/R stereo works properly. + */ + while ( ((src_channels%2) == 0) && + ((src_channels/2) >= dst_channels) ) { + cvt->filters[cvt->filter_index++] = + SDL_ConvertMono; + src_channels /= 2; + cvt->len_ratio /= 2; + } + if ( src_channels != dst_channels ) { + /* Uh oh.. */; + } + } + + /* Do rate conversion */ + cvt->rate_incr = 0.0; + if ( (src_rate/100) != (dst_rate/100) ) { + Uint32 hi_rate, lo_rate; + int len_mult; + double len_ratio; + void (SDLCALL *rate_cvt)(SDL_AudioCVT *cvt, Uint16 format); + + if ( src_rate > dst_rate ) { + hi_rate = src_rate; + lo_rate = dst_rate; + switch (src_channels) { + case 1: rate_cvt = SDL_RateDIV2; break; + case 2: rate_cvt = SDL_RateDIV2_c2; break; + case 4: rate_cvt = SDL_RateDIV2_c4; break; + case 6: rate_cvt = SDL_RateDIV2_c6; break; + default: return -1; + } + len_mult = 1; + len_ratio = 0.5; + } else { + hi_rate = dst_rate; + lo_rate = src_rate; + switch (src_channels) { + case 1: rate_cvt = SDL_RateMUL2; break; + case 2: rate_cvt = SDL_RateMUL2_c2; break; + case 4: rate_cvt = SDL_RateMUL2_c4; break; + case 6: rate_cvt = SDL_RateMUL2_c6; break; + default: return -1; + } + len_mult = 2; + len_ratio = 2.0; + } + /* If hi_rate = lo_rate*2^x then conversion is easy */ + while ( ((lo_rate*2)/100) <= (hi_rate/100) ) { + cvt->filters[cvt->filter_index++] = rate_cvt; + cvt->len_mult *= len_mult; + lo_rate *= 2; + cvt->len_ratio *= len_ratio; + } + /* We may need a slow conversion here to finish up */ + if ( (lo_rate/100) != (hi_rate/100) ) { +#if 1 + /* The problem with this is that if the input buffer is + say 1K, and the conversion rate is say 1.1, then the + output buffer is 1.1K, which may not be an acceptable + buffer size for the audio driver (not a power of 2) + */ + /* For now, punt and hope the rate distortion isn't great. + */ +#else + if ( src_rate < dst_rate ) { + cvt->rate_incr = (double)lo_rate/hi_rate; + cvt->len_mult *= 2; + cvt->len_ratio /= cvt->rate_incr; + } else { + cvt->rate_incr = (double)hi_rate/lo_rate; + cvt->len_ratio *= cvt->rate_incr; + } + cvt->filters[cvt->filter_index++] = SDL_RateSLOW; +#endif + } + } + + /* Set up the filter information */ + if ( cvt->filter_index != 0 ) { + cvt->needed = 1; + cvt->src_format = src_format; + cvt->dst_format = dst_format; + cvt->len = 0; + cvt->buf = NULL; + cvt->filters[cvt->filter_index] = NULL; + } + return(cvt->needed); +} diff --git a/3rdparty/SDL/src/audio/SDL_audiodev.c b/3rdparty/SDL/src/audio/SDL_audiodev.c new file mode 100644 index 0000000..396156c --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audiodev.c @@ -0,0 +1,179 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Get the name of the audio device we use for output */ + +#if SDL_AUDIO_DRIVER_BSD || SDL_AUDIO_DRIVER_OSS || SDL_AUDIO_DRIVER_SUNAUDIO + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "SDL_stdinc.h" +#include "SDL_audiodev_c.h" + +#ifndef _PATH_DEV_DSP +#if defined(__NETBSD__) || defined(__OPENBSD__) +#define _PATH_DEV_DSP "/dev/audio" +#else +#define _PATH_DEV_DSP "/dev/dsp" +#endif +#endif +#ifndef _PATH_DEV_DSP24 +#define _PATH_DEV_DSP24 "/dev/sound/dsp" +#endif +#ifndef _PATH_DEV_AUDIO +#define _PATH_DEV_AUDIO "/dev/audio" +#endif + + +int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic) +{ + const char *audiodev; + int audio_fd; + char audiopath[1024]; + + /* Figure out what our audio device is */ + if ( ((audiodev=SDL_getenv("SDL_PATH_DSP")) == NULL) && + ((audiodev=SDL_getenv("AUDIODEV")) == NULL) ) { + if ( classic ) { + audiodev = _PATH_DEV_AUDIO; + } else { + struct stat sb; + + /* Added support for /dev/sound/\* in Linux 2.4 */ + if ( ((stat("/dev/sound", &sb) == 0) && S_ISDIR(sb.st_mode)) && + ((stat(_PATH_DEV_DSP24, &sb) == 0) && S_ISCHR(sb.st_mode)) ) { + audiodev = _PATH_DEV_DSP24; + } else { + audiodev = _PATH_DEV_DSP; + } + } + } + audio_fd = open(audiodev, flags, 0); + + /* If the first open fails, look for other devices */ + if ( (audio_fd < 0) && (SDL_strlen(audiodev) < (sizeof(audiopath)-3)) ) { + int exists, instance; + struct stat sb; + + instance = 1; + do { /* Don't use errno ENOENT - it may not be thread-safe */ + SDL_snprintf(audiopath, SDL_arraysize(audiopath), + "%s%d", audiodev, instance++); + exists = 0; + if ( stat(audiopath, &sb) == 0 ) { + exists = 1; + audio_fd = open(audiopath, flags, 0); + } + } while ( exists && (audio_fd < 0) ); + audiodev = audiopath; + } + if ( path != NULL ) { + SDL_strlcpy(path, audiodev, maxlen); + path[maxlen-1] = '\0'; + } + return(audio_fd); +} + +#elif SDL_AUDIO_DRIVER_PAUD + +/* Get the name of the audio device we use for output */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include "SDL_stdinc.h" +#include "SDL_audiodev_c.h" + +#ifndef _PATH_DEV_DSP +#define _PATH_DEV_DSP "/dev/%caud%c/%c" +#endif + +char devsettings[][3] = +{ + { 'p', '0', '1' }, { 'p', '0', '2' }, { 'p', '0', '3' }, { 'p', '0', '4' }, + { 'p', '1', '1' }, { 'p', '1', '2' }, { 'p', '1', '3' }, { 'p', '1', '4' }, + { 'p', '2', '1' }, { 'p', '2', '2' }, { 'p', '2', '3' }, { 'p', '2', '4' }, + { 'p', '3', '1' }, { 'p', '3', '2' }, { 'p', '3', '3' }, { 'p', '3', '4' }, + { 'b', '0', '1' }, { 'b', '0', '2' }, { 'b', '0', '3' }, { 'b', '0', '4' }, + { 'b', '1', '1' }, { 'b', '1', '2' }, { 'b', '1', '3' }, { 'b', '1', '4' }, + { 'b', '2', '1' }, { 'b', '2', '2' }, { 'b', '2', '3' }, { 'b', '2', '4' }, + { 'b', '3', '1' }, { 'b', '3', '2' }, { 'b', '3', '3' }, { 'b', '3', '4' }, + { '\0', '\0', '\0' } +}; + +static int OpenUserDefinedDevice(char *path, int maxlen, int flags) +{ + const char *audiodev; + int audio_fd; + + /* Figure out what our audio device is */ + if ((audiodev=SDL_getenv("SDL_PATH_DSP")) == NULL) { + audiodev=SDL_getenv("AUDIODEV"); + } + if ( audiodev == NULL ) { + return -1; + } + audio_fd = open(audiodev, flags, 0); + if ( path != NULL ) { + SDL_strlcpy(path, audiodev, maxlen); + path[maxlen-1] = '\0'; + } + return audio_fd; +} + +int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic) +{ + struct stat sb; + int audio_fd; + char audiopath[1024]; + int cycle; + + audio_fd = OpenUserDefinedDevice(path,maxlen,flags); + if ( audio_fd != -1 ) { + return audio_fd; + } + + cycle = 0; + while( devsettings[cycle][0] != '\0' ) { + SDL_snprintf( audiopath, SDL_arraysize(audiopath), + _PATH_DEV_DSP, + devsettings[cycle][0], + devsettings[cycle][1], + devsettings[cycle][2]); + + if ( stat(audiopath, &sb) == 0 ) { + audio_fd = open(audiopath, flags, 0); + if ( audio_fd > 0 ) { + if ( path != NULL ) { + SDL_strlcpy( path, audiopath, maxlen ); + } + return audio_fd; + } + } + } + return -1; +} + +#endif /* Audio driver selection */ diff --git a/3rdparty/SDL/src/audio/SDL_audiodev_c.h b/3rdparty/SDL/src/audio/SDL_audiodev_c.h new file mode 100644 index 0000000..179d0d0 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audiodev_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Open the audio device, storing the pathname in 'path' */ +extern int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic); + diff --git a/3rdparty/SDL/src/audio/SDL_audiomem.h b/3rdparty/SDL/src/audio/SDL_audiomem.h new file mode 100644 index 0000000..a473a5e --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_audiomem.h @@ -0,0 +1,25 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define SDL_AllocAudioMem SDL_malloc +#define SDL_FreeAudioMem SDL_free diff --git a/3rdparty/SDL/src/audio/SDL_mixer.c b/3rdparty/SDL/src/audio/SDL_mixer.c new file mode 100644 index 0000000..b5d4d8b --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer.c @@ -0,0 +1,264 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This provides the default mixing callback for the SDL audio routines */ + +#include "SDL_cpuinfo.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "SDL_sysaudio.h" +#include "SDL_mixer_MMX.h" +#include "SDL_mixer_MMX_VC.h" +#include "SDL_mixer_m68k.h" + +/* This table is used to add two sound values together and pin + * the value to avoid overflow. (used with permission from ARDI) + * Changed to use 0xFE instead of 0xFF for better sound quality. + */ +static const Uint8 mix8[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, + 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, + 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, + 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, + 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, + 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, + 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, + 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE +}; + +/* The volume ranges from 0 - 128 */ +#define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME) +#define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) + +void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) +{ + Uint16 format; + + if ( volume == 0 ) { + return; + } + /* Mix the user-level audio format */ + if ( current_audio ) { + if ( current_audio->convert.needed ) { + format = current_audio->convert.src_format; + } else { + format = current_audio->spec.format; + } + } else { + /* HACK HACK HACK */ + format = AUDIO_S16; + } + switch (format) { + + case AUDIO_U8: { +#if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) + SDL_MixAudio_m68k_U8((char*)dst,(char*)src,(unsigned long)len,(long)volume,(char *)mix8); +#else + Uint8 src_sample; + + while ( len-- ) { + src_sample = *src; + ADJUST_VOLUME_U8(src_sample, volume); + *dst = mix8[*dst+src_sample]; + ++dst; + ++src; + } +#endif + } + break; + + case AUDIO_S8: { +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) + if (SDL_HasMMX()) + { + SDL_MixAudio_MMX_S8((char*)dst,(char*)src,(unsigned int)len,(int)volume); + } + else +#elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) + if (SDL_HasMMX()) + { + SDL_MixAudio_MMX_S8_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume); + } + else +#endif +#endif + +#if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) + SDL_MixAudio_m68k_S8((char*)dst,(char*)src,(unsigned long)len,(long)volume); +#else + { + Sint8 *dst8, *src8; + Sint8 src_sample; + int dst_sample; + const int max_audioval = ((1<<(8-1))-1); + const int min_audioval = -(1<<(8-1)); + + src8 = (Sint8 *)src; + dst8 = (Sint8 *)dst; + while ( len-- ) { + src_sample = *src8; + ADJUST_VOLUME(src_sample, volume); + dst_sample = *dst8 + src_sample; + if ( dst_sample > max_audioval ) { + *dst8 = max_audioval; + } else + if ( dst_sample < min_audioval ) { + *dst8 = min_audioval; + } else { + *dst8 = dst_sample; + } + ++dst8; + ++src8; + } + } +#endif + } + break; + + case AUDIO_S16LSB: { +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) + if (SDL_HasMMX()) + { + SDL_MixAudio_MMX_S16((char*)dst,(char*)src,(unsigned int)len,(int)volume); + } + else +#elif ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) + if (SDL_HasMMX()) + { + SDL_MixAudio_MMX_S16_VC((char*)dst,(char*)src,(unsigned int)len,(int)volume); + } + else +#endif +#endif + +#if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) + SDL_MixAudio_m68k_S16LSB((short*)dst,(short*)src,(unsigned long)len,(long)volume); +#else + { + Sint16 src1, src2; + int dst_sample; + const int max_audioval = ((1<<(16-1))-1); + const int min_audioval = -(1<<(16-1)); + + len /= 2; + while ( len-- ) { + src1 = ((src[1])<<8|src[0]); + ADJUST_VOLUME(src1, volume); + src2 = ((dst[1])<<8|dst[0]); + src += 2; + dst_sample = src1+src2; + if ( dst_sample > max_audioval ) { + dst_sample = max_audioval; + } else + if ( dst_sample < min_audioval ) { + dst_sample = min_audioval; + } + dst[0] = dst_sample&0xFF; + dst_sample >>= 8; + dst[1] = dst_sample&0xFF; + dst += 2; + } + } +#endif + } + break; + + case AUDIO_S16MSB: { +#if defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__)) && defined(SDL_ASSEMBLY_ROUTINES) + SDL_MixAudio_m68k_S16MSB((short*)dst,(short*)src,(unsigned long)len,(long)volume); +#else + Sint16 src1, src2; + int dst_sample; + const int max_audioval = ((1<<(16-1))-1); + const int min_audioval = -(1<<(16-1)); + + len /= 2; + while ( len-- ) { + src1 = ((src[0])<<8|src[1]); + ADJUST_VOLUME(src1, volume); + src2 = ((dst[0])<<8|dst[1]); + src += 2; + dst_sample = src1+src2; + if ( dst_sample > max_audioval ) { + dst_sample = max_audioval; + } else + if ( dst_sample < min_audioval ) { + dst_sample = min_audioval; + } + dst[1] = dst_sample&0xFF; + dst_sample >>= 8; + dst[0] = dst_sample&0xFF; + dst += 2; + } +#endif + } + break; + + default: /* If this happens... FIXME! */ + SDL_SetError("SDL_MixAudio(): unknown audio format"); + return; + } +} + diff --git a/3rdparty/SDL/src/audio/SDL_mixer_MMX.c b/3rdparty/SDL/src/audio/SDL_mixer_MMX.c new file mode 100644 index 0000000..a2f1d8d --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_MMX.c @@ -0,0 +1,207 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MMX assembler version of SDL_MixAudio for signed little endian 16 bit samples and signed 8 bit samples + Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr) + This code is licensed under the LGPL (see COPYING for details) + + Assumes buffer size in bytes is a multiple of 16 + Assumes SDL_MIX_MAXVOLUME = 128 +*/ + + +/*********************************************** +* Mixing for 16 bit signed buffers +***********************************************/ + +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) +void SDL_MixAudio_MMX_S16(char* dst,char* src,unsigned int size,int volume) +{ + __asm__ __volatile__ ( + +" movl %3,%%eax\n" /* eax = volume */ + +" movl %2,%%edx\n" /* edx = size */ + +" shrl $4,%%edx\n" /* process 16 bytes per iteration = 8 samples */ + +" jz .endS16\n" + +" pxor %%mm0,%%mm0\n" + +" movd %%eax,%%mm0\n" +" movq %%mm0,%%mm1\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" /* mm0 = vol|vol|vol|vol */ + +".align 8\n" +" .mixloopS16:\n" + +" movq (%1),%%mm1\n" /* mm1 = a|b|c|d */ + +" movq %%mm1,%%mm2\n" /* mm2 = a|b|c|d */ + +" movq 8(%1),%%mm4\n" /* mm4 = e|f|g|h */ + + /* pr charger le buffer dst dans mm7 */ +" movq (%0),%%mm7\n" /* mm7 = dst[0] */ + + /* multiplier par le volume */ +" pmullw %%mm0,%%mm1\n" /* mm1 = l(a*v)|l(b*v)|l(c*v)|l(d*v) */ + +" pmulhw %%mm0,%%mm2\n" /* mm2 = h(a*v)|h(b*v)|h(c*v)|h(d*v) */ +" movq %%mm4,%%mm5\n" /* mm5 = e|f|g|h */ + +" pmullw %%mm0,%%mm4\n" /* mm4 = l(e*v)|l(f*v)|l(g*v)|l(h*v) */ + +" pmulhw %%mm0,%%mm5\n" /* mm5 = h(e*v)|h(f*v)|h(g*v)|h(h*v) */ +" movq %%mm1,%%mm3\n" /* mm3 = l(a*v)|l(b*v)|l(c*v)|l(d*v) */ + +" punpckhwd %%mm2,%%mm1\n" /* mm1 = a*v|b*v */ + +" movq %%mm4,%%mm6\n" /* mm6 = l(e*v)|l(f*v)|l(g*v)|l(h*v) */ +" punpcklwd %%mm2,%%mm3\n" /* mm3 = c*v|d*v */ + +" punpckhwd %%mm5,%%mm4\n" /* mm4 = e*f|f*v */ + +" punpcklwd %%mm5,%%mm6\n" /* mm6 = g*v|h*v */ + + /* pr charger le buffer dst dans mm5 */ +" movq 8(%0),%%mm5\n" /* mm5 = dst[1] */ + + /* diviser par 128 */ +" psrad $7,%%mm1\n" /* mm1 = a*v/128|b*v/128 , 128 = SDL_MIX_MAXVOLUME */ +" add $16,%1\n" + +" psrad $7,%%mm3\n" /* mm3 = c*v/128|d*v/128 */ + +" psrad $7,%%mm4\n" /* mm4 = e*v/128|f*v/128 */ + + /* mm1 = le sample avec le volume modifi */ +" packssdw %%mm1,%%mm3\n" /* mm3 = s(a*v|b*v|c*v|d*v) */ + +" psrad $7,%%mm6\n" /* mm6= g*v/128|h*v/128 */ +" paddsw %%mm7,%%mm3\n" /* mm3 = adjust_volume(src)+dst */ + + /* mm4 = le sample avec le volume modifi */ +" packssdw %%mm4,%%mm6\n" /* mm6 = s(e*v|f*v|g*v|h*v) */ +" movq %%mm3,(%0)\n" + +" paddsw %%mm5,%%mm6\n" /* mm6 = adjust_volume(src)+dst */ + +" movq %%mm6,8(%0)\n" + +" add $16,%0\n" + +" dec %%edx\n" + +" jnz .mixloopS16\n" + +" emms\n" + +".endS16:\n" + : + : "r" (dst), "r"(src),"m"(size), + "m"(volume) + : "eax","edx","memory" + ); +} + + + +/*////////////////////////////////////////////// */ +/* Mixing for 8 bit signed buffers */ +/*////////////////////////////////////////////// */ + +void SDL_MixAudio_MMX_S8(char* dst,char* src,unsigned int size,int volume) +{ + __asm__ __volatile__ ( + +" movl %3,%%eax\n" /* eax = volume */ + +" movd %%eax,%%mm0\n" +" movq %%mm0,%%mm1\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" +" psllq $16,%%mm0\n" +" por %%mm1,%%mm0\n" + +" movl %2,%%edx\n" /* edx = size */ +" shr $3,%%edx\n" /* process 8 bytes per iteration = 8 samples */ + +" cmp $0,%%edx\n" +" je .endS8\n" + +".align 8\n" +" .mixloopS8:\n" + +" pxor %%mm2,%%mm2\n" /* mm2 = 0 */ +" movq (%1),%%mm1\n" /* mm1 = a|b|c|d|e|f|g|h */ + +" movq %%mm1,%%mm3\n" /* mm3 = a|b|c|d|e|f|g|h */ + + /* on va faire le "sign extension" en faisant un cmp avec 0 qui retourne 1 si <0, 0 si >0 */ +" pcmpgtb %%mm1,%%mm2\n" /* mm2 = 11111111|00000000|00000000.... */ + +" punpckhbw %%mm2,%%mm1\n" /* mm1 = 0|a|0|b|0|c|0|d */ + +" punpcklbw %%mm2,%%mm3\n" /* mm3 = 0|e|0|f|0|g|0|h */ +" movq (%0),%%mm2\n" /* mm2 = destination */ + +" pmullw %%mm0,%%mm1\n" /* mm1 = v*a|v*b|v*c|v*d */ +" add $8,%1\n" + +" pmullw %%mm0,%%mm3\n" /* mm3 = v*e|v*f|v*g|v*h */ +" psraw $7,%%mm1\n" /* mm1 = v*a/128|v*b/128|v*c/128|v*d/128 */ + +" psraw $7,%%mm3\n" /* mm3 = v*e/128|v*f/128|v*g/128|v*h/128 */ + +" packsswb %%mm1,%%mm3\n" /* mm1 = v*a/128|v*b/128|v*c/128|v*d/128|v*e/128|v*f/128|v*g/128|v*h/128 */ + +" paddsb %%mm2,%%mm3\n" /* add to destination buffer */ + +" movq %%mm3,(%0)\n" /* store back to ram */ +" add $8,%0\n" + +" dec %%edx\n" + +" jnz .mixloopS8\n" + +".endS8:\n" +" emms\n" + : + : "r" (dst), "r"(src),"m"(size), + "m"(volume) + : "eax","edx","memory" + ); +} +#endif +#endif diff --git a/3rdparty/SDL/src/audio/SDL_mixer_MMX.h b/3rdparty/SDL/src/audio/SDL_mixer_MMX.h new file mode 100644 index 0000000..836b259 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_MMX.h @@ -0,0 +1,17 @@ +/* + headers for MMX assembler version of SDL_MixAudio + Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr) + This code is licensed under the LGPL (see COPYING for details) + + Assumes buffer size in bytes is a multiple of 16 + Assumes SDL_MIX_MAXVOLUME = 128 +*/ +#include "SDL_config.h" + +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if defined(__GNUC__) && defined(__i386__) && defined(SDL_ASSEMBLY_ROUTINES) +void SDL_MixAudio_MMX_S16(char* ,char* ,unsigned int ,int ); +void SDL_MixAudio_MMX_S8(char* ,char* ,unsigned int ,int ); +#endif +#endif + diff --git a/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.c b/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.c new file mode 100644 index 0000000..cd0aa4c --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.c @@ -0,0 +1,183 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mixer_MMX_VC.h" + +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) +// MMX assembler version of SDL_MixAudio for signed little endian 16 bit samples and signed 8 bit samples +// Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr) +// Converted to Intel ASM notation by Cth +// This code is licensed under the LGPL (see COPYING for details) +// +// Assumes buffer size in bytes is a multiple of 16 +// Assumes SDL_MIX_MAXVOLUME = 128 + + +//////////////////////////////////////////////// +// Mixing for 16 bit signed buffers +//////////////////////////////////////////////// + +void SDL_MixAudio_MMX_S16_VC(char* dst,char* src,unsigned int nSize,int volume) +{ + __asm + { + + push edi + push esi + push ebx + + mov edi, dst // edi = dst + mov esi, src // esi = src + mov eax, volume // eax = volume + mov ebx, nSize // ebx = size + shr ebx, 4 // process 16 bytes per iteration = 8 samples + jz endS16 + + pxor mm0, mm0 + movd mm0, eax //%%eax,%%mm0 + movq mm1, mm0 //%%mm0,%%mm1 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 // mm0 = vol|vol|vol|vol + + #ifndef __WATCOMC__ + align 16 + #endif +mixloopS16: + movq mm1, [esi] //(%%esi),%%mm1\n" // mm1 = a|b|c|d + movq mm2, mm1 //%%mm1,%%mm2\n" // mm2 = a|b|c|d + movq mm4, [esi + 8] //8(%%esi),%%mm4\n" // mm4 = e|f|g|h + // pre charger le buffer dst dans mm7 + movq mm7, [edi] //(%%edi),%%mm7\n" // mm7 = dst[0]" + // multiplier par le volume + pmullw mm1, mm0 //%%mm0,%%mm1\n" // mm1 = l(a*v)|l(b*v)|l(c*v)|l(d*v) + pmulhw mm2, mm0 //%%mm0,%%mm2\n" // mm2 = h(a*v)|h(b*v)|h(c*v)|h(d*v) + movq mm5, mm4 //%%mm4,%%mm5\n" // mm5 = e|f|g|h + pmullw mm4, mm0 //%%mm0,%%mm4\n" // mm4 = l(e*v)|l(f*v)|l(g*v)|l(h*v) + pmulhw mm5, mm0 //%%mm0,%%mm5\n" // mm5 = h(e*v)|h(f*v)|h(g*v)|h(h*v) + movq mm3, mm1 //%%mm1,%%mm3\n" // mm3 = l(a*v)|l(b*v)|l(c*v)|l(d*v) + punpckhwd mm1, mm2 //%%mm2,%%mm1\n" // mm1 = a*v|b*v + movq mm6, mm4 //%%mm4,%%mm6\n" // mm6 = l(e*v)|l(f*v)|l(g*v)|l(h*v) + punpcklwd mm3, mm2 //%%mm2,%%mm3\n" // mm3 = c*v|d*v + punpckhwd mm4, mm5 //%%mm5,%%mm4\n" // mm4 = e*f|f*v + punpcklwd mm6, mm5 //%%mm5,%%mm6\n" // mm6 = g*v|h*v + // pre charger le buffer dst dans mm5 + movq mm5, [edi + 8] //8(%%edi),%%mm5\n" // mm5 = dst[1] + // diviser par 128 + psrad mm1, 7 //$7,%%mm1\n" // mm1 = a*v/128|b*v/128 , 128 = SDL_MIX_MAXVOLUME + add esi, 16 //$16,%%esi\n" + psrad mm3, 7 //$7,%%mm3\n" // mm3 = c*v/128|d*v/128 + psrad mm4, 7 //$7,%%mm4\n" // mm4 = e*v/128|f*v/128 + // mm1 = le sample avec le volume modifie + packssdw mm3, mm1 //%%mm1,%%mm3\n" // mm3 = s(a*v|b*v|c*v|d*v) + psrad mm6, 7 //$7,%%mm6\n" // mm6= g*v/128|h*v/128 + paddsw mm3, mm7 //%%mm7,%%mm3\n" // mm3 = adjust_volume(src)+dst + // mm4 = le sample avec le volume modifie + packssdw mm6, mm4 //%%mm4,%%mm6\n" // mm6 = s(e*v|f*v|g*v|h*v) + movq [edi], mm3 //%%mm3,(%%edi)\n" + paddsw mm6, mm5 //%%mm5,%%mm6\n" // mm6 = adjust_volume(src)+dst + movq [edi + 8], mm6 //%%mm6,8(%%edi)\n" + add edi, 16 //$16,%%edi\n" + dec ebx //%%ebx\n" + jnz mixloopS16 + +endS16: + emms + + pop ebx + pop esi + pop edi + } + +} + +//////////////////////////////////////////////// +// Mixing for 8 bit signed buffers +//////////////////////////////////////////////// + +void SDL_MixAudio_MMX_S8_VC(char* dst,char* src,unsigned int nSize,int volume) +{ + _asm + { + + push edi + push esi + push ebx + + mov edi, dst //movl %0,%%edi // edi = dst + mov esi, src //%1,%%esi // esi = src + mov eax, volume //%3,%%eax // eax = volume + + movd mm0, eax //%%eax,%%mm0 + movq mm1, mm0 //%%mm0,%%mm1 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 + psllq mm0, 16 //$16,%%mm0 + por mm0, mm1 //%%mm1,%%mm0 + + mov ebx, nSize //%2,%%ebx // ebx = size + shr ebx, 3 //$3,%%ebx // process 8 bytes per iteration = 8 samples + cmp ebx, 0 //$0,%%ebx + je endS8 + + #ifndef __WATCOMC__ + align 16 + #endif +mixloopS8: + pxor mm2, mm2 //%%mm2,%%mm2 // mm2 = 0 + movq mm1, [esi] //(%%esi),%%mm1 // mm1 = a|b|c|d|e|f|g|h + movq mm3, mm1 //%%mm1,%%mm3 // mm3 = a|b|c|d|e|f|g|h + // on va faire le "sign extension" en faisant un cmp avec 0 qui retourne 1 si <0, 0 si >0 + pcmpgtb mm2, mm1 //%%mm1,%%mm2 // mm2 = 11111111|00000000|00000000.... + punpckhbw mm1, mm2 //%%mm2,%%mm1 // mm1 = 0|a|0|b|0|c|0|d + punpcklbw mm3, mm2 //%%mm2,%%mm3 // mm3 = 0|e|0|f|0|g|0|h + movq mm2, [edi] //(%%edi),%%mm2 // mm2 = destination + pmullw mm1, mm0 //%%mm0,%%mm1 // mm1 = v*a|v*b|v*c|v*d + add esi, 8 //$8,%%esi + pmullw mm3, mm0 //%%mm0,%%mm3 // mm3 = v*e|v*f|v*g|v*h + psraw mm1, 7 //$7,%%mm1 // mm1 = v*a/128|v*b/128|v*c/128|v*d/128 + psraw mm3, 7 //$7,%%mm3 // mm3 = v*e/128|v*f/128|v*g/128|v*h/128 + packsswb mm3, mm1 //%%mm1,%%mm3 // mm1 = v*a/128|v*b/128|v*c/128|v*d/128|v*e/128|v*f/128|v*g/128|v*h/128 + paddsb mm3, mm2 //%%mm2,%%mm3 // add to destination buffer + movq [edi], mm3 //%%mm3,(%%edi) // store back to ram + add edi, 8 //$8,%%edi + dec ebx //%%ebx + jnz mixloopS8 + +endS8: + emms + + pop ebx + pop esi + pop edi + } +} + +#endif /* SDL_ASSEMBLY_ROUTINES */ +#endif /* SDL_BUGGY_MMX_MIXERS */ diff --git a/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.h b/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.h new file mode 100644 index 0000000..fbd0eb8 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_MMX_VC.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + + +#if defined(SDL_BUGGY_MMX_MIXERS) /* buggy, so we're disabling them. --ryan. */ +#if ((defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)) && defined(SDL_ASSEMBLY_ROUTINES) +/* headers for MMX assembler version of SDL_MixAudio + Copyright 2002 Stephane Marchesin (stephane.marchesin@wanadoo.fr) + Converted to Intel ASM notation by Cth + This code is licensed under the LGPL (see COPYING for details) + + Assumes buffer size in bytes is a multiple of 16 + Assumes SDL_MIX_MAXVOLUME = 128 +*/ +void SDL_MixAudio_MMX_S16_VC(char* ,char* ,unsigned int ,int ); +void SDL_MixAudio_MMX_S8_VC(char* ,char* ,unsigned int ,int ); +#endif +#endif diff --git a/3rdparty/SDL/src/audio/SDL_mixer_m68k.c b/3rdparty/SDL/src/audio/SDL_mixer_m68k.c new file mode 100644 index 0000000..22bb1cb --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_m68k.c @@ -0,0 +1,210 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + m68k assembly mix routines + + Patrice Mandin +*/ + +#if (defined(__m68k__) && !defined(__mcoldfire__)) && defined(__GNUC__) +void SDL_MixAudio_m68k_U8(char* dst, char* src, long len, long volume, char* mix8) +{ + __asm__ __volatile__ ( + + "tstl %2\n" +" beqs stoploop_u8\n" +"mixloop_u8:\n" + + /* Mix a sample */ + +" moveq #0,%%d0\n" +" moveq #0,%%d1\n" + +" moveb %1@+,%%d0\n" /* d0 = *src++ */ +" sub #128,%%d0\n" /* d0 -= 128 */ +" muls %3,%%d0\n" /* d0 *= volume (0<=volume<=128) */ +" moveb %0@,%%d1\n" /* d1 = *dst */ +" asr #7,%%d0\n" /* d0 /= 128 (SDL_MIX_MAXVOLUME) */ +" add #128,%%d0\n" /* d0 += 128 */ + +" add %%d1,%%d0\n" + +" moveb %4@(%%d0:w),%0@+\n" + + /* Loop till done */ + +" subql #1,%2\n" +" bhis mixloop_u8\n" +"stoploop_u8:\n" + + : /* no return value */ + : /* input */ + "a"(dst), "a"(src), "d"(len), "d"(volume), "a"(mix8) + : /* clobbered registers */ + "d0", "d1", "cc", "memory" + ); +} + +void SDL_MixAudio_m68k_S8(char* dst, char* src, long len, long volume) +{ + __asm__ __volatile__ ( + + "tstl %2\n" +" beqs stoploop_s8\n" +" moveq #-128,%%d2\n" +" moveq #127,%%d3\n" +"mixloop_s8:\n" + + /* Mix a sample */ + +" moveq #0,%%d0\n" +" moveq #0,%%d1\n" + +" moveb %1@+,%%d0\n" /* d0 = *src++ */ +" muls %3,%%d0\n" /* d0 *= volume (0<=volume<=128) */ +" moveb %0@,%%d1\n" /* d1 = *dst */ +" asr #7,%%d0\n" /* d0 /= 128 (SDL_MIX_MAXVOLUME) */ + +" add %%d1,%%d0\n" + +" cmp %%d2,%%d0\n" +" bges lower_limit_s8\n" +" move %%d2,%%d0\n" +"lower_limit_s8:\n" + +" cmp %%d3,%%d0\n" +" bles upper_limit_s8\n" +" move %%d3,%%d0\n" +"upper_limit_s8:\n" +" moveb %%d0,%0@+\n" + + /* Loop till done */ + +" subql #1,%2\n" +" bhis mixloop_s8\n" +"stoploop_s8:\n" + + : /* no return value */ + : /* input */ + "a"(dst), "a"(src), "d"(len), "d"(volume) + : /* clobbered registers */ + "d0", "d1", "d2", "d3", "cc", "memory" + ); +} + +void SDL_MixAudio_m68k_S16MSB(short* dst, short* src, long len, long volume) +{ + __asm__ __volatile__ ( + + "tstl %2\n" +" beqs stoploop_s16msb\n" +" movel #-32768,%%d2\n" +" movel #32767,%%d3\n" +" lsrl #1,%2\n" +"mixloop_s16msb:\n" + + /* Mix a sample */ + +" move %1@+,%%d0\n" /* d0 = *src++ */ +" muls %3,%%d0\n" /* d0 *= volume (0<=volume<=128) */ +" move %0@,%%d1\n" /* d1 = *dst */ +" extl %%d1\n" /* extend d1 to 32 bits */ +" asrl #7,%%d0\n" /* d0 /= 128 (SDL_MIX_MAXVOLUME) */ + +" addl %%d1,%%d0\n" + +" cmpl %%d2,%%d0\n" +" bges lower_limit_s16msb\n" +" move %%d2,%%d0\n" +"lower_limit_s16msb:\n" + +" cmpl %%d3,%%d0\n" +" bles upper_limit_s16msb\n" +" move %%d3,%%d0\n" +"upper_limit_s16msb:\n" +" move %%d0,%0@+\n" + + /* Loop till done */ + +" subql #1,%2\n" +" bhis mixloop_s16msb\n" +"stoploop_s16msb:\n" + + : /* no return value */ + : /* input */ + "a"(dst), "a"(src), "d"(len), "d"(volume) + : /* clobbered registers */ + "d0", "d1", "d2", "d3", "cc", "memory" + ); +} + +void SDL_MixAudio_m68k_S16LSB(short* dst, short* src, long len, long volume) +{ + __asm__ __volatile__ ( + + "tstl %2\n" +" beqs stoploop_s16lsb\n" +" movel #-32768,%%d2\n" +" movel #32767,%%d3\n" +" lsrl #1,%2\n" +"mixloop_s16lsb:\n" + + /* Mix a sample */ + +" move %1@+,%%d0\n" /* d0 = *src++ */ +" rorw #8,%%d0\n" +" muls %3,%%d0\n" /* d0 *= volume (0<=volume<=128) */ +" move %0@,%%d1\n" /* d1 = *dst */ +" rorw #8,%%d1\n" +" extl %%d1\n" /* extend d1 to 32 bits */ +" asrl #7,%%d0\n" /* d0 /= 128 (SDL_MIX_MAXVOLUME) */ + +" addl %%d1,%%d0\n" + +" cmpl %%d2,%%d0\n" +" bges lower_limit_s16lsb\n" +" move %%d2,%%d0\n" +"lower_limit_s16lsb:\n" + +" cmpl %%d3,%%d0\n" +" bles upper_limit_s16lsb\n" +" move %%d3,%%d0\n" +"upper_limit_s16lsb:\n" +" rorw #8,%%d0\n" +" move %%d0,%0@+\n" + + /* Loop till done */ + +" subql #1,%2\n" +" bhis mixloop_s16lsb\n" +"stoploop_s16lsb:\n" + + : /* no return value */ + : /* input */ + "a"(dst), "a"(src), "d"(len), "d"(volume) + : /* clobbered registers */ + "d0", "d1", "d2", "d3", "cc", "memory" + ); +} +#endif diff --git a/3rdparty/SDL/src/audio/SDL_mixer_m68k.h b/3rdparty/SDL/src/audio/SDL_mixer_m68k.h new file mode 100644 index 0000000..673df00 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_mixer_m68k.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + m68k assembly mix routines + + Patrice Mandin +*/ + +#if (defined(__m68k__) && !defined(__mcoldfire__)) && defined(__GNUC__) +void SDL_MixAudio_m68k_U8(char* dst,char* src, long len, long volume, char* mix8); +void SDL_MixAudio_m68k_S8(char* dst,char* src, long len, long volume); + +void SDL_MixAudio_m68k_S16MSB(short* dst,short* src, long len, long volume); +void SDL_MixAudio_m68k_S16LSB(short* dst,short* src, long len, long volume); +#endif diff --git a/3rdparty/SDL/src/audio/SDL_sysaudio.h b/3rdparty/SDL/src/audio/SDL_sysaudio.h new file mode 100644 index 0000000..74ac21d --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_sysaudio.h @@ -0,0 +1,186 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is SDL_free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_sysaudio_h +#define _SDL_sysaudio_h + +#include "SDL_mutex.h" +#include "SDL_thread.h" + +/* The SDL audio driver */ +typedef struct SDL_AudioDevice SDL_AudioDevice; + +/* Define the SDL audio driver structure */ +#define _THIS SDL_AudioDevice *_this +#ifndef _STATUS +#define _STATUS SDL_status *status +#endif +struct SDL_AudioDevice { + /* * * */ + /* The name of this audio driver */ + const char *name; + + /* * * */ + /* The description of this audio driver */ + const char *desc; + + /* * * */ + /* Public driver functions */ + int (*OpenAudio)(_THIS, SDL_AudioSpec *spec); + void (*ThreadInit)(_THIS); /* Called by audio thread at start */ + void (*WaitAudio)(_THIS); + void (*PlayAudio)(_THIS); + Uint8 *(*GetAudioBuf)(_THIS); + void (*WaitDone)(_THIS); + void (*CloseAudio)(_THIS); + + /* * * */ + /* Lock / Unlock functions added for the Mac port */ + void (*LockAudio)(_THIS); + void (*UnlockAudio)(_THIS); + + void (*SetCaption)(_THIS, const char *caption); + + /* * * */ + /* Data common to all devices */ + + /* The current audio specification (shared with audio thread) */ + SDL_AudioSpec spec; + + /* An audio conversion block for audio format emulation */ + SDL_AudioCVT convert; + + /* Current state flags */ + int enabled; + int paused; + int opened; + + /* Fake audio buffer for when the audio hardware is busy */ + Uint8 *fake_stream; + + /* A semaphore for locking the mixing buffers */ + SDL_mutex *mixer_lock; + + /* A thread to feed the audio device */ + SDL_Thread *thread; + Uint32 threadid; + + /* * * */ + /* Data private to this driver */ + struct SDL_PrivateAudioData *hidden; + + /* * * */ + /* The function used to dispose of this structure */ + void (*free)(_THIS); +}; +#undef _THIS + +typedef struct AudioBootStrap { + const char *name; + const char *desc; + int (*available)(void); + SDL_AudioDevice *(*create)(int devindex); +} AudioBootStrap; + +#if SDL_AUDIO_DRIVER_BSD +extern AudioBootStrap BSD_AUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_PULSE +extern AudioBootStrap PULSE_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_ALSA +extern AudioBootStrap ALSA_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_OSS +extern AudioBootStrap DSP_bootstrap; +extern AudioBootStrap DMA_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_QNXNTO +extern AudioBootStrap QNXNTOAUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_SUNAUDIO +extern AudioBootStrap SUNAUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DMEDIA +extern AudioBootStrap DMEDIA_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_ARTS +extern AudioBootStrap ARTS_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_ESD +extern AudioBootStrap ESD_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_NAS +extern AudioBootStrap NAS_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DSOUND +extern AudioBootStrap DSOUND_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_WAVEOUT +extern AudioBootStrap WAVEOUT_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_PAUD +extern AudioBootStrap Paud_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_BAUDIO +extern AudioBootStrap BAUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_COREAUDIO +extern AudioBootStrap COREAUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_SNDMGR +extern AudioBootStrap SNDMGR_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_MINT +extern AudioBootStrap MINTAUDIO_GSXB_bootstrap; +extern AudioBootStrap MINTAUDIO_MCSN_bootstrap; +extern AudioBootStrap MINTAUDIO_STFA_bootstrap; +extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap; +extern AudioBootStrap MINTAUDIO_DMA8_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DISK +extern AudioBootStrap DISKAUD_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DUMMY +extern AudioBootStrap DUMMYAUD_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DC +extern AudioBootStrap DCAUD_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_NDS +extern AudioBootStrap NDSAUD_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_MMEAUDIO +extern AudioBootStrap MMEAUDIO_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_DART +extern AudioBootStrap DART_bootstrap; +#endif +#if SDL_AUDIO_DRIVER_EPOCAUDIO +extern AudioBootStrap EPOCAudio_bootstrap; +#endif + +/* This is the current audio device */ +extern SDL_AudioDevice *current_audio; + +#endif /* _SDL_sysaudio_h */ diff --git a/3rdparty/SDL/src/audio/SDL_wave.c b/3rdparty/SDL/src/audio/SDL_wave.c new file mode 100644 index 0000000..b4ad6c7 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_wave.c @@ -0,0 +1,596 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Microsoft WAVE file loading routines */ + +#include "SDL_audio.h" +#include "SDL_wave.h" + + +static int ReadChunk(SDL_RWops *src, Chunk *chunk); + +struct MS_ADPCM_decodestate { + Uint8 hPredictor; + Uint16 iDelta; + Sint16 iSamp1; + Sint16 iSamp2; +}; +static struct MS_ADPCM_decoder { + WaveFMT wavefmt; + Uint16 wSamplesPerBlock; + Uint16 wNumCoef; + Sint16 aCoeff[7][2]; + /* * * */ + struct MS_ADPCM_decodestate state[2]; +} MS_ADPCM_state; + +static int InitMS_ADPCM(WaveFMT *format) +{ + Uint8 *rogue_feel; + int i; + + /* Set the rogue pointer to the MS_ADPCM specific data */ + MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); + MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); + MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); + MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); + MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); + MS_ADPCM_state.wavefmt.bitspersample = + SDL_SwapLE16(format->bitspersample); + rogue_feel = (Uint8 *)format+sizeof(*format); + if ( sizeof(*format) == 16 ) { + rogue_feel += sizeof(Uint16); + } + MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); + rogue_feel += sizeof(Uint16); + MS_ADPCM_state.wNumCoef = ((rogue_feel[1]<<8)|rogue_feel[0]); + rogue_feel += sizeof(Uint16); + if ( MS_ADPCM_state.wNumCoef != 7 ) { + SDL_SetError("Unknown set of MS_ADPCM coefficients"); + return(-1); + } + for ( i=0; i<MS_ADPCM_state.wNumCoef; ++i ) { + MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1]<<8)|rogue_feel[0]); + rogue_feel += sizeof(Uint16); + MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1]<<8)|rogue_feel[0]); + rogue_feel += sizeof(Uint16); + } + return(0); +} + +static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, + Uint8 nybble, Sint16 *coeff) +{ + const Sint32 max_audioval = ((1<<(16-1))-1); + const Sint32 min_audioval = -(1<<(16-1)); + const Sint32 adaptive[] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 + }; + Sint32 new_sample, delta; + + new_sample = ((state->iSamp1 * coeff[0]) + + (state->iSamp2 * coeff[1]))/256; + if ( nybble & 0x08 ) { + new_sample += state->iDelta * (nybble-0x10); + } else { + new_sample += state->iDelta * nybble; + } + if ( new_sample < min_audioval ) { + new_sample = min_audioval; + } else + if ( new_sample > max_audioval ) { + new_sample = max_audioval; + } + delta = ((Sint32)state->iDelta * adaptive[nybble])/256; + if ( delta < 16 ) { + delta = 16; + } + state->iDelta = (Uint16)delta; + state->iSamp2 = state->iSamp1; + state->iSamp1 = (Sint16)new_sample; + return(new_sample); +} + +static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) +{ + struct MS_ADPCM_decodestate *state[2]; + Uint8 *freeable, *encoded, *decoded; + Sint32 encoded_len, samplesleft; + Sint8 nybble, stereo; + Sint16 *coeff[2]; + Sint32 new_sample; + + /* Allocate the proper sized output buffer */ + encoded_len = *audio_len; + encoded = *audio_buf; + freeable = *audio_buf; + *audio_len = (encoded_len/MS_ADPCM_state.wavefmt.blockalign) * + MS_ADPCM_state.wSamplesPerBlock* + MS_ADPCM_state.wavefmt.channels*sizeof(Sint16); + *audio_buf = (Uint8 *)SDL_malloc(*audio_len); + if ( *audio_buf == NULL ) { + SDL_Error(SDL_ENOMEM); + return(-1); + } + decoded = *audio_buf; + + /* Get ready... Go! */ + stereo = (MS_ADPCM_state.wavefmt.channels == 2); + state[0] = &MS_ADPCM_state.state[0]; + state[1] = &MS_ADPCM_state.state[stereo]; + while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) { + /* Grab the initial information for this block */ + state[0]->hPredictor = *encoded++; + if ( stereo ) { + state[1]->hPredictor = *encoded++; + } + state[0]->iDelta = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + if ( stereo ) { + state[1]->iDelta = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + } + state[0]->iSamp1 = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + if ( stereo ) { + state[1]->iSamp1 = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + } + state[0]->iSamp2 = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + if ( stereo ) { + state[1]->iSamp2 = ((encoded[1]<<8)|encoded[0]); + encoded += sizeof(Sint16); + } + coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor]; + coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor]; + + /* Store the two initial samples we start with */ + decoded[0] = state[0]->iSamp2&0xFF; + decoded[1] = state[0]->iSamp2>>8; + decoded += 2; + if ( stereo ) { + decoded[0] = state[1]->iSamp2&0xFF; + decoded[1] = state[1]->iSamp2>>8; + decoded += 2; + } + decoded[0] = state[0]->iSamp1&0xFF; + decoded[1] = state[0]->iSamp1>>8; + decoded += 2; + if ( stereo ) { + decoded[0] = state[1]->iSamp1&0xFF; + decoded[1] = state[1]->iSamp1>>8; + decoded += 2; + } + + /* Decode and store the other samples in this block */ + samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)* + MS_ADPCM_state.wavefmt.channels; + while ( samplesleft > 0 ) { + nybble = (*encoded)>>4; + new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]); + decoded[0] = new_sample&0xFF; + new_sample >>= 8; + decoded[1] = new_sample&0xFF; + decoded += 2; + + nybble = (*encoded)&0x0F; + new_sample = MS_ADPCM_nibble(state[1],nybble,coeff[1]); + decoded[0] = new_sample&0xFF; + new_sample >>= 8; + decoded[1] = new_sample&0xFF; + decoded += 2; + + ++encoded; + samplesleft -= 2; + } + encoded_len -= MS_ADPCM_state.wavefmt.blockalign; + } + SDL_free(freeable); + return(0); +} + +struct IMA_ADPCM_decodestate { + Sint32 sample; + Sint8 index; +}; +static struct IMA_ADPCM_decoder { + WaveFMT wavefmt; + Uint16 wSamplesPerBlock; + /* * * */ + struct IMA_ADPCM_decodestate state[2]; +} IMA_ADPCM_state; + +static int InitIMA_ADPCM(WaveFMT *format) +{ + Uint8 *rogue_feel; + + /* Set the rogue pointer to the IMA_ADPCM specific data */ + IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); + IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); + IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); + IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); + IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); + IMA_ADPCM_state.wavefmt.bitspersample = + SDL_SwapLE16(format->bitspersample); + rogue_feel = (Uint8 *)format+sizeof(*format); + if ( sizeof(*format) == 16 ) { + rogue_feel += sizeof(Uint16); + } + IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); + return(0); +} + +static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state,Uint8 nybble) +{ + const Sint32 max_audioval = ((1<<(16-1))-1); + const Sint32 min_audioval = -(1<<(16-1)); + const int index_table[16] = { + -1, -1, -1, -1, + 2, 4, 6, 8, + -1, -1, -1, -1, + 2, 4, 6, 8 + }; + const Sint32 step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, + 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, + 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, + 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, + 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, + 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, + 22385, 24623, 27086, 29794, 32767 + }; + Sint32 delta, step; + + /* Compute difference and new sample value */ + step = step_table[state->index]; + delta = step >> 3; + if ( nybble & 0x04 ) delta += step; + if ( nybble & 0x02 ) delta += (step >> 1); + if ( nybble & 0x01 ) delta += (step >> 2); + if ( nybble & 0x08 ) delta = -delta; + state->sample += delta; + + /* Update index value */ + state->index += index_table[nybble]; + if ( state->index > 88 ) { + state->index = 88; + } else + if ( state->index < 0 ) { + state->index = 0; + } + + /* Clamp output sample */ + if ( state->sample > max_audioval ) { + state->sample = max_audioval; + } else + if ( state->sample < min_audioval ) { + state->sample = min_audioval; + } + return(state->sample); +} + +/* Fill the decode buffer with a channel block of data (8 samples) */ +static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, + int channel, int numchannels, struct IMA_ADPCM_decodestate *state) +{ + int i; + Sint8 nybble; + Sint32 new_sample; + + decoded += (channel * 2); + for ( i=0; i<4; ++i ) { + nybble = (*encoded)&0x0F; + new_sample = IMA_ADPCM_nibble(state, nybble); + decoded[0] = new_sample&0xFF; + new_sample >>= 8; + decoded[1] = new_sample&0xFF; + decoded += 2 * numchannels; + + nybble = (*encoded)>>4; + new_sample = IMA_ADPCM_nibble(state, nybble); + decoded[0] = new_sample&0xFF; + new_sample >>= 8; + decoded[1] = new_sample&0xFF; + decoded += 2 * numchannels; + + ++encoded; + } +} + +static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) +{ + struct IMA_ADPCM_decodestate *state; + Uint8 *freeable, *encoded, *decoded; + Sint32 encoded_len, samplesleft; + unsigned int c, channels; + + /* Check to make sure we have enough variables in the state array */ + channels = IMA_ADPCM_state.wavefmt.channels; + if ( channels > SDL_arraysize(IMA_ADPCM_state.state) ) { + SDL_SetError("IMA ADPCM decoder can only handle %d channels", + SDL_arraysize(IMA_ADPCM_state.state)); + return(-1); + } + state = IMA_ADPCM_state.state; + + /* Allocate the proper sized output buffer */ + encoded_len = *audio_len; + encoded = *audio_buf; + freeable = *audio_buf; + *audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * + IMA_ADPCM_state.wSamplesPerBlock* + IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16); + *audio_buf = (Uint8 *)SDL_malloc(*audio_len); + if ( *audio_buf == NULL ) { + SDL_Error(SDL_ENOMEM); + return(-1); + } + decoded = *audio_buf; + + /* Get ready... Go! */ + while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) { + /* Grab the initial information for this block */ + for ( c=0; c<channels; ++c ) { + /* Fill the state information for this block */ + state[c].sample = ((encoded[1]<<8)|encoded[0]); + encoded += 2; + if ( state[c].sample & 0x8000 ) { + state[c].sample -= 0x10000; + } + state[c].index = *encoded++; + /* Reserved byte in buffer header, should be 0 */ + if ( *encoded++ != 0 ) { + /* Uh oh, corrupt data? Buggy code? */; + } + + /* Store the initial sample we start with */ + decoded[0] = (Uint8)(state[c].sample&0xFF); + decoded[1] = (Uint8)(state[c].sample>>8); + decoded += 2; + } + + /* Decode and store the other samples in this block */ + samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels; + while ( samplesleft > 0 ) { + for ( c=0; c<channels; ++c ) { + Fill_IMA_ADPCM_block(decoded, encoded, + c, channels, &state[c]); + encoded += 4; + samplesleft -= 8; + } + decoded += (channels * 8 * 2); + } + encoded_len -= IMA_ADPCM_state.wavefmt.blockalign; + } + SDL_free(freeable); + return(0); +} + +SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc, + SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +{ + int was_error; + Chunk chunk; + int lenread; + int MS_ADPCM_encoded, IMA_ADPCM_encoded; + int samplesize; + + /* WAV magic header */ + Uint32 RIFFchunk; + Uint32 wavelen = 0; + Uint32 WAVEmagic; + Uint32 headerDiff = 0; + + /* FMT chunk */ + WaveFMT *format = NULL; + + /* Make sure we are passed a valid data source */ + was_error = 0; + if ( src == NULL ) { + was_error = 1; + goto done; + } + + /* Check the magic header */ + RIFFchunk = SDL_ReadLE32(src); + wavelen = SDL_ReadLE32(src); + if ( wavelen == WAVE ) { /* The RIFFchunk has already been read */ + WAVEmagic = wavelen; + wavelen = RIFFchunk; + RIFFchunk = RIFF; + } else { + WAVEmagic = SDL_ReadLE32(src); + } + if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) { + SDL_SetError("Unrecognized file type (not WAVE)"); + was_error = 1; + goto done; + } + headerDiff += sizeof(Uint32); /* for WAVE */ + + /* Read the audio data format chunk */ + chunk.data = NULL; + do { + if ( chunk.data != NULL ) { + SDL_free(chunk.data); + chunk.data = NULL; + } + lenread = ReadChunk(src, &chunk); + if ( lenread < 0 ) { + was_error = 1; + goto done; + } + /* 2 Uint32's for chunk header+len, plus the lenread */ + headerDiff += lenread + 2 * sizeof(Uint32); + } while ( (chunk.magic == FACT) || (chunk.magic == LIST) ); + + /* Decode the audio data format */ + format = (WaveFMT *)chunk.data; + if ( chunk.magic != FMT ) { + SDL_SetError("Complex WAVE files not supported"); + was_error = 1; + goto done; + } + MS_ADPCM_encoded = IMA_ADPCM_encoded = 0; + switch (SDL_SwapLE16(format->encoding)) { + case PCM_CODE: + /* We can understand this */ + break; + case MS_ADPCM_CODE: + /* Try to understand this */ + if ( InitMS_ADPCM(format) < 0 ) { + was_error = 1; + goto done; + } + MS_ADPCM_encoded = 1; + break; + case IMA_ADPCM_CODE: + /* Try to understand this */ + if ( InitIMA_ADPCM(format) < 0 ) { + was_error = 1; + goto done; + } + IMA_ADPCM_encoded = 1; + break; + case MP3_CODE: + SDL_SetError("MPEG Layer 3 data not supported", + SDL_SwapLE16(format->encoding)); + was_error = 1; + goto done; + default: + SDL_SetError("Unknown WAVE data format: 0x%.4x", + SDL_SwapLE16(format->encoding)); + was_error = 1; + goto done; + } + SDL_memset(spec, 0, (sizeof *spec)); + spec->freq = SDL_SwapLE32(format->frequency); + switch (SDL_SwapLE16(format->bitspersample)) { + case 4: + if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) { + spec->format = AUDIO_S16; + } else { + was_error = 1; + } + break; + case 8: + spec->format = AUDIO_U8; + break; + case 16: + spec->format = AUDIO_S16; + break; + default: + was_error = 1; + break; + } + if ( was_error ) { + SDL_SetError("Unknown %d-bit PCM data format", + SDL_SwapLE16(format->bitspersample)); + goto done; + } + spec->channels = (Uint8)SDL_SwapLE16(format->channels); + spec->samples = 4096; /* Good default buffer size */ + + /* Read the audio data chunk */ + *audio_buf = NULL; + do { + if ( *audio_buf != NULL ) { + SDL_free(*audio_buf); + *audio_buf = NULL; + } + lenread = ReadChunk(src, &chunk); + if ( lenread < 0 ) { + was_error = 1; + goto done; + } + *audio_len = lenread; + *audio_buf = chunk.data; + if(chunk.magic != DATA) headerDiff += lenread + 2 * sizeof(Uint32); + } while ( chunk.magic != DATA ); + headerDiff += 2 * sizeof(Uint32); /* for the data chunk and len */ + + if ( MS_ADPCM_encoded ) { + if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) { + was_error = 1; + goto done; + } + } + if ( IMA_ADPCM_encoded ) { + if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) { + was_error = 1; + goto done; + } + } + + /* Don't return a buffer that isn't a multiple of samplesize */ + samplesize = ((spec->format & 0xFF)/8)*spec->channels; + *audio_len &= ~(samplesize-1); + +done: + if ( format != NULL ) { + SDL_free(format); + } + if ( src ) { + if ( freesrc ) { + SDL_RWclose(src); + } else { + /* seek to the end of the file (given by the RIFF chunk) */ + SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR); + } + } + if ( was_error ) { + spec = NULL; + } + return(spec); +} + +/* Since the WAV memory is allocated in the shared library, it must also + be freed here. (Necessary under Win32, VC++) + */ +void SDL_FreeWAV(Uint8 *audio_buf) +{ + if ( audio_buf != NULL ) { + SDL_free(audio_buf); + } +} + +static int ReadChunk(SDL_RWops *src, Chunk *chunk) +{ + chunk->magic = SDL_ReadLE32(src); + chunk->length = SDL_ReadLE32(src); + chunk->data = (Uint8 *)SDL_malloc(chunk->length); + if ( chunk->data == NULL ) { + SDL_Error(SDL_ENOMEM); + return(-1); + } + if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) { + SDL_Error(SDL_EFREAD); + SDL_free(chunk->data); + chunk->data = NULL; + return(-1); + } + return(chunk->length); +} diff --git a/3rdparty/SDL/src/audio/SDL_wave.h b/3rdparty/SDL/src/audio/SDL_wave.h new file mode 100644 index 0000000..53b12e7 --- /dev/null +++ b/3rdparty/SDL/src/audio/SDL_wave.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is SDL_free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* WAVE files are little-endian */ + +/*******************************************/ +/* Define values for Microsoft WAVE format */ +/*******************************************/ +#define RIFF 0x46464952 /* "RIFF" */ +#define WAVE 0x45564157 /* "WAVE" */ +#define FACT 0x74636166 /* "fact" */ +#define LIST 0x5453494c /* "LIST" */ +#define FMT 0x20746D66 /* "fmt " */ +#define DATA 0x61746164 /* "data" */ +#define PCM_CODE 0x0001 +#define MS_ADPCM_CODE 0x0002 +#define IMA_ADPCM_CODE 0x0011 +#define MP3_CODE 0x0055 +#define WAVE_MONO 1 +#define WAVE_STEREO 2 + +/* Normally, these three chunks come consecutively in a WAVE file */ +typedef struct WaveFMT { +/* Not saved in the chunk we read: + Uint32 FMTchunk; + Uint32 fmtlen; +*/ + Uint16 encoding; + Uint16 channels; /* 1 = mono, 2 = stereo */ + Uint32 frequency; /* One of 11025, 22050, or 44100 Hz */ + Uint32 byterate; /* Average bytes per second */ + Uint16 blockalign; /* Bytes per sample block */ + Uint16 bitspersample; /* One of 8, 12, 16, or 4 for ADPCM */ +} WaveFMT; + +/* The general chunk found in the WAVE file */ +typedef struct Chunk { + Uint32 magic; + Uint32 length; + Uint8 *data; +} Chunk; + diff --git a/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.c b/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.c new file mode 100644 index 0000000..f10733e --- /dev/null +++ b/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.c @@ -0,0 +1,619 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <sys/types.h> +#include <signal.h> /* For kill() */ + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "SDL_alsa_audio.h" + +#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC +#include "SDL_name.h" +#include "SDL_loadso.h" +#else +#define SDL_NAME(X) X +#endif + + +/* The tag name used by ALSA audio */ +#define DRIVER_NAME "alsa" + +/* Audio driver functions */ +static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void ALSA_WaitAudio(_THIS); +static void ALSA_PlayAudio(_THIS); +static Uint8 *ALSA_GetAudioBuf(_THIS); +static void ALSA_CloseAudio(_THIS); + +#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC + +static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC; +static void *alsa_handle = NULL; +static int alsa_loaded = 0; + +static int (*SDL_NAME(snd_pcm_open))(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode); +static int (*SDL_NAME(snd_pcm_close))(snd_pcm_t *pcm); +static snd_pcm_sframes_t (*SDL_NAME(snd_pcm_writei))(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size); +static int (*SDL_NAME(snd_pcm_recover))(snd_pcm_t *pcm, int err, int silent); +static int (*SDL_NAME(snd_pcm_prepare))(snd_pcm_t *pcm); +static int (*SDL_NAME(snd_pcm_drain))(snd_pcm_t *pcm); +static const char *(*SDL_NAME(snd_strerror))(int errnum); +static size_t (*SDL_NAME(snd_pcm_hw_params_sizeof))(void); +static size_t (*SDL_NAME(snd_pcm_sw_params_sizeof))(void); +static void (*SDL_NAME(snd_pcm_hw_params_copy))(snd_pcm_hw_params_t *dst, const snd_pcm_hw_params_t *src); +static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); +static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); +static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); +static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); +static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params, unsigned int *val); +static int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *frames, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); +static int (*SDL_NAME(snd_pcm_hw_params_set_buffer_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); +static int (*SDL_NAME(snd_pcm_hw_params_get_buffer_size))(const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); +static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); +/* +*/ +static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams, snd_pcm_uframes_t val); +static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); +static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params, snd_pcm_uframes_t val); +static int (*SDL_NAME(snd_pcm_sw_params))(snd_pcm_t *pcm, snd_pcm_sw_params_t *params); +static int (*SDL_NAME(snd_pcm_nonblock))(snd_pcm_t *pcm, int nonblock); +static int (*SDL_NAME(snd_pcm_wait))(snd_pcm_t *pcm, int timeout); +#define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) +#define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) + +/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +static struct { + const char *name; + void **func; +} alsa_functions[] = { + { "snd_pcm_open", (void**)(char*)&SDL_NAME(snd_pcm_open) }, + { "snd_pcm_close", (void**)(char*)&SDL_NAME(snd_pcm_close) }, + { "snd_pcm_writei", (void**)(char*)&SDL_NAME(snd_pcm_writei) }, + { "snd_pcm_recover", (void**)(char*)&SDL_NAME(snd_pcm_recover) }, + { "snd_pcm_prepare", (void**)(char*)&SDL_NAME(snd_pcm_prepare) }, + { "snd_pcm_drain", (void**)(char*)&SDL_NAME(snd_pcm_drain) }, + { "snd_strerror", (void**)(char*)&SDL_NAME(snd_strerror) }, + { "snd_pcm_hw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_sizeof) }, + { "snd_pcm_sw_params_sizeof", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_sizeof) }, + { "snd_pcm_hw_params_copy", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_copy) }, + { "snd_pcm_hw_params_any", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_any) }, + { "snd_pcm_hw_params_set_access", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_access) }, + { "snd_pcm_hw_params_set_format", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_format) }, + { "snd_pcm_hw_params_set_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_channels) }, + { "snd_pcm_hw_params_get_channels", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_channels) }, + { "snd_pcm_hw_params_set_rate_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_rate_near) }, + { "snd_pcm_hw_params_set_period_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_period_size_near) }, + { "snd_pcm_hw_params_get_period_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_period_size) }, + { "snd_pcm_hw_params_set_periods_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_periods_near) }, + { "snd_pcm_hw_params_get_periods", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_periods) }, + { "snd_pcm_hw_params_set_buffer_size_near", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_set_buffer_size_near) }, + { "snd_pcm_hw_params_get_buffer_size", (void**)(char*)&SDL_NAME(snd_pcm_hw_params_get_buffer_size) }, + { "snd_pcm_hw_params", (void**)(char*)&SDL_NAME(snd_pcm_hw_params) }, + { "snd_pcm_sw_params_set_avail_min", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_avail_min) }, + { "snd_pcm_sw_params_current", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_current) }, + { "snd_pcm_sw_params_set_start_threshold", (void**)(char*)&SDL_NAME(snd_pcm_sw_params_set_start_threshold) }, + { "snd_pcm_sw_params", (void**)(char*)&SDL_NAME(snd_pcm_sw_params) }, + { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, + { "snd_pcm_wait", (void**)(char*)&SDL_NAME(snd_pcm_wait) }, +}; + +static void UnloadALSALibrary(void) { + if (alsa_loaded) { + SDL_UnloadObject(alsa_handle); + alsa_handle = NULL; + alsa_loaded = 0; + } +} + +static int LoadALSALibrary(void) { + int i, retval = -1; + + alsa_handle = SDL_LoadObject(alsa_library); + if (alsa_handle) { + alsa_loaded = 1; + retval = 0; + for (i = 0; i < SDL_arraysize(alsa_functions); i++) { + *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name); + if (!*alsa_functions[i].func) { + retval = -1; + UnloadALSALibrary(); + break; + } + } + } + return retval; +} + +#else + +static void UnloadALSALibrary(void) { + return; +} + +static int LoadALSALibrary(void) { + return 0; +} + +#endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */ + +static const char *get_audio_device(int channels) +{ + const char *device; + + device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */ + if ( device == NULL ) { + switch (channels) { + case 6: + device = "plug:surround51"; + break; + case 4: + device = "plug:surround40"; + break; + default: + device = "default"; + break; + } + } + return device; +} + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int available; + int status; + snd_pcm_t *handle; + + available = 0; + if (LoadALSALibrary() < 0) { + return available; + } + status = SDL_NAME(snd_pcm_open)(&handle, get_audio_device(2), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + if ( status >= 0 ) { + available = 1; + SDL_NAME(snd_pcm_close)(handle); + } + UnloadALSALibrary(); + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); + UnloadALSALibrary(); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + LoadALSALibrary(); + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = ALSA_OpenAudio; + this->WaitAudio = ALSA_WaitAudio; + this->PlayAudio = ALSA_PlayAudio; + this->GetAudioBuf = ALSA_GetAudioBuf; + this->CloseAudio = ALSA_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap ALSA_bootstrap = { + DRIVER_NAME, "ALSA PCM audio", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void ALSA_WaitAudio(_THIS) +{ + /* We're in blocking mode, so there's nothing to do here */ +} + + +/* + * http://bugzilla.libsdl.org/show_bug.cgi?id=110 + * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE + * and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR" + */ +#define SWIZ6(T) \ + T *ptr = (T *) mixbuf; \ + Uint32 i; \ + for (i = 0; i < this->spec.samples; i++, ptr += 6) { \ + T tmp; \ + tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \ + tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \ + } + +static __inline__ void swizzle_alsa_channels_6_64bit(_THIS) { SWIZ6(Uint64); } +static __inline__ void swizzle_alsa_channels_6_32bit(_THIS) { SWIZ6(Uint32); } +static __inline__ void swizzle_alsa_channels_6_16bit(_THIS) { SWIZ6(Uint16); } +static __inline__ void swizzle_alsa_channels_6_8bit(_THIS) { SWIZ6(Uint8); } + +#undef SWIZ6 + + +/* + * Called right before feeding this->mixbuf to the hardware. Swizzle channels + * from Windows/Mac order to the format alsalib will want. + */ +static __inline__ void swizzle_alsa_channels(_THIS) +{ + if (this->spec.channels == 6) { + const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */ + if (fmtsize == 16) + swizzle_alsa_channels_6_16bit(this); + else if (fmtsize == 8) + swizzle_alsa_channels_6_8bit(this); + else if (fmtsize == 32) + swizzle_alsa_channels_6_32bit(this); + else if (fmtsize == 64) + swizzle_alsa_channels_6_64bit(this); + } + + /* !!! FIXME: update this for 7.1 if needed, later. */ +} + + +static void ALSA_PlayAudio(_THIS) +{ + int status; + snd_pcm_uframes_t frames_left; + const Uint8 *sample_buf = (const Uint8 *) mixbuf; + const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) * this->spec.channels; + + swizzle_alsa_channels(this); + + frames_left = ((snd_pcm_uframes_t) this->spec.samples); + + while ( frames_left > 0 && this->enabled ) { + /* This works, but needs more testing before going live */ + /*SDL_NAME(snd_pcm_wait)(pcm_handle, -1);*/ + + status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, frames_left); + if ( status < 0 ) { + if ( status == -EAGAIN ) { + /* Apparently snd_pcm_recover() doesn't handle this case - does it assume snd_pcm_wait() above? */ + SDL_Delay(1); + continue; + } + status = SDL_NAME(snd_pcm_recover)(pcm_handle, status, 0); + if ( status < 0 ) { + /* Hmm, not much we can do - abort */ + fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", SDL_NAME(snd_strerror)(status)); + this->enabled = 0; + return; + } + continue; + } + sample_buf += status * frame_size; + frames_left -= status; + } +} + +static Uint8 *ALSA_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void ALSA_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( pcm_handle ) { + SDL_NAME(snd_pcm_drain)(pcm_handle); + SDL_NAME(snd_pcm_close)(pcm_handle); + pcm_handle = NULL; + } +} + +static int ALSA_finalize_hardware(_THIS, SDL_AudioSpec *spec, snd_pcm_hw_params_t *hwparams, int override) +{ + int status; + snd_pcm_uframes_t bufsize; + + /* "set" the hardware with the desired parameters */ + status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); + if ( status < 0 ) { + return(-1); + } + + /* Get samples for the actual buffer size */ + status = SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &bufsize); + if ( status < 0 ) { + return(-1); + } + if ( !override && bufsize != spec->samples * 2 ) { + return(-1); + } + + /* FIXME: Is this safe to do? */ + spec->samples = bufsize / 2; + + /* This is useful for debugging */ + if ( getenv("SDL_AUDIO_ALSA_DEBUG") ) { + snd_pcm_uframes_t persize = 0; + unsigned int periods = 0; + + SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, NULL); + SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, NULL); + + fprintf(stderr, "ALSA: period size = %ld, periods = %u, buffer size = %lu\n", persize, periods, bufsize); + } + return(0); +} + +static int ALSA_set_period_size(_THIS, SDL_AudioSpec *spec, snd_pcm_hw_params_t *params, int override) +{ + const char *env; + int status; + snd_pcm_hw_params_t *hwparams; + snd_pcm_uframes_t frames; + unsigned int periods; + + /* Copy the hardware parameters for this setup */ + snd_pcm_hw_params_alloca(&hwparams); + SDL_NAME(snd_pcm_hw_params_copy)(hwparams, params); + + if ( !override ) { + env = getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE"); + if ( env ) { + override = SDL_atoi(env); + if ( override == 0 ) { + return(-1); + } + } + } + + frames = spec->samples; + status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL); + if ( status < 0 ) { + return(-1); + } + + periods = 2; + status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL); + if ( status < 0 ) { + return(-1); + } + + return ALSA_finalize_hardware(this, spec, hwparams, override); +} + +static int ALSA_set_buffer_size(_THIS, SDL_AudioSpec *spec, snd_pcm_hw_params_t *params, int override) +{ + const char *env; + int status; + snd_pcm_hw_params_t *hwparams; + snd_pcm_uframes_t frames; + + /* Copy the hardware parameters for this setup */ + snd_pcm_hw_params_alloca(&hwparams); + SDL_NAME(snd_pcm_hw_params_copy)(hwparams, params); + + if ( !override ) { + env = getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"); + if ( env ) { + override = SDL_atoi(env); + if ( override == 0 ) { + return(-1); + } + } + } + + frames = spec->samples * 2; + status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames); + if ( status < 0 ) { + return(-1); + } + + return ALSA_finalize_hardware(this, spec, hwparams, override); +} + +static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + int status; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + snd_pcm_format_t format; + unsigned int rate; + unsigned int channels; + Uint16 test_format; + + /* Open the audio device */ + /* Name of device should depend on # channels in spec */ + status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + + if ( status < 0 ) { + SDL_SetError("Couldn't open audio device: %s", SDL_NAME(snd_strerror)(status)); + return(-1); + } + + /* Figure out what the hardware is capable of */ + snd_pcm_hw_params_alloca(&hwparams); + status = SDL_NAME(snd_pcm_hw_params_any)(pcm_handle, hwparams); + if ( status < 0 ) { + SDL_SetError("Couldn't get hardware config: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + + /* SDL only uses interleaved sample output */ + status = SDL_NAME(snd_pcm_hw_params_set_access)(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); + if ( status < 0 ) { + SDL_SetError("Couldn't set interleaved access: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + + /* Try for a closest match on audio format */ + status = -1; + for ( test_format = SDL_FirstAudioFormat(spec->format); + test_format && (status < 0); ) { + switch ( test_format ) { + case AUDIO_U8: + format = SND_PCM_FORMAT_U8; + break; + case AUDIO_S8: + format = SND_PCM_FORMAT_S8; + break; + case AUDIO_S16LSB: + format = SND_PCM_FORMAT_S16_LE; + break; + case AUDIO_S16MSB: + format = SND_PCM_FORMAT_S16_BE; + break; + case AUDIO_U16LSB: + format = SND_PCM_FORMAT_U16_LE; + break; + case AUDIO_U16MSB: + format = SND_PCM_FORMAT_U16_BE; + break; + default: + format = 0; + break; + } + if ( format != 0 ) { + status = SDL_NAME(snd_pcm_hw_params_set_format)(pcm_handle, hwparams, format); + } + if ( status < 0 ) { + test_format = SDL_NextAudioFormat(); + } + } + if ( status < 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + ALSA_CloseAudio(this); + return(-1); + } + spec->format = test_format; + + /* Set the number of channels */ + status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels); + channels = spec->channels; + if ( status < 0 ) { + status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams, &channels); + if ( status < 0 ) { + SDL_SetError("Couldn't set audio channels"); + ALSA_CloseAudio(this); + return(-1); + } + spec->channels = channels; + } + + /* Set the audio rate */ + rate = spec->freq; + + status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, &rate, NULL); + if ( status < 0 ) { + SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + spec->freq = rate; + + /* Set the buffer size, in samples */ + if ( ALSA_set_period_size(this, spec, hwparams, 0) < 0 && + ALSA_set_buffer_size(this, spec, hwparams, 0) < 0 ) { + /* Failed to set desired buffer size, do the best you can... */ + if ( ALSA_set_period_size(this, spec, hwparams, 1) < 0 ) { + SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + } + + /* Set the software parameters */ + snd_pcm_sw_params_alloca(&swparams); + status = SDL_NAME(snd_pcm_sw_params_current)(pcm_handle, swparams); + if ( status < 0 ) { + SDL_SetError("Couldn't get software config: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + status = SDL_NAME(snd_pcm_sw_params_set_avail_min)(pcm_handle, swparams, spec->samples); + if ( status < 0 ) { + SDL_SetError("Couldn't set minimum available samples: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 1); + if ( status < 0 ) { + SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams); + if ( status < 0 ) { + SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status)); + ALSA_CloseAudio(this); + return(-1); + } + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + ALSA_CloseAudio(this); + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Switch to blocking mode for playback */ + SDL_NAME(snd_pcm_nonblock)(pcm_handle, 0); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.h b/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.h new file mode 100644 index 0000000..55ae87b --- /dev/null +++ b/3rdparty/SDL/src/audio/alsa/SDL_alsa_audio.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ALSA_PCM_audio_h +#define _ALSA_PCM_audio_h + +#include <alsa/asoundlib.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The audio device handle */ + snd_pcm_t *pcm_handle; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; +}; + +/* Old variable names */ +#define pcm_handle (this->hidden->pcm_handle) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) + +#endif /* _ALSA_PCM_audio_h */ diff --git a/3rdparty/SDL/src/audio/arts/SDL_artsaudio.c b/3rdparty/SDL/src/audio/arts/SDL_artsaudio.c new file mode 100644 index 0000000..373f8c1 --- /dev/null +++ b/3rdparty/SDL/src/audio/arts/SDL_artsaudio.c @@ -0,0 +1,362 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif +#include <unistd.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_artsaudio.h" + +#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC +#include "SDL_name.h" +#include "SDL_loadso.h" +#else +#define SDL_NAME(X) X +#endif + +/* The tag name used by artsc audio */ +#define ARTS_DRIVER_NAME "arts" + +/* Audio driver functions */ +static int ARTS_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void ARTS_WaitAudio(_THIS); +static void ARTS_PlayAudio(_THIS); +static Uint8 *ARTS_GetAudioBuf(_THIS); +static void ARTS_CloseAudio(_THIS); + +#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC + +static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC; +static void *arts_handle = NULL; +static int arts_loaded = 0; + +static int (*SDL_NAME(arts_init))(void); +static void (*SDL_NAME(arts_free))(void); +static arts_stream_t (*SDL_NAME(arts_play_stream))(int rate, int bits, int channels, const char *name); +static int (*SDL_NAME(arts_stream_set))(arts_stream_t s, arts_parameter_t param, int value); +static int (*SDL_NAME(arts_stream_get))(arts_stream_t s, arts_parameter_t param); +static int (*SDL_NAME(arts_write))(arts_stream_t s, const void *buffer, int count); +static void (*SDL_NAME(arts_close_stream))(arts_stream_t s); +static int (*SDL_NAME(arts_suspend))(void); +static int (*SDL_NAME(arts_suspended))(void); +static const char *(*SDL_NAME(arts_error_text))(int errorcode); + +static struct { + const char *name; + void **func; +} arts_functions[] = { + { "arts_init", (void **)&SDL_NAME(arts_init) }, + { "arts_free", (void **)&SDL_NAME(arts_free) }, + { "arts_play_stream", (void **)&SDL_NAME(arts_play_stream) }, + { "arts_stream_set", (void **)&SDL_NAME(arts_stream_set) }, + { "arts_stream_get", (void **)&SDL_NAME(arts_stream_get) }, + { "arts_write", (void **)&SDL_NAME(arts_write) }, + { "arts_close_stream", (void **)&SDL_NAME(arts_close_stream) }, + { "arts_suspend", (void **)&SDL_NAME(arts_suspend) }, + { "arts_suspended", (void **)&SDL_NAME(arts_suspended) }, + { "arts_error_text", (void **)&SDL_NAME(arts_error_text) }, +}; + +static void UnloadARTSLibrary() +{ + if ( arts_loaded ) { + SDL_UnloadObject(arts_handle); + arts_handle = NULL; + arts_loaded = 0; + } +} + +static int LoadARTSLibrary(void) +{ + int i, retval = -1; + + arts_handle = SDL_LoadObject(arts_library); + if ( arts_handle ) { + arts_loaded = 1; + retval = 0; + for ( i=0; i<SDL_arraysize(arts_functions); ++i ) { + *arts_functions[i].func = SDL_LoadFunction(arts_handle, arts_functions[i].name); + if ( !*arts_functions[i].func ) { + retval = -1; + UnloadARTSLibrary(); + break; + } + } + } + return retval; +} + +#else + +static void UnloadARTSLibrary() +{ + return; +} + +static int LoadARTSLibrary(void) +{ + return 0; +} + +#endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */ + +/* Audio driver bootstrap functions */ + +static int ARTS_Suspend(void) +{ + const Uint32 abortms = SDL_GetTicks() + 3000; /* give up after 3 secs */ + while ( (!SDL_NAME(arts_suspended)()) && (SDL_GetTicks() < abortms) ) { + if ( SDL_NAME(arts_suspend)() ) { + break; + } + } + + return SDL_NAME(arts_suspended)(); +} + +static int Audio_Available(void) +{ + int available = 0; + + if ( LoadARTSLibrary() < 0 ) { + return available; + } + if ( SDL_NAME(arts_init)() == 0 ) { + if ( ARTS_Suspend() ) { + /* Play a stream so aRts doesn't crash */ + arts_stream_t stream2; + stream2=SDL_NAME(arts_play_stream)(44100, 16, 2, "SDL"); + SDL_NAME(arts_write)(stream2, "", 0); + SDL_NAME(arts_close_stream)(stream2); + available = 1; + } + SDL_NAME(arts_free)(); + } + UnloadARTSLibrary(); + + return available; +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); + UnloadARTSLibrary(); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + LoadARTSLibrary(); + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + stream = 0; + + /* Set the function pointers */ + this->OpenAudio = ARTS_OpenAudio; + this->WaitAudio = ARTS_WaitAudio; + this->PlayAudio = ARTS_PlayAudio; + this->GetAudioBuf = ARTS_GetAudioBuf; + this->CloseAudio = ARTS_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap ARTS_bootstrap = { + ARTS_DRIVER_NAME, "Analog Realtime Synthesizer", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void ARTS_WaitAudio(_THIS) +{ + Sint32 ticks; + + /* Check to see if the thread-parent process is still alive */ + { static int cnt = 0; + /* Note that this only works with thread implementations + that use a different process id for each thread. + */ + if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ + if ( kill(parent, 0) < 0 ) { + this->enabled = 0; + } + } + } + + /* Use timer for general audio synchronization */ + ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; + if ( ticks > 0 ) { + SDL_Delay(ticks); + } +} + +static void ARTS_PlayAudio(_THIS) +{ + int written; + + /* Write the audio data */ + written = SDL_NAME(arts_write)(stream, mixbuf, mixlen); + + /* If timer synchronization is enabled, set the next write frame */ + if ( frame_ticks ) { + next_frame += frame_ticks; + } + + /* If we couldn't write, assume fatal error for now */ + if ( written < 0 ) { + this->enabled = 0; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", written); +#endif +} + +static Uint8 *ARTS_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void ARTS_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( stream ) { + SDL_NAME(arts_close_stream)(stream); + stream = 0; + } + SDL_NAME(arts_free)(); +} + +static int ARTS_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + int bits, frag_spec; + Uint16 test_format, format; + int error_code; + + /* Reset the timer synchronization flag */ + frame_ticks = 0.0; + + mixbuf = NULL; + + /* Try for a closest match on audio format */ + format = 0; + bits = 0; + for ( test_format = SDL_FirstAudioFormat(spec->format); + ! format && test_format; ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + switch ( test_format ) { + case AUDIO_U8: + bits = 8; + format = 1; + break; + case AUDIO_S16LSB: + bits = 16; + format = 1; + break; + default: + format = 0; + break; + } + if ( ! format ) { + test_format = SDL_NextAudioFormat(); + } + } + if ( format == 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + return(-1); + } + spec->format = test_format; + + error_code = SDL_NAME(arts_init)(); + if ( error_code != 0 ) { + SDL_SetError("Unable to initialize ARTS: %s", SDL_NAME(arts_error_text)(error_code)); + return(-1); + } + if ( ! ARTS_Suspend() ) { + SDL_SetError("ARTS can not open audio device"); + return(-1); + } + stream = SDL_NAME(arts_play_stream)(spec->freq, bits, spec->channels, "SDL"); + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Determine the power of two of the fragment size */ + for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); + if ( (0x01<<frag_spec) != spec->size ) { + SDL_SetError("Fragment size must be a power of two"); + return(-1); + } + frag_spec |= 0x00020000; /* two fragments, for low latency */ + +#ifdef ARTS_P_PACKET_SETTINGS + SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SETTINGS, frag_spec); +#else + SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff); + SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_COUNT, frag_spec>>16); +#endif + spec->size = SDL_NAME(arts_stream_get)(stream, ARTS_P_PACKET_SIZE); + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/arts/SDL_artsaudio.h b/3rdparty/SDL/src/audio/arts/SDL_artsaudio.h new file mode 100644 index 0000000..de3b228 --- /dev/null +++ b/3rdparty/SDL/src/audio/arts/SDL_artsaudio.h @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_artscaudio_h +#define _SDL_artscaudio_h + +#include <artsc.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The stream descriptor for the audio device */ + arts_stream_t stream; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; + + /* Support for audio timing using a timer, in addition to select() */ + float frame_ticks; + float next_frame; +}; +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define stream (this->hidden->stream) +#define parent (this->hidden->parent) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_artscaudio_h */ + diff --git a/3rdparty/SDL/src/audio/baudio/SDL_beaudio.cc b/3rdparty/SDL/src/audio/baudio/SDL_beaudio.cc new file mode 100644 index 0000000..de635f8 --- /dev/null +++ b/3rdparty/SDL/src/audio/baudio/SDL_beaudio.cc @@ -0,0 +1,225 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to the audio stream on BeOS */ + +#include <SoundPlayer.h> + +#include "../../main/beos/SDL_BeApp.h" + +extern "C" { + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" +#include "../../thread/beos/SDL_systhread_c.h" +#include "SDL_beaudio.h" + + +/* Audio driver functions */ +static int BE_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void BE_WaitAudio(_THIS); +static void BE_PlayAudio(_THIS); +static Uint8 *BE_GetAudioBuf(_THIS); +static void BE_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->OpenAudio = BE_OpenAudio; + device->WaitAudio = BE_WaitAudio; + device->PlayAudio = BE_PlayAudio; + device->GetAudioBuf = BE_GetAudioBuf; + device->CloseAudio = BE_CloseAudio; + + device->free = Audio_DeleteDevice; + + return device; +} + +AudioBootStrap BAUDIO_bootstrap = { + "baudio", "BeOS BSoundPlayer", + Audio_Available, Audio_CreateDevice +}; + +/* The BeOS callback for handling the audio buffer */ +static void FillSound(void *device, void *stream, size_t len, + const media_raw_audio_format &format) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *)device; + + /* Silence the buffer, since it's ours */ + SDL_memset(stream, audio->spec.silence, len); + + /* Only do soemthing if audio is enabled */ + if ( ! audio->enabled ) + return; + + if ( ! audio->paused ) { + if ( audio->convert.needed ) { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback)(audio->spec.userdata, + (Uint8 *)audio->convert.buf,audio->convert.len); + SDL_mutexV(audio->mixer_lock); + SDL_ConvertAudio(&audio->convert); + SDL_memcpy(stream,audio->convert.buf,audio->convert.len_cvt); + } else { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback)(audio->spec.userdata, + (Uint8 *)stream, len); + SDL_mutexV(audio->mixer_lock); + } + } + return; +} + +/* Dummy functions -- we don't use thread-based audio */ +void BE_WaitAudio(_THIS) +{ + return; +} +void BE_PlayAudio(_THIS) +{ + return; +} +Uint8 *BE_GetAudioBuf(_THIS) +{ + return(NULL); +} + +void BE_CloseAudio(_THIS) +{ + if ( audio_obj ) { + audio_obj->Stop(); + delete audio_obj; + audio_obj = NULL; + } + + /* Quit the Be Application, if there's nothing left to do */ + SDL_QuitBeApp(); +} + +int BE_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + int valid_datatype = 0; + media_raw_audio_format format; + Uint16 test_format = SDL_FirstAudioFormat(spec->format); + + /* Parse the audio format and fill the Be raw audio format */ + memset(&format, '\0', sizeof (media_raw_audio_format)); + format.byte_order = B_MEDIA_LITTLE_ENDIAN; + format.frame_rate = (float) spec->freq; + format.channel_count = spec->channels; /* !!! FIXME: support > 2? */ + while ((!valid_datatype) && (test_format)) { + valid_datatype = 1; + spec->format = test_format; + switch (test_format) { + case AUDIO_S8: + format.format = media_raw_audio_format::B_AUDIO_CHAR; + break; + + case AUDIO_U8: + format.format = media_raw_audio_format::B_AUDIO_UCHAR; + break; + + case AUDIO_S16LSB: + format.format = media_raw_audio_format::B_AUDIO_SHORT; + break; + + case AUDIO_S16MSB: + format.format = media_raw_audio_format::B_AUDIO_SHORT; + format.byte_order = B_MEDIA_BIG_ENDIAN; + break; + + default: + valid_datatype = 0; + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { /* shouldn't happen, but just in case... */ + SDL_SetError("Unsupported audio format"); + return (-1); + } + + /* Initialize the Be Application, if it's not already started */ + if (SDL_InitBeApp() < 0) { + return (-1); + } + + format.buffer_size = spec->samples; + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Subscribe to the audio stream (creates a new thread) */ + { sigset_t omask; + SDL_MaskSignals(&omask); + audio_obj = new BSoundPlayer(&format, "SDL Audio", FillSound, + NULL, _this); + SDL_UnmaskSignals(&omask); + } + if ( audio_obj->Start() == B_NO_ERROR ) { + audio_obj->SetHasData(true); + } else { + SDL_SetError("Unable to start Be audio"); + return(-1); + } + + /* We're running! */ + return(1); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/audio/baudio/SDL_beaudio.h b/3rdparty/SDL/src/audio/baudio/SDL_beaudio.h new file mode 100644 index 0000000..adaf1de --- /dev/null +++ b/3rdparty/SDL/src/audio/baudio/SDL_beaudio.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *_this + +struct SDL_PrivateAudioData { + BSoundPlayer *audio_obj; +}; + +/* Old variable names */ +#define audio_obj (_this->hidden->audio_obj) + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.c b/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.c new file mode 100644 index 0000000..e5e0d94 --- /dev/null +++ b/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.c @@ -0,0 +1,404 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Driver for native OpenBSD/NetBSD audio(4). + * vedge@vedge.com.ar. + */ + +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/audioio.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_bsdaudio.h" + +/* The tag name used by NetBSD/OpenBSD audio */ +#ifdef __NetBSD__ +#define BSD_AUDIO_DRIVER_NAME "netbsd" +#define BSD_AUDIO_DRIVER_DESC "Native NetBSD audio" +#else +#define BSD_AUDIO_DRIVER_NAME "openbsd" +#define BSD_AUDIO_DRIVER_DESC "Native OpenBSD audio" +#endif + +/* Open the audio device for playback, and don't block if busy */ +/* #define USE_BLOCKING_WRITES */ + +/* Use timer for synchronization */ +/* #define USE_TIMER_SYNC */ + +/* #define DEBUG_AUDIO */ +/* #define DEBUG_AUDIO_STREAM */ + +#ifdef USE_BLOCKING_WRITES +#define OPEN_FLAGS O_WRONLY +#else +#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) +#endif + +/* Audio driver functions */ +static void OBSD_WaitAudio(_THIS); +static int OBSD_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void OBSD_PlayAudio(_THIS); +static Uint8 *OBSD_GetAudioBuf(_THIS); +static void OBSD_CloseAudio(_THIS); + +#ifdef DEBUG_AUDIO +static void OBSD_Status(_THIS); +#endif + +/* Audio driver bootstrap functions */ + +static int +Audio_Available(void) +{ + int fd; + int available; + + available = 0; + fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); + if(fd >= 0) { + available = 1; + close(fd); + } + return(available); +} + +static void +Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice +*Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice*)SDL_malloc(sizeof(SDL_AudioDevice)); + if(this) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = + (struct SDL_PrivateAudioData*)SDL_malloc((sizeof *this->hidden)); + } + if((this == NULL) || (this->hidden == NULL)) { + SDL_OutOfMemory(); + if(this) SDL_free(this); + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = OBSD_OpenAudio; + this->WaitAudio = OBSD_WaitAudio; + this->PlayAudio = OBSD_PlayAudio; + this->GetAudioBuf = OBSD_GetAudioBuf; + this->CloseAudio = OBSD_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap BSD_AUDIO_bootstrap = { + BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void +OBSD_WaitAudio(_THIS) +{ +#ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ + /* See if we need to use timed audio synchronization */ + if ( frame_ticks ) { + /* Use timer for general audio synchronization */ + Sint32 ticks; + + ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; + if ( ticks > 0 ) { + SDL_Delay(ticks); + } + } else { + /* Use select() for audio synchronization */ + fd_set fdset; + struct timeval timeout; + + FD_ZERO(&fdset); + FD_SET(audio_fd, &fdset); + timeout.tv_sec = 10; + timeout.tv_usec = 0; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Waiting for audio to get ready\n"); +#endif + if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { + const char *message = + "Audio timeout - buggy audio driver? (disabled)"; + /* In general we should never print to the screen, + but in this case we have no other way of letting + the user know what happened. + */ + fprintf(stderr, "SDL: %s\n", message); + this->enabled = 0; + /* Don't try to close - may hang */ + audio_fd = -1; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Done disabling audio\n"); +#endif + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Ready!\n"); +#endif + } +#endif /* !USE_BLOCKING_WRITES */ +} + +static void +OBSD_PlayAudio(_THIS) +{ + int written, p=0; + + /* Write the audio data, checking for EAGAIN on broken audio drivers */ + do { + written = write(audio_fd, &mixbuf[p], mixlen-p); + if (written>0) + p += written; + if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) + { + /* Non recoverable error has occurred. It should be reported!!! */ + perror("audio"); + break; + } + + if ( p < written || ((written < 0) && ((errno == 0) || (errno == EAGAIN))) ) { + SDL_Delay(1); /* Let a little CPU time go by */ + } + } while ( p < written ); + + /* If timer synchronization is enabled, set the next write frame */ + if ( frame_ticks ) { + next_frame += frame_ticks; + } + + /* If we couldn't write, assume fatal error for now */ + if ( written < 0 ) { + this->enabled = 0; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", written); +#endif +} + +static Uint8 +*OBSD_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void +OBSD_CloseAudio(_THIS) +{ + if(mixbuf != NULL) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if(audio_fd >= 0) { + close(audio_fd); + audio_fd = -1; + } +} + +#ifdef DEBUG_AUDIO +void +OBSD_Status(_THIS) +{ + audio_info_t info; + + if(ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { + fprintf(stderr,"AUDIO_GETINFO failed.\n"); + return; + } + + fprintf(stderr,"\n" +"[play/record info]\n" +"buffer size : %d bytes\n" +"sample rate : %i Hz\n" +"channels : %i\n" +"precision : %i-bit\n" +"encoding : 0x%x\n" +"seek : %i\n" +"sample count : %i\n" +"EOF count : %i\n" +"paused : %s\n" +"error occured : %s\n" +"waiting : %s\n" +"active : %s\n" +"", + info.play.buffer_size, + info.play.sample_rate, + info.play.channels, + info.play.precision, + info.play.encoding, + info.play.seek, + info.play.samples, + info.play.eof, + info.play.pause ? "yes" : "no", + info.play.error ? "yes" : "no", + info.play.waiting ? "yes" : "no", + info.play.active ? "yes": "no"); + + fprintf(stderr,"\n" +"[audio info]\n" +"monitor_gain : %i\n" +"hw block size : %d bytes\n" +"hi watermark : %i\n" +"lo watermark : %i\n" +"audio mode : %s\n" +"", + info.monitor_gain, + info.blocksize, + info.hiwat, info.lowat, + (info.mode == AUMODE_PLAY) ? "PLAY" + : (info.mode = AUMODE_RECORD) ? "RECORD" + : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" + : "?")); +} +#endif /* DEBUG_AUDIO */ + +static int +OBSD_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char audiodev[64]; + Uint16 format; + audio_info_t info; + + AUDIO_INITINFO(&info); + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + +#ifdef USE_TIMER_SYNC + frame_ticks = 0.0; +#endif + + /* Open the audio device */ + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + if(audio_fd < 0) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return(-1); + } + + /* Set to play mode */ + info.mode = AUMODE_PLAY; + if(ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { + SDL_SetError("Couldn't put device into play mode"); + return(-1); + } + + mixbuf = NULL; + AUDIO_INITINFO(&info); + for (format = SDL_FirstAudioFormat(spec->format); + format; format = SDL_NextAudioFormat()) + { + switch(format) { + case AUDIO_U8: + info.play.encoding = AUDIO_ENCODING_ULINEAR; + info.play.precision = 8; + break; + case AUDIO_S8: + info.play.encoding = AUDIO_ENCODING_SLINEAR; + info.play.precision = 8; + break; + case AUDIO_S16LSB: + info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; + info.play.precision = 16; + break; + case AUDIO_S16MSB: + info.play.encoding = AUDIO_ENCODING_SLINEAR_BE; + info.play.precision = 16; + break; + case AUDIO_U16LSB: + info.play.encoding = AUDIO_ENCODING_ULINEAR_LE; + info.play.precision = 16; + break; + case AUDIO_U16MSB: + info.play.encoding = AUDIO_ENCODING_ULINEAR_BE; + info.play.precision = 16; + break; + default: + continue; + } + if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) + break; + } + + if(!format) { + SDL_SetError("No supported encoding for 0x%x", spec->format); + return(-1); + } + + spec->format = format; + + AUDIO_INITINFO(&info); + info.play.channels = spec->channels; + if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1) + spec->channels = 1; + AUDIO_INITINFO(&info); + info.play.sample_rate = spec->freq; + info.blocksize = spec->size; + info.hiwat = 5; + info.lowat = 3; + (void)ioctl(audio_fd, AUDIO_SETINFO, &info); + (void)ioctl(audio_fd, AUDIO_GETINFO, &info); + spec->freq = info.play.sample_rate; + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8*)SDL_AllocAudioMem(mixlen); + if(mixbuf == NULL) { + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + +#ifdef DEBUG_AUDIO + OBSD_Status(this); +#endif + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.h b/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.h new file mode 100644 index 0000000..c9f69cf --- /dev/null +++ b/3rdparty/SDL/src/audio/bsd/SDL_bsdaudio.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_openbsdaudio_h +#define _SDL_openbsdaudio_h + +#include "../SDL_sysaudio.h" + +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData +{ + /* The file descriptor for the audio device */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; + + /* Support for audio timing using a timer, in addition to select() */ + float frame_ticks; + float next_frame; +}; + +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_openbsdaudio_h */ diff --git a/3rdparty/SDL/src/audio/dart/SDL_dart.c b/3rdparty/SDL/src/audio/dart/SDL_dart.c new file mode 100644 index 0000000..77e530d --- /dev/null +++ b/3rdparty/SDL/src/audio/dart/SDL_dart.c @@ -0,0 +1,441 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "SDL_dart.h" + +// Buffer states: +#define BUFFER_EMPTY 0 +#define BUFFER_USED 1 + +typedef struct _tMixBufferDesc { + int iBufferUsage; // BUFFER_EMPTY or BUFFER_USED + SDL_AudioDevice *pSDLAudioDevice; +} tMixBufferDesc, *pMixBufferDesc; + + +//--------------------------------------------------------------------- +// DARTEventFunc +// +// This function is called by DART, when an event occures, like end of +// playback of a buffer, etc... +//--------------------------------------------------------------------- +LONG APIENTRY DARTEventFunc(ULONG ulStatus, + PMCI_MIX_BUFFER pBuffer, + ULONG ulFlags) +{ + if (ulFlags && MIX_WRITE_COMPLETE) + { // Playback of buffer completed! + + // Get pointer to buffer description + pMixBufferDesc pBufDesc; + + if (pBuffer) + { + pBufDesc = (pMixBufferDesc) (*pBuffer).ulUserParm; + + if (pBufDesc) + { + SDL_AudioDevice *pSDLAudioDevice = pBufDesc->pSDLAudioDevice; + // Set the buffer to be empty + pBufDesc->iBufferUsage = BUFFER_EMPTY; + // And notify DART feeder thread that it will have to work a bit. + if (pSDLAudioDevice) + DosPostEventSem(pSDLAudioDevice->hidden->hevAudioBufferPlayed); + } + } + } + return TRUE; +} + + +int DART_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + Uint16 test_format = SDL_FirstAudioFormat(spec->format); + int valid_datatype = 0; + MCI_AMP_OPEN_PARMS AmpOpenParms; + MCI_GENERIC_PARMS GenericParms; + int iDeviceOrd = 0; // Default device to be used + int bOpenShared = 1; // Try opening it shared + int iBits = 16; // Default is 16 bits signed + int iFreq = 44100; // Default is 44KHz + int iChannels = 2; // Default is 2 channels (Stereo) + int iNumBufs = 2; // Number of audio buffers: 2 + int iBufSize; + int iOpenMode; + int iSilence; + int rc; + + // First thing is to try to open a given DART device! + SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); + // pszDeviceType should contain the device type in low word, and device ordinal in high word! + AmpOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX | (iDeviceOrd << 16)); + + iOpenMode = MCI_WAIT | MCI_OPEN_TYPE_ID; + if (bOpenShared) iOpenMode |= MCI_OPEN_SHAREABLE; + + rc = mciSendCommand( 0, MCI_OPEN, + iOpenMode, + (PVOID) &AmpOpenParms, 0); + if (rc!=MCIERR_SUCCESS) // No audio available?? + return (-1); + // Save the device ID we got from DART! + // We will use this in the next calls! + iDeviceOrd = AmpOpenParms.usDeviceID; + + // Determine the audio parameters from the AudioSpec + if (spec->channels > 2) + spec->channels = 2; // !!! FIXME: more than stereo support in OS/2? + + while ((!valid_datatype) && (test_format)) { + spec->format = test_format; + valid_datatype = 1; + switch (test_format) { + case AUDIO_U8: + // Unsigned 8 bit audio data + iSilence = 0x80; + iBits = 8; + break; + + case AUDIO_S16LSB: + // Signed 16 bit audio data + iSilence = 0x00; + iBits = 16; + break; + + default: + valid_datatype = 0; + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { // shouldn't happen, but just in case... + // Close DART, and exit with error code! + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Unsupported audio format"); + return (-1); + } + + iFreq = spec->freq; + iChannels = spec->channels; + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + iBufSize = spec->size; + + // Now query this device if it supports the given freq/bits/channels! + SDL_memset(&(_this->hidden->MixSetupParms), 0, sizeof(MCI_MIXSETUP_PARMS)); + _this->hidden->MixSetupParms.ulBitsPerSample = iBits; + _this->hidden->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM; + _this->hidden->MixSetupParms.ulSamplesPerSec = iFreq; + _this->hidden->MixSetupParms.ulChannels = iChannels; + _this->hidden->MixSetupParms.ulFormatMode = MCI_PLAY; + _this->hidden->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO; + _this->hidden->MixSetupParms.pmixEvent = DARTEventFunc; + rc = mciSendCommand (iDeviceOrd, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_QUERYMODE, + &(_this->hidden->MixSetupParms), 0); + if (rc!=MCIERR_SUCCESS) + { // The device cannot handle this format! + // Close DART, and exit with error code! + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Audio device doesn't support requested audio format"); + return(-1); + } + // The device can handle this format, so initialize! + rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP, + MCI_WAIT | MCI_MIXSETUP_INIT, + &(_this->hidden->MixSetupParms), 0); + if (rc!=MCIERR_SUCCESS) + { // The device could not be opened! + // Close DART, and exit with error code! + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Audio device could not be set up"); + return(-1); + } + // Ok, the device is initialized. + // Now we should allocate buffers. For this, we need a place where + // the buffer descriptors will be: + _this->hidden->pMixBuffers = (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER)*iNumBufs); + if (!(_this->hidden->pMixBuffers)) + { // Not enough memory! + // Close DART, and exit with error code! + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Not enough memory for audio buffer descriptors"); + return(-1); + } + // Now that we have the place for buffer list, we can ask DART for the + // buffers! + _this->hidden->BufferParms.ulNumBuffers = iNumBufs; // Number of buffers + _this->hidden->BufferParms.ulBufferSize = iBufSize; // each with this size + _this->hidden->BufferParms.pBufList = _this->hidden->pMixBuffers; // getting descriptorts into this list + // Allocate buffers! + rc = mciSendCommand(iDeviceOrd, MCI_BUFFER, + MCI_WAIT | MCI_ALLOCATE_MEMORY, + &(_this->hidden->BufferParms), 0); + if ((rc!=MCIERR_SUCCESS) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize==0)) + { // Could not allocate memory! + // Close DART, and exit with error code! + SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("DART could not allocate buffers"); + return(-1); + } + // Ok, we have all the buffers allocated, let's mark them! + { + int i; + for (i=0; i<iNumBufs; i++) + { + pMixBufferDesc pBufferDesc = (pMixBufferDesc) SDL_malloc(sizeof(tMixBufferDesc));; + // Check if this buffer was really allocated by DART + if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc)) + { // Wrong buffer! + // Close DART, and exit with error code! + // Free buffer descriptions + { int j; + for (j=0; j<i; j++) SDL_free((void *)(_this->hidden->pMixBuffers[j].ulUserParm)); + } + // and cleanup + mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); + SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Error at internal buffer check"); + return(-1); + } + pBufferDesc->iBufferUsage = BUFFER_EMPTY; + pBufferDesc->pSDLAudioDevice = _this; + + _this->hidden->pMixBuffers[i].ulBufferLength = _this->hidden->BufferParms.ulBufferSize; + _this->hidden->pMixBuffers[i].ulUserParm = (ULONG) pBufferDesc; // User parameter: Description of buffer + _this->hidden->pMixBuffers[i].ulFlags = 0; // Some stuff should be flagged here for DART, like end of + // audio data, but as we will continously send + // audio data, there will be no end.:) + SDL_memset(_this->hidden->pMixBuffers[i].pBuffer, iSilence, iBufSize); + } + } + _this->hidden->iNextFreeBuffer = 0; + _this->hidden->iLastPlayedBuf = -1; + // Create event semaphore + if (DosCreateEventSem(NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE)!=NO_ERROR) + { + // Could not create event semaphore! + { + int i; + for (i=0; i<iNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); + } + mciSendCommand(iDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); + SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; + mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + SDL_SetError("Could not create event semaphore"); + return(-1); + } + + // Store the new settings in global variables + _this->hidden->iCurrDeviceOrd = iDeviceOrd; + _this->hidden->iCurrFreq = iFreq; + _this->hidden->iCurrBits = iBits; + _this->hidden->iCurrChannels = iChannels; + _this->hidden->iCurrNumBufs = iNumBufs; + _this->hidden->iCurrBufSize = iBufSize; + + return (0); +} + + + +void DART_ThreadInit(_THIS) +{ + return; +} + +/* This function waits until it is possible to write a full sound buffer */ +void DART_WaitAudio(_THIS) +{ + int i; + pMixBufferDesc pBufDesc; + ULONG ulPostCount; + + DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); + // If there is already an empty buffer, then return now! + for (i=0; i<_this->hidden->iCurrNumBufs; i++) + { + pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[i].ulUserParm; + if (pBufDesc->iBufferUsage == BUFFER_EMPTY) + return; + } + // If there is no empty buffer, wait for one to be empty! + DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // Wait max 1 sec!!! Important! + return; +} + +void DART_PlayAudio(_THIS) +{ + int iFreeBuf = _this->hidden->iNextFreeBuffer; + pMixBufferDesc pBufDesc; + + pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; + pBufDesc->iBufferUsage = BUFFER_USED; + // Send it to DART to be queued + _this->hidden->MixSetupParms.pmixWrite(_this->hidden->MixSetupParms.ulMixHandle, + &(_this->hidden->pMixBuffers[iFreeBuf]), 1); + + _this->hidden->iLastPlayedBuf = iFreeBuf; + iFreeBuf = (iFreeBuf+1) % _this->hidden->iCurrNumBufs; + _this->hidden->iNextFreeBuffer = iFreeBuf; +} + +Uint8 *DART_GetAudioBuf(_THIS) +{ + int iFreeBuf; + Uint8 *pResult; + pMixBufferDesc pBufDesc; + + if (_this) + { + if (_this->hidden) + { + iFreeBuf = _this->hidden->iNextFreeBuffer; + pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[iFreeBuf].ulUserParm; + + if (pBufDesc) + { + if (pBufDesc->iBufferUsage == BUFFER_EMPTY) + { + pResult = _this->hidden->pMixBuffers[iFreeBuf].pBuffer; + return pResult; + } + } else + printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", pBufDesc); + } else + printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", _this->hidden); + } else + printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); + return NULL; +} + +void DART_WaitDone(_THIS) +{ + pMixBufferDesc pBufDesc; + ULONG ulPostCount; + APIRET rc; + + pBufDesc = (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm; + rc = NO_ERROR; + while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc==NO_ERROR)) + { + DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); + rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! + } +} + +void DART_CloseAudio(_THIS) +{ + MCI_GENERIC_PARMS GenericParms; + int rc; + + // Stop DART playback + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, &GenericParms, 0); + if (rc!=MCIERR_SUCCESS) + { +#ifdef SFX_DEBUG_BUILD + printf("Could not stop DART playback!\n"); + fflush(stdout); +#endif + } + + // Close event semaphore + DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); + + // Free memory of buffer descriptions + { + int i; + for (i=0; i<_this->hidden->iCurrNumBufs; i++) SDL_free((void *)(_this->hidden->pMixBuffers[i].ulUserParm)); + } + + // Deallocate buffers + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY, &(_this->hidden->BufferParms), 0); + + // Free bufferlist + SDL_free(_this->hidden->pMixBuffers); _this->hidden->pMixBuffers = NULL; + + // Close dart + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, &(GenericParms), 0); +} + +/* Audio driver bootstrap functions */ + +int Audio_Available(void) +{ + return(1); +} + +void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) + { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( this ) + SDL_free(this); + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = DART_OpenAudio; + this->ThreadInit = DART_ThreadInit; + this->WaitAudio = DART_WaitAudio; + this->PlayAudio = DART_PlayAudio; + this->GetAudioBuf = DART_GetAudioBuf; + this->WaitDone = DART_WaitDone; + this->CloseAudio = DART_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap DART_bootstrap = { + "dart", "OS/2 Direct Audio RouTines (DART)", + Audio_Available, Audio_CreateDevice +}; + diff --git a/3rdparty/SDL/src/audio/dart/SDL_dart.h b/3rdparty/SDL/src/audio/dart/SDL_dart.h new file mode 100644 index 0000000..68c27bd --- /dev/null +++ b/3rdparty/SDL/src/audio/dart/SDL_dart.h @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#define INCL_TYPES +#define INCL_DOSSEMAPHORES +#define INCL_DOSRESOURCES +#define INCL_DOSMISC +#define INCL_DOSERRORS + +#define INCL_OS2MM +#define INCL_MMIOOS2 +#define INCL_MCIOS2 +#include <os2.h> +#include <os2me.h> // DART stuff and MMIO stuff + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *_this + +/* The DirectSound objects */ +struct SDL_PrivateAudioData +{ + int iCurrDeviceOrd; + int iCurrFreq; + int iCurrBits; + int iCurrChannels; + int iCurrNumBufs; + int iCurrBufSize; + + int iLastPlayedBuf; + int iNextFreeBuffer; + + MCI_BUFFER_PARMS BufferParms; // Sound buffer parameters + MCI_MIX_BUFFER *pMixBuffers; // Sound buffers + MCI_MIXSETUP_PARMS MixSetupParms; // Mixer setup parameters + HEV hevAudioBufferPlayed; // Event semaphore to indicate that an audio buffer has been played by DART +}; + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/dc/SDL_dcaudio.c b/3rdparty/SDL/src/audio/dc/SDL_dcaudio.c new file mode 100644 index 0000000..88daa87 --- /dev/null +++ b/3rdparty/SDL/src/audio/dc/SDL_dcaudio.c @@ -0,0 +1,246 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + +*/ +#include "SDL_config.h" + +/* Output dreamcast aica */ + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_dcaudio.h" + +#include "aica.h" +#include <dc/spu.h> + +/* Audio driver functions */ +static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DCAUD_WaitAudio(_THIS); +static void DCAUD_PlayAudio(_THIS); +static Uint8 *DCAUD_GetAudioBuf(_THIS); +static void DCAUD_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ +static int DCAUD_Available(void) +{ + return 1; +} + +static void DCAUD_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *DCAUD_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = DCAUD_OpenAudio; + this->WaitAudio = DCAUD_WaitAudio; + this->PlayAudio = DCAUD_PlayAudio; + this->GetAudioBuf = DCAUD_GetAudioBuf; + this->CloseAudio = DCAUD_CloseAudio; + + this->free = DCAUD_DeleteDevice; + + spu_init(); + + return this; +} + +AudioBootStrap DCAUD_bootstrap = { + "dcaudio", "Dreamcast AICA audio", + DCAUD_Available, DCAUD_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void DCAUD_WaitAudio(_THIS) +{ + if (this->hidden->playing) { + /* wait */ + while(aica_get_pos(0)/this->spec.samples == this->hidden->nextbuf) { + thd_pass(); + } + } +} + +#define SPU_RAM_BASE 0xa0800000 + +static void spu_memload_stereo8(int leftpos,int rightpos,void *src0,size_t size) +{ + uint8 *src = src0; + uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); + uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); + size = (size+7)/8; + while(size--) { + unsigned lval,rval; + lval = *src++; + rval = *src++; + lval|= (*src++)<<8; + rval|= (*src++)<<8; + lval|= (*src++)<<16; + rval|= (*src++)<<16; + lval|= (*src++)<<24; + rval|= (*src++)<<24; + g2_write_32(left++,lval); + g2_write_32(right++,rval); + g2_fifo_wait(); + } +} + +static void spu_memload_stereo16(int leftpos,int rightpos,void *src0,size_t size) +{ + uint16 *src = src0; + uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); + uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); + size = (size+7)/8; + while(size--) { + unsigned lval,rval; + lval = *src++; + rval = *src++; + lval|= (*src++)<<16; + rval|= (*src++)<<16; + g2_write_32(left++,lval); + g2_write_32(right++,rval); + g2_fifo_wait(); + } +} + +static void DCAUD_PlayAudio(_THIS) +{ + SDL_AudioSpec *spec = &this->spec; + unsigned int offset; + + if (this->hidden->playing) { + /* wait */ + while(aica_get_pos(0)/spec->samples == this->hidden->nextbuf) { + thd_pass(); + } + } + + offset = this->hidden->nextbuf*spec->size; + this->hidden->nextbuf^=1; + /* Write the audio data, checking for EAGAIN on broken audio drivers */ + if (spec->channels==1) { + spu_memload(this->hidden->leftpos+offset,this->hidden->mixbuf,this->hidden->mixlen); + } else { + offset/=2; + if ((this->spec.format&255)==8) { + spu_memload_stereo8(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen); + } else { + spu_memload_stereo16(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen); + } + } + + if (!this->hidden->playing) { + int mode; + this->hidden->playing = 1; + mode = (spec->format==AUDIO_S8)?SM_8BIT:SM_16BIT; + if (spec->channels==1) { + aica_play(0,mode,this->hidden->leftpos,0,spec->samples*2,spec->freq,255,128,1); + } else { + aica_play(0,mode,this->hidden->leftpos ,0,spec->samples*2,spec->freq,255,0,1); + aica_play(1,mode,this->hidden->rightpos,0,spec->samples*2,spec->freq,255,255,1); + } + } +} + +static Uint8 *DCAUD_GetAudioBuf(_THIS) +{ + return(this->hidden->mixbuf); +} + +static void DCAUD_CloseAudio(_THIS) +{ + aica_stop(0); + if (this->spec.channels==2) aica_stop(1); + if ( this->hidden->mixbuf != NULL ) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } +} + +static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + Uint16 test_format = SDL_FirstAudioFormat(spec->format); + int valid_datatype = 0; + while ((!valid_datatype) && (test_format)) { + spec->format = test_format; + switch (test_format) { + /* only formats Dreamcast accepts... */ + case AUDIO_S8: + case AUDIO_S16LSB: + valid_datatype = 1; + break; + + default: + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { /* shouldn't happen, but just in case... */ + SDL_SetError("Unsupported audio format"); + return (-1); + } + + if (spec->channels > 2) + spec->channels = 2; /* no more than stereo on the Dreamcast. */ + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + this->hidden->mixlen = spec->size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if ( this->hidden->mixbuf == NULL ) { + return(-1); + } + SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); + this->hidden->leftpos = 0x11000; + this->hidden->rightpos = 0x11000+spec->size; + this->hidden->playing = 0; + this->hidden->nextbuf = 0; + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/dc/SDL_dcaudio.h b/3rdparty/SDL/src/audio/dc/SDL_dcaudio.h new file mode 100644 index 0000000..fba95b3 --- /dev/null +++ b/3rdparty/SDL/src/audio/dc/SDL_dcaudio.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dcaudio_h +#define _SDL_dcaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + Uint8 *mixbuf; + Uint32 mixlen; + int playing; + int leftpos,rightpos; + int nextbuf; +}; + +#endif /* _SDL_dcaudio_h */ diff --git a/3rdparty/SDL/src/audio/dc/aica.c b/3rdparty/SDL/src/audio/dc/aica.c new file mode 100644 index 0000000..b6a1c93 --- /dev/null +++ b/3rdparty/SDL/src/audio/dc/aica.c @@ -0,0 +1,271 @@ +/* This file is part of the Dreamcast function library. + * Please see libdream.c for further details. + * + * (c)2000 Dan Potter + * modify BERO + */ +#include "aica.h" + +#include <arch/irq.h> +#include <dc/spu.h> + +/* #define dc_snd_base ((volatile unsigned char *)0x00800000) */ /* arm side */ +#define dc_snd_base ((volatile unsigned char *)0xa0700000) /* dc side */ + +/* Some convienence macros */ +#define SNDREGADDR(x) (0xa0700000 + (x)) +#define CHNREGADDR(ch,x) SNDREGADDR(0x80*(ch)+(x)) + + +#define SNDREG32(x) (*(volatile unsigned long *)SNDREGADDR(x)) +#define SNDREG8(x) (*(volatile unsigned char *)SNDREGADDR(x)) +#define CHNREG32(ch, x) (*(volatile unsigned long *)CHNREGADDR(ch,x)) +#define CHNREG8(ch, x) (*(volatile unsigned long *)CHNREGADDR(ch,x)) + +#define G2_LOCK(OLD) \ + do { \ + if (!irq_inside_int()) \ + OLD = irq_disable(); \ + /* suspend any G2 DMA here... */ \ + while((*(volatile unsigned int *)0xa05f688c) & 0x20) \ + ; \ + } while(0) + +#define G2_UNLOCK(OLD) \ + do { \ + /* resume any G2 DMA here... */ \ + if (!irq_inside_int()) \ + irq_restore(OLD); \ + } while(0) + + +void aica_init() { + int i, j, old = 0; + + /* Initialize AICA channels */ + G2_LOCK(old); + SNDREG32(0x2800) = 0x0000; + + for (i=0; i<64; i++) { + for (j=0; j<0x80; j+=4) { + if ((j&31)==0) g2_fifo_wait(); + CHNREG32(i, j) = 0; + } + g2_fifo_wait(); + CHNREG32(i,0) = 0x8000; + CHNREG32(i,20) = 0x1f; + } + + SNDREG32(0x2800) = 0x000f; + g2_fifo_wait(); + G2_UNLOCK(old); +} + +/* Translates a volume from linear form to logarithmic form (required by + the AICA chip */ +/* int logs[] = { + +0, 40, 50, 58, 63, 68, 73, 77, 80, 83, 86, 89, 92, 94, 97, 99, 101, 103, +105, 107, 109, 111, 112, 114, 116, 117, 119, 120, 122, 123, 125, 126, 127, +129, 130, 131, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145, +146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, +160, 161, 162, 162, 163, 164, 165, 166, 166, 167, 168, 169, 170, 170, 171, +172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 180, 180, 181, 182, +182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 188, 189, 190, 190, 191, +191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 198, 199, 199, +200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207, +208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, +215, 216, 216, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, +222, 222, 223, 223, 224, 224, 225, 225, 225, 226, 226, 227, 227, 228, 228, +228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234, +234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, +240, 241, 241, 241, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, +246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, +251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255 + +}; */ + +const static unsigned char logs[] = { + 0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, 55, 57, 59, 61, + 63, 65, 67, 69, 71, 73, 74, 76, 78, 79, 81, 82, 84, 85, 87, 88, + 90, 91, 92, 94, 95, 96, 98, 99, 100, 102, 103, 104, 105, 106, + 108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 156, + 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, + 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, + 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, + 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, + 195, 195, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, + 203, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209, 210, 210, + 211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218, + 219, 219, 220, 220, 221, 221, 222, 223, 223, 224, 224, 225, 225, + 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 232, 232, 233, + 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 239, 239, 240, + 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, + 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 254, 255 +}; + +/* For the moment this is going to have to suffice, until we really + figure out what these mean. */ +#define AICA_PAN(x) ((x)==0x80?(0):((x)<0x80?(0x1f):(0x0f))) +#define AICA_VOL(x) (0xff - logs[128 + (((x) & 0xff) / 2)]) +//#define AICA_VOL(x) (0xff - logs[x&255]) + +static inline unsigned AICA_FREQ(unsigned freq) { + unsigned long freq_lo, freq_base = 5644800; + int freq_hi = 7; + + /* Need to convert frequency to floating point format + (freq_hi is exponent, freq_lo is mantissa) + Formula is ferq = 44100*2^freq_hi*(1+freq_lo/1024) */ + while (freq < freq_base && freq_hi > -8) { + freq_base >>= 1; + --freq_hi; + } + while (freq < freq_base && freq_hi > -8) { + freq_base >>= 1; + freq_hi--; + } + freq_lo = (freq<<10) / freq_base; + return (freq_hi << 11) | (freq_lo & 1023); +} + +/* Sets up a sound channel completely. This is generally good if you want + a quick and dirty way to play notes. If you want a more comprehensive + set of routines (more like PC wavetable cards) see below. + + ch is the channel to play on (0 - 63) + smpptr is the pointer to the sound data; if you're running off the + SH4, then this ought to be (ptr - 0xa0800000); otherwise it's just + ptr. Basically, it's an offset into sound ram. + mode is one of the mode constants (16 bit, 8 bit, ADPCM) + nsamp is the number of samples to play (not number of bytes!) + freq is the sampling rate of the sound + vol is the volume, 0 to 0xff (0xff is louder) + pan is a panning constant -- 0 is left, 128 is center, 255 is right. + + This routine (and the similar ones) owe a lot to Marcus' sound example -- + I hadn't gotten quite this far into dissecting the individual regs yet. */ +void aica_play(int ch,int mode,unsigned long smpptr,int loopst,int loopend,int freq,int vol,int pan,int loopflag) { +/* int i; +*/ + int val; + int old = 0; + + /* Stop the channel (if it's already playing) */ + aica_stop(ch); + /* doesn't seem to be needed, but it's here just in case */ +/* + for (i=0; i<256; i++) { + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + } +*/ + G2_LOCK(old); + /* Envelope setup. The first of these is the loop point, + e.g., where the sample starts over when it loops. The second + is the loop end. This is the full length of the sample when + you are not looping, or the loop end point when you are (though + storing more than that is a waste of memory if you're not doing + volume enveloping). */ + CHNREG32(ch, 8) = loopst & 0xffff; + CHNREG32(ch, 12) = loopend & 0xffff; + + /* Write resulting values */ + CHNREG32(ch, 24) = AICA_FREQ(freq); + + /* Set volume, pan, and some other things that we don't know what + they do =) */ + CHNREG32(ch, 36) = AICA_PAN(pan) | (0xf<<8); + /* Convert the incoming volume and pan into hardware values */ + /* Vol starts at zero so we can ramp */ + vol = AICA_VOL(vol); + CHNREG32(ch, 40) = 0x24 | (vol<<8); + /* Convert the incoming volume and pan into hardware values */ + /* Vol starts at zero so we can ramp */ + + /* If we supported volume envelopes (which we don't yet) then + this value would set that up. The top 4 bits determine the + envelope speed. f is the fastest, 1 is the slowest, and 0 + seems to be an invalid value and does weird things). The + default (below) sets it into normal mode (play and terminate/loop). + CHNREG32(ch, 16) = 0xf010; + */ + CHNREG32(ch, 16) = 0x1f; /* No volume envelope */ + + + /* Set sample format, buffer address, and looping control. If + 0x0200 mask is set on reg 0, the sample loops infinitely. If + it's not set, the sample plays once and terminates. We'll + also set the bits to start playback here. */ + CHNREG32(ch, 4) = smpptr & 0xffff; + val = 0xc000 | 0x0000 | (mode<<7) | (smpptr >> 16); + if (loopflag) val|=0x200; + + CHNREG32(ch, 0) = val; + + G2_UNLOCK(old); + + /* Enable playback */ + /* CHNREG32(ch, 0) |= 0xc000; */ + g2_fifo_wait(); + +#if 0 + for (i=0xff; i>=vol; i--) { + if ((i&7)==0) g2_fifo_wait(); + CHNREG32(ch, 40) = 0x24 | (i<<8);; + } + + g2_fifo_wait(); +#endif +} + +/* Stop the sound on a given channel */ +void aica_stop(int ch) { + g2_write_32(CHNREGADDR(ch, 0),(g2_read_32(CHNREGADDR(ch, 0)) & ~0x4000) | 0x8000); + g2_fifo_wait(); +} + + +/* The rest of these routines can change the channel in mid-stride so you + can do things like vibrato and panning effects. */ + +/* Set channel volume */ +void aica_vol(int ch,int vol) { +// g2_write_8(CHNREGADDR(ch, 41),AICA_VOL(vol)); + g2_write_32(CHNREGADDR(ch, 40),(g2_read_32(CHNREGADDR(ch, 40))&0xffff00ff)|(AICA_VOL(vol)<<8) ); + g2_fifo_wait(); +} + +/* Set channel pan */ +void aica_pan(int ch,int pan) { +// g2_write_8(CHNREGADDR(ch, 36),AICA_PAN(pan)); + g2_write_32(CHNREGADDR(ch, 36),(g2_read_32(CHNREGADDR(ch, 36))&0xffffff00)|(AICA_PAN(pan)) ); + g2_fifo_wait(); +} + +/* Set channel frequency */ +void aica_freq(int ch,int freq) { + g2_write_32(CHNREGADDR(ch, 24),AICA_FREQ(freq)); + g2_fifo_wait(); +} + +/* Get channel position */ +int aica_get_pos(int ch) { +#if 1 + /* Observe channel ch */ + g2_write_32(SNDREGADDR(0x280c),(g2_read_32(SNDREGADDR(0x280c))&0xffff00ff) | (ch<<8)); + g2_fifo_wait(); + /* Update position counters */ + return g2_read_32(SNDREGADDR(0x2814)) & 0xffff; +#else + /* Observe channel ch */ + g2_write_8(SNDREGADDR(0x280d),ch); + /* Update position counters */ + return g2_read_32(SNDREGADDR(0x2814)) & 0xffff; +#endif +} diff --git a/3rdparty/SDL/src/audio/dc/aica.h b/3rdparty/SDL/src/audio/dc/aica.h new file mode 100644 index 0000000..2721e42 --- /dev/null +++ b/3rdparty/SDL/src/audio/dc/aica.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _AICA_H_ +#define _AICA_H_ + +#define AICA_MEM 0xa0800000 + +#define SM_8BIT 1 +#define SM_16BIT 0 +#define SM_ADPCM 2 + +void aica_play(int ch,int mode,unsigned long smpptr,int looptst,int loopend,int freq,int vol,int pan,int loopflag); +void aica_stop(int ch); +void aica_vol(int ch,int vol); +void aica_pan(int ch,int pan); +void aica_freq(int ch,int freq); +int aica_get_pos(int ch); + +#endif diff --git a/3rdparty/SDL/src/audio/disk/SDL_diskaudio.c b/3rdparty/SDL/src/audio/disk/SDL_diskaudio.c new file mode 100644 index 0000000..47c1009 --- /dev/null +++ b/3rdparty/SDL/src/audio/disk/SDL_diskaudio.c @@ -0,0 +1,186 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + This file written by Ryan C. Gordon (icculus@icculus.org) +*/ +#include "SDL_config.h" + +/* Output raw audio data to a file. */ + +#if HAVE_STDIO_H +#include <stdio.h> +#endif + +#include "SDL_rwops.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_diskaudio.h" + +/* The tag name used by DISK audio */ +#define DISKAUD_DRIVER_NAME "disk" + +/* environment variables and defaults. */ +#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE" +#define DISKDEFAULT_OUTFILE "sdlaudio.raw" +#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY" +#define DISKDEFAULT_WRITEDELAY 150 + +/* Audio driver functions */ +static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DISKAUD_WaitAudio(_THIS); +static void DISKAUD_PlayAudio(_THIS); +static Uint8 *DISKAUD_GetAudioBuf(_THIS); +static void DISKAUD_CloseAudio(_THIS); + +static const char *DISKAUD_GetOutputFilename(void) +{ + const char *envr = SDL_getenv(DISKENVR_OUTFILE); + return((envr != NULL) ? envr : DISKDEFAULT_OUTFILE); +} + +/* Audio driver bootstrap functions */ +static int DISKAUD_Available(void) +{ + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + if (envr && (SDL_strcmp(envr, DISKAUD_DRIVER_NAME) == 0)) { + return(1); + } + return(0); +} + +static void DISKAUD_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *DISKAUD_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + const char *envr; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + envr = SDL_getenv(DISKENVR_WRITEDELAY); + this->hidden->write_delay = (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY; + + /* Set the function pointers */ + this->OpenAudio = DISKAUD_OpenAudio; + this->WaitAudio = DISKAUD_WaitAudio; + this->PlayAudio = DISKAUD_PlayAudio; + this->GetAudioBuf = DISKAUD_GetAudioBuf; + this->CloseAudio = DISKAUD_CloseAudio; + + this->free = DISKAUD_DeleteDevice; + + return this; +} + +AudioBootStrap DISKAUD_bootstrap = { + DISKAUD_DRIVER_NAME, "direct-to-disk audio", + DISKAUD_Available, DISKAUD_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void DISKAUD_WaitAudio(_THIS) +{ + SDL_Delay(this->hidden->write_delay); +} + +static void DISKAUD_PlayAudio(_THIS) +{ + int written; + + /* Write the audio data */ + written = SDL_RWwrite(this->hidden->output, + this->hidden->mixbuf, 1, + this->hidden->mixlen); + + /* If we couldn't write, assume fatal error for now */ + if ( (Uint32)written != this->hidden->mixlen ) { + this->enabled = 0; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", written); +#endif +} + +static Uint8 *DISKAUD_GetAudioBuf(_THIS) +{ + return(this->hidden->mixbuf); +} + +static void DISKAUD_CloseAudio(_THIS) +{ + if ( this->hidden->mixbuf != NULL ) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if ( this->hidden->output != NULL ) { + SDL_RWclose(this->hidden->output); + this->hidden->output = NULL; + } +} + +static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + const char *fname = DISKAUD_GetOutputFilename(); + + /* Open the audio device */ + this->hidden->output = SDL_RWFromFile(fname, "wb"); + if ( this->hidden->output == NULL ) { + return(-1); + } + +#if HAVE_STDIO_H + fprintf(stderr, "WARNING: You are using the SDL disk writer" + " audio driver!\n Writing to file [%s].\n", fname); +#endif + + /* Allocate mixing buffer */ + this->hidden->mixlen = spec->size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if ( this->hidden->mixbuf == NULL ) { + return(-1); + } + SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); + + /* We're ready to rock and roll. :-) */ + return(0); +} + diff --git a/3rdparty/SDL/src/audio/disk/SDL_diskaudio.h b/3rdparty/SDL/src/audio/disk/SDL_diskaudio.h new file mode 100644 index 0000000..24d7c9e --- /dev/null +++ b/3rdparty/SDL/src/audio/disk/SDL_diskaudio.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_diskaudio_h +#define _SDL_diskaudio_h + +#include "SDL_rwops.h" +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + SDL_RWops *output; + Uint8 *mixbuf; + Uint32 mixlen; + Uint32 write_delay; +}; + +#endif /* _SDL_diskaudio_h */ diff --git a/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.c b/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.c new file mode 100644 index 0000000..39f81d9 --- /dev/null +++ b/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.c @@ -0,0 +1,455 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <stdio.h> +#include <string.h> /* For strerror() */ +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#if SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H +/* This is installed on some systems */ +#include <soundcard.h> +#else +/* This is recommended by OSS */ +#include <sys/soundcard.h> +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((Uint8 *)-1) +#endif + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_dmaaudio.h" + +/* The tag name used by DMA audio */ +#define DMA_DRIVER_NAME "dma" + +/* Open the audio device for playback, and don't block if busy */ +#define OPEN_FLAGS (O_RDWR|O_NONBLOCK) + +/* Audio driver functions */ +static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DMA_WaitAudio(_THIS); +static void DMA_PlayAudio(_THIS); +static Uint8 *DMA_GetAudioBuf(_THIS); +static void DMA_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int available; + int fd; + + available = 0; + + fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); + if ( fd >= 0 ) { + int caps; + struct audio_buf_info info; + + if ( (ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) && + (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) && + (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0) ) { + available = 1; + } + close(fd); + } + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = DMA_OpenAudio; + this->WaitAudio = DMA_WaitAudio; + this->PlayAudio = DMA_PlayAudio; + this->GetAudioBuf = DMA_GetAudioBuf; + this->CloseAudio = DMA_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap DMA_bootstrap = { + DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void DMA_WaitAudio(_THIS) +{ + fd_set fdset; + + /* Check to see if the thread-parent process is still alive */ + { static int cnt = 0; + /* Note that this only works with thread implementations + that use a different process id for each thread. + */ + if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ + if ( kill(parent, 0) < 0 ) { + this->enabled = 0; + } + } + } + + /* See if we need to use timed audio synchronization */ + if ( frame_ticks ) { + /* Use timer for general audio synchronization */ + Sint32 ticks; + + ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; + if ( ticks > 0 ) { + SDL_Delay(ticks); + } + } else { + /* Use select() for audio synchronization */ + struct timeval timeout; + FD_ZERO(&fdset); + FD_SET(audio_fd, &fdset); + timeout.tv_sec = 10; + timeout.tv_usec = 0; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Waiting for audio to get ready\n"); +#endif + if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { + const char *message = +#ifdef AUDIO_OSPACE_HACK + "Audio timeout - buggy audio driver? (trying ospace)"; +#else + "Audio timeout - buggy audio driver? (disabled)"; +#endif + /* In general we should never print to the screen, + but in this case we have no other way of letting + the user know what happened. + */ + fprintf(stderr, "SDL: %s\n", message); +#ifdef AUDIO_OSPACE_HACK + /* We may be able to use GET_OSPACE trick */ + frame_ticks = (float)(this->spec->samples*1000) / + this->spec->freq; + next_frame = SDL_GetTicks()+frame_ticks; +#else + this->enabled = 0; + /* Don't try to close - may hang */ + audio_fd = -1; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Done disabling audio\n"); +#endif +#endif /* AUDIO_OSPACE_HACK */ + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Ready!\n"); +#endif + } +} + +static void DMA_PlayAudio(_THIS) +{ + /* If timer synchronization is enabled, set the next write frame */ + if ( frame_ticks ) { + next_frame += frame_ticks; + } + return; +} + +static Uint8 *DMA_GetAudioBuf(_THIS) +{ + count_info info; + int playing; + int filling; + + /* Get number of blocks, looping if we're not using select() */ + do { + if ( ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0 ) { + /* Uh oh... */ + this->enabled = 0; + return(NULL); + } + } while ( frame_ticks && (info.blocks < 1) ); +#ifdef DEBUG_AUDIO + if ( info.blocks > 1 ) { + printf("Warning: audio underflow (%d frags)\n", info.blocks-1); + } +#endif + playing = info.ptr / this->spec.size; + filling = (playing + 1)%num_buffers; + return (dma_buf + (filling * this->spec.size)); +} + +static void DMA_CloseAudio(_THIS) +{ + if ( dma_buf != NULL ) { + munmap(dma_buf, dma_len); + dma_buf = NULL; + } + if ( audio_fd >= 0 ) { + close(audio_fd); + audio_fd = -1; + } +} + +static int DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, + SDL_AudioSpec *spec) +{ + int frag_spec; + int value; + + /* Close and then reopen the audio device */ + close(audio_fd); + audio_fd = open(audiodev, O_RDWR, 0); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return(-1); + } + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Determine the power of two of the fragment size */ + for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); + if ( (0x01<<frag_spec) != spec->size ) { + SDL_SetError("Fragment size must be a power of two"); + return(-1); + } + + /* Set the audio buffering parameters */ + if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { + SDL_SetError("Couldn't set audio fragment spec"); + return(-1); + } + + /* Set the audio format */ + value = format; + if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || + (value != format) ) { + SDL_SetError("Couldn't set audio format"); + return(-1); + } + + /* Set mono or stereo audio */ + value = (spec->channels > 1); + if ( (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) || + (value != stereo) ) { + SDL_SetError("Couldn't set audio channels"); + return(-1); + } + + /* Set the DSP frequency */ + value = spec->freq; + if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) { + SDL_SetError("Couldn't set audio frequency"); + return(-1); + } + spec->freq = value; + + /* We successfully re-opened the audio */ + return(0); +} + +static int DMA_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char audiodev[1024]; + int format; + int stereo; + int value; + Uint16 test_format; + struct audio_buf_info info; + + /* Reset the timer synchronization flag */ + frame_ticks = 0.0; + + /* Open the audio device */ + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return(-1); + } + dma_buf = NULL; + ioctl(audio_fd, SNDCTL_DSP_RESET, 0); + + /* Get a list of supported hardware formats */ + if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { + SDL_SetError("Couldn't get audio format list"); + return(-1); + } + + /* Try for a closest match on audio format */ + format = 0; + for ( test_format = SDL_FirstAudioFormat(spec->format); + ! format && test_format; ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + switch ( test_format ) { + case AUDIO_U8: + if ( value & AFMT_U8 ) { + format = AFMT_U8; + } + break; + case AUDIO_S8: + if ( value & AFMT_S8 ) { + format = AFMT_S8; + } + break; + case AUDIO_S16LSB: + if ( value & AFMT_S16_LE ) { + format = AFMT_S16_LE; + } + break; + case AUDIO_S16MSB: + if ( value & AFMT_S16_BE ) { + format = AFMT_S16_BE; + } + break; + case AUDIO_U16LSB: + if ( value & AFMT_U16_LE ) { + format = AFMT_U16_LE; + } + break; + case AUDIO_U16MSB: + if ( value & AFMT_U16_BE ) { + format = AFMT_U16_BE; + } + break; + default: + format = 0; + break; + } + if ( ! format ) { + test_format = SDL_NextAudioFormat(); + } + } + if ( format == 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + return(-1); + } + spec->format = test_format; + + /* Set the audio format */ + value = format; + if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || + (value != format) ) { + SDL_SetError("Couldn't set audio format"); + return(-1); + } + + /* Set mono or stereo audio (currently only two channels supported) */ + stereo = (spec->channels > 1); + ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo); + if ( stereo ) { + spec->channels = 2; + } else { + spec->channels = 1; + } + + /* Because some drivers don't allow setting the buffer size + after setting the format, we must re-open the audio device + once we know what format and channels are supported + */ + if ( DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0 ) { + /* Error is set by DMA_ReopenAudio() */ + return(-1); + } + + /* Memory map the audio buffer */ + if ( ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0 ) { + SDL_SetError("Couldn't get OSPACE parameters"); + return(-1); + } + spec->size = info.fragsize; + spec->samples = spec->size / ((spec->format & 0xFF) / 8); + spec->samples /= spec->channels; + num_buffers = info.fragstotal; + dma_len = num_buffers*spec->size; + dma_buf = (Uint8 *)mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED, + audio_fd, 0); + if ( dma_buf == MAP_FAILED ) { + SDL_SetError("DMA memory map failed"); + dma_buf = NULL; + return(-1); + } + SDL_memset(dma_buf, spec->silence, dma_len); + + /* Check to see if we need to use select() workaround */ + { char *workaround; + workaround = SDL_getenv("SDL_DSP_NOSELECT"); + if ( workaround ) { + frame_ticks = (float)(spec->samples*1000)/spec->freq; + next_frame = SDL_GetTicks()+frame_ticks; + } + } + + /* Trigger audio playback */ + value = 0; + ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value); + value = PCM_ENABLE_OUTPUT; + if ( ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0 ) { + SDL_SetError("Couldn't trigger audio output"); + return(-1); + } + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.h b/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.h new file mode 100644 index 0000000..9a45f73 --- /dev/null +++ b/3rdparty/SDL/src/audio/dma/SDL_dmaaudio.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dspaudio_h +#define _SDL_dspaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *dma_buf; + int dma_len; + int num_buffers; + + /* Support for audio timing using a timer, in addition to select() */ + float frame_ticks; + float next_frame; +}; +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define dma_buf (this->hidden->dma_buf) +#define dma_len (this->hidden->dma_len) +#define num_buffers (this->hidden->num_buffers) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_dspaudio_h */ diff --git a/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.c b/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.c new file mode 100644 index 0000000..1dcd242 --- /dev/null +++ b/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.c @@ -0,0 +1,242 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer (For IRIX 6.5 and higher) */ +/* patch for IRIX 5 by Georg Schwarz 18/07/2004 */ + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "SDL_irixaudio.h" + + +#ifndef AL_RESOURCE /* as a test whether we use the old IRIX audio libraries */ +#define OLD_IRIX_AUDIO +#define alClosePort(x) ALcloseport(x) +#define alFreeConfig(x) ALfreeconfig(x) +#define alGetFillable(x) ALgetfillable(x) +#define alNewConfig() ALnewconfig() +#define alOpenPort(x,y,z) ALopenport(x,y,z) +#define alSetChannels(x,y) ALsetchannels(x,y) +#define alSetQueueSize(x,y) ALsetqueuesize(x,y) +#define alSetSampFmt(x,y) ALsetsampfmt(x,y) +#define alSetWidth(x,y) ALsetwidth(x,y) +#endif + +/* Audio driver functions */ +static int AL_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void AL_WaitAudio(_THIS); +static void AL_PlayAudio(_THIS); +static Uint8 *AL_GetAudioBuf(_THIS); +static void AL_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + return 1; +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = AL_OpenAudio; + this->WaitAudio = AL_WaitAudio; + this->PlayAudio = AL_PlayAudio; + this->GetAudioBuf = AL_GetAudioBuf; + this->CloseAudio = AL_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap DMEDIA_bootstrap = { + "AL", "IRIX DMedia audio", + Audio_Available, Audio_CreateDevice +}; + + +void static AL_WaitAudio(_THIS) +{ + Sint32 timeleft; + + timeleft = this->spec.samples - alGetFillable(audio_port); + if ( timeleft > 0 ) { + timeleft /= (this->spec.freq/1000); + SDL_Delay((Uint32)timeleft); + } +} + +static void AL_PlayAudio(_THIS) +{ + /* Write the audio data out */ + if ( alWriteFrames(audio_port, mixbuf, this->spec.samples) < 0 ) { + /* Assume fatal error, for now */ + this->enabled = 0; + } +} + +static Uint8 *AL_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void AL_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( audio_port != NULL ) { + alClosePort(audio_port); + audio_port = NULL; + } +} + +static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec) +{ + Uint16 test_format = SDL_FirstAudioFormat(spec->format); + long width = 0; + long fmt = 0; + int valid = 0; + +#ifdef OLD_IRIX_AUDIO + { + long audio_param[2]; + audio_param[0] = AL_OUTPUT_RATE; + audio_param[1] = spec->freq; + valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0); + } +#else + { + ALpv audio_param; + audio_param.param = AL_RATE; + audio_param.value.i = spec->freq; + valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0); + } +#endif + + while ((!valid) && (test_format)) { + valid = 1; + spec->format = test_format; + + switch (test_format) { + case AUDIO_S8: + width = AL_SAMPLE_8; + fmt = AL_SAMPFMT_TWOSCOMP; + break; + + case AUDIO_S16SYS: + width = AL_SAMPLE_16; + fmt = AL_SAMPFMT_TWOSCOMP; + break; + + default: + valid = 0; + test_format = SDL_NextAudioFormat(); + break; + } + + if (valid) { + ALconfig audio_config = alNewConfig(); + valid = 0; + if (audio_config) { + if (alSetChannels(audio_config, spec->channels) < 0) { + if (spec->channels > 2) { /* can't handle > stereo? */ + spec->channels = 2; /* try again below. */ + } + } + + if ((alSetSampFmt(audio_config, fmt) >= 0) && + ((!width) || (alSetWidth(audio_config, width) >= 0)) && + (alSetQueueSize(audio_config, spec->samples * 2) >= 0) && + (alSetChannels(audio_config, spec->channels) >= 0)) { + + audio_port = alOpenPort("SDL audio", "w", audio_config); + if (audio_port == NULL) { + /* docs say AL_BAD_CHANNELS happens here, too. */ + int err = oserror(); + if (err == AL_BAD_CHANNELS) { + spec->channels = 2; + alSetChannels(audio_config, spec->channels); + audio_port = alOpenPort("SDL audio", "w", + audio_config); + } + } + + if (audio_port != NULL) { + valid = 1; + } + } + + alFreeConfig(audio_config); + } + } + } + + if (!valid) { + SDL_SetError("Unsupported audio format"); + return (-1); + } + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size); + if (mixbuf == NULL) { + SDL_OutOfMemory(); + return (-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* We're ready to rock and roll. :-) */ + return (0); +} + diff --git a/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.h b/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.h new file mode 100644 index 0000000..c04f497 --- /dev/null +++ b/3rdparty/SDL/src/audio/dmedia/SDL_irixaudio.h @@ -0,0 +1,45 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include <dmedia/audio.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The handle for the audio device */ + ALport audio_port; + + Uint8 *mixbuf; /* The app mixing buffer */ +}; + +/* Old variable names */ +#define audio_port (this->hidden->audio_port) +#define mixbuf (this->hidden->mixbuf) + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.c b/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.c new file mode 100644 index 0000000..256c547 --- /dev/null +++ b/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.c @@ -0,0 +1,340 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Modified in Oct 2004 by Hannu Savolainen + hannu@opensound.com +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <stdio.h> /* For perror() */ +#include <string.h> /* For strerror() */ +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> + +#if SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H +/* This is installed on some systems */ +#include <soundcard.h> +#else +/* This is recommended by OSS */ +#include <sys/soundcard.h> +#endif + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_dspaudio.h" + +/* The tag name used by DSP audio */ +#define DSP_DRIVER_NAME "dsp" + +/* Open the audio device for playback, and don't block if busy */ +#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) + +/* Audio driver functions */ +static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DSP_WaitAudio(_THIS); +static void DSP_PlayAudio(_THIS); +static Uint8 *DSP_GetAudioBuf(_THIS); +static void DSP_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int fd; + int available; + + available = 0; + fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); + if ( fd >= 0 ) { + available = 1; + close(fd); + } + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = DSP_OpenAudio; + this->WaitAudio = DSP_WaitAudio; + this->PlayAudio = DSP_PlayAudio; + this->GetAudioBuf = DSP_GetAudioBuf; + this->CloseAudio = DSP_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap DSP_bootstrap = { + DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void DSP_WaitAudio(_THIS) +{ + /* Not needed at all since OSS handles waiting automagically */ +} + +static void DSP_PlayAudio(_THIS) +{ + if (write(audio_fd, mixbuf, mixlen)==-1) + { + perror("Audio write"); + this->enabled = 0; + } + +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); +#endif +} + +static Uint8 *DSP_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void DSP_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( audio_fd >= 0 ) { + close(audio_fd); + audio_fd = -1; + } +} + +static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char audiodev[1024]; + int format; + int value; + int frag_spec; + Uint16 test_format; + + /* Make sure fragment size stays a power of 2, or OSS fails. */ + /* I don't know which of these are actually legal values, though... */ + if (spec->channels > 8) + spec->channels = 8; + else if (spec->channels > 4) + spec->channels = 4; + else if (spec->channels > 2) + spec->channels = 2; + + /* Open the audio device */ + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return(-1); + } + mixbuf = NULL; + + /* Make the file descriptor use blocking writes with fcntl() */ + { long flags; + flags = fcntl(audio_fd, F_GETFL); + flags &= ~O_NONBLOCK; + if ( fcntl(audio_fd, F_SETFL, flags) < 0 ) { + SDL_SetError("Couldn't set audio blocking mode"); + DSP_CloseAudio(this); + return(-1); + } + } + + /* Get a list of supported hardware formats */ + if ( ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0 ) { + perror("SNDCTL_DSP_GETFMTS"); + SDL_SetError("Couldn't get audio format list"); + DSP_CloseAudio(this); + return(-1); + } + + /* Try for a closest match on audio format */ + format = 0; + for ( test_format = SDL_FirstAudioFormat(spec->format); + ! format && test_format; ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + switch ( test_format ) { + case AUDIO_U8: + if ( value & AFMT_U8 ) { + format = AFMT_U8; + } + break; + case AUDIO_S16LSB: + if ( value & AFMT_S16_LE ) { + format = AFMT_S16_LE; + } + break; + case AUDIO_S16MSB: + if ( value & AFMT_S16_BE ) { + format = AFMT_S16_BE; + } + break; +#if 0 +/* + * These formats are not used by any real life systems so they are not + * needed here. + */ + case AUDIO_S8: + if ( value & AFMT_S8 ) { + format = AFMT_S8; + } + break; + case AUDIO_U16LSB: + if ( value & AFMT_U16_LE ) { + format = AFMT_U16_LE; + } + break; + case AUDIO_U16MSB: + if ( value & AFMT_U16_BE ) { + format = AFMT_U16_BE; + } + break; +#endif + default: + format = 0; + break; + } + if ( ! format ) { + test_format = SDL_NextAudioFormat(); + } + } + if ( format == 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + DSP_CloseAudio(this); + return(-1); + } + spec->format = test_format; + + /* Set the audio format */ + value = format; + if ( (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || + (value != format) ) { + perror("SNDCTL_DSP_SETFMT"); + SDL_SetError("Couldn't set audio format"); + DSP_CloseAudio(this); + return(-1); + } + + /* Set the number of channels of output */ + value = spec->channels; + if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0 ) { + perror("SNDCTL_DSP_CHANNELS"); + SDL_SetError("Cannot set the number of channels"); + DSP_CloseAudio(this); + return(-1); + } + spec->channels = value; + + /* Set the DSP frequency */ + value = spec->freq; + if ( ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0 ) { + perror("SNDCTL_DSP_SPEED"); + SDL_SetError("Couldn't set audio frequency"); + DSP_CloseAudio(this); + return(-1); + } + spec->freq = value; + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Determine the power of two of the fragment size */ + for ( frag_spec = 0; (0x01U<<frag_spec) < spec->size; ++frag_spec ); + if ( (0x01U<<frag_spec) != spec->size ) { + SDL_SetError("Fragment size must be a power of two"); + DSP_CloseAudio(this); + return(-1); + } + frag_spec |= 0x00020000; /* two fragments, for low latency */ + + /* Set the audio buffering parameters */ +#ifdef DEBUG_AUDIO + fprintf(stderr, "Requesting %d fragments of size %d\n", + (frag_spec >> 16), 1<<(frag_spec&0xFFFF)); +#endif + if ( ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0 ) { + perror("SNDCTL_DSP_SETFRAGMENT"); + } +#ifdef DEBUG_AUDIO + { audio_buf_info info; + ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info); + fprintf(stderr, "fragments = %d\n", info.fragments); + fprintf(stderr, "fragstotal = %d\n", info.fragstotal); + fprintf(stderr, "fragsize = %d\n", info.fragsize); + fprintf(stderr, "bytes = %d\n", info.bytes); + } +#endif + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + DSP_CloseAudio(this); + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.h b/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.h new file mode 100644 index 0000000..382544f --- /dev/null +++ b/3rdparty/SDL/src/audio/dsp/SDL_dspaudio.h @@ -0,0 +1,53 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dspaudio_h +#define _SDL_dspaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; +}; +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_dspaudio_h */ diff --git a/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.c b/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.c new file mode 100644 index 0000000..484b50d --- /dev/null +++ b/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.c @@ -0,0 +1,156 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + This file written by Ryan C. Gordon (icculus@icculus.org) +*/ +#include "SDL_config.h" + +/* Output audio to nowhere... */ + +#include "SDL_rwops.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_dummyaudio.h" + +/* The tag name used by DUMMY audio */ +#define DUMMYAUD_DRIVER_NAME "dummy" + +/* Audio driver functions */ +static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DUMMYAUD_WaitAudio(_THIS); +static void DUMMYAUD_PlayAudio(_THIS); +static Uint8 *DUMMYAUD_GetAudioBuf(_THIS); +static void DUMMYAUD_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ +static int DUMMYAUD_Available(void) +{ + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) { + return(1); + } + return(0); +} + +static void DUMMYAUD_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *DUMMYAUD_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = DUMMYAUD_OpenAudio; + this->WaitAudio = DUMMYAUD_WaitAudio; + this->PlayAudio = DUMMYAUD_PlayAudio; + this->GetAudioBuf = DUMMYAUD_GetAudioBuf; + this->CloseAudio = DUMMYAUD_CloseAudio; + + this->free = DUMMYAUD_DeleteDevice; + + return this; +} + +AudioBootStrap DUMMYAUD_bootstrap = { + DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver", + DUMMYAUD_Available, DUMMYAUD_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void DUMMYAUD_WaitAudio(_THIS) +{ + /* Don't block on first calls to simulate initial fragment filling. */ + if (this->hidden->initial_calls) + this->hidden->initial_calls--; + else + SDL_Delay(this->hidden->write_delay); +} + +static void DUMMYAUD_PlayAudio(_THIS) +{ + /* no-op...this is a null driver. */ +} + +static Uint8 *DUMMYAUD_GetAudioBuf(_THIS) +{ + return(this->hidden->mixbuf); +} + +static void DUMMYAUD_CloseAudio(_THIS) +{ + if ( this->hidden->mixbuf != NULL ) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } +} + +static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + float bytes_per_sec = 0.0f; + + /* Allocate mixing buffer */ + this->hidden->mixlen = spec->size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if ( this->hidden->mixbuf == NULL ) { + return(-1); + } + SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); + + bytes_per_sec = (float) (((spec->format & 0xFF) / 8) * + spec->channels * spec->freq); + + /* + * We try to make this request more audio at the correct rate for + * a given audio spec, so timing stays fairly faithful. + * Also, we have it not block at all for the first two calls, so + * it seems like we're filling two audio fragments right out of the + * gate, like other SDL drivers tend to do. + */ + this->hidden->initial_calls = 2; + this->hidden->write_delay = + (Uint32) ((((float) spec->size) / bytes_per_sec) * 1000.0f); + + /* We're ready to rock and roll. :-) */ + return(0); +} + diff --git a/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.h b/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.h new file mode 100644 index 0000000..74a69ca --- /dev/null +++ b/3rdparty/SDL/src/audio/dummy/SDL_dummyaudio.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dummyaudio_h +#define _SDL_dummyaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + Uint8 *mixbuf; + Uint32 mixlen; + Uint32 write_delay; + Uint32 initial_calls; +}; + +#endif /* _SDL_dummyaudio_h */ diff --git a/3rdparty/SDL/src/audio/esd/SDL_esdaudio.c b/3rdparty/SDL/src/audio/esd/SDL_esdaudio.c new file mode 100644 index 0000000..f54b0ea --- /dev/null +++ b/3rdparty/SDL/src/audio/esd/SDL_esdaudio.c @@ -0,0 +1,323 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to an ESD network stream mixing buffer */ + +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <esd.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_esdaudio.h" + +#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC +#include "SDL_name.h" +#include "SDL_loadso.h" +#else +#define SDL_NAME(X) X +#endif + +/* The tag name used by ESD audio */ +#define ESD_DRIVER_NAME "esd" + +/* Audio driver functions */ +static int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void ESD_WaitAudio(_THIS); +static void ESD_PlayAudio(_THIS); +static Uint8 *ESD_GetAudioBuf(_THIS); +static void ESD_CloseAudio(_THIS); + +#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC + +static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; +static void *esd_handle = NULL; +static int esd_loaded = 0; + +static int (*SDL_NAME(esd_open_sound))( const char *host ); +static int (*SDL_NAME(esd_close))( int esd ); +static int (*SDL_NAME(esd_play_stream))( esd_format_t format, int rate, + const char *host, const char *name ); +static struct { + const char *name; + void **func; +} esd_functions[] = { + { "esd_open_sound", (void **)&SDL_NAME(esd_open_sound) }, + { "esd_close", (void **)&SDL_NAME(esd_close) }, + { "esd_play_stream", (void **)&SDL_NAME(esd_play_stream) }, +}; + +static void UnloadESDLibrary() +{ + if ( esd_loaded ) { + SDL_UnloadObject(esd_handle); + esd_handle = NULL; + esd_loaded = 0; + } +} + +static int LoadESDLibrary(void) +{ + int i, retval = -1; + + esd_handle = SDL_LoadObject(esd_library); + if ( esd_handle ) { + esd_loaded = 1; + retval = 0; + for ( i=0; i<SDL_arraysize(esd_functions); ++i ) { + *esd_functions[i].func = SDL_LoadFunction(esd_handle, esd_functions[i].name); + if ( !*esd_functions[i].func ) { + retval = -1; + UnloadESDLibrary(); + break; + } + } + } + return retval; +} + +#else + +static void UnloadESDLibrary() +{ + return; +} + +static int LoadESDLibrary(void) +{ + return 0; +} + +#endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */ + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int connection; + int available; + + available = 0; + if ( LoadESDLibrary() < 0 ) { + return available; + } + connection = SDL_NAME(esd_open_sound)(NULL); + if ( connection >= 0 ) { + available = 1; + SDL_NAME(esd_close)(connection); + } + UnloadESDLibrary(); + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); + UnloadESDLibrary(); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + LoadESDLibrary(); + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = ESD_OpenAudio; + this->WaitAudio = ESD_WaitAudio; + this->PlayAudio = ESD_PlayAudio; + this->GetAudioBuf = ESD_GetAudioBuf; + this->CloseAudio = ESD_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap ESD_bootstrap = { + ESD_DRIVER_NAME, "Enlightened Sound Daemon", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void ESD_WaitAudio(_THIS) +{ + Sint32 ticks; + + /* Check to see if the thread-parent process is still alive */ + { static int cnt = 0; + /* Note that this only works with thread implementations + that use a different process id for each thread. + */ + if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */ + if ( kill(parent, 0) < 0 ) { + this->enabled = 0; + } + } + } + + /* Use timer for general audio synchronization */ + ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; + if ( ticks > 0 ) { + SDL_Delay(ticks); + } +} + +static void ESD_PlayAudio(_THIS) +{ + int written; + + /* Write the audio data, checking for EAGAIN on broken audio drivers */ + do { + written = write(audio_fd, mixbuf, mixlen); + if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { + SDL_Delay(1); /* Let a little CPU time go by */ + } + } while ( (written < 0) && + ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); + + /* Set the next write frame */ + next_frame += frame_ticks; + + /* If we couldn't write, assume fatal error for now */ + if ( written < 0 ) { + this->enabled = 0; + } +} + +static Uint8 *ESD_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void ESD_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( audio_fd >= 0 ) { + SDL_NAME(esd_close)(audio_fd); + audio_fd = -1; + } +} + +/* Try to get the name of the program */ +static char *get_progname(void) +{ + char *progname = NULL; +#ifdef __LINUX__ + FILE *fp; + static char temp[BUFSIZ]; + + SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); + fp = fopen(temp, "r"); + if ( fp != NULL ) { + if ( fgets(temp, sizeof(temp)-1, fp) ) { + progname = SDL_strrchr(temp, '/'); + if ( progname == NULL ) { + progname = temp; + } else { + progname = progname+1; + } + } + fclose(fp); + } +#endif + return(progname); +} + +static int ESD_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + esd_format_t format; + + /* Convert audio spec to the ESD audio format */ + format = (ESD_STREAM | ESD_PLAY); + switch ( spec->format & 0xFF ) { + case 8: + format |= ESD_BITS8; + break; + case 16: + format |= ESD_BITS16; + break; + default: + SDL_SetError("Unsupported ESD audio format"); + return(-1); + } + if ( spec->channels == 1 ) { + format |= ESD_MONO; + } else { + format |= ESD_STEREO; + } +#if 0 + spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ +#endif + + /* Open a connection to the ESD audio server */ + audio_fd = SDL_NAME(esd_play_stream)(format, spec->freq, NULL, get_progname()); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open ESD connection"); + return(-1); + } + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + frame_ticks = (float)(spec->samples*1000)/spec->freq; + next_frame = SDL_GetTicks()+frame_ticks; + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/esd/SDL_esdaudio.h b/3rdparty/SDL/src/audio/esd/SDL_esdaudio.h new file mode 100644 index 0000000..da4ae6a --- /dev/null +++ b/3rdparty/SDL/src/audio/esd/SDL_esdaudio.h @@ -0,0 +1,57 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_esdaudio_h +#define _SDL_esdaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; + + /* Support for audio timing using a timer */ + float frame_ticks; + float next_frame; +}; +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_esdaudio_h */ diff --git a/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.c b/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.c new file mode 100644 index 0000000..31316d1 --- /dev/null +++ b/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.c @@ -0,0 +1,291 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <CoreAudio/CoreAudio.h> +#include <CoreServices/CoreServices.h> +#include <AudioUnit/AudioUnit.h> +#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 +#include <AudioUnit/AUNTComponent.h> +#endif + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" +#include "SDL_coreaudio.h" + + +/* Audio driver functions */ + +static int Core_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Core_WaitAudio(_THIS); +static void Core_PlayAudio(_THIS); +static Uint8 *Core_GetAudioBuf(_THIS); +static void Core_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Core_OpenAudio; + this->WaitAudio = Core_WaitAudio; + this->PlayAudio = Core_PlayAudio; + this->GetAudioBuf = Core_GetAudioBuf; + this->CloseAudio = Core_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap COREAUDIO_bootstrap = { + "coreaudio", "Mac OS X CoreAudio", + Audio_Available, Audio_CreateDevice +}; + +/* The CoreAudio callback */ +static OSStatus audioCallback (void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + SDL_AudioDevice *this = (SDL_AudioDevice *)inRefCon; + UInt32 remaining, len; + AudioBuffer *abuf; + void *ptr; + UInt32 i; + + /* Only do anything if audio is enabled and not paused */ + if ( ! this->enabled || this->paused ) { + for (i = 0; i < ioData->mNumberBuffers; i++) { + abuf = &ioData->mBuffers[i]; + SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize); + } + return 0; + } + + /* No SDL conversion should be needed here, ever, since we accept + any input format in OpenAudio, and leave the conversion to CoreAudio. + */ + /* + assert(!this->convert.needed); + assert(this->spec.channels == ioData->mNumberChannels); + */ + + for (i = 0; i < ioData->mNumberBuffers; i++) { + abuf = &ioData->mBuffers[i]; + remaining = abuf->mDataByteSize; + ptr = abuf->mData; + while (remaining > 0) { + if (bufferOffset >= bufferSize) { + /* Generate the data */ + SDL_memset(buffer, this->spec.silence, bufferSize); + SDL_mutexP(this->mixer_lock); + (*this->spec.callback)(this->spec.userdata, + buffer, bufferSize); + SDL_mutexV(this->mixer_lock); + bufferOffset = 0; + } + + len = bufferSize - bufferOffset; + if (len > remaining) + len = remaining; + SDL_memcpy(ptr, (char *)buffer + bufferOffset, len); + ptr = (char *)ptr + len; + remaining -= len; + bufferOffset += len; + } + } + + return 0; +} + +/* Dummy functions -- we don't use thread-based audio */ +void Core_WaitAudio(_THIS) +{ + return; +} + +void Core_PlayAudio(_THIS) +{ + return; +} + +Uint8 *Core_GetAudioBuf(_THIS) +{ + return(NULL); +} + +void Core_CloseAudio(_THIS) +{ + OSStatus result; + struct AURenderCallbackStruct callback; + + /* stop processing the audio unit */ + result = AudioOutputUnitStop (outputAudioUnit); + if (result != noErr) { + SDL_SetError("Core_CloseAudio: AudioOutputUnitStop"); + return; + } + + /* Remove the input callback */ + callback.inputProc = 0; + callback.inputProcRefCon = 0; + result = AudioUnitSetProperty (outputAudioUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)); + if (result != noErr) { + SDL_SetError("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); + return; + } + + result = CloseComponent(outputAudioUnit); + if (result != noErr) { + SDL_SetError("Core_CloseAudio: CloseComponent"); + return; + } + + SDL_free(buffer); +} + +#define CHECK_RESULT(msg) \ + if (result != noErr) { \ + SDL_SetError("Failed to start CoreAudio: " msg); \ + return -1; \ + } + + +int Core_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + OSStatus result = noErr; + Component comp; + ComponentDescription desc; + struct AURenderCallbackStruct callback; + AudioStreamBasicDescription requestedDesc; + + /* Setup a AudioStreamBasicDescription with the requested format */ + requestedDesc.mFormatID = kAudioFormatLinearPCM; + requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; + requestedDesc.mChannelsPerFrame = spec->channels; + requestedDesc.mSampleRate = spec->freq; + + requestedDesc.mBitsPerChannel = spec->format & 0xFF; + if (spec->format & 0x8000) + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; + if (spec->format & 0x1000) + requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; + + requestedDesc.mFramesPerPacket = 1; + requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8; + requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket; + + + /* Locate the default output audio unit */ + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + comp = FindNextComponent (NULL, &desc); + if (comp == NULL) { + SDL_SetError ("Failed to start CoreAudio: FindNextComponent returned NULL"); + return -1; + } + + /* Open & initialize the default output audio unit */ + result = OpenAComponent (comp, &outputAudioUnit); + CHECK_RESULT("OpenAComponent") + + result = AudioUnitInitialize (outputAudioUnit); + CHECK_RESULT("AudioUnitInitialize") + + /* Set the input format of the audio unit. */ + result = AudioUnitSetProperty (outputAudioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &requestedDesc, + sizeof (requestedDesc)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)") + + /* Set the audio callback */ + callback.inputProc = audioCallback; + callback.inputProcRefCon = this; + result = AudioUnitSetProperty (outputAudioUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callback, + sizeof(callback)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)") + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + /* Allocate a sample buffer */ + bufferOffset = bufferSize = this->spec.size; + buffer = SDL_malloc(bufferSize); + + /* Finally, start processing of the audio unit */ + result = AudioOutputUnitStart (outputAudioUnit); + CHECK_RESULT("AudioOutputUnitStart") + + + /* We're running! */ + return(1); +} diff --git a/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.h b/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.h new file mode 100644 index 0000000..c11bc03 --- /dev/null +++ b/3rdparty/SDL/src/audio/macosx/SDL_coreaudio.h @@ -0,0 +1,45 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_coreaudio_h +#define _SDL_coreaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + AudioUnit outputAudioUnit; + void *buffer; + UInt32 bufferOffset; + UInt32 bufferSize; +}; + +/* Old variable names */ +#define outputAudioUnit (this->hidden->outputAudioUnit) +#define buffer (this->hidden->buffer) +#define bufferOffset (this->hidden->bufferOffset) +#define bufferSize (this->hidden->bufferSize) + +#endif /* _SDL_coreaudio_h */ diff --git a/3rdparty/SDL/src/audio/macrom/SDL_romaudio.c b/3rdparty/SDL/src/audio/macrom/SDL_romaudio.c new file mode 100644 index 0000000..1b3d49e --- /dev/null +++ b/3rdparty/SDL/src/audio/macrom/SDL_romaudio.c @@ -0,0 +1,496 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +# include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +# include <Carbon.h> +#else +# include <Sound.h> /* SoundManager interface */ +# include <Gestalt.h> +# include <DriverServices.h> +#endif + +#if !defined(NewSndCallBackUPP) && (UNIVERSAL_INTERFACES_VERSION < 0x0335) +#if !defined(NewSndCallBackProc) /* avoid circular redefinition... */ +#define NewSndCallBackUPP NewSndCallBackProc +#endif +#if !defined(NewSndCallBackUPP) +#define NewSndCallBackUPP NewSndCallBackProc +#endif +#endif + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" +#include "SDL_romaudio.h" + +/* Audio driver functions */ + +static void Mac_CloseAudio(_THIS); +static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mac_LockAudio(_THIS); +static void Mac_UnlockAudio(_THIS); + +/* Audio driver bootstrap functions */ + + +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mac_OpenAudio; + this->CloseAudio = Mac_CloseAudio; + this->LockAudio = Mac_LockAudio; + this->UnlockAudio = Mac_UnlockAudio; + this->free = Audio_DeleteDevice; + +#ifdef __MACOSX__ /* Mac OS X uses threaded audio, so normal thread code is okay */ + this->LockAudio = NULL; + this->UnlockAudio = NULL; +#endif + return this; +} + +AudioBootStrap SNDMGR_bootstrap = { + "sndmgr", "MacOS SoundManager 3.0", + Audio_Available, Audio_CreateDevice +}; + +#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) +/* This works correctly on Mac OS X */ + +#pragma options align=power + +static volatile SInt32 audio_is_locked = 0; +static volatile SInt32 need_to_mix = 0; + +static UInt8 *buffer[2]; +static volatile UInt32 running = 0; +static CmpSoundHeader header; +static volatile Uint32 fill_me = 0; + +static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer) +{ + if ( ! audio->paused ) { +#ifdef __MACOSX__ + SDL_mutexP(audio->mixer_lock); +#endif + if ( audio->convert.needed ) { + audio->spec.callback(audio->spec.userdata, + (Uint8 *)audio->convert.buf,audio->convert.len); + SDL_ConvertAudio(&audio->convert); + if ( audio->convert.len_cvt != audio->spec.size ) { + /* Uh oh... probably crashes here */; + } + SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt); + } else { + audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size); + } +#ifdef __MACOSX__ + SDL_mutexV(audio->mixer_lock); +#endif + } + + DecrementAtomic((SInt32 *) &need_to_mix); +} + +static void Mac_LockAudio(_THIS) +{ + IncrementAtomic((SInt32 *) &audio_is_locked); +} + +static void Mac_UnlockAudio(_THIS) +{ + SInt32 oldval; + + oldval = DecrementAtomic((SInt32 *) &audio_is_locked); + if ( oldval != 1 ) /* != 1 means audio is still locked. */ + return; + + /* Did we miss the chance to mix in an interrupt? Do it now. */ + if ( BitAndAtomic (0xFFFFFFFF, (UInt32 *) &need_to_mix) ) { + /* + * Note that this could be a problem if you missed an interrupt + * while the audio was locked, and get preempted by a second + * interrupt here, but that means you locked for way too long anyhow. + */ + mix_buffer (this, buffer[fill_me]); + } +} + +static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { + UInt32 play_me; + SndCommand cmd; + SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo; + + IncrementAtomic((SInt32 *) &need_to_mix); + + fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ + play_me = ! fill_me; /* filled buffer to play _now_ */ + + if ( ! audio->enabled ) { + return; + } + + /* queue previously mixed buffer for playback. */ + header.samplePtr = (Ptr)buffer[play_me]; + cmd.cmd = bufferCmd; + cmd.param1 = 0; + cmd.param2 = (long)&header; + SndDoCommand (chan, &cmd, 0); + + memset (buffer[fill_me], 0, audio->spec.size); + + /* + * if audio device isn't locked, mix the next buffer to be queued in + * the memory block that just finished playing. + */ + if ( ! BitAndAtomic(0xFFFFFFFF, (UInt32 *) &audio_is_locked) ) { + mix_buffer (audio, buffer[fill_me]); + } + + /* set this callback to run again when current buffer drains. */ + if ( running ) { + cmd.cmd = callBackCmd; + cmd.param1 = 0; + cmd.param2 = play_me; + + SndDoCommand (chan, &cmd, 0); + } +} + +static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { + + SndCallBackUPP callback; + int sample_bits; + int i; + long initOptions; + + /* Very few conversions are required, but... */ + switch (spec->format) { + case AUDIO_S8: + spec->format = AUDIO_U8; + break; + case AUDIO_U16LSB: + spec->format = AUDIO_S16LSB; + break; + case AUDIO_U16MSB: + spec->format = AUDIO_S16MSB; + break; + } + SDL_CalculateAudioSpec(spec); + + /* initialize bufferCmd header */ + memset (&header, 0, sizeof(header)); + callback = (SndCallBackUPP) NewSndCallBackUPP (callBackProc); + sample_bits = spec->size / spec->samples / spec->channels * 8; + +#ifdef DEBUG_AUDIO + fprintf(stderr, + "Audio format 0x%x, channels = %d, sample_bits = %d, frequency = %d\n", + spec->format, spec->channels, sample_bits, spec->freq); +#endif /* DEBUG_AUDIO */ + + header.numChannels = spec->channels; + header.sampleSize = sample_bits; + header.sampleRate = spec->freq << 16; + header.numFrames = spec->samples; + header.encode = cmpSH; + + /* Note that we install the 16bitLittleEndian Converter if needed. */ + if ( spec->format == 0x8010 ) { + header.compressionID = fixedCompression; + header.format = k16BitLittleEndianFormat; + } + + /* allocate 2 buffers */ + for (i=0; i<2; i++) { + buffer[i] = (UInt8*)malloc (sizeof(UInt8) * spec->size); + if (buffer[i] == NULL) { + SDL_OutOfMemory(); + return (-1); + } + memset (buffer[i], 0, spec->size); + } + + /* Create the sound manager channel */ + channel = (SndChannelPtr)SDL_malloc(sizeof(*channel)); + if ( channel == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + if ( spec->channels >= 2 ) { + initOptions = initStereo; + } else { + initOptions = initMono; + } + channel->userInfo = (long)this; + channel->qLength = 128; + if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) { + SDL_SetError("Unable to create audio channel"); + SDL_free(channel); + channel = NULL; + return(-1); + } + + /* start playback */ + { + SndCommand cmd; + cmd.cmd = callBackCmd; + cmd.param2 = 0; + running = 1; + SndDoCommand (channel, &cmd, 0); + } + + return 1; +} + +static void Mac_CloseAudio(_THIS) { + + int i; + + running = 0; + + if (channel) { + SndDisposeChannel (channel, true); + channel = NULL; + } + + for ( i=0; i<2; ++i ) { + if ( buffer[i] ) { + SDL_free(buffer[i]); + buffer[i] = NULL; + } + } +} + +#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */ + +static void Mac_LockAudio(_THIS) +{ + /* no-op. */ +} + +static void Mac_UnlockAudio(_THIS) +{ + /* no-op. */ +} + + +/* This function is called by Sound Manager when it has exhausted one of + the buffers, so we'll zero it to silence and fill it with audio if + we're not paused. +*/ +static pascal +void sndDoubleBackProc (SndChannelPtr chan, SndDoubleBufferPtr newbuf) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *)newbuf->dbUserInfo[0]; + + /* If audio is quitting, don't do anything */ + if ( ! audio->enabled ) { + return; + } + memset (newbuf->dbSoundData, 0, audio->spec.size); + newbuf->dbNumFrames = audio->spec.samples; + if ( ! audio->paused ) { + if ( audio->convert.needed ) { + audio->spec.callback(audio->spec.userdata, + (Uint8 *)audio->convert.buf,audio->convert.len); + SDL_ConvertAudio(&audio->convert); +#if 0 + if ( audio->convert.len_cvt != audio->spec.size ) { + /* Uh oh... probably crashes here */; + } +#endif + SDL_memcpy(newbuf->dbSoundData, audio->convert.buf, + audio->convert.len_cvt); + } else { + audio->spec.callback(audio->spec.userdata, + (Uint8 *)newbuf->dbSoundData, audio->spec.size); + } + } + newbuf->dbFlags |= dbBufferReady; +} + +static int DoubleBufferAudio_Available(void) +{ + int available; + NumVersion sndversion; + long response; + + available = 0; + sndversion = SndSoundManagerVersion(); + if ( sndversion.majorRev >= 3 ) { + if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { + if ( (response & (1 << gestaltSndPlayDoubleBuffer)) ) { + available = 1; + } + } + } else { + if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { + if ( (response & (1 << gestaltHasASC)) ) { + available = 1; + } + } + } + return(available); +} + +static void Mac_CloseAudio(_THIS) +{ + int i; + + if ( channel != NULL ) { + /* Clean up the audio channel */ + SndDisposeChannel(channel, true); + channel = NULL; + } + for ( i=0; i<2; ++i ) { + if ( audio_buf[i] ) { + SDL_free(audio_buf[i]); + audio_buf[i] = NULL; + } + } +} + +static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + SndDoubleBufferHeader2 audio_dbh; + int i; + long initOptions; + int sample_bits; + SndDoubleBackUPP doubleBackProc; + + /* Check to make sure double-buffered audio is available */ + if ( ! DoubleBufferAudio_Available() ) { + SDL_SetError("Sound manager doesn't support double-buffering"); + return(-1); + } + + /* Very few conversions are required, but... */ + switch (spec->format) { + case AUDIO_S8: + spec->format = AUDIO_U8; + break; + case AUDIO_U16LSB: + spec->format = AUDIO_S16LSB; + break; + case AUDIO_U16MSB: + spec->format = AUDIO_S16MSB; + break; + } + SDL_CalculateAudioSpec(spec); + + /* initialize the double-back header */ + SDL_memset(&audio_dbh, 0, sizeof(audio_dbh)); + doubleBackProc = NewSndDoubleBackProc (sndDoubleBackProc); + sample_bits = spec->size / spec->samples / spec->channels * 8; + + audio_dbh.dbhNumChannels = spec->channels; + audio_dbh.dbhSampleSize = sample_bits; + audio_dbh.dbhCompressionID = 0; + audio_dbh.dbhPacketSize = 0; + audio_dbh.dbhSampleRate = spec->freq << 16; + audio_dbh.dbhDoubleBack = doubleBackProc; + audio_dbh.dbhFormat = 0; + + /* Note that we install the 16bitLittleEndian Converter if needed. */ + if ( spec->format == 0x8010 ) { + audio_dbh.dbhCompressionID = fixedCompression; + audio_dbh.dbhFormat = k16BitLittleEndianFormat; + } + + /* allocate the 2 double-back buffers */ + for ( i=0; i<2; ++i ) { + audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer)+spec->size); + if ( audio_buf[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + audio_buf[i]->dbNumFrames = spec->samples; + audio_buf[i]->dbFlags = dbBufferReady; + audio_buf[i]->dbUserInfo[0] = (long)this; + audio_dbh.dbhBufferPtr[i] = audio_buf[i]; + } + + /* Create the sound manager channel */ + channel = (SndChannelPtr)SDL_malloc(sizeof(*channel)); + if ( channel == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + if ( spec->channels >= 2 ) { + initOptions = initStereo; + } else { + initOptions = initMono; + } + channel->userInfo = 0; + channel->qLength = 128; + if ( SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr ) { + SDL_SetError("Unable to create audio channel"); + SDL_free(channel); + channel = NULL; + return(-1); + } + + /* Start playback */ + if ( SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr)&audio_dbh) + != noErr ) { + SDL_SetError("Unable to play double buffered audio"); + return(-1); + } + + return 1; +} + +#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ + diff --git a/3rdparty/SDL/src/audio/macrom/SDL_romaudio.h b/3rdparty/SDL/src/audio/macrom/SDL_romaudio.h new file mode 100644 index 0000000..90e19c0 --- /dev/null +++ b/3rdparty/SDL/src/audio/macrom/SDL_romaudio.h @@ -0,0 +1,50 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_romaudio_h +#define _SDL_romaudio_h + +#include "../SDL_sysaudio.h" + +/* This is Ryan's improved MacOS sound code, with locking support */ +#define USE_RYANS_SOUNDCODE + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* Sound manager audio channel */ + SndChannelPtr channel; +#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) + /* FIXME: Add Ryan's static data here */ +#else + /* Double buffering variables */ + SndDoubleBufferPtr audio_buf[2]; +#endif +}; + +/* Old variable names */ +#define channel (this->hidden->channel) +#define audio_buf (this->hidden->audio_buf) + +#endif /* _SDL_romaudio_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio.c new file mode 100644 index 0000000..46ba690 --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Audio interrupt variables and callback function + + Patrice Mandin +*/ + +#include <unistd.h> + +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/mintbind.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_stfa.h" + +/* The audio device */ + +SDL_AudioDevice *SDL_MintAudio_device; +Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */ +unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */ +volatile unsigned short SDL_MintAudio_numbuf; /* Buffer to play */ +volatile unsigned short SDL_MintAudio_mutex; +volatile unsigned long SDL_MintAudio_clocktics; +cookie_stfa_t *SDL_MintAudio_stfa; +unsigned short SDL_MintAudio_hasfpu; + +/* MiNT thread variables */ +SDL_bool SDL_MintAudio_mint_present; +SDL_bool SDL_MintAudio_quit_thread; +SDL_bool SDL_MintAudio_thread_finished; +long SDL_MintAudio_thread_pid; + +/* The callback function, called by each driver whenever needed */ + +void SDL_MintAudio_Callback(void) +{ + Uint8 *buffer; + SDL_AudioDevice *audio = SDL_MintAudio_device; + + buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + SDL_memset(buffer, audio->spec.silence, audio->spec.size); + + if (audio->paused) + return; + + if (audio->convert.needed) { + int silence; + + if ( audio->convert.src_format == AUDIO_U8 ) { + silence = 0x80; + } else { + silence = 0; + } + SDL_memset(audio->convert.buf, silence, audio->convert.len); + audio->spec.callback(audio->spec.userdata, + (Uint8 *)audio->convert.buf,audio->convert.len); + SDL_ConvertAudio(&audio->convert); + SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt); + } else { + audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size); + } +} + +/* Add a new frequency/clock/predivisor to the current list */ +void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, + Uint32 prediv, int gpio_bits) +{ + int i, p; + + if (MINTAUDIO_freqcount==MINTAUDIO_maxfreqs) { + return; + } + + /* Search where to insert the frequency (highest first) */ + for (p=0; p<MINTAUDIO_freqcount; p++) { + if (frequency > MINTAUDIO_frequencies[p].frequency) { + break; + } + } + + /* Put all following ones farer */ + if (MINTAUDIO_freqcount>0) { + for (i=MINTAUDIO_freqcount; i>p; i--) { + SDL_memcpy(&MINTAUDIO_frequencies[i], &MINTAUDIO_frequencies[i-1], sizeof(mint_frequency_t)); + } + } + + /* And insert new one */ + MINTAUDIO_frequencies[p].frequency = frequency; + MINTAUDIO_frequencies[p].masterclock = clock; + MINTAUDIO_frequencies[p].predivisor = prediv; + MINTAUDIO_frequencies[p].gpio_bits = gpio_bits; + + MINTAUDIO_freqcount++; +} + +/* Search for the nearest frequency */ +int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq) +{ + int i; + + /* Only 1 freq ? */ + if (MINTAUDIO_freqcount==1) { + return 0; + } + + /* Check the array */ + for (i=0; i<MINTAUDIO_freqcount; i++) { + if (desired_freq >= ((MINTAUDIO_frequencies[i].frequency+ + MINTAUDIO_frequencies[i+1].frequency)>>1)) { + return i; + } + } + + /* Not in the array, give the latest */ + return MINTAUDIO_freqcount-1; +} + +/* Check if FPU is present */ +void SDL_MintAudio_CheckFpu(void) +{ + long cookie_fpu; + + SDL_MintAudio_hasfpu = 0; + if (Getcookie(C__FPU, &cookie_fpu) != C_FOUND) { + return; + } + switch ((cookie_fpu>>16)&0xfffe) { + case 2: + case 4: + case 6: + case 8: + case 16: + SDL_MintAudio_hasfpu = 1; + break; + } +} + +/* The thread function, used under MiNT with xbios */ +int SDL_MintAudio_Thread(long param) +{ + SndBufPtr pointers; + SDL_bool buffers_filled[2] = {SDL_FALSE, SDL_FALSE}; + + SDL_MintAudio_thread_finished = SDL_FALSE; + while (!SDL_MintAudio_quit_thread) { + if (Buffptr(&pointers)!=0) + continue; + + if (( (unsigned long)pointers.play>=(unsigned long)SDL_MintAudio_audiobuf[0]) + && ( (unsigned long)pointers.play<=(unsigned long)SDL_MintAudio_audiobuf[1])) + { + /* DMA is reading buffer #0, setup buffer #1 if not already done */ + if (!buffers_filled[1]) { + SDL_MintAudio_numbuf = 1; + SDL_MintAudio_Callback(); + Setbuffer(0, SDL_MintAudio_audiobuf[1], SDL_MintAudio_audiobuf[1] + SDL_MintAudio_audiosize); + buffers_filled[1]=SDL_TRUE; + buffers_filled[0]=SDL_FALSE; + } + } else { + /* DMA is reading buffer #1, setup buffer #0 if not already done */ + if (!buffers_filled[0]) { + SDL_MintAudio_numbuf = 0; + SDL_MintAudio_Callback(); + Setbuffer(0, SDL_MintAudio_audiobuf[0], SDL_MintAudio_audiobuf[0] + SDL_MintAudio_audiosize); + buffers_filled[0]=SDL_TRUE; + buffers_filled[1]=SDL_FALSE; + } + } + + usleep(100); + } + SDL_MintAudio_thread_finished = SDL_TRUE; + return 0; +} + +void SDL_MintAudio_WaitThread(void) +{ + if (!SDL_MintAudio_mint_present) + return; + + if (SDL_MintAudio_thread_finished) + return; + + SDL_MintAudio_quit_thread = SDL_TRUE; + while (!SDL_MintAudio_thread_finished) { + Syield(); + } +} diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio.h b/3rdparty/SDL/src/audio/mint/SDL_mintaudio.h new file mode 100644 index 0000000..ba6056e --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio.h @@ -0,0 +1,121 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + + Patrice Mandin +*/ + +#ifndef _SDL_mintaudio_h +#define _SDL_mintaudio_h + +#include "../SDL_sysaudio.h" +#include "SDL_mintaudio_stfa.h" + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *this + +/* 16 predivisors with 3 clocks max. */ +#define MINTAUDIO_maxfreqs (16*3) + +typedef struct { + Uint32 frequency; + Uint32 masterclock; + Uint32 predivisor; + int gpio_bits; /* in case of external clock */ +} mint_frequency_t; + +struct SDL_PrivateAudioData { + mint_frequency_t frequencies[MINTAUDIO_maxfreqs]; + int freq_count; /* Number of frequencies in the array */ + int numfreq; /* Number of selected frequency */ +}; + +/* Old variable names */ + +#define MINTAUDIO_frequencies (this->hidden->frequencies) +#define MINTAUDIO_freqcount (this->hidden->freq_count) +#define MINTAUDIO_numfreq (this->hidden->numfreq) + +/* _MCH cookie (values>>16) */ +enum { + MCH_ST=0, + MCH_STE, + MCH_TT, + MCH_F30, + MCH_CLONE, + MCH_ARANYM +}; + +/* Master clocks for replay frequencies */ +#define MASTERCLOCK_STE 8010666 /* Not sure of this one */ +#define MASTERCLOCK_TT 16107953 /* Not sure of this one */ +#define MASTERCLOCK_FALCON1 25175000 +#define MASTERCLOCK_FALCON2 32000000 /* Only usable for DSP56K */ +#define MASTERCLOCK_FALCONEXT -1 /* Clock on DSP56K port, unknown */ +#define MASTERCLOCK_44K 22579200 /* Standard clock for 44.1 Khz */ +#define MASTERCLOCK_48K 24576000 /* Standard clock for 48 Khz */ + +/* Master clock predivisors */ +#define MASTERPREDIV_STE 160 +#define MASTERPREDIV_TT 320 +#define MASTERPREDIV_FALCON 256 +#define MASTERPREDIV_MILAN 256 + +/* Variables */ +extern SDL_AudioDevice *SDL_MintAudio_device; +extern Uint8 *SDL_MintAudio_audiobuf[2]; /* Pointers to buffers */ +extern unsigned long SDL_MintAudio_audiosize; /* Length of audio buffer=spec->size */ +extern volatile unsigned short SDL_MintAudio_numbuf; /* Buffer to play */ +extern volatile unsigned short SDL_MintAudio_mutex; +extern cookie_stfa_t *SDL_MintAudio_stfa; +extern volatile unsigned long SDL_MintAudio_clocktics; +extern unsigned short SDL_MintAudio_hasfpu; /* To preserve fpu registers if needed */ + +/* MiNT thread variables */ +extern SDL_bool SDL_MintAudio_mint_present; +extern SDL_bool SDL_MintAudio_quit_thread; +extern SDL_bool SDL_MintAudio_thread_finished; +extern long SDL_MintAudio_thread_pid; + +/* Functions */ +void SDL_MintAudio_Callback(void); +void SDL_MintAudio_AddFrequency(_THIS, Uint32 frequency, Uint32 clock, + Uint32 prediv, int gpio_bits); +int SDL_MintAudio_SearchFrequency(_THIS, int desired_freq); +void SDL_MintAudio_CheckFpu(void); + +/* MiNT thread functions */ +int SDL_MintAudio_Thread(long param); +void SDL_MintAudio_WaitThread(void); + +/* ASM interrupt functions */ +void SDL_MintAudio_GsxbInterrupt(void); +void SDL_MintAudio_EmptyGsxbInterrupt(void); +void SDL_MintAudio_XbiosInterruptMeasureClock(void); +void SDL_MintAudio_XbiosInterrupt(void); +void SDL_MintAudio_Dma8Interrupt(void); +void SDL_MintAudio_StfaInterrupt(void); + +#endif /* _SDL_mintaudio_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.c new file mode 100644 index 0000000..61feba3 --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.c @@ -0,0 +1,357 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + using DMA 8bits (hardware access) + + Patrice Mandin +*/ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" + +#include "../../video/ataricommon/SDL_atarimxalloc_c.h" + +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_dma8.h" + +/*--- Defines ---*/ + +#define MINT_AUDIO_DRIVER_NAME "mint_dma8" + +/* Debug print info */ +#define DEBUG_NAME "audio:dma8: " +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#else +#define DEBUG_PRINT(what) +#endif + +/*--- Static variables ---*/ + +static long cookie_snd, cookie_mch; + +/*--- Audio driver functions ---*/ + +static void Mint_CloseAudio(_THIS); +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_LockAudio(_THIS); +static void Mint_UnlockAudio(_THIS); + +/* To check/init hardware audio */ +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); + +/* Functions called in supervisor mode */ +static void Mint_InitDma(void); +static void Mint_StopReplay(void); +static void Mint_StartReplay(void); + +/*--- Audio driver bootstrap functions ---*/ + +static int Audio_Available(void) +{ + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + + /* Check if user asked a different audio driver */ + if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { + DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); + return 0; + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 8 bits audio */ + if ((cookie_snd & SND_8BIT)==0) { + DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n")); + return(0); + } + + /* Check if audio is lockable */ + if (cookie_snd & SND_16BIT) { + if (Locksnd()!=1) { + DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); + return(0); + } + + Unlocksnd(); + } + + DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n")); + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mint_OpenAudio; + this->CloseAudio = Mint_CloseAudio; + this->LockAudio = Mint_LockAudio; + this->UnlockAudio = Mint_UnlockAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MINTAUDIO_DMA8_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", + Audio_Available, Audio_CreateDevice +}; + +static void Mint_LockAudio(_THIS) +{ + Supexec(Mint_StopReplay); +} + +static void Mint_UnlockAudio(_THIS) +{ + Supexec(Mint_StartReplay); +} + +static void Mint_CloseAudio(_THIS) +{ + Supexec(Mint_StopReplay); + + DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n")); + + /* Disable interrupt */ + Jdisint(MFP_DMASOUND); + + DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n")); + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) { + } + + DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n")); + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } + + DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n")); +} + +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) +{ + int i, masterprediv, sfreq; + unsigned long masterclock; + + DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + if (spec->channels > 2) + spec->channels = 2; + + /* Check formats available */ + spec->format = AUDIO_S8; + + /* Calculate and select the closest frequency */ + sfreq=0; + masterclock=MASTERCLOCK_STE; + masterprediv=MASTERPREDIV_STE; + switch(cookie_mch>>16) { +/* + case MCH_STE: + masterclock=MASTERCLOCK_STE; + masterprediv=MASTERPREDIV_STE; + break; +*/ + case MCH_TT: + masterclock=MASTERCLOCK_TT; + masterprediv=MASTERPREDIV_TT; + break; + case MCH_F30: + case MCH_ARANYM: + masterclock=MASTERCLOCK_FALCON1; + masterprediv=MASTERPREDIV_FALCON; + sfreq=1; + break; + } + + MINTAUDIO_freqcount=0; + for (i=sfreq;i<4;i++) { + SDL_MintAudio_AddFrequency(this, masterclock/(masterprediv*(1<<i)), + masterclock, i-sfreq, -1); + } + +#if 1 + for (i=0; i<MINTAUDIO_freqcount; i++) { + DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", + i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, + MINTAUDIO_frequencies[i].predivisor + )); + } +#endif + + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + + DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + return 0; +} + +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + SDL_MintAudio_device = this; + + /* Check audio capabilities */ + if (Mint_CheckAudio(this, spec)==-1) { + return -1; + } + + SDL_CalculateAudioSpec(spec); + + /* Allocate memory for audio buffers in DMA-able RAM */ + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM); + if (SDL_MintAudio_audiobuf[0]==NULL) { + SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); + return (-1); + } + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ; + SDL_MintAudio_numbuf=0; + SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2); + SDL_MintAudio_audiosize = spec->size; + SDL_MintAudio_mutex = 0; + + DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0])); + DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1])); + + SDL_MintAudio_CheckFpu(); + + /* Set replay tracks */ + if (cookie_snd & SND_16BIT) { + Settracks(0,0); + Setmontracks(0); + } + + Supexec(Mint_InitDma); + + /* Set interrupt */ + Jdisint(MFP_DMASOUND); + Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt); + Jenabint(MFP_DMASOUND); + + if (cookie_snd & SND_16BIT) { + if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) { + DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n")); + } + } + + Supexec(Mint_StartReplay); + + return(1); /* We don't use threaded audio */ +} + +/* Functions called in supervisor mode */ + +static void Mint_InitDma(void) +{ + unsigned long buffer; + unsigned char mode; + SDL_AudioDevice *this = SDL_MintAudio_device; + + Mint_StopReplay(); + + /* Set buffer */ + buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + DMAAUDIO_IO.start_high = (buffer>>16) & 255; + DMAAUDIO_IO.start_mid = (buffer>>8) & 255; + DMAAUDIO_IO.start_low = buffer & 255; + + buffer += SDL_MintAudio_audiosize; + DMAAUDIO_IO.end_high = (buffer>>16) & 255; + DMAAUDIO_IO.end_mid = (buffer>>8) & 255; + DMAAUDIO_IO.end_low = buffer & 255; + + mode = 3-MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + if (this->spec.channels==1) { + mode |= 1<<7; + } + DMAAUDIO_IO.sound_ctrl = mode; +} + +static void Mint_StopReplay(void) +{ + /* Stop replay */ + DMAAUDIO_IO.control=0; +} + +static void Mint_StartReplay(void) +{ + /* Start replay */ + DMAAUDIO_IO.control=3; +} diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.h b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.h new file mode 100644 index 0000000..a52e5db --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_dma8.h @@ -0,0 +1,85 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + DMA 8bits and Falcon Codec audio definitions + + Patrice Mandin, Didier Mquignon +*/ + +#ifndef _SDL_mintaudio_dma8_h +#define _SDL_mintaudio_dma8_h + +#define DMAAUDIO_IO_BASE (0xffff8900) +struct DMAAUDIO_IO_S { + unsigned char int_ctrl; + unsigned char control; + + unsigned char dummy1; + unsigned char start_high; + unsigned char dummy2; + unsigned char start_mid; + unsigned char dummy3; + unsigned char start_low; + + unsigned char dummy4; + unsigned char cur_high; + unsigned char dummy5; + unsigned char cur_mid; + unsigned char dummy6; + unsigned char cur_low; + + unsigned char dummy7; + unsigned char end_high; + unsigned char dummy8; + unsigned char end_mid; + unsigned char dummy9; + unsigned char end_low; + + unsigned char dummy10[12]; + + unsigned char track_ctrl; /* CODEC only */ + unsigned char sound_ctrl; + unsigned short sound_data; + unsigned short sound_mask; + + unsigned char dummy11[10]; + + unsigned short dev_ctrl; + unsigned short dest_ctrl; + unsigned short sync_div; + unsigned char track_rec; + unsigned char adderin_input; + unsigned char channel_input; + unsigned char channel_amplification; + unsigned char channel_reduction; + + unsigned char dummy12[6]; + + unsigned char data_direction; + unsigned char dummy13; + unsigned char dev_data; +}; +#define DMAAUDIO_IO ((*(volatile struct DMAAUDIO_IO_S *)DMAAUDIO_IO_BASE)) + +#endif /* _SDL_mintaudio_dma8_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.c new file mode 100644 index 0000000..8d7716a --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.c @@ -0,0 +1,436 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + using XBIOS functions (GSXB compatible driver) + + Patrice Mandin +*/ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" + +#include "../../video/ataricommon/SDL_atarimxalloc_c.h" + +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_gsxb.h" + +/*--- Defines ---*/ + +#define MINT_AUDIO_DRIVER_NAME "mint_gsxb" + +/* Debug print info */ +#define DEBUG_NAME "audio:gsxb: " +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#else +#define DEBUG_PRINT(what) +#endif + +/*--- Static variables ---*/ + +static long cookie_snd, cookie_gsxb; + +/*--- Audio driver functions ---*/ + +static void Mint_CloseAudio(_THIS); +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_LockAudio(_THIS); +static void Mint_UnlockAudio(_THIS); + +/* To check/init hardware audio */ +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec); + +/* GSXB callbacks */ +static void Mint_GsxbInterrupt(void); +static void Mint_GsxbNullInterrupt(void); + +/*--- Audio driver bootstrap functions ---*/ + +static int Audio_Available(void) +{ + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + + /* Check if user asked a different audio driver */ + if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { + DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); + return(0); + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT)==0) { + DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); + return(0); + } + + /* Cookie GSXB present ? */ + cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND); + + /* Is it GSXB ? */ + if (((cookie_snd & SND_GSXB)==0) || (cookie_gsxb==0)) { + DEBUG_PRINT((DEBUG_NAME "no GSXB audio\n")); + return(0); + } + + /* Check if audio is lockable */ + if (Locksnd()!=1) { + DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); + return(0); + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n")); + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mint_OpenAudio; + this->CloseAudio = Mint_CloseAudio; + this->LockAudio = Mint_LockAudio; + this->UnlockAudio = Mint_UnlockAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MINTAUDIO_GSXB_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver", + Audio_Available, Audio_CreateDevice +}; + +static void Mint_LockAudio(_THIS) +{ + /* Stop replay */ + Buffoper(0); +} + +static void Mint_UnlockAudio(_THIS) +{ + /* Restart replay */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); +} + +static void Mint_CloseAudio(_THIS) +{ + /* Stop replay */ + Buffoper(0); + + /* Uninstall interrupt */ + if (NSetinterrupt(2, SI_NONE, Mint_GsxbNullInterrupt)<0) { + DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n")); + } + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) { + } + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } + + /* Unlock sound system */ + Unlocksnd(); +} + +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) +{ + long snd_format = 0; + int i, resolution, format_signed, format_bigendian; + Uint16 test_format = SDL_FirstAudioFormat(spec->format); + int valid_datatype = 0; + + resolution = spec->format & 0x00ff; + format_signed = ((spec->format & 0x8000)!=0); + format_bigendian = ((spec->format & 0x1000)!=0); + + DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + if (spec->channels > 2) { + spec->channels = 2; /* no more than stereo! */ + } + + while ((!valid_datatype) && (test_format)) { + /* Check formats available */ + snd_format = Sndstatus(SND_QUERYFORMATS); + spec->format = test_format; + resolution = spec->format & 0xff; + format_signed = (spec->format & (1<<15)); + format_bigendian = (spec->format & (1<<12)); + switch (test_format) { + case AUDIO_U8: + case AUDIO_S8: + if (snd_format & SND_FORMAT8) { + valid_datatype = 1; + snd_format = Sndstatus(SND_QUERY8BIT); + } + break; + + case AUDIO_U16LSB: + case AUDIO_S16LSB: + case AUDIO_U16MSB: + case AUDIO_S16MSB: + if (snd_format & SND_FORMAT16) { + valid_datatype = 1; + snd_format = Sndstatus(SND_QUERY16BIT); + } + break; + + default: + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { + SDL_SetError("Unsupported audio format"); + return (-1); + } + + /* Check signed/unsigned format */ + if (format_signed) { + if (snd_format & SND_FORMATSIGNED) { + /* Ok */ + } else if (snd_format & SND_FORMATUNSIGNED) { + /* Give unsigned format */ + spec->format = spec->format & (~0x8000); + } + } else { + if (snd_format & SND_FORMATUNSIGNED) { + /* Ok */ + } else if (snd_format & SND_FORMATSIGNED) { + /* Give signed format */ + spec->format |= 0x8000; + } + } + + if (format_bigendian) { + if (snd_format & SND_FORMATBIGENDIAN) { + /* Ok */ + } else if (snd_format & SND_FORMATLITTLEENDIAN) { + /* Give little endian format */ + spec->format = spec->format & (~0x1000); + } + } else { + if (snd_format & SND_FORMATLITTLEENDIAN) { + /* Ok */ + } else if (snd_format & SND_FORMATBIGENDIAN) { + /* Give big endian format */ + spec->format |= 0x1000; + } + } + + /* Calculate and select the closest frequency */ + MINTAUDIO_freqcount=0; + for (i=1;i<4;i++) { + SDL_MintAudio_AddFrequency(this, + MASTERCLOCK_44K/(MASTERPREDIV_MILAN*(1<<i)), MASTERCLOCK_44K, + (1<<i)-1, -1); + } + +#if 1 + for (i=0; i<MINTAUDIO_freqcount; i++) { + DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", + i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, + MINTAUDIO_frequencies[i].predivisor + )); + } +#endif + + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + + DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + return 0; +} + +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) +{ + int channels_mode, prediv; + void *buffer; + + /* Stop currently playing sound */ + Buffoper(0); + + /* Set replay tracks */ + Settracks(0,0); + Setmontracks(0); + + /* Select replay format */ + switch (spec->format & 0xff) { + case 8: + if (spec->channels==2) { + channels_mode=STEREO8; + } else { + channels_mode=MONO8; + } + break; + case 16: + if (spec->channels==2) { + channels_mode=STEREO16; + } else { + channels_mode=MONO16; + } + break; + default: + channels_mode=STEREO16; + break; + } + if (Setmode(channels_mode)<0) { + DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); + } + + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + Devconnect(DMAPLAY, DAC, CLKEXT, prediv, 1); + + /* Set buffer */ + buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + if (Setbuffer(0, buffer, buffer + spec->size)<0) { + DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); + } + + /* Install interrupt */ + if (NSetinterrupt(2, SI_PLAY, Mint_GsxbInterrupt)<0) { + DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n")); + } + + /* Go */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); + DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); +} + +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + /* Lock sound system */ + if (Locksnd()!=1) { + SDL_SetError("Mint_OpenAudio: Audio system already in use"); + return(-1); + } + + SDL_MintAudio_device = this; + + /* Check audio capabilities */ + if (Mint_CheckAudio(this, spec)==-1) { + return -1; + } + + SDL_CalculateAudioSpec(spec); + + /* Allocate memory for audio buffers in DMA-able RAM */ + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM); + if (SDL_MintAudio_audiobuf[0]==NULL) { + SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); + return (-1); + } + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ; + SDL_MintAudio_numbuf=0; + SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2); + SDL_MintAudio_audiosize = spec->size; + SDL_MintAudio_mutex = 0; + + DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0])); + DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1])); + + SDL_MintAudio_CheckFpu(); + + /* Setup audio hardware */ + Mint_InitAudio(this, spec); + + return(1); /* We don't use threaded audio */ +} + +static void Mint_GsxbInterrupt(void) +{ + Uint8 *newbuf; + + if (SDL_MintAudio_mutex) + return; + + SDL_MintAudio_mutex=1; + + SDL_MintAudio_numbuf ^= 1; + SDL_MintAudio_Callback(); + newbuf = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + Setbuffer(0, newbuf, newbuf + SDL_MintAudio_audiosize); + + SDL_MintAudio_mutex=0; +} + +static void Mint_GsxbNullInterrupt(void) +{ +} diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.h b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.h new file mode 100644 index 0000000..aee26b7 --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_gsxb.h @@ -0,0 +1,104 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GSXB audio definitions + * + * Patrice Mandin + */ + +#ifndef _SDL_mintaudio_gsxb_h +#define _SDL_mintaudio_gsxb_h + +#include <mint/falcon.h> /* for trap_14_xxx macros */ + +/* Bit 5 in cookie _SND */ + +#define SND_GSXB (1<<5) + +/* NSoundcmd modes */ + +#define SETRATE 7 /* Set sample rate */ +#define SET8BITFORMAT 8 /* 8 bits format */ +#define SET16BITFORMAT 9 /* 16 bits format */ +#define SET24BITFORMAT 10 /* 24 bits format */ +#define SET32BITFORMAT 11 /* 32 bits format */ +#define LTATTEN_MASTER 12 /* Attenuation */ +#define RTATTEN_MASTER 13 +#define LTATTEN_MICIN 14 +#define RTATTEN_MICIN 15 +#define LTATTEN_FMGEN 16 +#define RTATTEN_FMGEN 17 +#define LTATTEN_LINEIN 18 +#define RTATTEN_LINEIN 19 +#define LTATTEN_CDIN 20 +#define RTATTEN_CDIN 21 +#define LTATTEN_VIDIN 22 +#define RTATTEN_VIDIN 23 +#define LTATTEN_AUXIN 24 +#define RTATTEN_AUXIN 25 + +/* Setmode modes */ + +#define MONO16 3 +#define STEREO24 4 +#define STEREO32 5 +#define MONO24 6 +#define MONO32 7 + +/* Sndstatus modes */ + +#define SND_QUERYFORMATS 2 +#define SND_QUERYMIXERS 3 +#define SND_QUERYSOURCES 4 +#define SND_QUERYDUPLEX 5 +#define SND_QUERY8BIT 8 +#define SND_QUERY16BIT 9 +#define SND_QUERY24BIT 10 +#define SND_QUERY32BIT 11 + +#define SND_FORMAT8 (1<<0) +#define SND_FORMAT16 (1<<1) +#define SND_FORMAT24 (1<<2) +#define SND_FORMAT32 (1<<3) + +#define SND_FORMATSIGNED (1<<0) +#define SND_FORMATUNSIGNED (1<<1) +#define SND_FORMATBIGENDIAN (1<<2) +#define SND_FORMATLITTLEENDIAN (1<<3) + +/* Devconnect prescalers */ + +#define CLK_44K 1 +#define CLK_22K 3 +#define CLK_11K 7 + +/* Extra xbios functions */ + +#define NSoundcmd(mode,data,data2) \ + (long)trap_14_wwl((short)130,(short)(mode),(short)(data),(long)(data2)) +#define NSetinterrupt(src_inter,cause,inth_addr) \ + (long)trap_14_wwwl((short)135,(short)(src_inter),(short)(cause), \ + (long)(inth_addr)) + +#endif /* _SDL_mintaudio_gsxb_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_it.S b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_it.S new file mode 100644 index 0000000..a2ecac4 --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_it.S @@ -0,0 +1,386 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + Audio interrupts + + Patrice Mandin, Didier Mquignon + */ + + .text + + .globl _SDL_MintAudio_Callback + + .globl _SDL_MintAudio_XbiosInterrupt + .globl _SDL_MintAudio_XbiosInterruptMeasureClock + .globl _SDL_MintAudio_Dma8Interrupt + .globl _SDL_MintAudio_StfaInterrupt + + .globl _SDL_MintAudio_mutex + .globl _SDL_MintAudio_audiobuf + .globl _SDL_MintAudio_numbuf + .globl _SDL_MintAudio_audiosize + .globl _SDL_MintAudio_clocktics + .globl _SDL_MintAudio_hasfpu + + .globl _SDL_MintAudio_stfa + +/* + How it works: + - Audio is playing buffer #0 (resp. #1) + - We must calculate a sample in buffer #1 (resp. #0) + so we first call the callback to do it + - Then we swap the buffers +*/ + +#define savptr 0x4a2 +#define savamt 0x46 + +/*--- Save/restore FPU context ---*/ + +#if defined(__mcoldfire__) + +#define SAVE_FPU_CONTEXT \ + lea sp@(-216),sp; \ + fsave sp@; \ + fmovel fpiar,sp@-; \ + lea sp@(-64),sp; \ + fmovemd fp0-fp7,sp@ + +#define RESTORE_FPU_CONTEXT \ + fmovemd sp@,fp0-fp7; \ + lea sp@(64),sp; \ + fmovel sp@+,fpiar; \ + frestore sp@; \ + lea sp@(216),sp + +#else + +#define SAVE_FPU_CONTEXT \ + .chip 68k/68881; \ + fsave sp@-; \ + fmoveml fpcr/fpsr/fpiar,sp@-; \ + fmovemx fp0-fp7,sp@-; \ + .chip 68k + +#define RESTORE_FPU_CONTEXT \ + .chip 68k/68881; \ + fmovemx sp@+,fp0-fp7; \ + fmoveml sp@+,fpcr/fpsr/fpiar; \ + frestore sp@+; \ + .chip 68k + +#endif + +/*--- Xbios interrupt vector to measure Falcon external clock ---*/ + +_SDL_MintAudio_XbiosInterruptMeasureClock: /* 1 mS */ +#if defined(__mcoldfire__) + movel d0,sp@- + + moveql #0,d0 + btst d0,0xFFFF8901:w /* state DMA sound */ +#else + btst #0,0xFFFF8901:w /* state DMA sound */ +#endif + beqs SDL_MintAudio_EndIntMeasure + addql #1,_SDL_MintAudio_clocktics +SDL_MintAudio_EndIntMeasure: +#if defined(__mcoldfire__) + moveql #5,d0 + bclr d0,0xFFFFFA0F:w /* Clear service bit */ + + movel sp@+,d0 +#else + bclr #5,0xFFFFFA0F:w /* Clear service bit */ +#endif + rte + +/*--- Xbios interrupt vector ---*/ + +_SDL_MintAudio_XbiosInterrupt: +#if defined(__mcoldfire__) + lea sp@(-60),sp + moveml d0-d7/a0-a6,sp@ +#else + moveml d0-d7/a0-a6,sp@- +#endif + + /* Reenable interrupts, so other interrupts can work */ + movew #0x2300,sr + + /* Clear service bit, so other MFP interrupts can work */ +#if defined(__mcoldfire__) + moveql #5,d0 + bclr d0,0xfffffa0f:w +#else + bclr #5,0xfffffa0f:w +#endif + + /* Check if we are not already running */ + tstw _SDL_MintAudio_mutex + bne SDL_MintAudio_XbiosEnd + +#if defined(__mcoldfire__) + movew _SDL_MintAudio_mutex,d0 + notl d0 + movew d0,_SDL_MintAudio_mutex + + movew _SDL_MintAudio_numbuf,d1 + eorl #1,d1 + movew d1,_SDL_MintAudio_numbuf +#else + notw _SDL_MintAudio_mutex + + /* Swap buffers */ + eorw #1,_SDL_MintAudio_numbuf +#endif + + /* Save FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Xbios_nofpu1 + SAVE_FPU_CONTEXT +SDL_MintAudio_Xbios_nofpu1: + + /* Callback */ + jsr _SDL_MintAudio_Callback + + /* Restore FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Xbios_nofpu2 + RESTORE_FPU_CONTEXT +SDL_MintAudio_Xbios_nofpu2: + + /* Reserve space for registers */ +#if defined(__mcoldfire__) + movel #savamt,d0 + subl d0,savptr +#else + subl #savamt,savptr +#endif + + /* Set new buffer */ + + moveq #0,d0 + movel _SDL_MintAudio_audiosize,d1 + + movew _SDL_MintAudio_numbuf,d0 + lsll #2,d0 + lea _SDL_MintAudio_audiobuf,a0 + movel a0@(d0:l),a1 + + lea a1@(d1:l),a2 + + movel a2,sp@- + movel a1,sp@- + clrw sp@- + movew #131,sp@- + trap #14 + lea sp@(12),sp + + /* Restore registers space */ +#if defined(__mcoldfire__) + movel #savamt,d0 + addl d0,savptr +#else + addl #savamt,savptr +#endif + + clrw _SDL_MintAudio_mutex +SDL_MintAudio_XbiosEnd: +#if defined(__mcoldfire__) + moveml sp@,d0-d7/a0-a6 + lea sp@(60),sp +#else + moveml sp@+,d0-d7/a0-a6 +#endif + rte + +/*--- DMA 8 bits interrupt vector ---*/ + +_SDL_MintAudio_Dma8Interrupt: +#if defined(__mcoldfire__) + lea sp@(-16),sp + moveml d0-d1/a0-a1,sp@ +#else + moveml d0-d1/a0-a1,sp@- +#endif + + /* Reenable interrupts, so other interrupts can work */ + movew #0x2300,sr + + /* Clear service bit, so other MFP interrupts can work */ +#if defined(__mcoldfire__) + moveql #5,d0 + bclr d0,0xfffffa0f:w +#else + bclr #5,0xfffffa0f:w +#endif + /* Check if we are not already running */ + tstw _SDL_MintAudio_mutex + bne SDL_MintAudio_Dma8End + +#if defined(__mcoldfire__) + movew _SDL_MintAudio_mutex,d0 + notl d0 + movew d0,_SDL_MintAudio_mutex + + movew _SDL_MintAudio_numbuf,d1 + eorl #1,d1 + movew d1,_SDL_MintAudio_numbuf +#else + notw _SDL_MintAudio_mutex + + /* Swap buffers */ + eorw #1,_SDL_MintAudio_numbuf +#endif + + /* Save FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Dma8_nofpu1 + SAVE_FPU_CONTEXT +SDL_MintAudio_Dma8_nofpu1: + + /* Callback */ + jsr _SDL_MintAudio_Callback + + /* Restore FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Dma8_nofpu2 + RESTORE_FPU_CONTEXT +SDL_MintAudio_Dma8_nofpu2: + + /* Set new buffer */ + + moveq #0,d0 + + movew _SDL_MintAudio_numbuf,d0 + lsll #2,d0 + lea _SDL_MintAudio_audiobuf,a0 + movel a0@(d0:l),d1 + + /* Modify DMA addresses */ + lea 0xffff8900:w,a0 + + movel d1,d0 + + moveb d0,a0@(0x07) /* Start address */ + lsrl #8,d0 + moveb d0,a0@(0x05) + lsrl #8,d0 + moveb d0,a0@(0x03) + + addl _SDL_MintAudio_audiosize,d1 + + movel d1,d0 + + moveb d0,a0@(0x13) /* End address */ + lsrl #8,d0 + moveb d0,a0@(0x11) + lsrl #8,d0 + moveb d0,a0@(0x0f) + + clrw _SDL_MintAudio_mutex +SDL_MintAudio_Dma8End: +#if defined(__mcoldfire__) + moveml sp@,d0-d1/a0-a1 + lea sp@(16),sp +#else + moveml sp@+,d0-d1/a0-a1 +#endif + rte + +/*--- STFA interrupt vector ---*/ + +STFA_SOUND_START = 6 +STFA_SOUND_END = STFA_SOUND_START+8 + +_SDL_MintAudio_StfaInterrupt: + /* Reenable interrupts, so other interrupts can work */ + movew #0x2300,sr + + /* Check if we are not already running */ + tstw _SDL_MintAudio_mutex + +#if defined(__mcoldfire__) + bne SDL_MintAudio_StfaEnd + + lea sp@(-60),sp + moveml d0-d7/a0-a6,sp@ + + movew _SDL_MintAudio_mutex,d0 + notl d0 + movew d0,_SDL_MintAudio_mutex + + movew _SDL_MintAudio_numbuf,d1 + eorl #1,d1 + movew d1,_SDL_MintAudio_numbuf +#else + bnes SDL_MintAudio_StfaEnd + + moveml d0-d7/a0-a6,sp@- + + notw _SDL_MintAudio_mutex + + /* Swap buffers */ + eorw #1,_SDL_MintAudio_numbuf +#endif + + /* Save FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Stfa_nofpu1 + SAVE_FPU_CONTEXT +SDL_MintAudio_Stfa_nofpu1: + + /* Callback */ + jsr _SDL_MintAudio_Callback + + /* Restore FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_MintAudio_Stfa_nofpu2 + RESTORE_FPU_CONTEXT +SDL_MintAudio_Stfa_nofpu2: + + /* Set new buffer */ + + moveq #0,d0 + movel _SDL_MintAudio_stfa,a1 + + movew _SDL_MintAudio_numbuf,d0 + lsll #2,d0 + lea _SDL_MintAudio_audiobuf,a0 + movel a0@(d0:l),d1 + + /* Modify STFA replay buffers */ + movel d1,a1@(STFA_SOUND_START) + addl _SDL_MintAudio_audiosize,d1 + movel d1,a1@(STFA_SOUND_END) + +#if defined(__mcoldfire__) + moveml sp@,d0-d7/a0-a6 + lea sp@(60),sp +#else + moveml sp@+,d0-d7/a0-a6 +#endif + clrw _SDL_MintAudio_mutex +SDL_MintAudio_StfaEnd: + rte diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.c new file mode 100644 index 0000000..387609b --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.c @@ -0,0 +1,405 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + using XBIOS functions (MacSound compatible driver) + + Patrice Mandin +*/ + +#include <support.h> + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" + +#include "../../video/ataricommon/SDL_atarimxalloc_c.h" + +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_mcsn.h" + +/*--- Defines ---*/ + +#define MINT_AUDIO_DRIVER_NAME "mint_mcsn" + +/* Debug print info */ +#define DEBUG_NAME "audio:mcsn: " +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#else +#define DEBUG_PRINT(what) +#endif + +/*--- Static variables ---*/ + +static long cookie_snd, cookie_mch; +static cookie_mcsn_t *cookie_mcsn; + +/*--- Audio driver functions ---*/ + +static void Mint_CloseAudio(_THIS); +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_LockAudio(_THIS); +static void Mint_UnlockAudio(_THIS); + +/* To check/init hardware audio */ +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec); + +/*--- Audio driver bootstrap functions ---*/ + +static int Audio_Available(void) +{ + long dummy; + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + + SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); + + /* We can't use XBIOS in interrupt with Magic, don't know about thread */ + if (Getcookie(C_MagX, &dummy) == C_FOUND) { + return(0); + } + + /* Check if user asked a different audio driver */ + if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { + DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); + return(0); + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT)==0) { + DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); + return(0); + } + + /* Cookie MCSN present ? */ + if (Getcookie(C_McSn, &dummy) != C_FOUND) { + DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n")); + return(0); + } + cookie_mcsn = (cookie_mcsn_t *) dummy; + + /* Check if interrupt at end of replay */ + if (cookie_mcsn->pint == 0) { + DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n")); + return(0); + } + + /* Check if audio is lockable */ + if (Locksnd()!=1) { + DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); + return(0); + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n")); + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mint_OpenAudio; + this->CloseAudio = Mint_CloseAudio; + this->LockAudio = Mint_LockAudio; + this->UnlockAudio = Mint_UnlockAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MINTAUDIO_MCSN_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver", + Audio_Available, Audio_CreateDevice +}; + +static void Mint_LockAudio(_THIS) +{ + /* Stop replay */ + Buffoper(0); +} + +static void Mint_UnlockAudio(_THIS) +{ + /* Restart replay */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); +} + +static void Mint_CloseAudio(_THIS) +{ + /* Stop replay */ + SDL_MintAudio_WaitThread(); + Buffoper(0); + + if (!SDL_MintAudio_mint_present) { + /* Uninstall interrupt */ + Jdisint(MFP_DMASOUND); + } + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) { + } + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } + + /* Unlock sound system */ + Unlocksnd(); +} + +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) +{ + int i; + unsigned long masterclock, masterprediv; + + DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + if (spec->channels > 2) { + spec->channels = 2; /* no more than stereo! */ + } + + /* Check formats available */ + MINTAUDIO_freqcount=0; + switch(cookie_mcsn->play) { + case MCSN_ST: + spec->channels=1; + spec->format=8; /* FIXME: is it signed or unsigned ? */ + SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1); + break; + case MCSN_TT: /* Also STE, Mega STE */ + spec->format=AUDIO_S8; + masterclock=MASTERCLOCK_STE; + masterprediv=MASTERPREDIV_STE; + if ((cookie_mch>>16)==MCH_TT) { + masterclock=MASTERCLOCK_TT; + masterprediv=MASTERPREDIV_TT; + } + for (i=0; i<4; i++) { + SDL_MintAudio_AddFrequency(this, masterclock/(masterprediv*(1<<i)), + masterclock, 3-i, -1); + } + break; + case MCSN_FALCON: /* Also Mac */ + for (i=1; i<12; i++) { + /* Remove unusable Falcon codec predivisors */ + if ((i==6) || (i==8) || (i==10)) { + continue; + } + SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)), + CLK25M, i+1, -1); + } + if (cookie_mcsn->res1 != 0) { + for (i=1; i<4; i++) { + SDL_MintAudio_AddFrequency(this, (cookie_mcsn->res1)/(MASTERPREDIV_FALCON*(1<<i)), + CLKEXT, (1<<i)-1, -1); + } + } + spec->format |= 0x8000; /* Audio is always signed */ + if ((spec->format & 0x00ff)==16) { + spec->format |= 0x1000; /* Audio is always big endian */ + spec->channels=2; /* 16 bits always stereo */ + } + break; + } + +#if 0 + for (i=0; i<MINTAUDIO_freqcount; i++) { + DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", + i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, + MINTAUDIO_frequencies[i].predivisor + )); + } +#endif + + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + + DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + return 0; +} + +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) +{ + int channels_mode, prediv, dmaclock; + void *buffer; + + /* Stop currently playing sound */ + SDL_MintAudio_quit_thread = SDL_FALSE; + SDL_MintAudio_thread_finished = SDL_TRUE; + SDL_MintAudio_WaitThread(); + Buffoper(0); + + /* Set replay tracks */ + Settracks(0,0); + Setmontracks(0); + + /* Select replay format */ + channels_mode=STEREO16; + switch (spec->format & 0xff) { + case 8: + if (spec->channels==2) { + channels_mode=STEREO8; + } else { + channels_mode=MONO8; + } + break; + } + if (Setmode(channels_mode)<0) { + DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); + } + + dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock; + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + switch(cookie_mcsn->play) { + case MCSN_TT: + Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1); + Soundcmd(SETPRESCALE, prediv); + DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n")); + break; + case MCSN_FALCON: + Devconnect(DMAPLAY, DAC, dmaclock, prediv, 1); + DEBUG_PRINT((DEBUG_NAME "Falcon prescaler selected\n")); + break; + } + + /* Set buffer */ + buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + if (Setbuffer(0, buffer, buffer + spec->size)<0) { + DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); + } + + if (SDL_MintAudio_mint_present) { + SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); + } else { + /* Install interrupt */ + Jdisint(MFP_DMASOUND); + Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt); + Jenabint(MFP_DMASOUND); + + if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) { + DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n")); + } + } + + /* Go */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); + DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); +} + +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + /* Lock sound system */ + if (Locksnd()!=1) { + SDL_SetError("Mint_OpenAudio: Audio system already in use"); + return(-1); + } + + SDL_MintAudio_device = this; + + /* Check audio capabilities */ + if (Mint_CheckAudio(this, spec)==-1) { + return -1; + } + + SDL_CalculateAudioSpec(spec); + + /* Allocate memory for audio buffers in DMA-able RAM */ + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM); + if (SDL_MintAudio_audiobuf[0]==NULL) { + SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); + return (-1); + } + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ; + SDL_MintAudio_numbuf=0; + SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2); + SDL_MintAudio_audiosize = spec->size; + SDL_MintAudio_mutex = 0; + + DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0])); + DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1])); + + SDL_MintAudio_CheckFpu(); + + /* Setup audio hardware */ + Mint_InitAudio(this, spec); + + return(1); /* We don't use SDL threaded audio */ +} diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.h b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.h new file mode 100644 index 0000000..b772fda --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_mcsn.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MCSN control structure + + Patrice Mandin +*/ + +#ifndef _SDL_mintaudio_mcsh_h +#define _SDL_mintaudio_mcsh_h + +typedef struct { + unsigned short version; /* Version */ + unsigned short size; /* Size of structure */ + + unsigned short play; /* Replay capability */ + unsigned short record; /* Record capability */ + unsigned short dsp; /* DSP56K present */ + unsigned short pint; /* Interrupt at end of replay */ + unsigned short rint; /* Interrupt at end of record */ + + unsigned long res1; /* Frequency of external clock */ + unsigned long res2; + unsigned long res3; + unsigned long res4; +} cookie_mcsn_t; + +enum { + MCSN_ST=0, + MCSN_TT, + MCSN_STE=MCSN_TT, + MCSN_FALCON, + MCSN_MAC=MCSN_FALCON +}; + +#define SETSMPFREQ 7 /* Set sample frequency */ + +#endif /* _SDL_mintaudio_mcsh_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.c new file mode 100644 index 0000000..4a581e0 --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.c @@ -0,0 +1,326 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + using XBIOS functions (STFA driver) + + Patrice Mandin +*/ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" + +#include "../../video/ataricommon/SDL_atarimxalloc_c.h" +#include "../../video/ataricommon/SDL_atarisuper.h" + +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_stfa.h" + +/*--- Defines ---*/ + +#define MINT_AUDIO_DRIVER_NAME "mint_stfa" + +/* Debug print info */ +#define DEBUG_NAME "audio:stfa: " +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#else +#define DEBUG_PRINT(what) +#endif + +/*--- Static variables ---*/ + +static long cookie_snd, cookie_mch; +static cookie_stfa_t *cookie_stfa; + +static const int freqs[16]={ + 4995, 6269, 7493, 8192, + 9830, 10971, 12538, 14985, + 16384, 19819, 21943, 24576, + 30720, 32336, 43885, 49152 +}; + +/*--- Audio driver functions ---*/ + +static void Mint_CloseAudio(_THIS); +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_LockAudio(_THIS); +static void Mint_UnlockAudio(_THIS); + +/* To check/init hardware audio */ +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec); + +/*--- Audio driver bootstrap functions ---*/ + +static int Audio_Available(void) +{ + long dummy; + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + + /* Check if user asked a different audio driver */ + if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { + DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); + return(0); + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Cookie STFA present ? */ + if (Getcookie(C_STFA, &dummy) != C_FOUND) { + DEBUG_PRINT((DEBUG_NAME "no STFA audio\n")); + return(0); + } + cookie_stfa = (cookie_stfa_t *) dummy; + + SDL_MintAudio_stfa = cookie_stfa; + + DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n")); + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mint_OpenAudio; + this->CloseAudio = Mint_CloseAudio; + this->LockAudio = Mint_LockAudio; + this->UnlockAudio = Mint_UnlockAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MINTAUDIO_STFA_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver", + Audio_Available, Audio_CreateDevice +}; + +static void Mint_LockAudio(_THIS) +{ + void *oldpile; + + /* Stop replay */ + oldpile=(void *)Super(0); + cookie_stfa->sound_enable=STFA_PLAY_DISABLE; + SuperToUser(oldpile); +} + +static void Mint_UnlockAudio(_THIS) +{ + void *oldpile; + + /* Restart replay */ + oldpile=(void *)Super(0); + cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT; + SuperToUser(oldpile); +} + +static void Mint_CloseAudio(_THIS) +{ + void *oldpile; + + /* Stop replay */ + oldpile=(void *)Super(0); + cookie_stfa->sound_enable=STFA_PLAY_DISABLE; + SuperToUser(oldpile); + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) { + } + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } +} + +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) +{ + int i; + + DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + if (spec->channels > 2) { + spec->channels = 2; /* no more than stereo! */ + } + + /* Check formats available */ + MINTAUDIO_freqcount=0; + for (i=0;i<16;i++) { + SDL_MintAudio_AddFrequency(this, freqs[i], 0, i, -1); + } + +#if 1 + for (i=0; i<MINTAUDIO_freqcount; i++) { + DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", + i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, + MINTAUDIO_frequencies[i].predivisor + )); + } +#endif + + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + + DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + return 0; +} + +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) +{ + void *buffer; + void *oldpile; + + buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + + oldpile=(void *)Super(0); + + /* Stop replay */ + cookie_stfa->sound_enable=STFA_PLAY_DISABLE; + + /* Select replay format */ + cookie_stfa->sound_control = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + if ((spec->format & 0xff)==8) { + cookie_stfa->sound_control |= STFA_FORMAT_8BIT; + } else { + cookie_stfa->sound_control |= STFA_FORMAT_16BIT; + } + if (spec->channels==2) { + cookie_stfa->sound_control |= STFA_FORMAT_STEREO; + } else { + cookie_stfa->sound_control |= STFA_FORMAT_MONO; + } + if ((spec->format & 0x8000)!=0) { + cookie_stfa->sound_control |= STFA_FORMAT_SIGNED; + } else { + cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED; + } + if ((spec->format & 0x1000)!=0) { + cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN; + } else { + cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN; + } + + /* Set buffer */ + cookie_stfa->sound_start = (unsigned long) buffer; + cookie_stfa->sound_end = (unsigned long) (buffer + spec->size); + + /* Set interrupt */ + cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt; + + /* Restart replay */ + cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT; + + SuperToUser(oldpile); + + DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); +} + +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + SDL_MintAudio_device = this; + + /* Check audio capabilities */ + if (Mint_CheckAudio(this, spec)==-1) { + return -1; + } + + SDL_CalculateAudioSpec(spec); + + /* Allocate memory for audio buffers in DMA-able RAM */ + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM); + if (SDL_MintAudio_audiobuf[0]==NULL) { + SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); + return (-1); + } + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ; + SDL_MintAudio_numbuf=0; + SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2); + SDL_MintAudio_audiosize = spec->size; + SDL_MintAudio_mutex = 0; + + DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0])); + DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1])); + + SDL_MintAudio_CheckFpu(); + + /* Setup audio hardware */ + Mint_InitAudio(this, spec); + + return(1); /* We don't use threaded audio */ +} diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.h b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.h new file mode 100644 index 0000000..1789b4b --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_stfa.h @@ -0,0 +1,97 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + STFA control structure + + Patrice Mandin +*/ + +#ifndef _SDL_mintaudio_stfa_h +#define _SDL_mintaudio_stfa_h + +/*--- Defines ---*/ + +#define STFA_PLAY_ENABLE (1<<0) +#define STFA_PLAY_DISABLE (0<<0) +#define STFA_PLAY_REPEAT (1<<1) +#define STFA_PLAY_SINGLE (0<<1) + +#define STFA_FORMAT_SIGNED (1<<15) +#define STFA_FORMAT_UNSIGNED (0<<15) +#define STFA_FORMAT_STEREO (1<<14) +#define STFA_FORMAT_MONO (0<<14) +#define STFA_FORMAT_16BIT (1<<13) +#define STFA_FORMAT_8BIT (0<<13) +#define STFA_FORMAT_LITENDIAN (1<<9) +#define STFA_FORMAT_BIGENDIAN (0<<9) +#define STFA_FORMAT_FREQ_MASK 0x0f +enum { + STFA_FORMAT_F4995=0, + STFA_FORMAT_F6269, + STFA_FORMAT_F7493, + STFA_FORMAT_F8192, + + STFA_FORMAT_F9830, + STFA_FORMAT_F10971, + STFA_FORMAT_F12538, + STFA_FORMAT_F14985, + + STFA_FORMAT_F16384, + STFA_FORMAT_F19819, + STFA_FORMAT_F21943, + STFA_FORMAT_F24576, + + STFA_FORMAT_F30720, + STFA_FORMAT_F32336, + STFA_FORMAT_F43885, + STFA_FORMAT_F49152 +}; + +/*--- Types ---*/ + +typedef struct { + unsigned short sound_enable; + unsigned short sound_control; + unsigned short sound_output; + unsigned long sound_start; + unsigned long sound_current; + unsigned long sound_end; + unsigned short version; + void *old_vbl; + void *old_timera; + unsigned long old_mfp_status; + void *new_vbl; + void *drivers_list; + void *play_stop; + unsigned short frequency; + void *set_frequency; + unsigned short frequency_threshold; + unsigned short *custom_freq_table; + unsigned short stfa_on_off; + void *new_drivers_list; + unsigned long old_bit_2_of_cookie_snd; + void (*stfa_it)(void); +} cookie_stfa_t; + +#endif /* _SDL_mintaudio_stfa_h */ diff --git a/3rdparty/SDL/src/audio/mint/SDL_mintaudio_xbios.c b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_xbios.c new file mode 100644 index 0000000..42a0d4a --- /dev/null +++ b/3rdparty/SDL/src/audio/mint/SDL_mintaudio_xbios.c @@ -0,0 +1,490 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT audio driver + using XBIOS functions (Falcon) + + Patrice Mandin, Didier Mquignon +*/ + +#include <unistd.h> +#include <support.h> + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/falcon.h> +#include <mint/cookie.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" + +#include "../../video/ataricommon/SDL_atarimxalloc_c.h" +#include "../../video/ataricommon/SDL_atarisuper.h" + +#include "SDL_mintaudio.h" +#include "SDL_mintaudio_dma8.h" + +/*--- Defines ---*/ + +#define MINT_AUDIO_DRIVER_NAME "mint_xbios" + +/* Debug print info */ +#define DEBUG_NAME "audio:xbios: " +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#else +#define DEBUG_PRINT(what) +#endif + +/*--- Static variables ---*/ + +static long cookie_snd; + +/*--- Audio driver functions ---*/ + +static void Mint_CloseAudio(_THIS); +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_LockAudio(_THIS); +static void Mint_UnlockAudio(_THIS); + +/* To check/init hardware audio */ +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec); +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec); + +/*--- Audio driver bootstrap functions ---*/ + +static int Audio_Available(void) +{ +/* unsigned long dummy;*/ + const char *envr = SDL_getenv("SDL_AUDIODRIVER"); + + /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);*/ + SDL_MintAudio_mint_present = SDL_FALSE; + + /* We can't use XBIOS in interrupt with Magic, don't know about thread */ + /*if (Getcookie(C_MagX, &dummy) == C_FOUND) { + return(0); + }*/ + + /* Check if user asked a different audio driver */ + if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) { + DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); + return(0); + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT)==0) { + DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); + return(0); + } + + /* Check if audio is lockable */ + if (Locksnd()!=1) { + DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); + return(0); + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n")); + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = Mint_OpenAudio; + this->CloseAudio = Mint_CloseAudio; + this->LockAudio = Mint_LockAudio; + this->UnlockAudio = Mint_UnlockAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MINTAUDIO_XBIOS_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", + Audio_Available, Audio_CreateDevice +}; + +static void Mint_LockAudio(_THIS) +{ + /* Stop replay */ + Buffoper(0); +} + +static void Mint_UnlockAudio(_THIS) +{ + /* Restart replay */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); +} + +static void Mint_CloseAudio(_THIS) +{ + /* Stop replay */ + SDL_MintAudio_WaitThread(); + Buffoper(0); + + if (!SDL_MintAudio_mint_present) { + /* Uninstall interrupt */ + Jdisint(MFP_DMASOUND); + } + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) { + } + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } + + /* Unlock sound system */ + Unlocksnd(); +} + +/* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ +static void Devconnect2(int src, int dst, int sclk, int pre) +{ + static const unsigned short MASK1[3] = { 0, 0x6000, 0 }; + static const unsigned short MASK2[4] = { 0xFFF0, 0xFF8F, 0xF0FF, 0x0FFF }; + static const unsigned short INDEX1[4] = { 1, 3, 5, 7 }; + static const unsigned short INDEX2[4] = { 0, 2, 4, 6 }; + unsigned short sync_div,dev_ctrl,dest_ctrl; + void *oldstack; + + if (dst==0) { + return; + } + + oldstack=(void *)Super(0); + + dev_ctrl = DMAAUDIO_IO.dev_ctrl; + dest_ctrl = DMAAUDIO_IO.dest_ctrl; + dev_ctrl &= MASK2[src]; + + if (src==ADC) { + dev_ctrl |= MASK1[sclk]; + } else { + dev_ctrl |= (INDEX1[sclk] << (src<<4)); + } + + if (dst & DMAREC) { + dest_ctrl &= 0xFFF0; + dest_ctrl |= INDEX1[src]; + } + + if (dst & DSPRECV) { + dest_ctrl &= 0xFF8F; + dest_ctrl |= (INDEX1[src]<<4); + } + + if (dst & EXTOUT) { + dest_ctrl &= 0xF0FF; + dest_ctrl |= (INDEX1[src]<<8); + } + + if (dst & DAC) { + dev_ctrl &= 0x0FFF; + dev_ctrl |= MASK1[sclk]; + dest_ctrl &= 0x0FFF; + dest_ctrl |= (INDEX2[src]<<12); + } + + sync_div = DMAAUDIO_IO.sync_div; + if (sclk==CLKEXT) { + pre<<=8; + sync_div &= 0xF0FF; + } else { + sync_div &= 0xFFF0; + } + sync_div |= pre; + + DMAAUDIO_IO.dev_ctrl = dev_ctrl; + DMAAUDIO_IO.dest_ctrl = dest_ctrl; + DMAAUDIO_IO.sync_div = sync_div; + + SuperToUser(oldstack); +} + +static void Mint_CheckExternalClock(_THIS) +{ +#define SIZE_BUF_CLOCK_MEASURE (44100/10) + + char *buffer; + int i, j; + + /* DSP present with its GPIO port ? */ + if ((cookie_snd & SND_DSP)==0) { + return; + } + + buffer = Atari_SysMalloc(SIZE_BUF_CLOCK_MEASURE, MX_STRAM); + if (buffer==NULL) { + DEBUG_PRINT((DEBUG_NAME "Not enough memory for the measure\n")); + return; + } + SDL_memset(buffer, 0, SIZE_BUF_CLOCK_MEASURE); + + Buffoper(0); + Settracks(0,0); + Setmontracks(0); + Setmode(MONO8); + Jdisint(MFP_TIMERA); + + for (i=0; i<2; i++) { + Gpio(GPIO_SET,7); /* DSP port gpio outputs */ + Gpio(GPIO_WRITE,2+i); /* 22.5792/24.576 MHz for 44.1/48KHz */ + Devconnect2(DMAPLAY, DAC, CLKEXT, CLK50K); /* Matrix and clock source */ + Setbuffer(0, buffer, buffer + SIZE_BUF_CLOCK_MEASURE); /* Set buffer */ + Xbtimer(XB_TIMERA, 5, 38, SDL_MintAudio_XbiosInterruptMeasureClock); /* delay mode timer A, prediv /64, 1KHz */ + Jenabint(MFP_TIMERA); + SDL_MintAudio_clocktics = 0; + Buffoper(SB_PLA_ENA); + usleep(110000); + + if((Buffoper(-1) & 1)==0) { + if (SDL_MintAudio_clocktics) { + unsigned long khz; + + khz = ((SIZE_BUF_CLOCK_MEASURE/SDL_MintAudio_clocktics) +1) & 0xFFFFFFFE; + DEBUG_PRINT((DEBUG_NAME "measure %d: freq=%lu KHz\n", i+1, khz)); + + if(khz==44) { + for (j=1; j<4; j++) { + SDL_MintAudio_AddFrequency(this, MASTERCLOCK_44K/(MASTERPREDIV_FALCON*(1<<j)), MASTERCLOCK_44K, (1<<j)-1, 2+i); + } + } else if (khz==48) { + for (j=1; j<4; j++) { + SDL_MintAudio_AddFrequency(this, MASTERCLOCK_48K/(MASTERPREDIV_FALCON*(1<<j)), MASTERCLOCK_48K, (1<<j)-1, 2+i); + } + } + } else { + DEBUG_PRINT((DEBUG_NAME "No measure\n")); + } + } else { + DEBUG_PRINT((DEBUG_NAME "No SDMA clock\n")); + } + + Buffoper(0); /* stop */ + Jdisint(MFP_TIMERA); /* Uninstall interrupt */ + } + + Mfree(buffer); +} + +static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec) +{ + int i; + + DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + if (spec->channels > 2) { + spec->channels = 2; /* no more than stereo! */ + } + + spec->format |= 0x8000; /* Audio is always signed */ + if ((spec->format & 0x00ff)==16) { + spec->format |= 0x1000; /* Audio is always big endian */ + spec->channels=2; /* 16 bits always stereo */ + } + + MINTAUDIO_freqcount=0; + + /* Add external clocks if present */ + Mint_CheckExternalClock(this); + + /* Standard clocks */ + for (i=1;i<12;i++) { + /* Remove unusable Falcon codec predivisors */ + if ((i==6) || (i==8) || (i==10)) { + continue; + } + SDL_MintAudio_AddFrequency(this, MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1)), MASTERCLOCK_FALCON1, i, -1); + } + +#if 1 + for (i=0; i<MINTAUDIO_freqcount; i++) { + DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n", + i, MINTAUDIO_frequencies[i].frequency, MINTAUDIO_frequencies[i].masterclock, + MINTAUDIO_frequencies[i].predivisor + )); + } +#endif + + MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, spec->freq); + spec->freq=MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + + DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff)); + DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0))); + DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x1000)!=0))); + DEBUG_PRINT(("channels=%d, ", spec->channels)); + DEBUG_PRINT(("freq=%d\n", spec->freq)); + + return 0; +} + +static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec) +{ + int channels_mode, prediv; + void *buffer; + + /* Stop currently playing sound */ + SDL_MintAudio_quit_thread = SDL_FALSE; + SDL_MintAudio_thread_finished = SDL_TRUE; + SDL_MintAudio_WaitThread(); + Buffoper(0); + + /* Set replay tracks */ + Settracks(0,0); + Setmontracks(0); + + /* Select replay format */ + channels_mode=STEREO16; + switch (spec->format & 0xff) { + case 8: + if (spec->channels==2) { + channels_mode=STEREO8; + } else { + channels_mode=MONO8; + } + break; + } + if (Setmode(channels_mode)<0) { + DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n")); + } + + prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; + if (MINTAUDIO_frequencies[MINTAUDIO_numfreq].gpio_bits != -1) { + Gpio(GPIO_SET,7); /* DSP port gpio outputs */ + Gpio(GPIO_WRITE, MINTAUDIO_frequencies[MINTAUDIO_numfreq].gpio_bits); + Devconnect2(DMAPLAY, DAC|EXTOUT, CLKEXT, prediv); + } else { + Devconnect2(DMAPLAY, DAC, CLK25M, prediv); + } + + /* Set buffer */ + buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + if (Setbuffer(0, buffer, buffer + spec->size)<0) { + DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); + } + + if (SDL_MintAudio_mint_present) { + SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); + } else { + /* Install interrupt */ + Jdisint(MFP_DMASOUND); + /*Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);*/ + Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt); + Jenabint(MFP_DMASOUND); + + if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) { + DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n")); + } + } + + /* Go */ + Buffoper(SB_PLA_ENA|SB_PLA_RPT); + DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); +} + +static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + /* Lock sound system */ + if (Locksnd()!=1) { + SDL_SetError("Mint_OpenAudio: Audio system already in use"); + return(-1); + } + + SDL_MintAudio_device = this; + + /* Check audio capabilities */ + if (Mint_CheckAudio(this, spec)==-1) { + return -1; + } + + SDL_CalculateAudioSpec(spec); + + /* Allocate memory for audio buffers in DMA-able RAM */ + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM); + if (SDL_MintAudio_audiobuf[0]==NULL) { + SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); + return (-1); + } + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ; + SDL_MintAudio_numbuf=0; + SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2); + SDL_MintAudio_audiosize = spec->size; + SDL_MintAudio_mutex = 0; + + DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0])); + DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1])); + + SDL_MintAudio_CheckFpu(); + + /* Setup audio hardware */ + Mint_InitAudio(this, spec); + + return(1); /* We don't use SDL threaded audio */ +} diff --git a/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.c b/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.c new file mode 100644 index 0000000..64a0ecc --- /dev/null +++ b/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.c @@ -0,0 +1,264 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Tru64 UNIX MME support */ +#include <mme_api.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "SDL_mmeaudio.h" + +static BOOL inUse[NUM_BUFFERS]; + +/* Audio driver functions */ +static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void MME_WaitAudio(_THIS); +static Uint8 *MME_GetAudioBuf(_THIS); +static void MME_PlayAudio(_THIS); +static void MME_WaitDone(_THIS); +static void MME_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + SDL_free(device->hidden); + device->hidden = NULL; + } + SDL_free(device); + device = NULL; + } +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + +/* Initialize all variables that we clean on shutdown */ + this = SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + /* Set the function pointers */ + this->OpenAudio = MME_OpenAudio; + this->WaitAudio = MME_WaitAudio; + this->PlayAudio = MME_PlayAudio; + this->GetAudioBuf = MME_GetAudioBuf; + this->WaitDone = MME_WaitDone; + this->CloseAudio = MME_CloseAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MMEAUDIO_bootstrap = { + "waveout", "Tru64 MME WaveOut", + Audio_Available, Audio_CreateDevice +}; + +static void SetMMerror(char *function, MMRESULT code) +{ + int len; + char errbuf[MAXERRORLENGTH]; + + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); + len = SDL_strlen(errbuf); + waveOutGetErrorText(code, errbuf+len, MAXERRORLENGTH-len); + SDL_SetError("%s",errbuf); +} + +static void CALLBACK MME_CALLBACK(HWAVEOUT hwo, + UINT uMsg, + DWORD dwInstance, + LPARAM dwParam1, + LPARAM dwParam2) +{ + WAVEHDR *wp = (WAVEHDR *) dwParam1; + + if ( uMsg == WOM_DONE ) + inUse[wp->dwUser] = FALSE; +} + +static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + MMRESULT result; + int i; + + mixbuf = NULL; + + /* Set basic WAVE format parameters */ + shm = mmeAllocMem(sizeof(*shm)); + if ( shm == NULL ) { + SDL_SetError("Out of memory: shm"); + return(-1); + } + shm->sound = 0; + shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM; + + /* Determine the audio parameters from the AudioSpec */ + switch ( spec->format & 0xFF ) { + case 8: + /* Unsigned 8 bit audio data */ + spec->format = AUDIO_U8; + shm->wFmt.wBitsPerSample = 8; + break; + case 16: + /* Signed 16 bit audio data */ + spec->format = AUDIO_S16; + shm->wFmt.wBitsPerSample = 16; + break; + default: + SDL_SetError("Unsupported audio format"); + return(-1); + } + + shm->wFmt.wf.nChannels = spec->channels; + shm->wFmt.wf.nSamplesPerSec = spec->freq; + shm->wFmt.wf.nBlockAlign = + shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8; + shm->wFmt.wf.nAvgBytesPerSec = + shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign; + + /* Check the buffer size -- minimum of 1/4 second (word aligned) */ + if ( spec->samples < (spec->freq/4) ) + spec->samples = ((spec->freq/4)+3)&~3; + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Open the audio device */ + result = waveOutOpen(&(shm->sound), + WAVE_MAPPER, + &(shm->wFmt.wf), + MME_CALLBACK, + NULL, + (CALLBACK_FUNCTION|WAVE_OPEN_SHAREABLE)); + if ( result != MMSYSERR_NOERROR ) { + SetMMerror("waveOutOpen()", result); + return(-1); + } + + /* Create the sound buffers */ + mixbuf = (Uint8 *)mmeAllocBuffer(NUM_BUFFERS * (spec->size)); + if ( mixbuf == NULL ) { + SDL_SetError("Out of memory: mixbuf"); + return(-1); + } + + for (i = 0; i < NUM_BUFFERS; i++) { + shm->wHdr[i].lpData = &mixbuf[i * (spec->size)]; + shm->wHdr[i].dwBufferLength = spec->size; + shm->wHdr[i].dwFlags = 0; + shm->wHdr[i].dwUser = i; + shm->wHdr[i].dwLoops = 0; /* loop control counter */ + shm->wHdr[i].lpNext = NULL; /* reserved for driver */ + shm->wHdr[i].reserved = 0; + inUse[i] = FALSE; + } + next_buffer = 0; + return 0; +} + +static void MME_WaitAudio(_THIS) +{ + while ( inUse[next_buffer] ) { + mmeWaitForCallbacks(); + mmeProcessCallbacks(); + } +} + +static Uint8 *MME_GetAudioBuf(_THIS) +{ + Uint8 *retval; + + inUse[next_buffer] = TRUE; + retval = (Uint8 *)(shm->wHdr[next_buffer].lpData); + return retval; +} + +static void MME_PlayAudio(_THIS) +{ + /* Queue it up */ + waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR)); + next_buffer = (next_buffer+1)%NUM_BUFFERS; +} + +static void MME_WaitDone(_THIS) +{ + MMRESULT result; + int i; + + if ( shm->sound ) { + for (i = 0; i < NUM_BUFFERS; i++) + while ( inUse[i] ) { + mmeWaitForCallbacks(); + mmeProcessCallbacks(); + } + result = waveOutReset(shm->sound); + if ( result != MMSYSERR_NOERROR ) + SetMMerror("waveOutReset()", result); + mmeProcessCallbacks(); + } +} + +static void MME_CloseAudio(_THIS) +{ + MMRESULT result; + + if ( mixbuf ) { + result = mmeFreeBuffer(mixbuf); + if (result != MMSYSERR_NOERROR ) + SetMMerror("mmeFreeBuffer", result); + mixbuf = NULL; + } + + if ( shm ) { + if ( shm->sound ) { + result = waveOutClose(shm->sound); + if (result != MMSYSERR_NOERROR ) + SetMMerror("waveOutClose()", result); + mmeProcessCallbacks(); + } + result = mmeFreeMem(shm); + if (result != MMSYSERR_NOERROR ) + SetMMerror("mmeFreeMem()", result); + shm = NULL; + } +} + diff --git a/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.h b/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.h new file mode 100644 index 0000000..6bfaed3 --- /dev/null +++ b/3rdparty/SDL/src/audio/mme/SDL_mmeaudio.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this +#define NUM_BUFFERS 2 + +struct SharedMem { + HWAVEOUT sound; + WAVEHDR wHdr[NUM_BUFFERS]; + PCMWAVEFORMAT wFmt; +}; + +struct SDL_PrivateAudioData { + Uint8 *mixbuf; /* The raw allocated mixing buffer */ + struct SharedMem *shm; + int next_buffer; +}; + +#define shm (this->hidden->shm) +#define mixbuf (this->hidden->mixbuf) +#define next_buffer (this->hidden->next_buffer) +/* Old variable names */ +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/nas/SDL_nasaudio.c b/3rdparty/SDL/src/audio/nas/SDL_nasaudio.c new file mode 100644 index 0000000..a561e62 --- /dev/null +++ b/3rdparty/SDL/src/audio/nas/SDL_nasaudio.c @@ -0,0 +1,423 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + This driver was written by: + Erik Inge Bols + knan@mo.himolde.no +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <signal.h> +#include <unistd.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_nasaudio.h" + +#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC +#include "SDL_loadso.h" +#endif + +/* The tag name used by artsc audio */ +#define NAS_DRIVER_NAME "nas" + +static struct SDL_PrivateAudioData *this2 = NULL; + +static void (*NAS_AuCloseServer) (AuServer *); +static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *); +static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *); +static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *); +static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *); +static void (*NAS_AuSetElements) + (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *); +static void (*NAS_AuWriteElement) + (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *); +static AuServer *(*NAS_AuOpenServer) + (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **); +static AuEventHandlerRec *(*NAS_AuRegisterEventHandler) + (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer); + + +#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC + +static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC; +static void *nas_handle = NULL; + +static int +load_nas_sym(const char *fn, void **addr) +{ + *addr = SDL_LoadFunction(nas_handle, fn); + if (*addr == NULL) { + return 0; + } + return 1; +} + +/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +#define SDL_NAS_SYM(x) \ + if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1 +#else +#define SDL_NAS_SYM(x) NAS_##x = x +#endif + +static int +load_nas_syms(void) +{ + SDL_NAS_SYM(AuCloseServer); + SDL_NAS_SYM(AuNextEvent); + SDL_NAS_SYM(AuDispatchEvent); + SDL_NAS_SYM(AuCreateFlow); + SDL_NAS_SYM(AuStartFlow); + SDL_NAS_SYM(AuSetElements); + SDL_NAS_SYM(AuWriteElement); + SDL_NAS_SYM(AuOpenServer); + SDL_NAS_SYM(AuRegisterEventHandler); + return 0; +} + +#undef SDL_NAS_SYM + +#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC + +static void +UnloadNASLibrary(void) +{ + if (nas_handle != NULL) { + SDL_UnloadObject(nas_handle); + nas_handle = NULL; + } +} + +static int +LoadNASLibrary(void) +{ + int retval = 0; + if (nas_handle == NULL) { + nas_handle = SDL_LoadObject(nas_library); + if (nas_handle == NULL) { + /* Copy error string so we can use it in a new SDL_SetError(). */ + char *origerr = SDL_GetError(); + size_t len = SDL_strlen(origerr) + 1; + char *err = (char *) alloca(len); + SDL_strlcpy(err, origerr, len); + retval = -1; + SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n", + nas_library, err); + } else { + retval = load_nas_syms(); + if (retval < 0) { + UnloadNASLibrary(); + } + } + } + return retval; +} + +#else + +static void +UnloadNASLibrary(void) +{ +} + +static int +LoadNASLibrary(void) +{ + load_nas_syms(); + return 0; +} + +#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */ + + +/* Audio driver functions */ +static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void NAS_WaitAudio(_THIS); +static void NAS_PlayAudio(_THIS); +static Uint8 *NAS_GetAudioBuf(_THIS); +static void NAS_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + if (LoadNASLibrary() == 0) { + AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL); + if (!aud) { + UnloadNASLibrary(); + return 0; + } + NAS_AuCloseServer(aud); + UnloadNASLibrary(); + return 1; + } + return 0; +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + UnloadNASLibrary(); + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + if (LoadNASLibrary() < 0) { + return NULL; + } + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return NULL; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = NAS_OpenAudio; + this->WaitAudio = NAS_WaitAudio; + this->PlayAudio = NAS_PlayAudio; + this->GetAudioBuf = NAS_GetAudioBuf; + this->CloseAudio = NAS_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap NAS_bootstrap = { + NAS_DRIVER_NAME, "Network Audio System", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void NAS_WaitAudio(_THIS) +{ + while ( this->hidden->buf_free < this->hidden->mixlen ) { + AuEvent ev; + NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev); + NAS_AuDispatchEvent(this->hidden->aud, &ev); + } +} + +static void NAS_PlayAudio(_THIS) +{ + while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events, + in the hope that some of them is LowWater events telling us more + of the buffer is free now than what we think. */ + AuEvent ev; + NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev); + NAS_AuDispatchEvent(this->hidden->aud, &ev); + } + this->hidden->buf_free -= this->hidden->mixlen; + + /* Write the audio data */ + NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0, this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL); + + this->hidden->written += this->hidden->mixlen; + +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); +#endif +} + +static Uint8 *NAS_GetAudioBuf(_THIS) +{ + return(this->hidden->mixbuf); +} + +static void NAS_CloseAudio(_THIS) +{ + if ( this->hidden->mixbuf != NULL ) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if ( this->hidden->aud ) { + NAS_AuCloseServer(this->hidden->aud); + this->hidden->aud = 0; + } +} + +static unsigned char sdlformat_to_auformat(unsigned int fmt) +{ + switch (fmt) + { + case AUDIO_U8: + return AuFormatLinearUnsigned8; + case AUDIO_S8: + return AuFormatLinearSigned8; + case AUDIO_U16LSB: + return AuFormatLinearUnsigned16LSB; + case AUDIO_U16MSB: + return AuFormatLinearUnsigned16MSB; + case AUDIO_S16LSB: + return AuFormatLinearSigned16LSB; + case AUDIO_S16MSB: + return AuFormatLinearSigned16MSB; + } + return AuNone; +} + +static AuBool +event_handler(AuServer* aud, AuEvent* ev, AuEventHandlerRec* hnd) +{ + switch (ev->type) { + case AuEventTypeElementNotify: { + AuElementNotifyEvent* event = (AuElementNotifyEvent *)ev; + + switch (event->kind) { + case AuElementNotifyKindLowWater: + if (this2->buf_free >= 0) { + this2->really += event->num_bytes; + gettimeofday(&this2->last_tv, 0); + this2->buf_free += event->num_bytes; + } else { + this2->buf_free = event->num_bytes; + } + break; + case AuElementNotifyKindState: + switch (event->cur_state) { + case AuStatePause: + if (event->reason != AuReasonUser) { + if (this2->buf_free >= 0) { + this2->really += event->num_bytes; + gettimeofday(&this2->last_tv, 0); + this2->buf_free += event->num_bytes; + } else { + this2->buf_free = event->num_bytes; + } + } + break; + } + } + } + } + return AuTrue; +} + +static AuDeviceID +find_device(_THIS, int nch) +{ + /* These "Au" things are all macros, not functions... */ + int i; + for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) { + if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) == + AuComponentKindPhysicalOutput) && + AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) { + return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i)); + } + } + return AuNone; +} + +static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + AuElement elms[3]; + int buffer_size; + Uint16 test_format, format; + + this->hidden->mixbuf = NULL; + + /* Try for a closest match on audio format */ + format = 0; + for ( test_format = SDL_FirstAudioFormat(spec->format); + ! format && test_format; ) { + format = sdlformat_to_auformat(test_format); + + if (format == AuNone) { + test_format = SDL_NextAudioFormat(); + } + } + if ( format == 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + return(-1); + } + spec->format = test_format; + + this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL); + if (this->hidden->aud == 0) + { + SDL_SetError("Couldn't open connection to NAS server"); + return (-1); + } + + this->hidden->dev = find_device(this, spec->channels); + if ((this->hidden->dev == AuNone) || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, NULL)))) { + NAS_AuCloseServer(this->hidden->aud); + this->hidden->aud = 0; + SDL_SetError("Couldn't find a fitting playback device on NAS server"); + return (-1); + } + + buffer_size = spec->freq; + if (buffer_size < 4096) + buffer_size = 4096; + + if (buffer_size > 32768) + buffer_size = 32768; /* So that the buffer won't get unmanageably big. */ + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + this2 = this->hidden; + + /* These "Au" things without a NAS_ prefix are macros, not functions... */ + AuMakeElementImportClient(elms, spec->freq, format, spec->channels, AuTrue, + buffer_size, buffer_size / 4, 0, NULL); + AuMakeElementExportDevice(elms+1, 0, this->hidden->dev, spec->freq, + AuUnlimitedSamples, 0, NULL); + NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL); + NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, this->hidden->flow, + event_handler, (AuPointer) NULL); + + NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); + + /* Allocate mixing buffer */ + this->hidden->mixlen = spec->size; + this->hidden->mixbuf = (Uint8 *)SDL_AllocAudioMem(this->hidden->mixlen); + if ( this->hidden->mixbuf == NULL ) { + return(-1); + } + SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); + + /* Get the parent process id (we're the parent of the audio thread) */ + this->hidden->parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return(0); +} diff --git a/3rdparty/SDL/src/audio/nas/SDL_nasaudio.h b/3rdparty/SDL/src/audio/nas/SDL_nasaudio.h new file mode 100644 index 0000000..1c09630 --- /dev/null +++ b/3rdparty/SDL/src/audio/nas/SDL_nasaudio.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + This driver was written by: + Erik Inge Bols + knan@mo.himolde.no +*/ +#include "SDL_config.h" + +#ifndef _SDL_nasaudio_h +#define _SDL_nasaudio_h + +#ifdef __sgi +#include <nas/audiolib.h> +#else +#include <audio/audiolib.h> +#endif +#include <sys/time.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + AuServer* aud; + AuFlowID flow; + AuDeviceID dev; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; + + int written; + int really; + int bps; + struct timeval last_tv; + int buf_free; +}; +#endif /* _SDL_nasaudio_h */ + diff --git a/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.c b/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.c new file mode 100644 index 0000000..afe141a --- /dev/null +++ b/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.c @@ -0,0 +1,335 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ +#include <nds.h> +#include "SDL.h" +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "SDL_ndsaudio.h" +#include "soundcommon.h" + + +/* Audio driver functions */ +static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void NDS_WaitAudio(_THIS); +static void NDS_PlayAudio(_THIS); +static Uint8 *NDS_GetAudioBuf(_THIS); +static void NDS_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +u32 framecounter = 0,soundoffset = 0; +static SDL_AudioDevice *sdl_nds_audiodevice; + +//void SoundMixCallback(void *stream,u32 size) +//{ +// //printf("SoundMixCallback\n"); +// +// Uint8 *buffer; +// +// buffer = sdl_nds_audiodevice->hidden->mixbuf; +// memset(buffer, sdl_nds_audiodevice->spec.silence, size); +// +// if (!sdl_nds_audiodevice->paused){ +// +// +// //if (sdl_nds_audiodevice->convert.needed) { +// // int silence; +// +// // if (sdl_nds_audiodevice->convert.src_format == AUDIO_U8 ) { +// // silence = 0x80; +// // } else { +// // silence = 0; +// // } +// // memset(sdl_nds_audiodevice->convert.buf, silence, sdl_nds_audiodevice->convert.len); +// // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, +// // (Uint8 *)sdl_nds_audiodevice->convert.buf,sdl_nds_audiodevice->convert.len); +// // SDL_ConvertAudio(&sdl_nds_audiodevice->convert); +// // memcpy(buffer, sdl_nds_audiodevice->convert.buf, sdl_nds_audiodevice->convert.len_cvt); +// //} else +// { +// sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, buffer, size); +// //memcpy((Sint16 *)stream,buffer, size); +// } +// +// } +// +// if(soundsystem->format == 8) +// { +// int i; +// s32 *buffer32 = (s32 *)buffer; +// s32 *stream32 = (s32 *)stream; +// for(i=0;i<size/4;i++){ *stream32++ = buffer32[i] ^ 0x80808080;} +// //for(i = 0; i < size; i++) +// // ((s8*)stream)[i]=(buffer[i]^0x80); +// } +// else +// { +// int i; +// for(i = 0; i < size; i++){ +// //((short*)stream)[i] =(short)buffer[i] << 8; // sound 8bit ---> buffer 16bit +// //if (buffer[i] &0x80) +// //((Sint16*)stream)[i] = 0xff00 | buffer[i]; +// ((Sint16*)stream)[i] = (buffer[i] - 128) << 8; +// +// //else +// // ((Sint16*)stream)[i] = buffer[i]; +// } +// //register signed char *pSrc =buffer; +// //register short *pDest =stream; +// //int x; +// // for (x=size; x>0; x--) +// // { +// // register short temp = (((short)*pSrc)-128)<<8; +// // pSrc++; +// // *pDest++ = temp; +// // } +// +// //memcpy((Sint16 *)stream,buffer, size); +// } +//} + +void SoundMixCallback(void *stream,u32 len) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *)sdl_nds_audiodevice; + + /* Silence the buffer, since it's ours */ + SDL_memset(stream, audio->spec.silence, len); + + /* Only do soemthing if audio is enabled */ + if ( ! audio->enabled ) + return; + + if ( ! audio->paused ) { + if ( audio->convert.needed ) { + //fprintf(stderr,"converting audio\n"); + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback)(audio->spec.userdata, + (Uint8 *)audio->convert.buf,audio->convert.len); + SDL_mutexV(audio->mixer_lock); + SDL_ConvertAudio(&audio->convert); + SDL_memcpy(stream,audio->convert.buf,audio->convert.len_cvt); + } else { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback)(audio->spec.userdata, + (Uint8 *)stream, len); + SDL_mutexV(audio->mixer_lock); + } + } + return; +} +void MixSound(void) +{ + int remain; + + if(soundsystem->format == 8) + { + if((soundsystem->soundcursor + soundsystem->numsamples) > soundsystem->buffersize) + { + SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->buffersize - soundsystem->soundcursor); + remain = soundsystem->numsamples - (soundsystem->buffersize - soundsystem->soundcursor); + SoundMixCallback(soundsystem->mixbuffer,remain); + } + else + { + SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->numsamples); + } + } + else + { + if((soundsystem->soundcursor + soundsystem->numsamples) > (soundsystem->buffersize >> 1)) + { + SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],(soundsystem->buffersize >> 1) - soundsystem->soundcursor); + remain = soundsystem->numsamples - ((soundsystem->buffersize >> 1) - soundsystem->soundcursor); + SoundMixCallback(soundsystem->mixbuffer,remain); + } + else + { + SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],soundsystem->numsamples); + } + } +} + +void InterruptHandler(void) +{ + framecounter++; +} +void FiFoHandler(void) +{ + u32 command; + while ( !(REG_IPC_FIFO_CR & (IPC_FIFO_RECV_EMPTY)) ) + { + command = REG_IPC_FIFO_RX; + + switch(command) + { + case FIFO_NONE: + break; + case UPDATEON_ARM9: + REG_IME = 0; + MixSound(); + REG_IME = 1; + SendCommandToArm7(MIXCOMPLETE_ONARM9); + break; + } + } +} + + + + + +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = NDS_OpenAudio; + this->WaitAudio = NDS_WaitAudio; + this->PlayAudio = NDS_PlayAudio; + this->GetAudioBuf = NDS_GetAudioBuf; + this->CloseAudio = NDS_CloseAudio; + + this->free = Audio_DeleteDevice; +//fprintf(stderr,"Audio_CreateDevice\n"); + return this; +} + +AudioBootStrap NDSAUD_bootstrap = { + "nds", "NDS audio", + Audio_Available, Audio_CreateDevice +}; + + +void static NDS_WaitAudio(_THIS) +{ + //printf("NDS_WaitAudio\n"); +} + +static void NDS_PlayAudio(_THIS) +{ + //printf("playing audio\n"); + if (this->paused) + return; + +} + +static Uint8 *NDS_GetAudioBuf(_THIS) +{ + return NULL;//(this->hidden->mixbuf); +} + +static void NDS_CloseAudio(_THIS) +{ +/* if ( this->hidden->mixbuf != NULL ) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + }*/ +} + +static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + //printf("NDS_OpenAudio\n"); + int format = 0; + //switch(spec->format&0xff) { + //case 8: spec->format = AUDIO_S8;format=8; break; + //case 16: spec->format = AUDIO_S16LSB;format=16; break; + //default: + // SDL_SetError("Unsupported audio format"); + // return(-1); + //} + switch (spec->format&~0x1000) { + case AUDIO_S8: + /* Signed 8-bit audio supported */ + format=8; + break; + case AUDIO_U8: + spec->format ^= 0x80;format=8; + break; + case AUDIO_U16: + /* Unsigned 16-bit audio unsupported, convert to S16 */ + spec->format ^=0x8000;format=16; + case AUDIO_S16: + /* Signed 16-bit audio supported */ + format=16; + break; + } + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + //this->hidden->mixlen = spec->size; + //this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + //if ( this->hidden->mixbuf == NULL ) { + // SDL_SetError("Out of Memory"); + // return(-1); + //} + + SDL_NDSAudio_mutex = 0; + sdl_nds_audiodevice=this; + + irqInit(); + irqSet(IRQ_VBLANK,&InterruptHandler); + irqSet(IRQ_FIFO_NOT_EMPTY,&FiFoHandler); + irqEnable(IRQ_FIFO_NOT_EMPTY); + + REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ; + + + + SoundSystemInit(spec->freq,spec->size,0,format); + SoundStartMixer(); + + + return(1); +} diff --git a/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.h b/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.h new file mode 100644 index 0000000..cb6d1ea --- /dev/null +++ b/3rdparty/SDL/src/audio/nds/SDL_ndsaudio.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + //Uint8 *mixbuf; + //Uint32 mixlen; +}; +unsigned short SDL_NDSAudio_mutex=0; + + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/nds/sound9.c b/3rdparty/SDL/src/audio/nds/sound9.c new file mode 100644 index 0000000..59c1c21 --- /dev/null +++ b/3rdparty/SDL/src/audio/nds/sound9.c @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" +#include "SDL_stdinc.h" + +#include "soundcommon.h" + +void SoundSystemInit(u32 rate,u32 buffersize,u8 channel,u8 format) +{ + soundsystem->rate = rate; + + if(format == 8) + soundsystem->buffersize = buffersize; + else if(format == 16) + soundsystem->buffersize = buffersize * sizeof(short); + + soundsystem->mixbuffer = (s8*)SDL_malloc(soundsystem->buffersize); + //soundsystem->soundbuffer = soundsystem->mixbuffer; + soundsystem->format = format; + soundsystem->channel = channel; + soundsystem->prevtimer = 0; + soundsystem->soundcursor = 0; + soundsystem->numsamples = 0; + soundsystem->period = 0x1000000 / rate; + soundsystem->cmd = INIT; +} + +void SoundStartMixer(void) +{ + soundsystem->cmd |= MIX; +} + +void SendCommandToArm7(u32 command) +{ + while (REG_IPC_FIFO_CR & IPC_FIFO_SEND_FULL); + if (REG_IPC_FIFO_CR & IPC_FIFO_ERROR) + { + REG_IPC_FIFO_CR |= IPC_FIFO_SEND_CLEAR; + } + + REG_IPC_FIFO_TX = command; +} diff --git a/3rdparty/SDL/src/audio/nds/soundcommon.h b/3rdparty/SDL/src/audio/nds/soundcommon.h new file mode 100644 index 0000000..d38e37c --- /dev/null +++ b/3rdparty/SDL/src/audio/nds/soundcommon.h @@ -0,0 +1,80 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SOUNDCOMMON_H +#define __SOUNDCOMMON_H + +#include <nds.h> + +#define CLOCK (1 << 25) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + NONE = 0, + INIT = 1, + MIX = 2, + MIXING = 4, + STOP = 8 +}CommandType; + +typedef enum +{ + FIFO_NONE = 0, + UPDATEON_ARM9 = 1, + MIXCOMPLETE_ONARM9 = 2, +}FifoType; + +typedef struct +{ + s8 *mixbuffer;//,*soundbuffer; + u32 rate; + u32 buffersize; + u32 cmd; + u8 channel,format; + u32 soundcursor,numsamples; + s32 prevtimer; + s16 period; +}S_SoundSystem; + +#define soundsystem ((S_SoundSystem*)((u32)(IPC)+sizeof(TransferRegion))) + +#ifdef ARM9 +extern void SoundSystemInit(u32 rate,u32 buffersize,u8 channel,u8 format); +extern void SoundStartMixer(void); +extern void SendCommandToArm7(u32 command); +#else +extern void SoundVBlankIrq(void); +extern void SoundSwapAndMix(void); +extern void SoundSetTimer(int period); +extern void SoundFifoHandler(void); +extern void SendCommandToArm9(u32 command); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/3rdparty/SDL/src/audio/nto/SDL_nto_audio.c b/3rdparty/SDL/src/audio/nto/SDL_nto_audio.c new file mode 100644 index 0000000..f951825 --- /dev/null +++ b/3rdparty/SDL/src/audio/nto/SDL_nto_audio.c @@ -0,0 +1,507 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sched.h> +#include <sys/select.h> +#include <sys/neutrino.h> +#include <sys/asoundlib.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "SDL_nto_audio.h" + +/* The tag name used by NTO audio */ +#define DRIVER_NAME "qsa-nto" + +/* default channel communication parameters */ +#define DEFAULT_CPARAMS_RATE 22050 +#define DEFAULT_CPARAMS_VOICES 1 +/* FIXME: need to add in the near future flexible logic with frag_size and frags count */ +#define DEFAULT_CPARAMS_FRAG_SIZE 4096 +#define DEFAULT_CPARAMS_FRAGS_MIN 1 +#define DEFAULT_CPARAMS_FRAGS_MAX 1 + +/* Open the audio device for playback, and don't block if busy */ +#define OPEN_FLAGS SND_PCM_OPEN_PLAYBACK + +#define QSA_NO_WORKAROUNDS 0x00000000 +#define QSA_MMAP_WORKAROUND 0x00000001 + +struct BuggyCards +{ + char* cardname; + unsigned long bugtype; +}; + +#define QSA_WA_CARDS 3 + +struct BuggyCards buggycards[QSA_WA_CARDS]= +{ + {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, + {"Vortex 8820", QSA_MMAP_WORKAROUND}, + {"Vortex 8830", QSA_MMAP_WORKAROUND}, +}; + +/* Audio driver functions */ +static void NTO_ThreadInit(_THIS); +static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec); +static void NTO_WaitAudio(_THIS); +static void NTO_PlayAudio(_THIS); +static Uint8* NTO_GetAudioBuf(_THIS); +static void NTO_CloseAudio(_THIS); + +/* card names check to apply the workarounds */ +static int NTO_CheckBuggyCards(_THIS, unsigned long checkfor) +{ + char scardname[33]; + int it; + + if (snd_card_get_name(cardno, scardname, 32)<0) + { + return 0; + } + + for (it=0; it<QSA_WA_CARDS; it++) + { + if (SDL_strcmp(buggycards[it].cardname, scardname)==0) + { + if (buggycards[it].bugtype==checkfor) + { + return 1; + } + } + } + + return 0; +} + +static void NTO_ThreadInit(_THIS) +{ + int status; + struct sched_param param; + + /* increasing default 10 priority to 25 to avoid jerky sound */ + status=SchedGet(0, 0, ¶m); + param.sched_priority=param.sched_curpriority+15; + status=SchedSet(0, 0, SCHED_NOCHANGE, ¶m); +} + +/* PCM transfer channel parameters initialize function */ +static void NTO_InitAudioParams(snd_pcm_channel_params_t* cpars) +{ + SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t)); + + cpars->channel = SND_PCM_CHANNEL_PLAYBACK; + cpars->mode = SND_PCM_MODE_BLOCK; + cpars->start_mode = SND_PCM_START_DATA; + cpars->stop_mode = SND_PCM_STOP_STOP; + cpars->format.format = SND_PCM_SFMT_S16_LE; + cpars->format.interleave = 1; + cpars->format.rate = DEFAULT_CPARAMS_RATE; + cpars->format.voices = DEFAULT_CPARAMS_VOICES; + cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; + cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; + cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; +} + +static int NTO_AudioAvailable(void) +{ + /* See if we can open a nonblocking channel. + Return value '1' means we can. + Return value '0' means we cannot. */ + + int available; + int rval; + snd_pcm_t* handle; + + available = 0; + handle = NULL; + + rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); + + if (rval >= 0) + { + available = 1; + + if ((rval = snd_pcm_close(handle)) < 0) + { + SDL_SetError("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", snd_strerror(rval)); + available = 0; + } + } + else + { + SDL_SetError("NTO_AudioAvailable(): there are no available audio devices.\n"); + } + + return (available); +} + +static void NTO_DeleteAudioDevice(SDL_AudioDevice *device) +{ + if ((device)&&(device->hidden)) + { + SDL_free(device->hidden); + } + if (device) + { + SDL_free(device); + } +} + +static SDL_AudioDevice* NTO_CreateAudioDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if (this) + { + SDL_memset(this, 0, sizeof(SDL_AudioDevice)); + this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc(sizeof(struct SDL_PrivateAudioData)); + } + if ((this == NULL) || (this->hidden == NULL)) + { + SDL_OutOfMemory(); + if (this) + { + SDL_free(this); + } + return (0); + } + SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); + audio_handle = NULL; + + /* Set the function pointers */ + this->ThreadInit = NTO_ThreadInit; + this->OpenAudio = NTO_OpenAudio; + this->WaitAudio = NTO_WaitAudio; + this->PlayAudio = NTO_PlayAudio; + this->GetAudioBuf = NTO_GetAudioBuf; + this->CloseAudio = NTO_CloseAudio; + + this->free = NTO_DeleteAudioDevice; + + return this; +} + +AudioBootStrap QNXNTOAUDIO_bootstrap = +{ + DRIVER_NAME, "QNX6 QSA-NTO Audio", + NTO_AudioAvailable, + NTO_CreateAudioDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void NTO_WaitAudio(_THIS) +{ + fd_set wfds; + int selectret; + + FD_ZERO(&wfds); + FD_SET(audio_fd, &wfds); + + do { + selectret=select(audio_fd + 1, NULL, &wfds, NULL, NULL); + switch (selectret) + { + case -1: + case 0: SDL_SetError("NTO_WaitAudio(): select() failed: %s\n", strerror(errno)); + return; + default: if (FD_ISSET(audio_fd, &wfds)) + { + return; + } + break; + } + } while(1); +} + +static void NTO_PlayAudio(_THIS) +{ + int written, rval; + int towrite; + void* pcmbuffer; + + if (!this->enabled) + { + return; + } + + towrite = this->spec.size; + pcmbuffer = pcm_buf; + + /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ + do { + written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); + if (written != towrite) + { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + { + /* Let a little CPU time go by and try to write again */ + SDL_Delay(1); + /* if we wrote some data */ + towrite -= written; + pcmbuffer += written * this->spec.channels; + continue; + } + else + { + if ((errno == EINVAL) || (errno == EIO)) + { + SDL_memset(&cstatus, 0, sizeof(cstatus)); + cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; + if ((rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) + { + SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", snd_strerror(rval)); + return; + } + if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) + { + if ((rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) + { + SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval)); + return; + } + } + continue; + } + else + { + return; + } + } + } + else + { + /* we wrote all remaining data */ + towrite -= written; + pcmbuffer += written * this->spec.channels; + } + } while ((towrite > 0) && (this->enabled)); + + /* If we couldn't write, assume fatal error for now */ + if (towrite != 0) + { + this->enabled = 0; + } + + return; +} + +static Uint8* NTO_GetAudioBuf(_THIS) +{ + return pcm_buf; +} + +static void NTO_CloseAudio(_THIS) +{ + int rval; + + this->enabled = 0; + + if (audio_handle != NULL) + { + if ((rval = snd_pcm_plugin_flush(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) + { + SDL_SetError("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", snd_strerror(rval)); + return; + } + if ((rval = snd_pcm_close(audio_handle)) < 0) + { + SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n",snd_strerror(rval)); + return; + } + audio_handle = NULL; + } +} + +static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec) +{ + int rval; + int format; + Uint16 test_format; + int found; + + audio_handle = NULL; + this->enabled = 0; + + if (pcm_buf != NULL) + { + SDL_FreeAudioMem(pcm_buf); + pcm_buf = NULL; + } + + /* initialize channel transfer parameters to default */ + NTO_InitAudioParams(&cparams); + + /* Open the audio device */ + rval = snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); + if (rval < 0) + { + SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", snd_strerror(rval)); + return (-1); + } + + if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) + { + /* enable count status parameter */ + if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP)) < 0) + { + SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval)); + return (-1); + } + } + + /* Try for a closest match on audio format */ + format = 0; + /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ + found = 0; + + for (test_format=SDL_FirstAudioFormat(spec->format); !found ;) + { + /* if match found set format to equivalent ALSA format */ + switch (test_format) + { + case AUDIO_U8: + format = SND_PCM_SFMT_U8; + found = 1; + break; + case AUDIO_S8: + format = SND_PCM_SFMT_S8; + found = 1; + break; + case AUDIO_S16LSB: + format = SND_PCM_SFMT_S16_LE; + found = 1; + break; + case AUDIO_S16MSB: + format = SND_PCM_SFMT_S16_BE; + found = 1; + break; + case AUDIO_U16LSB: + format = SND_PCM_SFMT_U16_LE; + found = 1; + break; + case AUDIO_U16MSB: + format = SND_PCM_SFMT_U16_BE; + found = 1; + break; + default: + break; + } + + if (!found) + { + test_format = SDL_NextAudioFormat(); + } + } + + /* assumes test_format not 0 on success */ + if (test_format == 0) + { + SDL_SetError("NTO_OpenAudio(): Couldn't find any hardware audio formats"); + return (-1); + } + + spec->format = test_format; + + /* Set the audio format */ + cparams.format.format = format; + + /* Set mono or stereo audio (currently only two channels supported) */ + cparams.format.voices = spec->channels; + + /* Set rate */ + cparams.format.rate = spec->freq; + + /* Setup the transfer parameters according to cparams */ + rval = snd_pcm_plugin_params(audio_handle, &cparams); + if (rval < 0) + { + SDL_SetError("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", snd_strerror(rval)); + return (-1); + } + + /* Make sure channel is setup right one last time */ + SDL_memset(&csetup, 0x00, sizeof(csetup)); + csetup.channel = SND_PCM_CHANNEL_PLAYBACK; + if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) + { + SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n"); + return -1; + } + + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(spec); + + pcm_len = spec->size; + + if (pcm_len==0) + { + pcm_len = csetup.buf.block.frag_size * spec->channels * (snd_pcm_format_width(format)/8); + } + + /* Allocate memory to the audio buffer and initialize with silence (Note that + buffer size must be a multiple of fragment size, so find closest multiple) + */ + pcm_buf = (Uint8*)SDL_AllocAudioMem(pcm_len); + if (pcm_buf == NULL) + { + SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n"); + return (-1); + } + SDL_memset(pcm_buf, spec->silence, pcm_len); + + /* get the file descriptor */ + if ((audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) + { + SDL_SetError("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", snd_strerror(rval)); + return (-1); + } + + /* Trigger audio playback */ + rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); + if (rval < 0) + { + SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval)); + return (-1); + } + + this->enabled = 1; + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're really ready to rock and roll. :-) */ + return (0); +} diff --git a/3rdparty/SDL/src/audio/nto/SDL_nto_audio.h b/3rdparty/SDL/src/audio/nto/SDL_nto_audio.h new file mode 100644 index 0000000..cfd592c --- /dev/null +++ b/3rdparty/SDL/src/audio/nto/SDL_nto_audio.h @@ -0,0 +1,68 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_NTO_AUDIO_H__ +#define __SDL_NTO_AUDIO_H__ + +#include <sys/asoundlib.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData +{ + /* The audio device handle */ + int cardno; + int deviceno; + snd_pcm_t* audio_handle; + + /* The audio file descriptor */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8* pcm_buf; + Uint32 pcm_len; + + /* QSA parameters */ + snd_pcm_channel_status_t cstatus; + snd_pcm_channel_params_t cparams; + snd_pcm_channel_setup_t csetup; +}; + +#define cardno (this->hidden->cardno) +#define deviceno (this->hidden->deviceno) +#define audio_handle (this->hidden->audio_handle) +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define pcm_buf (this->hidden->pcm_buf) +#define pcm_len (this->hidden->pcm_len) +#define cstatus (this->hidden->cstatus) +#define cparams (this->hidden->cparams) +#define csetup (this->hidden->csetup) + +#endif /* __SDL_NTO_AUDIO_H__ */ diff --git a/3rdparty/SDL/src/audio/paudio/SDL_paudio.c b/3rdparty/SDL/src/audio/paudio/SDL_paudio.c new file mode 100644 index 0000000..6270d8c --- /dev/null +++ b/3rdparty/SDL/src/audio/paudio/SDL_paudio.c @@ -0,0 +1,511 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Carsten Griwodz + griff@kom.tu-darmstadt.de + + based on linux/SDL_dspaudio.c by Sam Lantinga +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_paudio.h" + +#define DEBUG_AUDIO 1 + +/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. + * I guess nobody ever uses audio... Shame over AIX header files. */ +#include <sys/machine.h> +#undef BIG_ENDIAN +#include <sys/audio.h> + +/* The tag name used by paud audio */ +#define Paud_DRIVER_NAME "paud" + +/* Open the audio device for playback, and don't block if busy */ +/* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ +#define OPEN_FLAGS O_WRONLY + +/* Audio driver functions */ +static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void Paud_WaitAudio(_THIS); +static void Paud_PlayAudio(_THIS); +static Uint8 *Paud_GetAudioBuf(_THIS); +static void Paud_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int fd; + int available; + + available = 0; + fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); + if ( fd >= 0 ) { + available = 1; + close(fd); + } + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = Paud_OpenAudio; + this->WaitAudio = Paud_WaitAudio; + this->PlayAudio = Paud_PlayAudio; + this->GetAudioBuf = Paud_GetAudioBuf; + this->CloseAudio = Paud_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap Paud_bootstrap = { + Paud_DRIVER_NAME, "AIX Paudio", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void Paud_WaitAudio(_THIS) +{ + fd_set fdset; + + /* See if we need to use timed audio synchronization */ + if ( frame_ticks ) { + /* Use timer for general audio synchronization */ + Sint32 ticks; + + ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; + if ( ticks > 0 ) { + SDL_Delay(ticks); + } + } else { + audio_buffer paud_bufinfo; + + /* Use select() for audio synchronization */ + struct timeval timeout; + FD_ZERO(&fdset); + FD_SET(audio_fd, &fdset); + + if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Couldn't get audio buffer information\n"); +#endif + timeout.tv_sec = 10; + timeout.tv_usec = 0; + } else { + long ms_in_buf = paud_bufinfo.write_buf_time; + timeout.tv_sec = ms_in_buf/1000; + ms_in_buf = ms_in_buf - timeout.tv_sec*1000; + timeout.tv_usec = ms_in_buf*1000; +#ifdef DEBUG_AUDIO + fprintf( stderr, + "Waiting for write_buf_time=%ld,%ld\n", + timeout.tv_sec, + timeout.tv_usec ); +#endif + } + +#ifdef DEBUG_AUDIO + fprintf(stderr, "Waiting for audio to get ready\n"); +#endif + if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { + const char *message = "Audio timeout - buggy audio driver? (disabled)"; + /* + * In general we should never print to the screen, + * but in this case we have no other way of letting + * the user know what happened. + */ + fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); + this->enabled = 0; + /* Don't try to close - may hang */ + audio_fd = -1; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Done disabling audio\n"); +#endif + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Ready!\n"); +#endif + } +} + +static void Paud_PlayAudio(_THIS) +{ + int written; + + /* Write the audio data, checking for EAGAIN on broken audio drivers */ + do { + written = write(audio_fd, mixbuf, mixlen); + if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { + SDL_Delay(1); /* Let a little CPU time go by */ + } + } while ( (written < 0) && + ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); + + /* If timer synchronization is enabled, set the next write frame */ + if ( frame_ticks ) { + next_frame += frame_ticks; + } + + /* If we couldn't write, assume fatal error for now */ + if ( written < 0 ) { + this->enabled = 0; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", written); +#endif +} + +static Uint8 *Paud_GetAudioBuf(_THIS) +{ + return mixbuf; +} + +static void Paud_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( audio_fd >= 0 ) { + close(audio_fd); + audio_fd = -1; + } +} + +static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char audiodev[1024]; + int format; + int bytes_per_sample; + Uint16 test_format; + audio_init paud_init; + audio_buffer paud_bufinfo; + audio_status paud_status; + audio_control paud_control; + audio_change paud_change; + + /* Reset the timer synchronization flag */ + frame_ticks = 0.0; + + /* Open the audio device */ + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return -1; + } + + /* + * We can't set the buffer size - just ask the device for the maximum + * that we can have. + */ + if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { + SDL_SetError("Couldn't get audio buffer information"); + return -1; + } + + mixbuf = NULL; + + if ( spec->channels > 1 ) + spec->channels = 2; + else + spec->channels = 1; + + /* + * Fields in the audio_init structure: + * + * Ignored by us: + * + * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only? + * paud.slot_number; * slot number of the adapter + * paud.device_id; * adapter identification number + * + * Input: + * + * paud.srate; * the sampling rate in Hz + * paud.bits_per_sample; * 8, 16, 32, ... + * paud.bsize; * block size for this rate + * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX + * paud.channels; * 1=mono, 2=stereo + * paud.flags; * FIXED - fixed length data + * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only) + * * TWOS_COMPLEMENT - 2's complement data + * * SIGNED - signed? comment seems wrong in sys/audio.h + * * BIG_ENDIAN + * paud.operation; * PLAY, RECORD + * + * Output: + * + * paud.flags; * PITCH - pitch is supported + * * INPUT - input is supported + * * OUTPUT - output is supported + * * MONITOR - monitor is supported + * * VOLUME - volume is supported + * * VOLUME_DELAY - volume delay is supported + * * BALANCE - balance is supported + * * BALANCE_DELAY - balance delay is supported + * * TREBLE - treble control is supported + * * BASS - bass control is supported + * * BESTFIT_PROVIDED - best fit returned + * * LOAD_CODE - DSP load needed + * paud.rc; * NO_PLAY - DSP code can't do play requests + * * NO_RECORD - DSP code can't do record requests + * * INVALID_REQUEST - request was invalid + * * CONFLICT - conflict with open's flags + * * OVERLOADED - out of DSP MIPS or memory + * paud.position_resolution; * smallest increment for position + */ + + paud_init.srate = spec->freq; + paud_init.mode = PCM; + paud_init.operation = PLAY; + paud_init.channels = spec->channels; + + /* Try for a closest match on audio format */ + format = 0; + for ( test_format = SDL_FirstAudioFormat(spec->format); + ! format && test_format; ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + switch ( test_format ) { + case AUDIO_U8: + bytes_per_sample = 1; + paud_init.bits_per_sample = 8; + paud_init.flags = TWOS_COMPLEMENT | FIXED; + format = 1; + break; + case AUDIO_S8: + bytes_per_sample = 1; + paud_init.bits_per_sample = 8; + paud_init.flags = SIGNED | + TWOS_COMPLEMENT | FIXED; + format = 1; + break; + case AUDIO_S16LSB: + bytes_per_sample = 2; + paud_init.bits_per_sample = 16; + paud_init.flags = SIGNED | + TWOS_COMPLEMENT | FIXED; + format = 1; + break; + case AUDIO_S16MSB: + bytes_per_sample = 2; + paud_init.bits_per_sample = 16; + paud_init.flags = BIG_ENDIAN | + SIGNED | + TWOS_COMPLEMENT | FIXED; + format = 1; + break; + case AUDIO_U16LSB: + bytes_per_sample = 2; + paud_init.bits_per_sample = 16; + paud_init.flags = TWOS_COMPLEMENT | FIXED; + format = 1; + break; + case AUDIO_U16MSB: + bytes_per_sample = 2; + paud_init.bits_per_sample = 16; + paud_init.flags = BIG_ENDIAN | + TWOS_COMPLEMENT | FIXED; + format = 1; + break; + default: + break; + } + if ( ! format ) { + test_format = SDL_NextAudioFormat(); + } + } + if ( format == 0 ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Couldn't find any hardware audio formats\n"); +#endif + SDL_SetError("Couldn't find any hardware audio formats"); + return -1; + } + spec->format = test_format; + + /* + * We know the buffer size and the max number of subsequent writes + * that can be pending. If more than one can pend, allow the application + * to do something like double buffering between our write buffer and + * the device's own buffer that we are filling with write() anyway. + * + * We calculate spec->samples like this because SDL_CalculateAudioSpec() + * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) + * into spec->size in return. + */ + if ( paud_bufinfo.request_buf_cap == 1 ) + { + spec->samples = paud_bufinfo.write_buf_cap + / bytes_per_sample + / spec->channels; + } + else + { + spec->samples = paud_bufinfo.write_buf_cap + / bytes_per_sample + / spec->channels + / 2; + } + paud_init.bsize = bytes_per_sample * spec->channels; + + SDL_CalculateAudioSpec(spec); + + /* + * The AIX paud device init can't modify the values of the audio_init + * structure that we pass to it. So we don't need any recalculation + * of this stuff and no reinit call as in linux dsp and dma code. + * + * /dev/paud supports all of the encoding formats, so we don't need + * to do anything like reopening the device, either. + */ + if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 ) { + switch ( paud_init.rc ) + { + case 1 : + SDL_SetError("Couldn't set audio format: DSP can't do play requests"); + return -1; + break; + case 2 : + SDL_SetError("Couldn't set audio format: DSP can't do record requests"); + return -1; + break; + case 4 : + SDL_SetError("Couldn't set audio format: request was invalid"); + return -1; + break; + case 5 : + SDL_SetError("Couldn't set audio format: conflict with open's flags"); + return -1; + break; + case 6 : + SDL_SetError("Couldn't set audio format: out of DSP MIPS or memory"); + return -1; + break; + default : + SDL_SetError("Couldn't set audio format: not documented in sys/audio.h"); + return -1; + break; + } + } + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + return -1; + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* + * Set some paramters: full volume, first speaker that we can find. + * Ignore the other settings for now. + */ + paud_change.input = AUDIO_IGNORE; /* the new input source */ + paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */ + paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ + paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */ + paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ + paud_change.balance = 0x3fffffff; /* the new balance */ + paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ + paud_change.treble = AUDIO_IGNORE; /* the new treble state */ + paud_change.bass = AUDIO_IGNORE; /* the new bass state */ + paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ + + paud_control.ioctl_request = AUDIO_CHANGE; + paud_control.request_info = (char*)&paud_change; + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Can't change audio display settings\n" ); +#endif + } + + /* + * Tell the device to expect data. Actual start will wait for + * the first write() call. + */ + paud_control.ioctl_request = AUDIO_START; + paud_control.position = 0; + if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Can't start audio play\n" ); +#endif + SDL_SetError("Can't start audio play"); + return -1; + } + + /* Check to see if we need to use select() workaround */ + { char *workaround; + workaround = SDL_getenv("SDL_DSP_NOSELECT"); + if ( workaround ) { + frame_ticks = (float)(spec->samples*1000)/spec->freq; + next_frame = SDL_GetTicks()+frame_ticks; + } + } + + /* Get the parent process id (we're the parent of the audio thread) */ + parent = getpid(); + + /* We're ready to rock and roll. :-) */ + return 0; +} + diff --git a/3rdparty/SDL/src/audio/paudio/SDL_paudio.h b/3rdparty/SDL/src/audio/paudio/SDL_paudio.h new file mode 100644 index 0000000..72eff1d --- /dev/null +++ b/3rdparty/SDL/src/audio/paudio/SDL_paudio.h @@ -0,0 +1,57 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_paudaudio_h +#define _SDL_paudaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + int audio_fd; + + /* The parent process id, to detect when application quits */ + pid_t parent; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; + + /* Support for audio timing using a timer, in addition to select() */ + float frame_ticks; + float next_frame; +}; +#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define parent (this->hidden->parent) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) +#define frame_ticks (this->hidden->frame_ticks) +#define next_frame (this->hidden->next_frame) + +#endif /* _SDL_paudaudio_h */ diff --git a/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.c b/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.c new file mode 100644 index 0000000..29373f3 --- /dev/null +++ b/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.c @@ -0,0 +1,570 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Stéphan Kochen + stephan@kochen.nl + + Based on parts of the ALSA and ESounD output drivers. +*/ +#include "SDL_config.h" + +/* Allow access to an PulseAudio network stream mixing buffer */ + +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <pulse/pulseaudio.h> +#include <pulse/simple.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "../../../include/SDL_video.h" /* for SDL_WM_GetCaption(). */ +#include "SDL_pulseaudio.h" + +#ifdef SDL_AUDIO_DRIVER_PULSE_DYNAMIC +#include "SDL_name.h" +#include "SDL_loadso.h" +#else +#define SDL_NAME(X) X +#endif + +/* The tag name used by the driver */ +#define PULSE_DRIVER_NAME "pulse" + +/* Audio driver functions */ +static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void PULSE_WaitAudio(_THIS); +static void PULSE_PlayAudio(_THIS); +static Uint8 *PULSE_GetAudioBuf(_THIS); +static void PULSE_CloseAudio(_THIS); +static void PULSE_WaitDone(_THIS); +static void PULSE_SetCaption(_THIS, const char *str); + +#ifdef SDL_AUDIO_DRIVER_PULSE_DYNAMIC + +static const char *pulse_library = SDL_AUDIO_DRIVER_PULSE_DYNAMIC; +static void *pulse_handle = NULL; +static int pulse_loaded = 0; + +static pa_simple* (*SDL_NAME(pa_simple_new))( + const char *server, + const char *name, + pa_stream_direction_t dir, + const char *dev, + const char *stream_name, + const pa_sample_spec *ss, + const pa_channel_map *map, + const pa_buffer_attr *attr, + int *error +); +static void (*SDL_NAME(pa_simple_free))(pa_simple *s); + +static pa_channel_map* (*SDL_NAME(pa_channel_map_init_auto))( + pa_channel_map *m, + unsigned channels, + pa_channel_map_def_t def +); + +static pa_mainloop * (*SDL_NAME(pa_mainloop_new))(void); +static pa_mainloop_api * (*SDL_NAME(pa_mainloop_get_api))(pa_mainloop *m); +static int (*SDL_NAME(pa_mainloop_iterate))(pa_mainloop *m, int block, int *retval); +static void (*SDL_NAME(pa_mainloop_free))(pa_mainloop *m); + +static pa_operation_state_t (*SDL_NAME(pa_operation_get_state))(pa_operation *o); +static void (*SDL_NAME(pa_operation_cancel))(pa_operation *o); +static void (*SDL_NAME(pa_operation_unref))(pa_operation *o); + +static pa_context * (*SDL_NAME(pa_context_new))( + pa_mainloop_api *m, const char *name); +static int (*SDL_NAME(pa_context_connect))( + pa_context *c, const char *server, + pa_context_flags_t flags, const pa_spawn_api *api); +static pa_context_state_t (*SDL_NAME(pa_context_get_state))(pa_context *c); +static void (*SDL_NAME(pa_context_disconnect))(pa_context *c); +static void (*SDL_NAME(pa_context_unref))(pa_context *c); + +static pa_stream * (*SDL_NAME(pa_stream_new))(pa_context *c, + const char *name, const pa_sample_spec *ss, const pa_channel_map *map); +static int (*SDL_NAME(pa_stream_connect_playback))(pa_stream *s, const char *dev, + const pa_buffer_attr *attr, pa_stream_flags_t flags, + pa_cvolume *volume, pa_stream *sync_stream); +static pa_stream_state_t (*SDL_NAME(pa_stream_get_state))(pa_stream *s); +static size_t (*SDL_NAME(pa_stream_writable_size))(pa_stream *s); +static int (*SDL_NAME(pa_stream_write))(pa_stream *s, const void *data, size_t nbytes, + pa_free_cb_t free_cb, int64_t offset, pa_seek_mode_t seek); +static pa_operation * (*SDL_NAME(pa_stream_drain))(pa_stream *s, + pa_stream_success_cb_t cb, void *userdata); +static int (*SDL_NAME(pa_stream_disconnect))(pa_stream *s); +static void (*SDL_NAME(pa_stream_unref))(pa_stream *s); +static pa_operation* (*SDL_NAME(pa_context_set_name))(pa_context *c, + const char *name, pa_context_success_cb_t cb, void *userdata); + +static struct { + const char *name; + void **func; +} pulse_functions[] = { + { "pa_simple_new", + (void **)&SDL_NAME(pa_simple_new) }, + { "pa_simple_free", + (void **)&SDL_NAME(pa_simple_free) }, + { "pa_channel_map_init_auto", + (void **)&SDL_NAME(pa_channel_map_init_auto) }, + { "pa_mainloop_new", + (void **)&SDL_NAME(pa_mainloop_new) }, + { "pa_mainloop_get_api", + (void **)&SDL_NAME(pa_mainloop_get_api) }, + { "pa_mainloop_iterate", + (void **)&SDL_NAME(pa_mainloop_iterate) }, + { "pa_mainloop_free", + (void **)&SDL_NAME(pa_mainloop_free) }, + { "pa_operation_get_state", + (void **)&SDL_NAME(pa_operation_get_state) }, + { "pa_operation_cancel", + (void **)&SDL_NAME(pa_operation_cancel) }, + { "pa_operation_unref", + (void **)&SDL_NAME(pa_operation_unref) }, + { "pa_context_new", + (void **)&SDL_NAME(pa_context_new) }, + { "pa_context_connect", + (void **)&SDL_NAME(pa_context_connect) }, + { "pa_context_get_state", + (void **)&SDL_NAME(pa_context_get_state) }, + { "pa_context_disconnect", + (void **)&SDL_NAME(pa_context_disconnect) }, + { "pa_context_unref", + (void **)&SDL_NAME(pa_context_unref) }, + { "pa_stream_new", + (void **)&SDL_NAME(pa_stream_new) }, + { "pa_stream_connect_playback", + (void **)&SDL_NAME(pa_stream_connect_playback) }, + { "pa_stream_get_state", + (void **)&SDL_NAME(pa_stream_get_state) }, + { "pa_stream_writable_size", + (void **)&SDL_NAME(pa_stream_writable_size) }, + { "pa_stream_write", + (void **)&SDL_NAME(pa_stream_write) }, + { "pa_stream_drain", + (void **)&SDL_NAME(pa_stream_drain) }, + { "pa_stream_disconnect", + (void **)&SDL_NAME(pa_stream_disconnect) }, + { "pa_stream_unref", + (void **)&SDL_NAME(pa_stream_unref) }, + { "pa_context_set_name", + (void **)&SDL_NAME(pa_context_set_name) }, +}; + +static void UnloadPulseLibrary() +{ + if ( pulse_loaded ) { + SDL_UnloadObject(pulse_handle); + pulse_handle = NULL; + pulse_loaded = 0; + } +} + +static int LoadPulseLibrary(void) +{ + int i, retval = -1; + + pulse_handle = SDL_LoadObject(pulse_library); + if ( pulse_handle ) { + pulse_loaded = 1; + retval = 0; + for ( i=0; i<SDL_arraysize(pulse_functions); ++i ) { + *pulse_functions[i].func = SDL_LoadFunction(pulse_handle, pulse_functions[i].name); + if ( !*pulse_functions[i].func ) { + retval = -1; + UnloadPulseLibrary(); + break; + } + } + } + return retval; +} + +#else + +static void UnloadPulseLibrary() +{ + return; +} + +static int LoadPulseLibrary(void) +{ + return 0; +} + +#endif /* SDL_AUDIO_DRIVER_PULSE_DYNAMIC */ + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + pa_sample_spec paspec; + pa_simple *connection; + int available; + + available = 0; + if ( LoadPulseLibrary() < 0 ) { + return available; + } + + /* Connect with a dummy format. */ + paspec.format = PA_SAMPLE_U8; + paspec.rate = 11025; + paspec.channels = 1; + connection = SDL_NAME(pa_simple_new)( + NULL, /* server */ + "Test stream", /* application name */ + PA_STREAM_PLAYBACK, /* playback mode */ + NULL, /* device on the server */ + "Simple DirectMedia Layer", /* stream description */ + &paspec, /* sample format spec */ + NULL, /* channel map */ + NULL, /* buffering attributes */ + NULL /* error code */ + ); + if ( connection != NULL ) { + available = 1; + SDL_NAME(pa_simple_free)(connection); + } + + UnloadPulseLibrary(); + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden->caption); + SDL_free(device->hidden); + SDL_free(device); + UnloadPulseLibrary(); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + LoadPulseLibrary(); + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = PULSE_OpenAudio; + this->WaitAudio = PULSE_WaitAudio; + this->PlayAudio = PULSE_PlayAudio; + this->GetAudioBuf = PULSE_GetAudioBuf; + this->CloseAudio = PULSE_CloseAudio; + this->WaitDone = PULSE_WaitDone; + this->SetCaption = PULSE_SetCaption; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap PULSE_bootstrap = { + PULSE_DRIVER_NAME, "PulseAudio", + Audio_Available, Audio_CreateDevice +}; + +/* This function waits until it is possible to write a full sound buffer */ +static void PULSE_WaitAudio(_THIS) +{ + int size; + while(1) { + if (SDL_NAME(pa_context_get_state)(context) != PA_CONTEXT_READY || + SDL_NAME(pa_stream_get_state)(stream) != PA_STREAM_READY || + SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { + this->enabled = 0; + return; + } + size = SDL_NAME(pa_stream_writable_size)(stream); + if (size >= mixlen) + return; + } +} + +static void PULSE_PlayAudio(_THIS) +{ + /* Write the audio data */ + if (SDL_NAME(pa_stream_write)(stream, mixbuf, mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) + this->enabled = 0; +} + +static Uint8 *PULSE_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +static void PULSE_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( stream != NULL ) { + SDL_NAME(pa_stream_disconnect)(stream); + SDL_NAME(pa_stream_unref)(stream); + stream = NULL; + } + if (context != NULL) { + SDL_NAME(pa_context_disconnect)(context); + SDL_NAME(pa_context_unref)(context); + context = NULL; + } + if (mainloop != NULL) { + SDL_NAME(pa_mainloop_free)(mainloop); + mainloop = NULL; + } +} + +/* Try to get the name of the program */ +static char *get_progname(void) +{ +#ifdef __LINUX__ + char *progname = NULL; + FILE *fp; + static char temp[BUFSIZ]; + + SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid()); + fp = fopen(temp, "r"); + if ( fp != NULL ) { + if ( fgets(temp, sizeof(temp)-1, fp) ) { + progname = SDL_strrchr(temp, '/'); + if ( progname == NULL ) { + progname = temp; + } else { + progname = progname+1; + } + } + fclose(fp); + } + return(progname); +#elif defined(__NetBSD__) + return getprogname(); +#else + return("unknown"); +#endif +} + +static void caption_set_complete(pa_context *c, int success, void *userdata) +{ + /* no-op. */ +} + +static void PULSE_SetCaption(_THIS, const char *str) +{ + SDL_free(this->hidden->caption); + if ((str == NULL) || (*str == '\0')) { + str = get_progname(); /* set a default so SOMETHING shows up. */ + } + this->hidden->caption = SDL_strdup(str); + if (context != NULL) { + SDL_NAME(pa_context_set_name)(context, this->hidden->caption, + caption_set_complete, 0); + } +} + +static void stream_drain_complete(pa_stream *s, int success, void *userdata) +{ + /* no-op. */ +} + +static void PULSE_WaitDone(_THIS) +{ + pa_operation *o; + + o = SDL_NAME(pa_stream_drain)(stream, stream_drain_complete, NULL); + if (!o) + return; + + while (SDL_NAME(pa_operation_get_state)(o) != PA_OPERATION_DONE) { + if (SDL_NAME(pa_context_get_state)(context) != PA_CONTEXT_READY || + SDL_NAME(pa_stream_get_state)(stream) != PA_STREAM_READY || + SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { + SDL_NAME(pa_operation_cancel)(o); + break; + } + } + SDL_NAME(pa_operation_unref)(o); +} + +static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + int state; + Uint16 test_format; + pa_sample_spec paspec; + pa_buffer_attr paattr; + pa_channel_map pacmap; + pa_stream_flags_t flags = 0; + + paspec.format = PA_SAMPLE_INVALID; + for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) { + switch ( test_format ) { + case AUDIO_U8: + paspec.format = PA_SAMPLE_U8; + break; + case AUDIO_S16LSB: + paspec.format = PA_SAMPLE_S16LE; + break; + case AUDIO_S16MSB: + paspec.format = PA_SAMPLE_S16BE; + break; + } + if ( paspec.format != PA_SAMPLE_INVALID ) + break; + test_format = SDL_NextAudioFormat(); + } + if (paspec.format == PA_SAMPLE_INVALID ) { + SDL_SetError("Couldn't find any suitable audio formats"); + return(-1); + } + spec->format = test_format; + + paspec.channels = spec->channels; + paspec.rate = spec->freq; + + /* Calculate the final parameters for this audio specification */ +#ifdef PA_STREAM_ADJUST_LATENCY + spec->samples /= 2; /* Mix in smaller chunck to avoid underruns */ +#endif + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + mixlen = spec->size; + mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); + if ( mixbuf == NULL ) { + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* Reduced prebuffering compared to the defaults. */ +#ifdef PA_STREAM_ADJUST_LATENCY + paattr.tlength = mixlen * 4; /* 2x original requested bufsize */ + paattr.prebuf = -1; + paattr.maxlength = -1; + paattr.minreq = mixlen; /* -1 can lead to pa_stream_writable_size() + >= mixlen never becoming true */ + flags = PA_STREAM_ADJUST_LATENCY; +#else + paattr.tlength = mixlen*2; + paattr.prebuf = mixlen*2; + paattr.maxlength = mixlen*2; + paattr.minreq = mixlen; +#endif + + /* The SDL ALSA output hints us that we use Windows' channel mapping */ + /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ + SDL_NAME(pa_channel_map_init_auto)( + &pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX); + + /* Set up a new main loop */ + if (!(mainloop = SDL_NAME(pa_mainloop_new)())) { + PULSE_CloseAudio(this); + SDL_SetError("pa_mainloop_new() failed"); + return(-1); + } + + if (this->hidden->caption == NULL) { + char *title = NULL; + SDL_WM_GetCaption(&title, NULL); + PULSE_SetCaption(this, title); + } + + mainloop_api = SDL_NAME(pa_mainloop_get_api)(mainloop); + if (!(context = SDL_NAME(pa_context_new)(mainloop_api, + this->hidden->caption))) { + PULSE_CloseAudio(this); + SDL_SetError("pa_context_new() failed"); + return(-1); + } + + /* Connect to the PulseAudio server */ + if (SDL_NAME(pa_context_connect)(context, NULL, 0, NULL) < 0) { + PULSE_CloseAudio(this); + SDL_SetError("Could not setup connection to PulseAudio"); + return(-1); + } + + do { + if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { + PULSE_CloseAudio(this); + SDL_SetError("pa_mainloop_iterate() failed"); + return(-1); + } + state = SDL_NAME(pa_context_get_state)(context); + if (!PA_CONTEXT_IS_GOOD(state)) { + PULSE_CloseAudio(this); + SDL_SetError("Could not connect to PulseAudio"); + return(-1); + } + } while (state != PA_CONTEXT_READY); + + stream = SDL_NAME(pa_stream_new)( + context, + "Simple DirectMedia Layer", /* stream description */ + &paspec, /* sample format spec */ + &pacmap /* channel map */ + ); + if ( stream == NULL ) { + PULSE_CloseAudio(this); + SDL_SetError("Could not setup PulseAudio stream"); + return(-1); + } + + if (SDL_NAME(pa_stream_connect_playback)(stream, NULL, &paattr, flags, + NULL, NULL) < 0) { + PULSE_CloseAudio(this); + SDL_SetError("Could not connect PulseAudio stream"); + return(-1); + } + + do { + if (SDL_NAME(pa_mainloop_iterate)(mainloop, 1, NULL) < 0) { + PULSE_CloseAudio(this); + SDL_SetError("pa_mainloop_iterate() failed"); + return(-1); + } + state = SDL_NAME(pa_stream_get_state)(stream); + if (!PA_STREAM_IS_GOOD(state)) { + PULSE_CloseAudio(this); + SDL_SetError("Could not create to PulseAudio stream"); + return(-1); + } + } while (state != PA_STREAM_READY); + + return(0); +} diff --git a/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.h b/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.h new file mode 100644 index 0000000..63ee751 --- /dev/null +++ b/3rdparty/SDL/src/audio/pulse/SDL_pulseaudio.h @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Stéphan Kochen + stephan@kochen.nl + + Based on parts of the ALSA and ESounD output drivers. +*/ +#include "SDL_config.h" + +#ifndef _SDL_pulseaudio_h +#define _SDL_pulseaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + pa_mainloop *mainloop; + pa_mainloop_api *mainloop_api; + pa_context *context; + pa_stream *stream; + + char *caption; + + /* Raw mixing buffer */ + Uint8 *mixbuf; + int mixlen; +}; + +#if (PA_API_VERSION < 12) +/** Return non-zero if the passed state is one of the connected states */ +static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) { + return + x == PA_CONTEXT_CONNECTING || + x == PA_CONTEXT_AUTHORIZING || + x == PA_CONTEXT_SETTING_NAME || + x == PA_CONTEXT_READY; +} +/** Return non-zero if the passed state is one of the connected states */ +static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) { + return + x == PA_STREAM_CREATING || + x == PA_STREAM_READY; +} +#endif /* pulseaudio <= 0.9.10 */ + +/* Old variable names */ +#define mainloop (this->hidden->mainloop) +#define mainloop_api (this->hidden->mainloop_api) +#define context (this->hidden->context) +#define stream (this->hidden->stream) +#define mixbuf (this->hidden->mixbuf) +#define mixlen (this->hidden->mixlen) + +#endif /* _SDL_pulseaudio_h */ + diff --git a/3rdparty/SDL/src/audio/sun/SDL_sunaudio.c b/3rdparty/SDL/src/audio/sun/SDL_sunaudio.c new file mode 100644 index 0000000..7a39e71 --- /dev/null +++ b/3rdparty/SDL/src/audio/sun/SDL_sunaudio.c @@ -0,0 +1,432 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <fcntl.h> +#include <errno.h> +#ifdef __NETBSD__ +#include <sys/ioctl.h> +#include <sys/audioio.h> +#endif +#ifdef __SVR4 +#include <sys/audioio.h> +#else +#include <sys/time.h> +#include <sys/types.h> +#endif +#include <unistd.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audiomem.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_sunaudio.h" + +/* Open the audio device for playback, and don't block if busy */ +#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) + +/* Audio driver functions */ +static int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DSP_WaitAudio(_THIS); +static void DSP_PlayAudio(_THIS); +static Uint8 *DSP_GetAudioBuf(_THIS); +static void DSP_CloseAudio(_THIS); + +static Uint8 snd2au(int sample); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + int fd; + int available; + + available = 0; + fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 1); + if ( fd >= 0 ) { + available = 1; + close(fd); + } + return(available); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + audio_fd = -1; + + /* Set the function pointers */ + this->OpenAudio = DSP_OpenAudio; + this->WaitAudio = DSP_WaitAudio; + this->PlayAudio = DSP_PlayAudio; + this->GetAudioBuf = DSP_GetAudioBuf; + this->CloseAudio = DSP_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap SUNAUDIO_bootstrap = { + "audio", "UNIX /dev/audio interface", + Audio_Available, Audio_CreateDevice +}; + +#ifdef DEBUG_AUDIO +void CheckUnderflow(_THIS) +{ +#ifdef AUDIO_GETINFO + audio_info_t info; + int left; + + ioctl(audio_fd, AUDIO_GETINFO, &info); + left = (written - info.play.samples); + if ( written && (left == 0) ) { + fprintf(stderr, "audio underflow!\n"); + } +#endif +} +#endif + +void DSP_WaitAudio(_THIS) +{ +#ifdef AUDIO_GETINFO +#define SLEEP_FUDGE 10 /* 10 ms scheduling fudge factor */ + audio_info_t info; + Sint32 left; + + ioctl(audio_fd, AUDIO_GETINFO, &info); + left = (written - info.play.samples); + if ( left > fragsize ) { + Sint32 sleepy; + + sleepy = ((left - fragsize)/frequency); + sleepy -= SLEEP_FUDGE; + if ( sleepy > 0 ) { + SDL_Delay(sleepy); + } + } +#else + fd_set fdset; + + FD_ZERO(&fdset); + FD_SET(audio_fd, &fdset); + select(audio_fd+1, NULL, &fdset, NULL, NULL); +#endif +} + +void DSP_PlayAudio(_THIS) +{ + /* Write the audio data */ + if ( ulaw_only ) { + /* Assuming that this->spec.freq >= 8000 Hz */ + int accum, incr, pos; + Uint8 *aubuf; + + accum = 0; + incr = this->spec.freq/8; + aubuf = ulaw_buf; + switch (audio_fmt & 0xFF) { + case 8: { + Uint8 *sndbuf; + + sndbuf = mixbuf; + for ( pos=0; pos < fragsize; ++pos ) { + *aubuf = snd2au((0x80-*sndbuf)*64); + accum += incr; + while ( accum > 0 ) { + accum -= 1000; + sndbuf += 1; + } + aubuf += 1; + } + } + break; + case 16: { + Sint16 *sndbuf; + + sndbuf = (Sint16 *)mixbuf; + for ( pos=0; pos < fragsize; ++pos ) { + *aubuf = snd2au(*sndbuf/4); + accum += incr; + while ( accum > 0 ) { + accum -= 1000; + sndbuf += 1; + } + aubuf += 1; + } + } + break; + } +#ifdef DEBUG_AUDIO + CheckUnderflow(this); +#endif + if ( write(audio_fd, ulaw_buf, fragsize) < 0 ) { + /* Assume fatal error, for now */ + this->enabled = 0; + } + written += fragsize; + } else { +#ifdef DEBUG_AUDIO + CheckUnderflow(this); +#endif + if ( write(audio_fd, mixbuf, this->spec.size) < 0 ) { + /* Assume fatal error, for now */ + this->enabled = 0; + } + written += fragsize; + } +} + +Uint8 *DSP_GetAudioBuf(_THIS) +{ + return(mixbuf); +} + +void DSP_CloseAudio(_THIS) +{ + if ( mixbuf != NULL ) { + SDL_FreeAudioMem(mixbuf); + mixbuf = NULL; + } + if ( ulaw_buf != NULL ) { + SDL_free(ulaw_buf); + ulaw_buf = NULL; + } + close(audio_fd); +} + +int DSP_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char audiodev[1024]; +#ifdef AUDIO_SETINFO + int enc; +#endif + int desired_freq = spec->freq; + + /* Initialize our freeable variables, in case we fail*/ + audio_fd = -1; + mixbuf = NULL; + ulaw_buf = NULL; + + /* Determine the audio parameters from the AudioSpec */ + switch ( spec->format & 0xFF ) { + + case 8: { /* Unsigned 8 bit audio data */ + spec->format = AUDIO_U8; +#ifdef AUDIO_SETINFO + enc = AUDIO_ENCODING_LINEAR8; +#endif + } + break; + + case 16: { /* Signed 16 bit audio data */ + spec->format = AUDIO_S16SYS; +#ifdef AUDIO_SETINFO + enc = AUDIO_ENCODING_LINEAR; +#endif + } + break; + + default: { + SDL_SetError("Unsupported audio format"); + return(-1); + } + } + audio_fmt = spec->format; + + /* Open the audio device */ + audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 1); + if ( audio_fd < 0 ) { + SDL_SetError("Couldn't open %s: %s", audiodev, + strerror(errno)); + return(-1); + } + + ulaw_only = 0; /* modern Suns do support linear audio */ +#ifdef AUDIO_SETINFO + for(;;) { + audio_info_t info; + AUDIO_INITINFO(&info); /* init all fields to "no change" */ + + /* Try to set the requested settings */ + info.play.sample_rate = spec->freq; + info.play.channels = spec->channels; + info.play.precision = (enc == AUDIO_ENCODING_ULAW) + ? 8 : spec->format & 0xff; + info.play.encoding = enc; + if( ioctl(audio_fd, AUDIO_SETINFO, &info) == 0 ) { + + /* Check to be sure we got what we wanted */ + if(ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { + SDL_SetError("Error getting audio parameters: %s", + strerror(errno)); + return -1; + } + if(info.play.encoding == enc + && info.play.precision == (spec->format & 0xff) + && info.play.channels == spec->channels) { + /* Yow! All seems to be well! */ + spec->freq = info.play.sample_rate; + break; + } + } + + switch(enc) { + case AUDIO_ENCODING_LINEAR8: + /* unsigned 8bit apparently not supported here */ + enc = AUDIO_ENCODING_LINEAR; + spec->format = AUDIO_S16SYS; + break; /* try again */ + + case AUDIO_ENCODING_LINEAR: + /* linear 16bit didn't work either, resort to -law */ + enc = AUDIO_ENCODING_ULAW; + spec->channels = 1; + spec->freq = 8000; + spec->format = AUDIO_U8; + ulaw_only = 1; + break; + + default: + /* oh well... */ + SDL_SetError("Error setting audio parameters: %s", + strerror(errno)); + return -1; + } + } +#endif /* AUDIO_SETINFO */ + written = 0; + + /* We can actually convert on-the-fly to U-Law */ + if ( ulaw_only ) { + spec->freq = desired_freq; + fragsize = (spec->samples*1000)/(spec->freq/8); + frequency = 8; + ulaw_buf = (Uint8 *)SDL_malloc(fragsize); + if ( ulaw_buf == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + spec->channels = 1; + } else { + fragsize = spec->samples; + frequency = spec->freq/1000; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Audio device %s U-Law only\n", + ulaw_only ? "is" : "is not"); + fprintf(stderr, "format=0x%x chan=%d freq=%d\n", + spec->format, spec->channels, spec->freq); +#endif + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Allocate mixing buffer */ + mixbuf = (Uint8 *)SDL_AllocAudioMem(spec->size); + if ( mixbuf == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(mixbuf, spec->silence, spec->size); + + /* We're ready to rock and roll. :-) */ + return(0); +} + +/************************************************************************/ +/* This function (snd2au()) copyrighted: */ +/************************************************************************/ +/* Copyright 1989 by Rich Gopstein and Harris Corporation */ +/* */ +/* Permission to use, copy, modify, and distribute this software */ +/* and its documentation for any purpose and without fee is */ +/* hereby granted, provided that the above copyright notice */ +/* appears in all copies and that both that copyright notice and */ +/* this permission notice appear in supporting documentation, and */ +/* that the name of Rich Gopstein and Harris Corporation not be */ +/* used in advertising or publicity pertaining to distribution */ +/* of the software without specific, written prior permission. */ +/* Rich Gopstein and Harris Corporation make no representations */ +/* about the suitability of this software for any purpose. It */ +/* provided "as is" without express or implied warranty. */ +/************************************************************************/ + +static Uint8 snd2au(int sample) +{ + + int mask; + + if (sample < 0) { + sample = -sample; + mask = 0x7f; + } else { + mask = 0xff; + } + + if (sample < 32) { + sample = 0xF0 | (15 - sample / 2); + } else if (sample < 96) { + sample = 0xE0 | (15 - (sample - 32) / 4); + } else if (sample < 224) { + sample = 0xD0 | (15 - (sample - 96) / 8); + } else if (sample < 480) { + sample = 0xC0 | (15 - (sample - 224) / 16); + } else if (sample < 992) { + sample = 0xB0 | (15 - (sample - 480) / 32); + } else if (sample < 2016) { + sample = 0xA0 | (15 - (sample - 992) / 64); + } else if (sample < 4064) { + sample = 0x90 | (15 - (sample - 2016) / 128); + } else if (sample < 8160) { + sample = 0x80 | (15 - (sample - 4064) / 256); + } else { + sample = 0x80; + } + return (mask & sample); +} diff --git a/3rdparty/SDL/src/audio/sun/SDL_sunaudio.h b/3rdparty/SDL/src/audio/sun/SDL_sunaudio.h new file mode 100644 index 0000000..e6be419 --- /dev/null +++ b/3rdparty/SDL/src/audio/sun/SDL_sunaudio.h @@ -0,0 +1,55 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData { + /* The file descriptor for the audio device */ + int audio_fd; + + Uint16 audio_fmt; /* The app audio format */ + Uint8 *mixbuf; /* The app mixing buffer */ + int ulaw_only; /* Flag -- does hardware only output U-law? */ + Uint8 *ulaw_buf; /* The U-law mixing buffer */ + Sint32 written; /* The number of samples written */ + int fragsize; /* The audio fragment size in samples */ + int frequency; /* The audio frequency in KHz */ +}; + +/* Old variable names */ +#define audio_fd (this->hidden->audio_fd) +#define audio_fmt (this->hidden->audio_fmt) +#define mixbuf (this->hidden->mixbuf) +#define ulaw_only (this->hidden->ulaw_only) +#define ulaw_buf (this->hidden->ulaw_buf) +#define written (this->hidden->written) +#define fragsize (this->hidden->fragsize) +#define frequency (this->hidden->frequency) + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.cpp b/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.cpp new file mode 100644 index 0000000..72a4eaf --- /dev/null +++ b/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.cpp @@ -0,0 +1,614 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocaudio.cpp + Epoc based SDL audio driver implementation + + Markus Mertama +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_epocaudio.c,v 0.0.0.0 2001/06/19 17:19:56 hercules Exp $"; +#endif + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> + +#include "epoc_sdl.h" + +#include <e32hal.h> + + +extern "C" { +#include "SDL_audio.h" +#include "SDL_error.h" +#include "SDL_audiomem.h" +#include "SDL_audio_c.h" +#include "SDL_timer.h" +#include "SDL_audiodev_c.h" +} + +#include "SDL_epocaudio.h" + +#include "streamplayer.h" + + +//#define DEBUG_AUDIO + + +/* Audio driver functions */ + +static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec); +static void EPOC_WaitAudio(SDL_AudioDevice *thisdevice); +static void EPOC_PlayAudio(SDL_AudioDevice *thisdevice); +static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice *thisdevice); +static void EPOC_CloseAudio(SDL_AudioDevice *thisdevice); +static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice); + +static int Audio_Available(void); +static SDL_AudioDevice *Audio_CreateDevice(int devindex); +static void Audio_DeleteDevice(SDL_AudioDevice *device); + + +//void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len); + +#ifdef __WINS__ +#define DODUMP +#endif + +#ifdef DODUMP +NONSHARABLE_CLASS(TDump) + { + public: + TInt Open(); + void Close(); + void Dump(const TDesC8& aDes); + private: + RFile iFile; + RFs iFs; + }; + +TInt TDump::Open() + { + TInt err = iFs.Connect(); + if(err == KErrNone) + { +#ifdef __WINS__ +_LIT(target, "C:\\sdlau.raw"); +#else +_LIT(target, "E:\\sdlau.raw"); +#endif + err = iFile.Replace(iFs, target, EFileWrite); + } + return err; + } +void TDump::Close() + { + iFile.Close(); + iFs.Close(); + } +void TDump::Dump(const TDesC8& aDes) + { + iFile.Write(aDes); + } +#endif + + +NONSHARABLE_CLASS(CSimpleWait) : public CTimer + { + public: + void Wait(TTimeIntervalMicroSeconds32 aWait); + static CSimpleWait* NewL(); + private: + CSimpleWait(); + void RunL(); + }; + + +CSimpleWait* CSimpleWait::NewL() + { + CSimpleWait* wait = new (ELeave) CSimpleWait(); + CleanupStack::PushL(wait); + wait->ConstructL(); + CleanupStack::Pop(); + return wait; + } + +void CSimpleWait::Wait(TTimeIntervalMicroSeconds32 aWait) + { + After(aWait); + CActiveScheduler::Start(); + } + +CSimpleWait::CSimpleWait() : CTimer(CActive::EPriorityStandard) + { + CActiveScheduler::Add(this); + } + +void CSimpleWait::RunL() + { + CActiveScheduler::Stop(); + } + +const TInt KAudioBuffers(2); + + +NONSHARABLE_CLASS(CEpocAudio) : public CBase, public MStreamObs, public MStreamProvider + { + public: + static void* NewL(TInt BufferSize, TInt aFill); + inline static CEpocAudio& Current(SDL_AudioDevice* thisdevice); + + static void Free(SDL_AudioDevice* thisdevice); + + void Wait(); + void Play(); + // void SetBuffer(const TDesC8& aBuffer); + void ThreadInitL(TAny* aDevice); + void Open(TInt iRate, TInt iChannels, TUint32 aType, TInt aBytes); + ~CEpocAudio(); + TUint8* Buffer(); + TBool SetPause(TBool aPause); + #ifdef DODUMP + void Dump(const TDesC8& aBuf) {iDump.Dump(aBuf);} + #endif + private: + CEpocAudio(TInt aBufferSize); + void Complete(TInt aState, TInt aError); + TPtrC8 Data(); + void ConstructL(TInt aFill); + private: + TInt iBufferSize; + CStreamPlayer* iPlayer; + TInt iBufferRate; + TInt iRate; + TInt iChannels; + TUint32 iType; + TInt iPosition; + TThreadId iTid; + TUint8* iAudioPtr; + TUint8* iBuffer; + // TTimeIntervalMicroSeconds iStart; + TTime iStart; + TInt iTune; + CSimpleWait* iWait; + #ifdef DODUMP + TDump iDump; + #endif + }; + +inline CEpocAudio& CEpocAudio::Current(SDL_AudioDevice* thisdevice) + { + return *static_cast<CEpocAudio*>((void*)thisdevice->hidden); + } + +/* + +TBool EndSc(TAny*) + { + CActiveScheduler::Stop(); + } + +LOCAL_C void CleanScL() + { + CIdle* d = CIdle::NewLC(CActive:::EPriorityIdle); + d->Start(TCallBack(EndSc)); + CActiveScheduler::Start(); + + } +*/ + +void CEpocAudio::Free(SDL_AudioDevice* thisdevice) + { + CEpocAudio* ea = static_cast<CEpocAudio*>((void*)thisdevice->hidden); + if(ea) + { + ASSERT(ea->iTid == RThread().Id()); + delete ea; + thisdevice->hidden = NULL; + + CActiveScheduler* as = CActiveScheduler::Current(); + ASSERT(as->StackDepth() == 0); + delete as; + CActiveScheduler::Install(NULL); + } + ASSERT(thisdevice->hidden == NULL); + } + +CEpocAudio::CEpocAudio(TInt aBufferSize) : iBufferSize(aBufferSize), iPosition(-1) + { + } + +void* CEpocAudio::NewL(TInt aBufferSize, TInt aFill) + { + CEpocAudio* eAudioLib = new (ELeave) CEpocAudio(aBufferSize); + CleanupStack::PushL(eAudioLib); + eAudioLib->ConstructL(aFill); + CleanupStack::Pop(); + return eAudioLib; + } + +void CEpocAudio::ConstructL(TInt aFill) + { + iBuffer = (TUint8*) User::AllocL(KAudioBuffers * iBufferSize); + memset(iBuffer, aFill, KAudioBuffers * iBufferSize); + iAudioPtr = iBuffer; + } + + +TBool CEpocAudio::SetPause(TBool aPause) + { + if(aPause && iPosition >= 0) + { + iPosition = -1; + if(iPlayer != NULL) + iPlayer->Stop(); + } + if(!aPause && iPosition < 0) + { + iPosition = 0; + if(iPlayer != NULL) + iPlayer->Start(); + } + return iPosition < 0; + } + +void CEpocAudio::ThreadInitL(TAny* aDevice) + { + iTid = RThread().Id(); + CActiveScheduler* as = new (ELeave) CActiveScheduler(); + CActiveScheduler::Install(as); + + EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem((TSdlCleanupOperation)EPOC_CloseAudio, aDevice)); + + iWait = CSimpleWait::NewL(); + + iPlayer = new (ELeave) CStreamPlayer(*this, *this); + iPlayer->ConstructL(); + iPlayer->OpenStream(iRate, iChannels, iType); + + #ifdef DODUMP + User::LeaveIfError(iDump.Open()); + #endif + } + + + +TUint8* CEpocAudio::Buffer() + { + iStart.UniversalTime(); +// iStart = iPlayer->Position(); + return iAudioPtr; + + } + +CEpocAudio::~CEpocAudio() + { + if(iWait != NULL) + iWait->Cancel(); + delete iWait; + if(iPlayer != NULL) + iPlayer->Close(); + delete iPlayer; + delete iBuffer; + } + +void CEpocAudio::Complete(TInt aState, TInt aError) + { + if(aState == MStreamObs::EClose) + { + } + if(iPlayer->Closed()) + return; + switch(aError) + { + case KErrUnderflow: + case KErrInUse: + iPlayer->Start(); + break; + case KErrAbort: + iPlayer->Open(); + } + } + + +void sos_adump(SDL_AudioDevice* thisdevice, void* data, int len) + { +#ifdef DODUMP + const TPtrC8 buf((TUint8*)data, len); + CEpocAudio::Current(thisdevice).Dump(buf); +#endif + } + +const TInt KClip(256); + +TPtrC8 CEpocAudio::Data() + { + if(iPosition < 0) + return KNullDesC8(); + + TPtrC8 data(iAudioPtr + iPosition, KClip); + +#ifdef DODUMP + iDump.Dump(data); +#endif + + iPosition += KClip; + if(iPosition >= iBufferSize) + { + +/* if(iAudioPtr == iBuffer) + iAudioPtr = iBuffer + iBufferSize; + else + iAudioPtr = iBuffer; +*/ + iAudioPtr += iBufferSize; + + if((iAudioPtr - iBuffer) >= KAudioBuffers * iBufferSize) + iAudioPtr = iBuffer; + + iPosition = -1; + if(iWait->IsActive()) + { + iWait->Cancel(); + CActiveScheduler::Stop(); + } + } + return data; + } + + + + +void CEpocAudio::Play() + { + iPosition = 0; + } + +void CEpocAudio::Wait() + { + if(iPosition >= 0 /*&& iPlayer->Playing()*/) + { + const TInt64 bufMs = TInt64(iBufferSize - KClip) * TInt64(1000000); + const TInt64 specTime = bufMs / TInt64(iRate * iChannels * 2); + iWait->After(specTime); + + CActiveScheduler::Start(); + TTime end; + end.UniversalTime(); + const TTimeIntervalMicroSeconds delta = end.MicroSecondsFrom(iStart); + + +// const TTimeIntervalMicroSeconds end = iPlayer->Position(); + + + + + const TInt diff = specTime - delta.Int64(); + + if(diff > 0 && diff < 200000) + { + User::After(diff); + } + + } + else + { + User::After(10000); +// iWait->Wait(10000); //just give some time... + } + } + +void CEpocAudio::Open(TInt aRate, TInt aChannels, TUint32 aType, TInt aBytes) + { + iRate = aRate; + iChannels = aChannels; + iType = aType; + iBufferRate = iRate * iChannels * aBytes; //1/x + } + + +/* Audio driver bootstrap functions */ + +AudioBootStrap EPOCAudio_bootstrap = { + "epoc\0\0\0", + "EPOC streaming audio\0\0\0", + Audio_Available, + Audio_CreateDevice +}; + + +static SDL_AudioDevice *Audio_CreateDevice(int /*devindex*/) +{ + SDL_AudioDevice *thisdevice; + + /* Initialize all variables that we clean on shutdown */ + thisdevice = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); + if ( thisdevice ) { + memset(thisdevice, 0, (sizeof *thisdevice)); + thisdevice->hidden = NULL; /*(struct SDL_PrivateAudioData *) + malloc((sizeof thisdevice->hidden)); */ + } + if ( (thisdevice == NULL) /*|| (thisdevice->hidden == NULL) */) { + SDL_OutOfMemory(); + if ( thisdevice ) { + free(thisdevice); + } + return(0); + } +// memset(thisdevice->hidden, 0, (sizeof *thisdevice->hidden)); + + /* Set the function pointers */ + thisdevice->OpenAudio = EPOC_OpenAudio; + thisdevice->WaitAudio = EPOC_WaitAudio; + thisdevice->PlayAudio = EPOC_PlayAudio; + thisdevice->GetAudioBuf = EPOC_GetAudioBuf; + thisdevice->CloseAudio = EPOC_CloseAudio; + thisdevice->ThreadInit = EPOC_ThreadInit; + thisdevice->free = Audio_DeleteDevice; + + return thisdevice; +} + + +static void Audio_DeleteDevice(SDL_AudioDevice *device) + { + //free(device->hidden); + free(device); + } + +static int Audio_Available(void) +{ + return(1); // Audio stream modules should be always there! +} + + +static int EPOC_OpenAudio(SDL_AudioDevice *thisdevice, SDL_AudioSpec *spec) +{ + SDL_TRACE("SDL:EPOC_OpenAudio"); + + + TUint32 type = KMMFFourCCCodePCM16; + TInt bytes = 2; + + switch(spec->format) + { + case AUDIO_U16LSB: + type = KMMFFourCCCodePCMU16; + break; + case AUDIO_S16LSB: + type = KMMFFourCCCodePCM16; + break; + case AUDIO_U16MSB: + type = KMMFFourCCCodePCMU16B; + break; + case AUDIO_S16MSB: + type = KMMFFourCCCodePCM16B; + break; + //8 bit not supported! + case AUDIO_U8: + case AUDIO_S8: + default: + spec->format = AUDIO_S16LSB; + }; + + + + if(spec->channels > 2) + spec->channels = 2; + + spec->freq = CStreamPlayer::ClosestSupportedRate(spec->freq); + + + /* Allocate mixing buffer */ + const TInt buflen = spec->size;// * bytes * spec->channels; +// audiobuf = NULL; + + TRAPD(err, thisdevice->hidden = static_cast<SDL_PrivateAudioData*>(CEpocAudio::NewL(buflen, spec->silence))); + if(err != KErrNone) + return -1; + + CEpocAudio::Current(thisdevice).Open(spec->freq, spec->channels, type, bytes); + + CEpocAudio::Current(thisdevice).SetPause(ETrue); + + // isSDLAudioPaused = 1; + + thisdevice->enabled = 0; /* enable only after audio engine has been initialized!*/ + + /* We're ready to rock and roll. :-) */ + return(0); +} + + +static void EPOC_CloseAudio(SDL_AudioDevice* thisdevice) + { +#ifdef DEBUG_AUDIO + SDL_TRACE("Close audio\n"); +#endif + + CEpocAudio::Free(thisdevice); + } + + +static void EPOC_ThreadInit(SDL_AudioDevice *thisdevice) + { + SDL_TRACE("SDL:EPOC_ThreadInit"); + CEpocAudio::Current(thisdevice).ThreadInitL(thisdevice); + RThread().SetPriority(EPriorityMore); + thisdevice->enabled = 1; + } + +/* This function waits until it is possible to write a full sound buffer */ +static void EPOC_WaitAudio(SDL_AudioDevice* thisdevice) +{ +#ifdef DEBUG_AUDIO + SDL_TRACE1("wait %d audio\n", CEpocAudio::AudioLib().StreamPlayer(KSfxChannel).SyncTime()); + TInt tics = User::TickCount(); +#endif + + CEpocAudio::Current(thisdevice).Wait(); + +#ifdef DEBUG_AUDIO + TInt ntics = User::TickCount() - tics; + SDL_TRACE1("audio waited %d\n", ntics); + SDL_TRACE1("audio at %d\n", tics); +#endif +} + + + +static void EPOC_PlayAudio(SDL_AudioDevice* thisdevice) + { + if(CEpocAudio::Current(thisdevice).SetPause(SDL_GetAudioStatus() == SDL_AUDIO_PAUSED)) + SDL_Delay(500); //hold on the busy loop + else + CEpocAudio::Current(thisdevice).Play(); + +#ifdef DEBUG_AUDIO + SDL_TRACE("buffer has audio data\n"); +#endif + + +#ifdef DEBUG_AUDIO + SDL_TRACE1("Wrote %d bytes of audio data\n", buflen); +#endif +} + +static Uint8 *EPOC_GetAudioBuf(SDL_AudioDevice* thisdevice) + { + return CEpocAudio::Current(thisdevice).Buffer(); + } + + + diff --git a/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.h b/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.h new file mode 100644 index 0000000..5c95c86 --- /dev/null +++ b/3rdparty/SDL/src/audio/symbian/SDL_epocaudio.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_epocaudio.h,v 1.1.2.2 2001/02/10 07:20:03 hercules Exp $"; +#endif + +#ifndef _SDL_EPOCAUDIO_H +#define _SDL_EPOCAUDIO_H + +extern "C" { +#include "SDL_sysaudio.h" +} + + +#endif /* _SDL_EPOCAUDIO_H */ diff --git a/3rdparty/SDL/src/audio/symbian/streamplayer.cpp b/3rdparty/SDL/src/audio/symbian/streamplayer.cpp new file mode 100644 index 0000000..dd733a1 --- /dev/null +++ b/3rdparty/SDL/src/audio/symbian/streamplayer.cpp @@ -0,0 +1,279 @@ +#include "streamplayer.h" +#include<mda/common/audio.h> + + + +const TInt KMaxVolume(256); + +LOCAL_C TInt GetSampleRate(TInt aRate) + { + switch(aRate) + { + case 8000: return TMdaAudioDataSettings::ESampleRate8000Hz; + case 11025: return TMdaAudioDataSettings::ESampleRate11025Hz; + case 12000: return TMdaAudioDataSettings::ESampleRate12000Hz; + case 16000: return TMdaAudioDataSettings::ESampleRate16000Hz; + case 22050: return TMdaAudioDataSettings::ESampleRate22050Hz; + case 24000: return TMdaAudioDataSettings::ESampleRate24000Hz; + case 32000: return TMdaAudioDataSettings::ESampleRate32000Hz; + case 44100: return TMdaAudioDataSettings::ESampleRate44100Hz; + case 48000: return TMdaAudioDataSettings::ESampleRate48000Hz; + case 96000: return TMdaAudioDataSettings::ESampleRate96000Hz; + case 64000: return TMdaAudioDataSettings::ESampleRate64000Hz; + } + return KErrNotFound; + } + +LOCAL_C TInt GetChannels(TInt aChannels) + { + switch(aChannels) + { + case 1: return TMdaAudioDataSettings::EChannelsMono; + case 2: return TMdaAudioDataSettings::EChannelsStereo; + } + return KErrNotFound; + } + +TInt CStreamPlayer::ClosestSupportedRate(TInt aRate) + { + if(aRate > 96000) + return 96000; + TInt rate = aRate; + while(GetSampleRate(rate) == KErrNotFound) + { + ++rate; + } + return rate; + } + +CStreamPlayer::CStreamPlayer(MStreamProvider& aProvider, MStreamObs& aObs) : + iProvider(aProvider), iObs(aObs), iVolume(KMaxVolume) + { + } + +CStreamPlayer::~CStreamPlayer() + { + iState |= EDied; + if(iState & EInited) + Close(); + User::After(100000); //wait buffer to be flushed + ASSERT(iPtr.Length() == 0); + delete iStream; + } + + +void CStreamPlayer::ConstructL() + { + iStream = CMdaAudioOutputStream::NewL(*this, EMdaPriorityMax); + iSilence.SetMax(); + iSilence.FillZ(); + } + + +TInt CStreamPlayer::OpenStream(TInt aRate, TInt aChannels, TUint32 aType) + { + Close(); + + iType = aType; + + iRate = GetSampleRate(aRate); + if(iRate == KErrNotFound) + return KErrNotSupported; + + iChannels = GetChannels(aChannels); + if(iChannels == KErrNotFound) + return KErrNotSupported; + + Open(); + + return KErrNone; + } + + +TInt CStreamPlayer::MaxVolume() const + { + return KMaxVolume; + } + +void CStreamPlayer::SetVolume(TInt aNew) + { + + const TInt maxi = MaxVolume(); + if(aNew > maxi) + return; + if(aNew < 0) + return; + + iVolume = aNew; + + iState |= EVolumeChange; + } + + TInt CStreamPlayer::Volume() const + { + return iVolume; + } + +void CStreamPlayer::Open() + { + TMdaAudioDataSettings audioSettings; + audioSettings.Query(); + audioSettings.iCaps = TMdaAudioDataSettings::ERealTime | + TMdaAudioDataSettings::ESampleRateFixed; + audioSettings.iSampleRate = iRate; + audioSettings.iChannels = iChannels; + audioSettings.iFlags = TMdaAudioDataSettings::ENoNetworkRouting; + audioSettings.iVolume = 0; + + iState &= ~EStopped; + iStream->Open(&audioSettings); + } + +void CStreamPlayer::Stop() + { + if(iState & (EStarted | EInited)) + { + Close(); + iState |= EStopped; + } + } + +void CStreamPlayer::Start() + { + if(iPtr.Length() == 0) + { + iState |= EStarted; + if(iState & EInited) + { + Request(); + } + else if(iState & EStopped) + { + Open(); + } + } + } + +void CStreamPlayer::Close() + { + iState &= ~EInited; + iStream->Stop(); + iState &= ~EStarted; + } + +void CStreamPlayer::Request() + { + if(iState & EInited) + { + iPtr.Set(KNullDesC8); + + if(iState & EVolumeChange) + { + const TReal newVol = iVolume; + const TReal newMax = MaxVolume(); + const TInt maxVol = iStream->MaxVolume(); + const TReal max = static_cast<TReal>(maxVol); + const TReal newvolume = (newVol * max) / newMax; + const TInt vol = static_cast<TReal>(newvolume); + iStream->SetVolume(vol); + iState &= ~EVolumeChange; + } + + if(iState & EStarted) + { + iPtr.Set(iProvider.Data()); + } + if(iPtr.Length() == 0) + { + iPtr.Set(iSilence); + } + TRAPD(err, iStream->WriteL(iPtr)); + if(err != KErrNone) + { + iObs.Complete(MStreamObs::EWrite, err); + } + /* else + { + iProvider.Written(iPtr.Length()); + }*/ + } + } + + +void CStreamPlayer::SetCapsL() + { + iStream->SetDataTypeL(iType); + iStream->SetAudioPropertiesL(iRate, iChannels); + } + +void CStreamPlayer::MaoscOpenComplete(TInt aError) + { + if(aError == KErrNone) + { + TRAPD(err, SetCapsL()); + if(err == KErrNone) + { + iStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime); + iState |= EInited; + + + SetVolume(Volume()); + + if(iState & EStarted) + { + Request(); + } + + } + aError = err; + } + if(!(iState & EDied)) + iObs.Complete(MStreamObs::EInit, aError); + } + +void CStreamPlayer::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/) + { + iPtr.Set(KNullDesC8); + if(aError == KErrNone) + { + if(iState & EInited) + Request(); + else + iStream->Stop(); + } + else if(!(iState & EDied)) + iObs.Complete(MStreamObs::EPlay, aError); + } + +void CStreamPlayer::MaoscPlayComplete(TInt aError) + { + iPtr.Set(KNullDesC8); + iState &= ~EStarted; + if(!(iState & EDied)) + iObs.Complete(MStreamObs::EClose, aError); + } + +TBool CStreamPlayer::Playing() const + { + return (iState & EInited) && (iState & EStarted); + } + +TBool CStreamPlayer::Closed() const + { + return !(iState & EInited) && !(iState & EDied); + } + + /* +void CStreamPlayer::Request() + { + SetActive(); + TRequestStatus* s = &iStatus; + User::RequestComplete(s, KErrNone); + } + // iTimer.After(0); + */ + + + + + diff --git a/3rdparty/SDL/src/audio/symbian/streamplayer.h b/3rdparty/SDL/src/audio/symbian/streamplayer.h new file mode 100644 index 0000000..8c6e74f --- /dev/null +++ b/3rdparty/SDL/src/audio/symbian/streamplayer.h @@ -0,0 +1,89 @@ +#ifndef STREAMPLAYER_H +#define STREAMPLAYER_H + +#include<MdaAudioOutputStream.h> + +const TInt KSilenceBuffer = 256; + +class MStreamObs + { + public: + enum + { + EInit, + EPlay, + EWrite, + EClose, + }; + virtual void Complete(TInt aState, TInt aError) = 0; + }; + +class MStreamProvider + { + public: + virtual TPtrC8 Data() = 0; + }; + +NONSHARABLE_CLASS(CStreamPlayer) : public CBase, public MMdaAudioOutputStreamCallback + { + public: + CStreamPlayer(MStreamProvider& aProvider, MStreamObs& aObs); + ~CStreamPlayer(); + void ConstructL(); + + static TInt ClosestSupportedRate(TInt aRate); + + TInt OpenStream(TInt aRate, TInt aChannels, TUint32 aType = KMMFFourCCCodePCM16); + + void SetVolume(TInt aNew); + TInt Volume() const; + TInt MaxVolume() const; + + void Stop(); + void Start(); + void Open(); + void Close(); + + TBool Playing() const; + TBool Closed() const; + + private: + + void MaoscOpenComplete(TInt aError) ; + void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer); + void MaoscPlayComplete(TInt aError); + + private: + void Request(); + void SetCapsL(); + + private: + MStreamProvider& iProvider; + MStreamObs& iObs; + TInt iVolume; + + CMdaAudioOutputStream* iStream; + + TInt iRate; + TInt iChannels; + TUint32 iType; + + enum + { + ENone = 0, + EInited = 0x1, + EStarted = 0x2, + EStopped = 0x4, + EVolumeChange = 0x8, + EDied = 0x10 + }; + + TInt iState; + TBuf8<KSilenceBuffer> iSilence; + TPtrC8 iPtr; + + }; + + +#endif + diff --git a/3rdparty/SDL/src/audio/ums/SDL_umsaudio.c b/3rdparty/SDL/src/audio/ums/SDL_umsaudio.c new file mode 100644 index 0000000..9488911 --- /dev/null +++ b/3rdparty/SDL/src/audio/ums/SDL_umsaudio.c @@ -0,0 +1,547 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Carsten Griwodz + griff@kom.tu-darmstadt.de + + based on linux/SDL_dspaudio.c by Sam Lantinga +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "SDL_umsaudio.h" + +/* The tag name used by UMS audio */ +#define UMS_DRIVER_NAME "ums" + +#define DEBUG_AUDIO 1 + +/* Audio driver functions */ +static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void UMS_PlayAudio(_THIS); +static Uint8 *UMS_GetAudioBuf(_THIS); +static void UMS_CloseAudio(_THIS); + +static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags); +static UMSAudioDevice_ReturnCode UADClose(_THIS); +static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits); +static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits); +static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate); +static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order); +static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt); +static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt); +static UMSAudioDevice_ReturnCode UADInitialize(_THIS); +static UMSAudioDevice_ReturnCode UADStart(_THIS); +static UMSAudioDevice_ReturnCode UADStop(_THIS); +static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt ); +static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size ); +static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size ); +static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size ); +static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret ); +static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume ); +static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance ); +static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels ); +static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block ); +static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain); +static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff, long samples, long* samples_written); + +/* Audio driver bootstrap functions */ +static int Audio_Available(void) +{ + return 1; +} + +static void Audio_DeleteDevice(_THIS) +{ + if(this->hidden->playbuf._buffer) SDL_free(this->hidden->playbuf._buffer); + if(this->hidden->fillbuf._buffer) SDL_free(this->hidden->fillbuf._buffer); + _somFree( this->hidden->umsdev ); + SDL_free(this->hidden); + SDL_free(this); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* + * Allocate and initialize management storage and private management + * storage for this SDL-using library. + */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); +#ifdef DEBUG_AUDIO + fprintf(stderr, "Creating UMS Audio device\n"); +#endif + + /* + * Calls for UMS env initialization and audio object construction. + */ + this->hidden->ev = somGetGlobalEnvironment(); + this->hidden->umsdev = UMSAudioDeviceNew(); + + /* + * Set the function pointers. + */ + this->OpenAudio = UMS_OpenAudio; + this->WaitAudio = NULL; /* we do blocking output */ + this->PlayAudio = UMS_PlayAudio; + this->GetAudioBuf = UMS_GetAudioBuf; + this->CloseAudio = UMS_CloseAudio; + this->free = Audio_DeleteDevice; + +#ifdef DEBUG_AUDIO + fprintf(stderr, "done\n"); +#endif + return this; +} + +AudioBootStrap UMS_bootstrap = { + UMS_DRIVER_NAME, "AIX UMS audio", + Audio_Available, Audio_CreateDevice +}; + +static Uint8 *UMS_GetAudioBuf(_THIS) +{ +#ifdef DEBUG_AUDIO + fprintf(stderr, "enter UMS_GetAudioBuf\n"); +#endif + return this->hidden->fillbuf._buffer; +/* + long bufSize; + UMSAudioDevice_ReturnCode rc; + + rc = UADSetTimeFormat(this, UMSAudioTypes_Bytes ); + rc = UADWriteBuffSize(this, bufSize ); +*/ +} + +static void UMS_CloseAudio(_THIS) +{ + UMSAudioDevice_ReturnCode rc; + +#ifdef DEBUG_AUDIO + fprintf(stderr, "enter UMS_CloseAudio\n"); +#endif + rc = UADPlayRemainingData(this, TRUE); + rc = UADStop(this); + rc = UADClose(this); +} + +static void UMS_PlayAudio(_THIS) +{ + UMSAudioDevice_ReturnCode rc; + long samplesToWrite; + long samplesWritten; + UMSAudioTypes_Buffer swpbuf; + +#ifdef DEBUG_AUDIO + fprintf(stderr, "enter UMS_PlayAudio\n"); +#endif + samplesToWrite = this->hidden->playbuf._length/this->hidden->bytesPerSample; + do + { + rc = UADWrite(this, &this->hidden->playbuf, + samplesToWrite, + &samplesWritten ); + samplesToWrite -= samplesWritten; + + /* rc values: UMSAudioDevice_Success + * UMSAudioDevice_Failure + * UMSAudioDevice_Preempted + * UMSAudioDevice_Interrupted + * UMSAudioDevice_DeviceError + */ + if ( rc == UMSAudioDevice_DeviceError ) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Returning from PlayAudio with devices error\n"); +#endif + return; + } + } + while(samplesToWrite>0); + + SDL_LockAudio(); + SDL_memcpy( &swpbuf, &this->hidden->playbuf, sizeof(UMSAudioTypes_Buffer) ); + SDL_memcpy( &this->hidden->playbuf, &this->hidden->fillbuf, sizeof(UMSAudioTypes_Buffer) ); + SDL_memcpy( &this->hidden->fillbuf, &swpbuf, sizeof(UMSAudioTypes_Buffer) ); + SDL_UnlockAudio(); + +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote audio data and swapped buffer\n"); +#endif +} + +#if 0 +// /* Set the DSP frequency */ +// value = spec->freq; +// if ( ioctl(this->hidden->audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) { +// SDL_SetError("Couldn't set audio frequency"); +// return(-1); +// } +// spec->freq = value; +#endif + +static int UMS_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + char* audiodev = "/dev/paud0"; + long lgain; + long rgain; + long outRate; + long outBufSize; + long bitsPerSample; + long samplesPerSec; + long success; + Uint16 test_format; + int frag_spec; + UMSAudioDevice_ReturnCode rc; + +#ifdef DEBUG_AUDIO + fprintf(stderr, "enter UMS_OpenAudio\n"); +#endif + rc = UADOpen(this, audiodev,"PLAY", UMSAudioDevice_BlockingIO); + if ( rc != UMSAudioDevice_Success ) { + SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); + return -1; + } + + rc = UADSetAudioFormatType(this, "PCM"); + + success = 0; + test_format = SDL_FirstAudioFormat(spec->format); + do + { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + switch ( test_format ) + { + case AUDIO_U8: +/* from the mac code: better ? */ +/* sample_bits = spec->size / spec->samples / spec->channels * 8; */ + success = 1; + bitsPerSample = 8; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "MSB"); /* irrelevant */ + rc = UADSetNumberFormat(this, "UNSIGNED"); + break; + case AUDIO_S8: + success = 1; + bitsPerSample = 8; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "MSB"); /* irrelevant */ + rc = UADSetNumberFormat(this, "SIGNED"); + break; + case AUDIO_S16LSB: + success = 1; + bitsPerSample = 16; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "LSB"); + rc = UADSetNumberFormat(this, "SIGNED"); + break; + case AUDIO_S16MSB: + success = 1; + bitsPerSample = 16; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "MSB"); + rc = UADSetNumberFormat(this, "SIGNED"); + break; + case AUDIO_U16LSB: + success = 1; + bitsPerSample = 16; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "LSB"); + rc = UADSetNumberFormat(this, "UNSIGNED"); + break; + case AUDIO_U16MSB: + success = 1; + bitsPerSample = 16; + rc = UADSetSampleRate(this, spec->freq << 16, &outRate ); + rc = UADSetByteOrder(this, "MSB"); + rc = UADSetNumberFormat(this, "UNSIGNED"); + break; + default: + break; + } + if ( ! success ) { + test_format = SDL_NextAudioFormat(); + } + } + while ( ! success && test_format ); + + if ( success == 0 ) { + SDL_SetError("Couldn't find any hardware audio formats"); + return -1; + } + + spec->format = test_format; + + for ( frag_spec = 0; (0x01<<frag_spec) < spec->size; ++frag_spec ); + if ( (0x01<<frag_spec) != spec->size ) { + SDL_SetError("Fragment size must be a power of two"); + return -1; + } + if ( frag_spec > 2048 ) frag_spec = 2048; + + this->hidden->bytesPerSample = (bitsPerSample / 8) * spec->channels; + samplesPerSec = this->hidden->bytesPerSample * outRate; + + this->hidden->playbuf._length = 0; + this->hidden->playbuf._maximum = spec->size; + this->hidden->playbuf._buffer = (unsigned char*)SDL_malloc(spec->size); + this->hidden->fillbuf._length = 0; + this->hidden->fillbuf._maximum = spec->size; + this->hidden->fillbuf._buffer = (unsigned char*)SDL_malloc(spec->size); + + rc = UADSetBitsPerSample(this, bitsPerSample ); + rc = UADSetDMABufferSize(this, frag_spec, &outBufSize ); + rc = UADSetChannels(this, spec->channels); /* functions reduces to mono or stereo */ + + lgain = 100; /*maximum left input gain*/ + rgain = 100; /*maimum right input gain*/ + rc = UADEnableOutput(this, "LINE_OUT",&lgain,&rgain); + rc = UADInitialize(this); + rc = UADStart(this); + rc = UADSetVolume(this, 100); + rc = UADSetBalance(this, 0); + + /* We're ready to rock and roll. :-) */ + return 0; +} + + +static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long* bits) +{ + return UMSAudioDevice_get_bits_per_sample( this->hidden->umsdev, + this->hidden->ev, + bits ); +} + +static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits) +{ + return UMSAudioDevice_set_bits_per_sample( this->hidden->umsdev, + this->hidden->ev, + bits ); +} + +static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate, long* set_rate) +{ + /* from the mac code: sample rate = spec->freq << 16; */ + return UMSAudioDevice_set_sample_rate( this->hidden->umsdev, + this->hidden->ev, + rate, + set_rate ); +} + +static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order) +{ + return UMSAudioDevice_set_byte_order( this->hidden->umsdev, + this->hidden->ev, + byte_order ); +} + +static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt) +{ + /* possible PCM, A_LAW or MU_LAW */ + return UMSAudioDevice_set_audio_format_type( this->hidden->umsdev, + this->hidden->ev, + fmt ); +} + +static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt) +{ + /* possible SIGNED, UNSIGNED, or TWOS_COMPLEMENT */ + return UMSAudioDevice_set_number_format( this->hidden->umsdev, + this->hidden->ev, + fmt ); +} + +static UMSAudioDevice_ReturnCode UADInitialize(_THIS) +{ + return UMSAudioDevice_initialize( this->hidden->umsdev, + this->hidden->ev ); +} + +static UMSAudioDevice_ReturnCode UADStart(_THIS) +{ + return UMSAudioDevice_start( this->hidden->umsdev, + this->hidden->ev ); +} + +static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt ) +{ + /* + * Switches the time format to the new format, immediately. + * possible UMSAudioTypes_Msecs, UMSAudioTypes_Bytes or UMSAudioTypes_Samples + */ + return UMSAudioDevice_set_time_format( this->hidden->umsdev, + this->hidden->ev, + fmt ); +} + +static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long* buff_size ) +{ + /* + * returns write buffer size in the current time format + */ + return UMSAudioDevice_write_buff_size( this->hidden->umsdev, + this->hidden->ev, + buff_size ); +} + +static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long* buff_size ) +{ + /* + * returns amount of available space in the write buffer + * in the current time format + */ + return UMSAudioDevice_write_buff_remain( this->hidden->umsdev, + this->hidden->ev, + buff_size ); +} + +static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long* buff_size ) +{ + /* + * returns amount of filled space in the write buffer + * in the current time format + */ + return UMSAudioDevice_write_buff_used( this->hidden->umsdev, + this->hidden->ev, + buff_size ); +} + +static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes, long* bytes_ret ) +{ + /* + * Request a new DMA buffer size, maximum requested size 2048. + * Takes effect with next initialize() call. + * Devices may or may not support DMA. + */ + return UMSAudioDevice_set_DMA_buffer_size( this->hidden->umsdev, + this->hidden->ev, + bytes, + bytes_ret ); +} + +static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume ) +{ + /* + * Set the volume. + * Takes effect immediately. + */ + return UMSAudioDevice_set_volume( this->hidden->umsdev, + this->hidden->ev, + volume ); +} + +static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance ) +{ + /* + * Set the balance. + * Takes effect immediately. + */ + return UMSAudioDevice_set_balance( this->hidden->umsdev, + this->hidden->ev, + balance ); +} + +static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels ) +{ + /* + * Set mono or stereo. + * Takes effect with next initialize() call. + */ + if ( channels != 1 ) channels = 2; + return UMSAudioDevice_set_number_of_channels( this->hidden->umsdev, + this->hidden->ev, + channels ); +} + +static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode, long flags) +{ + return UMSAudioDevice_open( this->hidden->umsdev, + this->hidden->ev, + device, + mode, + flags ); +} + +static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer* buff, + long samples, + long* samples_written) +{ + return UMSAudioDevice_write( this->hidden->umsdev, + this->hidden->ev, + buff, + samples, + samples_written ); +} + +static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block ) +{ + return UMSAudioDevice_play_remaining_data( this->hidden->umsdev, + this->hidden->ev, + block); +} + +static UMSAudioDevice_ReturnCode UADStop(_THIS) +{ + return UMSAudioDevice_stop( this->hidden->umsdev, + this->hidden->ev ); +} + +static UMSAudioDevice_ReturnCode UADClose(_THIS) +{ + return UMSAudioDevice_close( this->hidden->umsdev, + this->hidden->ev ); +} + +static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output, long* left_gain, long* right_gain) +{ + return UMSAudioDevice_enable_output( this->hidden->umsdev, + this->hidden->ev, + output, + left_gain, + right_gain ); +} + diff --git a/3rdparty/SDL/src/audio/ums/SDL_umsaudio.h b/3rdparty/SDL/src/audio/ums/SDL_umsaudio.h new file mode 100644 index 0000000..367fe85 --- /dev/null +++ b/3rdparty/SDL/src/audio/ums/SDL_umsaudio.h @@ -0,0 +1,50 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Carsten Griwodz + griff@kom.tu-darmstadt.de + + based on linux/SDL_dspaudio.h by Sam Lantinga +*/ +#include "SDL_config.h" + +#ifndef _SDL_UMSaudio_h +#define _SDL_UMSaudio_h + +#include <UMS/UMSAudioDevice.h> + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +struct SDL_PrivateAudioData +{ + /* Pointer to the (open) UMS audio device */ + Environment* ev; + UMSAudioDevice umsdev; + + /* Raw mixing buffer */ + UMSAudioTypes_Buffer playbuf; + UMSAudioTypes_Buffer fillbuf; + + long bytesPerSample; +}; + +#endif /* _SDL_UMSaudio_h */ + diff --git a/3rdparty/SDL/src/audio/windib/SDL_dibaudio.c b/3rdparty/SDL/src/audio/windib/SDL_dibaudio.c new file mode 100644 index 0000000..51a9a4d --- /dev/null +++ b/3rdparty/SDL/src/audio/windib/SDL_dibaudio.c @@ -0,0 +1,322 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "SDL_dibaudio.h" +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) +#include "win_ce_semaphore.h" +#endif + + +/* Audio driver functions */ +static int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DIB_ThreadInit(_THIS); +static void DIB_WaitAudio(_THIS); +static Uint8 *DIB_GetAudioBuf(_THIS); +static void DIB_PlayAudio(_THIS); +static void DIB_WaitDone(_THIS); +static void DIB_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = DIB_OpenAudio; + this->ThreadInit = DIB_ThreadInit; + this->WaitAudio = DIB_WaitAudio; + this->PlayAudio = DIB_PlayAudio; + this->GetAudioBuf = DIB_GetAudioBuf; + this->WaitDone = DIB_WaitDone; + this->CloseAudio = DIB_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap WAVEOUT_bootstrap = { + "waveout", "Win95/98/NT/2000 WaveOut", + Audio_Available, Audio_CreateDevice +}; + + +/* The Win32 callback for filling the WAVE device */ +static void CALLBACK FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, + DWORD dwParam1, DWORD dwParam2) +{ + SDL_AudioDevice *this = (SDL_AudioDevice *)dwInstance; + + /* Only service "buffer done playing" messages */ + if ( uMsg != WOM_DONE ) + return; + + /* Signal that we are done playing a buffer */ +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + ReleaseSemaphoreCE(audio_sem, 1, NULL); +#else + ReleaseSemaphore(audio_sem, 1, NULL); +#endif +} + +static void SetMMerror(char *function, MMRESULT code) +{ + size_t len; + char errbuf[MAXERRORLENGTH]; +#ifdef _WIN32_WCE + wchar_t werrbuf[MAXERRORLENGTH]; +#endif + + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function); + len = SDL_strlen(errbuf); + +#ifdef _WIN32_WCE + /* UNICODE version */ + waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH-len); + WideCharToMultiByte(CP_ACP,0,werrbuf,-1,errbuf+len,MAXERRORLENGTH-len,NULL,NULL); +#else + waveOutGetErrorText(code, errbuf+len, (UINT)(MAXERRORLENGTH-len)); +#endif + + SDL_SetError("%s",errbuf); +} + +/* Set high priority for the audio thread */ +static void DIB_ThreadInit(_THIS) +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); +} + +void DIB_WaitAudio(_THIS) +{ + /* Wait for an audio chunk to finish */ +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + WaitForSemaphoreCE(audio_sem, INFINITE); +#else + WaitForSingleObject(audio_sem, INFINITE); +#endif +} + +Uint8 *DIB_GetAudioBuf(_THIS) +{ + Uint8 *retval; + + retval = (Uint8 *)(wavebuf[next_buffer].lpData); + return retval; +} + +void DIB_PlayAudio(_THIS) +{ + /* Queue it up */ + waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); + next_buffer = (next_buffer+1)%NUM_BUFFERS; +} + +void DIB_WaitDone(_THIS) +{ + int i, left; + + do { + left = NUM_BUFFERS; + for ( i=0; i<NUM_BUFFERS; ++i ) { + if ( wavebuf[i].dwFlags & WHDR_DONE ) { + --left; + } + } + if ( left > 0 ) { + SDL_Delay(100); + } + } while ( left > 0 ); +} + +void DIB_CloseAudio(_THIS) +{ + int i; + + /* Close up audio */ + if ( audio_sem ) { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + CloseSynchHandle(audio_sem); +#else + CloseHandle(audio_sem); +#endif + } + if ( sound ) { + waveOutClose(sound); + } + + /* Clean up mixing buffers */ + for ( i=0; i<NUM_BUFFERS; ++i ) { + if ( wavebuf[i].dwUser != 0xFFFF ) { + waveOutUnprepareHeader(sound, &wavebuf[i], + sizeof(wavebuf[i])); + wavebuf[i].dwUser = 0xFFFF; + } + } + /* Free raw mixing buffer */ + if ( mixbuf != NULL ) { + SDL_free(mixbuf); + mixbuf = NULL; + } +} + +int DIB_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + MMRESULT result; + int i; + WAVEFORMATEX waveformat; + + /* Initialize the wavebuf structures for closing */ + sound = NULL; + audio_sem = NULL; + for ( i = 0; i < NUM_BUFFERS; ++i ) + wavebuf[i].dwUser = 0xFFFF; + mixbuf = NULL; + + /* Set basic WAVE format parameters */ + SDL_memset(&waveformat, 0, sizeof(waveformat)); + waveformat.wFormatTag = WAVE_FORMAT_PCM; + + /* Determine the audio parameters from the AudioSpec */ + switch ( spec->format & 0xFF ) { + case 8: + /* Unsigned 8 bit audio data */ + spec->format = AUDIO_U8; + waveformat.wBitsPerSample = 8; + break; + case 16: + /* Signed 16 bit audio data */ + spec->format = AUDIO_S16; + waveformat.wBitsPerSample = 16; + break; + default: + SDL_SetError("Unsupported audio format"); + return(-1); + } + waveformat.nChannels = spec->channels; + waveformat.nSamplesPerSec = spec->freq; + waveformat.nBlockAlign = + waveformat.nChannels * (waveformat.wBitsPerSample/8); + waveformat.nAvgBytesPerSec = + waveformat.nSamplesPerSec * waveformat.nBlockAlign; + + /* Check the buffer size -- minimum of 1/4 second (word aligned) */ + if ( spec->samples < (spec->freq/4) ) + spec->samples = ((spec->freq/4)+3)&~3; + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Open the audio device */ + result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, + (DWORD_PTR)FillSound, (DWORD_PTR)this, CALLBACK_FUNCTION); + if ( result != MMSYSERR_NOERROR ) { + SetMMerror("waveOutOpen()", result); + return(-1); + } + +#ifdef SOUND_DEBUG + /* Check the sound device we retrieved */ + { + WAVEOUTCAPS caps; + + result = waveOutGetDevCaps((UINT)sound, &caps, sizeof(caps)); + if ( result != MMSYSERR_NOERROR ) { + SetMMerror("waveOutGetDevCaps()", result); + return(-1); + } + printf("Audio device: %s\n", caps.szPname); + } +#endif + + /* Create the audio buffer semaphore */ +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); +#else + audio_sem = CreateSemaphore(NULL, NUM_BUFFERS-1, NUM_BUFFERS, NULL); +#endif + if ( audio_sem == NULL ) { + SDL_SetError("Couldn't create semaphore"); + return(-1); + } + + /* Create the sound buffers */ + mixbuf = (Uint8 *)SDL_malloc(NUM_BUFFERS*spec->size); + if ( mixbuf == NULL ) { + SDL_SetError("Out of memory"); + return(-1); + } + for ( i = 0; i < NUM_BUFFERS; ++i ) { + SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); + wavebuf[i].lpData = (LPSTR) &mixbuf[i*spec->size]; + wavebuf[i].dwBufferLength = spec->size; + wavebuf[i].dwFlags = WHDR_DONE; + result = waveOutPrepareHeader(sound, &wavebuf[i], + sizeof(wavebuf[i])); + if ( result != MMSYSERR_NOERROR ) { + SetMMerror("waveOutPrepareHeader()", result); + return(-1); + } + } + + /* Ready to go! */ + next_buffer = 0; + return(0); +} diff --git a/3rdparty/SDL/src/audio/windib/SDL_dibaudio.h b/3rdparty/SDL/src/audio/windib/SDL_dibaudio.h new file mode 100644 index 0000000..d2c6228 --- /dev/null +++ b/3rdparty/SDL/src/audio/windib/SDL_dibaudio.h @@ -0,0 +1,49 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +#define NUM_BUFFERS 2 /* -- Don't lower this! */ + +struct SDL_PrivateAudioData { + HWAVEOUT sound; + HANDLE audio_sem; + Uint8 *mixbuf; /* The raw allocated mixing buffer */ + WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */ + int next_buffer; +}; + +/* Old variable names */ +#define sound (this->hidden->sound) +#define audio_sem (this->hidden->audio_sem) +#define mixbuf (this->hidden->mixbuf) +#define wavebuf (this->hidden->wavebuf) +#define next_buffer (this->hidden->next_buffer) + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.c b/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.c new file mode 100644 index 0000000..c3d42ae --- /dev/null +++ b/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.c @@ -0,0 +1,705 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Allow access to a raw mixing buffer */ + +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "../SDL_audio_c.h" +#include "SDL_dx5audio.h" + +/* Define this if you want to use DirectX 6 DirectSoundNotify interface */ +//#define USE_POSITION_NOTIFY + +/* DirectX function pointers for audio */ +HRESULT (WINAPI *DSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); + +/* Audio driver functions */ +static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void DX5_ThreadInit(_THIS); +static void DX5_WaitAudio_BusyWait(_THIS); +#ifdef USE_POSITION_NOTIFY +static void DX6_WaitAudio_EventWait(_THIS); +#endif +static void DX5_PlayAudio(_THIS); +static Uint8 *DX5_GetAudioBuf(_THIS); +static void DX5_WaitDone(_THIS); +static void DX5_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ + +static int Audio_Available(void) +{ + HINSTANCE DSoundDLL; + int dsound_ok; + + /* Version check DSOUND.DLL (Is DirectX okay?) */ + dsound_ok = 0; + DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); + if ( DSoundDLL != NULL ) { + /* We just use basic DirectSound, we're okay */ + /* Yay! */ + /* Unfortunately, the sound drivers on NT have + higher latencies than the audio buffers used + by many SDL applications, so there are gaps + in the audio - it sounds terrible. Punt for now. + */ + OSVERSIONINFO ver; + ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + GetVersionEx(&ver); + switch (ver.dwPlatformId) { + case VER_PLATFORM_WIN32_NT: + if ( ver.dwMajorVersion > 4 ) { + /* Win2K */ + dsound_ok = 1; + } else { + /* WinNT */ + dsound_ok = 0; + } + break; + default: + /* Win95 or Win98 */ + dsound_ok = 1; + break; + } + /* Now check for DirectX 5 or better - otherwise + * we will fail later in DX5_OpenAudio without a chance + * to fall back to the DIB driver. */ + if (dsound_ok) { + /* DirectSoundCaptureCreate was added in DX5 */ + if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) + dsound_ok = 0; + + } + /* Clean up.. */ + FreeLibrary(DSoundDLL); + } + return(dsound_ok); +} + +/* Functions for loading the DirectX functions dynamically */ +static HINSTANCE DSoundDLL = NULL; + +static void DX5_Unload(void) +{ + if ( DSoundDLL != NULL ) { + FreeLibrary(DSoundDLL); + DSoundCreate = NULL; + DSoundDLL = NULL; + } +} +static int DX5_Load(void) +{ + int status; + + DX5_Unload(); + DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); + if ( DSoundDLL != NULL ) { + DSoundCreate = (void *)GetProcAddress(DSoundDLL, + TEXT("DirectSoundCreate")); + } + if ( DSoundDLL && DSoundCreate ) { + status = 0; + } else { + DX5_Unload(); + status = -1; + } + return status; +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + DX5_Unload(); + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + + /* Load DirectX */ + if ( DX5_Load() < 0 ) { + return(NULL); + } + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* Set the function pointers */ + this->OpenAudio = DX5_OpenAudio; + this->ThreadInit = DX5_ThreadInit; + this->WaitAudio = DX5_WaitAudio_BusyWait; + this->PlayAudio = DX5_PlayAudio; + this->GetAudioBuf = DX5_GetAudioBuf; + this->WaitDone = DX5_WaitDone; + this->CloseAudio = DX5_CloseAudio; + + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap DSOUND_bootstrap = { + "dsound", "Win95/98/2000 DirectSound", + Audio_Available, Audio_CreateDevice +}; + +static void SetDSerror(const char *function, int code) +{ + static const char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case E_NOINTERFACE: + error = + "Unsupported interface\n-- Is DirectX 5.0 or later installed?"; + break; + case DSERR_ALLOCATED: + error = "Audio device in use"; + break; + case DSERR_BADFORMAT: + error = "Unsupported audio format"; + break; + case DSERR_BUFFERLOST: + error = "Mixing buffer was lost"; + break; + case DSERR_CONTROLUNAVAIL: + error = "Control requested is not available"; + break; + case DSERR_INVALIDCALL: + error = "Invalid call for the current state"; + break; + case DSERR_INVALIDPARAM: + error = "Invalid parameter"; + break; + case DSERR_NODRIVER: + error = "No audio device found"; + break; + case DSERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DSERR_PRIOLEVELNEEDED: + error = "Caller doesn't have priority"; + break; + case DSERR_UNSUPPORTED: + error = "Function not supported"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectSound error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + +/* DirectSound needs to be associated with a window */ +static HWND mainwin = NULL; +/* */ +void DX5_SoundFocus(HWND hwnd) +{ + mainwin = hwnd; +} + +static void DX5_ThreadInit(_THIS) +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); +} + +static void DX5_WaitAudio_BusyWait(_THIS) +{ + DWORD status; + DWORD cursor, junk; + HRESULT result; + + /* Semi-busy wait, since we have no way of getting play notification + on a primary mixing buffer located in hardware (DirectX 5.0) + */ + result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + if ( result != DS_OK ) { + if ( result == DSERR_BUFFERLOST ) { + IDirectSoundBuffer_Restore(mixbuf); + } +#ifdef DEBUG_SOUND + SetDSerror("DirectSound GetCurrentPosition", result); +#endif + return; + } + + while ( (cursor/mixlen) == lastchunk ) { + /* FIXME: find out how much time is left and sleep that long */ + SDL_Delay(1); + + /* Try to restore a lost sound buffer */ + IDirectSoundBuffer_GetStatus(mixbuf, &status); + if ( (status&DSBSTATUS_BUFFERLOST) ) { + IDirectSoundBuffer_Restore(mixbuf); + IDirectSoundBuffer_GetStatus(mixbuf, &status); + if ( (status&DSBSTATUS_BUFFERLOST) ) { + break; + } + } + if ( ! (status&DSBSTATUS_PLAYING) ) { + result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); + if ( result == DS_OK ) { + continue; + } +#ifdef DEBUG_SOUND + SetDSerror("DirectSound Play", result); +#endif + return; + } + + /* Find out where we are playing */ + result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + &junk, &cursor); + if ( result != DS_OK ) { + SetDSerror("DirectSound GetCurrentPosition", result); + return; + } + } +} + +#ifdef USE_POSITION_NOTIFY +static void DX6_WaitAudio_EventWait(_THIS) +{ + DWORD status; + HRESULT result; + + /* Try to restore a lost sound buffer */ + IDirectSoundBuffer_GetStatus(mixbuf, &status); + if ( (status&DSBSTATUS_BUFFERLOST) ) { + IDirectSoundBuffer_Restore(mixbuf); + IDirectSoundBuffer_GetStatus(mixbuf, &status); + if ( (status&DSBSTATUS_BUFFERLOST) ) { + return; + } + } + if ( ! (status&DSBSTATUS_PLAYING) ) { + result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound Play", result); +#endif + return; + } + } + WaitForSingleObject(audio_event, INFINITE); +} +#endif /* USE_POSITION_NOTIFY */ + +static void DX5_PlayAudio(_THIS) +{ + /* Unlock the buffer, allowing it to play */ + if ( locked_buf ) { + IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); + } + +} + +static Uint8 *DX5_GetAudioBuf(_THIS) +{ + DWORD cursor, junk; + HRESULT result; + DWORD rawlen; + + /* Figure out which blocks to fill next */ + locked_buf = NULL; + result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + if ( result == DSERR_BUFFERLOST ) { + IDirectSoundBuffer_Restore(mixbuf); + result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + &junk, &cursor); + } + if ( result != DS_OK ) { + SetDSerror("DirectSound GetCurrentPosition", result); + return(NULL); + } + cursor /= mixlen; +#ifdef DEBUG_SOUND + /* Detect audio dropouts */ + { DWORD spot = cursor; + if ( spot < lastchunk ) { + spot += NUM_BUFFERS; + } + if ( spot > lastchunk+1 ) { + fprintf(stderr, "Audio dropout, missed %d fragments\n", + (spot - (lastchunk+1))); + } + } +#endif + lastchunk = cursor; + cursor = (cursor+1)%NUM_BUFFERS; + cursor *= mixlen; + + /* Lock the audio buffer */ + result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, + (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); + if ( result == DSERR_BUFFERLOST ) { + IDirectSoundBuffer_Restore(mixbuf); + result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, + (LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0); + } + if ( result != DS_OK ) { + SetDSerror("DirectSound Lock", result); + return(NULL); + } + return(locked_buf); +} + +static void DX5_WaitDone(_THIS) +{ + Uint8 *stream; + + /* Wait for the playing chunk to finish */ + stream = this->GetAudioBuf(this); + if ( stream != NULL ) { + SDL_memset(stream, silence, mixlen); + this->PlayAudio(this); + } + this->WaitAudio(this); + + /* Stop the looping sound buffer */ + IDirectSoundBuffer_Stop(mixbuf); +} + +static void DX5_CloseAudio(_THIS) +{ + if ( sound != NULL ) { + if ( mixbuf != NULL ) { + /* Clean up the audio buffer */ + IDirectSoundBuffer_Release(mixbuf); + mixbuf = NULL; + } + if ( audio_event != NULL ) { + CloseHandle(audio_event); + audio_event = NULL; + } + IDirectSound_Release(sound); + sound = NULL; + } +} + +#ifdef USE_PRIMARY_BUFFER +/* This function tries to create a primary audio buffer, and returns the + number of audio chunks available in the created buffer. +*/ +static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, + LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) +{ + HRESULT result; + DSBUFFERDESC format; + DSBCAPS caps; + int numchunks; + + /* Try to set primary mixing privileges */ + result = IDirectSound_SetCooperativeLevel(sndObj, focus, + DSSCL_WRITEPRIMARY); + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound SetCooperativeLevel", result); +#endif + return(-1); + } + + /* Try to create the primary buffer */ + SDL_memset(&format, 0, sizeof(format)); + format.dwSize = sizeof(format); + format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); + format.dwFlags |= DSBCAPS_STICKYFOCUS; +#ifdef USE_POSITION_NOTIFY + format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; +#endif + result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound CreateSoundBuffer", result); +#endif + return(-1); + } + + /* Check the size of the fragment buffer */ + SDL_memset(&caps, 0, sizeof(caps)); + caps.dwSize = sizeof(caps); + result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound GetCaps", result); +#endif + IDirectSoundBuffer_Release(*sndbuf); + return(-1); + } + if ( (chunksize > caps.dwBufferBytes) || + ((caps.dwBufferBytes%chunksize) != 0) ) { + /* The primary buffer size is not a multiple of 'chunksize' + -- this hopefully doesn't happen when 'chunksize' is a + power of 2. + */ + IDirectSoundBuffer_Release(*sndbuf); + SDL_SetError( +"Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", + caps.dwBufferBytes, chunksize); + return(-1); + } + numchunks = (caps.dwBufferBytes/chunksize); + + /* Set the primary audio format */ + result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound SetFormat", result); +#endif + IDirectSoundBuffer_Release(*sndbuf); + return(-1); + } + return(numchunks); +} +#endif /* USE_PRIMARY_BUFFER */ + +/* This function tries to create a secondary audio buffer, and returns the + number of audio chunks available in the created buffer. +*/ +static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, + LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) +{ + const int numchunks = 8; + HRESULT result; + DSBUFFERDESC format; + LPVOID pvAudioPtr1, pvAudioPtr2; + DWORD dwAudioBytes1, dwAudioBytes2; + + /* Try to set primary mixing privileges */ + if ( focus ) { + result = IDirectSound_SetCooperativeLevel(sndObj, + focus, DSSCL_PRIORITY); + } else { + result = IDirectSound_SetCooperativeLevel(sndObj, + GetDesktopWindow(), DSSCL_NORMAL); + } + if ( result != DS_OK ) { +#ifdef DEBUG_SOUND + SetDSerror("DirectSound SetCooperativeLevel", result); +#endif + return(-1); + } + + /* Try to create the secondary buffer */ + SDL_memset(&format, 0, sizeof(format)); + format.dwSize = sizeof(format); + format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; +#ifdef USE_POSITION_NOTIFY + format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; +#endif + if ( ! focus ) { + format.dwFlags |= DSBCAPS_GLOBALFOCUS; + } else { + format.dwFlags |= DSBCAPS_STICKYFOCUS; + } + format.dwBufferBytes = numchunks*chunksize; + if ( (format.dwBufferBytes < DSBSIZE_MIN) || + (format.dwBufferBytes > DSBSIZE_MAX) ) { + SDL_SetError("Sound buffer size must be between %d and %d", + DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks); + return(-1); + } + format.dwReserved = 0; + format.lpwfxFormat = wavefmt; + result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); + if ( result != DS_OK ) { + SetDSerror("DirectSound CreateSoundBuffer", result); + return(-1); + } + IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); + + /* Silence the initial audio buffer */ + result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes, + (LPVOID *)&pvAudioPtr1, &dwAudioBytes1, + (LPVOID *)&pvAudioPtr2, &dwAudioBytes2, + DSBLOCK_ENTIREBUFFER); + if ( result == DS_OK ) { + if ( wavefmt->wBitsPerSample == 8 ) { + SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1); + } else { + SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1); + } + IDirectSoundBuffer_Unlock(*sndbuf, + (LPVOID)pvAudioPtr1, dwAudioBytes1, + (LPVOID)pvAudioPtr2, dwAudioBytes2); + } + + /* We're ready to go */ + return(numchunks); +} + +/* This function tries to set position notify events on the mixing buffer */ +#ifdef USE_POSITION_NOTIFY +static int CreateAudioEvent(_THIS) +{ + LPDIRECTSOUNDNOTIFY notify; + DSBPOSITIONNOTIFY *notify_positions; + int i, retval; + HRESULT result; + + /* Default to fail on exit */ + retval = -1; + notify = NULL; + + /* Query for the interface */ + result = IDirectSoundBuffer_QueryInterface(mixbuf, + &IID_IDirectSoundNotify, (void *)¬ify); + if ( result != DS_OK ) { + goto done; + } + + /* Allocate the notify structures */ + notify_positions = (DSBPOSITIONNOTIFY *)SDL_malloc(NUM_BUFFERS* + sizeof(*notify_positions)); + if ( notify_positions == NULL ) { + goto done; + } + + /* Create the notify event */ + audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if ( audio_event == NULL ) { + goto done; + } + + /* Set up the notify structures */ + for ( i=0; i<NUM_BUFFERS; ++i ) { + notify_positions[i].dwOffset = i*mixlen; + notify_positions[i].hEventNotify = audio_event; + } + result = IDirectSoundNotify_SetNotificationPositions(notify, + NUM_BUFFERS, notify_positions); + if ( result == DS_OK ) { + retval = 0; + } +done: + if ( notify != NULL ) { + IDirectSoundNotify_Release(notify); + } + return(retval); +} +#endif /* USE_POSITION_NOTIFY */ + +static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + HRESULT result; + WAVEFORMATEX waveformat; + + /* Set basic WAVE format parameters */ + SDL_memset(&waveformat, 0, sizeof(waveformat)); + waveformat.wFormatTag = WAVE_FORMAT_PCM; + + /* Determine the audio parameters from the AudioSpec */ + switch ( spec->format & 0xFF ) { + case 8: + /* Unsigned 8 bit audio data */ + spec->format = AUDIO_U8; + silence = 0x80; + waveformat.wBitsPerSample = 8; + break; + case 16: + /* Signed 16 bit audio data */ + spec->format = AUDIO_S16; + silence = 0x00; + waveformat.wBitsPerSample = 16; + break; + default: + SDL_SetError("Unsupported audio format"); + return(-1); + } + waveformat.nChannels = spec->channels; + waveformat.nSamplesPerSec = spec->freq; + waveformat.nBlockAlign = + waveformat.nChannels * (waveformat.wBitsPerSample/8); + waveformat.nAvgBytesPerSec = + waveformat.nSamplesPerSec * waveformat.nBlockAlign; + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Open the audio device */ + result = DSoundCreate(NULL, &sound, NULL); + if ( result != DS_OK ) { + SetDSerror("DirectSoundCreate", result); + return(-1); + } + + /* Create the audio buffer to which we write */ + NUM_BUFFERS = -1; +#ifdef USE_PRIMARY_BUFFER + if ( mainwin ) { + NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, + &waveformat, spec->size); + } +#endif /* USE_PRIMARY_BUFFER */ + if ( NUM_BUFFERS < 0 ) { + NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, + &waveformat, spec->size); + if ( NUM_BUFFERS < 0 ) { + return(-1); + } +#ifdef DEBUG_SOUND + fprintf(stderr, "Using secondary audio buffer\n"); +#endif + } +#ifdef DEBUG_SOUND + else + fprintf(stderr, "Using primary audio buffer\n"); +#endif + + /* The buffer will auto-start playing in DX5_WaitAudio() */ + lastchunk = 0; + mixlen = spec->size; + +#ifdef USE_POSITION_NOTIFY + /* See if we can use DirectX 6 event notification */ + if ( CreateAudioEvent(this) == 0 ) { + this->WaitAudio = DX6_WaitAudio_EventWait; + } else { + this->WaitAudio = DX5_WaitAudio_BusyWait; + } +#endif + return(0); +} + diff --git a/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.h b/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.h new file mode 100644 index 0000000..bc4022f --- /dev/null +++ b/3rdparty/SDL/src/audio/windx5/SDL_dx5audio.h @@ -0,0 +1,55 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h + +#include "directx.h" + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this + +/* The DirectSound objects */ +struct SDL_PrivateAudioData { + LPDIRECTSOUND sound; + LPDIRECTSOUNDBUFFER mixbuf; + int NUM_BUFFERS; + int mixlen, silence; + DWORD lastchunk; + Uint8 *locked_buf; + HANDLE audio_event; +}; + +/* Old variable names */ +#define sound (this->hidden->sound) +#define mixbuf (this->hidden->mixbuf) +#define NUM_BUFFERS (this->hidden->NUM_BUFFERS) +#define mixlen (this->hidden->mixlen) +#define silence (this->hidden->silence) +#define lastchunk (this->hidden->lastchunk) +#define locked_buf (this->hidden->locked_buf) +#define audio_event (this->hidden->audio_event) + +#endif /* _SDL_lowaudio_h */ diff --git a/3rdparty/SDL/src/audio/windx5/directx.h b/3rdparty/SDL/src/audio/windx5/directx.h new file mode 100644 index 0000000..5f339f2 --- /dev/null +++ b/3rdparty/SDL/src/audio/windx5/directx.h @@ -0,0 +1,81 @@ + +#ifndef _directx_h +#define _directx_h + +/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> +#ifndef WIN32 +#define WIN32 +#endif +#undef WINNT + +/* Far pointers don't exist in 32-bit code */ +#ifndef FAR +#define FAR +#endif + +/* Error codes not yet included in Win32 API header files */ +#ifndef MAKE_HRESULT +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code)))) +#endif + +#ifndef S_OK +#define S_OK (HRESULT)0x00000000L +#endif + +#ifndef SUCCEEDED +#define SUCCEEDED(x) ((HRESULT)(x) >= 0) +#endif +#ifndef FAILED +#define FAILED(x) ((HRESULT)(x)<0) +#endif + +#ifndef E_FAIL +#define E_FAIL (HRESULT)0x80000008L +#endif +#ifndef E_NOINTERFACE +#define E_NOINTERFACE (HRESULT)0x80004002L +#endif +#ifndef E_OUTOFMEMORY +#define E_OUTOFMEMORY (HRESULT)0x8007000EL +#endif +#ifndef E_INVALIDARG +#define E_INVALIDARG (HRESULT)0x80070057L +#endif +#ifndef E_NOTIMPL +#define E_NOTIMPL (HRESULT)0x80004001L +#endif +#ifndef REGDB_E_CLASSNOTREG +#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L +#endif + +/* Severity codes */ +#ifndef SEVERITY_ERROR +#define SEVERITY_ERROR 1 +#endif + +/* Error facility codes */ +#ifndef FACILITY_WIN32 +#define FACILITY_WIN32 7 +#endif + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) +#endif + +/* DirectX headers (if it isn't included, I haven't tested it yet) + */ +/* We need these defines to mark what version of DirectX API we use */ +#define DIRECTDRAW_VERSION 0x0700 +#define DIRECTSOUND_VERSION 0x0500 +#define DIRECTINPUT_VERSION 0x0500 + +#include <ddraw.h> +#include <dsound.h> +#include <dinput.h> + +#endif /* _directx_h */ diff --git a/3rdparty/SDL/src/cdrom/SDL_cdrom.c b/3rdparty/SDL/src/cdrom/SDL_cdrom.c new file mode 100644 index 0000000..8f91bb1 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/SDL_cdrom.c @@ -0,0 +1,341 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the CD-audio control API for Simple DirectMedia Layer */ + +#include "SDL_cdrom.h" +#include "SDL_syscdrom.h" + +#if !defined(__MACOS__) +#define CLIP_FRAMES 10 /* Some CD-ROMs won't go all the way */ +#endif + +static int SDL_cdinitted = 0; +static SDL_CD *default_cdrom; + +/* The system level CD-ROM control functions */ +struct CDcaps SDL_CDcaps = { + NULL, /* Name */ + NULL, /* Open */ + NULL, /* GetTOC */ + NULL, /* Status */ + NULL, /* Play */ + NULL, /* Pause */ + NULL, /* Resume */ + NULL, /* Stop */ + NULL, /* Eject */ + NULL, /* Close */ +}; +int SDL_numcds; + +int SDL_CDROMInit(void) +{ + int retval; + + SDL_numcds = 0; + retval = SDL_SYS_CDInit(); + if ( retval == 0 ) { + SDL_cdinitted = 1; + } + default_cdrom = NULL; + return(retval); +} + +/* Check to see if the CD-ROM subsystem has been initialized */ +static int CheckInit(int check_cdrom, SDL_CD **cdrom) +{ + int okay; + + okay = SDL_cdinitted; + if ( check_cdrom && (*cdrom == NULL) ) { + *cdrom = default_cdrom; + if ( *cdrom == NULL ) { + SDL_SetError("CD-ROM not opened"); + okay = 0; + } + } + if ( ! SDL_cdinitted ) { + SDL_SetError("CD-ROM subsystem not initialized"); + } + return(okay); +} + +int SDL_CDNumDrives(void) +{ + if ( ! CheckInit(0, NULL) ) { + return(-1); + } + return(SDL_numcds); +} + +const char *SDL_CDName(int drive) +{ + if ( ! CheckInit(0, NULL) ) { + return(NULL); + } + if ( drive >= SDL_numcds ) { + SDL_SetError("Invalid CD-ROM drive index"); + return(NULL); + } + if ( SDL_CDcaps.Name ) { + return(SDL_CDcaps.Name(drive)); + } else { + return(""); + } +} + +SDL_CD *SDL_CDOpen(int drive) +{ + struct SDL_CD *cdrom; + + if ( ! CheckInit(0, NULL) ) { + return(NULL); + } + if ( drive >= SDL_numcds ) { + SDL_SetError("Invalid CD-ROM drive index"); + return(NULL); + } + cdrom = (SDL_CD *)SDL_malloc(sizeof(*cdrom)); + if ( cdrom == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cdrom, 0, sizeof(*cdrom)); + cdrom->id = SDL_CDcaps.Open(drive); + if ( cdrom->id < 0 ) { + SDL_free(cdrom); + return(NULL); + } + default_cdrom = cdrom; + return(cdrom); +} + +CDstatus SDL_CDStatus(SDL_CD *cdrom) +{ + CDstatus status; + int i; + Uint32 position; + + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + /* Get the current status of the drive */ + cdrom->numtracks = 0; + cdrom->cur_track = 0; + cdrom->cur_frame = 0; + status = SDL_CDcaps.Status(cdrom, &i); + position = (Uint32)i; + cdrom->status = status; + + /* Get the table of contents, if there's a CD available */ + if ( CD_INDRIVE(status) ) { + if ( SDL_CDcaps.GetTOC(cdrom) < 0 ) { + status = CD_ERROR; + } + /* If the drive is playing, get current play position */ + if ( (status == CD_PLAYING) || (status == CD_PAUSED) ) { + for ( i=1; cdrom->track[i].offset <= position; ++i ) { + /* Keep looking */; + } +#ifdef DEBUG_CDROM + fprintf(stderr, "Current position: %d, track = %d (offset is %d)\n", + position, i-1, cdrom->track[i-1].offset); +#endif + cdrom->cur_track = i-1; + position -= cdrom->track[cdrom->cur_track].offset; + cdrom->cur_frame = position; + } + } + return(status); +} + +int SDL_CDPlayTracks(SDL_CD *cdrom, + int strack, int sframe, int ntracks, int nframes) +{ + int etrack, eframe; + int start, length; + + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + /* Determine the starting and ending tracks */ + if ( (strack < 0) || (strack >= cdrom->numtracks) ) { + SDL_SetError("Invalid starting track"); + return(CD_ERROR); + } + if ( ! ntracks && ! nframes ) { + etrack = cdrom->numtracks; + eframe = 0; + } else { + etrack = strack+ntracks; + if ( etrack == strack ) { + eframe = sframe + nframes; + } else { + eframe = nframes; + } + } + if ( etrack > cdrom->numtracks ) { + SDL_SetError("Invalid play length"); + return(CD_ERROR); + } + + /* Skip data tracks and verify frame offsets */ + while ( (strack <= etrack) && + (cdrom->track[strack].type == SDL_DATA_TRACK) ) { + ++strack; + } + if ( sframe >= (int)cdrom->track[strack].length ) { + SDL_SetError("Invalid starting frame for track %d", strack); + return(CD_ERROR); + } + while ( (etrack > strack) && + (cdrom->track[etrack-1].type == SDL_DATA_TRACK) ) { + --etrack; + } + if ( eframe > (int)cdrom->track[etrack].length ) { + SDL_SetError("Invalid ending frame for track %d", etrack); + return(CD_ERROR); + } + + /* Determine start frame and play length */ + start = (cdrom->track[strack].offset+sframe); + length = (cdrom->track[etrack].offset+eframe)-start; +#ifdef CLIP_FRAMES + /* I've never seen this necessary, but xmcd does it.. */ + length -= CLIP_FRAMES; /* CLIP_FRAMES == 10 */ +#endif + if ( length < 0 ) { + return(0); + } + + /* Play! */ +#ifdef DEBUG_CDROM + fprintf(stderr, "Playing %d frames at offset %d\n", length, start); +#endif + return(SDL_CDcaps.Play(cdrom, start, length)); +} + +int SDL_CDPlay(SDL_CD *cdrom, int sframe, int length) +{ + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + return(SDL_CDcaps.Play(cdrom, sframe, length)); +} + +int SDL_CDPause(SDL_CD *cdrom) +{ + CDstatus status; + int retval; + + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + status = SDL_CDcaps.Status(cdrom, NULL); + switch (status) { + case CD_PLAYING: + retval = SDL_CDcaps.Pause(cdrom); + break; + default: + retval = 0; + break; + } + return(retval); +} + +int SDL_CDResume(SDL_CD *cdrom) +{ + CDstatus status; + int retval; + + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + status = SDL_CDcaps.Status(cdrom, NULL); + switch (status) { + case CD_PAUSED: + retval = SDL_CDcaps.Resume(cdrom); + default: + retval = 0; + break; + } + return(retval); +} + +int SDL_CDStop(SDL_CD *cdrom) +{ + CDstatus status; + int retval; + + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + + status = SDL_CDcaps.Status(cdrom, NULL); + switch (status) { + case CD_PLAYING: + case CD_PAUSED: + retval = SDL_CDcaps.Stop(cdrom); + default: + retval = 0; + break; + } + return(retval); +} + +int SDL_CDEject(SDL_CD *cdrom) +{ + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return(CD_ERROR); + } + return(SDL_CDcaps.Eject(cdrom)); +} + +void SDL_CDClose(SDL_CD *cdrom) +{ + /* Check if the CD-ROM subsystem has been initialized */ + if ( ! CheckInit(1, &cdrom) ) { + return; + } + SDL_CDcaps.Close(cdrom); + SDL_free(cdrom); + default_cdrom = NULL; +} + +void SDL_CDROMQuit(void) +{ + SDL_SYS_CDQuit(); + SDL_cdinitted = 0; +} diff --git a/3rdparty/SDL/src/cdrom/SDL_syscdrom.h b/3rdparty/SDL/src/cdrom/SDL_syscdrom.h new file mode 100644 index 0000000..0feeee5 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/SDL_syscdrom.h @@ -0,0 +1,76 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is SDL_free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the system specific header for the SDL CD-ROM API */ + +/* Structure of CD audio control functions */ +extern struct CDcaps { + /* Get the name of the specified drive */ + const char *(*Name)(int drive); + + /* Open the specified drive, returning a drive id, or -1 on error */ + int (*Open)(int drive); + + /* Get table-of-contents (number of tracks + track info) for disk. + The TOC information should be stored in the cdrom structure. + This function should return 0 on success, or -1 on error. + */ + int (*GetTOC)(SDL_CD *cdrom); + + /* Return the current status and play position, in frames, of the + drive. 'position' may be NULL, and if so, should be ignored. + */ + CDstatus (*Status)(SDL_CD *cdrom, int *position); + + /* Play from frame 'start' to 'start+len' */ + int (*Play)(SDL_CD *cdrom, int start, int len); + + /* Pause play */ + int (*Pause)(SDL_CD *cdrom); + + /* Resume play */ + int (*Resume)(SDL_CD *cdrom); + + /* Stop play */ + int (*Stop)(SDL_CD *cdrom); + + /* Eject the current disk */ + int (*Eject)(SDL_CD *cdrom); + + /* Close the specified drive */ + void (*Close)(SDL_CD *cdrom); +} SDL_CDcaps; + +/* The number of available CD-ROM drives on the system */ +extern int SDL_numcds; + +/* Function to scan the system for CD-ROM drives and fill SDL_CDcaps. + * This function should set SDL_numcds to the number of available CD + * drives. Drive 0 should be the system default CD-ROM. + * It should return 0, or -1 on an unrecoverable fatal error. +*/ +extern int SDL_SYS_CDInit(void); + +/* Function to perform any system-specific CD-ROM related cleanup */ +extern void SDL_SYS_CDQuit(void); + diff --git a/3rdparty/SDL/src/cdrom/aix/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/aix/SDL_syscdrom.c new file mode 100644 index 0000000..e7e0558 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/aix/SDL_syscdrom.c @@ -0,0 +1,660 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Carsten Griwodz + griff@kom.tu-darmstadt.de + + based on linux/SDL_syscdrom.c by Sam Lantinga +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_AIX + +/* Functions for system-level CD-ROM audio control */ + +/*#define DEBUG_CDROM 1*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <sys/ioctl.h> +#include <sys/devinfo.h> +#include <sys/mntctl.h> +#include <sys/statfs.h> +#include <sys/vmount.h> +#include <fstab.h> +#include <sys/scdisk.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); +static int SDL_SYS_CDioctl(int id, int command, void *arg); + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd; + int cdfd; + int ret; + struct devinfo info; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return -1; + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { + cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + ret = SDL_SYS_CDioctl( cdfd, IOCINFO, &info ); + if ( ret < 0 ) { + /* Some kind of error */ + is_cd = 0; + } else { + if ( info.devtype == DD_CDROM ) { + is_cd = 1; + } else { + is_cd = 0; + } + } + close(cdfd); + } +#ifdef DEBUG_CDROM + else + { + fprintf(stderr, "Could not open drive %s (%s)\n", drive, strerror(errno)); + } +#endif + } + return is_cd; +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +static void CheckMounts() +{ + char* buffer; + int bufsz; + struct vmount* ptr; + int ret; + + buffer = (char*)SDL_malloc(10); + bufsz = 10; + if ( buffer==NULL ) + { + fprintf(stderr, "Could not allocate 10 bytes in aix/SDL_syscdrom.c:CheckMounts\n" ); + exit ( -10 ); + } + + do + { + /* mntctrl() returns an array of all mounted filesystems */ + ret = mntctl ( MCTL_QUERY, bufsz, buffer ); + if ( ret == 0 ) + { + /* Buffer was too small, realloc. */ + bufsz = *(int*)buffer; /* Required size is in first word. */ + /* (whatever a word is in AIX 4.3.3) */ + /* int seems to be OK in 32bit mode. */ + SDL_free(buffer); + buffer = (char*)SDL_malloc(bufsz); + if ( buffer==NULL ) + { + fprintf(stderr, + "Could not allocate %d bytes in aix/SDL_syscdrom.c:CheckMounts\n", + bufsz ); + exit ( -10 ); + } + } + else if ( ret < 0 ) + { +#ifdef DEBUG_CDROM + fprintf(stderr, "Error reading vmount structures\n"); +#endif + return; + } + } + while ( ret == 0 ); + +#ifdef DEBUG_CDROM + fprintf ( stderr, "Read %d vmount structures\n",ret ); +#endif + ptr = (struct vmount*)buffer; + do + { + switch(ptr->vmt_gfstype) + { + case MNT_CDROM : + { + struct stat stbuf; + char* text; + + text = (char*)ptr + ptr->vmt_data[VMT_OBJECT].vmt_off; +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking mount path: %s mounted on %s\n", + text, (char*)ptr + ptr->vmt_data[VMT_STUB].vmt_off ); +#endif + if ( CheckDrive( text, &stbuf) > 0) + { + AddDrive( text, &stbuf); + } + } + break; + default : + break; + } + ptr = (struct vmount*)((char*)ptr + ptr->vmt_length); + ret--; + } + while ( ret > 0 ); + + free ( buffer ); +} + +static int CheckNonmounts() +{ +#ifdef _THREAD_SAFE + AFILE_t fsFile = NULL; + int passNo = 0; + int ret; + struct fstab entry; + struct stat stbuf; + + ret = setfsent_r( &fsFile, &passNo ); + if ( ret != 0 ) return -1; + do + { + ret = getfsent_r ( &entry, &fsFile, &passNo ); + if ( ret == 0 ) { + char* l = SDL_strrchr(entry.fs_spec,'/'); + if ( l != NULL ) { + if ( !SDL_strncmp("cd",++l,2) ) { +#ifdef DEBUG_CDROM + fprintf(stderr, + "Found unmounted CD ROM drive with device name %s\n", + entry.fs_spec); +#endif + if ( CheckDrive( entry.fs_spec, &stbuf) > 0) + { + AddDrive( entry.fs_spec, &stbuf); + } + } + } + } + } + while ( ret == 0 ); + ret = endfsent_r ( &fsFile ); + if ( ret != 0 ) return -1; + return 0; +#else + struct fstab* entry; + struct stat stbuf; + + setfsent(); + do + { + entry = getfsent(); + if ( entry != NULL ) { + char* l = SDL_strrchr(entry->fs_spec,'/'); + if ( l != NULL ) { + if ( !SDL_strncmp("cd",++l,2) ) { +#ifdef DEBUG_CDROM + fprintf(stderr,"Found unmounted CD ROM drive with device name %s", entry->fs_spec); +#endif + if ( CheckDrive( entry->fs_spec, &stbuf) > 0) + { + AddDrive( entry->fs_spec, &stbuf); + } + } + } + } + } + while ( entry != NULL ); + endfsent(); +#endif +} + +int SDL_SYS_CDInit(void) +{ + char *SDLcdrom; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom); +#endif + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + + CheckMounts(); + CheckNonmounts(); + + return 0; +} + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int id, int command, void *arg) +{ + int retval; + + retval = ioctl(id, command, arg); + if ( retval < 0 ) { + SDL_SetError("ioctl() error: %s", strerror(errno)); + } + return retval; +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + int fd; + char* lastsl; + char* cdromname; + size_t len; + + /* + * We found /dev/cd? drives and that is in our list. But we can + * open only the /dev/rcd? versions of those devices for Audio CD. + */ + len = SDL_strlen(SDL_cdlist[drive])+2; + cdromname = (char*)SDL_malloc(len); + SDL_strlcpy(cdromname,SDL_cdlist[drive],len); + lastsl = SDL_strrchr(cdromname,'/'); + if (lastsl) { + *lastsl = 0; + SDL_strlcat(cdromname,"/r",len); + lastsl = SDL_strrchr(SDL_cdlist[drive],'/'); + if (lastsl) { + lastsl++; + SDL_strlcat(cdromname,lastsl,len); + } + } + +#ifdef DEBUG_CDROM + fprintf(stderr, "Should open drive %s, opening %s\n", SDL_cdlist[drive], cdromname); +#endif + + /* + * Use exclusive access. Don't use SC_DIAGNOSTICS as xmcd does because they + * require root priviledges, and we don't want that. SC_SINGLE provides + * exclusive access with less trouble. + */ + fd = openx(cdromname, O_RDONLY, NULL, SC_SINGLE); + if ( fd < 0 ) + { +#ifdef DEBUG_CDROM + fprintf(stderr, "Could not open drive %s (%s)\n", cdromname, strerror(errno)); +#endif + } + else + { + struct mode_form_op cdMode; + int ret; +#ifdef DEBUG_CDROM + cdMode.action = CD_GET_MODE; + ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode); + if ( ret < 0 ) { + fprintf(stderr, + "Could not get drive mode for %s (%s)\n", + cdromname, strerror(errno)); + } else { + switch(cdMode.cd_mode_form) { + case CD_MODE1 : + fprintf(stderr, + "Drive mode for %s is %s\n", + cdromname, "CD-ROM Data Mode 1"); + break; + case CD_MODE2_FORM1 : + fprintf(stderr, + "Drive mode for %s is %s\n", + cdromname, "CD-ROM XA Data Mode 2 Form 1"); + break; + case CD_MODE2_FORM2 : + fprintf(stderr, + "Drive mode for %s is %s\n", + cdromname, "CD-ROM XA Data Mode 2 Form 2"); + break; + case CD_DA : + fprintf(stderr, + "Drive mode for %s is %s\n", + cdromname, "CD-DA"); + break; + default : + fprintf(stderr, + "Drive mode for %s is %s\n", + cdromname, "unknown"); + break; + } + } +#endif + + cdMode.action = CD_CHG_MODE; + cdMode.cd_mode_form = CD_DA; + ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode); + if ( ret < 0 ) { +#ifdef DEBUG_CDROM + fprintf(stderr, + "Could not set drive mode for %s (%s)\n", + cdromname, strerror(errno)); +#endif + SDL_SetError("ioctl() error: Could not set CD drive mode, %s", + strerror(errno)); + } else { +#ifdef DEBUG_CDROM + fprintf(stderr, + "Drive mode for %s set to CD_DA\n", + cdromname); +#endif + } + } + SDL_free(cdromname); + return fd; +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + struct cd_audio_cmd cmd; + struct cd_audio_cmd entry; + int i; + int okay; + + cmd.audio_cmds = CD_TRK_INFO_AUDIO; + cmd.msf_flag = FALSE; + if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) { + return -1; + } + + okay = 0; + cdrom->numtracks = cmd.indexing.track_index.last_track + - cmd.indexing.track_index.first_track+1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + + /* Read all the track TOC entries */ + for ( i=0; i<=cdrom->numtracks; ++i ) { + if ( i == cdrom->numtracks ) { + cdrom->track[i].id = 0xAA;; + } else { + cdrom->track[i].id = cmd.indexing.track_index.first_track+i; + } + entry.audio_cmds = CD_GET_TRK_MSF; + entry.indexing.track_msf.track = cdrom->track[i].id; + if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &entry) < 0 ) { + break; + } else { + cdrom->track[i].type = 0; /* don't know how to detect 0x04 data track */ + cdrom->track[i].offset = MSF_TO_FRAMES( + entry.indexing.track_msf.mins, + entry.indexing.track_msf.secs, + entry.indexing.track_msf.frames); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = cdrom->track[i].offset + - cdrom->track[i-1].offset; + } + } + } + if ( i == (cdrom->numtracks+1) ) { + okay = 1; + } + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct cd_audio_cmd cmd; + cmd.audio_cmds = CD_INFO_AUDIO; + + if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "ioctl failed in SDL_SYS_CDStatus (%s)\n", SDL_GetError()); +#endif + status = CD_ERROR; + } else { + switch (cmd.status) { + case CD_NO_AUDIO: + case CD_COMPLETED: + status = CD_STOPPED; + break; + case CD_PLAY_AUDIO: + status = CD_PLAYING; + break; + case CD_PAUSE_AUDIO: + status = CD_PAUSED; + break; + case CD_NOT_VALID: +#ifdef DEBUG_CDROM + fprintf(stderr, "cdStatus failed with CD_NOT_VALID\n"); +#endif + status = CD_ERROR; + break; + case CD_STATUS_ERROR: +#ifdef DEBUG_CDROM + fprintf(stderr, "cdStatus failed with CD_STATUS_ERROR\n"); +#endif + status = CD_ERROR; + break; + default: +#ifdef DEBUG_CDROM + fprintf(stderr, "cdStatus failed with unknown error\n"); +#endif + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = MSF_TO_FRAMES( cmd.indexing.info_audio.current_mins, + cmd.indexing.info_audio.current_secs, + cmd.indexing.info_audio.current_frames); + } else { + *position = 0; + } + } + return status; +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + struct cd_audio_cmd cmd; + + /* + * My CD Rom is muted by default. I think I read that this is new with + * AIX 4.3. SDL does not change the volume, so I need a kludge. Maybe + * its better to do this elsewhere? + */ + cmd.audio_cmds = CD_PLAY_AUDIO | CD_SET_VOLUME; + cmd.msf_flag = TRUE; + FRAMES_TO_MSF(start, + &cmd.indexing.msf.first_mins, + &cmd.indexing.msf.first_secs, + &cmd.indexing.msf.first_frames); + FRAMES_TO_MSF(start+length, + &cmd.indexing.msf.last_mins, + &cmd.indexing.msf.last_secs, + &cmd.indexing.msf.last_frames); + cmd.volume_type = CD_VOLUME_ALL; + cmd.all_channel_vol = 255; /* This is a uchar. What is a good value? No docu! */ + cmd.out_port_0_sel = CD_AUDIO_CHNL_0; + cmd.out_port_1_sel = CD_AUDIO_CHNL_1; + cmd.out_port_2_sel = CD_AUDIO_CHNL_2; + cmd.out_port_3_sel = CD_AUDIO_CHNL_3; + +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + cmd.indexing.msf.first_mins, + cmd.indexing.msf.first_secs, + cmd.indexing.msf.first_frames, + cmd.indexing.msf.last_mins, + cmd.indexing.msf.last_secs, + cmd.indexing.msf.last_frames); +#endif + return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + struct cd_audio_cmd cmd; + cmd.audio_cmds = CD_PAUSE_AUDIO; + return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + struct cd_audio_cmd cmd; + cmd.audio_cmds = CD_RESUME_AUDIO; + return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + struct cd_audio_cmd cmd; + cmd.audio_cmds = CD_STOP_AUDIO; + return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, DKEJECT, 0)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_AIX */ diff --git a/3rdparty/SDL/src/cdrom/beos/SDL_syscdrom.cc b/3rdparty/SDL/src/cdrom/beos/SDL_syscdrom.cc new file mode 100644 index 0000000..9a62c38 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/beos/SDL_syscdrom.cc @@ -0,0 +1,410 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_BEOS + +/* Functions for system-level CD-ROM audio control on BeOS + (not completely implemented yet) + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <scsi.h> +#include <Directory.h> +#include <Entry.h> +#include <Path.h> + +#include "SDL_cdrom.h" +extern "C" { +#include "../SDL_syscdrom.h" +} + +/* Constants to help us get at the SCSI table-of-contents info */ +#define CD_NUMTRACKS(toc) toc.toc_data[3] +#define CD_TRACK(toc, track) (&toc.toc_data[6+(track)*8]) +#define CD_TRACK_N(toc, track) CD_TRACK(toc, track)[0] +#define CD_TRACK_M(toc, track) CD_TRACK(toc, track)[3] +#define CD_TRACK_S(toc, track) CD_TRACK(toc, track)[4] +#define CD_TRACK_F(toc, track) CD_TRACK(toc, track)[5] + +/* Constants to help us get at the SCSI position info */ +#define POS_TRACK(pos) pos.position[6] +#define POS_ABS_M(pos) pos.position[9] +#define POS_ABS_S(pos) pos.position[10] +#define POS_ABS_F(pos) pos.position[11] +#define POS_REL_M(pos) pos.position[13] +#define POS_REL_S(pos) pos.position[14] +#define POS_REL_F(pos) pos.position[15] + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); +int try_dir(const char *directory); + + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive) +{ + struct stat stbuf; + int is_cd, cdfd; + device_geometry info; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, &stbuf) < 0 ) { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + cdfd = open(drive, 0); + if ( cdfd >= 0 ) { + if ( ioctl(cdfd, B_GET_GEOMETRY, &info) == B_NO_ERROR ) { + if ( info.device_type == B_CD ) { + is_cd = 1; + } + } + close(cdfd); + } else { + /* This can happen when the drive is open .. (?) */; + is_cd = 1; + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive) +{ + int i; + size_t len; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Add this drive to our list */ + i = SDL_numcds; + len = SDL_strlen(drive)+1; + SDL_cdlist[i] = (char *)SDL_malloc(len); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_strlcpy(SDL_cdlist[i], drive, len); + ++SDL_numcds; +#ifdef CDROM_DEBUG + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +/* IDE bus scanning magic */ +enum { + IDE_GET_DEVICES_INFO = B_DEVICE_OP_CODES_END + 50, +}; +struct ide_ctrl_info { + bool ide_0_present; + bool ide_0_master_present; + bool ide_0_slave_present; + int ide_0_master_type; + int ide_0_slave_type; + bool ide_1_present; + bool ide_1_master_present; + bool ide_1_slave_present; + int ide_1_master_type; + int ide_1_slave_type; +}; + +int SDL_SYS_CDInit(void) +{ + char *SDLcdrom; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom) > 0 ) { + AddDrive(SDLcdrom); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + + /* Scan the system for CD-ROM drives */ + try_dir("/dev/disk"); + return 0; +} + + +int try_dir(const char *directory) +{ + BDirectory dir; + dir.SetTo(directory); + if(dir.InitCheck() != B_NO_ERROR) { + return false; + } + dir.Rewind(); + BEntry entry; + while(dir.GetNextEntry(&entry) >= 0) { + BPath path; + const char *name; + entry_ref e; + + if(entry.GetPath(&path) != B_NO_ERROR) + continue; + name = path.Path(); + + if(entry.GetRef(&e) != B_NO_ERROR) + continue; + + if(entry.IsDirectory()) { + if(SDL_strcmp(e.name, "floppy") == 0) + continue; /* ignore floppy (it is not silent) */ + int devfd = try_dir(name); + if(devfd >= 0) + return devfd; + } + else { + int devfd; + device_geometry g; + + if(SDL_strcmp(e.name, "raw") != 0) + continue; /* ignore partitions */ + + devfd = open(name, O_RDONLY); + if(devfd < 0) + continue; + + if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) { + if(g.device_type == B_CD) + { + AddDrive(strdup(name)); + } + } + close(devfd); + } + } + return B_ERROR; +} + + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int index, int command, void *arg) +{ + int okay; + int fd; + + okay = 0; + fd = open(SDL_cdlist[index], 0); + if ( fd >= 0 ) { + if ( ioctl(fd, command, arg) == B_NO_ERROR ) { + okay = 1; + } + close(fd); + } + return(okay ? 0 : -1); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(drive); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + int i; + scsi_toc toc; + + if ( SDL_SYS_CDioctl(cdrom->id, B_SCSI_GET_TOC, &toc) == 0 ) { + cdrom->numtracks = CD_NUMTRACKS(toc); + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + for ( i=0; i<=cdrom->numtracks; ++i ) { + cdrom->track[i].id = CD_TRACK_N(toc, i); + /* FIXME: How do we tell on BeOS? */ + cdrom->track[i].type = SDL_AUDIO_TRACK; + cdrom->track[i].offset = MSF_TO_FRAMES( + CD_TRACK_M(toc, i), + CD_TRACK_S(toc, i), + CD_TRACK_F(toc, i)); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = + cdrom->track[i].offset- + cdrom->track[i-1].offset; + } + } + return(0); + } else { + return(-1); + } +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + int fd; + int cur_frame; + scsi_position pos; + + fd = open(SDL_cdlist[cdrom->id], 0); + cur_frame = 0; + if ( fd >= 0 ) { + if ( ioctl(fd, B_SCSI_GET_POSITION, &pos) == B_NO_ERROR ) { + cur_frame = MSF_TO_FRAMES( + POS_ABS_M(pos), POS_ABS_S(pos), POS_ABS_F(pos)); + } + if ( ! pos.position[1] || (pos.position[1] >= 0x13) || + ((pos.position[1] == 0x12) && (!pos.position[6])) ) { + status = CD_STOPPED; + } else + if ( pos.position[1] == 0x11 ) { + status = CD_PLAYING; + } else { + status = CD_PAUSED; + } + close(fd); + } else { + status = CD_TRAYEMPTY; + } + if ( position ) { + *position = cur_frame; + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + int okay; + int fd; + scsi_play_position pos; + + okay = 0; + fd = open(SDL_cdlist[cdrom->id], 0); + if ( fd >= 0 ) { + FRAMES_TO_MSF(start, &pos.start_m, &pos.start_s, &pos.start_f); + FRAMES_TO_MSF(start+length, &pos.end_m, &pos.end_s, &pos.end_f); + if ( ioctl(fd, B_SCSI_PLAY_POSITION, &pos) == B_NO_ERROR ) { + okay = 1; + } + close(fd); + } + return(okay ? 0 : -1); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_PAUSE_AUDIO, 0)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_RESUME_AUDIO, 0)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_STOP_AUDIO, 0)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_EJECT, 0)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_BEOS */ diff --git a/3rdparty/SDL/src/cdrom/bsdi/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/bsdi/SDL_syscdrom.c new file mode 100644 index 0000000..61edb81 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/bsdi/SDL_syscdrom.c @@ -0,0 +1,542 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_BSDI + +/* + * Functions for system-level CD-ROM audio control for BSD/OS 4.x + * This started life out as a copy of the freebsd/SDL_cdrom.c file but was + * heavily modified. Works for standard (MMC) SCSI and ATAPI CDrom drives. + * + * Steven Schultz - sms@to.gd-es.com +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <err.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include </sys/dev/scsi/scsi.h> +#include </sys/dev/scsi/scsi_ioctl.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* + * The msf_to_frame and frame_to_msf were yanked from libcdrom and inlined + * here so that -lcdrom doesn't have to be dragged in for something so simple. +*/ + +#define FRAMES_PER_SECOND 75 +#define FRAMES_PER_MINUTE (FRAMES_PER_SECOND * 60) + +int +msf_to_frame(int minute, int second, int frame) + { + return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame); + } + +void +frame_to_msf(int frame, int *minp, int *secp, int *framep) + { + *minp = frame / FRAMES_PER_MINUTE; + *secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND; + *framep = frame % FRAMES_PER_SECOND; + } + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +typedef struct scsi_cdb cdb_t; + +static int scsi_cmd(int fd, + struct scsi_cdb *cdb, + int cdblen, + int rw, + caddr_t data, + int datalen, + struct scsi_user_cdb *sus) + { + int scsistatus; + unsigned char *cp; + struct scsi_user_cdb suc; + + /* safety checks */ + if (!cdb) return(-1); + if (rw != SUC_READ && rw != SUC_WRITE) return(-1); + + suc.suc_flags = rw; + suc.suc_cdblen = cdblen; + bcopy(cdb, suc.suc_cdb, cdblen); + suc.suc_datalen = datalen; + suc.suc_data = data; + suc.suc_timeout = 10; /* 10 secs max for TUR or SENSE */ + if (ioctl(fd, SCSIRAWCDB, &suc) == -1) + return(-11); + scsistatus = suc.suc_sus.sus_status; + cp = suc.suc_sus.sus_sense; + +/* + * If a place to copy the sense data back to has been provided then the + * caller is responsible for checking the errors and printing any information + * out if the status was not successful. +*/ + if (scsistatus != 0 && !sus) + { + fprintf(stderr,"scsistatus = %x cmd = %x\n", + scsistatus, cdb[0]); + fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", + cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], + cp[6], cp[7], cp[8], cp[9], cp[10], cp[11], + cp[12], cp[13], cp[14], cp[15]); + return(1); + } + if (sus) + bcopy(&suc, sus, sizeof (struct scsi_user_cdb)); + if (scsistatus) + return(1); /* Return non-zero for unsuccessful status */ + return(0); + } + +/* request vendor brand and model */ +unsigned char *Inquiry(int fd) + { + static struct scsi_cdb6 cdb = + { + 0x12, + 0, 0, 0, + 56, + 0 + }; + static unsigned char Inqbuffer[56]; + + if (scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer, + sizeof(Inqbuffer), 0)) + return("\377"); + return(Inqbuffer); + } + +#define ADD_SENSECODE 12 +#define ADD_SC_QUALIFIER 13 + +int TestForMedium(int fd) + { + int sts, asc, ascq; + struct scsi_user_cdb sus; + static struct scsi_cdb6 cdb = + { + CMD_TEST_UNIT_READY, /* command */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0 /* reserved */ + }; + +again: sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus); + asc = sus.suc_sus.sus_sense[ADD_SENSECODE]; + ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER]; + if (asc == 0x3a && ascq == 0x0) /* no medium */ + return(0); + if (asc == 0x28 && ascq == 0x0) /* medium changed */ + goto again; + if (asc == 0x4 && ascq == 0x1 ) /* coming ready */ + { + sleep(2); + goto again; + } + return(1); + } + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd = 0, cdfd; + char *p; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + p = Inquiry(cdfd); + if (*p == TYPE_ROM) + is_cd = 1; + close(cdfd); + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +int SDL_SYS_CDInit(void) +{ + /* checklist: /dev/rsr?c */ + static char *checklist[] = { + "?0 rsr?", NULL + }; + char *SDLcdrom; + int i, j, exists; + char drive[32]; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + + /* Scan the system for CD-ROM drives */ + for ( i=0; checklist[i]; ++i ) { + if ( checklist[i][0] == '?' ) { + char *insert; + exists = 1; + for ( j=checklist[i][1]; exists; ++j ) { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]); + insert = SDL_strchr(drive, '?'); + if ( insert != NULL ) { + *insert = j; + } + switch (CheckDrive(drive, &stbuf)) { + /* Drive exists and is a CD-ROM */ + case 1: + AddDrive(drive, &stbuf); + break; + /* Drive exists, but isn't a CD-ROM */ + case 0: + break; + /* Drive doesn't exist */ + case -1: + exists = 0; + break; + } + } + } else { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); + if ( CheckDrive(drive, &stbuf) > 0 ) { + AddDrive(drive, &stbuf); + } + } + } + return(0); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0)); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) + { + u_char cdb[10], buf[4], *p, *toc; + struct scsi_user_cdb sus; + int i, sts, first_track, last_track, ntracks, toc_size; + + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x43; /* Read TOC */ + cdb[1] = 0x2; /* MSF */ + cdb[8] = 4; /* size TOC header */ + sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus); + if (sts < 0) + return(-1); + first_track = buf[2]; + last_track = buf[3]; + ntracks = last_track - first_track + 1; + cdrom->numtracks = ntracks; + toc_size = 4 + (ntracks + 1) * 8; + toc = (u_char *)SDL_malloc(toc_size); + if (toc == NULL) + return(-1); + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x43; + cdb[1] = 0x2; + cdb[6] = first_track; + cdb[7] = toc_size >> 8; + cdb[8] = toc_size & 0xff; + sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size, + &sus); + if (sts < 0) + { + SDL_free(toc); + return(-1); + } + + for (i = 0, p = toc+4; i <= ntracks; i++, p+= 8) + { + if (i == ntracks) + cdrom->track[i].id = 0xAA; /* Leadout */ + else + cdrom->track[i].id = first_track + i; + if (p[1] & 0x20) + cdrom->track[i].type = SDL_DATA_TRACK; + else + cdrom->track[i].type = SDL_AUDIO_TRACK; + cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]); + cdrom->track[i].length = 0; + if (i > 0) + cdrom->track[i-1].length = cdrom->track[i].offset - + cdrom->track[i-1].offset; + } + SDL_free(toc); + return(0); + } + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) + { + CDstatus status; + u_char cdb[10], buf[16]; + int sts; + struct scsi_user_cdb sus; + + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x42; /* read subq */ + cdb[1] = 0x2; /* MSF */ + cdb[2] = 0x40; /* q channel */ + cdb[3] = 1; /* current pos */ + cdb[7] = sizeof (buf) >> 8; + cdb[8] = sizeof (buf) & 0xff; + sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf), + &sus); + if (sts < 0) + return(-1); + if (sts) + { + if (TestForMedium(cdrom->id) == 0) + status = CD_TRAYEMPTY; + else + status = CD_ERROR; + } + else + { + switch (buf[1]) + { + case 0x11: + status = CD_PLAYING; + break; + case 0x12: + status = CD_PAUSED; + break; + case 0x13: + case 0x14: + case 0x15: + status = CD_STOPPED; + break; + default: + status = CD_ERROR; + break; + } + } + if (position) + { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) + *position = msf_to_frame(buf[9], buf[10], buf[11]); + else + *position = 0; + } + return(status); + } + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) + { + u_char cdb[10]; + int sts, minute, second, frame, eminute, esecond, eframe; + struct scsi_user_cdb sus; + + bzero(cdb, sizeof(cdb)); + cdb[0] = 0x47; /* Play */ + frame_to_msf(start, &minute, &second, &frame); + frame_to_msf(start + length, &eminute, &esecond, &eframe); + cdb[3] = minute; + cdb[4] = second; + cdb[5] = frame; + cdb[6] = eminute; + cdb[7] = esecond; + cdb[8] = eframe; + sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus); + return(sts); + } + +static int +pauseresume(SDL_CD *cdrom, int flag) + { + u_char cdb[10]; + struct scsi_user_cdb sus; + + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x4b; + cdb[8] = flag & 0x1; + return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus)); + } + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(pauseresume(cdrom, 0)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(pauseresume(cdrom, 1)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + u_char cdb[6]; + struct scsi_user_cdb sus; + + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x1b; /* stop */ + cdb[1] = 1; /* immediate */ + return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + u_char cdb[6]; + struct scsi_user_cdb sus; + + bzero(cdb, sizeof (cdb)); + cdb[0] = 0x1b; /* stop */ + cdb[1] = 1; /* immediate */ + cdb[4] = 2; /* eject */ + return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) + { + close(cdrom->id); + } + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + } + SDL_numcds = 0; +} + +#endif /* SDL_CDROM_BSDI */ diff --git a/3rdparty/SDL/src/cdrom/dc/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/dc/SDL_syscdrom.c new file mode 100644 index 0000000..445ad7c --- /dev/null +++ b/3rdparty/SDL/src/cdrom/dc/SDL_syscdrom.c @@ -0,0 +1,167 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_DC + +/* Functions for system-level CD-ROM audio control */ + +#include <dc/cdrom.h> +#include <dc/spu.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + + +int SDL_SYS_CDInit(void) +{ + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + return(0); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return "/cd"; +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(drive); +} + +#define TRACK_CDDA 0 +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + CDROM_TOC toc; + int ret,i; + + ret = cdrom_read_toc(&toc,0); + if (ret!=ERR_OK) { + return -1; + } + + cdrom->numtracks = TOC_TRACK(toc.last)-TOC_TRACK(toc.first)+1; + for(i=0;i<cdrom->numtracks;i++) { + unsigned long entry = toc.entry[i]; + cdrom->track[i].id = i+1; + cdrom->track[i].type = (TOC_CTRL(toc.entry[i])==TRACK_CDDA)?SDL_AUDIO_TRACK:SDL_DATA_TRACK; + cdrom->track[i].offset = TOC_LBA(entry)-150; + cdrom->track[i].length = TOC_LBA((i+1<toc.last)?toc.entry[i+1]:toc.leadout_sector)-TOC_LBA(entry); + } + + return 0; +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + int ret,dc_status,disc_type; + + ret = cdrom_get_status(&dc_status,&disc_type); + if (ret!=ERR_OK) return CD_ERROR; + + switch(dc_status) { +// case CD_STATUS_BUSY: + case CD_STATUS_PAUSED: + return CD_PAUSED; + case CD_STATUS_STANDBY: + return CD_STOPPED; + case CD_STATUS_PLAYING: + return CD_PLAYING; +// case CD_STATUS_SEEKING: +// case CD_STATUS_SCANING: + case CD_STATUS_OPEN: + case CD_STATUS_NO_DISC: + return CD_TRAYEMPTY; + default: + return CD_ERROR; + } +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + int ret = cdrom_cdda_play(start-150,start-150+length,1,CDDA_SECTORS); + return ret==ERR_OK?0:-1; +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + int ret=cdrom_cdda_pause(); + return ret==ERR_OK?0:-1; +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + int ret=cdrom_cdda_resume(); + return ret==ERR_OK?0:-1; +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + int ret=cdrom_spin_down(); + return ret==ERR_OK?0:-1; +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return -1; +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ +} + +void SDL_SYS_CDQuit(void) +{ + +} + +#endif /* SDL_CDROM_DC */ diff --git a/3rdparty/SDL/src/cdrom/dummy/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/dummy/SDL_syscdrom.c new file mode 100644 index 0000000..9821e97 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/dummy/SDL_syscdrom.c @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(SDL_CDROM_DUMMY) || defined(SDL_CDROM_DISABLED) + +/* Stub functions for system-level CD-ROM audio control */ + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +int SDL_SYS_CDInit(void) +{ + return(0); +} + +void SDL_SYS_CDQuit(void) +{ + return; +} + +#endif /* SDL_CDROM_DUMMY || SDL_CDROM_DISABLED */ diff --git a/3rdparty/SDL/src/cdrom/freebsd/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/freebsd/SDL_syscdrom.c new file mode 100644 index 0000000..0260c94 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/freebsd/SDL_syscdrom.c @@ -0,0 +1,406 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_FREEBSD + +/* Functions for system-level CD-ROM audio control */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/cdio.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* Some ioctl() errno values which occur when the tray is empty */ +#define ERRNO_TRAYEMPTY(errno) \ + ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL)) + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd, cdfd; + struct ioc_read_subchannel info; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { + cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + info.address_format = CD_MSF_FORMAT; + info.data_format = CD_CURRENT_POSITION; + info.data_len = 0; + info.data = NULL; + /* Under Linux, EIO occurs when a disk is not present. + This isn't 100% reliable, so we use the USE_MNTENT + code above instead. + */ + if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) || + ERRNO_TRAYEMPTY(errno) ) { + is_cd = 1; + } + close(cdfd); + } + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +int SDL_SYS_CDInit(void) +{ + /* checklist: /dev/cdrom,/dev/cd?c /dev/acd?c + /dev/matcd?c /dev/mcd?c /dev/scd?c */ + static char *checklist[] = { + "cdrom", "?0 cd?", "?0 acd?", "?0 matcd?", "?0 mcd?", "?0 scd?",NULL + }; + char *SDLcdrom; + int i, j, exists; + char drive[32]; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + + /* Scan the system for CD-ROM drives */ + for ( i=0; checklist[i]; ++i ) { + if ( checklist[i][0] == '?' ) { + char *insert; + exists = 1; + for ( j=checklist[i][1]; exists; ++j ) { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]); + insert = SDL_strchr(drive, '?'); + if ( insert != NULL ) { + *insert = j; + } + switch (CheckDrive(drive, &stbuf)) { + /* Drive exists and is a CD-ROM */ + case 1: + AddDrive(drive, &stbuf); + break; + /* Drive exists, but isn't a CD-ROM */ + case 0: + break; + /* Drive doesn't exist */ + case -1: + exists = 0; + break; + } + } + } else { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); + if ( CheckDrive(drive, &stbuf) > 0 ) { + AddDrive(drive, &stbuf); + } + } + } + return(0); +} + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int id, int command, void *arg) +{ + int retval; + + retval = ioctl(id, command, arg); + if ( retval < 0 ) { + SDL_SetError("ioctl() error: %s", strerror(errno)); + } + return(retval); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + struct ioc_toc_header toc; + int i, okay; + struct ioc_read_toc_entry entry; + struct cd_toc_entry data; + + okay = 0; + if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) { + cdrom->numtracks = toc.ending_track-toc.starting_track+1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + /* Read all the track TOC entries */ + for ( i=0; i<=cdrom->numtracks; ++i ) { + if ( i == cdrom->numtracks ) { + cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */ + } else { + cdrom->track[i].id = toc.starting_track+i; + } + entry.starting_track = cdrom->track[i].id; + entry.address_format = CD_MSF_FORMAT; + entry.data_len = sizeof(data); + entry.data = &data; + if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS, + &entry) < 0 ) { + break; + } else { + cdrom->track[i].type = data.control; + cdrom->track[i].offset = MSF_TO_FRAMES( + data.addr.msf.minute, + data.addr.msf.second, + data.addr.msf.frame); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = + cdrom->track[i].offset- + cdrom->track[i-1].offset; + } + } + } + if ( i == (cdrom->numtracks+1) ) { + okay = 1; + } + } + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct ioc_toc_header toc; + struct ioc_read_subchannel info; + struct cd_sub_channel_info data; + + info.address_format = CD_MSF_FORMAT; + info.data_format = CD_CURRENT_POSITION; + info.track = 0; + info.data_len = sizeof(data); + info.data = &data; + if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) { + if ( ERRNO_TRAYEMPTY(errno) ) { + status = CD_TRAYEMPTY; + } else { + status = CD_ERROR; + } + } else { + switch (data.header.audio_status) { + case CD_AS_AUDIO_INVALID: + case CD_AS_NO_STATUS: + /* Try to determine if there's a CD available */ + if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0) + status = CD_STOPPED; + else + status = CD_TRAYEMPTY; + break; + case CD_AS_PLAY_COMPLETED: + status = CD_STOPPED; + break; + case CD_AS_PLAY_IN_PROGRESS: + status = CD_PLAYING; + break; + case CD_AS_PLAY_PAUSED: + status = CD_PAUSED; + break; + default: + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = MSF_TO_FRAMES( + data.what.position.absaddr.msf.minute, + data.what.position.absaddr.msf.second, + data.what.position.absaddr.msf.frame); + } else { + *position = 0; + } + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + struct ioc_play_msf playtime; + + FRAMES_TO_MSF(start, + &playtime.start_m, &playtime.start_s, &playtime.start_f); + FRAMES_TO_MSF(start+length, + &playtime.end_m, &playtime.end_s, &playtime.end_f); +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, + playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); +#endif + ioctl(cdrom->id, CDIOCSTART, 0); + return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_FREEBSD */ diff --git a/3rdparty/SDL/src/cdrom/linux/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/linux/SDL_syscdrom.c new file mode 100644 index 0000000..6804057 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/linux/SDL_syscdrom.c @@ -0,0 +1,564 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_LINUX + +/* Functions for system-level CD-ROM audio control */ + +#include <string.h> /* For strerror() */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#ifdef __LINUX__ +#ifdef HAVE_LINUX_VERSION_H +/* linux 2.6.9 workaround */ +#include <linux/version.h> +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9) +#include <asm/types.h> +#define __le64 __u64 +#define __le32 __u32 +#define __le16 __u16 +#define __be64 __u64 +#define __be32 __u32 +#define __be16 __u16 +#endif /* linux 2.6.9 workaround */ +#endif /* HAVE_LINUX_VERSION_H */ +#include <linux/cdrom.h> +#endif +#ifdef __SVR4 +#include <sys/cdio.h> +#endif + +/* Define this to use the alternative getmntent() code */ +#ifndef __SVR4 +#define USE_MNTENT +#endif + +#ifdef USE_MNTENT +#if defined(__USLC__) +#include <sys/mntent.h> +#else +#include <mntent.h> +#endif + +#ifndef _PATH_MNTTAB +#ifdef MNTTAB +#define _PATH_MNTTAB MNTTAB +#else +#define _PATH_MNTTAB "/etc/fstab" +#endif +#endif /* !_PATH_MNTTAB */ + +#ifndef _PATH_MOUNTED +#define _PATH_MOUNTED "/etc/mtab" +#endif /* !_PATH_MOUNTED */ + +#ifndef MNTTYPE_CDROM +#define MNTTYPE_CDROM "iso9660" +#endif +#ifndef MNTTYPE_SUPER +#define MNTTYPE_SUPER "supermount" +#endif +#endif /* USE_MNTENT */ + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* Some ioctl() errno values which occur when the tray is empty */ +#ifndef ENOMEDIUM +#define ENOMEDIUM ENOENT +#endif +#define ERRNO_TRAYEMPTY(errno) \ + ((errno == EIO) || (errno == ENOENT) || \ + (errno == EINVAL) || (errno == ENOMEDIUM)) + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf) +{ + int is_cd, cdfd; + struct cdrom_subchnl info; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { + cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + info.cdsc_format = CDROM_MSF; + /* Under Linux, EIO occurs when a disk is not present. + */ + if ( (ioctl(cdfd, CDROMSUBCHNL, &info) == 0) || + ERRNO_TRAYEMPTY(errno) ) { + is_cd = 1; + } + close(cdfd); + } +#ifdef USE_MNTENT + /* Even if we can't read it, it might be mounted */ + else if ( mnttype && (SDL_strcmp(mnttype, MNTTYPE_CDROM) == 0) ) { + is_cd = 1; + } +#endif + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +#ifdef USE_MNTENT +static void CheckMounts(const char *mtab) +{ + FILE *mntfp; + struct mntent *mntent; + struct stat stbuf; + + mntfp = setmntent(mtab, "r"); + if ( mntfp != NULL ) { + char *tmp; + char *mnt_type; + size_t mnt_type_len; + char *mnt_dev; + size_t mnt_dev_len; + + while ( (mntent=getmntent(mntfp)) != NULL ) { + mnt_type_len = SDL_strlen(mntent->mnt_type) + 1; + mnt_type = SDL_stack_alloc(char, mnt_type_len); + if (mnt_type == NULL) + continue; /* maybe you'll get lucky next time. */ + + mnt_dev_len = SDL_strlen(mntent->mnt_fsname) + 1; + mnt_dev = SDL_stack_alloc(char, mnt_dev_len); + if (mnt_dev == NULL) { + SDL_stack_free(mnt_type); + continue; + } + + SDL_strlcpy(mnt_type, mntent->mnt_type, mnt_type_len); + SDL_strlcpy(mnt_dev, mntent->mnt_fsname, mnt_dev_len); + + /* Handle "supermount" filesystem mounts */ + if ( SDL_strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) { + tmp = SDL_strstr(mntent->mnt_opts, "fs="); + if ( tmp ) { + SDL_stack_free(mnt_type); + mnt_type = SDL_strdup(tmp + SDL_strlen("fs=")); + if ( mnt_type ) { + tmp = SDL_strchr(mnt_type, ','); + if ( tmp ) { + *tmp = '\0'; + } + } + } + tmp = SDL_strstr(mntent->mnt_opts, "dev="); + if ( tmp ) { + SDL_stack_free(mnt_dev); + mnt_dev = SDL_strdup(tmp + SDL_strlen("dev=")); + if ( mnt_dev ) { + tmp = SDL_strchr(mnt_dev, ','); + if ( tmp ) { + *tmp = '\0'; + } + } + } + } + if ( SDL_strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking mount path from %s: %s mounted on %s of %s\n", + mtab, mnt_dev, mntent->mnt_dir, mnt_type); +#endif + if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) { + AddDrive(mnt_dev, &stbuf); + } + } + SDL_stack_free(mnt_dev); + SDL_stack_free(mnt_type); + } + endmntent(mntfp); + } +} +#endif /* USE_MNTENT */ + +int SDL_SYS_CDInit(void) +{ + /* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */ + static char *checklist[] = { + "cdrom", "?a hd?", "?0 scd?", "?0 sr?", NULL + }; + char *SDLcdrom; + int i, j, exists; + char drive[32]; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom); +#endif + if ( CheckDrive(SDLcdrom, NULL, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + +#ifdef USE_MNTENT + /* Check /dev/cdrom first :-) */ + if (CheckDrive("/dev/cdrom", NULL, &stbuf) > 0) { + AddDrive("/dev/cdrom", &stbuf); + } + + /* Now check the currently mounted CD drives */ + CheckMounts(_PATH_MOUNTED); + + /* Finally check possible mountable drives in /etc/fstab */ + CheckMounts(_PATH_MNTTAB); + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } +#endif /* USE_MNTENT */ + + /* Scan the system for CD-ROM drives. + Not always 100% reliable, so use the USE_MNTENT code above first. + */ + for ( i=0; checklist[i]; ++i ) { + if ( checklist[i][0] == '?' ) { + char *insert; + exists = 1; + for ( j=checklist[i][1]; exists; ++j ) { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); + insert = SDL_strchr(drive, '?'); + if ( insert != NULL ) { + *insert = j; + } +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); +#endif + switch (CheckDrive(drive, NULL, &stbuf)) { + /* Drive exists and is a CD-ROM */ + case 1: + AddDrive(drive, &stbuf); + break; + /* Drive exists, but isn't a CD-ROM */ + case 0: + break; + /* Drive doesn't exist */ + case -1: + exists = 0; + break; + } + } + } else { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); +#ifdef DEBUG_CDROM + fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); +#endif + if ( CheckDrive(drive, NULL, &stbuf) > 0 ) { + AddDrive(drive, &stbuf); + } + } + } + return(0); +} + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int id, int command, void *arg) +{ + int retval; + + retval = ioctl(id, command, arg); + if ( retval < 0 ) { + SDL_SetError("ioctl() error: %s", strerror(errno)); + } + return(retval); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(open(SDL_cdlist[drive], (O_RDONLY|O_NONBLOCK), 0)); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + struct cdrom_tochdr toc; + int i, okay; + struct cdrom_tocentry entry; + + okay = 0; + if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0 ) { + cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + /* Read all the track TOC entries */ + for ( i=0; i<=cdrom->numtracks; ++i ) { + if ( i == cdrom->numtracks ) { + cdrom->track[i].id = CDROM_LEADOUT; + } else { + cdrom->track[i].id = toc.cdth_trk0+i; + } + entry.cdte_track = cdrom->track[i].id; + entry.cdte_format = CDROM_MSF; + if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, + &entry) < 0 ) { + break; + } else { + if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) { + cdrom->track[i].type = SDL_DATA_TRACK; + } else { + cdrom->track[i].type = SDL_AUDIO_TRACK; + } + cdrom->track[i].offset = MSF_TO_FRAMES( + entry.cdte_addr.msf.minute, + entry.cdte_addr.msf.second, + entry.cdte_addr.msf.frame); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = + cdrom->track[i].offset- + cdrom->track[i-1].offset; + } + } + } + if ( i == (cdrom->numtracks+1) ) { + okay = 1; + } + } + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct cdrom_tochdr toc; + struct cdrom_subchnl info; + + info.cdsc_format = CDROM_MSF; + if ( ioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) { + if ( ERRNO_TRAYEMPTY(errno) ) { + status = CD_TRAYEMPTY; + } else { + status = CD_ERROR; + } + } else { + switch (info.cdsc_audiostatus) { + case CDROM_AUDIO_INVALID: + case CDROM_AUDIO_NO_STATUS: + /* Try to determine if there's a CD available */ + if (ioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) + status = CD_STOPPED; + else + status = CD_TRAYEMPTY; + break; + case CDROM_AUDIO_COMPLETED: + status = CD_STOPPED; + break; + case CDROM_AUDIO_PLAY: + status = CD_PLAYING; + break; + case CDROM_AUDIO_PAUSED: + /* Workaround buggy CD-ROM drive */ + if ( info.cdsc_trk == CDROM_LEADOUT ) { + status = CD_STOPPED; + } else { + status = CD_PAUSED; + } + break; + default: + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = MSF_TO_FRAMES( + info.cdsc_absaddr.msf.minute, + info.cdsc_absaddr.msf.second, + info.cdsc_absaddr.msf.frame); + } else { + *position = 0; + } + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + struct cdrom_msf playtime; + + FRAMES_TO_MSF(start, + &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0); + FRAMES_TO_MSF(start+length, + &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1); +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, + playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); +#endif + return(SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_LINUX */ diff --git a/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom.c new file mode 100644 index 0000000..10a2025 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom.c @@ -0,0 +1,525 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_MACOS + +/* MacOS functions for system-level CD-ROM audio control */ + +#include <Devices.h> +#include <Files.h> +#include <LowMem.h> /* Use entry table macros, not functions in InterfaceLib */ + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" +#include "SDL_syscdrom_c.h" + +/* Added by Matt Slot */ +#if !defined(LMGetUnitTableEntryCount) + #define LMGetUnitTableEntryCount() *(short *)0x01D2 +#endif + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 26 + +/* A list of available CD-ROM drives */ +static long SDL_cdversion = 0; +static struct { + short dRefNum; + short driveNum; + long frames; + char name[256]; + Boolean hasAudio; + } SDL_cdlist[MAX_DRIVES]; +static StringPtr gDriverName = "\p.AppleCD"; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +static short SDL_SYS_ShortToBCD(short value) +{ + return((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */ +} + +static short SDL_SYS_BCDToShort(short value) +{ + return((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */ +} + +int SDL_SYS_CDInit(void) +{ + SInt16 dRefNum = 0; + SInt16 first, last; + + SDL_numcds = 0; + + /* Check that the software is available */ + if (Gestalt(kGestaltAudioCDSelector, &SDL_cdversion) || + !SDL_cdversion) return(0); + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Walk the list, count each AudioCD driver, and save the refnums */ + first = -1; + last = 0 - LMGetUnitTableEntryCount(); + for(dRefNum = first; dRefNum >= last; dRefNum--) { + Str255 driverName; + StringPtr namePtr; + DCtlHandle deviceEntry; + + deviceEntry = GetDCtlEntry(dRefNum); + if (! deviceEntry) continue; + + /* Is this an .AppleCD ? */ + namePtr = (*deviceEntry)->dCtlFlags & (1L << dRAMBased) ? + ((StringPtr) ((DCtlPtr) deviceEntry)->dCtlDriver + 18) : + ((StringPtr) (*deviceEntry)->dCtlDriver + 18); + BlockMoveData(namePtr, driverName, namePtr[0]+1); + if (driverName[0] > gDriverName[0]) driverName[0] = gDriverName[0]; + if (! EqualString(driverName, gDriverName, false, false)) continue; + + /* Record the basic info for each drive */ + SDL_cdlist[SDL_numcds].dRefNum = dRefNum; + BlockMoveData(namePtr + 1, SDL_cdlist[SDL_numcds].name, namePtr[0]); + SDL_cdlist[SDL_numcds].name[namePtr[0]] = 0; + SDL_cdlist[SDL_numcds].hasAudio = false; + SDL_numcds++; + } + return(0); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive].name); +} + +static int get_drivenum(int drive) +{ + QHdr *driveQ = GetDrvQHdr(); + DrvQEl *driveElem; + + /* Update the drive number */ + SDL_cdlist[drive].driveNum = 0; + if ( driveQ->qTail ) { + driveQ->qTail->qLink = 0; + } + for ( driveElem=(DrvQEl *)driveQ->qHead; driveElem; + driveElem = (DrvQEl *)driveElem->qLink ) { + if ( driveElem->dQRefNum == SDL_cdlist[drive].dRefNum ) { + SDL_cdlist[drive].driveNum = driveElem->dQDrive; + break; + } + } + return(SDL_cdlist[drive].driveNum); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(drive); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + CDCntrlParam cdpb; + CDTrackData tracks[SDL_MAX_TRACKS]; + long i, leadout; + + /* Get the number of tracks on the CD by examining the TOC */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kReadTOC; + cdpb.csParam.words[0] = kGetTrackRange; + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + cdrom->numtracks = + SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - + SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) + cdrom->numtracks = SDL_MAX_TRACKS; + cdrom->status = CD_STOPPED; + cdrom->cur_track = 0; /* Apparently these are set elsewhere */ + cdrom->cur_frame = 0; /* Apparently these are set elsewhere */ + + + /* Get the lead out area of the CD by examining the TOC */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kReadTOC; + cdpb.csParam.words[0] = kGetLeadOutArea; + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + leadout = MSF_TO_FRAMES( + SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]), + SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]), + SDL_SYS_BCDToShort(cdpb.csParam.bytes[2])); + + /* Get an array of track locations by examining the TOC */ + SDL_memset(tracks, 0, sizeof(tracks)); + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kReadTOC; + cdpb.csParam.words[0] = kGetTrackEntries; /* Type of Query */ + * ((long *) (cdpb.csParam.words+1)) = (long) tracks; + cdpb.csParam.words[3] = cdrom->numtracks * sizeof(tracks[0]); + * ((char *) (cdpb.csParam.words+4)) = 1; /* First track */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + /* Read all the track TOC entries */ + SDL_cdlist[cdrom->id].hasAudio = false; + for ( i=0; i<cdrom->numtracks; ++i ) + { + cdrom->track[i].id = i+1; + if (tracks[i].entry.control & kDataTrackMask) + cdrom->track[i].type = SDL_DATA_TRACK; + else + { + cdrom->track[i].type = SDL_AUDIO_TRACK; + SDL_cdlist[SDL_numcds].hasAudio = true; + } + + cdrom->track[i].offset = MSF_TO_FRAMES( + SDL_SYS_BCDToShort(tracks[i].entry.min), + SDL_SYS_BCDToShort(tracks[i].entry.min), + SDL_SYS_BCDToShort(tracks[i].entry.frame)); + cdrom->track[i].length = MSF_TO_FRAMES( + SDL_SYS_BCDToShort(tracks[i+1].entry.min), + SDL_SYS_BCDToShort(tracks[i+1].entry.min), + SDL_SYS_BCDToShort(tracks[i+1].entry.frame)) - + cdrom->track[i].offset; + } + + /* Apparently SDL wants a fake last entry */ + cdrom->track[i].offset = leadout; + cdrom->track[i].length = 0; + + return(0); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDCntrlParam cdpb; + CDstatus status = CD_ERROR; + Boolean spinning = false; + + if (position) *position = 0; + + /* Get the number of tracks on the CD by examining the TOC */ + if ( ! get_drivenum(cdrom->id) ) { + return(CD_TRAYEMPTY); + } + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kReadTOC; + cdpb.csParam.words[0] = kGetTrackRange; + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(CD_ERROR); + } + + cdrom->numtracks = + SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - + SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) + cdrom->numtracks = SDL_MAX_TRACKS; + cdrom->cur_track = 0; /* Apparently these are set elsewhere */ + cdrom->cur_frame = 0; /* Apparently these are set elsewhere */ + + + if (1 || SDL_cdlist[cdrom->id].hasAudio) { + /* Get the current playback status */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioStatus; + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + switch(cdpb.csParam.cd.status) { + case kStatusPlaying: + status = CD_PLAYING; + spinning = true; + break; + case kStatusPaused: + status = CD_PAUSED; + spinning = true; + break; + case kStatusMuted: + status = CD_PLAYING; /* What should I do here? */ + spinning = true; + break; + case kStatusDone: + status = CD_STOPPED; + spinning = true; + break; + case kStatusStopped: + status = CD_STOPPED; + spinning = false; + break; + case kStatusError: + default: + status = CD_ERROR; + spinning = false; + break; + } + + if (spinning && position) *position = MSF_TO_FRAMES( + SDL_SYS_BCDToShort(cdpb.csParam.cd.minute), + SDL_SYS_BCDToShort(cdpb.csParam.cd.second), + SDL_SYS_BCDToShort(cdpb.csParam.cd.frame)); + } + else + status = CD_ERROR; /* What should I do here? */ + + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + CDCntrlParam cdpb; + + /* Pause the current audio playback to avoid audible artifacts */ + if ( SDL_SYS_CDPause(cdrom) < 0 ) { + return(-1); + } + + /* Specify the AudioCD playback mode */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kSetPlayMode; + cdpb.csParam.bytes[0] = false; /* Repeat? */ + cdpb.csParam.bytes[1] = kPlayModeSequential; /* Play mode */ + /* Treat as soft error, NEC Drive doesnt support this call */ + PBControlSync((ParmBlkPtr) &cdpb); + +#if 1 + /* Specify the end of audio playback */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioStop; + cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */ + *(long *) (cdpb.csParam.words + 1) = start+length-1; /* Search Address */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + /* Specify the start of audio playback, and start it */ + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioPlay; + cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */ + *(long *) (cdpb.csParam.words + 1) = start+1; /* Search Address */ + cdpb.csParam.words[3] = false; /* Stop address? */ + cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } +#else + /* Specify the end of audio playback */ + FRAMES_TO_MSF(start+length, &m, &s, &f); + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioStop; + cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */ + cdpb.csParam.words[1] = 0; /* Search Address (hiword)*/ + cdpb.csParam.words[2] = /* Search Address (loword)*/ + SDL_SYS_ShortToBCD(cdrom->numtracks); + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + + /* Specify the start of audio playback, and start it */ + FRAMES_TO_MSF(start, &m, &s, &f); + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioPlay; + cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */ + cdpb.csParam.words[1] = 0; /* Search Address (hiword)*/ + cdpb.csParam.words[2] = SDL_SYS_ShortToBCD(1); /* Search Address (loword)*/ + cdpb.csParam.words[3] = false; /* Stop address? */ + cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } +#endif + + return(0); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + CDCntrlParam cdpb; + + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioPause; + cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */ + cdpb.csParam.words[1] = 1; /* Pause/Continue Flag (loword) */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + return(0); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + CDCntrlParam cdpb; + + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioPause; + cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */ + cdpb.csParam.words[1] = 0; /* Pause/Continue Flag (loword) */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + return(0); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + CDCntrlParam cdpb; + + SDL_memset(&cdpb, 0, sizeof(cdpb)); + cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; + cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cdpb.csCode = kAudioStop; + cdpb.csParam.words[0] = 0; /* Position Mode */ + cdpb.csParam.words[1] = 0; /* Search Address (hiword) */ + cdpb.csParam.words[2] = 0; /* Search Address (loword) */ + if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + return(0); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + Boolean disk = false; + QHdr *driveQ = GetDrvQHdr(); + DrvQEl *driveElem; + HParamBlockRec hpb; + ParamBlockRec cpb; + + for ( driveElem = (DrvQEl *) driveQ->qHead; driveElem; driveElem = + (driveElem) ? ((DrvQEl *) driveElem->qLink) : + ((DrvQEl *) driveQ->qHead) ) { + if ( driveQ->qTail ) { + driveQ->qTail->qLink = 0; + } + if ( driveElem->dQRefNum != SDL_cdlist[cdrom->id].dRefNum ) { + continue; + } + + /* Does drive contain mounted volume? If not, skip */ + SDL_memset(&hpb, 0, sizeof(hpb)); + hpb.volumeParam.ioVRefNum = driveElem->dQDrive; + if ( PBHGetVInfoSync(&hpb) != noErr ) { + continue; + } + if ( (UnmountVol(0, driveElem->dQDrive) == noErr) && + (Eject(0, driveElem->dQDrive) == noErr) ) { + driveElem = 0; /* Clear pointer to reset our loop */ + disk = true; + } + } + + /* If no disk is present, just eject the tray */ + if (! disk) { + SDL_memset(&cpb, 0, sizeof(cpb)); + cpb.cntrlParam.ioVRefNum = 0; /* No Drive */ + cpb.cntrlParam.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; + cpb.cntrlParam.csCode = kEjectTheDisc; + if ( PBControlSync((ParmBlkPtr)&cpb) != noErr ) { + SDL_SetError("PBControlSync() failed"); + return(-1); + } + } + return(0); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + return; +} + +void SDL_SYS_CDQuit(void) +{ + while(SDL_numcds--) + SDL_memset(SDL_cdlist + SDL_numcds, 0, sizeof(SDL_cdlist[0])); +} + +#endif /* SDL_CDROM_MACOS */ diff --git a/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom_c.h b/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom_c.h new file mode 100644 index 0000000..e715a25 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macos/SDL_syscdrom_c.h @@ -0,0 +1,140 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the MacOS specific header for the SDL CD-ROM API + Contributed by Matt Slot + */ + +/* AppleCD Control calls */ +#define kVerifyTheDisc 5 /* Returns noErr if there is disc inserted */ +#define kEjectTheDisc 7 /* Eject disc from drive */ +#define kUserEject 80 /* Enable/disable the CD-ROM eject button */ +#define kReadTOC 100 /* Extract various TOC information from the disc */ +#define kReadQ 101 /* Extract Q subcode info for the current track */ +#define kAudioTrackSearch 103 /* Start playback from the indicated position */ +#define kAudioPlay 104 /* Start playback from the indicated position */ +#define kAudioPause 105 /* Pause/continue the playback */ +#define kAudioStop 106 /* Stop playback at the indicated position */ +#define kAudioStatus 107 /* Return audio play status */ +#define kAudioControl 109 /* Set the output volume for the audio channels */ +#define kReadAudioVolume 112 /* Get the output volume for the audio channels */ +#define kSetTrackList 122 /* Set the track program for the audio CD to play */ +#define kGetTrackList 123 /* Get the track program the audio CD is playing */ +#define kGetTrackIndex 124 /* Get the track index the audio CD is playing */ +#define kSetPlayMode 125 /* Set the audio tracks play mode */ +#define kGetPlayMode 126 /* Get the audio tracks play mode */ + +/* AppleCD Status calls */ +#define kGetDriveType 96 /* Get the type of the physical CD-ROM drive */ +#define kWhoIsThere 97 /* Get a bitmap of SCSI IDs the driver controls */ +#define kGetBlockSize 98 /* Get current block size of the CD-ROM drive */ + +/* AppleCD other constants */ +#define kBlockPosition 0 /* Position at the specified logical block number */ +#define kAbsMSFPosition 1 /* Position at the specified Min/Sec/Frame (in BCD) */ +#define kTrackPosition 2 /* Position at the specified track number (in BCD) */ +#define kIndexPosition 3 /* Position at the nth track in program (in BCD) */ + +#define kMutedPlayMode 0 /* Play the audio track with no output */ +#define kStereoPlayMode 9 /* Play the audio track in normal stereo */ + +#define kControlFieldMask 0x0D /* Bits 3,2,0 in the nibble */ +#define kDataTrackMask 0x04 /* Indicates Data Track */ + +#define kGetTrackRange 1 /* Query TOC for track numbers */ +#define kGetLeadOutArea 2 /* Query TOC for "Lead Out" end of audio data */ +#define kGetTrackEntries 3 /* Query TOC for track starts and data types */ + +#define kStatusPlaying 0 /* Audio Play operation in progress */ +#define kStatusPaused 1 /* CD-ROM device in Hold Track ("Pause") state */ +#define kStatusMuted 2 /* MUTING-ON operation in progress */ +#define kStatusDone 3 /* Audio Play completed */ +#define kStatusError 4 /* Error occurred during audio play operation */ +#define kStatusStopped 5 /* Audio play operation not requested */ + +#define kPlayModeSequential 0 /* Play tracks in order */ +#define kPlayModeShuffled 1 /* Play tracks randomly */ +#define kPlayModeProgrammed 2 /* Use custom playlist */ + +/* AppleCD Gestalt selectors */ +#define kGestaltAudioCDSelector 'aucd' +#define kDriverVersion52 0x00000520 +#define kDriverVersion51 0x00000510 +#define kDriverVersion50 0x00000500 + +/* Drive type constants */ +#define kDriveAppleCD_SC 1 +#define kDriveAppleCD_SCPlus_or_150 2 +#define kDriveAppleCD_300_or_300Plus 3 + +/* Misc constants */ +#define kFirstSCSIDevice -33 +#define kLastSCSIDevice -40 + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#endif + +/* AppleCD driver parameter block */ +typedef struct CDCntrlParam { + QElemPtr qLink; + short qType; + short ioTrap; + Ptr ioCmdAddr; + IOCompletionUPP ioCompletion; + OSErr ioResult; + StringPtr ioNamePtr; + short ioVRefNum; + short ioCRefNum; + short csCode; + + union { + long longs[6]; + short words[11]; + unsigned char bytes[22]; + struct { + unsigned char status; + unsigned char play; + unsigned char control; + unsigned char minute; + unsigned char second; + unsigned char frame; + } cd; + } csParam; + + } CDCntrlParam, *CDCntrlParamPtr; + +typedef union CDTrackData { + long value; /* Treat as a longword value */ + struct { + unsigned char reserved : 4; /* Unused by AppleCD driver */ + unsigned char control : 4; /* Track flags (data track?) */ + unsigned char min; /* Start of track (BCD) */ + unsigned char sec; /* Start of track (BCD) */ + unsigned char frame; /* Start of track (BCD) */ + } entry; /* Broken into fields */ + } CDTrackData, *CDTrackPtr; + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#endif diff --git a/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.c b/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.c new file mode 100644 index 0000000..97cb9b2 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.c @@ -0,0 +1,360 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + This file based on Apple sample code. We haven't changed the file name, + so if you want to see the original search for it on apple.com/developer +*/ +#include "SDL_config.h" +#include "SDL_endian.h" + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AudioFilePlayer.cpp +*/ +#include "AudioFilePlayer.h" + +/* +void ThrowResult (OSStatus result, const char* str) +{ + SDL_SetError ("Error: %s %d", str, result); + throw result; +} +*/ + +#if DEBUG +static void PrintStreamDesc (AudioStreamBasicDescription *inDesc) +{ + if (!inDesc) { + printf ("Can't print a NULL desc!\n"); + return; + } + + printf ("- - - - - - - - - - - - - - - - - - - -\n"); + printf (" Sample Rate:%f\n", inDesc->mSampleRate); + printf (" Format ID:%s\n", (char*)&inDesc->mFormatID); + printf (" Format Flags:%lX\n", inDesc->mFormatFlags); + printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); + printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); + printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); + printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); + printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); + printf ("- - - - - - - - - - - - - - - - - - - -\n"); +} +#endif + + +static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit *inDestUnit) +{ + /*if (afp->mConnected) throw static_cast<OSStatus>(-1);*/ /* can't set dest if already engaged */ + if (afp->mConnected) + return 0 ; + + SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit)); + + OSStatus result = noErr; + + + /* we can "down" cast a component instance to a component */ + ComponentDescription desc; + result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0); + if (result) return 0; /*THROW_RESULT("GetComponentInfo")*/ + + /* we're going to use this to know which convert routine to call + a v1 audio unit will have a type of 'aunt' + a v2 audio unit will have one of several different types. */ + if (desc.componentType != kAudioUnitType_Output) { + result = badComponentInstance; + /*THROW_RESULT("BAD COMPONENT")*/ + if (result) return 0; + } + + /* Set the input format of the audio unit. */ + result = AudioUnitSetProperty (*inDestUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &afp->mFileDescription, + sizeof (afp->mFileDescription)); + /*THROW_RESULT("AudioUnitSetProperty")*/ + if (result) return 0; + return 1; +} + +static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon) +{ + afp->mNotifier = inNotifier; + afp->mRefCon = inRefCon; +} + +static int AudioFilePlayer_IsConnected(AudioFilePlayer *afp) +{ + return afp->mConnected; +} + +static AudioUnit AudioFilePlayer_GetDestUnit(AudioFilePlayer *afp) +{ + return afp->mPlayUnit; +} + +static void AudioFilePlayer_Print(AudioFilePlayer *afp) +{ +#if DEBUG + printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false")); + printf ("- - - - - - - - - - - - - - \n"); +#endif +} + +static void AudioFilePlayer_SetStartFrame (AudioFilePlayer *afp, int frame) +{ + SInt64 position = frame * 2352; + + afp->mStartFrame = frame; + afp->mAudioFileManager->SetPosition (afp->mAudioFileManager, position); +} + + +static int AudioFilePlayer_GetCurrentFrame (AudioFilePlayer *afp) +{ + return afp->mStartFrame + (afp->mAudioFileManager->GetByteCounter(afp->mAudioFileManager) / 2352); +} + +static void AudioFilePlayer_SetStopFrame (AudioFilePlayer *afp, int frame) +{ + SInt64 position = frame * 2352; + + afp->mAudioFileManager->SetEndOfFile (afp->mAudioFileManager, position); +} + +void delete_AudioFilePlayer(AudioFilePlayer *afp) +{ + if (afp != NULL) + { + afp->Disconnect(afp); + + if (afp->mAudioFileManager) { + delete_AudioFileManager(afp->mAudioFileManager); + afp->mAudioFileManager = 0; + } + + if (afp->mForkRefNum) { + FSCloseFork (afp->mForkRefNum); + afp->mForkRefNum = 0; + } + SDL_free(afp); + } +} + +static int AudioFilePlayer_Connect(AudioFilePlayer *afp) +{ +#if DEBUG + printf ("Connect:%x, engaged=%d\n", (int)afp->mPlayUnit, (afp->mConnected ? 1 : 0)); +#endif + if (!afp->mConnected) + { + if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager)) + return 0; + + /* set the render callback for the file data to be supplied to the sound converter AU */ + afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc; + afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager; + + OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &afp->mInputCallback, + sizeof(afp->mInputCallback)); + if (result) return 0; /*THROW_RESULT("AudioUnitSetProperty")*/ + afp->mConnected = 1; + } + + return 1; +} + +/* warning noted, now please go away ;-) */ +/* #warning This should redirect the calling of notification code to some other thread */ +static void AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus) +{ + if (afp->mNotifier) { + (*afp->mNotifier) (afp->mRefCon, inStatus); + } else { + SDL_SetError ("Notification posted with no notifier in place"); + + if (inStatus == kAudioFilePlay_FileIsFinished) + afp->Disconnect(afp); + else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun) + afp->Disconnect(afp); + } +} + +static void AudioFilePlayer_Disconnect (AudioFilePlayer *afp) +{ +#if DEBUG + printf ("Disconnect:%x,%ld, engaged=%d\n", (int)afp->mPlayUnit, 0, (afp->mConnected ? 1 : 0)); +#endif + if (afp->mConnected) + { + afp->mConnected = 0; + + afp->mInputCallback.inputProc = 0; + afp->mInputCallback.inputProcRefCon = 0; + OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &afp->mInputCallback, + sizeof(afp->mInputCallback)); + if (result) + SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result); + + afp->mAudioFileManager->Disconnect(afp->mAudioFileManager); + } +} + +typedef struct { + UInt32 offset; + UInt32 blockSize; +} SSNDData; + +static int AudioFilePlayer_OpenFile (AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileDataSize) +{ + ContainerChunk chunkHeader; + ChunkHeader chunk; + SSNDData ssndData; + + OSErr result; + HFSUniStr255 dfName; + ByteCount actual; + SInt64 offset; + + /* Open the data fork of the input file */ + result = FSGetDataForkName(&dfName); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")*/ + + result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")*/ + + /* Read the file header, and check if it's indeed an AIFC file */ + result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ + + if (SDL_SwapBE32(chunkHeader.ckID) != 'FORM') { + result = -1; + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");*/ + } + + if (SDL_SwapBE32(chunkHeader.formType) != 'AIFC') { + result = -1; + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");*/ + } + + /* Search for the SSND chunk. We ignore all compression etc. information + in other chunks. Of course that is kind of evil, but for now we are lazy + and rely on the cdfs to always give us the same fixed format. + TODO: Parse the COMM chunk we currently skip to fill in mFileDescription. + */ + offset = 0; + do { + result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ + + chunk.ckID = SDL_SwapBE32(chunk.ckID); + chunk.ckSize = SDL_SwapBE32(chunk.ckSize); + + /* Skip the chunk data */ + offset = chunk.ckSize; + } while (chunk.ckID != 'SSND'); + + /* Read the header of the SSND chunk. After this, we are positioned right + at the start of the audio data. */ + result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ + + ssndData.offset = SDL_SwapBE32(ssndData.offset); + + result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset); + if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")*/ + + /* Data size */ + *outFileDataSize = chunk.ckSize - ssndData.offset - 8; + + /* File format */ + afp->mFileDescription.mSampleRate = 44100; + afp->mFileDescription.mFormatID = kAudioFormatLinearPCM; + afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; + afp->mFileDescription.mBytesPerPacket = 4; + afp->mFileDescription.mFramesPerPacket = 1; + afp->mFileDescription.mBytesPerFrame = 4; + afp->mFileDescription.mChannelsPerFrame = 2; + afp->mFileDescription.mBitsPerChannel = 16; + + return 1; +} + +AudioFilePlayer *new_AudioFilePlayer (const FSRef *inFileRef) +{ + SInt64 fileDataSize = 0; + + AudioFilePlayer *afp = (AudioFilePlayer *) SDL_malloc(sizeof (AudioFilePlayer)); + if (afp == NULL) + return NULL; + SDL_memset(afp, '\0', sizeof (*afp)); + + #define SET_AUDIOFILEPLAYER_METHOD(m) afp->m = AudioFilePlayer_##m + SET_AUDIOFILEPLAYER_METHOD(SetDestination); + SET_AUDIOFILEPLAYER_METHOD(SetNotifier); + SET_AUDIOFILEPLAYER_METHOD(SetStartFrame); + SET_AUDIOFILEPLAYER_METHOD(GetCurrentFrame); + SET_AUDIOFILEPLAYER_METHOD(SetStopFrame); + SET_AUDIOFILEPLAYER_METHOD(Connect); + SET_AUDIOFILEPLAYER_METHOD(Disconnect); + SET_AUDIOFILEPLAYER_METHOD(DoNotification); + SET_AUDIOFILEPLAYER_METHOD(IsConnected); + SET_AUDIOFILEPLAYER_METHOD(GetDestUnit); + SET_AUDIOFILEPLAYER_METHOD(Print); + SET_AUDIOFILEPLAYER_METHOD(OpenFile); + #undef SET_AUDIOFILEPLAYER_METHOD + + if (!afp->OpenFile (afp, inFileRef, &fileDataSize)) + { + SDL_free(afp); + return NULL; + } + + /* we want about 4 seconds worth of data for the buffer */ + int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame); + +#if DEBUG + printf("File format:\n"); + PrintStreamDesc (&afp->mFileDescription); +#endif + + afp->mAudioFileManager = new_AudioFileManager(afp, afp->mForkRefNum, + fileDataSize, + bytesPerSecond); + if (afp->mAudioFileManager == NULL) + { + delete_AudioFilePlayer(afp); + return NULL; + } + + return afp; +} + diff --git a/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.h b/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.h new file mode 100644 index 0000000..886d017 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/AudioFilePlayer.h @@ -0,0 +1,178 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + This file based on Apple sample code. We haven't changed the file name, + so if you want to see the original search for it on apple.com/developer +*/ +#include "SDL_config.h" + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AudioFilePlayer.h +*/ +#ifndef __AudioFilePlayer_H__ +#define __AudioFilePlayer_H__ + +#include <CoreServices/CoreServices.h> + +#include <AudioUnit/AudioUnit.h> +#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 +#include <AudioUnit/AUNTComponent.h> +#endif + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050) +typedef SInt16 FSIORefNum; +#endif + +#include "SDL_error.h" + +const char* AudioFilePlayerErrorStr (OSStatus error); + +/* +void ThrowResult (OSStatus result, const char *str); + +#define THROW_RESULT(str) \ + if (result) { \ + ThrowResult (result, str); \ + } +*/ + +typedef void (*AudioFilePlayNotifier)(void *inRefCon, + OSStatus inStatus); + +enum { + kAudioFilePlayErr_FilePlayUnderrun = -10000, + kAudioFilePlay_FileIsFinished = -10001, + kAudioFilePlay_PlayerIsUninitialized = -10002 +}; + + +struct S_AudioFileManager; + +#pragma mark __________ AudioFilePlayer +typedef struct S_AudioFilePlayer +{ +/*public:*/ + int (*SetDestination)(struct S_AudioFilePlayer *afp, AudioUnit *inDestUnit); + void (*SetNotifier)(struct S_AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon); + void (*SetStartFrame)(struct S_AudioFilePlayer *afp, int frame); /* seek in the file */ + int (*GetCurrentFrame)(struct S_AudioFilePlayer *afp); /* get the current frame position */ + void (*SetStopFrame)(struct S_AudioFilePlayer *afp, int frame); /* set limit in the file */ + int (*Connect)(struct S_AudioFilePlayer *afp); + void (*Disconnect)(struct S_AudioFilePlayer *afp); + void (*DoNotification)(struct S_AudioFilePlayer *afp, OSStatus inError); + int (*IsConnected)(struct S_AudioFilePlayer *afp); + AudioUnit (*GetDestUnit)(struct S_AudioFilePlayer *afp); + void (*Print)(struct S_AudioFilePlayer *afp); + +/*private:*/ + AudioUnit mPlayUnit; + FSIORefNum mForkRefNum; + + AURenderCallbackStruct mInputCallback; + + AudioStreamBasicDescription mFileDescription; + + int mConnected; + + struct S_AudioFileManager* mAudioFileManager; + + AudioFilePlayNotifier mNotifier; + void* mRefCon; + + int mStartFrame; + +#pragma mark __________ Private_Methods + + int (*OpenFile)(struct S_AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileSize); +} AudioFilePlayer; + + +AudioFilePlayer *new_AudioFilePlayer(const FSRef *inFileRef); +void delete_AudioFilePlayer(AudioFilePlayer *afp); + + + +#pragma mark __________ AudioFileManager +typedef struct S_AudioFileManager +{ +/*public:*/ + /* this method should NOT be called by an object of this class + as it is called by the parent's Disconnect() method */ + void (*Disconnect)(struct S_AudioFileManager *afm); + int (*DoConnect)(struct S_AudioFileManager *afm); + OSStatus (*Read)(struct S_AudioFileManager *afm, char *buffer, ByteCount *len); + const char* (*GetFileBuffer)(struct S_AudioFileManager *afm); + const AudioFilePlayer *(*GetParent)(struct S_AudioFileManager *afm); + void (*SetPosition)(struct S_AudioFileManager *afm, SInt64 pos); /* seek/rewind in the file */ + int (*GetByteCounter)(struct S_AudioFileManager *afm); /* return actual bytes streamed to audio hardware */ + void (*SetEndOfFile)(struct S_AudioFileManager *afm, SInt64 pos); /* set the "EOF" (will behave just like it reached eof) */ + +/*protected:*/ + AudioFilePlayer* mParent; + SInt16 mForkRefNum; + SInt64 mAudioDataOffset; + + char* mFileBuffer; + + int mByteCounter; + + int mReadFromFirstBuffer; + int mLockUnsuccessful; + int mIsEngaged; + + int mNumTimesAskedSinceFinished; + + + void* mTmpBuffer; + UInt32 mBufferSize; + UInt32 mBufferOffset; +/*public:*/ + UInt32 mChunkSize; + SInt64 mFileLength; + SInt64 mReadFilePosition; + int mWriteToFirstBuffer; + int mFinishedReadingData; + +/*protected:*/ + OSStatus (*Render)(struct S_AudioFileManager *afm, AudioBufferList *ioData); + OSStatus (*GetFileData)(struct S_AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize); + void (*AfterRender)(struct S_AudioFileManager *afm); + +/*public:*/ + /*static*/ + OSStatus (*FileInputProc)(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData); +} AudioFileManager; + + +AudioFileManager *new_AudioFileManager (AudioFilePlayer *inParent, + SInt16 inForkRefNum, + SInt64 inFileLength, + UInt32 inChunkSize); + +void delete_AudioFileManager(AudioFileManager *afm); + +#endif + diff --git a/3rdparty/SDL/src/cdrom/macosx/AudioFileReaderThread.c b/3rdparty/SDL/src/cdrom/macosx/AudioFileReaderThread.c new file mode 100644 index 0000000..0007c07 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/AudioFileReaderThread.c @@ -0,0 +1,610 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + This file based on Apple sample code. We haven't changed the file name, + so if you want to see the original search for it on apple.com/developer +*/ +#include "SDL_config.h" + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AudioFileManager.cpp +*/ +#include "AudioFilePlayer.h" +#include <mach/mach.h> /* used for setting policy of thread */ +#include "SDLOSXCAGuard.h" +#include <pthread.h> + +/*#include <list>*/ + +/*typedef void *FileData;*/ +typedef struct S_FileData +{ + AudioFileManager *obj; + struct S_FileData *next; +} FileData; + + +typedef struct S_FileReaderThread { +/*public:*/ + SDLOSXCAGuard* (*GetGuard)(struct S_FileReaderThread *frt); + void (*AddReader)(struct S_FileReaderThread *frt); + void (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem); + int (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem); + + int mThreadShouldDie; + +/*private:*/ + /*typedef std::list<AudioFileManager*> FileData;*/ + + SDLOSXCAGuard *mGuard; + UInt32 mThreadPriority; + + int mNumReaders; + FileData *mFileData; + + + void (*ReadNextChunk)(struct S_FileReaderThread *frt); + int (*StartFixedPriorityThread)(struct S_FileReaderThread *frt); + /*static*/ + UInt32 (*GetThreadBasePriority)(pthread_t inThread); + /*static*/ + void* (*DiskReaderEntry)(void *inRefCon); +} FileReaderThread; + + +static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt) +{ + return frt->mGuard; +} + +/* returns 1 if succeeded */ +static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem) +{ + int didLock = 0; + int succeeded = 0; + if (frt->mGuard->Try(frt->mGuard, &didLock)) + { + /*frt->mFileData.push_back (inItem);*/ + /* !!! FIXME: this could be faster with a "tail" member. --ryan. */ + FileData *i = frt->mFileData; + FileData *prev = NULL; + + FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData)); + newfd->obj = inItem; + newfd->next = NULL; + + while (i != NULL) { prev = i; i = i->next; } + if (prev == NULL) + frt->mFileData = newfd; + else + prev->next = newfd; + + frt->mGuard->Notify(frt->mGuard); + succeeded = 1; + + if (didLock) + frt->mGuard->Unlock(frt->mGuard); + } + + return succeeded; +} + +static void FileReaderThread_AddReader(FileReaderThread *frt) +{ + if (frt->mNumReaders == 0) + { + frt->mThreadShouldDie = 0; + frt->StartFixedPriorityThread (frt); + } + frt->mNumReaders++; +} + +static void FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem) +{ + if (frt->mNumReaders > 0) + { + int bNeedsRelease = frt->mGuard->Lock(frt->mGuard); + + /*frt->mFileData.remove (inItem);*/ + FileData *i = frt->mFileData; + FileData *prev = NULL; + while (i != NULL) + { + FileData *next = i->next; + if (i->obj != inItem) + prev = i; + else + { + if (prev == NULL) + frt->mFileData = next; + else + prev->next = next; + SDL_free(i); + } + i = next; + } + + if (--frt->mNumReaders == 0) { + frt->mThreadShouldDie = 1; + frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */ + frt->mGuard->Wait(frt->mGuard); /* wait for thread to die */ + } + + if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); + } +} + +static int FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt) +{ + pthread_attr_t theThreadAttrs; + pthread_t pThread; + + OSStatus result = pthread_attr_init(&theThreadAttrs); + if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/ + + result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED); + if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/ + + result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt); + if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/ + + pthread_attr_destroy(&theThreadAttrs); + + /* we've now created the thread and started it + we'll now set the priority of the thread to the nominated priority + and we'll also make the thread fixed */ + thread_extended_policy_data_t theFixedPolicy; + thread_precedence_policy_data_t thePrecedencePolicy; + SInt32 relativePriority; + + /* make thread fixed */ + theFixedPolicy.timeshare = 0; /* set to 1 for a non-fixed thread */ + result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); + if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/ + /* set priority */ + /* precedency policy's "importance" value is relative to spawning thread's priority */ + relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self()); + + thePrecedencePolicy.importance = relativePriority; + result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); + if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/ + + return 1; +} + +static UInt32 FileReaderThread_GetThreadBasePriority (pthread_t inThread) +{ + thread_basic_info_data_t threadInfo; + policy_info_data_t thePolicyInfo; + unsigned int count; + + /* get basic info */ + count = THREAD_BASIC_INFO_COUNT; + thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count); + + switch (threadInfo.policy) { + case POLICY_TIMESHARE: + count = POLICY_TIMESHARE_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count); + return thePolicyInfo.ts.base_priority; + break; + + case POLICY_FIFO: + count = POLICY_FIFO_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count); + if (thePolicyInfo.fifo.depressed) { + return thePolicyInfo.fifo.depress_priority; + } else { + return thePolicyInfo.fifo.base_priority; + } + break; + + case POLICY_RR: + count = POLICY_RR_INFO_COUNT; + thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count); + if (thePolicyInfo.rr.depressed) { + return thePolicyInfo.rr.depress_priority; + } else { + return thePolicyInfo.rr.base_priority; + } + break; + } + + return 0; +} + +static void *FileReaderThread_DiskReaderEntry (void *inRefCon) +{ + FileReaderThread *frt = (FileReaderThread *)inRefCon; + frt->ReadNextChunk(frt); + #if DEBUG + printf ("finished with reading file\n"); + #endif + + return 0; +} + +static void FileReaderThread_ReadNextChunk (FileReaderThread *frt) +{ + OSStatus result; + ByteCount dataChunkSize; + AudioFileManager* theItem = 0; + + for (;;) + { + { /* this is a scoped based lock */ + int bNeedsRelease = frt->mGuard->Lock(frt->mGuard); + + if (frt->mThreadShouldDie) { + frt->mGuard->Notify(frt->mGuard); + if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); + return; + } + + /*if (frt->mFileData.empty())*/ + if (frt->mFileData == NULL) + { + frt->mGuard->Wait(frt->mGuard); + } + + /* kill thread */ + if (frt->mThreadShouldDie) { + + frt->mGuard->Notify(frt->mGuard); + if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); + return; + } + + /*theItem = frt->mFileData.front();*/ + /*frt->mFileData.pop_front();*/ + theItem = NULL; + if (frt->mFileData != NULL) + { + FileData *next = frt->mFileData->next; + theItem = frt->mFileData->obj; + SDL_free(frt->mFileData); + frt->mFileData = next; + } + + if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); + } + + if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize) + dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition; + else + dataChunkSize = theItem->mChunkSize; + + /* this is the exit condition for the thread */ + if (dataChunkSize <= 0) { + theItem->mFinishedReadingData = 1; + continue; + } + /* construct pointer */ + char* writePtr = (char *) (theItem->GetFileBuffer(theItem) + + (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); + + /* read data */ + result = theItem->Read(theItem, writePtr, &dataChunkSize); + if (result != noErr && result != eofErr) { + AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem); + afp->DoNotification(afp, result); + continue; + } + + if (dataChunkSize != theItem->mChunkSize) + { + writePtr += dataChunkSize; + + /* can't exit yet.. we still have to pass the partial buffer back */ + SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize)); + } + + theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; /* switch buffers */ + + if (result == eofErr) + theItem->mReadFilePosition = theItem->mFileLength; + else + theItem->mReadFilePosition += dataChunkSize; /* increment count */ + } +} + +void delete_FileReaderThread(FileReaderThread *frt) +{ + if (frt != NULL) + { + delete_SDLOSXCAGuard(frt->mGuard); + SDL_free(frt); + } +} + +FileReaderThread *new_FileReaderThread () +{ + FileReaderThread *frt = (FileReaderThread *) SDL_malloc(sizeof (FileReaderThread)); + if (frt == NULL) + return NULL; + SDL_memset(frt, '\0', sizeof (*frt)); + + frt->mGuard = new_SDLOSXCAGuard(); + if (frt->mGuard == NULL) + { + SDL_free(frt); + return NULL; + } + + #define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m + SET_FILEREADERTHREAD_METHOD(GetGuard); + SET_FILEREADERTHREAD_METHOD(AddReader); + SET_FILEREADERTHREAD_METHOD(RemoveReader); + SET_FILEREADERTHREAD_METHOD(TryNextRead); + SET_FILEREADERTHREAD_METHOD(ReadNextChunk); + SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread); + SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority); + SET_FILEREADERTHREAD_METHOD(DiskReaderEntry); + #undef SET_FILEREADERTHREAD_METHOD + + frt->mThreadPriority = 62; + return frt; +} + + +static FileReaderThread *sReaderThread; + + +static int AudioFileManager_DoConnect (AudioFileManager *afm) +{ + if (!afm->mIsEngaged) + { + OSStatus result; + + /*afm->mReadFilePosition = 0;*/ + afm->mFinishedReadingData = 0; + + afm->mNumTimesAskedSinceFinished = 0; + afm->mLockUnsuccessful = 0; + + ByteCount dataChunkSize; + + if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize) + dataChunkSize = afm->mFileLength - afm->mReadFilePosition; + else + dataChunkSize = afm->mChunkSize; + + result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize); + if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/ + + afm->mReadFilePosition += dataChunkSize; + + afm->mWriteToFirstBuffer = 0; + afm->mReadFromFirstBuffer = 1; + + sReaderThread->AddReader(sReaderThread); + + afm->mIsEngaged = 1; + } + /* + else + throw static_cast<OSStatus>(-1); */ /* thread has already been started */ + + return 1; +} + +static void AudioFileManager_Disconnect (AudioFileManager *afm) +{ + if (afm->mIsEngaged) + { + sReaderThread->RemoveReader (sReaderThread, afm); + afm->mIsEngaged = 0; + } +} + +static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, ByteCount *len) +{ + return FSReadFork (afm->mForkRefNum, + fsFromStart, + afm->mReadFilePosition + afm->mAudioDataOffset, + *len, + buffer, + len); +} + +static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize) +{ + if (afm->mFinishedReadingData) + { + ++afm->mNumTimesAskedSinceFinished; + *inOutDataSize = 0; + *inOutData = 0; + return noErr; + } + + if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) { + #if DEBUG + printf ("* * * * * * * Can't keep up with reading file\n"); + #endif + + afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun); + *inOutDataSize = 0; + *inOutData = 0; + } else { + *inOutDataSize = afm->mChunkSize; + *inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize); + } + + afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm); + + afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer; + + return noErr; +} + +static void AudioFileManager_AfterRender (AudioFileManager *afm) +{ + if (afm->mNumTimesAskedSinceFinished > 0) + { + int didLock = 0; + SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread); + if (guard->Try(guard, &didLock)) { + afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished); + if (didLock) + guard->Unlock(guard); + } + } + + if (afm->mLockUnsuccessful) + afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm); +} + +static void AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos) +{ + if (pos < 0 || pos >= afm->mFileLength) { + SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n", + (unsigned int)pos, (unsigned int)afm->mFileLength); + pos = 0; + } + + afm->mReadFilePosition = pos; +} + +static void AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos) +{ + if (pos <= 0 || pos > afm->mFileLength) { + SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n"); + pos = afm->mFileLength; + } + + afm->mFileLength = pos; +} + +static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm) +{ + return afm->mFileBuffer; +} + +const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm) +{ + return afm->mParent; +} + +static int AudioFileManager_GetByteCounter(AudioFileManager *afm) +{ + return afm->mByteCounter; +} + +static OSStatus AudioFileManager_FileInputProc (void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) +{ + AudioFileManager* afm = (AudioFileManager*)inRefCon; + return afm->Render(afm, ioData); +} + +static OSStatus AudioFileManager_Render (AudioFileManager *afm, AudioBufferList *ioData) +{ + OSStatus result = noErr; + AudioBuffer *abuf; + UInt32 i; + + for (i = 0; i < ioData->mNumberBuffers; i++) { + abuf = &ioData->mBuffers[i]; + if (afm->mBufferOffset >= afm->mBufferSize) { + result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize); + if (result) { + SDL_SetError ("AudioConverterFillBuffer:%ld\n", result); + afm->mParent->DoNotification(afm->mParent, result); + return result; + } + + afm->mBufferOffset = 0; + } + + if (abuf->mDataByteSize > afm->mBufferSize - afm->mBufferOffset) + abuf->mDataByteSize = afm->mBufferSize - afm->mBufferOffset; + abuf->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset; + afm->mBufferOffset += abuf->mDataByteSize; + + afm->mByteCounter += abuf->mDataByteSize; + afm->AfterRender(afm); + } + return result; +} + + +void delete_AudioFileManager (AudioFileManager *afm) +{ + if (afm != NULL) { + if (afm->mFileBuffer) { + free(afm->mFileBuffer); + } + + SDL_free(afm); + } +} + + +AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent, + SInt16 inForkRefNum, + SInt64 inFileLength, + UInt32 inChunkSize) +{ + AudioFileManager *afm; + + if (sReaderThread == NULL) + { + sReaderThread = new_FileReaderThread(); + if (sReaderThread == NULL) + return NULL; + } + + afm = (AudioFileManager *) SDL_malloc(sizeof (AudioFileManager)); + if (afm == NULL) + return NULL; + SDL_memset(afm, '\0', sizeof (*afm)); + + #define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m + SET_AUDIOFILEMANAGER_METHOD(Disconnect); + SET_AUDIOFILEMANAGER_METHOD(DoConnect); + SET_AUDIOFILEMANAGER_METHOD(Read); + SET_AUDIOFILEMANAGER_METHOD(GetFileBuffer); + SET_AUDIOFILEMANAGER_METHOD(GetParent); + SET_AUDIOFILEMANAGER_METHOD(SetPosition); + SET_AUDIOFILEMANAGER_METHOD(GetByteCounter); + SET_AUDIOFILEMANAGER_METHOD(SetEndOfFile); + SET_AUDIOFILEMANAGER_METHOD(Render); + SET_AUDIOFILEMANAGER_METHOD(GetFileData); + SET_AUDIOFILEMANAGER_METHOD(AfterRender); + SET_AUDIOFILEMANAGER_METHOD(FileInputProc); + #undef SET_AUDIOFILEMANAGER_METHOD + + afm->mParent = inParent; + afm->mForkRefNum = inForkRefNum; + afm->mBufferSize = inChunkSize; + afm->mBufferOffset = inChunkSize; + afm->mChunkSize = inChunkSize; + afm->mFileLength = inFileLength; + afm->mFileBuffer = (char*) SDL_malloc(afm->mChunkSize * 2); + FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset); + assert (afm->mFileBuffer != NULL); + return afm; +} + diff --git a/3rdparty/SDL/src/cdrom/macosx/CDPlayer.c b/3rdparty/SDL/src/cdrom/macosx/CDPlayer.c new file mode 100644 index 0000000..beb87cd --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/CDPlayer.c @@ -0,0 +1,636 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "CDPlayer.h" +#include "AudioFilePlayer.h" +#include "SDLOSXCAGuard.h" + +/* we're exporting these functions into C land for SDL_syscdrom.c */ +/*extern "C" {*/ + +/*/////////////////////////////////////////////////////////////////////////// + Constants + //////////////////////////////////////////////////////////////////////////*/ + +#define kAudioCDFilesystemID (UInt16)(('J' << 8) | 'H') /* 'JH'; this avoids compiler warning */ + +/* XML PList keys */ +#define kRawTOCDataString "Format 0x02 TOC Data" +#define kSessionsString "Sessions" +#define kSessionTypeString "Session Type" +#define kTrackArrayString "Track Array" +#define kFirstTrackInSessionString "First Track" +#define kLastTrackInSessionString "Last Track" +#define kLeadoutBlockString "Leadout Block" +#define kDataKeyString "Data" +#define kPointKeyString "Point" +#define kSessionNumberKeyString "Session Number" +#define kStartBlockKeyString "Start Block" + +/*/////////////////////////////////////////////////////////////////////////// + Globals + //////////////////////////////////////////////////////////////////////////*/ + +#pragma mark -- Globals -- + +static int playBackWasInit = 0; +static AudioUnit theUnit; +static AudioFilePlayer* thePlayer = NULL; +static CDPlayerCompletionProc completionProc = NULL; +static SDL_mutex *apiMutex = NULL; +static SDL_sem *callbackSem; +static SDL_CD* theCDROM; + +/*/////////////////////////////////////////////////////////////////////////// + Prototypes + //////////////////////////////////////////////////////////////////////////*/ + +#pragma mark -- Prototypes -- + +static OSStatus CheckInit (); + +static void FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus); + +static int RunCallBackThread (void* inRefCon); + + +#pragma mark -- Public Functions -- + +void Lock () +{ + if (!apiMutex) { + apiMutex = SDL_CreateMutex(); + } + SDL_mutexP(apiMutex); +} + +void Unlock () +{ + SDL_mutexV(apiMutex); +} + +int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) +{ + int volumeIndex; + int cdVolumeCount = 0; + OSStatus result = noErr; + + for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) + { + FSVolumeRefNum actualVolume; + FSVolumeInfo volumeInfo; + + memset (&volumeInfo, 0, sizeof(volumeInfo)); + + result = FSGetVolumeInfo (kFSInvalidVolumeRefNum, + volumeIndex, + &actualVolume, + kFSVolInfoFSInfo, + &volumeInfo, + NULL, + NULL); + + if (result == noErr) + { + if (volumeInfo.filesystemID == kAudioCDFilesystemID) /* It's an audio CD */ + { + if (volumes != NULL && cdVolumeCount < numVolumes) + volumes[cdVolumeCount] = actualVolume; + + cdVolumeCount++; + } + } + else + { + /* I'm commenting this out because it seems to be harmless */ + /*SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result);*/ + } + } + + return cdVolumeCount; +} + +int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD) +{ + HFSUniStr255 dataForkName; + OSStatus theErr; + FSIORefNum forkRefNum; + SInt64 forkSize; + Ptr forkData = 0; + ByteCount actualRead; + CFDataRef dataRef = 0; + CFPropertyListRef propertyListRef = 0; + FSRefParam fsRefPB; + FSRef tocPlistFSRef; + FSRef rootRef; + const char* error = "Unspecified Error"; + const UniChar uniName[] = { '.','T','O','C','.','p','l','i','s','t' }; + + theErr = FSGetVolumeInfo(theVolume, 0, 0, kFSVolInfoNone, 0, 0, &rootRef); + if(theErr != noErr) { + error = "FSGetVolumeInfo"; + goto bail; + } + + SDL_memset(&fsRefPB, '\0', sizeof (fsRefPB)); + + /* get stuff from .TOC.plist */ + fsRefPB.ref = &rootRef; + fsRefPB.newRef = &tocPlistFSRef; + fsRefPB.nameLength = sizeof (uniName) / sizeof (uniName[0]); + fsRefPB.name = uniName; + fsRefPB.textEncodingHint = kTextEncodingUnknown; + + theErr = PBMakeFSRefUnicodeSync (&fsRefPB); + if(theErr != noErr) { + error = "PBMakeFSRefUnicodeSync"; + goto bail; + } + + /* Load and parse the TOC XML data */ + + theErr = FSGetDataForkName (&dataForkName); + if (theErr != noErr) { + error = "FSGetDataForkName"; + goto bail; + } + + theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); + if (theErr != noErr) { + error = "FSOpenFork"; + goto bail; + } + + theErr = FSGetForkSize (forkRefNum, &forkSize); + if (theErr != noErr) { + error = "FSGetForkSize"; + goto bail; + } + + /* Allocate some memory for the XML data */ + forkData = NewPtr (forkSize); + if(forkData == NULL) { + error = "NewPtr"; + goto bail; + } + + theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead); + if(theErr != noErr) { + error = "FSReadFork"; + goto bail; + } + + dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize); + if(dataRef == 0) { + error = "CFDataCreate"; + goto bail; + } + + propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, + dataRef, + kCFPropertyListImmutable, + NULL); + if (propertyListRef == NULL) { + error = "CFPropertyListCreateFromXMLData"; + goto bail; + } + + /* Now we got the Property List in memory. Parse it. */ + + /* First, make sure the root item is a CFDictionary. If not, release and bail. */ + if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID()) + { + CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef; + + CFDataRef theRawTOCDataRef; + CFArrayRef theSessionArrayRef; + CFIndex numSessions; + CFIndex index; + + /* This is how we get the Raw TOC Data */ + theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString)); + + /* Get the session array info. */ + theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString)); + + /* Find out how many sessions there are. */ + numSessions = CFArrayGetCount (theSessionArrayRef); + + /* Initialize the total number of tracks to 0 */ + theCD->numtracks = 0; + + /* Iterate over all sessions, collecting the track data */ + for(index = 0; index < numSessions; index++) + { + CFDictionaryRef theSessionDict; + CFNumberRef leadoutBlock; + CFArrayRef trackArray; + CFIndex numTracks; + CFIndex trackIndex; + UInt32 value = 0; + + theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index); + leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString)); + + trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString)); + + numTracks = CFArrayGetCount (trackArray); + + for(trackIndex = 0; trackIndex < numTracks; trackIndex++) { + + CFDictionaryRef theTrackDict; + CFNumberRef trackNumber; + CFNumberRef sessionNumber; + CFNumberRef startBlock; + CFBooleanRef isDataTrack; + UInt32 value; + + theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex); + + trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString)); + sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString)); + startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString)); + isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString)); + + /* Fill in the SDL_CD struct */ + int idx = theCD->numtracks++; + + CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value); + theCD->track[idx].id = value; + + CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value); + theCD->track[idx].offset = value; + + theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; + + /* Since the track lengths are not stored in .TOC.plist we compute them. */ + if (trackIndex > 0) { + theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset; + } + } + + /* Compute the length of the last track */ + CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value); + + theCD->track[theCD->numtracks-1].length = + value - theCD->track[theCD->numtracks-1].offset; + + /* Set offset to leadout track */ + theCD->track[theCD->numtracks].offset = value; + } + + } + + theErr = 0; + goto cleanup; +bail: + SDL_SetError ("ReadTOCData: %s returned %d", error, theErr); + theErr = -1; +cleanup: + + if (propertyListRef != NULL) + CFRelease(propertyListRef); + if (dataRef != NULL) + CFRelease(dataRef); + if (forkData != NULL) + DisposePtr(forkData); + + FSCloseFork (forkRefNum); + + return theErr; +} + +int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks) +{ + OSStatus result = -1; + FSIterator iterator; + ItemCount actualObjects; + FSRef rootDirectory; + FSRef ref; + HFSUniStr255 nameStr; + + result = FSGetVolumeInfo (theVolume, + 0, + NULL, + kFSVolInfoFSInfo, + NULL, + NULL, + &rootDirectory); + + if (result != noErr) { + SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result); + return result; + } + + result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator); + if (result == noErr) { + do + { + result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects, + NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr); + if (result == noErr) { + + CFStringRef name; + name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length); + + /* Look for .aiff extension */ + if (CFStringHasSuffix (name, CFSTR(".aiff")) || + CFStringHasSuffix (name, CFSTR(".cdda"))) { + + /* Extract the track id from the filename */ + int trackID = 0, i = 0; + while (i < nameStr.length && !isdigit(nameStr.unicode[i])) { + ++i; + } + while (i < nameStr.length && isdigit(nameStr.unicode[i])) { + trackID = 10 * trackID +(nameStr.unicode[i] - '0'); + ++i; + } + + #if DEBUG_CDROM + printf("Found AIFF for track %d: '%s'\n", trackID, + CFStringGetCStringPtr (name, CFStringGetSystemEncoding())); + #endif + + /* Track ID's start at 1, but we want to start at 0 */ + trackID--; + + assert(0 <= trackID && trackID <= SDL_MAX_TRACKS); + + if (trackID < numTracks) + memcpy (&trackFiles[trackID], &ref, sizeof(FSRef)); + } + CFRelease (name); + } + } while(noErr == result); + FSCloseIterator (iterator); + } + + return 0; +} + +int LoadFile (const FSRef *ref, int startFrame, int stopFrame) +{ + int error = -1; + + if (CheckInit () < 0) + goto bail; + + /* release any currently playing file */ + if (ReleaseFile () < 0) + goto bail; + + #if DEBUG_CDROM + printf ("LoadFile: %d %d\n", startFrame, stopFrame); + #endif + + /*try {*/ + + /* create a new player, and attach to the audio unit */ + + thePlayer = new_AudioFilePlayer(ref); + if (thePlayer == NULL) { + SDL_SetError ("LoadFile: Could not create player"); + return -3; /*throw (-3);*/ + } + + if (!thePlayer->SetDestination(thePlayer, &theUnit)) + goto bail; + + if (startFrame >= 0) + thePlayer->SetStartFrame (thePlayer, startFrame); + + if (stopFrame >= 0 && stopFrame > startFrame) + thePlayer->SetStopFrame (thePlayer, stopFrame); + + /* we set the notifier later */ + /*thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);*/ + + if (!thePlayer->Connect(thePlayer)) + goto bail; + + #if DEBUG_CDROM + thePlayer->Print(thePlayer); + fflush (stdout); + #endif + /*} + catch (...) + { + goto bail; + }*/ + + error = 0; + + bail: + return error; +} + +int ReleaseFile () +{ + int error = -1; + + /* (Don't see any way that the original C++ code could throw here.) --ryan. */ + /*try {*/ + if (thePlayer != NULL) { + + thePlayer->Disconnect(thePlayer); + + delete_AudioFilePlayer(thePlayer); + + thePlayer = NULL; + } + /*} + catch (...) + { + goto bail; + }*/ + + error = 0; + +/* bail: */ + return error; +} + +int PlayFile () +{ + OSStatus result = -1; + + if (CheckInit () < 0) + goto bail; + + /*try {*/ + + // start processing of the audio unit + result = AudioOutputUnitStart (theUnit); + if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart") + + /*} + catch (...) + { + goto bail; + }*/ + + result = 0; + +bail: + return result; +} + +int PauseFile () +{ + OSStatus result = -1; + + if (CheckInit () < 0) + goto bail; + + /*try {*/ + + /* stop processing the audio unit */ + result = AudioOutputUnitStop (theUnit); + if (result) goto bail; /*THROW_RESULT("PauseFile: AudioOutputUnitStop")*/ + /*} + catch (...) + { + goto bail; + }*/ + + result = 0; +bail: + return result; +} + +void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom) +{ + assert(thePlayer != NULL); + + theCDROM = cdrom; + completionProc = proc; + thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom); +} + +int GetCurrentFrame () +{ + int frame; + + if (thePlayer == NULL) + frame = 0; + else + frame = thePlayer->GetCurrentFrame (thePlayer); + + return frame; +} + + +#pragma mark -- Private Functions -- + +static OSStatus CheckInit () +{ + if (playBackWasInit) + return 0; + + OSStatus result = noErr; + + /* Create the callback semaphore */ + callbackSem = SDL_CreateSemaphore(0); + + /* Start callback thread */ + SDL_CreateThread(RunCallBackThread, NULL); + + { /*try {*/ + ComponentDescription desc; + + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + Component comp = FindNextComponent (NULL, &desc); + if (comp == NULL) { + SDL_SetError ("CheckInit: FindNextComponent returned NULL"); + if (result) return -1; //throw(internalComponentErr); + } + + result = OpenAComponent (comp, &theUnit); + if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent") + + // you need to initialize the output unit before you set it as a destination + result = AudioUnitInitialize (theUnit); + if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize") + + + playBackWasInit = true; + } + /*catch (...) + { + return -1; + }*/ + + return 0; +} + +static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus) +{ + if (inStatus == kAudioFilePlay_FileIsFinished) { + + /* notify non-CA thread to perform the callback */ + SDL_SemPost(callbackSem); + + } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) { + + SDL_SetError ("CDPlayer Notification: buffer underrun"); + } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) { + + SDL_SetError ("CDPlayer Notification: player is uninitialized"); + } else { + + SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus); + } +} + +static int RunCallBackThread (void *param) +{ + for (;;) { + + SDL_SemWait(callbackSem); + + if (completionProc && theCDROM) { + #if DEBUG_CDROM + printf ("callback!\n"); + #endif + (*completionProc)(theCDROM); + } else { + #if DEBUG_CDROM + printf ("callback?\n"); + #endif + } + } + + #if DEBUG_CDROM + printf ("thread dying now...\n"); + #endif + + return 0; +} + +/*}; // extern "C" */ diff --git a/3rdparty/SDL/src/cdrom/macosx/CDPlayer.h b/3rdparty/SDL/src/cdrom/macosx/CDPlayer.h new file mode 100644 index 0000000..be1ac18 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/CDPlayer.h @@ -0,0 +1,69 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __CDPlayer__H__ +#define __CDPlayer__H__ 1 + +#include <string.h> + +#include <Carbon/Carbon.h> +#include <CoreFoundation/CoreFoundation.h> +#include <AudioUnit/AudioUnit.h> + +#include "SDL.h" +#include "SDL_thread.h" +#include "SDL_mutex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*CDPlayerCompletionProc)(SDL_CD *cdrom) ; + +void Lock (); + +void Unlock(); + +int LoadFile (const FSRef *ref, int startFrame, int endFrame); /* pass -1 to do nothing */ + +int ReleaseFile (); + +int PlayFile (); + +int PauseFile (); + +void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom); + +int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD); + +int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks); + +int DetectAudioCDVolumes (FSVolumeRefNum *volumes, int numVolumes); + +int GetCurrentFrame (); + +#ifdef __cplusplus +}; +#endif + +#endif /* __CD_Player__H__ */ diff --git a/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.c b/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.c new file mode 100644 index 0000000..e8caf1b --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.c @@ -0,0 +1,199 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Note: This file hasn't been modified so technically we have to keep the disclaimer :-( + + Copyright: Copyright 2002 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apples + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*============================================================================= + CAGuard.cp + +=============================================================================*/ + +/*============================================================================= + Includes + =============================================================================*/ + +/* +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +*/ +#include "SDL_stdinc.h" + +/*#define NDEBUG 1*/ +/* +#include <assert.h> +*/ +#define assert(X) + + +#include "SDLOSXCAGuard.h" + +/*#warning Need a try-based Locker too*/ +/*============================================================================= + SDLOSXCAGuard + =============================================================================*/ + +static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag) +{ + int theAnswer = 0; + + if(pthread_self() != cag->mOwner) + { + OSStatus theError = pthread_mutex_lock(&cag->mMutex); + (void)theError; + assert(theError == 0); + cag->mOwner = pthread_self(); + theAnswer = 1; + } + + return theAnswer; +} + +static void SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag) +{ + OSStatus theError; + assert(pthread_self() == cag->mOwner); + + cag->mOwner = 0; + theError = pthread_mutex_unlock(&cag->mMutex); + (void)theError; + assert(theError == 0); +} + +static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked) +{ + int theAnswer = 0; + *outWasLocked = 0; + + if (pthread_self() == cag->mOwner) { + theAnswer = 1; + *outWasLocked = 0; + } else { + OSStatus theError = pthread_mutex_trylock(&cag->mMutex); + if (theError == 0) { + cag->mOwner = pthread_self(); + theAnswer = 1; + *outWasLocked = 1; + } + } + + return theAnswer; +} + +static void SDLOSXCAGuard_Wait(SDLOSXCAGuard *cag) +{ + OSStatus theError; + assert(pthread_self() == cag->mOwner); + + cag->mOwner = 0; + + theError = pthread_cond_wait(&cag->mCondVar, &cag->mMutex); + (void)theError; + assert(theError == 0); + cag->mOwner = pthread_self(); +} + +static void SDLOSXCAGuard_Notify(SDLOSXCAGuard *cag) +{ + OSStatus theError = pthread_cond_signal(&cag->mCondVar); + (void)theError; + assert(theError == 0); +} + + +SDLOSXCAGuard *new_SDLOSXCAGuard(void) +{ + OSStatus theError; + SDLOSXCAGuard *cag = (SDLOSXCAGuard *) SDL_malloc(sizeof (SDLOSXCAGuard)); + if (cag == NULL) + return NULL; + SDL_memset(cag, '\0', sizeof (*cag)); + + #define SET_SDLOSXCAGUARD_METHOD(m) cag->m = SDLOSXCAGuard_##m + SET_SDLOSXCAGUARD_METHOD(Lock); + SET_SDLOSXCAGUARD_METHOD(Unlock); + SET_SDLOSXCAGUARD_METHOD(Try); + SET_SDLOSXCAGUARD_METHOD(Wait); + SET_SDLOSXCAGUARD_METHOD(Notify); + #undef SET_SDLOSXCAGUARD_METHOD + + theError = pthread_mutex_init(&cag->mMutex, NULL); + (void)theError; + assert(theError == 0); + + theError = pthread_cond_init(&cag->mCondVar, NULL); + (void)theError; + assert(theError == 0); + + cag->mOwner = 0; + return cag; +} + +void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag) +{ + if (cag != NULL) + { + pthread_mutex_destroy(&cag->mMutex); + pthread_cond_destroy(&cag->mCondVar); + SDL_free(cag); + } +} + diff --git a/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.h b/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.h new file mode 100644 index 0000000..f22c695 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/SDLOSXCAGuard.h @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Note: This file hasn't been modified so technically we have to keep the disclaimer :-( + + + Copyright: Copyright 2002 Apple Computer, Inc. All rights reserved. + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under Apples + copyrights in this original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks or logos of + Apple Computer, Inc. may be used to endorse or promote products derived from the + Apple Software without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any patent rights that + may be infringed by your derivative works or by other works in which the Apple + Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT + (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*============================================================================= + CAGuard.h + +=============================================================================*/ +#if !defined(__CAGuard_h__) +#define __CAGuard_h__ + +/*============================================================================= + Includes + =============================================================================*/ + +#include <CoreAudio/CoreAudioTypes.h> +#include <pthread.h> + + +/*============================================================================= + CAGuard + + This is your typical mutex with signalling implemented via pthreads. + Lock() will return true if and only if the guard is locked on that call. + A thread that already has the guard will receive 'false' if it locks it + again. Use of the stack-based CAGuard::Locker class is highly recommended + to properly manage the recursive nesting. The Wait calls with timeouts + will return true if and only if the timeout period expired. They will + return false if they receive notification any other way. + =============================================================================*/ + +typedef struct S_SDLOSXCAGuard +{ + +/* Construction/Destruction */ +/*public:*/ +/* Actions */ +/*public:*/ + int (*Lock)(struct S_SDLOSXCAGuard *cag); + void (*Unlock)(struct S_SDLOSXCAGuard *cag); + int (*Try)(struct S_SDLOSXCAGuard *cag, int *outWasLocked); /* returns true if lock is free, false if not */ + void (*Wait)(struct S_SDLOSXCAGuard *cag); + void (*Notify)(struct S_SDLOSXCAGuard *cag); + +/* Implementation */ +/*protected:*/ + pthread_mutex_t mMutex; + pthread_cond_t mCondVar; + pthread_t mOwner; +} SDLOSXCAGuard; + +SDLOSXCAGuard *new_SDLOSXCAGuard(void); +void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag); + +#endif + diff --git a/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom.c new file mode 100644 index 0000000..5018750 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom.c @@ -0,0 +1,514 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_MACOSX + +#include "SDL_syscdrom_c.h" + +#pragma mark -- Globals -- + +static FSRef** tracks; +static FSVolumeRefNum* volumes; +static CDstatus status; +static int nextTrackFrame; +static int nextTrackFramesRemaining; +static int fakeCD; +static int currentTrack; +static int didReadTOC; +static int cacheTOCNumTracks; +static int currentDrive; /* Only allow 1 drive in use at a time */ + +#pragma mark -- Prototypes -- + +static const char *SDL_SYS_CDName (int drive); +static int SDL_SYS_CDOpen (int drive); +static int SDL_SYS_CDGetTOC (SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay (SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause (SDL_CD *cdrom); +static int SDL_SYS_CDResume (SDL_CD *cdrom); +static int SDL_SYS_CDStop (SDL_CD *cdrom); +static int SDL_SYS_CDEject (SDL_CD *cdrom); +static void SDL_SYS_CDClose (SDL_CD *cdrom); + +#pragma mark -- Helper Functions -- + +/* Read a list of tracks from the volume */ +static int LoadTracks (SDL_CD *cdrom) +{ + /* Check if tracks are already loaded */ + if ( tracks[cdrom->id] != NULL ) + return 0; + + /* Allocate memory for tracks */ + tracks[cdrom->id] = (FSRef*) SDL_calloc (1, sizeof(**tracks) * cdrom->numtracks); + if (tracks[cdrom->id] == NULL) { + SDL_OutOfMemory (); + return -1; + } + + /* Load tracks */ + if (ListTrackFiles (volumes[cdrom->id], tracks[cdrom->id], cdrom->numtracks) < 0) + return -1; + + return 0; +} + +/* Find a file for a given start frame and length */ +static FSRef* GetFileForOffset (SDL_CD *cdrom, int start, int length, int *outStartFrame, int *outStopFrame) +{ + int i; + + for (i = 0; i < cdrom->numtracks; i++) { + + if (cdrom->track[i].offset <= start && + start < (cdrom->track[i].offset + cdrom->track[i].length)) + break; + } + + if (i == cdrom->numtracks) + return NULL; + + currentTrack = i; + + *outStartFrame = start - cdrom->track[i].offset; + + if ((*outStartFrame + length) < cdrom->track[i].length) { + *outStopFrame = *outStartFrame + length; + length = 0; + nextTrackFrame = -1; + nextTrackFramesRemaining = -1; + } + else { + *outStopFrame = -1; + length -= cdrom->track[i].length - *outStartFrame; + nextTrackFrame = cdrom->track[i+1].offset; + nextTrackFramesRemaining = length; + } + + return &tracks[cdrom->id][i]; +} + +/* Setup another file for playback, or stop playback (called from another thread) */ +static void CompletionProc (SDL_CD *cdrom) +{ + + Lock (); + + if (nextTrackFrame > 0 && nextTrackFramesRemaining > 0) { + + /* Load the next file to play */ + int startFrame, stopFrame; + FSRef *file; + + PauseFile (); + ReleaseFile (); + + file = GetFileForOffset (cdrom, nextTrackFrame, + nextTrackFramesRemaining, &startFrame, &stopFrame); + + if (file == NULL) { + status = CD_STOPPED; + Unlock (); + return; + } + + LoadFile (file, startFrame, stopFrame); + + SetCompletionProc (CompletionProc, cdrom); + + PlayFile (); + } + else { + + /* Release the current file */ + PauseFile (); + ReleaseFile (); + status = CD_STOPPED; + } + + Unlock (); +} + + +#pragma mark -- Driver Functions -- + +/* Initialize */ +int SDL_SYS_CDInit (void) +{ + /* Initialize globals */ + volumes = NULL; + tracks = NULL; + status = CD_STOPPED; + nextTrackFrame = -1; + nextTrackFramesRemaining = -1; + fakeCD = SDL_FALSE; + currentTrack = -1; + didReadTOC = SDL_FALSE; + cacheTOCNumTracks = -1; + currentDrive = -1; + + /* Fill in function pointers */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* + Read the list of "drives" + + This is currently a hack that infers drives from + mounted audio CD volumes, rather than + actual CD-ROM devices - which means it may not + act as expected sometimes. + */ + + /* Find out how many cd volumes are mounted */ + SDL_numcds = DetectAudioCDVolumes (NULL, 0); + + /* + If there are no volumes, fake a cd device + so tray empty can be reported. + */ + if (SDL_numcds == 0) { + + fakeCD = SDL_TRUE; + SDL_numcds = 1; + status = CD_TRAYEMPTY; + + return 0; + } + + /* Allocate space for volumes */ + volumes = (FSVolumeRefNum*) SDL_calloc (1, sizeof(*volumes) * SDL_numcds); + if (volumes == NULL) { + SDL_OutOfMemory (); + return -1; + } + + /* Allocate space for tracks */ + tracks = (FSRef**) SDL_calloc (1, sizeof(*tracks) * (SDL_numcds + 1)); + if (tracks == NULL) { + SDL_OutOfMemory (); + return -1; + } + + /* Mark the end of the tracks array */ + tracks[ SDL_numcds ] = (FSRef*)-1; + + /* + Redetect, now save all volumes for later + Update SDL_numcds just in case it changed + */ + { + int numVolumes = SDL_numcds; + + SDL_numcds = DetectAudioCDVolumes (volumes, numVolumes); + + /* If more cds suddenly show up, ignore them */ + if (SDL_numcds > numVolumes) { + SDL_SetError ("Some CD's were added but they will be ignored"); + SDL_numcds = numVolumes; + } + } + + return 0; +} + +/* Shutdown and cleanup */ +void SDL_SYS_CDQuit(void) +{ + ReleaseFile(); + + if (volumes != NULL) + free (volumes); + + if (tracks != NULL) { + + FSRef **ptr; + for (ptr = tracks; *ptr != (FSRef*)-1; ptr++) + if (*ptr != NULL) + free (*ptr); + + free (tracks); + } +} + +/* Get the Unix disk name of the volume */ +static const char *SDL_SYS_CDName (int drive) +{ + /* + * !!! FIXME: PBHGetVolParmsSync() is gone in 10.6, + * !!! FIXME: replaced with FSGetVolumeParms(), which + * !!! FIXME: isn't available before 10.5. :/ + */ + return "Mac OS X CD-ROM Device"; + +#if 0 + OSStatus err = noErr; + HParamBlockRec pb; + GetVolParmsInfoBuffer volParmsInfo; + + if (fakeCD) + return "Fake CD-ROM Device"; + + pb.ioParam.ioNamePtr = NULL; + pb.ioParam.ioVRefNum = volumes[drive]; + pb.ioParam.ioBuffer = (Ptr)&volParmsInfo; + pb.ioParam.ioReqCount = (SInt32)sizeof(volParmsInfo); + err = PBHGetVolParmsSync(&pb); + + if (err != noErr) { + SDL_SetError ("PBHGetVolParmsSync returned %d", err); + return NULL; + } + + return volParmsInfo.vMDeviceID; +#endif +} + +/* Open the "device" */ +static int SDL_SYS_CDOpen (int drive) +{ + /* Only allow 1 device to be open */ + if (currentDrive >= 0) { + SDL_SetError ("Only one cdrom is supported"); + return -1; + } + else + currentDrive = drive; + + return drive; +} + +/* Get the table of contents */ +static int SDL_SYS_CDGetTOC (SDL_CD *cdrom) +{ + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + if (didReadTOC) { + cdrom->numtracks = cacheTOCNumTracks; + return 0; + } + + + ReadTOCData (volumes[cdrom->id], cdrom); + didReadTOC = SDL_TRUE; + cacheTOCNumTracks = cdrom->numtracks; + + return 0; +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position) +{ + if (position) { + int trackFrame; + + Lock (); + trackFrame = GetCurrentFrame (); + Unlock (); + + *position = cdrom->track[currentTrack].offset + trackFrame; + } + + return status; +} + +/* Start playback */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + int startFrame, stopFrame; + FSRef *ref; + + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + Lock(); + + if (LoadTracks (cdrom) < 0) + return -2; + + if (PauseFile () < 0) + return -3; + + if (ReleaseFile () < 0) + return -4; + + ref = GetFileForOffset (cdrom, start, length, &startFrame, &stopFrame); + if (ref == NULL) { + SDL_SetError ("SDL_SYS_CDPlay: No file for start=%d, length=%d", start, length); + return -5; + } + + if (LoadFile (ref, startFrame, stopFrame) < 0) + return -6; + + SetCompletionProc (CompletionProc, cdrom); + + if (PlayFile () < 0) + return -7; + + status = CD_PLAYING; + + Unlock(); + + return 0; +} + +/* Pause playback */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + Lock (); + + if (PauseFile () < 0) { + Unlock (); + return -2; + } + + status = CD_PAUSED; + + Unlock (); + + return 0; +} + +/* Resume playback */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + Lock (); + + if (PlayFile () < 0) { + Unlock (); + return -2; + } + + status = CD_PLAYING; + + Unlock (); + + return 0; +} + +/* Stop playback */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + Lock (); + + if (PauseFile () < 0) { + Unlock (); + return -2; + } + + if (ReleaseFile () < 0) { + Unlock (); + return -3; + } + + status = CD_STOPPED; + + Unlock (); + + return 0; +} + +/* Eject the CD-ROM (Unmount the volume) */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + OSStatus err; + pid_t dissenter; + + if (fakeCD) { + SDL_SetError (kErrorFakeDevice); + return -1; + } + + Lock (); + + if (PauseFile () < 0) { + Unlock (); + return -2; + } + + if (ReleaseFile () < 0) { + Unlock (); + return -3; + } + + status = CD_STOPPED; + + /* Eject the volume */ + err = FSEjectVolumeSync(volumes[cdrom->id], kNilOptions, &dissenter); + + if (err != noErr) { + Unlock (); + SDL_SetError ("PBUnmountVol returned %d", err); + return -4; + } + + status = CD_TRAYEMPTY; + + /* Invalidate volume and track info */ + volumes[cdrom->id] = 0; + free (tracks[cdrom->id]); + tracks[cdrom->id] = NULL; + + Unlock (); + + return 0; +} + +/* Close the CD-ROM */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + currentDrive = -1; + return; +} + +#endif /* SDL_CDROM_MACOSX */ diff --git a/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom_c.h b/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom_c.h new file mode 100644 index 0000000..589c589 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/macosx/SDL_syscdrom_c.h @@ -0,0 +1,136 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the Mac OS X / CoreAudio specific header for the SDL CD-ROM API + Contributed by Darrell Walisser and Max Horn + */ + +/*********************************************************************************** + Implementation Notes + ********************* + + This code has several limitations currently (all of which are proabaly fixable): + + 1. A CD-ROM device is inferred from a mounted cdfs volume, so device 0 is + not necessarily the first CD-ROM device on the system. (Somewhat easy to fix + by useing the device name from the volume id's to reorder the volumes) + + 2. You can only open and control 1 CD-ROM device at a time. (Challenging to fix, + due to extensive code restructuring) + + 3. The status reported by SDL_CDStatus only changes to from CD_PLAYING to CD_STOPPED in + 1-second intervals (because the audio is buffered in 1-second chunks) If + the audio data is less than 1 second, the remainder is filled with silence. + + If you need to play sequences back-to-back that are less that 1 second long, + use the frame position to determine when to play the next sequence, instead + of SDL_CDStatus. + + This may be possible to fix with a clever usage of the AudioUnit API. + + 4. When new volumes are inserted, our volume information is not updated. The only way + to refresh this information is to reinit the CD-ROM subsystem of SDL. To fix this, + one would probably have to fix point 1 above first, then figure out how to register + for a notification when new media is mounted in order to perform an automatic + rescan for cdfs volumes. + + + + So, here comes a description of how this all works. + + < Initializing > + + To get things rolling, we have to locate mounted volumes that contain + audio (since nearly all Macs don't have analog audio-in on the sound card). + That's easy, since these volumes have a flag that indicates this special + filesystem. See DetectAudioCDVolumes() in CDPlayer.cpp for this code. + + Next, we parse the invisible .TOC.plist in the root of the volume, which gets us + the track information (number, offset, length, leadout, etc). See ReadTOCData() in + CDPlayer.cpp for the skinny on this. + + + < The Playback Loop > + + Now come the tricky parts. Let's start with basic audio playback. When a frame + range to play is requested, we must first find the .aiff files on the volume, + hopefully in the right order. Since these files all begin with a number "1 Audio Track", + etc, this is used to determine the correct track order. + + Once all files are determined, we have to find what file corresponds to the start + and length parameter to SDL_SYS_CDPlay(). Again, this is quite simple by walking the + cdrom's track list. At this point, we also save the offset to the next track and frames + remaining, if we're going to have to play another file after the first one. See + GetFileForOffset() for this code. + + At this point we have all info needed to start playback, so we hand off to the LoadFile() + function, which proceeds to do its magic and plays back the file. + + When the file is finished playing, CompletionProc() is invoked, at which time we can + play the next file if the previously saved next track and frames remaining + indicates that we should. + + + < Magic > + + OK, so it's not really magic, but since I don't fully understand all the hidden details it + seems like it to me ;-) The API's involved are the AudioUnit and AudioFile API's. These + appear to be an extension of CoreAudio for creating modular playback and f/x entities. + The important thing is that CPU usage is very low and reliability is very high. You'd + be hard-pressed to find a way to stutter the playback with other CPU-intensive tasks. + + One part of this magic is that it uses multiple threads, which carries the usual potential + for disaster if not handled carefully. Playback currently requires 4 additional threads: + 1. The coreaudio runloop thread + 2. The coreaudio device i/o thread + 3. The file streaming thread + 4. The notification/callback thread + + The first 2 threads are necessary evil - CoreAudio creates this no matter what the situation + is (even the SDL sound implementation creates theses suckers). The last two are are created + by us. + + The file is streamed from disk using a threaded double-buffer approach. + This way, the high latency operation of reading from disk can be performed without interrupting + the real-time device thread (which amounts to avoiding dropouts). The device thread grabs the + buffer that isn't being read and sends it to the CoreAudio mixer where it eventually gets + to the sound card. + + The device thread posts a notification when the file streaming thread is out of data. This + notification must be handled in a separate thread to avoid potential deadlock in the + device thread. That's where the notification thread comes in. This thread is signaled + whenever a notification needs to be processed, so another file can be played back if need be. + + The API in CDPlayer.cpp contains synchronization because otherwise both the notification thread + and main thread (or another other thread using the SDL CD api) can potentially call it at the same time. + +************************************************************************************/ + + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +#include "CDPlayer.h" + +#define kErrorFakeDevice "Error: Cannot proceed since we're faking a CD-ROM device. Reinit the CD-ROM subsystem to scan for new volumes." + diff --git a/3rdparty/SDL/src/cdrom/mint/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/mint/SDL_syscdrom.c new file mode 100644 index 0000000..0bc10ed --- /dev/null +++ b/3rdparty/SDL/src/cdrom/mint/SDL_syscdrom.c @@ -0,0 +1,317 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_MINT + +/* + Atari MetaDOS CD-ROM functions + + Patrice Mandin +*/ + +#include <errno.h> + +#include <mint/cdromio.h> +#include <mint/metados.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* Some ioctl() errno values which occur when the tray is empty */ +#ifndef ENOMEDIUM +#define ENOMEDIUM ENOENT +#endif +#define ERRNO_TRAYEMPTY(errno) \ + ((errno == EIO) || (errno == ENOENT) || \ + (errno == EINVAL) || (errno == ENOMEDIUM)) + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 32 + +typedef struct { + char device[3]; /* Physical device letter + ':' + '\0' */ + metaopen_t metaopen; /* Infos on opened drive */ +} metados_drive_t; + +static metados_drive_t metados_drives[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static void SDL_SYS_CDClose(SDL_CD *cdrom); +static int SDL_SYS_CDioctl(int id, int command, void *arg); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); + +int SDL_SYS_CDInit(void) +{ + metainit_t metainit={0,0,0,0}; + metaopen_t metaopen; + int i, handle; + struct cdrom_subchnl info; + + Metainit(&metainit); + if (metainit.version == NULL) { +#ifdef DEBUG_CDROM + fprintf(stderr, "MetaDOS not installed\n"); +#endif + return -1; + } + + if (metainit.drives_map == 0) { +#ifdef DEBUG_CDROM + fprintf(stderr, "No MetaDOS devices present\n"); +#endif + return -1; + } + + SDL_numcds = 0; + + for (i='A'; i<='Z'; i++) { + metados_drives[SDL_numcds].device[0] = 0; + metados_drives[SDL_numcds].device[1] = ':'; + metados_drives[SDL_numcds].device[2] = 0; + + if (metainit.drives_map & (1<<(i-'A'))) { + handle = Metaopen(i, &metaopen); + if (handle == 0) { + + info.cdsc_format = CDROM_MSF; + if ( (Metaioctl(i, METADOS_IOCTL_MAGIC, CDROMSUBCHNL, &info) == 0) || ERRNO_TRAYEMPTY(errno) ) { + metados_drives[SDL_numcds].device[0] = i; + ++SDL_numcds; + } + + Metaclose(i); + } + } + } + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + + return 0; +} + +void SDL_SYS_CDQuit(void) +{ + SDL_numcds = 0; +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(metados_drives[drive].device); +} + +static int SDL_SYS_CDOpen(int drive) +{ + int handle; + + handle = Metaopen(metados_drives[drive].device[0], &(metados_drives[drive].metaopen)); + if (handle == 0) { + return drive; + } + + return -1; +} + +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + Metaclose(metados_drives[cdrom->id].device[0]); +} + +static int SDL_SYS_CDioctl(int id, int command, void *arg) +{ + int retval; + + retval = Metaioctl(metados_drives[id].device[0], METADOS_IOCTL_MAGIC, command, arg); + if ( retval < 0 ) { + SDL_SetError("ioctl() error: %s", strerror(errno)); + } + return(retval); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + int i,okay; + struct cdrom_tochdr toc; + struct cdrom_tocentry entry; + + /* Use standard ioctl() */ + if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)<0) { + return -1; + } + + cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + + /* Read all the track TOC entries */ + okay=1; + for ( i=0; i<=cdrom->numtracks; ++i ) { + if ( i == cdrom->numtracks ) { + cdrom->track[i].id = CDROM_LEADOUT; + } else { + cdrom->track[i].id = toc.cdth_trk0+i; + } + entry.cdte_track = cdrom->track[i].id; + entry.cdte_format = CDROM_MSF; + if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, &entry) < 0 ) { + okay=0; + break; + } else { + if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) { + cdrom->track[i].type = SDL_DATA_TRACK; + } else { + cdrom->track[i].type = SDL_AUDIO_TRACK; + } + cdrom->track[i].offset = MSF_TO_FRAMES( + entry.cdte_addr.msf.minute, + entry.cdte_addr.msf.second, + entry.cdte_addr.msf.frame); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset; + } + } + } + + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct cdrom_tochdr toc; + struct cdrom_subchnl info; + + info.cdsc_format = CDROM_MSF; + if ( SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) { + if ( ERRNO_TRAYEMPTY(errno) ) { + status = CD_TRAYEMPTY; + } else { + status = CD_ERROR; + } + } else { + switch (info.cdsc_audiostatus) { + case CDROM_AUDIO_INVALID: + case CDROM_AUDIO_NO_STATUS: + /* Try to determine if there's a CD available */ + if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) { + status = CD_STOPPED; + } else { + status = CD_TRAYEMPTY; + } + break; + case CDROM_AUDIO_COMPLETED: + status = CD_STOPPED; + break; + case CDROM_AUDIO_PLAY: + status = CD_PLAYING; + break; + case CDROM_AUDIO_PAUSED: + /* Workaround buggy CD-ROM drive */ + if ( info.cdsc_trk == CDROM_LEADOUT ) { + status = CD_STOPPED; + } else { + status = CD_PAUSED; + } + break; + default: + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = MSF_TO_FRAMES( + info.cdsc_absaddr.msf.minute, + info.cdsc_absaddr.msf.second, + info.cdsc_absaddr.msf.frame); + } else { + *position = 0; + } + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + struct cdrom_msf playtime; + + FRAMES_TO_MSF(start, + &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0); + FRAMES_TO_MSF(start+length, + &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1); +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, + playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); +#endif + + return SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0); +} + +#endif /* SDL_CDROM_MINT */ diff --git a/3rdparty/SDL/src/cdrom/openbsd/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/openbsd/SDL_syscdrom.c new file mode 100644 index 0000000..e4d03a6 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/openbsd/SDL_syscdrom.c @@ -0,0 +1,416 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_OPENBSD + +/* Functions for system-level CD-ROM audio control */ + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/cdio.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* Some ioctl() errno values which occur when the tray is empty */ +#define ERRNO_TRAYEMPTY(errno) \ + ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL) || \ + (errno == ENODEV)) + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd, cdfd; + struct ioc_read_subchannel info; + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { + cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + info.address_format = CD_MSF_FORMAT; + info.data_format = CD_CURRENT_POSITION; + info.data_len = 0; + info.data = NULL; + /* Under Linux, EIO occurs when a disk is not present. + This isn't 100% reliable, so we use the USE_MNTENT + code above instead. + */ + if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) || + ERRNO_TRAYEMPTY(errno) ) { + is_cd = 1; + } + close(cdfd); + } + else if (ERRNO_TRAYEMPTY(errno)) + is_cd = 1; + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +int SDL_SYS_CDInit(void) +{ + static char *checklist[] = { +#if defined(__OPENBSD__) + "?0 cd?c", "cdrom", NULL +#elif defined(__NETBSD__) + "?0 cd?d", "?0 cd?c", "cdrom", NULL +#else + "?0 cd?c", "?0 acd?c", "cdrom", NULL +#endif + }; + char *SDLcdrom; + int i, j, exists; + char drive[32]; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + + /* Scan the system for CD-ROM drives */ + for ( i=0; checklist[i]; ++i ) { + if ( checklist[i][0] == '?' ) { + char *insert; + exists = 1; + for ( j=checklist[i][1]; exists; ++j ) { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); + insert = SDL_strchr(drive, '?'); + if ( insert != NULL ) { + *insert = j; + } + switch (CheckDrive(drive, &stbuf)) { + /* Drive exists and is a CD-ROM */ + case 1: + AddDrive(drive, &stbuf); + break; + /* Drive exists, but isn't a CD-ROM */ + case 0: + break; + /* Drive doesn't exist */ + case -1: + exists = 0; + break; + } + } + } else { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); + if ( CheckDrive(drive, &stbuf) > 0 ) { + AddDrive(drive, &stbuf); + } + } + } + return(0); +} + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int id, int command, void *arg) +{ + int retval; + + retval = ioctl(id, command, arg); + if ( retval < 0 ) { + SDL_SetError("ioctl() error: %s", strerror(errno)); + } + return(retval); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + struct ioc_toc_header toc; + int i, okay; + struct ioc_read_toc_entry entry; + struct cd_toc_entry data; + + okay = 0; + if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) { + cdrom->numtracks = toc.ending_track-toc.starting_track+1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + /* Read all the track TOC entries */ + for ( i=0; i<=cdrom->numtracks; ++i ) { + if ( i == cdrom->numtracks ) { + cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */ + } else { + cdrom->track[i].id = toc.starting_track+i; + } + entry.starting_track = cdrom->track[i].id; + entry.address_format = CD_MSF_FORMAT; + entry.data_len = sizeof(data); + entry.data = &data; + if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS, + &entry) < 0 ) { + break; + } else { + cdrom->track[i].type = data.control; + cdrom->track[i].offset = MSF_TO_FRAMES( + data.addr.msf.minute, + data.addr.msf.second, + data.addr.msf.frame); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = + cdrom->track[i].offset- + cdrom->track[i-1].offset; + } + } + } + if ( i == (cdrom->numtracks+1) ) { + okay = 1; + } + } + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct ioc_toc_header toc; + struct ioc_read_subchannel info; + struct cd_sub_channel_info data; + + info.address_format = CD_MSF_FORMAT; + info.data_format = CD_CURRENT_POSITION; + info.track = 0; + info.data_len = sizeof(data); + info.data = &data; + if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) { + if ( ERRNO_TRAYEMPTY(errno) ) { + status = CD_TRAYEMPTY; + } else { + status = CD_ERROR; + } + } else { + switch (data.header.audio_status) { + case CD_AS_AUDIO_INVALID: + case CD_AS_NO_STATUS: + /* Try to determine if there's a CD available */ + if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0) + status = CD_STOPPED; + else + status = CD_TRAYEMPTY; + break; + case CD_AS_PLAY_COMPLETED: + status = CD_STOPPED; + break; + case CD_AS_PLAY_IN_PROGRESS: + status = CD_PLAYING; + break; + case CD_AS_PLAY_PAUSED: + status = CD_PAUSED; + break; + default: + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = MSF_TO_FRAMES( + data.what.position.absaddr.msf.minute, + data.what.position.absaddr.msf.second, + data.what.position.absaddr.msf.frame); + } else { + *position = 0; + } + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + struct ioc_play_msf playtime; + + FRAMES_TO_MSF(start, + &playtime.start_m, &playtime.start_s, &playtime.start_f); + FRAMES_TO_MSF(start+length, + &playtime.end_m, &playtime.end_s, &playtime.end_f); +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + playtime.start_m, playtime.start_s, playtime.start_f, + playtime.end_m, playtime.end_s, playtime.end_f); +#endif + ioctl(cdrom->id, CDIOCSTART, 0); + return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + SDL_SYS_CDioctl(cdrom->id, CDIOCALLOW, 0); + return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_OPENBSD */ diff --git a/3rdparty/SDL/src/cdrom/os2/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/os2/SDL_syscdrom.c new file mode 100644 index 0000000..6ed9c65 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/os2/SDL_syscdrom.c @@ -0,0 +1,393 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_OS2 + +/* Functions for system-level CD-ROM audio control */ + +#define INCL_MCIOS2 +#include <os2.h> +#include <os2me.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* Size of MCI result buffer (in bytes) */ +#define MCI_CMDRETBUFSIZE 128 + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +//static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* MCI Timing Functions */ +#define MCI_MMTIMEPERSECOND 3000 +#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND) + + +/* Ready for MCI CDAudio Devices */ +int SDL_SYS_CDInit(void) +{ +int i; /* generig counter */ +MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */ +CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result */ + +/* Fill in our driver capabilities */ +SDL_CDcaps.Name = SDL_SYS_CDName; +SDL_CDcaps.Open = SDL_SYS_CDOpen; +SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; +SDL_CDcaps.Status = SDL_SYS_CDStatus; +SDL_CDcaps.Play = SDL_SYS_CDPlay; +SDL_CDcaps.Pause = SDL_SYS_CDPause; +SDL_CDcaps.Resume = SDL_SYS_CDResume; +SDL_CDcaps.Stop = SDL_SYS_CDStop; +SDL_CDcaps.Eject = SDL_SYS_CDEject; +SDL_CDcaps.Close = SDL_SYS_CDClose; + +/* Get the number of CD ROMs in the System */ +/* Clean SysInfo structure */ +SDL_memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS)); +/* Prepare structure to Ask Numer of Audio CDs */ +msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */ +msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */ +msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */ +if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR); +SDL_numcds = atoi(SysInfoRet); +if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */ + +/* Get and Add their system name to the SDL_cdlist */ +msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */ +msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */ +msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */ +for (i=0; i<SDL_numcds; i++) + { + msp.ulNumber = i+1; + mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0); + SDL_cdlist[i] = SDL_strdup(SysInfoRet); + if ( SDL_cdlist[i] == NULL ) + { + SDL_OutOfMemory(); + return(-1); + } + } +return(0); +} + +/* Return CDAudio System Dependent Device Name - Ready for MCI*/ +static const char *SDL_SYS_CDName(int drive) +{ +return(SDL_cdlist[drive]); +} + +/* Open CDAudio Device - Ready for MCI */ +static int SDL_SYS_CDOpen(int drive) +{ +MCI_OPEN_PARMS mop; +MCI_SET_PARMS msp; +MCI_GENERIC_PARMS mgp; + +/* Open the device */ +mop.hwndCallback = (HWND)NULL; // None +mop.usDeviceID = (USHORT)NULL; // Will be returned. +mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Device +if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR); +/* Set time format */ +msp.hwndCallback = (HWND)NULL; // None +msp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structure +msp.ulSpeedFormat = (ULONG)NULL; // No change +msp.ulAudio = (ULONG)NULL; // No Channel +msp.ulLevel = (ULONG)NULL; // No Volume +msp.ulOver = (ULONG)NULL; // No Delay +msp.ulItem = (ULONG)NULL; // No item +msp.ulValue = (ULONG)NULL; // No value for item flag +if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID); +/* Error setting time format? - Close opened device */ +mgp.hwndCallback = (HWND)NULL; // None +mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0); +return(CD_ERROR); +} + +/* Get CD Table Of Contents - Ready for MCI */ +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ +MCI_TOC_PARMS mtp; +MCI_STATUS_PARMS msp; +MCI_TOC_REC * mtr; +INT i; + +/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */ +if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0; + +/* Get Number of Tracks */ +msp.hwndCallback = (HWND)NULL; /* None */ +msp.ulReturn = (ULONG)NULL; /* We want this information */ +msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS; +msp.ulValue = (ULONG)NULL; /* No additional information */ +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR); +cdrom->numtracks = msp.ulReturn; +if ( cdrom->numtracks > SDL_MAX_TRACKS ) + { + cdrom->numtracks = SDL_MAX_TRACKS; + } +/* Alocate space for TOC data */ +mtr = (MCI_TOC_REC *)SDL_malloc(cdrom->numtracks*sizeof(MCI_TOC_REC)); +if ( mtr == NULL ) + { + SDL_OutOfMemory(); + return(-1); + } +/* Get TOC from CD */ +mtp.pBuf = mtr; +mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC); +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS) + { + SDL_OutOfMemory(); + SDL_free(mtr); + return(CD_ERROR); + } +/* Fill SDL Tracks Structure */ +for (i=0; i<cdrom->numtracks; i++) + { + /* Set Track ID */ + cdrom->track[i].id = (mtr+i)->TrackNum; + /* Set Track Type */ + msp.hwndCallback = (HWND)NULL; /* None */ + msp.ulReturn = (ULONG)NULL; /* We want this information */ + msp.ulItem = MCI_CD_STATUS_TRACK_TYPE; + msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */ + if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) + { + SDL_free(mtr); + return (CD_ERROR); + } + if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK; + else cdrom->track[i].type = SDL_DATA_TRACK; + /* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */ + cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr); + /* Set Track Offset */ + cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr); + } +SDL_free(mtr); +return(0); +} + + +/* Get CD-ROM status - Ready for MCI */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ +CDstatus status; +MCI_STATUS_PARMS msp; + +/* Get Status from MCI */ +msp.hwndCallback = (HWND)NULL; /* None */ +msp.ulReturn = (ULONG)NULL; /* We want this information */ +msp.ulItem = MCI_STATUS_MODE; +msp.ulValue = (ULONG)NULL; /* No additional information */ +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR; +else + { + switch(msp.ulReturn) + { + case MCI_MODE_NOT_READY: + status = CD_TRAYEMPTY; + break; + case MCI_MODE_PAUSE: + status = CD_PAUSED; + break; + case MCI_MODE_PLAY: + status = CD_PLAYING; + break; + case MCI_MODE_STOP: + status = CD_STOPPED; + break; + /* These cases should not occour */ + case MCI_MODE_RECORD: + case MCI_MODE_SEEK: + default: + status = CD_ERROR; + break; + } + } + +/* Determine position */ +if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */ + { + if ((status == CD_PLAYING) || (status == CD_PAUSED)) + { + /* Get Position */ + msp.hwndCallback = (HWND)NULL; /* None */ + msp.ulReturn = (ULONG)NULL; /* We want this information */ + msp.ulItem = MCI_STATUS_POSITION; + msp.ulValue = (ULONG)NULL; /* No additiona info */ + if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR); + /* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */ + *position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn)); + } + else *position = 0; + } +return(status); +} + +/* Start play - Ready for MCI */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ +MCI_GENERIC_PARMS mgp; +MCI_STATUS_PARMS msp; +MCI_PLAY_PARMS mpp; +ULONG min,sec,frm; + +/* Start MSF */ +FRAMES_TO_MSF(start, &min, &sec, &frm); +MSF_MINUTE(mpp.ulFrom) = min; +MSF_SECOND(mpp.ulFrom) = sec; +MSF_FRAME(mpp.ulFrom) = frm; +/* End MSF */ +FRAMES_TO_MSF(start+length, &min, &sec, &frm); +MSF_MINUTE(mpp.ulTo) = min; +MSF_SECOND(mpp.ulTo) = sec; +MSF_FRAME(mpp.ulTo) = frm; +#ifdef DEBUG_CDROM + fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", + playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, + playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); +#endif +/* Verifies if it is paused first... and if it is, unpause before stopping it. */ +msp.hwndCallback = (HWND)NULL; /* None */ +msp.ulReturn = (ULONG)NULL; /* We want this information */ +msp.ulItem = MCI_STATUS_MODE; +msp.ulValue = (ULONG)NULL; /* No additional information */ +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS) + { + if (msp.ulReturn == MCI_MODE_PAUSE) + { + mgp.hwndCallback = (HWND)NULL; // None + mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0); + } + } +/* Now play it. */ +mpp.hwndCallback = (HWND)NULL; // We do not want the info. temp +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0; +return (CD_ERROR); +} + +/* Pause play - Ready for MCI */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ +MCI_GENERIC_PARMS mgp; + +mgp.hwndCallback = (HWND)NULL; // None +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0; +return(CD_ERROR); +} + +/* Resume play - Ready for MCI */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ +MCI_GENERIC_PARMS mgp; + +mgp.hwndCallback = (HWND)NULL; // None +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0; +return(CD_ERROR); +} + +/* Stop play - Ready for MCI */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ +MCI_GENERIC_PARMS mgp; +MCI_STATUS_PARMS msp; + +/* Verifies if it is paused first... and if it is, unpause before stopping it. */ +msp.hwndCallback = (HWND)NULL; /* None */ +msp.ulReturn = (ULONG)NULL; /* We want this information */ +msp.ulItem = MCI_STATUS_MODE; +msp.ulValue = (ULONG)NULL; /* No additional information */ +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS) + { + if (msp.ulReturn == MCI_MODE_PAUSE) + { + mgp.hwndCallback = (HWND)NULL; // None + mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0); + } + } +/* Now stops the media */ +mgp.hwndCallback = (HWND)NULL; // None +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0; +return(CD_ERROR); +} + +/* Eject the CD-ROM - Ready for MCI */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ +MCI_SET_PARMS msp; + +msp.hwndCallback = (HWND)NULL; // None +msp.ulTimeFormat = (ULONG)NULL; // No change +msp.ulSpeedFormat = (ULONG)NULL; // No change +msp.ulAudio = (ULONG)NULL; // No Channel +msp.ulLevel = (ULONG)NULL; // No Volume +msp.ulOver = (ULONG)NULL; // No Delay +msp.ulItem = (ULONG)NULL; // No item +msp.ulValue = (ULONG)NULL; // No value for item flag +if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0; +return(CD_ERROR); +} + +/* Close the CD-ROM handle - Ready for MCI */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ +MCI_GENERIC_PARMS mgp; + +mgp.hwndCallback = (HWND)NULL; // None +mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0); +} + +/* Finalize CDROM Subsystem - Ready for MCI */ +void SDL_SYS_CDQuit(void) +{ +int i; + +if ( SDL_numcds > 0 ) + { + for ( i=0; i<SDL_numcds; ++i ) + { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_OS2 */ diff --git a/3rdparty/SDL/src/cdrom/osf/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/osf/SDL_syscdrom.c new file mode 100644 index 0000000..8478a7b --- /dev/null +++ b/3rdparty/SDL/src/cdrom/osf/SDL_syscdrom.c @@ -0,0 +1,444 @@ +/* + Tru64 audio module for SDL (Simple DirectMedia Layer) + Copyright (C) 2003 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_OSF + +/* Functions for system-level CD-ROM audio control */ + +/* #define DEBUG_CDROM 1 */ + +#include <sys/types.h> +#include <dirent.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <io/cam/cdrom.h> +#include <io/cam/rzdisk.h> +#include <io/common/devgetinfo.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* Check a drive to see if it is a CD-ROM */ +/* Caution!! Not tested. */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int cdfd, is_cd = 0; + struct mode_sel_sns_params msp; + struct inquiry_info inq; + +#ifdef DEBUG_CDROM + char *devtype[] = {"Disk", "Tape", "Printer", "Processor", "WORM", + "CD-ROM", "Scanner", "Optical", "Changer", "Comm", "Unknown"}; +#endif + + bzero(&msp, sizeof(msp)); + bzero(&inq, sizeof(inq)); + + /* If it doesn't exist, return -1 */ + if ( stat(drive, stbuf) < 0 ) { + return(-1); + } + + if ( (cdfd = open(drive, (O_RDWR|O_NDELAY), 0)) >= 0 ) { + msp.msp_addr = (caddr_t) &inq; + msp.msp_pgcode = 0; + msp.msp_pgctrl = 0; + msp.msp_length = sizeof(inq); + msp.msp_setps = 0; + + if ( ioctl(cdfd, SCSI_GET_INQUIRY_DATA, &msp) ) + return (0); + +#ifdef DEBUG_CDROM + fprintf(stderr, "Device Type: %s\n", devtype[inq.perfdt]); + fprintf(stderr, "Vendor: %.8s\n", inq.vndrid); + fprintf(stderr, "Product: %.8s\n", inq.prodid); + fprintf(stderr, "Revision: %.8s\n", inq.revlvl); +#endif + if ( inq.perfdt == DTYPE_RODIRECT ) + is_cd = 1; + } + + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Check to make sure it's not already in our list. + * This can happen when we see a drive via symbolic link. + * + */ + for ( i=0; i<SDL_numcds; ++i ) { + if ( stbuf->st_rdev == SDL_cdmode[i] ) { +#ifdef DEBUG_CDROM + fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); +#endif + return; + } + } + + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; +#ifdef DEBUG_CDROM + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +int SDL_SYS_CDInit(void) +{ + /* checklist: + * + * Tru64 5.X (/dev/rdisk/cdrom?c) + * dir: /dev/rdisk, name: cdrom + * + * Digital UNIX 4.0X (/dev/rrz?c) + * dir: /dev, name: rrz + * + */ + struct { + char *dir; + char *name; + } checklist[] = { + {"/dev/rdisk", "cdrom"}, + {"/dev", "rrz"}, + {NULL, NULL}}; + char drive[32]; + char *SDLcdrom; + int i, j, exists; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if ( cdpath != NULL ) { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if ( SDL_numcds > 0 ) { + return(0); + } + } + /* Scan the system for CD-ROM drives */ + for ( i = 0; checklist[i].dir; ++i) { + DIR *devdir; + struct dirent *devent; + int name_len; + + devdir = opendir(checklist[i].dir); + if (devdir) { + name_len = SDL_strlen(checklist[i].name); + while (devent = readdir(devdir)) + if (SDL_memcmp(checklist[i].name, devent->d_name, name_len) == 0) + if (devent->d_name[devent->d_namlen-1] == 'c') { + SDL_snprintf(drive, SDL_arraysize(drive), "%s/%s", checklist[i].dir, devent->d_name); +#ifdef DEBUG_CDROM + fprintf(stderr, "Try to add drive: %s\n", drive); +#endif + if ( CheckDrive(drive, &stbuf) > 0 ) + AddDrive(drive, &stbuf); + } + closedir(devdir); + } else { +#ifdef DEBUG_CDROM + fprintf(stderr, "cannot open dir: %s\n", checklist[i].dir); +#endif + } + } + return (0); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + /* O_RDWR: To use ioctl(fd, SCSI_STOP_UNIT) */ + return(open(SDL_cdlist[drive], (O_RDWR|O_NDELAY), 0)); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + struct cd_toc toc; + struct cd_toc_header hdr; + struct cd_toc_entry *cdte; + int i; + int okay = 0; + if ( ioctl(cdrom->id, CDROM_TOC_HEADER, &hdr) ) { + fprintf(stderr,"ioctl error CDROM_TOC_HEADER\n"); + return -1; + } + cdrom->numtracks = hdr.th_ending_track - hdr.th_starting_track + 1; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } +#ifdef DEBUG_CDROM + fprintf(stderr,"hdr.th_data_len1 = %d\n", hdr.th_data_len1); + fprintf(stderr,"hdr.th_data_len0 = %d\n", hdr.th_data_len0); + fprintf(stderr,"hdr.th_starting_track = %d\n", hdr.th_starting_track); + fprintf(stderr,"hdr.th_ending_track = %d\n", hdr.th_ending_track); + fprintf(stderr,"cdrom->numtracks = %d\n", cdrom->numtracks); +#endif + toc.toc_address_format = CDROM_LBA_FORMAT; + toc.toc_starting_track = 0; + toc.toc_alloc_length = (hdr.th_data_len1 << 8) + + hdr.th_data_len0 + sizeof(hdr); + if ( (toc.toc_buffer = alloca(toc.toc_alloc_length)) == NULL) { + fprintf(stderr,"cannot allocate toc.toc_buffer\n"); + return -1; + } + + bzero (toc.toc_buffer, toc.toc_alloc_length); + if (ioctl(cdrom->id, CDROM_TOC_ENTRYS, &toc)) { + fprintf(stderr,"ioctl error CDROM_TOC_ENTRYS\n"); + return -1; + } + + cdte =(struct cd_toc_entry *) ((char *) toc.toc_buffer + sizeof(hdr)); + for (i=0; i <= cdrom->numtracks; ++i) { + if (i == cdrom->numtracks ) { + cdrom->track[i].id = 0xAA;; + } else { + cdrom->track[i].id = hdr.th_starting_track + i; + } + + cdrom->track[i].type = + cdte[i].te_control & CDROM_DATA_TRACK; + cdrom->track[i].offset = + cdte[i].te_absaddr.lba.addr3 << 24 | + cdte[i].te_absaddr.lba.addr2 << 16 | + cdte[i].te_absaddr.lba.addr1 << 8 | + cdte[i].te_absaddr.lba.addr0; + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i - 1].length = + cdrom->track[i].offset - + cdrom->track[i - 1].offset; + } + } +#ifdef DEBUG_CDROM + for (i = 0; i <= cdrom->numtracks; i++) { + fprintf(stderr,"toc_entry[%d].te_track_number = %d\n", + i,cdte[i].te_track_number); + fprintf(stderr,"cdrom->track[%d].id = %d\n", i,cdrom->track[i].id); + fprintf(stderr,"cdrom->track[%d].type = %x\n", i,cdrom->track[i].type); + fprintf(stderr,"cdrom->track[%d].offset = %d\n", i,cdrom->track[i].offset); + fprintf(stderr,"cdrom->track[%d].length = %d\n", i,cdrom->track[i].length); + } +#endif + if ( i == (cdrom->numtracks+1) ) { + okay = 1; + } + + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + struct cd_sub_channel sc; + struct cd_subc_channel_data scd; + + sc.sch_address_format = CDROM_LBA_FORMAT; + sc.sch_data_format = CDROM_CURRENT_POSITION; + sc.sch_track_number = 0; + sc.sch_alloc_length = sizeof(scd); + sc.sch_buffer = (caddr_t)&scd; + if ( ioctl(cdrom->id, CDROM_READ_SUBCHANNEL, &sc) ) { + status = CD_ERROR; + fprintf(stderr,"ioctl error CDROM_READ_SUBCHANNEL \n"); + } else { + switch (scd.scd_header.sh_audio_status) { + case AS_AUDIO_INVALID: + status = CD_STOPPED; + break; + case AS_PLAY_IN_PROGRESS: + status = CD_PLAYING; + break; + case AS_PLAY_PAUSED: + status = CD_PAUSED; + break; + case AS_PLAY_COMPLETED: + status = CD_STOPPED; + break; + case AS_PLAY_ERROR: + status = CD_ERROR; + break; + case AS_NO_STATUS: + status = CD_STOPPED; + break; + default: + status = CD_ERROR; + break; + } +#ifdef DEBUG_CDROM + fprintf(stderr,"scd.scd_header.sh_audio_status = %x\n", + scd.scd_header.sh_audio_status); +#endif + } + if (position) { + if (status == CD_PLAYING || (status == CD_PAUSED) ) { + *position = + scd.scd_position_data.scp_absaddr.lba.addr3 << 24 | + scd.scd_position_data.scp_absaddr.lba.addr2 << 16 | + scd.scd_position_data.scp_absaddr.lba.addr1 << 8 | + scd.scd_position_data.scp_absaddr.lba.addr0; + } else { + *position = 0; + } + } + + return status; +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ +/* + * Play MSF + */ + struct cd_play_audio_msf msf; + int end; + + bzero(&msf, sizeof(msf)); + end = start +length; + FRAMES_TO_MSF(start + 150, /* LBA = 4500*M + 75*S + F - 150 */ + &msf.msf_starting_M_unit, + &msf.msf_starting_S_unit, + &msf.msf_starting_F_unit); + FRAMES_TO_MSF(end + 150, /* LBA = 4500*M + 75*S + F - 150 */ + &msf.msf_ending_M_unit, + &msf.msf_ending_S_unit, + &msf.msf_ending_F_unit); + + return(ioctl(cdrom->id, CDROM_PLAY_AUDIO_MSF, &msf)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + return(ioctl(cdrom->id, CDROM_PAUSE_PLAY)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + return(ioctl(cdrom->id, CDROM_RESUME_PLAY)); +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(ioctl(cdrom->id, SCSI_STOP_UNIT)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(ioctl(cdrom->id, CDROM_EJECT_CADDY)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_OSF */ diff --git a/3rdparty/SDL/src/cdrom/qnx/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/qnx/SDL_syscdrom.c new file mode 100644 index 0000000..0e38b79 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/qnx/SDL_syscdrom.c @@ -0,0 +1,551 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_QNX + +/* Functions for system-level CD-ROM audio control */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/cdrom.h> +#include <sys/dcmd_cam.h> + +#include "SDL_timer.h" +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* The maximum number of CD-ROM drives we'll detect */ +#define MAX_DRIVES 16 + +#define QNX_CD_OPENMODE O_RDONLY | O_EXCL + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static dev_t SDL_cdmode[MAX_DRIVES]; +static int SDL_cdopen[MAX_DRIVES]; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + +/* Check a drive to see if it is a CD-ROM */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd, cdfd; + cam_devinfo_t dinfo; + int devctlret=0; + + int atapi; + int removable; + int cdb10; + + /* If it doesn't exist, return -1 */ + if (stat(drive, stbuf) < 0) + { + return(-1); + } + + /* If it does exist, verify that it's an available CD-ROM */ + is_cd = 0; + + if (S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode)) + { + cdfd = open(drive, QNX_CD_OPENMODE); + if ( cdfd >= 0 ) + { + devctlret=devctl(cdfd, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL); + + if (devctlret==EOK) + { + atapi=dinfo.flags & DEV_ATAPI; + removable=dinfo.flags & DEV_REMOVABLE; + cdb10=dinfo.flags & DEV_CDB_10; /* I'm not sure about that flag */ + + /* in the near future need to add more checks for splitting cdroms from other devices */ + if ((atapi)&&(removable)) + { + is_cd = 1; + } + } + + close(cdfd); + } + } + return(is_cd); +} + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive, struct stat *stbuf) +{ + int i; + + if (SDL_numcds < MAX_DRIVES) + { + /* Check to make sure it's not already in our list. + This can happen when we see a drive via symbolic link. */ + + for (i=0; i<SDL_numcds; ++i) + { + if (stbuf->st_rdev == SDL_cdmode[i]) + { + return; + } + } + + /* Add this drive to our list */ + + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if (SDL_cdlist[i] == NULL) + { + SDL_OutOfMemory(); + return; + } + SDL_cdmode[i] = stbuf->st_rdev; + ++SDL_numcds; + } +} + +int SDL_SYS_CDInit(void) +{ + /* checklist: /dev/cdrom, /dev/cd?, /dev/scd? */ + static char *checklist[]={"cdrom", "?0 cd?", "?1 cd?", "?0 scd?", NULL}; + + char *SDLcdrom; + int i, j, exists; + char drive[32]; + struct stat stbuf; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* clearing device open status */ + for (i=0; i<MAX_DRIVES; i++) + { + SDL_cdopen[i]=0; + } + + /* Look in the environment for our CD-ROM drive list */ + SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) + { + char *cdpath, *delim; + size_t len = SDL_strlen(SDLcdrom)+1; + cdpath = SDL_stack_alloc(char, len); + if (cdpath != NULL) + { + SDL_strlcpy(cdpath, SDLcdrom, len); + SDLcdrom = cdpath; + do { + delim = SDL_strchr(SDLcdrom, ':'); + if (delim) + { + *delim++ = '\0'; + } + if (CheckDrive(SDLcdrom, &stbuf) > 0) + { + AddDrive(SDLcdrom, &stbuf); + } + if (delim) + { + SDLcdrom = delim; + } + else + { + SDLcdrom = NULL; + } + } while (SDLcdrom); + SDL_stack_free(cdpath); + } + + /* If we found our drives, there's nothing left to do */ + if (SDL_numcds > 0) + { + return(0); + } + } + + /* Scan the system for CD-ROM drives */ + for ( i=0; checklist[i]; ++i ) + { + if (checklist[i][0] == '?') + { + char* insert; + exists = 1; + + for ( j=checklist[i][1]; exists; ++j ) + { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); + insert = SDL_strchr(drive, '?'); + if (insert != NULL) + { + *insert = j; + } + switch (CheckDrive(drive, &stbuf)) + { + /* Drive exists and is a CD-ROM */ + case 1: + AddDrive(drive, &stbuf); + break; + /* Drive exists, but isn't a CD-ROM */ + case 0: + break; + /* Drive doesn't exist */ + case -1: + exists = 0; + break; + } + } + } + else + { + SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); + if (CheckDrive(drive, &stbuf) > 0) + { + AddDrive(drive, &stbuf); + } + } + } + return(0); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + int handle; + + handle=open(SDL_cdlist[drive], QNX_CD_OPENMODE); + + if (handle>0) + { + SDL_cdopen[drive]=handle; + } + + return (handle); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + cdrom_read_toc_t toc; + int i, okay; + + okay = 0; + if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL) == 0) + { + cdrom->numtracks = toc.last_track - toc.first_track + 1; + if (cdrom->numtracks > SDL_MAX_TRACKS) + { + cdrom->numtracks = SDL_MAX_TRACKS; + } + /* Read all the track TOC entries */ + for (i=0; i<=cdrom->numtracks; ++i) + { + if (i == cdrom->numtracks) + { + cdrom->track[i].id = CDROM_LEADOUT; + } + else + { + cdrom->track[i].id = toc.first_track+i; + } + + cdrom->track[i].type = toc.toc_entry[i].control_adr & 0x0F; + cdrom->track[i].offset = toc.toc_entry[i].addr.lba; + cdrom->track[i].length = 0; + + if (i > 0) + { + cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset; + } + } + if (i == (cdrom->numtracks+1)) + { + okay = 1; + } + } + return (okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + + cdrom_read_toc_t toc; + cdrom_subch_data_t info; + cam_devinfo_t dinfo; + + int devctlret=0; + int drive=-1; + int i; + int eagaincnt=0; + + /* check media presence before read subchannel call, some cdroms can lockups */ + /* if no media, while calling read subchannel functions. */ + devctlret=devctl(cdrom->id, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL); + + if (devctlret==EOK) + { + if ((dinfo.flags & DEV_NO_MEDIA)!=0) + { + status = CD_TRAYEMPTY; + if (position) + { + *position = 0; + } + return (status); + } + } + + /* if media exists, then do other stuff */ + + SDL_memset(&info, 0x00, sizeof(info)); + info.subch_command.data_format = CDROM_SUBCH_CURRENT_POSITION; + + do { + devctlret=devctl(cdrom->id, DCMD_CAM_CDROMSUBCHNL, &info, sizeof(info), NULL); + if (devctlret==EIO) + { + /* big workaround for media change, handle is unusable after that, + that bug was found in QNX 6.2, 6.2.1 is not released yet. */ + + for (i=0; i<MAX_DRIVES; i++) + { + if (SDL_cdopen[i]==cdrom->id) + { + drive=i; + break; + } + } + if (drive==-1) + { + /* that cannot happen, but ... */ + break; + } + close(cdrom->id); + cdrom->id=open(SDL_cdlist[drive], QNX_CD_OPENMODE); + devctlret=EAGAIN; + } + if (devctlret==EAGAIN) + { + eagaincnt++; + } + if (eagaincnt==2) + { + /* workaround for broken cdroms, which can return always EAGAIN when its not ready, */ + /* that mean errornous media or just no media avail */ + devctlret=ENXIO; + break; + } + } while ((devctlret==EAGAIN)||(devctlret==ESTALE)); + + if (devctlret != 0) + { + if (devctlret==ENXIO) + { + status = CD_TRAYEMPTY; + } + else + { + status = CD_ERROR; + } + } + else + { + switch (info.current_position.header.audio_status) + { + case CDROM_AUDIO_INVALID: + case CDROM_AUDIO_NO_STATUS: + /* Try to determine if there's a CD available */ + if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL)==0) + status = CD_STOPPED; + else + status = CD_TRAYEMPTY; + break; + case CDROM_AUDIO_COMPLETED: + status = CD_STOPPED; + break; + case CDROM_AUDIO_PLAY: + status = CD_PLAYING; + break; + case CDROM_AUDIO_PAUSED: + /* Workaround buggy CD-ROM drive */ + if (info.current_position.data_format == CDROM_LEADOUT) + { + status = CD_STOPPED; + } + else + { + status = CD_PAUSED; + } + break; + default: + status = CD_ERROR; + break; + } + } + + if (position) + { + if (status==CD_PLAYING || (status==CD_PAUSED)) + { + *position = MSF_TO_FRAMES(info.current_position.addr.msf.minute, + info.current_position.addr.msf.second, + info.current_position.addr.msf.frame); + } + else + { + *position = 0; + } + } + + return (status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + cdrom_playmsf_t playtime; + + FRAMES_TO_MSF(start, &playtime.start_minute, &playtime.start_second, &playtime.start_frame); + FRAMES_TO_MSF(start+length, &playtime.end_minute, &playtime.end_second, &playtime.end_frame); + + if (devctl(cdrom->id, DCMD_CAM_CDROMPLAYMSF, &playtime, sizeof(playtime), NULL) != 0) + { + return -1; + } + else + { + return 0; + } +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ + if (devctl(cdrom->id, DCMD_CAM_CDROMPAUSE, NULL, 0, NULL)!=0) + { + return -1; + } + else + { + return 0; + } +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ + if (devctl(cdrom->id, DCMD_CAM_CDROMRESUME, NULL, 0, NULL)!=0) + { + return -1; + } + else + { + return 0; + } +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + if (devctl(cdrom->id, DCMD_CAM_CDROMSTOP, NULL, 0, NULL)!=0) + { + return -1; + } + else + { + return 0; + } +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + if (devctl(cdrom->id, DCMD_CAM_EJECT_MEDIA, NULL, 0, NULL)!=0) + { + return -1; + } + else + { + return 0; + } +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + int i; + + for (i=0; i<MAX_DRIVES; i++) + { + if (SDL_cdopen[i]==cdrom->id) + { + SDL_cdopen[i]=0; + break; + } + } + + close(cdrom->id); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if (SDL_numcds > 0) + { + for (i=0; i<SDL_numcds; ++i) + { + SDL_free(SDL_cdlist[i]); + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_QNX */ diff --git a/3rdparty/SDL/src/cdrom/win32/SDL_syscdrom.c b/3rdparty/SDL/src/cdrom/win32/SDL_syscdrom.c new file mode 100644 index 0000000..cac9fd3 --- /dev/null +++ b/3rdparty/SDL/src/cdrom/win32/SDL_syscdrom.c @@ -0,0 +1,386 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_CDROM_WIN32 + +/* Functions for system-level CD-ROM audio control */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> + +#include "SDL_cdrom.h" +#include "../SDL_syscdrom.h" + +/* This really broken?? */ +#define BROKEN_MCI_PAUSE /* Pausing actually stops play -- Doh! */ + +/* The maximum number of CD-ROM drives we'll detect (Don't change!) */ +#define MAX_DRIVES 26 + +/* A list of available CD-ROM drives */ +static char *SDL_cdlist[MAX_DRIVES]; +static MCIDEVICEID SDL_mciID[MAX_DRIVES]; +#ifdef BROKEN_MCI_PAUSE +static int SDL_paused[MAX_DRIVES]; +#endif +static int SDL_CD_end_position; + +/* The system-dependent CD control functions */ +static const char *SDL_SYS_CDName(int drive); +static int SDL_SYS_CDOpen(int drive); +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); +static int SDL_SYS_CDPause(SDL_CD *cdrom); +static int SDL_SYS_CDResume(SDL_CD *cdrom); +static int SDL_SYS_CDStop(SDL_CD *cdrom); +static int SDL_SYS_CDEject(SDL_CD *cdrom); +static void SDL_SYS_CDClose(SDL_CD *cdrom); + + +/* Add a CD-ROM drive to our list of valid drives */ +static void AddDrive(char *drive) +{ + int i; + + if ( SDL_numcds < MAX_DRIVES ) { + /* Add this drive to our list */ + i = SDL_numcds; + SDL_cdlist[i] = SDL_strdup(drive); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + ++SDL_numcds; +#ifdef CDROM_DEBUG + fprintf(stderr, "Added CD-ROM drive: %s\n", drive); +#endif + } +} + +int SDL_SYS_CDInit(void) +{ + /* checklist: Drive 'A' - 'Z' */ + int i; + char drive[4]; + + /* Fill in our driver capabilities */ + SDL_CDcaps.Name = SDL_SYS_CDName; + SDL_CDcaps.Open = SDL_SYS_CDOpen; + SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; + SDL_CDcaps.Status = SDL_SYS_CDStatus; + SDL_CDcaps.Play = SDL_SYS_CDPlay; + SDL_CDcaps.Pause = SDL_SYS_CDPause; + SDL_CDcaps.Resume = SDL_SYS_CDResume; + SDL_CDcaps.Stop = SDL_SYS_CDStop; + SDL_CDcaps.Eject = SDL_SYS_CDEject; + SDL_CDcaps.Close = SDL_SYS_CDClose; + + /* Scan the system for CD-ROM drives */ + for ( i='A'; i<='Z'; ++i ) { + SDL_snprintf(drive, SDL_arraysize(drive), "%c:\\", i); + if ( GetDriveType(drive) == DRIVE_CDROM ) { + AddDrive(drive); + } + } + SDL_memset(SDL_mciID, 0, sizeof(SDL_mciID)); + return(0); +} + +/* General ioctl() CD-ROM command function */ +static int SDL_SYS_CDioctl(int id, UINT msg, DWORD flags, void *arg) +{ + MCIERROR mci_error; + + mci_error = mciSendCommand(SDL_mciID[id], msg, flags, (DWORD_PTR)arg); + if ( mci_error ) { + char error[256]; + + mciGetErrorString(mci_error, error, 256); + SDL_SetError("mciSendCommand() error: %s", error); + } + return(!mci_error ? 0 : -1); +} + +static const char *SDL_SYS_CDName(int drive) +{ + return(SDL_cdlist[drive]); +} + +static int SDL_SYS_CDOpen(int drive) +{ + MCI_OPEN_PARMS mci_open; + MCI_SET_PARMS mci_set; + char device[3]; + DWORD flags; + + /* Open the requested device */ + mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO; + device[0] = *SDL_cdlist[drive]; + device[1] = ':'; + device[2] = '\0'; + mci_open.lpstrElementName = device; + flags = + (MCI_OPEN_TYPE|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT); + if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) { + flags &= ~MCI_OPEN_SHAREABLE; + if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) { + return(-1); + } + } + SDL_mciID[drive] = mci_open.wDeviceID; + + /* Set the minute-second-frame time format */ + mci_set.dwTimeFormat = MCI_FORMAT_MSF; + SDL_SYS_CDioctl(drive, MCI_SET, MCI_SET_TIME_FORMAT, &mci_set); + +#ifdef BROKEN_MCI_PAUSE + SDL_paused[drive] = 0; +#endif + return(drive); +} + +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) +{ + MCI_STATUS_PARMS mci_status; + int i, okay; + DWORD flags; + + okay = 0; + mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; + flags = MCI_STATUS_ITEM | MCI_WAIT; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) { + cdrom->numtracks = mci_status.dwReturn; + if ( cdrom->numtracks > SDL_MAX_TRACKS ) { + cdrom->numtracks = SDL_MAX_TRACKS; + } + /* Read all the track TOC entries */ + flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT; + for ( i=0; i<cdrom->numtracks; ++i ) { + cdrom->track[i].id = i+1; + mci_status.dwTrack = cdrom->track[i].id; +#ifdef MCI_CDA_STATUS_TYPE_TRACK + mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, + &mci_status) < 0 ) { + break; + } + if ( mci_status.dwReturn == MCI_CDA_TRACK_AUDIO ) { + cdrom->track[i].type = SDL_AUDIO_TRACK; + } else { + cdrom->track[i].type = SDL_DATA_TRACK; + } +#else + cdrom->track[i].type = SDL_AUDIO_TRACK; +#endif + mci_status.dwItem = MCI_STATUS_POSITION; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, + &mci_status) < 0 ) { + break; + } + cdrom->track[i].offset = MSF_TO_FRAMES( + MCI_MSF_MINUTE(mci_status.dwReturn), + MCI_MSF_SECOND(mci_status.dwReturn), + MCI_MSF_FRAME(mci_status.dwReturn)); + cdrom->track[i].length = 0; + if ( i > 0 ) { + cdrom->track[i-1].length = + cdrom->track[i].offset- + cdrom->track[i-1].offset; + } + } + if ( i == cdrom->numtracks ) { + mci_status.dwTrack = cdrom->track[i - 1].id; + mci_status.dwItem = MCI_STATUS_LENGTH; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, + &mci_status) == 0 ) { + cdrom->track[i - 1].length = MSF_TO_FRAMES( + MCI_MSF_MINUTE(mci_status.dwReturn), + MCI_MSF_SECOND(mci_status.dwReturn), + MCI_MSF_FRAME(mci_status.dwReturn)); + /* compute lead-out offset */ + cdrom->track[i].offset = cdrom->track[i - 1].offset + + cdrom->track[i - 1].length; + cdrom->track[i].length = 0; + okay = 1; + } + } + } + return(okay ? 0 : -1); +} + +/* Get CD-ROM status */ +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) +{ + CDstatus status; + MCI_STATUS_PARMS mci_status; + DWORD flags; + + flags = MCI_STATUS_ITEM | MCI_WAIT; + mci_status.dwItem = MCI_STATUS_MODE; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) { + status = CD_ERROR; + } else { + switch (mci_status.dwReturn) { + case MCI_MODE_NOT_READY: + case MCI_MODE_OPEN: + status = CD_TRAYEMPTY; + break; + case MCI_MODE_STOP: +#ifdef BROKEN_MCI_PAUSE + if ( SDL_paused[cdrom->id] ) { + status = CD_PAUSED; + } else { + status = CD_STOPPED; + } +#else + status = CD_STOPPED; +#endif /* BROKEN_MCI_PAUSE */ + break; + case MCI_MODE_PLAY: +#ifdef BROKEN_MCI_PAUSE + if ( SDL_paused[cdrom->id] ) { + status = CD_PAUSED; + } else { + status = CD_PLAYING; + } +#else + status = CD_PLAYING; +#endif /* BROKEN_MCI_PAUSE */ + break; + case MCI_MODE_PAUSE: + status = CD_PAUSED; + break; + default: + status = CD_ERROR; + break; + } + } + if ( position ) { + if ( status == CD_PLAYING || (status == CD_PAUSED) ) { + mci_status.dwItem = MCI_STATUS_POSITION; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, + &mci_status) == 0 ) { + *position = MSF_TO_FRAMES( + MCI_MSF_MINUTE(mci_status.dwReturn), + MCI_MSF_SECOND(mci_status.dwReturn), + MCI_MSF_FRAME(mci_status.dwReturn)); + } else { + *position = 0; + } + } else { + *position = 0; + } + } + return(status); +} + +/* Start play */ +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) +{ + MCI_PLAY_PARMS mci_play; + int m, s, f; + DWORD flags; + + flags = MCI_FROM | MCI_TO | MCI_NOTIFY; + mci_play.dwCallback = 0; + FRAMES_TO_MSF(start, &m, &s, &f); + mci_play.dwFrom = MCI_MAKE_MSF(m, s, f); + FRAMES_TO_MSF(start+length, &m, &s, &f); + mci_play.dwTo = MCI_MAKE_MSF(m, s, f); + SDL_CD_end_position = mci_play.dwTo; + return(SDL_SYS_CDioctl(cdrom->id, MCI_PLAY, flags, &mci_play)); +} + +/* Pause play */ +static int SDL_SYS_CDPause(SDL_CD *cdrom) +{ +#ifdef BROKEN_MCI_PAUSE + SDL_paused[cdrom->id] = 1; +#endif + return(SDL_SYS_CDioctl(cdrom->id, MCI_PAUSE, MCI_WAIT, NULL)); +} + +/* Resume play */ +static int SDL_SYS_CDResume(SDL_CD *cdrom) +{ +#ifdef BROKEN_MCI_PAUSE + MCI_STATUS_PARMS mci_status; + int okay; + int flags; + + okay = 0; + /* Play from the current play position to the end position set earlier */ + flags = MCI_STATUS_ITEM | MCI_WAIT; + mci_status.dwItem = MCI_STATUS_POSITION; + if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) { + MCI_PLAY_PARMS mci_play; + + flags = MCI_FROM | MCI_TO | MCI_NOTIFY; + mci_play.dwCallback = 0; + mci_play.dwFrom = mci_status.dwReturn; + mci_play.dwTo = SDL_CD_end_position; + if (SDL_SYS_CDioctl(cdrom->id,MCI_PLAY,flags,&mci_play) == 0) { + okay = 1; + SDL_paused[cdrom->id] = 0; + } + } + return(okay ? 0 : -1); +#else + return(SDL_SYS_CDioctl(cdrom->id, MCI_RESUME, MCI_WAIT, NULL)); +#endif /* BROKEN_MCI_PAUSE */ +} + +/* Stop play */ +static int SDL_SYS_CDStop(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, MCI_STOP, MCI_WAIT, NULL)); +} + +/* Eject the CD-ROM */ +static int SDL_SYS_CDEject(SDL_CD *cdrom) +{ + return(SDL_SYS_CDioctl(cdrom->id, MCI_SET, MCI_SET_DOOR_OPEN, NULL)); +} + +/* Close the CD-ROM handle */ +static void SDL_SYS_CDClose(SDL_CD *cdrom) +{ + SDL_SYS_CDioctl(cdrom->id, MCI_CLOSE, MCI_WAIT, NULL); +} + +void SDL_SYS_CDQuit(void) +{ + int i; + + if ( SDL_numcds > 0 ) { + for ( i=0; i<SDL_numcds; ++i ) { + SDL_free(SDL_cdlist[i]); + SDL_cdlist[i] = NULL; + } + SDL_numcds = 0; + } +} + +#endif /* SDL_CDROM_WIN32 */ diff --git a/3rdparty/SDL/src/cpuinfo/SDL_cpuinfo.c b/3rdparty/SDL/src/cpuinfo/SDL_cpuinfo.c new file mode 100644 index 0000000..0cd0838 --- /dev/null +++ b/3rdparty/SDL/src/cpuinfo/SDL_cpuinfo.c @@ -0,0 +1,499 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* CPU feature detection for SDL */ + +#include "SDL.h" +#include "SDL_cpuinfo.h" + +#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) +#include <sys/sysctl.h> /* For AltiVec check */ +#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP +#include <signal.h> +#include <setjmp.h> +#endif + +#define CPU_HAS_RDTSC 0x00000001 +#define CPU_HAS_MMX 0x00000002 +#define CPU_HAS_MMXEXT 0x00000004 +#define CPU_HAS_3DNOW 0x00000010 +#define CPU_HAS_3DNOWEXT 0x00000020 +#define CPU_HAS_SSE 0x00000040 +#define CPU_HAS_SSE2 0x00000080 +#define CPU_HAS_ALTIVEC 0x00000100 + +#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ +/* This is the brute force way of detecting instruction sets... + the idea is borrowed from the libmpeg2 library - thanks! + */ +static jmp_buf jmpbuf; +static void illegal_instruction(int sig) +{ + longjmp(jmpbuf, 1); +} +#endif /* HAVE_SETJMP */ + +static __inline__ int CPU_haveCPUID(void) +{ + int has_CPUID = 0; +#if defined(__GNUC__) && defined(i386) + __asm__ ( +" pushfl # Get original EFLAGS \n" +" popl %%eax \n" +" movl %%eax,%%ecx \n" +" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" +" pushl %%eax # Save new EFLAGS value on stack \n" +" popfl # Replace current EFLAGS value \n" +" pushfl # Get new EFLAGS \n" +" popl %%eax # Store new EFLAGS in EAX \n" +" xorl %%ecx,%%eax # Can not toggle ID bit, \n" +" jz 1f # Processor=80486 \n" +" movl $1,%0 # We have CPUID support \n" +"1: \n" + : "=m" (has_CPUID) + : + : "%eax", "%ecx" + ); +#elif defined(__GNUC__) && defined(__x86_64__) +/* Technically, if this is being compiled under __x86_64__ then it has +CPUid by definition. But it's nice to be able to prove it. :) */ + __asm__ ( +" pushfq # Get original EFLAGS \n" +" popq %%rax \n" +" movq %%rax,%%rcx \n" +" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" +" pushq %%rax # Save new EFLAGS value on stack \n" +" popfq # Replace current EFLAGS value \n" +" pushfq # Get new EFLAGS \n" +" popq %%rax # Store new EFLAGS in EAX \n" +" xorl %%ecx,%%eax # Can not toggle ID bit, \n" +" jz 1f # Processor=80486 \n" +" movl $1,%0 # We have CPUID support \n" +"1: \n" + : "=m" (has_CPUID) + : + : "%rax", "%rcx" + ); +#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + __asm { + pushfd ; Get original EFLAGS + pop eax + mov ecx, eax + xor eax, 200000h ; Flip ID bit in EFLAGS + push eax ; Save new EFLAGS value on stack + popfd ; Replace current EFLAGS value + pushfd ; Get new EFLAGS + pop eax ; Store new EFLAGS in EAX + xor eax, ecx ; Can not toggle ID bit, + jz done ; Processor=80486 + mov has_CPUID,1 ; We have CPUID support +done: + } +#elif defined(__sun) && defined(__i386) + __asm ( +" pushfl \n" +" popl %eax \n" +" movl %eax,%ecx \n" +" xorl $0x200000,%eax \n" +" pushl %eax \n" +" popfl \n" +" pushfl \n" +" popl %eax \n" +" xorl %ecx,%eax \n" +" jz 1f \n" +" movl $1,-8(%ebp) \n" +"1: \n" + ); +#elif defined(__sun) && defined(__amd64) + __asm ( +" pushfq \n" +" popq %rax \n" +" movq %rax,%rcx \n" +" xorl $0x200000,%eax \n" +" pushq %rax \n" +" popfq \n" +" pushfq \n" +" popq %rax \n" +" xorl %ecx,%eax \n" +" jz 1f \n" +" movl $1,-8(%rbp) \n" +"1: \n" + ); +#endif + return has_CPUID; +} + +static __inline__ int CPU_getCPUIDFeatures(void) +{ + int features = 0; +#if defined(__GNUC__) && defined(i386) + __asm__ ( +" xorl %%eax,%%eax # Set up for CPUID instruction \n" +" pushl %%ebx \n" +" cpuid # Get and save vendor ID \n" +" popl %%ebx \n" +" cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" +" jl 1f # We dont have the CPUID instruction\n" +" xorl %%eax,%%eax \n" +" incl %%eax \n" +" pushl %%ebx \n" +" cpuid # Get family/model/stepping/features\n" +" popl %%ebx \n" +" movl %%edx,%0 \n" +"1: \n" + : "=m" (features) + : + : "%eax", "%ecx", "%edx" + ); +#elif defined(__GNUC__) && defined(__x86_64__) + __asm__ ( +" xorl %%eax,%%eax # Set up for CPUID instruction \n" +" pushq %%rbx \n" +" cpuid # Get and save vendor ID \n" +" popq %%rbx \n" +" cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" +" jl 1f # We dont have the CPUID instruction\n" +" xorl %%eax,%%eax \n" +" incl %%eax \n" +" pushq %%rbx \n" +" cpuid # Get family/model/stepping/features\n" +" popq %%rbx \n" +" movl %%edx,%0 \n" +"1: \n" + : "=m" (features) + : + : "%rax", "%rcx", "%rdx" + ); +#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + __asm { + xor eax, eax ; Set up for CPUID instruction + push ebx + cpuid ; Get and save vendor ID + pop ebx + cmp eax, 1 ; Make sure 1 is valid input for CPUID + jl done ; We dont have the CPUID instruction + xor eax, eax + inc eax + push ebx + cpuid ; Get family/model/stepping/features + pop ebx + mov features, edx +done: + } +#elif defined(__sun) && (defined(__i386) || defined(__amd64)) + __asm( +" xorl %eax,%eax \n" +" pushl %ebx \n" +" cpuid \n" +" popl %ebx \n" +" cmpl $1,%eax \n" +" jl 1f \n" +" xorl %eax,%eax \n" +" incl %eax \n" +" pushl %ebx \n" +" cpuid \n" +" popl %ebx \n" +#ifdef __i386 +" movl %edx,-8(%ebp) \n" +#else +" movl %edx,-8(%rbp) \n" +#endif +"1: \n" +#endif + return features; +} + +static __inline__ int CPU_getCPUIDFeaturesExt(void) +{ + int features = 0; +#if defined(__GNUC__) && defined(i386) + __asm__ ( +" movl $0x80000000,%%eax # Query for extended functions \n" +" pushl %%ebx \n" +" cpuid # Get extended function limit \n" +" popl %%ebx \n" +" cmpl $0x80000001,%%eax \n" +" jl 1f # Nope, we dont have function 800000001h\n" +" movl $0x80000001,%%eax # Setup extended function 800000001h\n" +" pushl %%ebx \n" +" cpuid # and get the information \n" +" popl %%ebx \n" +" movl %%edx,%0 \n" +"1: \n" + : "=m" (features) + : + : "%eax", "%ecx", "%edx" + ); +#elif defined(__GNUC__) && defined (__x86_64__) + __asm__ ( +" movl $0x80000000,%%eax # Query for extended functions \n" +" pushq %%rbx \n" +" cpuid # Get extended function limit \n" +" popq %%rbx \n" +" cmpl $0x80000001,%%eax \n" +" jl 1f # Nope, we dont have function 800000001h\n" +" movl $0x80000001,%%eax # Setup extended function 800000001h\n" +" pushq %%rbx \n" +" cpuid # and get the information \n" +" popq %%rbx \n" +" movl %%edx,%0 \n" +"1: \n" + : "=m" (features) + : + : "%rax", "%rcx", "%rdx" + ); +#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + __asm { + mov eax,80000000h ; Query for extended functions + push ebx + cpuid ; Get extended function limit + pop ebx + cmp eax,80000001h + jl done ; Nope, we dont have function 800000001h + mov eax,80000001h ; Setup extended function 800000001h + push ebx + cpuid ; and get the information + pop ebx + mov features,edx +done: + } +#elif defined(__sun) && ( defined(__i386) || defined(__amd64) ) + __asm ( +" movl $0x80000000,%eax \n" +" pushl %ebx \n" +" cpuid \n" +" popl %ebx \n" +" cmpl $0x80000001,%eax \n" +" jl 1f \n" +" movl $0x80000001,%eax \n" +" pushl %ebx \n" +" cpuid \n" +" popl %ebx \n" +#ifdef __i386 +" movl %edx,-8(%ebp) \n" +#else +" movl %edx,-8(%rbp) \n" +#endif +"1: \n" + ); +#endif + return features; +} + +static __inline__ int CPU_haveRDTSC(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x00000010); + } + return 0; +} + +static __inline__ int CPU_haveMMX(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x00800000); + } + return 0; +} + +static __inline__ int CPU_haveMMXExt(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x00400000); + } + return 0; +} + +static __inline__ int CPU_have3DNow(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x80000000); + } + return 0; +} + +static __inline__ int CPU_have3DNowExt(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeaturesExt() & 0x40000000); + } + return 0; +} + +static __inline__ int CPU_haveSSE(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x02000000); + } + return 0; +} + +static __inline__ int CPU_haveSSE2(void) +{ + if ( CPU_haveCPUID() ) { + return (CPU_getCPUIDFeatures() & 0x04000000); + } + return 0; +} + +static __inline__ int CPU_haveAltiVec(void) +{ + volatile int altivec = 0; +#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) + int selectors[2] = { CTL_HW, HW_VECTORUNIT }; + int hasVectorUnit = 0; + size_t length = sizeof(hasVectorUnit); + int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); + if( 0 == error ) + altivec = (hasVectorUnit != 0); +#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP + void (*handler)(int sig); + handler = signal(SIGILL, illegal_instruction); + if ( setjmp(jmpbuf) == 0 ) { + asm volatile ("mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1)); + altivec = 1; + } + signal(SIGILL, handler); +#endif + return altivec; +} + +static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; + +static Uint32 SDL_GetCPUFeatures(void) +{ + if ( SDL_CPUFeatures == 0xFFFFFFFF ) { + SDL_CPUFeatures = 0; + if ( CPU_haveRDTSC() ) { + SDL_CPUFeatures |= CPU_HAS_RDTSC; + } + if ( CPU_haveMMX() ) { + SDL_CPUFeatures |= CPU_HAS_MMX; + } + if ( CPU_haveMMXExt() ) { + SDL_CPUFeatures |= CPU_HAS_MMXEXT; + } + if ( CPU_have3DNow() ) { + SDL_CPUFeatures |= CPU_HAS_3DNOW; + } + if ( CPU_have3DNowExt() ) { + SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; + } + if ( CPU_haveSSE() ) { + SDL_CPUFeatures |= CPU_HAS_SSE; + } + if ( CPU_haveSSE2() ) { + SDL_CPUFeatures |= CPU_HAS_SSE2; + } + if ( CPU_haveAltiVec() ) { + SDL_CPUFeatures |= CPU_HAS_ALTIVEC; + } + } + return SDL_CPUFeatures; +} + +SDL_bool SDL_HasRDTSC(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_RDTSC ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasMMX(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasMMXExt(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_Has3DNow(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOW ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_Has3DNowExt(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasSSE(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_SSE ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasSSE2(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasAltiVec(void) +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +#ifdef TEST_MAIN + +#include <stdio.h> + +int main() +{ + printf("RDTSC: %d\n", SDL_HasRDTSC()); + printf("MMX: %d\n", SDL_HasMMX()); + printf("MMXExt: %d\n", SDL_HasMMXExt()); + printf("3DNow: %d\n", SDL_Has3DNow()); + printf("3DNowExt: %d\n", SDL_Has3DNowExt()); + printf("SSE: %d\n", SDL_HasSSE()); + printf("SSE2: %d\n", SDL_HasSSE2()); + printf("AltiVec: %d\n", SDL_HasAltiVec()); + return 0; +} + +#endif /* TEST_MAIN */ diff --git a/3rdparty/SDL/src/events/SDL_active.c b/3rdparty/SDL/src/events/SDL_active.c new file mode 100644 index 0000000..201fb80 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_active.c @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Application focus/iconification handling code for SDL */ + +#include "SDL_events.h" +#include "SDL_events_c.h" + + +/* These are static for our active event handling code */ +static Uint8 SDL_appstate = 0; + +/* Public functions */ +int SDL_AppActiveInit(void) +{ + /* Start completely active */ + SDL_appstate = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + /* That's it! */ + return(0); +} +void SDL_AppActiveQuit(void) +{ +} + +Uint8 SDL_GetAppState(void) +{ + return(SDL_appstate); +} + +/* This is global for SDL_eventloop.c */ +int SDL_PrivateAppActive(Uint8 gain, Uint8 state) +{ + int posted; + Uint8 new_state; + + /* Modify the current state with the given mask */ + if ( gain ) { + new_state = (SDL_appstate | state); + } else { + new_state = (SDL_appstate & ~state); + } + + /* Drop events that don't change state */ + if ( new_state == SDL_appstate ) { + return(0); + } + + /* Update internal active state */ + SDL_appstate = new_state; + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[SDL_ACTIVEEVENT] == SDL_ENABLE ) { + SDL_Event event; + SDL_memset(&event, 0, sizeof(event)); + event.type = SDL_ACTIVEEVENT; + event.active.gain = gain; + event.active.state = state; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + + /* If we lost keyboard focus, post key-up events */ + if ( (state & SDL_APPINPUTFOCUS) && !gain ) { + SDL_ResetKeyboard(); + } + /* If we were minimized, post button-up events */ + if ( (state & SDL_APPACTIVE) && !gain ) { + SDL_ResetMouse(); + } + return(posted); +} diff --git a/3rdparty/SDL/src/events/SDL_events.c b/3rdparty/SDL/src/events/SDL_events.c new file mode 100644 index 0000000..8f23c01 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_events.c @@ -0,0 +1,502 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General event handling code for SDL */ + +#include "SDL.h" +#include "SDL_syswm.h" +#include "SDL_sysevents.h" +#include "SDL_events_c.h" +#include "../timer/SDL_timer_c.h" +#if !SDL_JOYSTICK_DISABLED +#include "../joystick/SDL_joystick_c.h" +#endif + +/* Public data -- the event filter */ +SDL_EventFilter SDL_EventOK = NULL; +Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; +static Uint32 SDL_eventstate = 0; + +/* Private data -- event queue */ +#define MAXEVENTS 128 +static struct { + SDL_mutex *lock; + int active; + int head; + int tail; + SDL_Event event[MAXEVENTS]; + int wmmsg_next; + struct SDL_SysWMmsg wmmsg[MAXEVENTS]; +} SDL_EventQ; + +/* Private data -- event locking structure */ +static struct { + SDL_mutex *lock; + int safe; +} SDL_EventLock; + +/* Thread functions */ +static SDL_Thread *SDL_EventThread = NULL; /* Thread handle */ +static Uint32 event_thread; /* The event thread id */ + +void SDL_Lock_EventThread(void) +{ + if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) { + /* Grab lock and spin until we're sure event thread stopped */ + SDL_mutexP(SDL_EventLock.lock); + while ( ! SDL_EventLock.safe ) { + SDL_Delay(1); + } + } +} +void SDL_Unlock_EventThread(void) +{ + if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) { + SDL_mutexV(SDL_EventLock.lock); + } +} + +#ifdef __OS2__ +/* + * We'll increase the priority of GobbleEvents thread, so it will process + * events in time for sure! For this, we need the DosSetPriority() API + * from the os2.h include file. + */ +#define INCL_DOSPROCESS +#include <os2.h> +#include <time.h> +#endif + +static int SDLCALL SDL_GobbleEvents(void *unused) +{ + event_thread = SDL_ThreadID(); + +#ifdef __OS2__ +#ifdef USE_DOSSETPRIORITY + /* Increase thread priority, so it will process events in time for sure! */ + DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +16, 0); +#endif +#endif + + while ( SDL_EventQ.active ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Get events from the video subsystem */ + if ( video ) { + video->PumpEvents(this); + } + + /* Queue pending key-repeat events */ + SDL_CheckKeyRepeat(); + +#if !SDL_JOYSTICK_DISABLED + /* Check for joystick state change */ + if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) { + SDL_JoystickUpdate(); + } +#endif + + /* Give up the CPU for the rest of our timeslice */ + SDL_EventLock.safe = 1; + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(1); + + /* Check for event locking. + On the P of the lock mutex, if the lock is held, this thread + will wait until the lock is released before continuing. The + safe flag will be set, meaning that the other thread can go + about it's business. The safe flag is reset before the V, + so as soon as the mutex is free, other threads can see that + it's not safe to interfere with the event thread. + */ + SDL_mutexP(SDL_EventLock.lock); + SDL_EventLock.safe = 0; + SDL_mutexV(SDL_EventLock.lock); + } + SDL_SetTimerThreaded(0); + event_thread = 0; + return(0); +} + +static int SDL_StartEventThread(Uint32 flags) +{ + /* Reset everything to zero */ + SDL_EventThread = NULL; + SDL_memset(&SDL_EventLock, 0, sizeof(SDL_EventLock)); + + /* Create the lock and set ourselves active */ +#if !SDL_THREADS_DISABLED + SDL_EventQ.lock = SDL_CreateMutex(); + if ( SDL_EventQ.lock == NULL ) { +#ifdef __MACOS__ /* MacOS classic you can't multithread, so no lock needed */ + ; +#else + return(-1); +#endif + } +#endif /* !SDL_THREADS_DISABLED */ + SDL_EventQ.active = 1; + + if ( (flags&SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) { + SDL_EventLock.lock = SDL_CreateMutex(); + if ( SDL_EventLock.lock == NULL ) { + return(-1); + } + SDL_EventLock.safe = 0; + + /* The event thread will handle timers too */ + SDL_SetTimerThreaded(2); +#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__) +#undef SDL_CreateThread + SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL, NULL, NULL); +#else + SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL); +#endif + if ( SDL_EventThread == NULL ) { + return(-1); + } + } else { + event_thread = 0; + } + return(0); +} + +static void SDL_StopEventThread(void) +{ + SDL_EventQ.active = 0; + if ( SDL_EventThread ) { + SDL_WaitThread(SDL_EventThread, NULL); + SDL_EventThread = NULL; + SDL_DestroyMutex(SDL_EventLock.lock); + SDL_EventLock.lock = NULL; + } +#ifndef IPOD + SDL_DestroyMutex(SDL_EventQ.lock); + SDL_EventQ.lock = NULL; +#endif +} + +Uint32 SDL_EventThreadID(void) +{ + return(event_thread); +} + +/* Public functions */ + +void SDL_StopEventLoop(void) +{ + /* Halt the event thread, if running */ + SDL_StopEventThread(); + + /* Shutdown event handlers */ + SDL_AppActiveQuit(); + SDL_KeyboardQuit(); + SDL_MouseQuit(); + SDL_QuitQuit(); + + /* Clean out EventQ */ + SDL_EventQ.head = 0; + SDL_EventQ.tail = 0; + SDL_EventQ.wmmsg_next = 0; +} + +/* This function (and associated calls) may be called more than once */ +int SDL_StartEventLoop(Uint32 flags) +{ + int retcode; + + /* Clean out the event queue */ + SDL_EventThread = NULL; + SDL_EventQ.lock = NULL; + SDL_StopEventLoop(); + + /* No filter to start with, process most event types */ + SDL_EventOK = NULL; + SDL_memset(SDL_ProcessEvents,SDL_ENABLE,sizeof(SDL_ProcessEvents)); + SDL_eventstate = ~0; + /* It's not save to call SDL_EventState() yet */ + SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT); + SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE; + + /* Initialize event handlers */ + retcode = 0; + retcode += SDL_AppActiveInit(); + retcode += SDL_KeyboardInit(); + retcode += SDL_MouseInit(); + retcode += SDL_QuitInit(); + if ( retcode < 0 ) { + /* We don't expect them to fail, but... */ + return(-1); + } + + /* Create the lock and event thread */ + if ( SDL_StartEventThread(flags) < 0 ) { + SDL_StopEventLoop(); + return(-1); + } + return(0); +} + + +/* Add an event to the event queue -- called with the queue locked */ +static int SDL_AddEvent(SDL_Event *event) +{ + int tail, added; + + tail = (SDL_EventQ.tail+1)%MAXEVENTS; + if ( tail == SDL_EventQ.head ) { + /* Overflow, drop event */ + added = 0; + } else { + SDL_EventQ.event[SDL_EventQ.tail] = *event; + if (event->type == SDL_SYSWMEVENT) { + /* Note that it's possible to lose an event */ + int next = SDL_EventQ.wmmsg_next; + SDL_EventQ.wmmsg[next] = *event->syswm.msg; + SDL_EventQ.event[SDL_EventQ.tail].syswm.msg = + &SDL_EventQ.wmmsg[next]; + SDL_EventQ.wmmsg_next = (next+1)%MAXEVENTS; + } + SDL_EventQ.tail = tail; + added = 1; + } + return(added); +} + +/* Cut an event, and return the next valid spot, or the tail */ +/* -- called with the queue locked */ +static int SDL_CutEvent(int spot) +{ + if ( spot == SDL_EventQ.head ) { + SDL_EventQ.head = (SDL_EventQ.head+1)%MAXEVENTS; + return(SDL_EventQ.head); + } else + if ( (spot+1)%MAXEVENTS == SDL_EventQ.tail ) { + SDL_EventQ.tail = spot; + return(SDL_EventQ.tail); + } else + /* We cut the middle -- shift everything over */ + { + int here, next; + + /* This can probably be optimized with SDL_memcpy() -- careful! */ + if ( --SDL_EventQ.tail < 0 ) { + SDL_EventQ.tail = MAXEVENTS-1; + } + for ( here=spot; here != SDL_EventQ.tail; here = next ) { + next = (here+1)%MAXEVENTS; + SDL_EventQ.event[here] = SDL_EventQ.event[next]; + } + return(spot); + } + /* NOTREACHED */ +} + +/* Lock the event queue, take a peep at it, and unlock it */ +int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, + Uint32 mask) +{ + int i, used; + + /* Don't look after we've quit */ + if ( ! SDL_EventQ.active ) { + return(-1); + } + /* Lock the event queue */ + used = 0; + if ( SDL_mutexP(SDL_EventQ.lock) == 0 ) { + if ( action == SDL_ADDEVENT ) { + for ( i=0; i<numevents; ++i ) { + used += SDL_AddEvent(&events[i]); + } + } else { + SDL_Event tmpevent; + int spot; + + /* If 'events' is NULL, just see if they exist */ + if ( events == NULL ) { + action = SDL_PEEKEVENT; + numevents = 1; + events = &tmpevent; + } + spot = SDL_EventQ.head; + while ((used < numevents)&&(spot != SDL_EventQ.tail)) { + if ( mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type) ) { + events[used++] = SDL_EventQ.event[spot]; + if ( action == SDL_GETEVENT ) { + spot = SDL_CutEvent(spot); + } else { + spot = (spot+1)%MAXEVENTS; + } + } else { + spot = (spot+1)%MAXEVENTS; + } + } + } + SDL_mutexV(SDL_EventQ.lock); + } else { + SDL_SetError("Couldn't lock event queue"); + used = -1; + } + return(used); +} + +/* Run the system dependent event loops */ +void SDL_PumpEvents(void) +{ + if ( !SDL_EventThread ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Get events from the video subsystem */ + if ( video ) { + video->PumpEvents(this); + } + + /* Queue pending key-repeat events */ + SDL_CheckKeyRepeat(); + +#if !SDL_JOYSTICK_DISABLED + /* Check for joystick state change */ + if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) { + SDL_JoystickUpdate(); + } +#endif + } +} + +/* Public functions */ + +int SDL_PollEvent (SDL_Event *event) +{ + SDL_PumpEvents(); + + /* We can't return -1, just return 0 (no event) on error */ + if ( SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS) <= 0 ) + return 0; + return 1; +} + +int SDL_WaitEvent (SDL_Event *event) +{ + while ( 1 ) { + SDL_PumpEvents(); + switch(SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) { + case -1: return 0; + case 1: return 1; + case 0: SDL_Delay(10); + } + } +} + +int SDL_PushEvent(SDL_Event *event) +{ + if ( SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0) <= 0 ) + return -1; + return 0; +} + +void SDL_SetEventFilter (SDL_EventFilter filter) +{ + SDL_Event bitbucket; + + /* Set filter and discard pending events */ + SDL_EventOK = filter; + while ( SDL_PollEvent(&bitbucket) > 0 ) + ; +} + +SDL_EventFilter SDL_GetEventFilter(void) +{ + return(SDL_EventOK); +} + +Uint8 SDL_EventState (Uint8 type, int state) +{ + SDL_Event bitbucket; + Uint8 current_state; + + /* If SDL_ALLEVENTS was specified... */ + if ( type == 0xFF ) { + current_state = SDL_IGNORE; + for ( type=0; type<SDL_NUMEVENTS; ++type ) { + if ( SDL_ProcessEvents[type] != SDL_IGNORE ) { + current_state = SDL_ENABLE; + } + SDL_ProcessEvents[type] = state; + if ( state == SDL_ENABLE ) { + SDL_eventstate |= (0x00000001 << (type)); + } else { + SDL_eventstate &= ~(0x00000001 << (type)); + } + } + while ( SDL_PollEvent(&bitbucket) > 0 ) + ; + return(current_state); + } + + /* Just set the state for one event type */ + current_state = SDL_ProcessEvents[type]; + switch (state) { + case SDL_IGNORE: + case SDL_ENABLE: + /* Set state and discard pending events */ + SDL_ProcessEvents[type] = state; + if ( state == SDL_ENABLE ) { + SDL_eventstate |= (0x00000001 << (type)); + } else { + SDL_eventstate &= ~(0x00000001 << (type)); + } + while ( SDL_PollEvent(&bitbucket) > 0 ) + ; + break; + default: + /* Querying state? */ + break; + } + return(current_state); +} + +/* This is a generic event handler. + */ +int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message) +{ + int posted; + + posted = 0; + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_Event event; + SDL_memset(&event, 0, sizeof(event)); + event.type = SDL_SYSWMEVENT; + event.syswm.msg = message; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + /* Update internal event state */ + return(posted); +} diff --git a/3rdparty/SDL/src/events/SDL_events_c.h b/3rdparty/SDL/src/events/SDL_events_c.h new file mode 100644 index 0000000..4378451 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_events_c.h @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_events.c */ +#include "SDL_events.h" + +/* Start and stop the event processing loop */ +extern int SDL_StartEventLoop(Uint32 flags); +extern void SDL_StopEventLoop(void); +extern void SDL_QuitInterrupt(void); + +extern void SDL_Lock_EventThread(void); +extern void SDL_Unlock_EventThread(void); +extern Uint32 SDL_EventThreadID(void); + +/* Event handler init routines */ +extern int SDL_AppActiveInit(void); +extern int SDL_KeyboardInit(void); +extern int SDL_MouseInit(void); +extern int SDL_QuitInit(void); + +/* Event handler quit routines */ +extern void SDL_AppActiveQuit(void); +extern void SDL_KeyboardQuit(void); +extern void SDL_MouseQuit(void); +extern void SDL_QuitQuit(void); + +/* The event filter function */ +extern SDL_EventFilter SDL_EventOK; + +/* The array of event processing states */ +extern Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; + +/* Internal event queueing functions + (from SDL_active.c, SDL_mouse.c, SDL_keyboard.c, SDL_quit.c, SDL_events.c) + */ +extern int SDL_PrivateAppActive(Uint8 gain, Uint8 state); +extern int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, + Sint16 x, Sint16 y); +extern int SDL_PrivateMouseButton(Uint8 state, Uint8 button,Sint16 x,Sint16 y); +extern int SDL_PrivateKeyboard(Uint8 state, SDL_keysym *key); +extern int SDL_PrivateResize(int w, int h); +extern int SDL_PrivateExpose(void); +extern int SDL_PrivateQuit(void); +extern int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message); + +/* Used to clamp the mouse coordinates separately from the video surface */ +extern void SDL_SetMouseRange(int maxX, int maxY); + +/* Used by the activity event handler to remove mouse focus */ +extern void SDL_ResetMouse(void); + +/* Used by the activity event handler to remove keyboard focus */ +extern void SDL_ResetKeyboard(void); + +/* Used by the event loop to queue pending keyboard repeat events */ +extern void SDL_CheckKeyRepeat(void); + +/* Used by the OS keyboard code to detect whether or not to do UNICODE */ +#ifndef DEFAULT_UNICODE_TRANSLATION +#define DEFAULT_UNICODE_TRANSLATION 0 /* Default off because of overhead */ +#endif +extern int SDL_TranslateUNICODE; diff --git a/3rdparty/SDL/src/events/SDL_expose.c b/3rdparty/SDL/src/events/SDL_expose.c new file mode 100644 index 0000000..d5b0143 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_expose.c @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Refresh event handling code for SDL */ + +#include "SDL_events.h" +#include "SDL_events_c.h" + + +/* This is global for SDL_eventloop.c */ +int SDL_PrivateExpose(void) +{ + int posted; + SDL_Event events[32]; + + /* Pull out all old refresh events */ + SDL_PeepEvents(events, sizeof(events)/sizeof(events[0]), + SDL_GETEVENT, SDL_VIDEOEXPOSEMASK); + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[SDL_VIDEOEXPOSE] == SDL_ENABLE ) { + SDL_Event event; + event.type = SDL_VIDEOEXPOSE; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} diff --git a/3rdparty/SDL/src/events/SDL_keyboard.c b/3rdparty/SDL/src/events/SDL_keyboard.c new file mode 100644 index 0000000..5753927 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_keyboard.c @@ -0,0 +1,614 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General keyboard handling code for SDL */ + +#include "SDL_timer.h" +#include "SDL_events.h" +#include "SDL_events_c.h" +#include "SDL_sysevents.h" + + +/* Global keystate information */ +static Uint8 SDL_KeyState[SDLK_LAST]; +static SDLMod SDL_ModState; +int SDL_TranslateUNICODE = 0; + +static const char *keynames[SDLK_LAST]; /* Array of keycode names */ + +/* + * jk 991215 - added + */ +struct { + int firsttime; /* if we check against the delay or repeat value */ + int delay; /* the delay before we start repeating */ + int interval; /* the delay between key repeat events */ + Uint32 timestamp; /* the time the first keydown event occurred */ + + SDL_Event evt; /* the event we are supposed to repeat */ +} SDL_KeyRepeat; + +/* Global no-lock-keys support */ +static Uint8 SDL_NoLockKeys; + +#define SDL_NLK_CAPS 0x01 +#define SDL_NLK_NUM 0x02 + +/* Public functions */ +int SDL_KeyboardInit(void) +{ + const char* env; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Set default mode of UNICODE translation */ + SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION); + + /* Initialize the tables */ + SDL_ModState = KMOD_NONE; + SDL_memset((void*)keynames, 0, sizeof(keynames)); + SDL_memset(SDL_KeyState, 0, sizeof(SDL_KeyState)); + video->InitOSKeymap(this); + + SDL_EnableKeyRepeat(0, 0); + + /* Allow environment override to disable special lock-key behavior */ + SDL_NoLockKeys = 0; + env = SDL_getenv("SDL_DISABLE_LOCK_KEYS"); + if (env) { + switch (SDL_atoi(env)) { + case 1: + SDL_NoLockKeys = SDL_NLK_CAPS | SDL_NLK_NUM; + break; + case 2: + SDL_NoLockKeys = SDL_NLK_CAPS; + break; + case 3: + SDL_NoLockKeys = SDL_NLK_NUM; + break; + default: + break; + } + } + + /* Fill in the blanks in keynames */ + keynames[SDLK_BACKSPACE] = "backspace"; + keynames[SDLK_TAB] = "tab"; + keynames[SDLK_CLEAR] = "clear"; + keynames[SDLK_RETURN] = "return"; + keynames[SDLK_PAUSE] = "pause"; + keynames[SDLK_ESCAPE] = "escape"; + keynames[SDLK_SPACE] = "space"; + keynames[SDLK_EXCLAIM] = "!"; + keynames[SDLK_QUOTEDBL] = "\""; + keynames[SDLK_HASH] = "#"; + keynames[SDLK_DOLLAR] = "$"; + keynames[SDLK_AMPERSAND] = "&"; + keynames[SDLK_QUOTE] = "'"; + keynames[SDLK_LEFTPAREN] = "("; + keynames[SDLK_RIGHTPAREN] = ")"; + keynames[SDLK_ASTERISK] = "*"; + keynames[SDLK_PLUS] = "+"; + keynames[SDLK_COMMA] = ","; + keynames[SDLK_MINUS] = "-"; + keynames[SDLK_PERIOD] = "."; + keynames[SDLK_SLASH] = "/"; + keynames[SDLK_0] = "0"; + keynames[SDLK_1] = "1"; + keynames[SDLK_2] = "2"; + keynames[SDLK_3] = "3"; + keynames[SDLK_4] = "4"; + keynames[SDLK_5] = "5"; + keynames[SDLK_6] = "6"; + keynames[SDLK_7] = "7"; + keynames[SDLK_8] = "8"; + keynames[SDLK_9] = "9"; + keynames[SDLK_COLON] = ":"; + keynames[SDLK_SEMICOLON] = ";"; + keynames[SDLK_LESS] = "<"; + keynames[SDLK_EQUALS] = "="; + keynames[SDLK_GREATER] = ">"; + keynames[SDLK_QUESTION] = "?"; + keynames[SDLK_AT] = "@"; + keynames[SDLK_LEFTBRACKET] = "["; + keynames[SDLK_BACKSLASH] = "\\"; + keynames[SDLK_RIGHTBRACKET] = "]"; + keynames[SDLK_CARET] = "^"; + keynames[SDLK_UNDERSCORE] = "_"; + keynames[SDLK_BACKQUOTE] = "`"; + keynames[SDLK_a] = "a"; + keynames[SDLK_b] = "b"; + keynames[SDLK_c] = "c"; + keynames[SDLK_d] = "d"; + keynames[SDLK_e] = "e"; + keynames[SDLK_f] = "f"; + keynames[SDLK_g] = "g"; + keynames[SDLK_h] = "h"; + keynames[SDLK_i] = "i"; + keynames[SDLK_j] = "j"; + keynames[SDLK_k] = "k"; + keynames[SDLK_l] = "l"; + keynames[SDLK_m] = "m"; + keynames[SDLK_n] = "n"; + keynames[SDLK_o] = "o"; + keynames[SDLK_p] = "p"; + keynames[SDLK_q] = "q"; + keynames[SDLK_r] = "r"; + keynames[SDLK_s] = "s"; + keynames[SDLK_t] = "t"; + keynames[SDLK_u] = "u"; + keynames[SDLK_v] = "v"; + keynames[SDLK_w] = "w"; + keynames[SDLK_x] = "x"; + keynames[SDLK_y] = "y"; + keynames[SDLK_z] = "z"; + keynames[SDLK_DELETE] = "delete"; + + keynames[SDLK_WORLD_0] = "world 0"; + keynames[SDLK_WORLD_1] = "world 1"; + keynames[SDLK_WORLD_2] = "world 2"; + keynames[SDLK_WORLD_3] = "world 3"; + keynames[SDLK_WORLD_4] = "world 4"; + keynames[SDLK_WORLD_5] = "world 5"; + keynames[SDLK_WORLD_6] = "world 6"; + keynames[SDLK_WORLD_7] = "world 7"; + keynames[SDLK_WORLD_8] = "world 8"; + keynames[SDLK_WORLD_9] = "world 9"; + keynames[SDLK_WORLD_10] = "world 10"; + keynames[SDLK_WORLD_11] = "world 11"; + keynames[SDLK_WORLD_12] = "world 12"; + keynames[SDLK_WORLD_13] = "world 13"; + keynames[SDLK_WORLD_14] = "world 14"; + keynames[SDLK_WORLD_15] = "world 15"; + keynames[SDLK_WORLD_16] = "world 16"; + keynames[SDLK_WORLD_17] = "world 17"; + keynames[SDLK_WORLD_18] = "world 18"; + keynames[SDLK_WORLD_19] = "world 19"; + keynames[SDLK_WORLD_20] = "world 20"; + keynames[SDLK_WORLD_21] = "world 21"; + keynames[SDLK_WORLD_22] = "world 22"; + keynames[SDLK_WORLD_23] = "world 23"; + keynames[SDLK_WORLD_24] = "world 24"; + keynames[SDLK_WORLD_25] = "world 25"; + keynames[SDLK_WORLD_26] = "world 26"; + keynames[SDLK_WORLD_27] = "world 27"; + keynames[SDLK_WORLD_28] = "world 28"; + keynames[SDLK_WORLD_29] = "world 29"; + keynames[SDLK_WORLD_30] = "world 30"; + keynames[SDLK_WORLD_31] = "world 31"; + keynames[SDLK_WORLD_32] = "world 32"; + keynames[SDLK_WORLD_33] = "world 33"; + keynames[SDLK_WORLD_34] = "world 34"; + keynames[SDLK_WORLD_35] = "world 35"; + keynames[SDLK_WORLD_36] = "world 36"; + keynames[SDLK_WORLD_37] = "world 37"; + keynames[SDLK_WORLD_38] = "world 38"; + keynames[SDLK_WORLD_39] = "world 39"; + keynames[SDLK_WORLD_40] = "world 40"; + keynames[SDLK_WORLD_41] = "world 41"; + keynames[SDLK_WORLD_42] = "world 42"; + keynames[SDLK_WORLD_43] = "world 43"; + keynames[SDLK_WORLD_44] = "world 44"; + keynames[SDLK_WORLD_45] = "world 45"; + keynames[SDLK_WORLD_46] = "world 46"; + keynames[SDLK_WORLD_47] = "world 47"; + keynames[SDLK_WORLD_48] = "world 48"; + keynames[SDLK_WORLD_49] = "world 49"; + keynames[SDLK_WORLD_50] = "world 50"; + keynames[SDLK_WORLD_51] = "world 51"; + keynames[SDLK_WORLD_52] = "world 52"; + keynames[SDLK_WORLD_53] = "world 53"; + keynames[SDLK_WORLD_54] = "world 54"; + keynames[SDLK_WORLD_55] = "world 55"; + keynames[SDLK_WORLD_56] = "world 56"; + keynames[SDLK_WORLD_57] = "world 57"; + keynames[SDLK_WORLD_58] = "world 58"; + keynames[SDLK_WORLD_59] = "world 59"; + keynames[SDLK_WORLD_60] = "world 60"; + keynames[SDLK_WORLD_61] = "world 61"; + keynames[SDLK_WORLD_62] = "world 62"; + keynames[SDLK_WORLD_63] = "world 63"; + keynames[SDLK_WORLD_64] = "world 64"; + keynames[SDLK_WORLD_65] = "world 65"; + keynames[SDLK_WORLD_66] = "world 66"; + keynames[SDLK_WORLD_67] = "world 67"; + keynames[SDLK_WORLD_68] = "world 68"; + keynames[SDLK_WORLD_69] = "world 69"; + keynames[SDLK_WORLD_70] = "world 70"; + keynames[SDLK_WORLD_71] = "world 71"; + keynames[SDLK_WORLD_72] = "world 72"; + keynames[SDLK_WORLD_73] = "world 73"; + keynames[SDLK_WORLD_74] = "world 74"; + keynames[SDLK_WORLD_75] = "world 75"; + keynames[SDLK_WORLD_76] = "world 76"; + keynames[SDLK_WORLD_77] = "world 77"; + keynames[SDLK_WORLD_78] = "world 78"; + keynames[SDLK_WORLD_79] = "world 79"; + keynames[SDLK_WORLD_80] = "world 80"; + keynames[SDLK_WORLD_81] = "world 81"; + keynames[SDLK_WORLD_82] = "world 82"; + keynames[SDLK_WORLD_83] = "world 83"; + keynames[SDLK_WORLD_84] = "world 84"; + keynames[SDLK_WORLD_85] = "world 85"; + keynames[SDLK_WORLD_86] = "world 86"; + keynames[SDLK_WORLD_87] = "world 87"; + keynames[SDLK_WORLD_88] = "world 88"; + keynames[SDLK_WORLD_89] = "world 89"; + keynames[SDLK_WORLD_90] = "world 90"; + keynames[SDLK_WORLD_91] = "world 91"; + keynames[SDLK_WORLD_92] = "world 92"; + keynames[SDLK_WORLD_93] = "world 93"; + keynames[SDLK_WORLD_94] = "world 94"; + keynames[SDLK_WORLD_95] = "world 95"; + + keynames[SDLK_KP0] = "[0]"; + keynames[SDLK_KP1] = "[1]"; + keynames[SDLK_KP2] = "[2]"; + keynames[SDLK_KP3] = "[3]"; + keynames[SDLK_KP4] = "[4]"; + keynames[SDLK_KP5] = "[5]"; + keynames[SDLK_KP6] = "[6]"; + keynames[SDLK_KP7] = "[7]"; + keynames[SDLK_KP8] = "[8]"; + keynames[SDLK_KP9] = "[9]"; + keynames[SDLK_KP_PERIOD] = "[.]"; + keynames[SDLK_KP_DIVIDE] = "[/]"; + keynames[SDLK_KP_MULTIPLY] = "[*]"; + keynames[SDLK_KP_MINUS] = "[-]"; + keynames[SDLK_KP_PLUS] = "[+]"; + keynames[SDLK_KP_ENTER] = "enter"; + keynames[SDLK_KP_EQUALS] = "equals"; + + keynames[SDLK_UP] = "up"; + keynames[SDLK_DOWN] = "down"; + keynames[SDLK_RIGHT] = "right"; + keynames[SDLK_LEFT] = "left"; + keynames[SDLK_DOWN] = "down"; + keynames[SDLK_INSERT] = "insert"; + keynames[SDLK_HOME] = "home"; + keynames[SDLK_END] = "end"; + keynames[SDLK_PAGEUP] = "page up"; + keynames[SDLK_PAGEDOWN] = "page down"; + + keynames[SDLK_F1] = "f1"; + keynames[SDLK_F2] = "f2"; + keynames[SDLK_F3] = "f3"; + keynames[SDLK_F4] = "f4"; + keynames[SDLK_F5] = "f5"; + keynames[SDLK_F6] = "f6"; + keynames[SDLK_F7] = "f7"; + keynames[SDLK_F8] = "f8"; + keynames[SDLK_F9] = "f9"; + keynames[SDLK_F10] = "f10"; + keynames[SDLK_F11] = "f11"; + keynames[SDLK_F12] = "f12"; + keynames[SDLK_F13] = "f13"; + keynames[SDLK_F14] = "f14"; + keynames[SDLK_F15] = "f15"; + + keynames[SDLK_NUMLOCK] = "numlock"; + keynames[SDLK_CAPSLOCK] = "caps lock"; + keynames[SDLK_SCROLLOCK] = "scroll lock"; + keynames[SDLK_RSHIFT] = "right shift"; + keynames[SDLK_LSHIFT] = "left shift"; + keynames[SDLK_RCTRL] = "right ctrl"; + keynames[SDLK_LCTRL] = "left ctrl"; + keynames[SDLK_RALT] = "right alt"; + keynames[SDLK_LALT] = "left alt"; + keynames[SDLK_RMETA] = "right meta"; + keynames[SDLK_LMETA] = "left meta"; + keynames[SDLK_LSUPER] = "left super"; /* "Windows" keys */ + keynames[SDLK_RSUPER] = "right super"; + keynames[SDLK_MODE] = "alt gr"; + keynames[SDLK_COMPOSE] = "compose"; + + keynames[SDLK_HELP] = "help"; + keynames[SDLK_PRINT] = "print screen"; + keynames[SDLK_SYSREQ] = "sys req"; + keynames[SDLK_BREAK] = "break"; + keynames[SDLK_MENU] = "menu"; + keynames[SDLK_POWER] = "power"; + keynames[SDLK_EURO] = "euro"; + keynames[SDLK_UNDO] = "undo"; + + /* Done. Whew. */ + return(0); +} +void SDL_KeyboardQuit(void) +{ +} + +/* We lost the keyboard, so post key up messages for all pressed keys */ +void SDL_ResetKeyboard(void) +{ + SDL_keysym keysym; + SDLKey key; + + SDL_memset(&keysym, 0, (sizeof keysym)); + for ( key=SDLK_FIRST; key<SDLK_LAST; ++key ) { + if ( SDL_KeyState[key] == SDL_PRESSED ) { + keysym.sym = key; + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + } + SDL_KeyRepeat.timestamp = 0; +} + +int SDL_EnableUNICODE(int enable) +{ + int old_mode; + + old_mode = SDL_TranslateUNICODE; + if ( enable >= 0 ) { + SDL_TranslateUNICODE = enable; + } + return(old_mode); +} + +Uint8 * SDL_GetKeyState (int *numkeys) +{ + if ( numkeys != (int *)0 ) + *numkeys = SDLK_LAST; + return(SDL_KeyState); +} +SDLMod SDL_GetModState (void) +{ + return(SDL_ModState); +} +void SDL_SetModState (SDLMod modstate) +{ + SDL_ModState = modstate; +} + +char *SDL_GetKeyName(SDLKey key) +{ + const char *keyname; + + keyname = NULL; + if ( key < SDLK_LAST ) { + keyname = keynames[key]; + } + if ( keyname == NULL ) { + keyname = "unknown key"; + } + /* FIXME: make this function const in 1.3 */ + return (char *)(keyname); +} + +/* These are global for SDL_eventloop.c */ +int SDL_PrivateKeyboard(Uint8 state, SDL_keysym *keysym) +{ + SDL_Event event; + int posted, repeatable; + Uint16 modstate; + + SDL_memset(&event, 0, sizeof(event)); + +#if 0 +printf("The '%s' key has been %s\n", SDL_GetKeyName(keysym->sym), + state == SDL_PRESSED ? "pressed" : "released"); +#endif + /* Set up the keysym */ + modstate = (Uint16)SDL_ModState; + + repeatable = 0; + + if ( state == SDL_PRESSED ) { + keysym->mod = (SDLMod)modstate; + switch (keysym->sym) { + case SDLK_UNKNOWN: + break; + case SDLK_NUMLOCK: + modstate ^= KMOD_NUM; + if ( SDL_NoLockKeys & SDL_NLK_NUM ) + break; + if ( ! (modstate&KMOD_NUM) ) + state = SDL_RELEASED; + keysym->mod = (SDLMod)modstate; + break; + case SDLK_CAPSLOCK: + modstate ^= KMOD_CAPS; + if ( SDL_NoLockKeys & SDL_NLK_CAPS ) + break; + if ( ! (modstate&KMOD_CAPS) ) + state = SDL_RELEASED; + keysym->mod = (SDLMod)modstate; + break; + case SDLK_LCTRL: + modstate |= KMOD_LCTRL; + break; + case SDLK_RCTRL: + modstate |= KMOD_RCTRL; + break; + case SDLK_LSHIFT: + modstate |= KMOD_LSHIFT; + break; + case SDLK_RSHIFT: + modstate |= KMOD_RSHIFT; + break; + case SDLK_LALT: + modstate |= KMOD_LALT; + break; + case SDLK_RALT: + modstate |= KMOD_RALT; + break; + case SDLK_LMETA: + modstate |= KMOD_LMETA; + break; + case SDLK_RMETA: + modstate |= KMOD_RMETA; + break; + case SDLK_MODE: + modstate |= KMOD_MODE; + break; + default: + repeatable = 1; + break; + } + } else { + switch (keysym->sym) { + case SDLK_UNKNOWN: + break; + case SDLK_NUMLOCK: + if ( SDL_NoLockKeys & SDL_NLK_NUM ) + break; + /* Only send keydown events */ + return(0); + case SDLK_CAPSLOCK: + if ( SDL_NoLockKeys & SDL_NLK_CAPS ) + break; + /* Only send keydown events */ + return(0); + case SDLK_LCTRL: + modstate &= ~KMOD_LCTRL; + break; + case SDLK_RCTRL: + modstate &= ~KMOD_RCTRL; + break; + case SDLK_LSHIFT: + modstate &= ~KMOD_LSHIFT; + break; + case SDLK_RSHIFT: + modstate &= ~KMOD_RSHIFT; + break; + case SDLK_LALT: + modstate &= ~KMOD_LALT; + break; + case SDLK_RALT: + modstate &= ~KMOD_RALT; + break; + case SDLK_LMETA: + modstate &= ~KMOD_LMETA; + break; + case SDLK_RMETA: + modstate &= ~KMOD_RMETA; + break; + case SDLK_MODE: + modstate &= ~KMOD_MODE; + break; + default: + break; + } + keysym->mod = (SDLMod)modstate; + } + + /* Figure out what type of event this is */ + switch (state) { + case SDL_PRESSED: + event.type = SDL_KEYDOWN; + break; + case SDL_RELEASED: + event.type = SDL_KEYUP; + /* + * jk 991215 - Added + */ + if ( SDL_KeyRepeat.timestamp && + SDL_KeyRepeat.evt.key.keysym.sym == keysym->sym ) { + SDL_KeyRepeat.timestamp = 0; + } + break; + default: + /* Invalid state -- bail */ + return(0); + } + + if ( keysym->sym != SDLK_UNKNOWN ) { + /* Drop events that don't change state */ + if ( SDL_KeyState[keysym->sym] == state ) { +#if 0 +printf("Keyboard event didn't change state - dropped!\n"); +#endif + return(0); + } + + /* Update internal keyboard state */ + SDL_ModState = (SDLMod)modstate; + SDL_KeyState[keysym->sym] = state; + } + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { + event.key.state = state; + event.key.keysym = *keysym; + /* + * jk 991215 - Added + */ + if (repeatable && (SDL_KeyRepeat.delay != 0)) { + SDL_KeyRepeat.evt = event; + SDL_KeyRepeat.firsttime = 1; + SDL_KeyRepeat.timestamp=SDL_GetTicks(); + } + if ( (SDL_EventOK == NULL) || SDL_EventOK(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} + +/* + * jk 991215 - Added + */ +void SDL_CheckKeyRepeat(void) +{ + if ( SDL_KeyRepeat.timestamp ) { + Uint32 now, interval; + + now = SDL_GetTicks(); + interval = (now - SDL_KeyRepeat.timestamp); + if ( SDL_KeyRepeat.firsttime ) { + if ( interval > (Uint32)SDL_KeyRepeat.delay ) { + SDL_KeyRepeat.timestamp = now; + SDL_KeyRepeat.firsttime = 0; + } + } else { + if ( interval > (Uint32)SDL_KeyRepeat.interval ) { + SDL_KeyRepeat.timestamp = now; + if ( (SDL_EventOK == NULL) || SDL_EventOK(&SDL_KeyRepeat.evt) ) { + SDL_PushEvent(&SDL_KeyRepeat.evt); + } + } + } + } +} + +int SDL_EnableKeyRepeat(int delay, int interval) +{ + if ( (delay < 0) || (interval < 0) ) { + SDL_SetError("keyboard repeat value less than zero"); + return(-1); + } + SDL_KeyRepeat.firsttime = 0; + SDL_KeyRepeat.delay = delay; + SDL_KeyRepeat.interval = interval; + SDL_KeyRepeat.timestamp = 0; + return(0); +} + +void SDL_GetKeyRepeat(int *delay, int *interval) +{ + *delay = SDL_KeyRepeat.delay; + *interval = SDL_KeyRepeat.interval; +} + diff --git a/3rdparty/SDL/src/events/SDL_mouse.c b/3rdparty/SDL/src/events/SDL_mouse.c new file mode 100644 index 0000000..e37a4c6 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_mouse.c @@ -0,0 +1,268 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General mouse handling code for SDL */ + +#include "SDL_events.h" +#include "SDL_events_c.h" +#include "../video/SDL_cursor_c.h" +#include "../video/SDL_sysvideo.h" + + +/* These are static for our mouse handling code */ +static Sint16 SDL_MouseX = 0; +static Sint16 SDL_MouseY = 0; +static Sint16 SDL_DeltaX = 0; +static Sint16 SDL_DeltaY = 0; +static Sint16 SDL_MouseMaxX = 0; +static Sint16 SDL_MouseMaxY = 0; +static Uint8 SDL_ButtonState = 0; + + +/* Public functions */ +int SDL_MouseInit(void) +{ + /* The mouse is at (0,0) */ + SDL_MouseX = 0; + SDL_MouseY = 0; + SDL_DeltaX = 0; + SDL_DeltaY = 0; + SDL_MouseMaxX = 0; + SDL_MouseMaxY = 0; + SDL_ButtonState = 0; + + /* That's it! */ + return(0); +} +void SDL_MouseQuit(void) +{ +} + +/* We lost the mouse, so post button up messages for all pressed buttons */ +void SDL_ResetMouse(void) +{ + Uint8 i; + for ( i = 0; i < sizeof(SDL_ButtonState)*8; ++i ) { + if ( SDL_ButtonState & SDL_BUTTON(i) ) { + SDL_PrivateMouseButton(SDL_RELEASED, i, 0, 0); + } + } +} + +Uint8 SDL_GetMouseState (int *x, int *y) +{ + if ( x ) { + *x = SDL_MouseX; + } + if ( y ) { + *y = SDL_MouseY; + } + return(SDL_ButtonState); +} + +Uint8 SDL_GetRelativeMouseState (int *x, int *y) +{ + if ( x ) + *x = SDL_DeltaX; + if ( y ) + *y = SDL_DeltaY; + SDL_DeltaX = 0; + SDL_DeltaY = 0; + return(SDL_ButtonState); +} + +static void ClipOffset(Sint16 *x, Sint16 *y) +{ + /* This clips absolute mouse coordinates when the apparent + display surface is smaller than the real display surface. + */ + if ( SDL_VideoSurface && SDL_VideoSurface->offset ) { + *y -= SDL_VideoSurface->offset/SDL_VideoSurface->pitch; + *x -= (SDL_VideoSurface->offset%SDL_VideoSurface->pitch)/ + SDL_VideoSurface->format->BytesPerPixel; + } +} + +void SDL_SetMouseRange(int maxX, int maxY) +{ + SDL_MouseMaxX = (Sint16)maxX; + SDL_MouseMaxY = (Sint16)maxY; +} + +/* These are global for SDL_eventloop.c */ +int SDL_PrivateMouseMotion(Uint8 buttonstate, int relative, Sint16 x, Sint16 y) +{ + int posted; + Uint16 X, Y; + Sint16 Xrel; + Sint16 Yrel; + + /* Default buttonstate is the current one */ + if ( ! buttonstate ) { + buttonstate = SDL_ButtonState; + } + + Xrel = x; + Yrel = y; + if ( relative ) { + /* Push the cursor around */ + x = (SDL_MouseX+x); + y = (SDL_MouseY+y); + } else { + /* Do we need to clip {x,y} ? */ + ClipOffset(&x, &y); + } + + /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ + if ( x < 0 ) + X = 0; + else + if ( x >= SDL_MouseMaxX ) + X = SDL_MouseMaxX-1; + else + X = (Uint16)x; + + if ( y < 0 ) + Y = 0; + else + if ( y >= SDL_MouseMaxY ) + Y = SDL_MouseMaxY-1; + else + Y = (Uint16)y; + + /* If not relative mode, generate relative motion from clamped X/Y. + This prevents lots of extraneous large delta relative motion when + the screen is windowed mode and the mouse is outside the window. + */ + if ( ! relative ) { + Xrel = X-SDL_MouseX; + Yrel = Y-SDL_MouseY; + } + + /* Drop events that don't change state */ + if ( ! Xrel && ! Yrel ) { +#if 0 +printf("Mouse event didn't change state - dropped!\n"); +#endif + return(0); + } + + /* Update internal mouse state */ + SDL_ButtonState = buttonstate; + SDL_MouseX = X; + SDL_MouseY = Y; + SDL_DeltaX += Xrel; + SDL_DeltaY += Yrel; + SDL_MoveCursor(SDL_MouseX, SDL_MouseY); + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[SDL_MOUSEMOTION] == SDL_ENABLE ) { + SDL_Event event; + SDL_memset(&event, 0, sizeof(event)); + event.type = SDL_MOUSEMOTION; + event.motion.state = buttonstate; + event.motion.x = X; + event.motion.y = Y; + event.motion.xrel = Xrel; + event.motion.yrel = Yrel; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} + +int SDL_PrivateMouseButton(Uint8 state, Uint8 button, Sint16 x, Sint16 y) +{ + SDL_Event event; + int posted; + int move_mouse; + Uint8 buttonstate; + + SDL_memset(&event, 0, sizeof(event)); + + /* Check parameters */ + if ( x || y ) { + ClipOffset(&x, &y); + move_mouse = 1; + /* Mouse coordinates range from 0 - width-1 and 0 - height-1 */ + if ( x < 0 ) + x = 0; + else + if ( x >= SDL_MouseMaxX ) + x = SDL_MouseMaxX-1; + + if ( y < 0 ) + y = 0; + else + if ( y >= SDL_MouseMaxY ) + y = SDL_MouseMaxY-1; + } else { + move_mouse = 0; + } + if ( ! x ) + x = SDL_MouseX; + if ( ! y ) + y = SDL_MouseY; + + /* Figure out which event to perform */ + buttonstate = SDL_ButtonState; + switch ( state ) { + case SDL_PRESSED: + event.type = SDL_MOUSEBUTTONDOWN; + buttonstate |= SDL_BUTTON(button); + break; + case SDL_RELEASED: + event.type = SDL_MOUSEBUTTONUP; + buttonstate &= ~SDL_BUTTON(button); + break; + default: + /* Invalid state -- bail */ + return(0); + } + + /* Update internal mouse state */ + SDL_ButtonState = buttonstate; + if ( move_mouse ) { + SDL_MouseX = x; + SDL_MouseY = y; + SDL_MoveCursor(SDL_MouseX, SDL_MouseY); + } + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { + event.button.state = state; + event.button.button = button; + event.button.x = x; + event.button.y = y; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} + diff --git a/3rdparty/SDL/src/events/SDL_quit.c b/3rdparty/SDL/src/events/SDL_quit.c new file mode 100644 index 0000000..2e6c56e --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_quit.c @@ -0,0 +1,124 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General quit handling code for SDL */ + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#include "SDL_events.h" +#include "SDL_events_c.h" + + +#ifdef HAVE_SIGNAL_H +static void SDL_HandleSIG(int sig) +{ + /* Reset the signal handler */ + signal(sig, SDL_HandleSIG); + + /* Signal a quit interrupt */ + SDL_PrivateQuit(); +} +#endif /* HAVE_SIGNAL_H */ + +/* Public functions */ +int SDL_QuitInit(void) +{ +#ifdef HAVE_SIGACTION + struct sigaction action; + sigaction(SIGINT, NULL, &action); +# ifdef HAVE_SA_SIGACTION + if ( action.sa_handler == SIG_DFL && action.sa_sigaction == (void*)SIG_DFL ) { +# else + if ( action.sa_handler == SIG_DFL ) { +# endif + action.sa_handler = SDL_HandleSIG; + sigaction(SIGINT, &action, NULL); + } + sigaction(SIGTERM, NULL, &action); +# ifdef HAVE_SA_SIGACTION + if ( action.sa_handler == SIG_DFL && action.sa_sigaction == (void*)SIG_DFL ) { +# else + if ( action.sa_handler == SIG_DFL ) { +# endif + action.sa_handler = SDL_HandleSIG; + sigaction(SIGTERM, &action, NULL); + } +#elif HAVE_SIGNAL_H + void (*ohandler)(int); + + /* Both SIGINT and SIGTERM are translated into quit interrupts */ + ohandler = signal(SIGINT, SDL_HandleSIG); + if ( ohandler != SIG_DFL ) + signal(SIGINT, ohandler); + ohandler = signal(SIGTERM, SDL_HandleSIG); + if ( ohandler != SIG_DFL ) + signal(SIGTERM, ohandler); +#endif /* HAVE_SIGNAL_H */ + + /* That's it! */ + return(0); +} +void SDL_QuitQuit(void) +{ +#ifdef HAVE_SIGACTION + struct sigaction action; + sigaction(SIGINT, NULL, &action); + if ( action.sa_handler == SDL_HandleSIG ) { + action.sa_handler = SIG_DFL; + sigaction(SIGINT, &action, NULL); + } + sigaction(SIGTERM, NULL, &action); + if ( action.sa_handler == SDL_HandleSIG ) { + action.sa_handler = SIG_DFL; + sigaction(SIGTERM, &action, NULL); + } +#elif HAVE_SIGNAL_H + void (*ohandler)(int); + + ohandler = signal(SIGINT, SIG_DFL); + if ( ohandler != SDL_HandleSIG ) + signal(SIGINT, ohandler); + ohandler = signal(SIGTERM, SIG_DFL); + if ( ohandler != SDL_HandleSIG ) + signal(SIGTERM, ohandler); +#endif /* HAVE_SIGNAL_H */ +} + +/* This function returns 1 if it's okay to close the application window */ +int SDL_PrivateQuit(void) +{ + int posted; + + posted = 0; + if ( SDL_ProcessEvents[SDL_QUIT] == SDL_ENABLE ) { + SDL_Event event; + event.type = SDL_QUIT; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} diff --git a/3rdparty/SDL/src/events/SDL_resize.c b/3rdparty/SDL/src/events/SDL_resize.c new file mode 100644 index 0000000..e754a07 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_resize.c @@ -0,0 +1,71 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Resize event handling code for SDL */ + +#include "SDL_events.h" +#include "SDL_events_c.h" +#include "../video/SDL_sysvideo.h" + + +/* Keep the last resize event so we don't post duplicates */ +static struct { + int w; + int h; +} last_resize; + +/* This is global for SDL_eventloop.c */ +int SDL_PrivateResize(int w, int h) +{ + int posted; + SDL_Event events[32]; + + /* See if this event would change the video surface */ + if ( !w || !h || + (( last_resize.w == w ) && ( last_resize.h == h )) || + !SDL_VideoSurface ) { + return(0); + } + last_resize.w = w; + last_resize.h = h; + + SDL_SetMouseRange(w, h); + + /* Pull out all old resize events */ + SDL_PeepEvents(events, sizeof(events)/sizeof(events[0]), + SDL_GETEVENT, SDL_VIDEORESIZEMASK); + + /* Post the event, if desired */ + posted = 0; + if ( SDL_ProcessEvents[SDL_VIDEORESIZE] == SDL_ENABLE ) { + SDL_Event event; + event.type = SDL_VIDEORESIZE; + event.resize.w = w; + event.resize.h = h; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } + return(posted); +} diff --git a/3rdparty/SDL/src/events/SDL_sysevents.h b/3rdparty/SDL/src/events/SDL_sysevents.h new file mode 100644 index 0000000..480bfe1 --- /dev/null +++ b/3rdparty/SDL/src/events/SDL_sysevents.h @@ -0,0 +1,46 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is SDL_free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../video/SDL_sysvideo.h" + +/* Useful functions and variables from SDL_sysevents.c */ + +#ifdef __BEOS__ /* The Be event loop runs in a separate thread */ +#define MUST_THREAD_EVENTS +#endif + +#ifdef __WIN32__ /* Win32 doesn't allow a separate event thread */ +#define CANT_THREAD_EVENTS +#endif + +#ifdef IPOD /* iPod doesn't support threading at all */ +#define CANT_THREAD_EVENTS +#endif + +#ifdef __MACOS__ /* MacOS 7/8 don't support preemptive multi-tasking */ +#define CANT_THREAD_EVENTS +#endif + +#ifdef __OS2__ /* The OS/2 event loop runs in a separate thread */ +#define MUST_THREAD_EVENTS +#endif diff --git a/3rdparty/SDL/src/file/SDL_rwops.c b/3rdparty/SDL/src/file/SDL_rwops.c new file mode 100644 index 0000000..1593e97 --- /dev/null +++ b/3rdparty/SDL/src/file/SDL_rwops.c @@ -0,0 +1,673 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file provides a general interface for SDL to read and write + data sources. It can easily be extended to files, memory, etc. +*/ + +#include "SDL_endian.h" +#include "SDL_rwops.h" + + +#if defined(__WIN32__) && !defined(__SYMBIAN32__) + +/* Functions to read/write Win32 API file pointers */ +/* Will not use it on WinCE because stdio is buffered, it means + faster, and all stdio functions anyway are embedded in coredll.dll - + the main wince dll*/ + +#define WINDOWS_LEAN_AND_MEAN +#include <windows.h> + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER 0xFFFFFFFF +#endif + +#define READAHEAD_BUFFER_SIZE 1024 + +static int SDLCALL win32_file_open(SDL_RWops *context, const char *filename, const char *mode) +{ +#ifndef _WIN32_WCE + UINT old_error_mode; +#endif + HANDLE h; + DWORD r_right, w_right; + DWORD must_exist, truncate; + int a_mode; + + if (!context) + return -1; /* failed (invalid call) */ + + context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* mark this as unusable */ + context->hidden.win32io.buffer.data = NULL; + context->hidden.win32io.buffer.size = 0; + context->hidden.win32io.buffer.left = 0; + + /* "r" = reading, file must exist */ + /* "w" = writing, truncate existing, file may not exist */ + /* "r+"= reading or writing, file must exist */ + /* "a" = writing, append file may not exist */ + /* "a+"= append + read, file may not exist */ + /* "w+" = read, write, truncate. file may not exist */ + + must_exist = ( SDL_strchr(mode,'r') != NULL ) ? OPEN_EXISTING : 0; + truncate = ( SDL_strchr(mode,'w') != NULL ) ? CREATE_ALWAYS : 0; + r_right = ( SDL_strchr(mode,'+') != NULL || must_exist ) ? GENERIC_READ : 0; + a_mode = ( SDL_strchr(mode,'a') != NULL ) ? OPEN_ALWAYS : 0; + w_right = ( a_mode || SDL_strchr(mode,'+') || truncate ) ? GENERIC_WRITE : 0; + + if (!r_right && !w_right) /* inconsistent mode */ + return -1; /* failed (invalid call) */ + + context->hidden.win32io.buffer.data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); + if (!context->hidden.win32io.buffer.data) { + SDL_OutOfMemory(); + return -1; + } + +#ifdef _WIN32_WCE + { + size_t size = SDL_strlen(filename)+1; + wchar_t *filenameW = SDL_stack_alloc(wchar_t, size); + + if ( MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, size) == 0 ) { + SDL_stack_free(filenameW); + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Unable to convert filename to Unicode"); + return -1; + } + h = CreateFile(filenameW, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, + NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + SDL_stack_free(filenameW); + } +#else + { + + /* handle Unicode filenames. We do some tapdancing here to make sure this + works on Win9x, which doesn't support anything but 1-byte codepages. */ + const size_t size = SDL_strlen(filename)+1; + static int unicode_support = -1; + + if (unicode_support == -1) { + OSVERSIONINFO osVerInfo; /* Information about the OS */ + osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); + if (!GetVersionEx(&osVerInfo)) { + unicode_support = 0; + } else if (osVerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { + unicode_support = 1; /* Not Win95/98/ME. */ + } else { + unicode_support = 0; + } + } + + if (unicode_support) { /* everything but Win95/98/ME. */ + wchar_t *filenameW = SDL_stack_alloc(wchar_t, size); + if ( MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, size) == 0 ) { + SDL_stack_free(filenameW); + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Unable to convert filename to Unicode"); + return -1; + } + + /* Do not open a dialog box if failure */ + old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + h = CreateFileW(filenameW, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, + NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + /* restore old behaviour */ + SetErrorMode(old_error_mode); + + SDL_stack_free(filenameW); + } else { + /* CP_UTF8 might not be supported (Win95), so use SDL_iconv to get wchars. */ + /* Use UCS2: no UTF-16 support here. Try again in SDL 1.3. :) */ + char *utf16 = SDL_iconv_string("UCS2", "UTF8", filename, SDL_strlen(filename) + 1); + char *filenameA = SDL_stack_alloc(char, size * 6); /* 6, just in case. */ + BOOL bDefCharUsed = FALSE; + + /* Dither down to a codepage and hope for the best. */ + if (!utf16 || + !WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)utf16, -1, filenameA, size*6, 0, &bDefCharUsed) || + bDefCharUsed) { + SDL_stack_free(filenameA); + SDL_free(utf16); + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Unable to convert filename to Unicode"); + return -1; + } + + /* Do not open a dialog box if failure */ + old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + h = CreateFile(filenameA, (w_right|r_right), (w_right)? 0 : FILE_SHARE_READ, + NULL, (must_exist|truncate|a_mode), FILE_ATTRIBUTE_NORMAL,NULL); + /* restore old behaviour */ + SetErrorMode(old_error_mode); + + SDL_stack_free(filenameA); + SDL_free(utf16); + } + + } +#endif /* _WIN32_WCE */ + + if (h==INVALID_HANDLE_VALUE) { + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + SDL_SetError("Couldn't open %s",filename); + return -2; /* failed (CreateFile) */ + } + context->hidden.win32io.h = h; + context->hidden.win32io.append = a_mode; + + return 0; /* ok */ +} +static int SDLCALL win32_file_seek(SDL_RWops *context, int offset, int whence) +{ + DWORD win32whence; + int file_pos; + + if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE) { + SDL_SetError("win32_file_seek: invalid context/file not opened"); + return -1; + } + + /* FIXME: We may be able to satisfy the seek within buffered data */ + if (whence == RW_SEEK_CUR && context->hidden.win32io.buffer.left) { + offset -= context->hidden.win32io.buffer.left; + } + context->hidden.win32io.buffer.left = 0; + + switch (whence) { + case RW_SEEK_SET: + win32whence = FILE_BEGIN; break; + case RW_SEEK_CUR: + win32whence = FILE_CURRENT; break; + case RW_SEEK_END: + win32whence = FILE_END; break; + default: + SDL_SetError("win32_file_seek: Unknown value for 'whence'"); + return -1; + } + + file_pos = SetFilePointer(context->hidden.win32io.h,offset,NULL,win32whence); + + if ( file_pos != INVALID_SET_FILE_POINTER ) + return file_pos; /* success */ + + SDL_Error(SDL_EFSEEK); + return -1; /* error */ +} +static int SDLCALL win32_file_read(SDL_RWops *context, void *ptr, int size, int maxnum) +{ + int total_need; + int total_read = 0; + int read_ahead; + DWORD byte_read; + + total_need = size*maxnum; + + if (!context || context->hidden.win32io.h == INVALID_HANDLE_VALUE || total_need<=0 || !size) + return 0; + + if (context->hidden.win32io.buffer.left > 0) { + void *data = (char *)context->hidden.win32io.buffer.data + + context->hidden.win32io.buffer.size - + context->hidden.win32io.buffer.left; + read_ahead = SDL_min(total_need, context->hidden.win32io.buffer.left); + SDL_memcpy(ptr, data, read_ahead); + context->hidden.win32io.buffer.left -= read_ahead; + + if (read_ahead == total_need) { + return maxnum; + } + ptr = (char *)ptr + read_ahead; + total_need -= read_ahead; + total_read += read_ahead; + } + + if (total_need < READAHEAD_BUFFER_SIZE) { + if (!ReadFile(context->hidden.win32io.h,context->hidden.win32io.buffer.data,READAHEAD_BUFFER_SIZE,&byte_read,NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + read_ahead = SDL_min(total_need, (int)byte_read); + SDL_memcpy(ptr, context->hidden.win32io.buffer.data, read_ahead); + context->hidden.win32io.buffer.size = byte_read; + context->hidden.win32io.buffer.left = byte_read-read_ahead; + total_read += read_ahead; + } else { + if (!ReadFile(context->hidden.win32io.h,ptr,total_need,&byte_read,NULL)) { + SDL_Error(SDL_EFREAD); + return 0; + } + total_read += byte_read; + } + return (total_read/size); +} +static int SDLCALL win32_file_write(SDL_RWops *context, const void *ptr, int size, int num) +{ + + int total_bytes; + DWORD byte_written,nwritten; + + total_bytes = size*num; + + if (!context || context->hidden.win32io.h==INVALID_HANDLE_VALUE || total_bytes<=0 || !size) + return 0; + + if (context->hidden.win32io.buffer.left) { + SetFilePointer(context->hidden.win32io.h,-context->hidden.win32io.buffer.left,NULL,FILE_CURRENT); + context->hidden.win32io.buffer.left = 0; + } + + /* if in append mode, we must go to the EOF before write */ + if (context->hidden.win32io.append) { + if ( SetFilePointer(context->hidden.win32io.h,0L,NULL,FILE_END) == INVALID_SET_FILE_POINTER ) { + SDL_Error(SDL_EFWRITE); + return 0; + } + } + + if (!WriteFile(context->hidden.win32io.h,ptr,total_bytes,&byte_written,NULL)) { + SDL_Error(SDL_EFWRITE); + return 0; + } + + nwritten = byte_written/size; + return nwritten; +} +static int SDLCALL win32_file_close(SDL_RWops *context) +{ + + if ( context ) { + if (context->hidden.win32io.h != INVALID_HANDLE_VALUE) { + CloseHandle(context->hidden.win32io.h); + context->hidden.win32io.h = INVALID_HANDLE_VALUE; /* to be sure */ + } + if (context->hidden.win32io.buffer.data) { + SDL_free(context->hidden.win32io.buffer.data); + context->hidden.win32io.buffer.data = NULL; + } + SDL_FreeRW(context); + } + return(0); +} +#endif /* __WIN32__ */ + +#ifdef HAVE_STDIO_H + +/* Functions to read/write stdio file pointers */ + +static int SDLCALL stdio_seek(SDL_RWops *context, int offset, int whence) +{ + if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 ) { + return(ftell(context->hidden.stdio.fp)); + } else { + SDL_Error(SDL_EFSEEK); + return(-1); + } +} +static int SDLCALL stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum) +{ + size_t nread; + + nread = fread(ptr, size, maxnum, context->hidden.stdio.fp); + if ( nread == 0 && ferror(context->hidden.stdio.fp) ) { + SDL_Error(SDL_EFREAD); + } + return(nread); +} +static int SDLCALL stdio_write(SDL_RWops *context, const void *ptr, int size, int num) +{ + size_t nwrote; + + nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp); + if ( nwrote == 0 && ferror(context->hidden.stdio.fp) ) { + SDL_Error(SDL_EFWRITE); + } + return(nwrote); +} +static int SDLCALL stdio_close(SDL_RWops *context) +{ + if ( context ) { + if ( context->hidden.stdio.autoclose ) { + /* WARNING: Check the return value here! */ + fclose(context->hidden.stdio.fp); + } + SDL_FreeRW(context); + } + return(0); +} +#endif /* !HAVE_STDIO_H */ + +/* Functions to read/write memory pointers */ + +static int SDLCALL mem_seek(SDL_RWops *context, int offset, int whence) +{ + Uint8 *newpos; + + switch (whence) { + case RW_SEEK_SET: + newpos = context->hidden.mem.base+offset; + break; + case RW_SEEK_CUR: + newpos = context->hidden.mem.here+offset; + break; + case RW_SEEK_END: + newpos = context->hidden.mem.stop+offset; + break; + default: + SDL_SetError("Unknown value for 'whence'"); + return(-1); + } + if ( newpos < context->hidden.mem.base ) { + newpos = context->hidden.mem.base; + } + if ( newpos > context->hidden.mem.stop ) { + newpos = context->hidden.mem.stop; + } + context->hidden.mem.here = newpos; + return(context->hidden.mem.here-context->hidden.mem.base); +} +static int SDLCALL mem_read(SDL_RWops *context, void *ptr, int size, int maxnum) +{ + size_t total_bytes; + size_t mem_available; + + total_bytes = (maxnum * size); + if ( (maxnum <= 0) || (size <= 0) || ((total_bytes / maxnum) != (size_t) size) ) { + return 0; + } + + mem_available = (context->hidden.mem.stop - context->hidden.mem.here); + if (total_bytes > mem_available) { + total_bytes = mem_available; + } + + SDL_memcpy(ptr, context->hidden.mem.here, total_bytes); + context->hidden.mem.here += total_bytes; + + return (total_bytes / size); +} +static int SDLCALL mem_write(SDL_RWops *context, const void *ptr, int size, int num) +{ + if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) { + num = (context->hidden.mem.stop-context->hidden.mem.here)/size; + } + SDL_memcpy(context->hidden.mem.here, ptr, num*size); + context->hidden.mem.here += num*size; + return(num); +} +static int SDLCALL mem_writeconst(SDL_RWops *context, const void *ptr, int size, int num) +{ + SDL_SetError("Can't write to read-only memory"); + return(-1); +} +static int SDLCALL mem_close(SDL_RWops *context) +{ + if ( context ) { + SDL_FreeRW(context); + } + return(0); +} + + +/* Functions to create SDL_RWops structures from various data sources */ + +#ifdef __MACOS__ +/* + * translate unix-style slash-separated filename to mac-style colon-separated + * name; return malloced string + */ +static char *unix_to_mac(const char *file) +{ + int flen = SDL_strlen(file); + char *path = SDL_malloc(flen + 2); + const char *src = file; + char *dst = path; + if(*src == '/') { + /* really depends on filesystem layout, hope for the best */ + src++; + } else { + /* Check if this is a MacOS path to begin with */ + if(*src != ':') + *dst++ = ':'; /* relative paths begin with ':' */ + } + while(src < file + flen) { + const char *end = SDL_strchr(src, '/'); + int len; + if(!end) + end = file + flen; /* last component */ + len = end - src; + if(len == 0 || (len == 1 && src[0] == '.')) { + /* remove repeated slashes and . */ + } else { + if(len == 2 && src[0] == '.' && src[1] == '.') { + /* replace .. with the empty string */ + } else { + SDL_memcpy(dst, src, len); + dst += len; + } + if(end < file + flen) + *dst++ = ':'; + } + src = end + 1; + } + *dst++ = '\0'; + return path; +} +#endif /* __MACOS__ */ + +SDL_RWops *SDL_RWFromFile(const char *file, const char *mode) +{ + SDL_RWops *rwops = NULL; +#ifdef HAVE_STDIO_H + FILE *fp = NULL; + (void) fp; +#endif + if ( !file || !*file || !mode || !*mode ) { + SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); + return NULL; + } + +#if defined(__WIN32__) && !defined(__SYMBIAN32__) + rwops = SDL_AllocRW(); + if (!rwops) + return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ + if (win32_file_open(rwops,file,mode) < 0) { + SDL_FreeRW(rwops); + return NULL; + } + rwops->seek = win32_file_seek; + rwops->read = win32_file_read; + rwops->write = win32_file_write; + rwops->close = win32_file_close; + +#elif HAVE_STDIO_H + +#ifdef __MACOS__ + { + char *mpath = unix_to_mac(file); + fp = fopen(mpath, mode); + SDL_free(mpath); + } +#else + fp = fopen(file, mode); +#endif + if ( fp == NULL ) { + SDL_SetError("Couldn't open %s", file); + } else { + rwops = SDL_RWFromFP(fp, 1); + } +#else + SDL_SetError("SDL not compiled with stdio support"); +#endif /* !HAVE_STDIO_H */ + + return(rwops); +} + +#ifdef HAVE_STDIO_H +SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose) +{ + SDL_RWops *rwops = NULL; + + rwops = SDL_AllocRW(); + if ( rwops != NULL ) { + rwops->seek = stdio_seek; + rwops->read = stdio_read; + rwops->write = stdio_write; + rwops->close = stdio_close; + rwops->hidden.stdio.fp = fp; + rwops->hidden.stdio.autoclose = autoclose; + } + return(rwops); +} +#endif /* HAVE_STDIO_H */ + +SDL_RWops *SDL_RWFromMem(void *mem, int size) +{ + SDL_RWops *rwops; + + rwops = SDL_AllocRW(); + if ( rwops != NULL ) { + rwops->seek = mem_seek; + rwops->read = mem_read; + rwops->write = mem_write; + rwops->close = mem_close; + rwops->hidden.mem.base = (Uint8 *)mem; + rwops->hidden.mem.here = rwops->hidden.mem.base; + rwops->hidden.mem.stop = rwops->hidden.mem.base+size; + } + return(rwops); +} + +SDL_RWops *SDL_RWFromConstMem(const void *mem, int size) +{ + SDL_RWops *rwops; + + rwops = SDL_AllocRW(); + if ( rwops != NULL ) { + rwops->seek = mem_seek; + rwops->read = mem_read; + rwops->write = mem_writeconst; + rwops->close = mem_close; + rwops->hidden.mem.base = (Uint8 *)mem; + rwops->hidden.mem.here = rwops->hidden.mem.base; + rwops->hidden.mem.stop = rwops->hidden.mem.base+size; + } + return(rwops); +} + +SDL_RWops *SDL_AllocRW(void) +{ + SDL_RWops *area; + + area = (SDL_RWops *)SDL_malloc(sizeof *area); + if ( area == NULL ) { + SDL_OutOfMemory(); + } + return(area); +} + +void SDL_FreeRW(SDL_RWops *area) +{ + SDL_free(area); +} + +/* Functions for dynamically reading and writing endian-specific values */ + +Uint16 SDL_ReadLE16 (SDL_RWops *src) +{ + Uint16 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapLE16(value)); +} +Uint16 SDL_ReadBE16 (SDL_RWops *src) +{ + Uint16 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapBE16(value)); +} +Uint32 SDL_ReadLE32 (SDL_RWops *src) +{ + Uint32 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapLE32(value)); +} +Uint32 SDL_ReadBE32 (SDL_RWops *src) +{ + Uint32 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapBE32(value)); +} +Uint64 SDL_ReadLE64 (SDL_RWops *src) +{ + Uint64 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapLE64(value)); +} +Uint64 SDL_ReadBE64 (SDL_RWops *src) +{ + Uint64 value; + + SDL_RWread(src, &value, (sizeof value), 1); + return(SDL_SwapBE64(value)); +} + +int SDL_WriteLE16 (SDL_RWops *dst, Uint16 value) +{ + value = SDL_SwapLE16(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} +int SDL_WriteBE16 (SDL_RWops *dst, Uint16 value) +{ + value = SDL_SwapBE16(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} +int SDL_WriteLE32 (SDL_RWops *dst, Uint32 value) +{ + value = SDL_SwapLE32(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} +int SDL_WriteBE32 (SDL_RWops *dst, Uint32 value) +{ + value = SDL_SwapBE32(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} +int SDL_WriteLE64 (SDL_RWops *dst, Uint64 value) +{ + value = SDL_SwapLE64(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} +int SDL_WriteBE64 (SDL_RWops *dst, Uint64 value) +{ + value = SDL_SwapBE64(value); + return(SDL_RWwrite(dst, &value, (sizeof value), 1)); +} diff --git a/3rdparty/SDL/src/hermes/COPYING.LIB b/3rdparty/SDL/src/hermes/COPYING.LIB new file mode 100644 index 0000000..69679a5 --- /dev/null +++ b/3rdparty/SDL/src/hermes/COPYING.LIB @@ -0,0 +1,438 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + diff --git a/3rdparty/SDL/src/hermes/HeadMMX.h b/3rdparty/SDL/src/hermes/HeadMMX.h new file mode 100644 index 0000000..5d9850c --- /dev/null +++ b/3rdparty/SDL/src/hermes/HeadMMX.h @@ -0,0 +1,100 @@ +/* + Header definitions for the MMX routines for the HERMES library + Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk) + This source code is licensed under the GNU LGPL + + Please refer to the file COPYING.LIB contained in the distribution for + licensing conditions +*/ +#include "SDL_config.h" + +#ifndef __HERMES_HEAD_MMX__ +#define __HERMES_HEAD_MMX__ + + +/* If you cannot stand ifdefs, then please do not look into this file, it's + going to end your life :) */ + +#ifdef X86_ASSEMBLER + + +#ifdef __cplusplus +extern "C" { +#endif + +void STACKCALL ConvertMMX(HermesConverterInterface *); + +void STACKCALL ClearMMX_32(HermesClearInterface *); +void STACKCALL ClearMMX_24(HermesClearInterface *); +void STACKCALL ClearMMX_16(HermesClearInterface *); +void STACKCALL ClearMMX_8(HermesClearInterface *); + +void ConvertMMXpII32_24RGB888(); +void ConvertMMXpII32_16RGB565(); +void ConvertMMXpII32_16BGR565(); +void ConvertMMXpII32_16RGB555(); +void ConvertMMXpII32_16BGR565(); +void ConvertMMXpII32_16BGR555(); + +void ConvertMMXp32_16RGB555(); + +#ifdef __cplusplus +} +#endif + + + +/* Fix the underscore business with ELF compilers */ + +#if (defined(__ELF__) && defined(__GNUC__)) || defined(__SUNPRO_C) + #ifdef __cplusplus + extern "C" { + #endif + + extern void _ConvertMMX(HermesConverterInterface *); + extern void _ConvertMMXpII32_24RGB888(); + extern void _ConvertMMXpII32_16RGB565(); + extern void _ConvertMMXpII32_16BGR565(); + extern void _ConvertMMXpII32_16RGB555(); + extern void _ConvertMMXpII32_16BGR555(); + + #define ConvertMMX _ConvertMMX + #define ConvertMMXpII32_24RGB888 _ConvertMMXpII32_24RGB888 + #define ConvertMMXpII32_16RGB565 _ConvertMMXpII32_16RGB565 + #define ConvertMMXpII32_16BGR565 _ConvertMMXpII32_16BGR565 + #define ConvertMMXpII32_16RGB555 _ConvertMMXpII32_16RGB555 + #define ConvertMMXpII32_16BGR555 _ConvertMMXpII32_16BGR555 + + #ifdef __cplusplus + } + #endif + +#endif /* ELF and GNUC */ + + + + +/* Make it work with Watcom */ +#ifdef __WATCOMC__ +#pragma warning 601 9 + +#pragma aux ConvertMMX "_*" modify [EAX EBX ECX EDX ESI EDI] + +#pragma aux ClearMMX_32 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearMMX_24 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearMMX_16 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearMMX_8 "_*" modify [EAX EBX ECX EDX ESI EDI] + +#pragma aux ConvertMMXpII32_24RGB888 "_*" +#pragma aux ConvertMMXpII32_16RGB565 "_*" +#pragma aux ConvertMMXpII32_16BGR565 "_*" +#pragma aux ConvertMMXpII32_16RGB555 "_*" +#pragma aux ConvertMMXpII32_16BGR555 "_*" +#pragma aux ConvertMMXp32_16RGB555 "_*" + +#endif /* WATCOM */ + +#endif /* X86_ASSEMBLER */ + + +#endif diff --git a/3rdparty/SDL/src/hermes/HeadX86.h b/3rdparty/SDL/src/hermes/HeadX86.h new file mode 100644 index 0000000..fc6b6dd --- /dev/null +++ b/3rdparty/SDL/src/hermes/HeadX86.h @@ -0,0 +1,186 @@ +/* + Header definitions for the x86 routines for the HERMES library + Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at) + This source code is licensed under the GNU LGPL + + Please refer to the file COPYING.LIB contained in the distribution for + licensing conditions +*/ + +#ifndef __HERMES_HEAD_X86__ +#define __HERMES_HEAD_X86__ + + +#ifdef X86_ASSEMBLER + +/* If you can't stand IFDEFS, then close your eyes now, please :) */ + +/* Ok, we start with normal function definitions */ +#ifdef __cplusplus +extern "C" { +#endif + + +void STACKCALL ConvertX86(HermesConverterInterface *); +void STACKCALL ClearX86_32(HermesClearInterface *); +void STACKCALL ClearX86_24(HermesClearInterface *); +void STACKCALL ClearX86_16(HermesClearInterface *); +void STACKCALL ClearX86_8(HermesClearInterface *); + +int STACKCALL Hermes_X86_CPU(); + +void ConvertX86p32_32BGR888(); +void ConvertX86p32_32RGBA888(); +void ConvertX86p32_32BGRA888(); +void ConvertX86p32_24RGB888(); +void ConvertX86p32_24BGR888(); +void ConvertX86p32_16RGB565(); +void ConvertX86p32_16BGR565(); +void ConvertX86p32_16RGB555(); +void ConvertX86p32_16BGR555(); +void ConvertX86p32_8RGB332(); + +void ConvertX86p16_32RGB888(); +void ConvertX86p16_32BGR888(); +void ConvertX86p16_32RGBA888(); +void ConvertX86p16_32BGRA888(); +void ConvertX86p16_24RGB888(); +void ConvertX86p16_24BGR888(); +void ConvertX86p16_16BGR565(); +void ConvertX86p16_16RGB555(); +void ConvertX86p16_16BGR555(); +void ConvertX86p16_8RGB332(); + +void CopyX86p_4byte(); +void CopyX86p_3byte(); +void CopyX86p_2byte(); +void CopyX86p_1byte(); + +void ConvertX86pI8_32(); +void ConvertX86pI8_24(); +void ConvertX86pI8_16(); + +extern int ConvertX86p16_32RGB888_LUT_X86[512]; +extern int ConvertX86p16_32BGR888_LUT_X86[512]; +extern int ConvertX86p16_32RGBA888_LUT_X86[512]; +extern int ConvertX86p16_32BGRA888_LUT_X86[512]; + +#ifdef __cplusplus +} +#endif + + + + +/* Now fix up the ELF underscore problem */ + +#if (defined(__ELF__) && defined(__GNUC__)) || defined(__SUNPRO_C) + #ifdef __cplusplus + extern "C" { + #endif + + extern int _Hermes_X86_CPU(); + + extern void _ConvertX86(HermesConverterInterface *); + + extern void _ConvertX86p32_32BGR888(); + extern void _ConvertX86p32_32RGBA888(); + extern void _ConvertX86p32_32BGRA888(); + extern void _ConvertX86p32_24RGB888(); + extern void _ConvertX86p32_24BGR888(); + extern void _ConvertX86p32_16RGB565(); + extern void _ConvertX86p32_16BGR565(); + extern void _ConvertX86p32_16RGB555(); + extern void _ConvertX86p32_16BGR555(); + extern void _ConvertX86p32_8RGB332(); + + extern void _ConvertX86p16_16BGR565(); + extern void _ConvertX86p16_16RGB555(); + extern void _ConvertX86p16_16BGR555(); + extern void _ConvertX86p16_8RGB332(); + + + #define Hermes_X86_CPU _Hermes_X86_CPU + + #define ConvertX86 _ConvertX86 + + #define ConvertX86p32_32BGR888 _ConvertX86p32_32BGR888 + #define ConvertX86p32_32RGBA888 _ConvertX86p32_32RGBA888 + #define ConvertX86p32_32BGRA888 _ConvertX86p32_32BGRA888 + #define ConvertX86p32_24RGB888 _ConvertX86p32_24RGB888 + #define ConvertX86p32_24BGR888 _ConvertX86p32_24BGR888 + #define ConvertX86p32_16RGB565 _ConvertX86p32_16RGB565 + #define ConvertX86p32_16BGR565 _ConvertX86p32_16BGR565 + #define ConvertX86p32_16RGB555 _ConvertX86p32_16RGB555 + #define ConvertX86p32_16BGR555 _ConvertX86p32_16BGR555 + #define ConvertX86p32_8RGB332 _ConvertX86p32_8RGB332 + + #define ConvertX86p16_16BGR565 _ConvertX86p16_16BGR565 + #define ConvertX86p16_16RGB555 _ConvertX86p16_16RGB555 + #define ConvertX86p16_16BGR555 _ConvertX86p16_16BGR555 + #define ConvertX86p16_8RGB332 _ConvertX86p16_8RGB332 + + + #ifdef __cplusplus + } + #endif + +#endif /* ELF & GNU */ + + + +/* Make it run with WATCOM C */ +#ifdef __WATCOMC__ +#pragma warning 601 9 + +#pragma aux Hermes_X86_CPU "_*" + +#pragma aux ConvertX86 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearX86_32 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearX86_24 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearX86_16 "_*" modify [EAX EBX ECX EDX ESI EDI] +#pragma aux ClearX86_8 "_*" modify [EAX EBX ECX EDX ESI EDI] + +#pragma aux ConvertX86p32_32BGR888 "_*" +#pragma aux ConvertX86p32_32RGBA888 "_*" +#pragma aux ConvertX86p32_32BGRA888 "_*" +#pragma aux ConvertX86p32_24RGB888 "_*" +#pragma aux ConvertX86p32_24BGR888 "_*" +#pragma aux ConvertX86p32_16RGB565 "_*" +#pragma aux ConvertX86p32_16BGR565 "_*" +#pragma aux ConvertX86p32_16RGB555 "_*" +#pragma aux ConvertX86p32_16BGR555 "_*" +#pragma aux ConvertX86p32_8RGB332 "_*" + +#pragma aux ConvertX86p16_32RGB888 "_*" +#pragma aux ConvertX86p16_32BGR888 "_*" +#pragma aux ConvertX86p16_32RGBA888 "_*" +#pragma aux ConvertX86p16_32BGRA888 "_*" +#pragma aux ConvertX86p16_24RGB888 "_*" +#pragma aux ConvertX86p16_24BGR888 "_*" +#pragma aux ConvertX86p16_16BGR565 "_*" +#pragma aux ConvertX86p16_16RGB555 "_*" +#pragma aux ConvertX86p16_16BGR555 "_*" +#pragma aux ConvertX86p16_8RGB332 "_*" + +#pragma aux CopyX86p_4byte "_*" +#pragma aux CopyX86p_3byte "_*" +#pragma aux CopyX86p_2byte "_*" +#pragma aux CopyX86p_1byte "_*" + +#pragma aux ConvertX86pI8_32 "_*" +#pragma aux ConvertX86pI8_24 "_*" +#pragma aux ConvertX86pI8_16 "_*" + +#pragma aux ConvertX86p16_32RGB888_LUT_X86 "_*" +#pragma aux ConvertX86p16_32BGR888_LUT_X86 "_*" +#pragma aux ConvertX86p16_32RGBA888_LUT_X86 "_*" +#pragma aux ConvertX86p16_32BGRA888_LUT_X86 "_*" + +#endif /* __WATCOMC__ */ + + +#endif /* X86_ASSEMBLER */ + + +#endif diff --git a/3rdparty/SDL/src/hermes/README b/3rdparty/SDL/src/hermes/README new file mode 100644 index 0000000..a03b6cf --- /dev/null +++ b/3rdparty/SDL/src/hermes/README @@ -0,0 +1,13 @@ +HERMES 1.2.4 (c)1998 Christian Nentwich (brn) (c.nentwich@cs.ucl.ac.uk) +and quite a few assembler routines (c) Glenn Fielder (gaffer@gaffer.org) + +This library and all the files enclosed in this package are free software +under the terms of the GNU Library General Public License (LGPL). Please +refer to the included file COPYING.LIB for the exact terms. +---------------------------------------------------------------------------- + +This is a stripped down version of HERMES, including only the x86 assembler +converters, for use with Simple DirectMedia Layer. + +The full HERMES library is available at: http://hermes.terminal.at/ + diff --git a/3rdparty/SDL/src/hermes/common.inc b/3rdparty/SDL/src/hermes/common.inc new file mode 100644 index 0000000..9587e6f --- /dev/null +++ b/3rdparty/SDL/src/hermes/common.inc @@ -0,0 +1,9 @@ +; Some common macros for hermes nasm code + +%macro SDL_FUNC 1 +%ifdef HIDDEN_VISIBILITY +GLOBAL %1:function hidden +%else +GLOBAL %1 +%endif +%endmacro diff --git a/3rdparty/SDL/src/hermes/mmx_main.asm b/3rdparty/SDL/src/hermes/mmx_main.asm new file mode 100644 index 0000000..00032b9 --- /dev/null +++ b/3rdparty/SDL/src/hermes/mmx_main.asm @@ -0,0 +1,74 @@ +; +; mmx format converter main loops for HERMES +; Some routines Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk) +; This source code is licensed under the GNU LGPL +; +; Please refer to the file COPYING.LIB contained in the distribution for +; licensing conditions +; + +BITS 32 + +%include "common.inc" + +SDL_FUNC _ConvertMMX + +SECTION .text + +;; _ConvertMMX: +;; [ESP+8] ConverterInfo* +;; -------------------------------------------------------------------------- +;; ConverterInfo (ebp+..) +;; 0: void *s_pixels +;; 4: int s_width +;; 8: int s_height +;; 12: int s_add +;; 16: void *d_pixels +;; 20: int d_width +;; 24: int d_height +;; 28: int d_add +;; 32: void (*converter_function)() +;; 36: int32 *lookup + +_ConvertMMX: + push ebp + mov ebp,esp + +; Save the registers used by the blitters, necessary for optimized code + pusha + + mov eax,[ebp+8] + + cmp dword [eax+4],BYTE 0 + je endconvert + + mov ebp,eax + + mov esi,[ebp+0] + mov edi,[ebp+16] + +y_loop: + mov ecx,[ebp+4] + + call [ebp+32] + + add esi,[ebp+12] + add edi,[ebp+28] + + dec dword [ebp+8] + jnz y_loop + + +; Restore the registers used by the blitters, necessary for optimized code + popa + + pop ebp + +endconvert: + emms + + ret + +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/3rdparty/SDL/src/hermes/mmxp2_32.asm b/3rdparty/SDL/src/hermes/mmxp2_32.asm new file mode 100644 index 0000000..20c3277 --- /dev/null +++ b/3rdparty/SDL/src/hermes/mmxp2_32.asm @@ -0,0 +1,405 @@ +; +; pII-optimised MMX format converters for HERMES +; Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk) +; and (c) 1999 Jonathan Matthew (jmatthew@uq.net.au) +; This source code is licensed under the GNU LGPL +; +; Please refer to the file COPYING.LIB contained in the distribution for +; licensing conditions +; +; COPYRIGHT NOTICE +; +; This file partly contains code that is (c) Intel Corporation, specifically +; the mode detection routine, and the converter to 15 bit (8 pixel +; conversion routine from the mmx programming tutorial pages). +; +; +; These routines aren't exactly pII optimised - it's just that as they +; are, they're terrible on p5 MMXs, but less so on pIIs. Someone needs to +; optimise them for p5 MMXs.. + +BITS 32 + +%include "common.inc" + +SDL_FUNC _ConvertMMXpII32_24RGB888 +SDL_FUNC _ConvertMMXpII32_16RGB565 +SDL_FUNC _ConvertMMXpII32_16BGR565 +SDL_FUNC _ConvertMMXpII32_16RGB555 +SDL_FUNC _ConvertMMXpII32_16BGR555 + +;; Macros for conversion routines + +%macro _push_immq_mask 1 + push dword %1 + push dword %1 +%endmacro + +%macro load_immq 2 + _push_immq_mask %2 + movq %1, [esp] +%endmacro + +%macro pand_immq 2 + _push_immq_mask %2 + pand %1, [esp] +%endmacro + +%define CLEANUP_IMMQ_LOADS(num) \ + add esp, byte 8 * num + +%define mmx32_rgb888_mask 00ffffffh +%define mmx32_rgb565_b 000000f8h +%define mmx32_rgb565_g 0000fc00h +%define mmx32_rgb565_r 00f80000h + +%define mmx32_rgb555_rb 00f800f8h +%define mmx32_rgb555_g 0000f800h +%define mmx32_rgb555_mul 20000008h +%define mmx32_bgr555_mul 00082000h + +SECTION .text + +_ConvertMMXpII32_24RGB888: + + ; set up mm6 as the mask, mm7 as zero + load_immq mm6, mmx32_rgb888_mask + CLEANUP_IMMQ_LOADS(1) + pxor mm7, mm7 + + mov edx, ecx ; save ecx + and ecx, 0fffffffch ; clear lower two bits + jnz .L1 + jmp .L2 + +.L1: + + movq mm0, [esi] ; A R G B a r g b + pand mm0, mm6 ; 0 R G B 0 r g b + movq mm1, [esi+8] ; A R G B a r g b + pand mm1, mm6 ; 0 R G B 0 r g b + + movq mm2, mm0 ; 0 R G B 0 r g b + punpckhdq mm2, mm7 ; 0 0 0 0 0 R G B + punpckldq mm0, mm7 ; 0 0 0 0 0 r g b + psllq mm2, 24 ; 0 0 R G B 0 0 0 + por mm0, mm2 ; 0 0 R G B r g b + + movq mm3, mm1 ; 0 R G B 0 r g b + psllq mm3, 48 ; g b 0 0 0 0 0 0 + por mm0, mm3 ; g b R G B r g b + + movq mm4, mm1 ; 0 R G B 0 r g b + punpckhdq mm4, mm7 ; 0 0 0 0 0 R G B + punpckldq mm1, mm7 ; 0 0 0 0 0 r g b + psrlq mm1, 16 ; 0 0 0 R G B 0 r + psllq mm4, 8 ; 0 0 0 0 R G B 0 + por mm1, mm4 ; 0 0 0 0 R G B r + + movq [edi], mm0 + add esi, BYTE 16 + movd [edi+8], mm1 + add edi, BYTE 12 + sub ecx, BYTE 4 + jnz .L1 + +.L2: + mov ecx, edx + and ecx, BYTE 3 + jz .L4 +.L3: + mov al, [esi] + mov bl, [esi+1] + mov dl, [esi+2] + mov [edi], al + mov [edi+1], bl + mov [edi+2], dl + add esi, BYTE 4 + add edi, BYTE 3 + dec ecx + jnz .L3 +.L4: + retn + + + +_ConvertMMXpII32_16RGB565: + + ; set up masks + load_immq mm5, mmx32_rgb565_b + load_immq mm6, mmx32_rgb565_g + load_immq mm7, mmx32_rgb565_r + CLEANUP_IMMQ_LOADS(3) + + mov edx, ecx + shr ecx, 2 + jnz .L1 + jmp .L2 ; not necessary at the moment, but doesn't hurt (much) + +.L1: + movq mm0, [esi] ; argb + movq mm1, mm0 ; argb + pand mm0, mm6 ; 00g0 + movq mm3, mm1 ; argb + pand mm1, mm5 ; 000b + pand mm3, mm7 ; 0r00 + pslld mm1, 2 ; 0 0 000000bb bbb00000 + por mm0, mm1 ; 0 0 ggggggbb bbb00000 + psrld mm0, 5 ; 0 0 00000ggg gggbbbbb + + movq mm4, [esi+8] ; argb + movq mm2, mm4 ; argb + pand mm4, mm6 ; 00g0 + movq mm1, mm2 ; argb + pand mm2, mm5 ; 000b + pand mm1, mm7 ; 0r00 + pslld mm2, 2 ; 0 0 000000bb bbb00000 + por mm4, mm2 ; 0 0 ggggggbb bbb00000 + psrld mm4, 5 ; 0 0 00000ggg gggbbbbb + + packuswb mm3, mm1 ; R 0 r 0 + packssdw mm0, mm4 ; as above.. ish + por mm0, mm3 ; done. + movq [edi], mm0 + + add esi, 16 + add edi, 8 + dec ecx + jnz .L1 + +.L2: + mov ecx, edx + and ecx, BYTE 3 + jz .L4 +.L3: + mov al, [esi] + mov bh, [esi+1] + mov ah, [esi+2] + shr al, 3 + and eax, 0F81Fh ; BYTE? + shr ebx, 5 + and ebx, 07E0h ; BYTE? + add eax, ebx + mov [edi], al + mov [edi+1], ah + add esi, BYTE 4 + add edi, BYTE 2 + dec ecx + jnz .L3 + +.L4: + retn + + +_ConvertMMXpII32_16BGR565: + + load_immq mm5, mmx32_rgb565_r + load_immq mm6, mmx32_rgb565_g + load_immq mm7, mmx32_rgb565_b + CLEANUP_IMMQ_LOADS(3) + + mov edx, ecx + shr ecx, 2 + jnz .L1 + jmp .L2 + +.L1: + movq mm0, [esi] ; a r g b + movq mm1, mm0 ; a r g b + pand mm0, mm6 ; 0 0 g 0 + movq mm3, mm1 ; a r g b + pand mm1, mm5 ; 0 r 0 0 + pand mm3, mm7 ; 0 0 0 b + + psllq mm3, 16 ; 0 b 0 0 + psrld mm1, 14 ; 0 0 000000rr rrr00000 + por mm0, mm1 ; 0 0 ggggggrr rrr00000 + psrld mm0, 5 ; 0 0 00000ggg gggrrrrr + + movq mm4, [esi+8] ; a r g b + movq mm2, mm4 ; a r g b + pand mm4, mm6 ; 0 0 g 0 + movq mm1, mm2 ; a r g b + pand mm2, mm5 ; 0 r 0 0 + pand mm1, mm7 ; 0 0 0 b + + psllq mm1, 16 ; 0 b 0 0 + psrld mm2, 14 ; 0 0 000000rr rrr00000 + por mm4, mm2 ; 0 0 ggggggrr rrr00000 + psrld mm4, 5 ; 0 0 00000ggg gggrrrrr + + packuswb mm3, mm1 ; BBBBB000 00000000 bbbbb000 00000000 + packssdw mm0, mm4 ; 00000GGG GGGRRRRR 00000GGG GGGRRRRR + por mm0, mm3 ; BBBBBGGG GGGRRRRR bbbbbggg gggrrrrr + movq [edi], mm0 + + add esi, BYTE 16 + add edi, BYTE 8 + dec ecx + jnz .L1 + +.L2: + and edx, BYTE 3 + jz .L4 +.L3: + mov al, [esi+2] + mov bh, [esi+1] + mov ah, [esi] + shr al, 3 + and eax, 0F81Fh ; BYTE ? + shr ebx, 5 + and ebx, 07E0h ; BYTE ? + add eax, ebx + mov [edi], al + mov [edi+1], ah + add esi, BYTE 4 + add edi, BYTE 2 + dec edx + jnz .L3 + +.L4: + retn + +_ConvertMMXpII32_16BGR555: + + ; the 16BGR555 converter is identical to the RGB555 one, + ; except it uses a different multiplier for the pmaddwd + ; instruction. cool huh. + + load_immq mm7, mmx32_bgr555_mul + jmp _convert_bgr555_cheat + +; This is the same as the Intel version.. they obviously went to +; much more trouble to expand/coil the loop than I did, so theirs +; would almost certainly be faster, even if only a little. +; I did rename 'mmx32_rgb555_add' to 'mmx32_rgb555_mul', which is +; (I think) a more accurate name.. +_ConvertMMXpII32_16RGB555: + + load_immq mm7, mmx32_rgb555_mul +_convert_bgr555_cheat: + load_immq mm6, mmx32_rgb555_g + CLEANUP_IMMQ_LOADS(2) + + mov edx,ecx ; Save ecx + + and ecx,DWORD 0fffffff8h ; clear lower three bits + jnz .L_OK + jmp near .L2 + +.L_OK: + + movq mm2,[esi+8] + + movq mm0,[esi] + movq mm3,mm2 + + pand_immq mm3, mmx32_rgb555_rb + movq mm1,mm0 + + pand_immq mm1, mmx32_rgb555_rb + pmaddwd mm3,mm7 + + CLEANUP_IMMQ_LOADS(2) + + pmaddwd mm1,mm7 + pand mm2,mm6 + +.L1: + movq mm4,[esi+24] + pand mm0,mm6 + + movq mm5,[esi+16] + por mm3,mm2 + + psrld mm3,6 + por mm1,mm0 + + movq mm0,mm4 + psrld mm1,6 + + pand_immq mm0, mmx32_rgb555_rb + packssdw mm1,mm3 + + movq mm3,mm5 + pmaddwd mm0,mm7 + + pand_immq mm3, mmx32_rgb555_rb + pand mm4,mm6 + + movq [edi],mm1 + pmaddwd mm3,mm7 + + add esi,BYTE 32 + por mm4,mm0 + + pand mm5,mm6 + psrld mm4,6 + + movq mm2,[esi+8] + por mm5,mm3 + + movq mm0,[esi] + psrld mm5,6 + + movq mm3,mm2 + movq mm1,mm0 + + pand_immq mm3, mmx32_rgb555_rb + packssdw mm5,mm4 + + pand_immq mm1, mmx32_rgb555_rb + pand mm2,mm6 + + CLEANUP_IMMQ_LOADS(4) + + movq [edi+8],mm5 + pmaddwd mm3,mm7 + + pmaddwd mm1,mm7 + add edi,BYTE 16 + + sub ecx,BYTE 8 + jz .L2 + jmp .L1 + + +.L2: + mov ecx,edx + + and ecx,BYTE 7 + jz .L4 + +.L3: + mov ebx,[esi] + add esi,BYTE 4 + + mov eax,ebx + mov edx,ebx + + shr eax,3 + shr edx,6 + + and eax,BYTE 0000000000011111b + and edx, 0000001111100000b + + shr ebx,9 + + or eax,edx + + and ebx, 0111110000000000b + + or eax,ebx + + mov [edi],ax + add edi,BYTE 2 + + dec ecx + jnz .L3 + +.L4: + retn + +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/3rdparty/SDL/src/hermes/x86_main.asm b/3rdparty/SDL/src/hermes/x86_main.asm new file mode 100644 index 0000000..f7dd3db --- /dev/null +++ b/3rdparty/SDL/src/hermes/x86_main.asm @@ -0,0 +1,75 @@ +; +; x86 format converters for HERMES +; Some routines Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at) +; This source code is licensed under the GNU LGPL +; +; Please refer to the file COPYING.LIB contained in the distribution for +; licensing conditions +; +; Most routines are (c) Glenn Fiedler (ptc@gaffer.org), used with permission +; + +BITS 32 + +%include "common.inc" + +SDL_FUNC _ConvertX86 + +SECTION .text + +;; _ConvertX86: +;; [ESP+8] ConverterInfo* +;; -------------------------------------------------------------------------- +;; ConverterInfo (ebp+..) +;; 0: void *s_pixels +;; 4: int s_width +;; 8: int s_height +;; 12: int s_add +;; 16: void *d_pixels +;; 20: int d_width +;; 24: int d_height +;; 28: int d_add +;; 32: void (*converter_function)() +;; 36: int32 *lookup + +_ConvertX86: + push ebp + mov ebp,esp + +; Save the registers used by the blitters, necessary for optimized code + pusha + + mov eax,[ebp+8] + + cmp dword [eax+4],BYTE 0 + je endconvert + + mov ebp,eax + + mov esi,[ebp+0] + mov edi,[ebp+16] + +y_loop: + mov ecx,[ebp+4] + + call [ebp+32] + + add esi,[ebp+12] + add edi,[ebp+28] + + dec dword [ebp+8] + jnz y_loop + +; Restore the registers used by the blitters, necessary for optimized code + popa + + pop ebp + +endconvert: + ret + + + +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/3rdparty/SDL/src/hermes/x86p_16.asm b/3rdparty/SDL/src/hermes/x86p_16.asm new file mode 100644 index 0000000..1801bcd --- /dev/null +++ b/3rdparty/SDL/src/hermes/x86p_16.asm @@ -0,0 +1,490 @@ +; +; x86 format converters for HERMES +; Copyright (c) 1998 Glenn Fielder (gaffer@gaffer.org) +; This source code is licensed under the GNU LGPL +; +; Please refer to the file COPYING.LIB contained in the distribution for +; licensing conditions +; +; Routines adjusted for Hermes by Christian Nentwich (brn@eleet.mcb.at) +; Used with permission. +; + +BITS 32 + +%include "common.inc" + +SDL_FUNC _ConvertX86p16_16BGR565 +SDL_FUNC _ConvertX86p16_16RGB555 +SDL_FUNC _ConvertX86p16_16BGR555 +SDL_FUNC _ConvertX86p16_8RGB332 + +EXTERN _ConvertX86 + +SECTION .text + +_ConvertX86p16_16BGR565: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + + +.L1: ; short loop + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + and ebx,11111100000b + shl edx,11 + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov eax,edi + and eax,BYTE 11b + jz .L4 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + and ebx,11111100000b + shl edx,11 + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + +.L4: ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*4] + lea edi,[edi+ecx*4] + + ; negative counter + neg ecx + jmp SHORT .L6 + +.L5: mov [edi+ecx*4-4],eax +.L6: mov eax,[esi+ecx*4] + + mov ebx,[esi+ecx*4] + and eax,07E007E0h + + mov edx,[esi+ecx*4] + and ebx,0F800F800h + + shr ebx,11 + and edx,001F001Fh + + shl edx,11 + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + and ecx,BYTE 1 + jz .L7 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + and ebx,11111100000b + shl edx,11 + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + +.L7: + retn + + + + + + +_ConvertX86p16_16RGB555: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + + +.L1: ; short loop + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + shr ebx,1 + and ebx, 0111111111100000b + and eax,BYTE 0000000000011111b + add eax,ebx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov eax,edi + and eax,BYTE 11b + jz .L4 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + shr ebx,1 + and ebx, 0111111111100000b + and eax,BYTE 0000000000011111b + add eax,ebx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + +.L4: ; save ebp + push ebp + + ; save count + push ecx + + ; unroll four times + shr ecx,2 + + ; point arrays to end + lea esi,[esi+ecx*8] + lea edi,[edi+ecx*8] + + ; negative counter + xor ebp,ebp + sub ebp,ecx + +.L5: mov eax,[esi+ebp*8] ; agi? + mov ecx,[esi+ebp*8+4] + + mov ebx,eax + mov edx,ecx + + and eax,0FFC0FFC0h + and ecx,0FFC0FFC0h + + shr eax,1 + and ebx,001F001Fh + + shr ecx,1 + and edx,001F001Fh + + add eax,ebx + add ecx,edx + + mov [edi+ebp*8],eax + mov [edi+ebp*8+4],ecx + + inc ebp + jnz .L5 + + ; tail + pop ecx +.L6: and ecx,BYTE 11b + jz .L7 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + shr ebx,1 + and ebx, 0111111111100000b + and eax,BYTE 0000000000011111b + add eax,ebx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + jmp SHORT .L6 + +.L7: pop ebp + retn + + + + + + +_ConvertX86p16_16BGR555: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + + +.L1: ; short loop + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + shr ebx,1 + and ebx,1111100000b + shl edx,10 + and edx,0111110000000000b + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov eax,edi + and eax,BYTE 11b + jz .L4 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + shr ebx,1 + and ebx,1111100000b + shl edx,10 + and edx,0111110000000000b + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + dec ecx + +.L4: ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*4] + lea edi,[edi+ecx*4] + + ; negative counter + neg ecx + jmp SHORT .L6 + +.L5: mov [edi+ecx*4-4],eax +.L6: mov eax,[esi+ecx*4] + + shr eax,1 + mov ebx,[esi+ecx*4] + + and eax,03E003E0h + mov edx,[esi+ecx*4] + + and ebx,0F800F800h + + shr ebx,11 + and edx,001F001Fh + + shl edx,10 + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + and ecx,BYTE 1 + jz .L7 + mov al,[esi] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + shr eax,11 + and eax,BYTE 11111b + shr ebx,1 + and ebx,1111100000b + shl edx,10 + and edx,0111110000000000b + add eax,ebx + add eax,edx + mov [edi],al + mov [edi+1],ah + add esi,BYTE 2 + add edi,BYTE 2 + +.L7: + retn + + + + + + +_ConvertX86p16_8RGB332: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + + +.L1: ; short loop + mov al,[esi+0] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + and eax,BYTE 11000b ; blue + shr eax,3 + and ebx,11100000000b ; green + shr ebx,6 + and edx,1110000000000000b ; red + shr edx,8 + add eax,ebx + add eax,edx + mov [edi],al + add esi,BYTE 2 + inc edi + dec ecx + jnz .L1 +.L2: + retn + +.L3: mov eax,edi + and eax,BYTE 11b + jz .L4 + mov al,[esi+0] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + and eax,BYTE 11000b ; blue + shr eax,3 + and ebx,11100000000b ; green + shr ebx,6 + and edx,1110000000000000b ; red + shr edx,8 + add eax,ebx + add eax,edx + mov [edi],al + add esi,BYTE 2 + inc edi + dec ecx + jmp SHORT .L3 + +.L4: ; save ebp + push ebp + + ; save count + push ecx + + ; unroll 4 times + shr ecx,2 + + ; prestep + mov dl,[esi+0] + mov bl,[esi+1] + mov dh,[esi+2] + +.L5: shl edx,16 + mov bh,[esi+3] + + shl ebx,16 + mov dl,[esi+4] + + mov dh,[esi+6] + mov bl,[esi+5] + + and edx,00011000000110000001100000011000b + mov bh,[esi+7] + + ror edx,16+3 + mov eax,ebx ; setup eax for reds + + and ebx,00000111000001110000011100000111b + and eax,11100000111000001110000011100000b ; reds + + ror ebx,16-2 + add esi,BYTE 8 + + ror eax,16 + add edi,BYTE 4 + + add eax,ebx + mov bl,[esi+1] ; greens + + add eax,edx + mov dl,[esi+0] ; blues + + mov [edi-4],eax + mov dh,[esi+2] + + dec ecx + jnz .L5 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L7 + +.L6: ; tail + mov al,[esi+0] + mov ah,[esi+1] + mov ebx,eax + mov edx,eax + and eax,BYTE 11000b ; blue + shr eax,3 + and ebx,11100000000b ; green + shr ebx,6 + and edx,1110000000000000b ; red + shr edx,8 + add eax,ebx + add eax,edx + mov [edi],al + add esi,BYTE 2 + inc edi + dec ecx + jnz .L6 + +.L7: pop ebp + retn + +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/3rdparty/SDL/src/hermes/x86p_32.asm b/3rdparty/SDL/src/hermes/x86p_32.asm new file mode 100644 index 0000000..2b47880 --- /dev/null +++ b/3rdparty/SDL/src/hermes/x86p_32.asm @@ -0,0 +1,1044 @@ +; +; x86 format converters for HERMES +; Some routines Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at) +; This source code is licensed under the GNU LGPL +; +; Please refer to the file COPYING.LIB contained in the distribution for +; licensing conditions +; +; Most routines are (c) Glenn Fiedler (ptc@gaffer.org), used with permission +; + +BITS 32 + +%include "common.inc" + +SDL_FUNC _ConvertX86p32_32BGR888 +SDL_FUNC _ConvertX86p32_32RGBA888 +SDL_FUNC _ConvertX86p32_32BGRA888 +SDL_FUNC _ConvertX86p32_24RGB888 +SDL_FUNC _ConvertX86p32_24BGR888 +SDL_FUNC _ConvertX86p32_16RGB565 +SDL_FUNC _ConvertX86p32_16BGR565 +SDL_FUNC _ConvertX86p32_16RGB555 +SDL_FUNC _ConvertX86p32_16BGR555 +SDL_FUNC _ConvertX86p32_8RGB332 + +SECTION .text + +;; _Convert_* +;; Paramters: +;; ESI = source +;; EDI = dest +;; ECX = amount (NOT 0!!! (the _ConvertX86 routine checks for that though)) +;; Destroys: +;; EAX, EBX, EDX + + +_ConvertX86p32_32BGR888: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + +.L1: ; short loop + mov edx,[esi] + bswap edx + ror edx,8 + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; save ebp + push ebp + + ; unroll four times + mov ebp,ecx + shr ebp,2 + + ; save count + push ecx + +.L4: mov eax,[esi] + mov ebx,[esi+4] + + bswap eax + + bswap ebx + + ror eax,8 + mov ecx,[esi+8] + + ror ebx,8 + mov edx,[esi+12] + + bswap ecx + + bswap edx + + ror ecx,8 + mov [edi+0],eax + + ror edx,8 + mov [edi+4],ebx + + mov [edi+8],ecx + mov [edi+12],edx + + add esi,BYTE 16 + add edi,BYTE 16 + + dec ebp + jnz .L4 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L6 + +.L5: ; tail loop + mov edx,[esi] + bswap edx + ror edx,8 + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L5 + +.L6: pop ebp + retn + + + + +_ConvertX86p32_32RGBA888: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + +.L1: ; short loop + mov edx,[esi] + rol edx,8 + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; save ebp + push ebp + + ; unroll four times + mov ebp,ecx + shr ebp,2 + + ; save count + push ecx + +.L4: mov eax,[esi] + mov ebx,[esi+4] + + rol eax,8 + mov ecx,[esi+8] + + rol ebx,8 + mov edx,[esi+12] + + rol ecx,8 + mov [edi+0],eax + + rol edx,8 + mov [edi+4],ebx + + mov [edi+8],ecx + mov [edi+12],edx + + add esi,BYTE 16 + add edi,BYTE 16 + + dec ebp + jnz .L4 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L6 + +.L5: ; tail loop + mov edx,[esi] + rol edx,8 + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L5 + +.L6: pop ebp + retn + + + + +_ConvertX86p32_32BGRA888: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + +.L1: ; short loop + mov edx,[esi] + bswap edx + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; save ebp + push ebp + + ; unroll four times + mov ebp,ecx + shr ebp,2 + + ; save count + push ecx + +.L4: mov eax,[esi] + mov ebx,[esi+4] + + mov ecx,[esi+8] + mov edx,[esi+12] + + bswap eax + + bswap ebx + + bswap ecx + + bswap edx + + mov [edi+0],eax + mov [edi+4],ebx + + mov [edi+8],ecx + mov [edi+12],edx + + add esi,BYTE 16 + add edi,BYTE 16 + + dec ebp + jnz .L4 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L6 + +.L5: ; tail loop + mov edx,[esi] + bswap edx + mov [edi],edx + add esi,BYTE 4 + add edi,BYTE 4 + dec ecx + jnz .L5 + +.L6: pop ebp + retn + + + + +;; 32 bit RGB 888 to 24 BIT RGB 888 + +_ConvertX86p32_24RGB888: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + +.L1: ; short loop + mov al,[esi] + mov bl,[esi+1] + mov dl,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov edx,edi + and edx,BYTE 11b + jz .L4 + mov al,[esi] + mov bl,[esi+1] + mov dl,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jmp SHORT .L3 + +.L4: ; unroll 4 times + push ebp + mov ebp,ecx + shr ebp,2 + + ; save count + push ecx + +.L5: mov eax,[esi] ; first dword eax = [A][R][G][B] + mov ebx,[esi+4] ; second dword ebx = [a][r][g][b] + + shl eax,8 ; eax = [R][G][B][.] + mov ecx,[esi+12] ; third dword ecx = [a][r][g][b] + + shl ebx,8 ; ebx = [r][g][b][.] + mov al,[esi+4] ; eax = [R][G][B][b] + + ror eax,8 ; eax = [b][R][G][B] (done) + mov bh,[esi+8+1] ; ebx = [r][g][G][.] + + mov [edi],eax + add edi,BYTE 3*4 + + shl ecx,8 ; ecx = [r][g][b][.] + mov bl,[esi+8+0] ; ebx = [r][g][G][B] + + rol ebx,16 ; ebx = [G][B][r][g] (done) + mov cl,[esi+8+2] ; ecx = [r][g][b][R] (done) + + mov [edi+4-3*4],ebx + add esi,BYTE 4*4 + + mov [edi+8-3*4],ecx + dec ebp + + jnz .L5 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L7 + +.L6: ; tail loop + mov al,[esi] + mov bl,[esi+1] + mov dl,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jnz .L6 + +.L7: pop ebp + retn + + + + +;; 32 bit RGB 888 to 24 bit BGR 888 + +_ConvertX86p32_24BGR888: + + ; check short + cmp ecx,BYTE 32 + ja .L3 + +.L1: ; short loop + mov dl,[esi] + mov bl,[esi+1] + mov al,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov edx,edi + and edx,BYTE 11b + jz .L4 + mov dl,[esi] + mov bl,[esi+1] + mov al,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jmp SHORT .L3 + +.L4: ; unroll 4 times + push ebp + mov ebp,ecx + shr ebp,2 + + ; save count + push ecx + +.L5: + mov eax,[esi] ; first dword eax = [A][R][G][B] + mov ebx,[esi+4] ; second dword ebx = [a][r][g][b] + + bswap eax ; eax = [B][G][R][A] + + bswap ebx ; ebx = [b][g][r][a] + + mov al,[esi+4+2] ; eax = [B][G][R][r] + mov bh,[esi+4+4+1] ; ebx = [b][g][G][a] + + ror eax,8 ; eax = [r][B][G][R] (done) + mov bl,[esi+4+4+2] ; ebx = [b][g][G][R] + + ror ebx,16 ; ebx = [G][R][b][g] (done) + mov [edi],eax + + mov [edi+4],ebx + mov ecx,[esi+12] ; third dword ecx = [a][r][g][b] + + bswap ecx ; ecx = [b][g][r][a] + + mov cl,[esi+8] ; ecx = [b][g][r][B] (done) + add esi,BYTE 4*4 + + mov [edi+8],ecx + add edi,BYTE 3*4 + + dec ebp + jnz .L5 + + ; check tail + pop ecx + and ecx,BYTE 11b + jz .L7 + +.L6: ; tail loop + mov dl,[esi] + mov bl,[esi+1] + mov al,[esi+2] + mov [edi],al + mov [edi+1],bl + mov [edi+2],dl + add esi,BYTE 4 + add edi,BYTE 3 + dec ecx + jnz .L6 + +.L7: + pop ebp + retn + + + + +;; 32 bit RGB 888 to 16 BIT RGB 565 + +_ConvertX86p32_16RGB565: + ; check short + cmp ecx,BYTE 16 + ja .L3 + +.L1: ; short loop + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + jnz .L1 + +.L2: ; End of short loop + retn + + +.L3: ; head + mov ebx,edi + and ebx,BYTE 11b + jz .L4 + + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + +.L4: + ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*8] + lea edi,[edi+ecx*4] + + ; negative counter + neg ecx + jmp SHORT .L6 + +.L5: + mov [edi+ecx*4-4],eax +.L6: + mov eax,[esi+ecx*8] + + shr ah,2 + mov ebx,[esi+ecx*8+4] + + shr eax,3 + mov edx,[esi+ecx*8+4] + + shr bh,2 + mov dl,[esi+ecx*8+2] + + shl ebx,13 + and eax,000007FFh + + shl edx,8 + and ebx,07FF0000h + + and edx,0F800F800h + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + test cl,1 + jz .L7 + + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + +.L7: + retn + + + + +;; 32 bit RGB 888 to 16 BIT BGR 565 + +_ConvertX86p32_16BGR565: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + +.L1: ; short loop + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov ebx,edi + and ebx,BYTE 11b + jz .L4 + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + +.L4: ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*8] + lea edi,[edi+ecx*4] + + ; negative count + neg ecx + jmp SHORT .L6 + +.L5: + mov [edi+ecx*4-4],eax +.L6: + mov edx,[esi+ecx*8+4] + + mov bh,[esi+ecx*8+4] + mov ah,[esi+ecx*8] + + shr bh,3 + mov al,[esi+ecx*8+1] + + shr ah,3 + mov bl,[esi+ecx*8+5] + + shl eax,3 + mov dl,[esi+ecx*8+2] + + shl ebx,19 + and eax,0000FFE0h + + shr edx,3 + and ebx,0FFE00000h + + and edx,001F001Fh + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + and ecx,BYTE 1 + jz .L7 + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111100b + shl eax,3 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + +.L7: + retn + + + + +;; 32 BIT RGB TO 16 BIT RGB 555 + +_ConvertX86p32_16RGB555: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + +.L1: ; short loop + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov ebx,edi + and ebx,BYTE 11b + jz .L4 + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + +.L4: ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*8] + lea edi,[edi+ecx*4] + + ; negative counter + neg ecx + jmp SHORT .L6 + +.L5: + mov [edi+ecx*4-4],eax +.L6: + mov eax,[esi+ecx*8] + + shr ah,3 + mov ebx,[esi+ecx*8+4] + + shr eax,3 + mov edx,[esi+ecx*8+4] + + shr bh,3 + mov dl,[esi+ecx*8+2] + + shl ebx,13 + and eax,000007FFh + + shl edx,7 + and ebx,07FF0000h + + and edx,07C007C00h + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + and ecx,BYTE 1 + jz .L7 + mov bl,[esi+0] ; blue + mov al,[esi+1] ; green + mov ah,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + +.L7: + retn + + + + +;; 32 BIT RGB TO 16 BIT BGR 555 + +_ConvertX86p32_16BGR555: + + ; check short + cmp ecx,BYTE 16 + ja .L3 + + +.L1: ; short loop + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + jnz .L1 +.L2: + retn + +.L3: ; head + mov ebx,edi + and ebx,BYTE 11b + jz .L4 + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + dec ecx + +.L4: ; save count + push ecx + + ; unroll twice + shr ecx,1 + + ; point arrays to end + lea esi,[esi+ecx*8] + lea edi,[edi+ecx*4] + + ; negative counter + neg ecx + jmp SHORT .L6 + +.L5: + mov [edi+ecx*4-4],eax +.L6: + mov edx,[esi+ecx*8+4] + + mov bh,[esi+ecx*8+4] + mov ah,[esi+ecx*8] + + shr bh,3 + mov al,[esi+ecx*8+1] + + shr ah,3 + mov bl,[esi+ecx*8+5] + + shl eax,2 + mov dl,[esi+ecx*8+2] + + shl ebx,18 + and eax,00007FE0h + + shr edx,3 + and ebx,07FE00000h + + and edx,001F001Fh + add eax,ebx + + add eax,edx + inc ecx + + jnz .L5 + + mov [edi+ecx*4-4],eax + + ; tail + pop ecx + and ecx,BYTE 1 + jz .L7 + mov ah,[esi+0] ; blue + mov al,[esi+1] ; green + mov bl,[esi+2] ; red + shr ah,3 + and al,11111000b + shl eax,2 + shr bl,3 + add al,bl + mov [edi+0],al + mov [edi+1],ah + add esi,BYTE 4 + add edi,BYTE 2 + +.L7: + retn + + + + + +;; FROM 32 BIT RGB to 8 BIT RGB (rrrgggbbb) +;; This routine writes FOUR pixels at once (dword) and then, if they exist +;; the trailing three pixels +_ConvertX86p32_8RGB332: + + +.L_ALIGNED: + push ecx + + shr ecx,2 ; We will draw 4 pixels at once + jnz .L1 + + jmp .L2 ; short jump out of range :( + +.L1: + mov eax,[esi] ; first pair of pixels + mov edx,[esi+4] + + shr dl,6 + mov ebx,eax + + shr al,6 + and ah,0e0h + + shr ebx,16 + and dh,0e0h + + shr ah,3 + and bl,0e0h + + shr dh,3 + + or al,bl + + mov ebx,edx + or al,ah + + shr ebx,16 + or dl,dh + + and bl,0e0h + + or dl,bl + + mov ah,dl + + + + mov ebx,[esi+8] ; second pair of pixels + + mov edx,ebx + and bh,0e0h + + shr bl,6 + and edx,0e00000h + + shr edx,16 + + shr bh,3 + + ror eax,16 + or bl,dl + + mov edx,[esi+12] + or bl,bh + + mov al,bl + + mov ebx,edx + and dh,0e0h + + shr dl,6 + and ebx,0e00000h + + shr dh,3 + mov ah,dl + + shr ebx,16 + or ah,dh + + or ah,bl + + rol eax,16 + add esi,BYTE 16 + + mov [edi],eax + add edi,BYTE 4 + + dec ecx + jz .L2 ; L1 out of range for short jump :( + + jmp .L1 +.L2: + + pop ecx + and ecx,BYTE 3 ; mask out number of pixels to draw + + jz .L4 ; Nothing to do anymore + +.L3: + mov eax,[esi] ; single pixel conversion for trailing pixels + + mov ebx,eax + + shr al,6 + and ah,0e0h + + shr ebx,16 + + shr ah,3 + and bl,0e0h + + or al,ah + or al,bl + + mov [edi],al + + inc edi + add esi,BYTE 4 + + dec ecx + jnz .L3 + +.L4: + retn + +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/3rdparty/SDL/src/joystick/SDL_joystick.c b/3rdparty/SDL/src/joystick/SDL_joystick.c new file mode 100644 index 0000000..083b017 --- /dev/null +++ b/3rdparty/SDL/src/joystick/SDL_joystick.c @@ -0,0 +1,606 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the joystick API for Simple DirectMedia Layer */ + +#include "SDL_events.h" +#include "SDL_sysjoystick.h" +#include "SDL_joystick_c.h" +#if !SDL_EVENTS_DISABLED +#include "../events/SDL_events_c.h" +#endif + +/* This is used for Quake III Arena */ +#if SDL_EVENTS_DISABLED +#define SDL_Lock_EventThread() +#define SDL_Unlock_EventThread() +#endif + +Uint8 SDL_numjoysticks = 0; +int SDL_allocatedjoysticks = 0; +SDL_Joystick **SDL_joysticks = NULL; + +int SDL_JoystickInit(void) +{ + int arraylen; + int status; + + SDL_numjoysticks = 0; + status = SDL_SYS_JoystickInit(); + if ( status >= 0 ) { + SDL_allocatedjoysticks = status; + arraylen = (SDL_allocatedjoysticks+1)*sizeof(*SDL_joysticks); + SDL_joysticks = (SDL_Joystick **)SDL_malloc(arraylen); + if ( SDL_joysticks == NULL ) { + SDL_numjoysticks = 0; + SDL_allocatedjoysticks = 0; + } else { + SDL_memset(SDL_joysticks, 0, arraylen); + SDL_numjoysticks = status; + } + status = 0; + } + return(status); +} + +/* + * Count the number of joysticks attached to the system + */ +int SDL_NumJoysticks(void) +{ + return SDL_numjoysticks; +} + +/* + * Get the implementation dependent name of a joystick + */ +const char *SDL_JoystickName(int device_index) +{ + if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { + SDL_SetError("There are %d joysticks available", + SDL_numjoysticks); + return(NULL); + } + return(SDL_SYS_JoystickName(device_index)); +} + +/* + * Open a joystick for use - the index passed as an argument refers to + * the N'th joystick on the system. This index is the value which will + * identify this joystick in future joystick events. + * + * This function returns a joystick identifier, or NULL if an error occurred. + */ +SDL_Joystick *SDL_JoystickOpen(int device_index) +{ + int i; + SDL_Joystick *joystick; + + if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) { + SDL_SetError("There are %d joysticks available", + SDL_numjoysticks); + return(NULL); + } + + /* If the joystick is already open, return it */ + for ( i=0; SDL_joysticks[i]; ++i ) { + if ( device_index == SDL_joysticks[i]->index ) { + joystick = SDL_joysticks[i]; + ++joystick->ref_count; + return(joystick); + } + } + + /* Create and initialize the joystick */ + joystick = (SDL_Joystick *)SDL_malloc((sizeof *joystick)); + if ( !joystick ) { + SDL_OutOfMemory(); + return(NULL); + } + + SDL_memset(joystick, 0, (sizeof *joystick)); + joystick->index = device_index; + if ( SDL_SYS_JoystickOpen(joystick) < 0 ) { + SDL_free(joystick); + return(NULL); + } + + if ( joystick->naxes > 0 ) { + joystick->axes = (Sint16 *)SDL_malloc + (joystick->naxes*sizeof(Sint16)); + } + if ( joystick->nhats > 0 ) { + joystick->hats = (Uint8 *)SDL_malloc + (joystick->nhats*sizeof(Uint8)); + } + if ( joystick->nballs > 0 ) { + joystick->balls = (struct balldelta *)SDL_malloc + (joystick->nballs*sizeof(*joystick->balls)); + } + if ( joystick->nbuttons > 0 ) { + joystick->buttons = (Uint8 *)SDL_malloc + (joystick->nbuttons*sizeof(Uint8)); + } + if ( ((joystick->naxes > 0) && !joystick->axes) + || ((joystick->nhats > 0) && !joystick->hats) + || ((joystick->nballs > 0) && !joystick->balls) + || ((joystick->nbuttons > 0) && !joystick->buttons)) { + SDL_OutOfMemory(); + SDL_JoystickClose(joystick); + return(NULL); + } + + if ( joystick->axes ) { + SDL_memset(joystick->axes, 0, + joystick->naxes*sizeof(Sint16)); + } + if ( joystick->hats ) { + SDL_memset(joystick->hats, 0, + joystick->nhats*sizeof(Uint8)); + } + if ( joystick->balls ) { + SDL_memset(joystick->balls, 0, + joystick->nballs*sizeof(*joystick->balls)); + } + if ( joystick->buttons ) { + SDL_memset(joystick->buttons, 0, + joystick->nbuttons*sizeof(Uint8)); + } + + /* Add joystick to list */ + ++joystick->ref_count; + SDL_Lock_EventThread(); + for ( i=0; SDL_joysticks[i]; ++i ) + /* Skip to next joystick */ ; + SDL_joysticks[i] = joystick; + SDL_Unlock_EventThread(); + + return(joystick); +} + +/* + * Returns 1 if the joystick has been opened, or 0 if it has not. + */ +int SDL_JoystickOpened(int device_index) +{ + int i, opened; + + opened = 0; + for ( i=0; SDL_joysticks[i]; ++i ) { + if ( SDL_joysticks[i]->index == (Uint8)device_index ) { + opened = 1; + break; + } + } + return(opened); +} + +static int ValidJoystick(SDL_Joystick **joystick) +{ + int valid; + + if ( *joystick == NULL ) { + SDL_SetError("Joystick hasn't been opened yet"); + valid = 0; + } else { + valid = 1; + } + return valid; +} + +/* + * Get the device index of an opened joystick. + */ +int SDL_JoystickIndex(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->index); +} + +/* + * Get the number of multi-dimensional axis controls on a joystick + */ +int SDL_JoystickNumAxes(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->naxes); +} + +/* + * Get the number of hats on a joystick + */ +int SDL_JoystickNumHats(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->nhats); +} + +/* + * Get the number of trackballs on a joystick + */ +int SDL_JoystickNumBalls(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->nballs); +} + +/* + * Get the number of buttons on a joystick + */ +int SDL_JoystickNumButtons(SDL_Joystick *joystick) +{ + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + return(joystick->nbuttons); +} + +/* + * Get the current state of an axis control on a joystick + */ +Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis) +{ + Sint16 state; + + if ( ! ValidJoystick(&joystick) ) { + return(0); + } + if ( axis < joystick->naxes ) { + state = joystick->axes[axis]; + } else { + SDL_SetError("Joystick only has %d axes", joystick->naxes); + state = 0; + } + return(state); +} + +/* + * Get the current state of a hat on a joystick + */ +Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat) +{ + Uint8 state; + + if ( ! ValidJoystick(&joystick) ) { + return(0); + } + if ( hat < joystick->nhats ) { + state = joystick->hats[hat]; + } else { + SDL_SetError("Joystick only has %d hats", joystick->nhats); + state = 0; + } + return(state); +} + +/* + * Get the ball axis change since the last poll + */ +int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy) +{ + int retval; + + if ( ! ValidJoystick(&joystick) ) { + return(-1); + } + + retval = 0; + if ( ball < joystick->nballs ) { + if ( dx ) { + *dx = joystick->balls[ball].dx; + } + if ( dy ) { + *dy = joystick->balls[ball].dy; + } + joystick->balls[ball].dx = 0; + joystick->balls[ball].dy = 0; + } else { + SDL_SetError("Joystick only has %d balls", joystick->nballs); + retval = -1; + } + return(retval); +} + +/* + * Get the current state of a button on a joystick + */ +Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button) +{ + Uint8 state; + + if ( ! ValidJoystick(&joystick) ) { + return(0); + } + if ( button < joystick->nbuttons ) { + state = joystick->buttons[button]; + } else { + SDL_SetError("Joystick only has %d buttons",joystick->nbuttons); + state = 0; + } + return(state); +} + +/* + * Close a joystick previously opened with SDL_JoystickOpen() + */ +void SDL_JoystickClose(SDL_Joystick *joystick) +{ + int i; + + if ( ! ValidJoystick(&joystick) ) { + return; + } + + /* First decrement ref count */ + if ( --joystick->ref_count > 0 ) { + return; + } + + /* Lock the event queue - prevent joystick polling */ + SDL_Lock_EventThread(); + + SDL_SYS_JoystickClose(joystick); + + /* Remove joystick from list */ + for ( i=0; SDL_joysticks[i]; ++i ) { + if ( joystick == SDL_joysticks[i] ) { + SDL_memmove(&SDL_joysticks[i], &SDL_joysticks[i+1], + (SDL_allocatedjoysticks-i)*sizeof(joystick)); + break; + } + } + + /* Let the event thread keep running */ + SDL_Unlock_EventThread(); + + /* Free the data associated with this joystick */ + if ( joystick->axes ) { + SDL_free(joystick->axes); + } + if ( joystick->hats ) { + SDL_free(joystick->hats); + } + if ( joystick->balls ) { + SDL_free(joystick->balls); + } + if ( joystick->buttons ) { + SDL_free(joystick->buttons); + } + SDL_free(joystick); +} + +void SDL_JoystickQuit(void) +{ + const int numsticks = SDL_numjoysticks; + int i; + + /* Stop the event polling */ + SDL_Lock_EventThread(); + SDL_numjoysticks = 0; + SDL_Unlock_EventThread(); + + if (SDL_joysticks != NULL) { + for (i = 0; i < numsticks; i++) { + SDL_Joystick *stick = SDL_joysticks[i]; + if (stick && (stick->ref_count >= 1)) { + stick->ref_count = 1; + SDL_JoystickClose(stick); + } + } + } + + /* Quit the joystick setup */ + SDL_SYS_JoystickQuit(); + if ( SDL_joysticks ) { + SDL_free(SDL_joysticks); + SDL_joysticks = NULL; + SDL_allocatedjoysticks = 0; + } +} + + +/* These are global for SDL_sysjoystick.c and SDL_events.c */ + +int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value) +{ + int posted; + + /* Make sure we're not getting garbage events */ + if (axis >= joystick->naxes) { + return 0; + } + + /* Update internal joystick state */ + joystick->axes[axis] = value; + + /* Post the event, if desired */ + posted = 0; +#if !SDL_EVENTS_DISABLED + if ( SDL_ProcessEvents[SDL_JOYAXISMOTION] == SDL_ENABLE ) { + SDL_Event event; + event.type = SDL_JOYAXISMOTION; + event.jaxis.which = joystick->index; + event.jaxis.axis = axis; + event.jaxis.value = value; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } +#endif /* !SDL_EVENTS_DISABLED */ + return(posted); +} + +int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value) +{ + int posted; + + /* Make sure we're not getting garbage events */ + if (hat >= joystick->nhats) { + return 0; + } + + /* Update internal joystick state */ + joystick->hats[hat] = value; + + /* Post the event, if desired */ + posted = 0; +#if !SDL_EVENTS_DISABLED + if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) { + SDL_Event event; + event.jhat.type = SDL_JOYHATMOTION; + event.jhat.which = joystick->index; + event.jhat.hat = hat; + event.jhat.value = value; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } +#endif /* !SDL_EVENTS_DISABLED */ + return(posted); +} + +int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, + Sint16 xrel, Sint16 yrel) +{ + int posted; + + /* Make sure we're not getting garbage events */ + if (ball >= joystick->nballs) { + return 0; + } + + /* Update internal mouse state */ + joystick->balls[ball].dx += xrel; + joystick->balls[ball].dy += yrel; + + /* Post the event, if desired */ + posted = 0; +#if !SDL_EVENTS_DISABLED + if ( SDL_ProcessEvents[SDL_JOYBALLMOTION] == SDL_ENABLE ) { + SDL_Event event; + event.jball.type = SDL_JOYBALLMOTION; + event.jball.which = joystick->index; + event.jball.ball = ball; + event.jball.xrel = xrel; + event.jball.yrel = yrel; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } +#endif /* !SDL_EVENTS_DISABLED */ + return(posted); +} + +int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state) +{ + int posted; +#if !SDL_EVENTS_DISABLED + SDL_Event event; + + switch ( state ) { + case SDL_PRESSED: + event.type = SDL_JOYBUTTONDOWN; + break; + case SDL_RELEASED: + event.type = SDL_JOYBUTTONUP; + break; + default: + /* Invalid state -- bail */ + return(0); + } +#endif /* !SDL_EVENTS_DISABLED */ + + /* Make sure we're not getting garbage events */ + if (button >= joystick->nbuttons) { + return 0; + } + + /* Update internal joystick state */ + joystick->buttons[button] = state; + + /* Post the event, if desired */ + posted = 0; +#if !SDL_EVENTS_DISABLED + if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) { + event.jbutton.which = joystick->index; + event.jbutton.button = button; + event.jbutton.state = state; + if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { + posted = 1; + SDL_PushEvent(&event); + } + } +#endif /* !SDL_EVENTS_DISABLED */ + return(posted); +} + +void SDL_JoystickUpdate(void) +{ + int i; + + for ( i=0; SDL_joysticks[i]; ++i ) { + SDL_SYS_JoystickUpdate(SDL_joysticks[i]); + } +} + +int SDL_JoystickEventState(int state) +{ +#if SDL_EVENTS_DISABLED + return SDL_IGNORE; +#else + const Uint8 event_list[] = { + SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, + SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, + }; + unsigned int i; + + switch (state) { + case SDL_QUERY: + state = SDL_IGNORE; + for ( i=0; i<SDL_arraysize(event_list); ++i ) { + state = SDL_EventState(event_list[i],SDL_QUERY); + if ( state == SDL_ENABLE ) { + break; + } + } + break; + default: + for ( i=0; i<SDL_arraysize(event_list); ++i ) { + SDL_EventState(event_list[i], state); + } + break; + } + return(state); +#endif /* SDL_EVENTS_DISABLED */ +} diff --git a/3rdparty/SDL/src/joystick/SDL_joystick_c.h b/3rdparty/SDL/src/joystick/SDL_joystick_c.h new file mode 100644 index 0000000..9a9d130 --- /dev/null +++ b/3rdparty/SDL/src/joystick/SDL_joystick_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_joystick.c */ +#include "SDL_joystick.h" + +/* The number of available joysticks on the system */ +extern Uint8 SDL_numjoysticks; + +/* Internal event queueing functions */ +extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, + Uint8 axis, Sint16 value); +extern int SDL_PrivateJoystickBall(SDL_Joystick *joystick, + Uint8 ball, Sint16 xrel, Sint16 yrel); +extern int SDL_PrivateJoystickHat(SDL_Joystick *joystick, + Uint8 hat, Uint8 value); +extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick, + Uint8 button, Uint8 state); diff --git a/3rdparty/SDL/src/joystick/SDL_sysjoystick.h b/3rdparty/SDL/src/joystick/SDL_sysjoystick.h new file mode 100644 index 0000000..6a1b76a --- /dev/null +++ b/3rdparty/SDL/src/joystick/SDL_sysjoystick.h @@ -0,0 +1,82 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is SDL_free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the system specific header for the SDL joystick API */ + +#include "SDL_joystick.h" + +/* The SDL joystick structure */ +struct _SDL_Joystick { + Uint8 index; /* Device index */ + const char *name; /* Joystick name - system dependent */ + + int naxes; /* Number of axis controls on the joystick */ + Sint16 *axes; /* Current axis states */ + + int nhats; /* Number of hats on the joystick */ + Uint8 *hats; /* Current hat states */ + + int nballs; /* Number of trackballs on the joystick */ + struct balldelta { + int dx; + int dy; + } *balls; /* Current ball motion deltas */ + + int nbuttons; /* Number of buttons on the joystick */ + Uint8 *buttons; /* Current button states */ + + struct joystick_hwdata *hwdata; /* Driver dependent information */ + + int ref_count; /* Reference count for multiple opens */ +}; + +/* Function to scan the system for joysticks. + * Joystick 0 should be the system default joystick. + * This function should return the number of available joysticks, or -1 + * on an unrecoverable fatal error. + */ +extern int SDL_SYS_JoystickInit(void); + +/* Function to get the device-dependent name of a joystick */ +extern const char *SDL_SYS_JoystickName(int index); + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +extern int SDL_SYS_JoystickOpen(SDL_Joystick *joystick); + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +extern void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick); + +/* Function to close a joystick after use */ +extern void SDL_SYS_JoystickClose(SDL_Joystick *joystick); + +/* Function to perform any system-specific joystick related cleanup */ +extern void SDL_SYS_JoystickQuit(void); + diff --git a/3rdparty/SDL/src/joystick/beos/SDL_bejoystick.cc b/3rdparty/SDL/src/joystick/beos/SDL_bejoystick.cc new file mode 100644 index 0000000..af8a341 --- /dev/null +++ b/3rdparty/SDL/src/joystick/beos/SDL_bejoystick.cc @@ -0,0 +1,237 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_BEOS + +/* This is the system specific header for the SDL joystick API */ + +#include <be/support/String.h> +#include <be/device/Joystick.h> + +extern "C" { + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + + +/* The maximum number of joysticks we'll detect */ +#define MAX_JOYSTICKS 16 + +/* A list of available joysticks */ +static char *SDL_joyport[MAX_JOYSTICKS]; +static char *SDL_joyname[MAX_JOYSTICKS]; + +/* The private structure used to keep track of a joystick */ +struct joystick_hwdata { + BJoystick *stick; + uint8 *new_hats; + int16 *new_axes; +}; + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + BJoystick joystick; + int numjoysticks; + int i; + int32 nports; + char name[B_OS_NAME_LENGTH]; + + /* Search for attached joysticks */ + nports = joystick.CountDevices(); + numjoysticks = 0; + SDL_memset(SDL_joyport, 0, (sizeof SDL_joyport)); + SDL_memset(SDL_joyname, 0, (sizeof SDL_joyname)); + for ( i=0; (SDL_numjoysticks < MAX_JOYSTICKS) && (i < nports); ++i ) { + if ( joystick.GetDeviceName(i, name) == B_OK ) { + if ( joystick.Open(name) != B_ERROR ) { + BString stick_name; + joystick.GetControllerName(&stick_name); + SDL_joyport[numjoysticks] = strdup(name); + SDL_joyname[numjoysticks] = + strdup(stick_name.String()); + numjoysticks++; + joystick.Close(); + } + } + } + return(numjoysticks); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + return SDL_joyname[index]; +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + BJoystick *stick; + + /* Create the joystick data structure */ + joystick->hwdata = (struct joystick_hwdata *) + SDL_malloc(sizeof(*joystick->hwdata)); + if ( joystick->hwdata == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + stick = new BJoystick; + joystick->hwdata->stick = stick; + + /* Open the requested joystick for use */ + if ( stick->Open(SDL_joyport[joystick->index]) == B_ERROR ) { + SDL_SetError("Unable to open joystick"); + SDL_SYS_JoystickClose(joystick); + return(-1); + } + + /* Set the joystick to calibrated mode */ + stick->EnableCalibration(); + + /* Get the number of buttons, hats, and axes on the joystick */ + joystick->nbuttons = stick->CountButtons(); + joystick->naxes = stick->CountAxes(); + joystick->nhats = stick->CountHats(); + + joystick->hwdata->new_axes = (int16 *) + SDL_malloc(joystick->naxes*sizeof(int16)); + joystick->hwdata->new_hats = (uint8 *) + SDL_malloc(joystick->nhats*sizeof(uint8)); + if ( ! joystick->hwdata->new_hats || ! joystick->hwdata->new_axes ) { + SDL_OutOfMemory(); + SDL_SYS_JoystickClose(joystick); + return(-1); + } + + /* We're done! */ + return(0); +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + static const Uint8 hat_map[9] = { + SDL_HAT_CENTERED, + SDL_HAT_UP, + SDL_HAT_RIGHTUP, + SDL_HAT_RIGHT, + SDL_HAT_RIGHTDOWN, + SDL_HAT_DOWN, + SDL_HAT_LEFTDOWN, + SDL_HAT_LEFT, + SDL_HAT_LEFTUP + }; + const int JITTER = (32768/10); /* 10% jitter threshold (ok?) */ + + BJoystick *stick; + int i, change; + int16 *axes; + uint8 *hats; + uint32 buttons; + + /* Set up data pointers */ + stick = joystick->hwdata->stick; + axes = joystick->hwdata->new_axes; + hats = joystick->hwdata->new_hats; + + /* Get the new joystick state */ + stick->Update(); + stick->GetAxisValues(axes); + stick->GetHatValues(hats); + buttons = stick->ButtonValues(); + + /* Generate axis motion events */ + for ( i=0; i<joystick->naxes; ++i ) { + change = ((int32)axes[i] - joystick->axes[i]); + if ( (change > JITTER) || (change < -JITTER) ) { + SDL_PrivateJoystickAxis(joystick, i, axes[i]); + } + } + + /* Generate hat change events */ + for ( i=0; i<joystick->nhats; ++i ) { + if ( hats[i] != joystick->hats[i] ) { + SDL_PrivateJoystickHat(joystick, i, hat_map[hats[i]]); + } + } + + /* Generate button events */ + for ( i=0; i<joystick->nbuttons; ++i ) { + if ( (buttons&0x01) != joystick->buttons[i] ) { + SDL_PrivateJoystickButton(joystick, i, (buttons&0x01)); + } + buttons >>= 1; + } +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + if ( joystick->hwdata ) { + joystick->hwdata->stick->Close(); + delete joystick->hwdata->stick; + if ( joystick->hwdata->new_hats ) { + SDL_free(joystick->hwdata->new_hats); + } + if ( joystick->hwdata->new_axes ) { + SDL_free(joystick->hwdata->new_axes); + } + SDL_free(joystick->hwdata); + joystick->hwdata = NULL; + } +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + int i; + + for ( i=0; SDL_joyport[i]; ++i ) { + SDL_free(SDL_joyport[i]); + } + SDL_joyport[0] = NULL; + + for ( i=0; SDL_joyname[i]; ++i ) { + SDL_free(SDL_joyname[i]); + } + SDL_joyname[0] = NULL; +} + +}; // extern "C" + +#endif /* SDL_JOYSTICK_BEOS */ diff --git a/3rdparty/SDL/src/joystick/bsd/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/bsd/SDL_sysjoystick.c new file mode 100644 index 0000000..500fc62 --- /dev/null +++ b/3rdparty/SDL/src/joystick/bsd/SDL_sysjoystick.c @@ -0,0 +1,608 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_USBHID + +/* + * Joystick driver for the uhid(4) interface found in OpenBSD, + * NetBSD and FreeBSD. + * + * Maintainer: <vedge at csoft.org> + */ + +#include <sys/param.h> + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#ifndef __FreeBSD_kernel_version +#define __FreeBSD_kernel_version __FreeBSD_version +#endif + +#if defined(HAVE_USB_H) +#include <usb.h> +#endif +#ifdef __DragonFly__ +#include <bus/usb/usb.h> +#include <bus/usb/usbhid.h> +#else +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> +#endif + +#if defined(HAVE_USBHID_H) +#include <usbhid.h> +#elif defined(HAVE_LIBUSB_H) +#include <libusb.h> +#elif defined(HAVE_LIBUSBHID_H) +#include <libusbhid.h> +#endif + +#if defined(__FREEBSD__) || defined(__FreeBSD_kernel__) +#ifndef __DragonFly__ +#include <osreldate.h> +#endif +#if __FreeBSD_kernel_version > 800063 +#include <dev/usb/usb_ioctl.h> +#endif +#include <sys/joystick.h> +#endif + +#if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H +#include <machine/joystick.h> +#endif + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#define MAX_UHID_JOYS 4 +#define MAX_JOY_JOYS 2 +#define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) + +struct report { +#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) + struct usb_gen_descriptor *buf; /* Buffer */ +#else + struct usb_ctl_report *buf; /* Buffer */ +#endif + size_t size; /* Buffer size */ + int rid; /* Report ID */ + enum { + SREPORT_UNINIT, + SREPORT_CLEAN, + SREPORT_DIRTY + } status; +}; + +static struct { + int uhid_report; + hid_kind_t kind; + const char *name; +} const repinfo[] = { + { UHID_INPUT_REPORT, hid_input, "input" }, + { UHID_OUTPUT_REPORT, hid_output, "output" }, + { UHID_FEATURE_REPORT, hid_feature, "feature" } +}; + +enum { + REPORT_INPUT = 0, + REPORT_OUTPUT = 1, + REPORT_FEATURE = 2 +}; + +enum { + JOYAXE_X, + JOYAXE_Y, + JOYAXE_Z, + JOYAXE_SLIDER, + JOYAXE_WHEEL, + JOYAXE_RX, + JOYAXE_RY, + JOYAXE_RZ, + JOYAXE_count +}; + +struct joystick_hwdata { + int fd; + char *path; + enum { + BSDJOY_UHID, /* uhid(4) */ + BSDJOY_JOY /* joy(4) */ + } type; + struct report_desc *repdesc; + struct report inreport; + int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,..*/ + int x; + int y; + int xmin; + int ymin; + int xmax; + int ymax; +}; + +static char *joynames[MAX_JOYS]; +static char *joydevnames[MAX_JOYS]; + +static int report_alloc(struct report *, struct report_desc *, int); +static void report_free(struct report *); + +#if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) +#define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) +#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) +#define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) +#else +#define REP_BUF_DATA(rep) ((rep)->buf->data) +#endif + +int +SDL_SYS_JoystickInit(void) +{ + char s[16]; + int i, fd; + + SDL_numjoysticks = 0; + + SDL_memset(joynames, 0, sizeof(joynames)); + SDL_memset(joydevnames, 0, sizeof(joydevnames)); + + for (i = 0; i < MAX_UHID_JOYS; i++) { + SDL_Joystick nj; + + SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i); + + nj.index = SDL_numjoysticks; + joynames[nj.index] = strdup(s); + + if (SDL_SYS_JoystickOpen(&nj) == 0) { + SDL_SYS_JoystickClose(&nj); + SDL_numjoysticks++; + } else { + SDL_free(joynames[nj.index]); + joynames[nj.index] = NULL; + } + } + for (i = 0; i < MAX_JOY_JOYS; i++) { + SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i); + fd = open(s, O_RDONLY); + if (fd != -1) { + joynames[SDL_numjoysticks++] = strdup(s); + close(fd); + } + } + + /* Read the default USB HID usage table. */ + hid_init(NULL); + + return (SDL_numjoysticks); +} + +const char * +SDL_SYS_JoystickName(int index) +{ + if (joydevnames[index] != NULL) { + return (joydevnames[index]); + } + return (joynames[index]); +} + +static int +usage_to_joyaxe(unsigned usage) +{ + int joyaxe; + switch (usage) { + case HUG_X: + joyaxe = JOYAXE_X; break; + case HUG_Y: + joyaxe = JOYAXE_Y; break; + case HUG_Z: + joyaxe = JOYAXE_Z; break; + case HUG_SLIDER: + joyaxe = JOYAXE_SLIDER; break; + case HUG_WHEEL: + joyaxe = JOYAXE_WHEEL; break; + case HUG_RX: + joyaxe = JOYAXE_RX; break; + case HUG_RY: + joyaxe = JOYAXE_RY; break; + case HUG_RZ: + joyaxe = JOYAXE_RZ; break; + default: + joyaxe = -1; + } + return joyaxe; +} + +static unsigned +hatval_to_sdl(Sint32 hatval) +{ + static const unsigned hat_dir_map[8] = { + SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN, + SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP + }; + unsigned result; + if ((hatval & 7) == hatval) + result = hat_dir_map[hatval]; + else + result = SDL_HAT_CENTERED; + return result; +} + + +int +SDL_SYS_JoystickOpen(SDL_Joystick *joy) +{ + char *path = joynames[joy->index]; + struct joystick_hwdata *hw; + struct hid_item hitem; + struct hid_data *hdata; + struct report *rep; + int fd; + int i; + + fd = open(path, O_RDONLY); + if (fd == -1) { + SDL_SetError("%s: %s", path, strerror(errno)); + return (-1); + } + + hw = (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata)); + if (hw == NULL) { + SDL_OutOfMemory(); + close(fd); + return (-1); + } + joy->hwdata = hw; + hw->fd = fd; + hw->path = strdup(path); + hw->x = 0; + hw->y = 0; + hw->xmin = 0xffff; + hw->ymin = 0xffff; + hw->xmax = 0; + hw->ymax = 0; + if (! SDL_strncmp(path, "/dev/joy", 8)) { + hw->type = BSDJOY_JOY; + joy->naxes = 2; + joy->nbuttons = 2; + joy->nhats = 0; + joy->nballs = 0; + joydevnames[joy->index] = strdup("Gameport joystick"); + goto usbend; + } else { + hw->type = BSDJOY_UHID; + } + + { + int ax; + for (ax = 0; ax < JOYAXE_count; ax++) + hw->axis_map[ax] = -1; + } + hw->repdesc = hid_get_report_desc(fd); + if (hw->repdesc == NULL) { + SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path, + strerror(errno)); + goto usberr; + } + rep = &hw->inreport; +#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) + rep->rid = hid_get_report_id(fd); + if (rep->rid < 0) { +#else + if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) { +#endif + rep->rid = -1; /* XXX */ + } + if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) { + goto usberr; + } + if (rep->size <= 0) { + SDL_SetError("%s: Input report descriptor has invalid length", + hw->path); + goto usberr; + } + +#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) + hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid); +#else + hdata = hid_start_parse(hw->repdesc, 1 << hid_input); +#endif + if (hdata == NULL) { + SDL_SetError("%s: Cannot start HID parser", hw->path); + goto usberr; + } + joy->naxes = 0; + joy->nbuttons = 0; + joy->nhats = 0; + joy->nballs = 0; + for (i=0; i<JOYAXE_count; i++) + hw->axis_map[i] = -1; + + while (hid_get_item(hdata, &hitem) > 0) { + char *sp; + const char *s; + + switch (hitem.kind) { + case hid_collection: + switch (HID_PAGE(hitem.usage)) { + case HUP_GENERIC_DESKTOP: + switch (HID_USAGE(hitem.usage)) { + case HUG_JOYSTICK: + case HUG_GAME_PAD: + s = hid_usage_in_page(hitem.usage); + sp = SDL_malloc(SDL_strlen(s) + 5); + SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)", s, + joy->index); + joydevnames[joy->index] = sp; + } + } + break; + case hid_input: + switch (HID_PAGE(hitem.usage)) { + case HUP_GENERIC_DESKTOP: { + unsigned usage = HID_USAGE(hitem.usage); + int joyaxe = usage_to_joyaxe(usage); + if (joyaxe >= 0) { + hw->axis_map[joyaxe] = 1; + } else if (usage == HUG_HAT_SWITCH) { + joy->nhats++; + } + break; + } + case HUP_BUTTON: + joy->nbuttons++; + break; + default: + break; + } + break; + default: + break; + } + } + hid_end_parse(hdata); + for (i=0; i<JOYAXE_count; i++) + if (hw->axis_map[i] > 0) + hw->axis_map[i] = joy->naxes++; + +usbend: + /* The poll blocks the event thread. */ + fcntl(fd, F_SETFL, O_NONBLOCK); + + return (0); +usberr: + close(hw->fd); + SDL_free(hw->path); + SDL_free(hw); + return (-1); +} + +void +SDL_SYS_JoystickUpdate(SDL_Joystick *joy) +{ + struct hid_item hitem; + struct hid_data *hdata; + struct report *rep; + int nbutton, naxe = -1; + Sint32 v; + +#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) + struct joystick gameport; + + if (joy->hwdata->type == BSDJOY_JOY) { + if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport) + return; + if (abs(joy->hwdata->x - gameport.x) > 8) { + joy->hwdata->x = gameport.x; + if (joy->hwdata->x < joy->hwdata->xmin) { + joy->hwdata->xmin = joy->hwdata->x; + } + if (joy->hwdata->x > joy->hwdata->xmax) { + joy->hwdata->xmax = joy->hwdata->x; + } + if (joy->hwdata->xmin == joy->hwdata->xmax) { + joy->hwdata->xmin--; + joy->hwdata->xmax++; + } + v = (Sint32)joy->hwdata->x; + v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2; + v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2); + SDL_PrivateJoystickAxis(joy, 0, v); + } + if (abs(joy->hwdata->y - gameport.y) > 8) { + joy->hwdata->y = gameport.y; + if (joy->hwdata->y < joy->hwdata->ymin) { + joy->hwdata->ymin = joy->hwdata->y; + } + if (joy->hwdata->y > joy->hwdata->ymax) { + joy->hwdata->ymax = joy->hwdata->y; + } + if (joy->hwdata->ymin == joy->hwdata->ymax) { + joy->hwdata->ymin--; + joy->hwdata->ymax++; + } + v = (Sint32)joy->hwdata->y; + v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2; + v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2); + SDL_PrivateJoystickAxis(joy, 1, v); + } + if (gameport.b1 != joy->buttons[0]) { + SDL_PrivateJoystickButton(joy, 0, gameport.b1); + } + if (gameport.b2 != joy->buttons[1]) { + SDL_PrivateJoystickButton(joy, 1, gameport.b2); + } + return; + } +#endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */ + + rep = &joy->hwdata->inreport; + + if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) { + return; + } +#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); +#else + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); +#endif + if (hdata == NULL) { + fprintf(stderr, "%s: Cannot start HID parser\n", + joy->hwdata->path); + return; + } + + for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { + switch (hitem.kind) { + case hid_input: + switch (HID_PAGE(hitem.usage)) { + case HUP_GENERIC_DESKTOP: { + unsigned usage = HID_USAGE(hitem.usage); + int joyaxe = usage_to_joyaxe(usage); + if (joyaxe >= 0) { + naxe = joy->hwdata->axis_map[joyaxe]; + /* scaleaxe */ + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), + &hitem); + v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; + v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); + if (v != joy->axes[naxe]) { + SDL_PrivateJoystickAxis(joy, naxe, v); + } + } else if (usage == HUG_HAT_SWITCH) { + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), + &hitem); + SDL_PrivateJoystickHat(joy, 0, + hatval_to_sdl(v)-hitem.logical_minimum); + } + break; + } + case HUP_BUTTON: + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), + &hitem); + if (joy->buttons[nbutton] != v) { + SDL_PrivateJoystickButton(joy, + nbutton, v); + } + nbutton++; + break; + default: + continue; + } + break; + default: + break; + } + } + hid_end_parse(hdata); + + return; +} + +/* Function to close a joystick after use */ +void +SDL_SYS_JoystickClose(SDL_Joystick *joy) +{ + if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) { + report_free(&joy->hwdata->inreport); + hid_dispose_report_desc(joy->hwdata->repdesc); + } + close(joy->hwdata->fd); + SDL_free(joy->hwdata->path); + SDL_free(joy->hwdata); + + return; +} + +void +SDL_SYS_JoystickQuit(void) +{ + int i; + + for (i = 0; i < MAX_JOYS; i++) { + if (joynames[i] != NULL) + SDL_free(joynames[i]); + if (joydevnames[i] != NULL) + SDL_free(joydevnames[i]); + } + + return; +} + +static int +report_alloc(struct report *r, struct report_desc *rd, int repind) +{ + int len; + +#ifdef __DragonFly__ + len = hid_report_size(rd, r->rid, repinfo[repind].kind); +#elif __FREEBSD__ +# if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) +# if (__FreeBSD_kernel_version <= 500111) + len = hid_report_size(rd, r->rid, repinfo[repind].kind); +# else + len = hid_report_size(rd, repinfo[repind].kind, r->rid); +# endif +# else + len = hid_report_size(rd, repinfo[repind].kind, &r->rid); +# endif +#else +# ifdef USBHID_NEW + len = hid_report_size(rd, repinfo[repind].kind, r->rid); +# else + len = hid_report_size(rd, repinfo[repind].kind, &r->rid); +# endif +#endif + + if (len < 0) { + SDL_SetError("Negative HID report size"); + return (-1); + } + r->size = len; + + if (r->size > 0) { + r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + + r->size); + if (r->buf == NULL) { + SDL_OutOfMemory(); + return (-1); + } + } else { + r->buf = NULL; + } + + r->status = SREPORT_CLEAN; + return (0); +} + +static void +report_free(struct report *r) +{ + if (r->buf != NULL) { + SDL_free(r->buf); + } + r->status = SREPORT_UNINIT; +} + +#endif /* SDL_JOYSTICK_USBHID */ diff --git a/3rdparty/SDL/src/joystick/darwin/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/darwin/SDL_sysjoystick.c new file mode 100644 index 0000000..a9ccb35 --- /dev/null +++ b/3rdparty/SDL/src/joystick/darwin/SDL_sysjoystick.c @@ -0,0 +1,842 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_IOKIT + +/* SDL joystick driver for Darwin / Mac OS X, based on the IOKit HID API */ +/* Written 2001 by Max Horn */ + +#include <unistd.h> +#include <ctype.h> +#include <sysexits.h> +#include <mach/mach.h> +#include <mach/mach_error.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOCFPlugIn.h> +#ifdef MACOS_10_0_4 +#include <IOKit/hidsystem/IOHIDUsageTables.h> +#else +/* The header was moved here in Mac OS X 10.1 */ +#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h> +#endif +#include <IOKit/hid/IOHIDLib.h> +#include <IOKit/hid/IOHIDKeys.h> +#include <CoreFoundation/CoreFoundation.h> +#include <Carbon/Carbon.h> /* for NewPtrClear, DisposePtr */ + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +struct recElement +{ + IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */ + long min; /* reported min value possible */ + long max; /* reported max value possible */ +#if 0 + /* TODO: maybe should handle the following stuff somehow? */ + + long scaledMin; /* reported scaled min value possible */ + long scaledMax; /* reported scaled max value possible */ + long size; /* size in bits of data return from element */ + Boolean relative; /* are reports relative to last report (deltas) */ + Boolean wrapping; /* does element wrap around (one value higher than max is min) */ + Boolean nonLinear; /* are the values reported non-linear relative to element movement */ + Boolean preferredState; /* does element have a preferred state (such as a button) */ + Boolean nullState; /* does element have null state */ +#endif /* 0 */ + + /* runtime variables used for auto-calibration */ + long minReport; /* min returned value */ + long maxReport; /* max returned value */ + + struct recElement * pNext; /* next element in list */ +}; +typedef struct recElement recElement; + +struct joystick_hwdata +{ + IOHIDDeviceInterface ** interface; /* interface to device, NULL = no interface */ + + char product[256]; /* name of product */ + long usage; /* usage page from IOUSBHID Parser.h which defines general usage */ + long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ + + long axes; /* number of axis (calculated, not reported by device) */ + long buttons; /* number of buttons (calculated, not reported by device) */ + long hats; /* number of hat switches (calculated, not reported by device) */ + long elements; /* number of total elements (shouldbe total of above) (calculated, not reported by device) */ + + recElement* firstAxis; + recElement* firstButton; + recElement* firstHat; + + int removed; + int uncentered; + + struct joystick_hwdata* pNext; /* next device */ +}; +typedef struct joystick_hwdata recDevice; + + +/* Linked list of all available devices */ +static recDevice *gpDeviceList = NULL; + + +static void HIDReportErrorNum (char * strError, long numError) +{ + SDL_SetError(strError); +} + +static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice); + +/* returns current value for element, polling element + * will return 0 on error conditions which should be accounted for by application + */ + +static SInt32 HIDGetElementValue (recDevice *pDevice, recElement *pElement) +{ + IOReturn result = kIOReturnSuccess; + IOHIDEventStruct hidEvent; + hidEvent.value = 0; + + if (NULL != pDevice && NULL != pElement && NULL != pDevice->interface) + { + result = (*(pDevice->interface))->getElementValue(pDevice->interface, pElement->cookie, &hidEvent); + if (kIOReturnSuccess == result) + { + /* record min and max for auto calibration */ + if (hidEvent.value < pElement->minReport) + pElement->minReport = hidEvent.value; + if (hidEvent.value > pElement->maxReport) + pElement->maxReport = hidEvent.value; + } + } + + /* auto user scale */ + return hidEvent.value; +} + +static SInt32 HIDScaledCalibratedValue (recDevice *pDevice, recElement *pElement, long min, long max) +{ + float deviceScale = max - min; + float readScale = pElement->maxReport - pElement->minReport; + SInt32 value = HIDGetElementValue(pDevice, pElement); + if (readScale == 0) + return value; /* no scaling at all */ + else + return ((value - pElement->minReport) * deviceScale / readScale) + min; +} + + +static void HIDRemovalCallback(void * target, + IOReturn result, + void * refcon, + void * sender) +{ + recDevice *device = (recDevice *) refcon; + device->removed = 1; + device->uncentered = 1; +} + + + +/* Create and open an interface to device, required prior to extracting values or building queues. + * Note: appliction now owns the device and must close and release it prior to exiting + */ + +static IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, recDevice *pDevice) +{ + IOReturn result = kIOReturnSuccess; + HRESULT plugInResult = S_OK; + SInt32 score = 0; + IOCFPlugInInterface ** ppPlugInInterface = NULL; + + if (NULL == pDevice->interface) + { + result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &ppPlugInInterface, &score); + if (kIOReturnSuccess == result) + { + /* Call a method of the intermediate plug-in to create the device interface */ + plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface, + CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface)); + if (S_OK != plugInResult) + HIDReportErrorNum ("Couldnt query HID class device interface from plugInInterface", plugInResult); + (*ppPlugInInterface)->Release (ppPlugInInterface); + } + else + HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result); + } + if (NULL != pDevice->interface) + { + result = (*(pDevice->interface))->open (pDevice->interface, 0); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("Failed to open pDevice->interface via open.", result); + else + (*(pDevice->interface))->setRemovalCallback (pDevice->interface, HIDRemovalCallback, pDevice, pDevice); + + } + return result; +} + +/* Closes and releases interface to device, should be done prior to exting application + * Note: will have no affect if device or interface do not exist + * application will "own" the device if interface is not closed + * (device may have to be plug and re-plugged in different location to get it working again without a restart) + */ + +static IOReturn HIDCloseReleaseInterface (recDevice *pDevice) +{ + IOReturn result = kIOReturnSuccess; + + if ((NULL != pDevice) && (NULL != pDevice->interface)) + { + /* close the interface */ + result = (*(pDevice->interface))->close (pDevice->interface); + if (kIOReturnNotOpen == result) + { + /* do nothing as device was not opened, thus can't be closed */ + } + else if (kIOReturnSuccess != result) + HIDReportErrorNum ("Failed to close IOHIDDeviceInterface.", result); + /* release the interface */ + result = (*(pDevice->interface))->Release (pDevice->interface); + if (kIOReturnSuccess != result) + HIDReportErrorNum ("Failed to release IOHIDDeviceInterface.", result); + pDevice->interface = NULL; + } + return result; +} + +/* extracts actual specific element information from each element CF dictionary entry */ + +static void HIDGetElementInfo (CFTypeRef refElement, recElement *pElement) +{ + long number; + CFTypeRef refType; + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->cookie = (IOHIDElementCookie) number; + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->minReport = pElement->min = number; + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->maxReport = pElement->max = number; +/* + TODO: maybe should handle the following stuff somehow? + + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->scaledMin = number; + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->scaledMax = number; + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); + if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) + pElement->size = number; + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); + if (refType) + pElement->relative = CFBooleanGetValue (refType); + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); + if (refType) + pElement->wrapping = CFBooleanGetValue (refType); + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); + if (refType) + pElement->nonLinear = CFBooleanGetValue (refType); + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); + if (refType) + pElement->preferredState = CFBooleanGetValue (refType); + refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); + if (refType) + pElement->nullState = CFBooleanGetValue (refType); +*/ +} + +/* examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements + * if element of interest allocate storage, add to list and retrieve element specific info + * if collection then pass on to deconstruction collection into additional individual elements + */ + +static void HIDAddElement (CFTypeRef refElement, recDevice* pDevice) +{ + recElement* element = NULL; + recElement** headElement = NULL; + long elementType, usagePage, usage; + CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey)); + CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey)); + CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey)); + + + if ((refElementType) && (CFNumberGetValue (refElementType, kCFNumberLongType, &elementType))) + { + /* look at types of interest */ + if ((elementType == kIOHIDElementTypeInput_Misc) || (elementType == kIOHIDElementTypeInput_Button) || + (elementType == kIOHIDElementTypeInput_Axis)) + { + if (refUsagePage && CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage) && + refUsage && CFNumberGetValue (refUsage, kCFNumberLongType, &usage)) + { + switch (usagePage) /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ + { + case kHIDPage_GenericDesktop: + { + switch (usage) /* look at usage to determine function */ + { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: + case kHIDUsage_GD_Dial: + case kHIDUsage_GD_Wheel: + element = (recElement *) NewPtrClear (sizeof (recElement)); + if (element) + { + pDevice->axes++; + headElement = &(pDevice->firstAxis); + } + break; + case kHIDUsage_GD_Hatswitch: + element = (recElement *) NewPtrClear (sizeof (recElement)); + if (element) + { + pDevice->hats++; + headElement = &(pDevice->firstHat); + } + break; + } + } + break; + case kHIDPage_Button: + element = (recElement *) NewPtrClear (sizeof (recElement)); + if (element) + { + pDevice->buttons++; + headElement = &(pDevice->firstButton); + } + break; + default: + break; + } + } + } + else if (kIOHIDElementTypeCollection == elementType) + HIDGetCollectionElements ((CFMutableDictionaryRef) refElement, pDevice); + } + + if (element && headElement) /* add to list */ + { + pDevice->elements++; + if (NULL == *headElement) + *headElement = element; + else + { + recElement *elementPrevious, *elementCurrent; + elementCurrent = *headElement; + while (elementCurrent) + { + elementPrevious = elementCurrent; + elementCurrent = elementPrevious->pNext; + } + elementPrevious->pNext = element; + } + element->pNext = NULL; + HIDGetElementInfo (refElement, element); + } +} + +/* collects information from each array member in device element list (each array memeber = element) */ + +static void HIDGetElementsCFArrayHandler (const void * value, void * parameter) +{ + if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) + HIDAddElement ((CFTypeRef) value, (recDevice *) parameter); +} + +/* handles retrieval of element information from arrays of elements in device IO registry information */ + +static void HIDGetElements (CFTypeRef refElementCurrent, recDevice *pDevice) +{ + CFTypeID type = CFGetTypeID (refElementCurrent); + if (type == CFArrayGetTypeID()) /* if element is an array */ + { + CFRange range = {0, CFArrayGetCount (refElementCurrent)}; + /* CountElementsCFArrayHandler called for each array member */ + CFArrayApplyFunction (refElementCurrent, range, HIDGetElementsCFArrayHandler, pDevice); + } +} + +/* handles extracting element information from element collection CF types + * used from top level element decoding and hierarchy deconstruction to flatten device element list + */ + +static void HIDGetCollectionElements (CFMutableDictionaryRef deviceProperties, recDevice *pDevice) +{ + CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey)); + if (refElementTop) + HIDGetElements (refElementTop, pDevice); +} + +/* use top level element usage page and usage to discern device usage page and usage setting appropriate vlaues in device record */ + +static void HIDTopLevelElementHandler (const void * value, void * parameter) +{ + CFTypeRef refCF = 0; + if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) + return; + refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); + if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usagePage)) + SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); + if (!CFNumberGetValue (refCF, kCFNumberLongType, &((recDevice *) parameter)->usage)) + SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); +} + +/* extracts device info from CF dictionary records in IO registry */ + +static void HIDGetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, recDevice *pDevice) +{ + CFMutableDictionaryRef usbProperties = 0; + io_registry_entry_t parent1, parent2; + + /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + */ + if ((KERN_SUCCESS == IORegistryEntryGetParentEntry (hidDevice, kIOServicePlane, &parent1)) && + (KERN_SUCCESS == IORegistryEntryGetParentEntry (parent1, kIOServicePlane, &parent2)) && + (KERN_SUCCESS == IORegistryEntryCreateCFProperties (parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) + { + if (usbProperties) + { + CFTypeRef refCF = 0; + /* get device info + * try hid dictionary first, if fail then go to usb dictionary + */ + + + /* get product name */ + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); + if (!refCF) + refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); + if (refCF) + { + if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) + SDL_SetError ("CFStringGetCString error retrieving pDevice->product."); + } + + /* get usage page and usage */ + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) + { + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) + SDL_SetError ("CFNumberGetValue error retrieving pDevice->usagePage."); + refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) + if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) + SDL_SetError ("CFNumberGetValue error retrieving pDevice->usage."); + } + + if (NULL == refCF) /* get top level element HID usage page or usage */ + { + /* use top level element instead */ + CFTypeRef refCFTopElement = 0; + refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); + { + /* refCFTopElement points to an array of element dictionaries */ + CFRange range = {0, CFArrayGetCount (refCFTopElement)}; + CFArrayApplyFunction (refCFTopElement, range, HIDTopLevelElementHandler, pDevice); + } + } + + CFRelease (usbProperties); + } + else + SDL_SetError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); + + if (kIOReturnSuccess != IOObjectRelease (parent2)) + SDL_SetError ("IOObjectRelease error with parent2."); + if (kIOReturnSuccess != IOObjectRelease (parent1)) + SDL_SetError ("IOObjectRelease error with parent1."); + } +} + + +static recDevice *HIDBuildDevice (io_object_t hidDevice) +{ + recDevice *pDevice = (recDevice *) NewPtrClear (sizeof (recDevice)); + if (pDevice) + { + /* get dictionary for HID properties */ + CFMutableDictionaryRef hidProperties = 0; + kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions); + if ((result == KERN_SUCCESS) && hidProperties) + { + /* create device interface */ + result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); + if (kIOReturnSuccess == result) + { + HIDGetDeviceInfo (hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */ + HIDGetCollectionElements (hidProperties, pDevice); + } + else + { + DisposePtr((Ptr)pDevice); + pDevice = NULL; + } + CFRelease (hidProperties); + } + else + { + DisposePtr((Ptr)pDevice); + pDevice = NULL; + } + } + return pDevice; +} + +/* disposes of the element list associated with a device and the memory associated with the list + */ + +static void HIDDisposeElementList (recElement **elementList) +{ + recElement *pElement = *elementList; + while (pElement) + { + recElement *pElementNext = pElement->pNext; + DisposePtr ((Ptr) pElement); + pElement = pElementNext; + } + *elementList = NULL; +} + +/* disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL + * all your device no longer belong to us... (i.e., you do not 'own' the device anymore) + */ + +static recDevice *HIDDisposeDevice (recDevice **ppDevice) +{ + kern_return_t result = KERN_SUCCESS; + recDevice *pDeviceNext = NULL; + if (*ppDevice) + { + /* save next device prior to disposing of this device */ + pDeviceNext = (*ppDevice)->pNext; + + /* free element lists */ + HIDDisposeElementList (&(*ppDevice)->firstAxis); + HIDDisposeElementList (&(*ppDevice)->firstButton); + HIDDisposeElementList (&(*ppDevice)->firstHat); + + result = HIDCloseReleaseInterface (*ppDevice); /* function sanity checks interface value (now application does not own device) */ + if (kIOReturnSuccess != result) + HIDReportErrorNum ("HIDCloseReleaseInterface failed when trying to dipose device.", result); + DisposePtr ((Ptr)*ppDevice); + *ppDevice = NULL; + } + return pDeviceNext; +} + + +/* Function to scan the system for joysticks. + * Joystick 0 should be the system default joystick. + * This function should return the number of available joysticks, or -1 + * on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + IOReturn result = kIOReturnSuccess; + mach_port_t masterPort = 0; + io_iterator_t hidObjectIterator = 0; + CFMutableDictionaryRef hidMatchDictionary = NULL; + recDevice *device, *lastDevice; + io_object_t ioHIDDeviceObject = 0; + + SDL_numjoysticks = 0; + + if (gpDeviceList) + { + SDL_SetError("Joystick: Device list already inited."); + return -1; + } + + result = IOMasterPort (bootstrap_port, &masterPort); + if (kIOReturnSuccess != result) + { + SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); + return -1; + } + + /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ + hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); + if (hidMatchDictionary) + { + /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ + + /* NOTE: we now perform this filtering later + UInt32 usagePage = kHIDPage_GenericDesktop; + UInt32 usage = kHIDUsage_GD_Joystick; + CFNumberRef refUsage = NULL, refUsagePage = NULL; + + refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); + refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); + CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); + */ + } + else + { + SDL_SetError("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); + return -1; + } + + /*/ Now search I/O Registry for matching devices. */ + result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); + /* Check for errors */ + if (kIOReturnSuccess != result) + { + SDL_SetError("Joystick: Couldn't create a HID object iterator."); + return -1; + } + if (!hidObjectIterator) /* there are no joysticks */ + { + gpDeviceList = NULL; + SDL_numjoysticks = 0; + return 0; + } + /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ + + /* build flat linked list of devices from device iterator */ + + gpDeviceList = lastDevice = NULL; + + while ((ioHIDDeviceObject = IOIteratorNext (hidObjectIterator))) + { + /* build a device record */ + device = HIDBuildDevice (ioHIDDeviceObject); + if (!device) + continue; + + /* dump device object, it is no longer needed */ + result = IOObjectRelease (ioHIDDeviceObject); +/* if (KERN_SUCCESS != result) + HIDReportErrorNum ("IOObjectRelease error with ioHIDDeviceObject.", result); +*/ + + /* Filter device list to non-keyboard/mouse stuff */ + if ( (device->usagePage != kHIDPage_GenericDesktop) || + ((device->usage != kHIDUsage_GD_Joystick && + device->usage != kHIDUsage_GD_GamePad && + device->usage != kHIDUsage_GD_MultiAxisController)) ) { + + /* release memory for the device */ + HIDDisposeDevice (&device); + DisposePtr((Ptr)device); + continue; + } + + /* Add device to the end of the list */ + if (lastDevice) + lastDevice->pNext = device; + else + gpDeviceList = device; + lastDevice = device; + } + result = IOObjectRelease (hidObjectIterator); /* release the iterator */ + + /* Count the total number of devices we found */ + device = gpDeviceList; + while (device) + { + SDL_numjoysticks++; + device = device->pNext; + } + + return SDL_numjoysticks; +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + recDevice *device = gpDeviceList; + + for (; index > 0; index--) + device = device->pNext; + + return device->product; +} + +/* Function to open a joystick for use. + * The joystick to open is specified by the index field of the joystick. + * This should fill the nbuttons and naxes fields of the joystick structure. + * It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + recDevice *device = gpDeviceList; + int index; + + for (index = joystick->index; index > 0; index--) + device = device->pNext; + + joystick->hwdata = device; + joystick->name = device->product; + + joystick->naxes = device->axes; + joystick->nhats = device->hats; + joystick->nballs = 0; + joystick->nbuttons = device->buttons; + + return 0; +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + recDevice *device = joystick->hwdata; + recElement *element; + SInt32 value, range; + int i; + + if (device->removed) /* device was unplugged; ignore it. */ + { + if (device->uncentered) + { + device->uncentered = 0; + + /* Tell the app that everything is centered/unpressed... */ + for (i = 0; i < device->axes; i++) + SDL_PrivateJoystickAxis(joystick, i, 0); + + for (i = 0; i < device->buttons; i++) + SDL_PrivateJoystickButton(joystick, i, 0); + + for (i = 0; i < device->hats; i++) + SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); + } + + return; + } + + element = device->firstAxis; + i = 0; + while (element) + { + value = HIDScaledCalibratedValue(device, element, -32768, 32767); + if ( value != joystick->axes[i] ) + SDL_PrivateJoystickAxis(joystick, i, value); + element = element->pNext; + ++i; + } + + element = device->firstButton; + i = 0; + while (element) + { + value = HIDGetElementValue(device, element); + if (value > 1) /* handle pressure-sensitive buttons */ + value = 1; + if ( value != joystick->buttons[i] ) + SDL_PrivateJoystickButton(joystick, i, value); + element = element->pNext; + ++i; + } + + element = device->firstHat; + i = 0; + while (element) + { + Uint8 pos = 0; + + range = (element->max - element->min + 1); + value = HIDGetElementValue(device, element) - element->min; + if (range == 4) /* 4 position hatswitch - scale up value */ + value *= 2; + else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ + value = -1; + switch(value) + { + case 0: + pos = SDL_HAT_UP; + break; + case 1: + pos = SDL_HAT_RIGHTUP; + break; + case 2: + pos = SDL_HAT_RIGHT; + break; + case 3: + pos = SDL_HAT_RIGHTDOWN; + break; + case 4: + pos = SDL_HAT_DOWN; + break; + case 5: + pos = SDL_HAT_LEFTDOWN; + break; + case 6: + pos = SDL_HAT_LEFT; + break; + case 7: + pos = SDL_HAT_LEFTUP; + break; + default: + /* Every other value is mapped to center. We do that because some + * joysticks use 8 and some 15 for this value, and apparently + * there are even more variants out there - so we try to be generous. + */ + pos = SDL_HAT_CENTERED; + break; + } + if ( pos != joystick->hats[i] ) + SDL_PrivateJoystickHat(joystick, i, pos); + element = element->pNext; + ++i; + } + + return; +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + /* Should we do anything here? */ + return; +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + while (NULL != gpDeviceList) + gpDeviceList = HIDDisposeDevice (&gpDeviceList); +} + +#endif /* SDL_JOYSTICK_IOKIT */ diff --git a/3rdparty/SDL/src/joystick/dc/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/dc/SDL_sysjoystick.c new file mode 100644 index 0000000..dc089e7 --- /dev/null +++ b/3rdparty/SDL/src/joystick/dc/SDL_sysjoystick.c @@ -0,0 +1,193 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_DC + +#include "SDL_events.h" +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#include <dc/maple.h> +#include <dc/maple/controller.h> + +#define MAX_JOYSTICKS 8 /* only 2 are supported in the multimedia API */ +#define MAX_AXES 6 /* each joystick can have up to 6 axes */ +#define MAX_BUTTONS 8 /* and 8 buttons */ +#define MAX_HATS 2 + +#define JOYNAMELEN 8 + +/* array to hold joystick ID values */ +static uint8 SYS_Joystick_addr[MAX_JOYSTICKS]; + +/* The private structure used to keep track of a joystick */ +struct joystick_hwdata +{ + cont_cond_t prev_cond; + int prev_buttons; +}; + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + int numdevs; + + int p,u; + + numdevs = 0; + for(p=0;p<MAPLE_PORT_COUNT;p++) { + for(u=0;u<MAPLE_UNIT_COUNT;u++) { + if (maple_device_func(p,u)&MAPLE_FUNC_CONTROLLER) { + SYS_Joystick_addr[numdevs] = maple_addr(p,u); + numdevs++; + } + } + } + + return(numdevs); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + maple_device_t *dev; + if (maple_compat_resolve(SYS_Joystick_addr[index],&dev,MAPLE_FUNC_CONTROLLER)!=0) return NULL; + return dev->info.product_name; +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + /* allocate memory for system specific hardware data */ + joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); + if (joystick->hwdata == NULL) + { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + + /* fill nbuttons, naxes, and nhats fields */ + joystick->nbuttons = MAX_BUTTONS; + joystick->naxes = MAX_AXES; + joystick->nhats = MAX_HATS; + return(0); +} + + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ + +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ +const int sdl_buttons[] = { + CONT_C, + CONT_B, + CONT_A, + CONT_START, + CONT_Z, + CONT_Y, + CONT_X, + CONT_D +}; + + uint8 addr; + cont_cond_t cond,*prev_cond; + int buttons,prev_buttons,i,changed; + + addr = SYS_Joystick_addr[joystick->index]; + if (cont_get_cond(addr,&cond)<0) return; + + buttons = cond.buttons; + prev_buttons = joystick->hwdata->prev_buttons; + changed = buttons^prev_buttons; + + if ((changed)&(CONT_DPAD_UP|CONT_DPAD_DOWN|CONT_DPAD_LEFT|CONT_DPAD_RIGHT)) { + int hat = SDL_HAT_CENTERED; + if (buttons&CONT_DPAD_UP) hat|=SDL_HAT_UP; + if (buttons&CONT_DPAD_DOWN) hat|=SDL_HAT_DOWN; + if (buttons&CONT_DPAD_LEFT) hat|=SDL_HAT_LEFT; + if (buttons&CONT_DPAD_RIGHT) hat|=SDL_HAT_RIGHT; + SDL_PrivateJoystickHat(joystick, 0, hat); + } + if ((changed)&(CONT_DPAD2_UP|CONT_DPAD2_DOWN|CONT_DPAD2_LEFT|CONT_DPAD2_RIGHT)) { + int hat = SDL_HAT_CENTERED; + if (buttons&CONT_DPAD2_UP) hat|=SDL_HAT_UP; + if (buttons&CONT_DPAD2_DOWN) hat|=SDL_HAT_DOWN; + if (buttons&CONT_DPAD2_LEFT) hat|=SDL_HAT_LEFT; + if (buttons&CONT_DPAD2_RIGHT) hat|=SDL_HAT_RIGHT; + SDL_PrivateJoystickHat(joystick, 1, hat); + } + + for(i=0;i<sizeof(sdl_buttons)/sizeof(sdl_buttons[0]);i++) { + if (changed & sdl_buttons[i]) { + SDL_PrivateJoystickButton(joystick, i, (buttons & sdl_buttons[i])?SDL_PRESSED:SDL_RELEASED); + } + } + + prev_cond = &joystick->hwdata->prev_cond; + if (cond.joyx!=prev_cond->joyx) + SDL_PrivateJoystickAxis(joystick, 0, cond.joyx-128); + if (cond.joyy!=prev_cond->joyy) + SDL_PrivateJoystickAxis(joystick, 1, cond.joyy-128); + if (cond.rtrig!=prev_cond->rtrig) + SDL_PrivateJoystickAxis(joystick, 2, cond.rtrig); + if (cond.ltrig!=prev_cond->ltrig) + SDL_PrivateJoystickAxis(joystick, 3, cond.ltrig); + if (cond.joy2x!=prev_cond->joy2x) + SDL_PrivateJoystickAxis(joystick, 4, cond.joy2x-128); + if (cond.joy2y!=prev_cond->joy2y) + SDL_PrivateJoystickAxis(joystick, 5, cond.joy2y-128); + + joystick->hwdata->prev_buttons = buttons; + joystick->hwdata->prev_cond = cond; +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + if (joystick->hwdata != NULL) { + /* free system specific hardware data */ + SDL_free(joystick->hwdata); + } +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + return; +} + +#endif /* SDL_JOYSTICK_DC */ diff --git a/3rdparty/SDL/src/joystick/dummy/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/dummy/SDL_sysjoystick.c new file mode 100644 index 0000000..3a1aae7 --- /dev/null +++ b/3rdparty/SDL/src/joystick/dummy/SDL_sysjoystick.c @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED) + +/* This is the system specific header for the SDL joystick API */ + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + SDL_numjoysticks = 0; + return(0); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + SDL_SetError("Logic error: No joysticks available"); + return(NULL); +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + SDL_SetError("Logic error: No joysticks available"); + return(-1); +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + return; +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + return; +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + return; +} + +#endif /* SDL_JOYSTICK_DUMMY || SDL_JOYSTICK_DISABLED */ diff --git a/3rdparty/SDL/src/joystick/linux/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/linux/SDL_sysjoystick.c new file mode 100644 index 0000000..ee43974 --- /dev/null +++ b/3rdparty/SDL/src/joystick/linux/SDL_sysjoystick.c @@ -0,0 +1,1218 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_LINUX + +/* This is the system specific header for the SDL joystick API */ + +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <limits.h> /* For the definition of PATH_MAX */ +#include <linux/joystick.h> +#if SDL_INPUT_LINUXEV +#include <linux/input.h> +#endif + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +/* Special joystick configurations */ +static struct { + const char *name; + int naxes; + int nhats; + int nballs; +} special_joysticks[] = { + { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */ + { "SideWinder Precision Pro", 4, 1, 0 }, + { "SideWinder 3D Pro", 4, 1, 0 }, + { "Microsoft SideWinder 3D Pro", 4, 1, 0 }, + { "Microsoft SideWinder Precision Pro", 4, 1, 0 }, + { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 }, + { "WingMan Interceptor", 3, 3, 0 }, + { "WingMan Extreme Digital 3D", 4, 1, 0 }, + { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 }, + { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 }, + { "Saitek Saitek X45", 6, 1, 0 } +}; + +/* It looks like newer kernels have the logical mapping at the driver level */ +#define NO_LOGICAL_JOYSTICKS + +#ifndef NO_LOGICAL_JOYSTICKS + +/* + Some USB HIDs show up as a single joystick even though they actually + control 2 or more joysticks. +*/ +/* + This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can + be identified by their transparent blue design. It's quite trivial + to add other joysticks with similar quirky behavior. + -id +*/ + +struct joystick_logical_mapping { + int njoy; + int nthing; +}; + +/* + {logical joy, logical axis}, + {logical joy, logical hat}, + {logical joy, logical ball}, + {logical joy, logical button} +*/ + +static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = { + {0,0},{0,1},{0,2},{0,3},{0,4},{0,5} +}; +static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = { + {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11} +}; + +static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = { + {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, + {1,2},{1,3},{0,4},{0,5},{1,4},{1,5} +}; +static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = { + {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, + {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11} +}; + +static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = { + {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, + {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, + {0,4},{0,5},{1,4},{1,5},{2,4},{2,5} +}; +static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = { + {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, + {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, + {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11} +}; + +static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = { + {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, + {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, + {3,0},{3,1},{3,2},{3,3},{0,4},{0,5}, + {1,4},{1,5},{2,4},{2,5},{3,4},{3,5} +}; +static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = { + {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, + {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, + {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, + {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11} +}; + +struct joystick_logical_layout { + int naxes; + int nhats; + int nballs; + int nbuttons; +}; + +static struct joystick_logical_layout mp88xx_1_logical_layout[] = { + {6, 0, 0, 12} +}; +static struct joystick_logical_layout mp88xx_2_logical_layout[] = { + {6, 0, 0, 12}, + {6, 0, 0, 12} +}; +static struct joystick_logical_layout mp88xx_3_logical_layout[] = { + {6, 0, 0, 12}, + {6, 0, 0, 12}, + {6, 0, 0, 12} +}; +static struct joystick_logical_layout mp88xx_4_logical_layout[] = { + {6, 0, 0, 12}, + {6, 0, 0, 12}, + {6, 0, 0, 12}, + {6, 0, 0, 12} +}; + +/* + This array sets up a means of mapping a single physical joystick to + multiple logical joysticks. (djm) + + njoys + the number of logical joysticks + + layouts + an array of layout structures, one to describe each logical joystick + + axes, hats, balls, buttons + arrays that map a physical thingy to a logical thingy + */ +struct joystick_logicalmap { + const char *name; + int nbuttons; + int njoys; + struct joystick_logical_layout *layout; + struct joystick_logical_mapping *axismap; + struct joystick_logical_mapping *hatmap; + struct joystick_logical_mapping *ballmap; + struct joystick_logical_mapping *buttonmap; +}; + +static struct joystick_logicalmap joystick_logicalmap[] = { + { + "WiseGroup.,Ltd MP-8866 Dual USB Joypad", + 12, + 1, + mp88xx_1_logical_layout, + mp88xx_1_logical_axismap, + NULL, + NULL, + mp88xx_1_logical_buttonmap + }, + { + "WiseGroup.,Ltd MP-8866 Dual USB Joypad", + 24, + 2, + mp88xx_2_logical_layout, + mp88xx_2_logical_axismap, + NULL, + NULL, + mp88xx_2_logical_buttonmap + }, + { + "WiseGroup.,Ltd MP-8800 Quad USB Joypad", + 12, + 1, + mp88xx_1_logical_layout, + mp88xx_1_logical_axismap, + NULL, + NULL, + mp88xx_1_logical_buttonmap + }, + { + "WiseGroup.,Ltd MP-8800 Quad USB Joypad", + 24, + 2, + mp88xx_2_logical_layout, + mp88xx_2_logical_axismap, + NULL, + NULL, + mp88xx_2_logical_buttonmap + }, + { + "WiseGroup.,Ltd MP-8800 Quad USB Joypad", + 36, + 3, + mp88xx_3_logical_layout, + mp88xx_3_logical_axismap, + NULL, + NULL, + mp88xx_3_logical_buttonmap + }, + { + "WiseGroup.,Ltd MP-8800 Quad USB Joypad", + 48, + 4, + mp88xx_4_logical_layout, + mp88xx_4_logical_axismap, + NULL, + NULL, + mp88xx_4_logical_buttonmap + } +}; + +/* find the head of a linked list, given a point in it + */ +#define SDL_joylist_head(i, start)\ + for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev; + +#define SDL_logical_joydecl(d) d + + +#else + +#define SDL_logical_joydecl(d) + +#endif /* USE_LOGICAL_JOYSTICKS */ + +/* The maximum number of joysticks we'll detect */ +#define MAX_JOYSTICKS 32 + +/* A list of available joysticks */ +static struct +{ + char* fname; +#ifndef NO_LOGICAL_JOYSTICKS + SDL_Joystick* joy; + struct joystick_logicalmap* map; + int prev; + int next; + int logicalno; +#endif /* USE_LOGICAL_JOYSTICKS */ +} SDL_joylist[MAX_JOYSTICKS]; + + +/* The private structure used to keep track of a joystick */ +struct joystick_hwdata { + int fd; + /* The current linux joystick driver maps hats to two axes */ + struct hwdata_hat { + int axis[2]; + } *hats; + /* The current linux joystick driver maps balls to two axes */ + struct hwdata_ball { + int axis[2]; + } *balls; + + /* Support for the Linux 2.4 unified input interface */ +#if SDL_INPUT_LINUXEV + SDL_bool is_hid; + Uint8 key_map[KEY_MAX-BTN_MISC]; + Uint8 abs_map[ABS_MAX]; + struct axis_correct { + int used; + int coef[3]; + } abs_correct[ABS_MAX]; +#endif +}; + + +#ifndef NO_LOGICAL_JOYSTICKS + +static int CountLogicalJoysticks(int max) +{ + register int i, j, k, ret, prev; + const char* name; + int nbuttons, fd; + unsigned char n; + + ret = 0; + + for(i = 0; i < max; i++) { + name = SDL_SYS_JoystickName(i); + + fd = open(SDL_joylist[i].fname, O_RDONLY, 0); + if ( fd >= 0 ) { + if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { + nbuttons = -1; + } else { + nbuttons = n; + } + close(fd); + } + else { + nbuttons=-1; + } + + if (name) { + for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) { + if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) { + prev = i; + SDL_joylist[prev].map = &(joystick_logicalmap[j]); + + for(k = 1; k < joystick_logicalmap[j].njoys; k++) { + SDL_joylist[prev].next = max + ret; + SDL_joylist[max+ret].prev = prev; + + prev = max + ret; + SDL_joylist[prev].logicalno = k; + SDL_joylist[prev].map = &(joystick_logicalmap[j]); + ret++; + } + + break; + } + } + } + } + + return ret; +} + +static void LogicalSuffix(int logicalno, char* namebuf, int len) +{ + register int slen; + const static char suffixs[] = + "01020304050607080910111213141516171819" + "20212223242526272829303132"; + const char* suffix; + slen = SDL_strlen(namebuf); + suffix = NULL; + + if (logicalno*2<sizeof(suffixs)) + suffix = suffixs + (logicalno*2); + + if (slen + 4 < len && suffix) { + namebuf[slen++] = ' '; + namebuf[slen++] = '#'; + namebuf[slen++] = suffix[0]; + namebuf[slen++] = suffix[1]; + namebuf[slen++] = 0; + } +} + +#endif /* USE_LOGICAL_JOYSTICKS */ + +#if SDL_INPUT_LINUXEV +#define test_bit(nr, addr) \ + (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0) +#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1) + +static int EV_IsJoystick(int fd) +{ + unsigned long evbit[NBITS(EV_MAX)] = { 0 }; + unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; + unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; + + if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) || + (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || + (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) { + return(0); + } + if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) && + test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && + (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0; + return(1); +} + +#endif /* SDL_INPUT_LINUXEV */ + +/* Function to scan the system for joysticks */ +int SDL_SYS_JoystickInit(void) +{ + /* The base path of the joystick devices */ + const char *joydev_pattern[] = { +#if SDL_INPUT_LINUXEV + "/dev/input/event%d", +#endif + "/dev/input/js%d", + "/dev/js%d" + }; + int numjoysticks; + int i, j; + int fd; + char path[PATH_MAX]; + dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */ + struct stat sb; + int n, duplicate; + + numjoysticks = 0; + + /* First see if the user specified one or more joysticks to use */ + if ( SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL ) { + char *envcopy, *envpath, *delim; + envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE")); + envpath = envcopy; + while ( envpath != NULL ) { + delim = SDL_strchr(envpath, ':'); + if ( delim != NULL ) { + *delim++ = '\0'; + } + if ( stat(envpath, &sb) == 0 ) { + fd = open(envpath, O_RDONLY, 0); + if ( fd >= 0 ) { + /* Assume the user knows what they're doing. */ + SDL_joylist[numjoysticks].fname = SDL_strdup(envpath); + if ( SDL_joylist[numjoysticks].fname ) { + dev_nums[numjoysticks] = sb.st_rdev; + ++numjoysticks; + } + close(fd); + } + } + envpath = delim; + } + SDL_free(envcopy); + } + + for ( i=0; i<SDL_arraysize(joydev_pattern); ++i ) { + for ( j=0; j < MAX_JOYSTICKS; ++j ) { + SDL_snprintf(path, SDL_arraysize(path), joydev_pattern[i], j); + + /* rcg06302000 replaced access(F_OK) call with stat(). + * stat() will fail if the file doesn't exist, so it's + * equivalent behaviour. + */ + if ( stat(path, &sb) == 0 ) { + /* Check to make sure it's not already in list. + * This happens when we see a stick via symlink. + */ + duplicate = 0; + for (n=0; (n<numjoysticks) && !duplicate; ++n) { + if ( sb.st_rdev == dev_nums[n] ) { + duplicate = 1; + } + } + if (duplicate) { + continue; + } + + fd = open(path, O_RDONLY, 0); + if ( fd < 0 ) { + continue; + } +#if SDL_INPUT_LINUXEV +#ifdef DEBUG_INPUT_EVENTS + printf("Checking %s\n", path); +#endif + if ( (i == 0) && ! EV_IsJoystick(fd) ) { + close(fd); + continue; + } +#endif + close(fd); + + /* We're fine, add this joystick */ + SDL_joylist[numjoysticks].fname = SDL_strdup(path); + if ( SDL_joylist[numjoysticks].fname ) { + dev_nums[numjoysticks] = sb.st_rdev; + ++numjoysticks; + } + } + } + +#if SDL_INPUT_LINUXEV + /* This is a special case... + If the event devices are valid then the joystick devices + will be duplicates but without extra information about their + hats or balls. Unfortunately, the event devices can't + currently be calibrated, so it's a win-lose situation. + So : /dev/input/eventX = /dev/input/jsY = /dev/jsY + */ + if ( (i == 0) && (numjoysticks > 0) ) + break; +#endif + } +#ifndef NO_LOGICAL_JOYSTICKS + numjoysticks += CountLogicalJoysticks(numjoysticks); +#endif + + return(numjoysticks); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + int fd; + static char namebuf[128]; + char *name; + SDL_logical_joydecl(int oindex = index); + +#ifndef NO_LOGICAL_JOYSTICKS + SDL_joylist_head(index, index); +#endif + name = NULL; + fd = open(SDL_joylist[index].fname, O_RDONLY, 0); + if ( fd >= 0 ) { + if ( +#if SDL_INPUT_LINUXEV + (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) && +#endif + (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) { + name = SDL_joylist[index].fname; + } else { + name = namebuf; + } + close(fd); + + +#ifndef NO_LOGICAL_JOYSTICKS + if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex) + { + LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128); + } +#endif + } + return name; +} + +static int allocate_hatdata(SDL_Joystick *joystick) +{ + int i; + + joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc( + joystick->nhats * sizeof(struct hwdata_hat)); + if ( joystick->hwdata->hats == NULL ) { + return(-1); + } + for ( i=0; i<joystick->nhats; ++i ) { + joystick->hwdata->hats[i].axis[0] = 1; + joystick->hwdata->hats[i].axis[1] = 1; + } + return(0); +} + +static int allocate_balldata(SDL_Joystick *joystick) +{ + int i; + + joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc( + joystick->nballs * sizeof(struct hwdata_ball)); + if ( joystick->hwdata->balls == NULL ) { + return(-1); + } + for ( i=0; i<joystick->nballs; ++i ) { + joystick->hwdata->balls[i].axis[0] = 0; + joystick->hwdata->balls[i].axis[1] = 0; + } + return(0); +} + +static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd) +{ + SDL_bool handled; + unsigned char n; + int tmp_naxes, tmp_nhats, tmp_nballs; + const char *name; + char *env, env_name[128]; + int i; + + handled = SDL_FALSE; + + /* Default joystick device settings */ + if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) { + joystick->naxes = 2; + } else { + joystick->naxes = n; + } + if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { + joystick->nbuttons = 2; + } else { + joystick->nbuttons = n; + } + + name = SDL_SYS_JoystickName(joystick->index); + + /* Generic analog joystick support */ + if ( SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat") ) { + if ( SDL_sscanf(name,"Analog %d-axis %*d-button %d-hat", + &tmp_naxes, &tmp_nhats) == 2 ) { + + joystick->naxes = tmp_naxes; + joystick->nhats = tmp_nhats; + + handled = SDL_TRUE; + } + } + + /* Special joystick support */ + for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) { + if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) { + + joystick->naxes = special_joysticks[i].naxes; + joystick->nhats = special_joysticks[i].nhats; + joystick->nballs = special_joysticks[i].nballs; + + handled = SDL_TRUE; + break; + } + } + + /* User environment joystick support */ + if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) { + *env_name = '\0'; + if ( *env == '\'' && SDL_sscanf(env, "'%[^']s'", env_name) == 1 ) + env += SDL_strlen(env_name)+2; + else if ( SDL_sscanf(env, "%s", env_name) == 1 ) + env += SDL_strlen(env_name); + + if ( SDL_strcmp(name, env_name) == 0 ) { + + if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats, + &tmp_nballs) == 3 ) { + + joystick->naxes = tmp_naxes; + joystick->nhats = tmp_nhats; + joystick->nballs = tmp_nballs; + + handled = SDL_TRUE; + } + } + } + + /* Remap hats and balls */ + if (handled) { + if ( joystick->nhats > 0 ) { + if ( allocate_hatdata(joystick) < 0 ) { + joystick->nhats = 0; + } + } + if ( joystick->nballs > 0 ) { + if ( allocate_balldata(joystick) < 0 ) { + joystick->nballs = 0; + } + } + } + + return(handled); +} + +#if SDL_INPUT_LINUXEV + +static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd) +{ + int i, t; + unsigned long keybit[NBITS(KEY_MAX)] = { 0 }; + unsigned long absbit[NBITS(ABS_MAX)] = { 0 }; + unsigned long relbit[NBITS(REL_MAX)] = { 0 }; + + /* See if this device uses the new unified event API */ + if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) && + (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) && + (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) { + joystick->hwdata->is_hid = SDL_TRUE; + + /* Get the number of buttons, axes, and other thingamajigs */ + for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) { + if ( test_bit(i, keybit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has button: 0x%x\n", i); +#endif + joystick->hwdata->key_map[i-BTN_MISC] = + joystick->nbuttons; + ++joystick->nbuttons; + } + } + for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) { + if ( test_bit(i, keybit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has button: 0x%x\n", i); +#endif + joystick->hwdata->key_map[i-BTN_MISC] = + joystick->nbuttons; + ++joystick->nbuttons; + } + } + for ( i=0; i<ABS_MISC; ++i ) { + /* Skip hats */ + if ( i == ABS_HAT0X ) { + i = ABS_HAT3Y; + continue; + } + if ( test_bit(i, absbit) ) { + struct input_absinfo absinfo; + + if ( ioctl(fd, EVIOCGABS(i), &absinfo) < 0 ) + continue; +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has absolute axis: %x\n", i); + printf("Values = { %d, %d, %d, %d, %d }\n", + absinfo.value, absinfo.minimum, + absinfo.maximum, absinfo.fuzz, absinfo.flat); +#endif /* DEBUG_INPUT_EVENTS */ + joystick->hwdata->abs_map[i] = joystick->naxes; + if ( absinfo.minimum == absinfo.maximum ) { + joystick->hwdata->abs_correct[i].used = 0; + } else { + joystick->hwdata->abs_correct[i].used = 1; + joystick->hwdata->abs_correct[i].coef[0] = + (absinfo.maximum + absinfo.minimum) / 2 - absinfo.flat; + joystick->hwdata->abs_correct[i].coef[1] = + (absinfo.maximum + absinfo.minimum) / 2 + absinfo.flat; + t = ((absinfo.maximum - absinfo.minimum) / 2 - 2 * absinfo.flat); + if ( t != 0 ) { + joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t; + } else { + joystick->hwdata->abs_correct[i].coef[2] = 0; + } + } + ++joystick->naxes; + } + } + for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) { + if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) { +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2); +#endif + ++joystick->nhats; + } + } + if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) { + ++joystick->nballs; + } + + /* Allocate data to keep track of these thingamajigs */ + if ( joystick->nhats > 0 ) { + if ( allocate_hatdata(joystick) < 0 ) { + joystick->nhats = 0; + } + } + if ( joystick->nballs > 0 ) { + if ( allocate_balldata(joystick) < 0 ) { + joystick->nballs = 0; + } + } + } + return(joystick->hwdata->is_hid); +} + +#endif /* SDL_INPUT_LINUXEV */ + +#ifndef NO_LOGICAL_JOYSTICKS +static void ConfigLogicalJoystick(SDL_Joystick *joystick) +{ + struct joystick_logical_layout* layout; + + layout = SDL_joylist[joystick->index].map->layout + + SDL_joylist[joystick->index].logicalno; + + joystick->nbuttons = layout->nbuttons; + joystick->nhats = layout->nhats; + joystick->naxes = layout->naxes; + joystick->nballs = layout->nballs; +} +#endif + + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int fd; + SDL_logical_joydecl(int realindex); + SDL_logical_joydecl(SDL_Joystick *realjoy = NULL); + + /* Open the joystick and set the joystick file descriptor */ +#ifndef NO_LOGICAL_JOYSTICKS + if (SDL_joylist[joystick->index].fname == NULL) { + SDL_joylist_head(realindex, joystick->index); + realjoy = SDL_JoystickOpen(realindex); + + if (realjoy == NULL) + return(-1); + + fd = realjoy->hwdata->fd; + + } else { + fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0); + } + SDL_joylist[joystick->index].joy = joystick; +#else + fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0); +#endif + + if ( fd < 0 ) { + SDL_SetError("Unable to open %s\n", + SDL_joylist[joystick->index]); + return(-1); + } + joystick->hwdata = (struct joystick_hwdata *) + SDL_malloc(sizeof(*joystick->hwdata)); + if ( joystick->hwdata == NULL ) { + SDL_OutOfMemory(); + close(fd); + return(-1); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + joystick->hwdata->fd = fd; + + /* Set the joystick to non-blocking read mode */ + fcntl(fd, F_SETFL, O_NONBLOCK); + + /* Get the number of buttons and axes on the joystick */ +#ifndef NO_LOGICAL_JOYSTICKS + if (realjoy) + ConfigLogicalJoystick(joystick); + else +#endif +#if SDL_INPUT_LINUXEV + if ( ! EV_ConfigJoystick(joystick, fd) ) +#endif + JS_ConfigJoystick(joystick, fd); + + return(0); +} + +#ifndef NO_LOGICAL_JOYSTICKS + +static SDL_Joystick* FindLogicalJoystick( + SDL_Joystick *joystick, struct joystick_logical_mapping* v) +{ + SDL_Joystick *logicaljoy; + register int i; + + i = joystick->index; + logicaljoy = NULL; + + /* get the fake joystick that will receive the event + */ + for(;;) { + + if (SDL_joylist[i].logicalno == v->njoy) { + logicaljoy = SDL_joylist[i].joy; + break; + } + + if (SDL_joylist[i].next == 0) + break; + + i = SDL_joylist[i].next; + + } + + return logicaljoy; +} + +static int LogicalJoystickButton( + SDL_Joystick *joystick, Uint8 button, Uint8 state){ + struct joystick_logical_mapping* buttons; + SDL_Joystick *logicaljoy = NULL; + + /* if there's no map then this is just a regular joystick + */ + if (SDL_joylist[joystick->index].map == NULL) + return 0; + + /* get the logical joystick that will receive the event + */ + buttons = SDL_joylist[joystick->index].map->buttonmap+button; + logicaljoy = FindLogicalJoystick(joystick, buttons); + + if (logicaljoy == NULL) + return 1; + + SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state); + + return 1; +} + +static int LogicalJoystickAxis( + SDL_Joystick *joystick, Uint8 axis, Sint16 value) +{ + struct joystick_logical_mapping* axes; + SDL_Joystick *logicaljoy = NULL; + + /* if there's no map then this is just a regular joystick + */ + if (SDL_joylist[joystick->index].map == NULL) + return 0; + + /* get the logical joystick that will receive the event + */ + axes = SDL_joylist[joystick->index].map->axismap+axis; + logicaljoy = FindLogicalJoystick(joystick, axes); + + if (logicaljoy == NULL) + return 1; + + SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value); + + return 1; +} +#endif /* USE_LOGICAL_JOYSTICKS */ + +static __inline__ +void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value) +{ + struct hwdata_hat *the_hat; + const Uint8 position_map[3][3] = { + { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, + { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, + { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } + }; + SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL); + SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL); + + if (stick->nhats <= hat) { + return; /* whoops, that shouldn't happen! */ + } + + the_hat = &stick->hwdata->hats[hat]; + if ( value < 0 ) { + value = 0; + } else + if ( value == 0 ) { + value = 1; + } else + if ( value > 0 ) { + value = 2; + } + if ( value != the_hat->axis[axis] ) { + the_hat->axis[axis] = value; + +#ifndef NO_LOGICAL_JOYSTICKS + /* if there's no map then this is just a regular joystick + */ + if (SDL_joylist[stick->index].map != NULL) { + + /* get the fake joystick that will receive the event + */ + hats = SDL_joylist[stick->index].map->hatmap+hat; + logicaljoy = FindLogicalJoystick(stick, hats); + } + + if (logicaljoy) { + stick = logicaljoy; + hat = hats->nthing; + } +#endif /* USE_LOGICAL_JOYSTICKS */ + + SDL_PrivateJoystickHat(stick, hat, + position_map[the_hat->axis[1]][the_hat->axis[0]]); + } +} + +static __inline__ +void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value) +{ + if ((stick->nballs <= ball) || (axis >= 2)) { + return; /* whoops, that shouldn't happen! */ + } + stick->hwdata->balls[ball].axis[axis] += value; +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +static __inline__ void JS_HandleEvents(SDL_Joystick *joystick) +{ + struct js_event events[32]; + int i, len; + Uint8 other_axis; + +#ifndef NO_LOGICAL_JOYSTICKS + if (SDL_joylist[joystick->index].fname == NULL) { + SDL_joylist_head(i, joystick->index); + JS_HandleEvents(SDL_joylist[i].joy); + return; + } +#endif + + while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) { + len /= sizeof(events[0]); + for ( i=0; i<len; ++i ) { + switch (events[i].type & ~JS_EVENT_INIT) { + case JS_EVENT_AXIS: + if ( events[i].number < joystick->naxes ) { +#ifndef NO_LOGICAL_JOYSTICKS + if (!LogicalJoystickAxis(joystick, + events[i].number, events[i].value)) +#endif + SDL_PrivateJoystickAxis(joystick, + events[i].number, events[i].value); + break; + } + events[i].number -= joystick->naxes; + other_axis = (events[i].number / 2); + if ( other_axis < joystick->nhats ) { + HandleHat(joystick, other_axis, + events[i].number%2, + events[i].value); + break; + } + events[i].number -= joystick->nhats*2; + other_axis = (events[i].number / 2); + if ( other_axis < joystick->nballs ) { + HandleBall(joystick, other_axis, + events[i].number%2, + events[i].value); + break; + } + break; + case JS_EVENT_BUTTON: +#ifndef NO_LOGICAL_JOYSTICKS + if (!LogicalJoystickButton(joystick, + events[i].number, events[i].value)) +#endif + SDL_PrivateJoystickButton(joystick, + events[i].number, events[i].value); + break; + default: + /* ?? */ + break; + } + } + } +} +#if SDL_INPUT_LINUXEV +static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value) +{ + struct axis_correct *correct; + + correct = &joystick->hwdata->abs_correct[which]; + if ( correct->used ) { + if ( value > correct->coef[0] ) { + if ( value < correct->coef[1] ) { + return 0; + } + value -= correct->coef[1]; + } else { + value -= correct->coef[0]; + } + value *= correct->coef[2]; + value >>= 14; + } + + /* Clamp and return */ + if ( value < -32768 ) return -32768; + if ( value > 32767 ) return 32767; + + return value; +} + +static __inline__ void EV_HandleEvents(SDL_Joystick *joystick) +{ + struct input_event events[32]; + int i, len; + int code; + +#ifndef NO_LOGICAL_JOYSTICKS + if (SDL_joylist[joystick->index].fname == NULL) { + SDL_joylist_head(i, joystick->index); + return EV_HandleEvents(SDL_joylist[i].joy); + } +#endif + + while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) { + len /= sizeof(events[0]); + for ( i=0; i<len; ++i ) { + code = events[i].code; + switch (events[i].type) { + case EV_KEY: + if ( code >= BTN_MISC ) { + code -= BTN_MISC; +#ifndef NO_LOGICAL_JOYSTICKS + if (!LogicalJoystickButton(joystick, + joystick->hwdata->key_map[code], + events[i].value)) +#endif + SDL_PrivateJoystickButton(joystick, + joystick->hwdata->key_map[code], + events[i].value); + } + break; + case EV_ABS: + switch (code) { + case ABS_HAT0X: + case ABS_HAT0Y: + case ABS_HAT1X: + case ABS_HAT1Y: + case ABS_HAT2X: + case ABS_HAT2Y: + case ABS_HAT3X: + case ABS_HAT3Y: + code -= ABS_HAT0X; + HandleHat(joystick, code/2, code%2, + events[i].value); + break; + default: + events[i].value = EV_AxisCorrect(joystick, code, events[i].value); +#ifndef NO_LOGICAL_JOYSTICKS + if (!LogicalJoystickAxis(joystick, + joystick->hwdata->abs_map[code], + events[i].value)) +#endif + SDL_PrivateJoystickAxis(joystick, + joystick->hwdata->abs_map[code], + events[i].value); + break; + } + break; + case EV_REL: + switch (code) { + case REL_X: + case REL_Y: + code -= REL_X; + HandleBall(joystick, code/2, code%2, + events[i].value); + break; + default: + break; + } + break; + default: + break; + } + } + } +} +#endif /* SDL_INPUT_LINUXEV */ + +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + int i; + +#if SDL_INPUT_LINUXEV + if ( joystick->hwdata->is_hid ) + EV_HandleEvents(joystick); + else +#endif + JS_HandleEvents(joystick); + + /* Deliver ball motion updates */ + for ( i=0; i<joystick->nballs; ++i ) { + int xrel, yrel; + + xrel = joystick->hwdata->balls[i].axis[0]; + yrel = joystick->hwdata->balls[i].axis[1]; + if ( xrel || yrel ) { + joystick->hwdata->balls[i].axis[0] = 0; + joystick->hwdata->balls[i].axis[1] = 0; + SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel); + } + } +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ +#ifndef NO_LOGICAL_JOYSTICKS + register int i; + if (SDL_joylist[joystick->index].fname == NULL) { + SDL_joylist_head(i, joystick->index); + SDL_JoystickClose(SDL_joylist[i].joy); + } +#endif + + if ( joystick->hwdata ) { +#ifndef NO_LOGICAL_JOYSTICKS + if (SDL_joylist[joystick->index].fname != NULL) +#endif + close(joystick->hwdata->fd); + if ( joystick->hwdata->hats ) { + SDL_free(joystick->hwdata->hats); + } + if ( joystick->hwdata->balls ) { + SDL_free(joystick->hwdata->balls); + } + SDL_free(joystick->hwdata); + joystick->hwdata = NULL; + } +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + int i; + + for ( i=0; SDL_joylist[i].fname; ++i ) { + SDL_free(SDL_joylist[i].fname); + SDL_joylist[i].fname = NULL; + } +} + +#endif /* SDL_JOYSTICK_LINUX */ diff --git a/3rdparty/SDL/src/joystick/macos/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/macos/SDL_sysjoystick.c new file mode 100644 index 0000000..3645dbd --- /dev/null +++ b/3rdparty/SDL/src/joystick/macos/SDL_sysjoystick.c @@ -0,0 +1,320 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_MACOS + +/* SDL stuff -- "SDL_sysjoystick.c" + MacOS joystick functions by Frederick Reitberger + + The code that follows is meant for SDL. Use at your own risk. +*/ + +#include <InputSprocket.h> + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + + +/* The max number of joysticks we will detect */ +#define MAX_JOYSTICKS 16 +/* Limit ourselves to 32 elements per device */ +#define kMaxReferences 32 + +#define ISpSymmetricAxisToFloat(axis) ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle)) +#define ISpAsymmetricAxisToFloat(axis) (((float) axis) / (kISpAxisMaximum)) + + +static ISpDeviceReference SYS_Joysticks[MAX_JOYSTICKS]; +static ISpElementListReference SYS_Elements[MAX_JOYSTICKS]; +static ISpDeviceDefinition SYS_DevDef[MAX_JOYSTICKS]; + +struct joystick_hwdata +{ + char name[64]; +/* Uint8 id;*/ + ISpElementReference refs[kMaxReferences]; + /* gonna need some sort of mapping info */ +}; + + +/* Function to scan the system for joysticks. + * Joystick 0 should be the system default joystick. + * This function should return the number of available joysticks, or -1 + * on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + static ISpDeviceClass classes[4] = { + kISpDeviceClass_Joystick, + #if kISpDeviceClass_Gamepad + kISpDeviceClass_Gamepad, + #endif + kISpDeviceClass_Wheel, + 0 + }; + OSErr err; + int i; + UInt32 count, numJoysticks; + + if ( (Ptr)0 == (Ptr)ISpStartup ) { + SDL_SetError("InputSprocket not installed"); + return -1; // InputSprocket not installed + } + + if( (Ptr)0 == (Ptr)ISpGetVersion ) { + SDL_SetError("InputSprocket not version 1.1 or newer"); + return -1; // old version of ISp (not at least 1.1) + } + + ISpStartup(); + + /* Get all the joysticks */ + numJoysticks = 0; + for ( i=0; classes[i]; ++i ) { + count = 0; + err = ISpDevices_ExtractByClass( + classes[i], + MAX_JOYSTICKS-numJoysticks, + &count, + &SYS_Joysticks[numJoysticks]); + numJoysticks += count; + } + + for(i = 0; i < numJoysticks; i++) + { + ISpDevice_GetDefinition( + SYS_Joysticks[i], sizeof(ISpDeviceDefinition), + &SYS_DevDef[i]); + + err = ISpElementList_New( + 0, NULL, + &SYS_Elements[i], 0); + + if (err) { + SDL_OutOfMemory(); + return -1; + } + + ISpDevice_GetElementList( + SYS_Joysticks[i], + &SYS_Elements[i]); + } + + ISpDevices_Deactivate(numJoysticks, SYS_Joysticks); + + return numJoysticks; +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + static char name[64]; + int len; + + /* convert pascal string to c-string */ + len = SYS_DevDef[index].deviceName[0]; + if ( len >= sizeof(name) ) { + len = (sizeof(name) - 1); + } + SDL_memcpy(name, &SYS_DevDef[index].deviceName[1], len); + name[len] = '\0'; + + return name; +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int index; + UInt32 count, gotCount, count2; + long numAxis, numButtons, numHats, numBalls; + + count = kMaxReferences; + count2 = 0; + numAxis = numButtons = numHats = numBalls = 0; + + index = joystick->index; + + /* allocate memory for system specific hardware data */ + joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); + if (joystick->hwdata == NULL) + { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + SDL_strlcpy(joystick->hwdata->name, SDL_SYS_JoystickName(index), SDL_arraysize(joystick->hwdata->name)); + joystick->name = joystick->hwdata->name; + + ISpElementList_ExtractByKind( + SYS_Elements[index], + kISpElementKind_Axis, + count, + &gotCount, + joystick->hwdata->refs); + + numAxis = gotCount; + count -= gotCount; + count2 += gotCount; + + ISpElementList_ExtractByKind( + SYS_Elements[index], + kISpElementKind_DPad, + count, + &gotCount, + &(joystick->hwdata->refs[count2])); + + numHats = gotCount; + count -= gotCount; + count2 += gotCount; + + ISpElementList_ExtractByKind( + SYS_Elements[index], + kISpElementKind_Button, + count, + &gotCount, + &(joystick->hwdata->refs[count2])); + + numButtons = gotCount; + count -= gotCount; + count2 += gotCount; + + joystick->naxes = numAxis; + joystick->nhats = numHats; + joystick->nballs = numBalls; + joystick->nbuttons = numButtons; + + ISpDevices_Activate( + 1, + &SYS_Joysticks[index]); + + return 0; +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + int i, j; + ISpAxisData a; + ISpDPadData b; + //ISpDeltaData c; + ISpButtonData d; + + for(i = 0, j = 0; i < joystick->naxes; i++, j++) + { + Sint16 value; + + ISpElement_GetSimpleState( + joystick->hwdata->refs[j], + &a); + value = (ISpSymmetricAxisToFloat(a)* 32767.0); + if ( value != joystick->axes[i] ) { + SDL_PrivateJoystickAxis(joystick, i, value); + } + } + + for(i = 0; i < joystick->nhats; i++, j++) + { + Uint8 pos; + + ISpElement_GetSimpleState( + joystick->hwdata->refs[j], + &b); + switch(b) { + case kISpPadIdle: + pos = SDL_HAT_CENTERED; + break; + case kISpPadLeft: + pos = SDL_HAT_LEFT; + break; + case kISpPadUpLeft: + pos = SDL_HAT_LEFTUP; + break; + case kISpPadUp: + pos = SDL_HAT_UP; + break; + case kISpPadUpRight: + pos = SDL_HAT_RIGHTUP; + break; + case kISpPadRight: + pos = SDL_HAT_RIGHT; + break; + case kISpPadDownRight: + pos = SDL_HAT_RIGHTDOWN; + break; + case kISpPadDown: + pos = SDL_HAT_DOWN; + break; + case kISpPadDownLeft: + pos = SDL_HAT_LEFTDOWN; + break; + } + if ( pos != joystick->hats[i] ) { + SDL_PrivateJoystickHat(joystick, i, pos); + } + } + + for(i = 0; i < joystick->nballs; i++, j++) + { + /* ignore balls right now */ + } + + for(i = 0; i < joystick->nbuttons; i++, j++) + { + ISpElement_GetSimpleState( + joystick->hwdata->refs[j], + &d); + if ( d != joystick->buttons[i] ) { + SDL_PrivateJoystickButton(joystick, i, d); + } + } +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + int index; + + index = joystick->index; + + ISpDevices_Deactivate( + 1, + &SYS_Joysticks[index]); +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + ISpShutdown(); +} + +#endif /* SDL_JOYSTICK_MACOS */ diff --git a/3rdparty/SDL/src/joystick/mint/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/mint/SDL_sysjoystick.c new file mode 100644 index 0000000..9a36152 --- /dev/null +++ b/3rdparty/SDL/src/joystick/mint/SDL_sysjoystick.c @@ -0,0 +1,826 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_MINT + +/* + * Atari Joystick/Joypad drivers + * + * Patrice Mandin + */ + +#include <mint/cookie.h> +#include <mint/osbind.h> + +#include "SDL_events.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#include "../../video/ataricommon/SDL_ikbdinterrupt_s.h" +#include "../../video/ataricommon/SDL_xbiosevents_c.h" +#include "../../video/ataricommon/SDL_xbiosinterrupt_s.h" + +/*--- Const ---*/ + +/* We can have: + 1 joystick on IKBD port 1, read via hardware I/O + or same joystick on IKBD port 1, read via xbios + 1 joypad on port A (up to 4 with teamtap) + or 2 joysticks on joypad port A + or 1 analog paddle on joypad port A + or 1 lightpen on joypad port A + 1 joypad on port B (up to 4 with teamtap) + or 2 joysticks on joypad port B + or 1 analog paddle on joypad port B + 2 joysticks on parallel port +*/ + +enum { + IKBD_JOY1=0, + XBIOS_JOY1, + PORTA_PAD0, + PORTA_PAD1, + PORTA_PAD2, + PORTA_PAD3, + PORTB_PAD0, + PORTB_PAD1, + PORTB_PAD2, + PORTB_PAD3, + PORTA_JOY0, + PORTA_JOY1, + PORTB_JOY0, + PORTB_JOY1, + PORTA_LP, + PORTA_ANPAD, + PORTB_ANPAD, +#if 0 + PARA_JOY0, + PARA_JOY1, +#endif + MAX_JOYSTICKS +}; + +enum { + MCH_ST=0, + MCH_STE, + MCH_TT, + MCH_F30, + MCH_CLONE, + MCH_ARANYM +}; + +/* Joypad buttons + * Procontroller note: + * L,R are connected to 4,6 + * X,Y,Z are connected to 7,8,9 + */ + +enum { + JP_UP=0, JP_DOWN, JP_LEFT, JP_RIGHT, + JP_KPMULT, JP_KP7, JP_KP4, JP_KP1, + JP_KP0, JP_KP8, JP_KP5, JP_KP2, + JP_KPNUM, JP_KP9, JP_KP6, JP_KP3, + JP_PAUSE, JP_FIRE0, JP_UNDEF0, JP_FIRE1, + JP_UNDEF1, JP_FIRE2, JP_UNDEF2, JP_OPTION +}; + +#define JP_NUM_BUTTONS 17 + +#define PORT_JS_RIGHT (1<<0) +#define PORT_JS_LEFT (1<<1) +#define PORT_JS_DOWN (1<<2) +#define PORT_JS_UP (1<<3) +#define PORT_JS_FIRE (1<<4) + +enum { + TEAMTAP_MAYBE=0, + TEAMTAP_YES, + TEAMTAP_NO +}; + +/* Teamtap detection values */ +static const Uint32 teamtap_ghosts[20][4]={ + {1<<JP_UP, /* for this event on joypad 0, port X */ + (1<<JP_UP)|(1<<JP_KP0), /* we get this on joypad 1 */ + (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KP0), /* this on joypad 2 */ + (1<<JP_KPMULT)|(1<<JP_KP0)}, /* this on joypad 3 */ + {1<<JP_DOWN, + (1<<JP_DOWN)|(1<<JP_KP8), + (1<<JP_DOWN)|(1<<JP_KP9)|(1<<JP_KP8), + (1<<JP_KP7)|(1<<JP_KP8)}, + {1<<JP_LEFT, + (1<<JP_LEFT)|(1<<JP_KP5), + (1<<JP_LEFT)|(1<<JP_KP6)|(1<<JP_KP5), + (1<<JP_KP4)|(1<<JP_KP5)}, + {1<<JP_RIGHT, + (1<<JP_RIGHT)|(1<<JP_KP2), + (1<<JP_RIGHT)|(1<<JP_KP3)|(1<<JP_KP2), + (1<<JP_KP1)|(1<<JP_KP2)}, + {1<<JP_OPTION, + (1<<JP_OPTION)|(1<<JP_FIRE1)|(1<<JP_FIRE2), + (1<<JP_FIRE0)|(1<<JP_FIRE1)|(1<<JP_FIRE2), + 0}, + {1<<JP_FIRE0, + (1<<JP_FIRE2)|(1<<JP_FIRE0), + (1<<JP_FIRE0)|(1<<JP_OPTION)|(1<<JP_FIRE2), + (1<<JP_FIRE1)|(1<<JP_FIRE2)}, + {1<<JP_FIRE1, + (1<<JP_FIRE0), + (1<<JP_OPTION)|(1<<JP_FIRE0)|(1<<JP_FIRE1), + (1<<JP_FIRE0)|(1<<JP_FIRE2)}, + {1<<JP_FIRE2, + (1<<JP_OPTION)|(1<<JP_FIRE0)|(1<<JP_FIRE1)|(1<<JP_FIRE2), + (1<<JP_OPTION), + (1<<JP_FIRE0)|(1<<JP_FIRE1)}, + {1<<JP_KP1, + (1<<JP_RIGHT)|(1<<JP_KP1), + (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP3), + (1<<JP_RIGHT)|(1<<JP_KP2)}, + {1<<JP_KP2, + (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2)|(1<<JP_KP3), + (1<<JP_KP3), + (1<<JP_RIGHT)|(1<<JP_KP1)}, + {1<<JP_KP3, + (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2)|(1<<JP_KP3), + (1<<JP_RIGHT)|(1<<JP_KP1)|(1<<JP_KP2), + 0}, + {1<<JP_KP4, + (1<<JP_LEFT)|(1<<JP_KP4), + (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP6), + (1<<JP_LEFT)|(1<<JP_KP5)}, + {1<<JP_KP5, + (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5)|(1<<JP_KP6), + (1<<JP_KP6), + (1<<JP_LEFT)|(1<<JP_KP4)}, + {1<<JP_KP6, + (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5)|(1<<JP_KP6), + (1<<JP_LEFT)|(1<<JP_KP4)|(1<<JP_KP5), + 0}, + {1<<JP_KP7, + (1<<JP_DOWN)|(1<<JP_KP7), + (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP9), + (1<<JP_DOWN)|(1<<JP_KP8)}, + {1<<JP_KP8, + (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8)|(1<<JP_KP9), + (1<<JP_KP9), + (1<<JP_DOWN)|(1<<JP_KP7)}, + {1<<JP_KP9, + (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8)|(1<<JP_KP9), + (1<<JP_DOWN)|(1<<JP_KP7)|(1<<JP_KP8), + 0}, + {1<<JP_KPMULT, + (1<<JP_UP)|(1<<JP_KPMULT), + (1<<JP_UP)|(1<<JP_KPNUM), + (1<<JP_UP)|(1<<JP_KP0)}, + {1<<JP_KP0, + (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KPMULT)|(1<<JP_KP0), + 1<<JP_KPNUM, + (1<<JP_UP)|(1<<JP_KPMULT)}, + {1<<JP_KPNUM, + (1<<JP_UP)|(1<<JP_KPNUM)|(1<<JP_KPMULT)|(1<<JP_KP0), + (1<<JP_UP)|(1<<JP_KPMULT)|(1<<JP_KP0), + 0}, +}; + +/*--- Types ---*/ + +typedef struct { + SDL_bool enabled; + char *name; + Uint32 prevstate; +} atarijoy_t; + +/*--- Variables ---*/ + +static atarijoy_t atarijoysticks[MAX_JOYSTICKS]={ + {SDL_FALSE,"IKBD joystick port 1",0}, + {SDL_FALSE,"Xbios joystick port 1",0}, + {SDL_FALSE,"Joypad 0 port A",0}, + {SDL_FALSE,"Joypad 1 port A",0}, + {SDL_FALSE,"Joypad 2 port A",0}, + {SDL_FALSE,"Joypad 3 port A",0}, + {SDL_FALSE,"Joypad 0 port B",0}, + {SDL_FALSE,"Joypad 1 port B",0}, + {SDL_FALSE,"Joypad 2 port B",0}, + {SDL_FALSE,"Joypad 3 port B",0}, + {SDL_FALSE,"Joystick 0 port A",0}, + {SDL_FALSE,"Joystick 1 port A",0}, + {SDL_FALSE,"Joystick 0 port B",0}, + {SDL_FALSE,"Joystick 1 port B",0}, + {SDL_FALSE,"Lightpen port A",0}, + {SDL_FALSE,"Analog paddle port A",0}, + {SDL_FALSE,"Analog paddle port B",0} +#if 0 + ,{SDL_FALSE,"Joystick 0 parallel port",0}, + {SDL_FALSE,"Joystick 1 parallel port",0} +#endif +}; + +static const int jp_buttons[JP_NUM_BUTTONS]={ + JP_FIRE0, JP_FIRE1, JP_FIRE2, JP_PAUSE, + JP_OPTION, JP_KPMULT, JP_KPNUM, JP_KP0, + JP_KP1, JP_KP2, JP_KP3, JP_KP4, + JP_KP5, JP_KP6, JP_KP7, JP_KP8, + JP_KP9 +}; + +static SDL_bool joypad_ports_enabled=SDL_FALSE; +static int has_teamtap[2]={TEAMTAP_MAYBE,TEAMTAP_MAYBE}; + +/* Updated joypad ports */ +static Uint16 jp_paddles[4]; +static Uint16 jp_lightpens[2]; +static Uint16 jp_directions; +static Uint16 jp_fires; +static Uint32 jp_joypads[8]; + +/*--- Functions prototypes ---*/ + +static int GetEnabledAtariJoystick(int index); +static void UpdateJoypads(void); + +/*--- Functions ---*/ + +int SDL_SYS_JoystickInit(void) +{ + int i; + long cookie_mch; + const char *envr=SDL_getenv("SDL_JOYSTICK_ATARI"); + +#define TEST_JOY_ENABLED(env,idstring,num) \ + if (SDL_strstr(env,idstring"-off")) { \ + atarijoysticks[num].enabled=SDL_FALSE; \ + } \ + if (SDL_strstr(env,idstring"-on")) { \ + atarijoysticks[num].enabled=SDL_TRUE; \ + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) != C_FOUND) { + cookie_mch = MCH_ST << 16; + } + + /* Enable some default joysticks */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16) || + (cookie_mch == MCH_ARANYM<<16)) + { + atarijoysticks[IKBD_JOY1].enabled=(SDL_AtariIkbd_enabled!=0); + } + if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16) || + (cookie_mch == MCH_ARANYM<<16)) + { + atarijoysticks[PORTA_PAD0].enabled = + atarijoysticks[PORTA_PAD1].enabled = + atarijoysticks[PORTA_PAD2].enabled = + atarijoysticks[PORTA_PAD3].enabled = + atarijoysticks[PORTB_PAD0].enabled = + atarijoysticks[PORTB_PAD1].enabled = + atarijoysticks[PORTB_PAD2].enabled = + atarijoysticks[PORTB_PAD3].enabled = SDL_TRUE; + } + if (!atarijoysticks[IKBD_JOY1].enabled) { + atarijoysticks[XBIOS_JOY1].enabled=(SDL_AtariXbios_enabled!=0); + } + + /* Read environment for joysticks to enable */ + if (envr) { + /* IKBD on any Atari, maybe clones */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16) || + (cookie_mch == MCH_ARANYM<<16)) { + if (SDL_AtariIkbd_enabled!=0) { + TEST_JOY_ENABLED(envr, "ikbd-joy1", IKBD_JOY1); + } + } + /* Joypads ports on STE, Falcon and maybe others */ + if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16) || + (cookie_mch == MCH_ARANYM<<16)) { + TEST_JOY_ENABLED(envr, "porta-pad", PORTA_PAD0); + if (!atarijoysticks[PORTA_PAD0].enabled) { + TEST_JOY_ENABLED(envr, "porta-joy0", PORTA_JOY0); + TEST_JOY_ENABLED(envr, "porta-joy1", PORTA_JOY1); + if (!(atarijoysticks[PORTA_JOY0].enabled) && !(atarijoysticks[PORTA_JOY1].enabled)) { + TEST_JOY_ENABLED(envr, "porta-lp", PORTA_LP); + if (!atarijoysticks[PORTA_LP].enabled) { + TEST_JOY_ENABLED(envr, "porta-anpad", PORTA_ANPAD); + } + } + } + + TEST_JOY_ENABLED(envr, "portb-pad", PORTB_PAD0); + if (!atarijoysticks[PORTB_PAD0].enabled) { + TEST_JOY_ENABLED(envr, "portb-joy0", PORTB_JOY0); + TEST_JOY_ENABLED(envr, "portb-joy1", PORTB_JOY1); + if (!(atarijoysticks[PORTB_JOY0].enabled) && !(atarijoysticks[PORTB_JOY1].enabled)) { + TEST_JOY_ENABLED(envr, "portb-anpad", PORTB_ANPAD); + } + } + } + + if (!atarijoysticks[IKBD_JOY1].enabled) { + if (SDL_AtariXbios_enabled!=0) { + TEST_JOY_ENABLED(envr, "xbios-joy1", XBIOS_JOY1); + } + } +#if 0 + /* Parallel port on any Atari, maybe clones */ + if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) || + (cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) { + TEST_JOY_ENABLED(envr, "para-joy0", PARA_JOY0); + TEST_JOY_ENABLED(envr, "para-joy1", PARA_JOY1); + } +#endif + } + + /* Need to update joypad ports ? */ + joypad_ports_enabled=SDL_FALSE; + for (i=PORTA_PAD0;i<=PORTB_ANPAD;i++) { + if (atarijoysticks[i].enabled) { + joypad_ports_enabled=SDL_TRUE; + break; + } + } + + SDL_numjoysticks = 0; + for (i=0;i<MAX_JOYSTICKS;i++) { + if (atarijoysticks[i].enabled) { + ++SDL_numjoysticks; + } + } + + return(SDL_numjoysticks); +} + +static int GetEnabledAtariJoystick(int index) +{ + int i,j; + + /* Return the nth'index' enabled atari joystick */ + j=0; + for (i=0;i<MAX_JOYSTICKS;i++) { + if (!atarijoysticks[i].enabled) { + continue; + } + + if (j==index) { + break; + } + + ++j; + } + if (i==MAX_JOYSTICKS) + return -1; + + return i; +} + +const char *SDL_SYS_JoystickName(int index) +{ + int numjoystick; + + numjoystick=GetEnabledAtariJoystick(index); + if (numjoystick==-1) + return NULL; + + return(atarijoysticks[numjoystick].name); +} + +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int numjoystick; + + numjoystick=GetEnabledAtariJoystick(joystick->index); + if (numjoystick==-1) + return -1; + + joystick->naxes=0; + joystick->nhats=0; + joystick->nballs=0; + + switch(numjoystick) { + case PORTA_PAD0: + case PORTA_PAD1: + case PORTA_PAD2: + case PORTA_PAD3: + case PORTB_PAD0: + case PORTB_PAD1: + case PORTB_PAD2: + case PORTB_PAD3: + joystick->nhats=1; + joystick->nbuttons=JP_NUM_BUTTONS; + break; + case PORTA_LP: + case PORTA_ANPAD: + case PORTB_ANPAD: + joystick->naxes=2; + joystick->nbuttons=2; + break; + default: + joystick->nhats=1; + joystick->nbuttons=1; + break; + } + + return(0); +} + +/* Detect Teamtap using ghost events */ +static void detect_teamtap(int num_port) +{ + int i,j; + + /* Check if joypad 1,2,3 triggered but not 0 */ + for (i=1; i<4; i++) { + if (jp_joypads[num_port*4+i] && (jp_joypads[num_port*4]==0)) { + has_teamtap[num_port] = TEAMTAP_YES; + return; + } + } + + /* Check if joypad 0 on a given port triggered ghost events for + * other joypads + */ + for (i=0; i<20; i++) { + int with_teamtap=1; + + if (jp_joypads[num_port*4]!=teamtap_ghosts[i][0]) + continue; + + /* If any button on first joypad pressed, check other pads */ + for (j=1; j<4; j++) { + if ((jp_joypads[num_port*4+j] & teamtap_ghosts[i][j]) + ==teamtap_ghosts[i][j]) + { + with_teamtap = 0; + } + } + + has_teamtap[num_port] = (with_teamtap ? TEAMTAP_YES : TEAMTAP_NO); + break; + } +} + +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + int numjoystick; + Uint8 hatstate; + Uint32 curstate,prevstate; + + numjoystick=GetEnabledAtariJoystick(joystick->index); + if (numjoystick==-1) + return; + + prevstate = atarijoysticks[numjoystick].prevstate; + + if (joypad_ports_enabled) { + Supexec(UpdateJoypads); + } + + switch (numjoystick) { + case IKBD_JOY1: + case XBIOS_JOY1: + { + curstate = 0; + + if (numjoystick==IKBD_JOY1) { + curstate = SDL_AtariIkbd_joystick & 0xff; + } + if (numjoystick==XBIOS_JOY1) { + curstate = SDL_AtariXbios_joystick & 0xff; + } + + if (curstate != prevstate) { + hatstate = SDL_HAT_CENTERED; + if (curstate & IKBD_JOY_LEFT) { + hatstate |= SDL_HAT_LEFT; + } + if (curstate & IKBD_JOY_RIGHT) { + hatstate |= SDL_HAT_RIGHT; + } + if (curstate & IKBD_JOY_UP) { + hatstate |= SDL_HAT_UP; + } + if (curstate & IKBD_JOY_DOWN) { + hatstate |= SDL_HAT_DOWN; + } + SDL_PrivateJoystickHat(joystick, 0, hatstate); + + /* Button */ + if ((curstate & IKBD_JOY_FIRE) && !(prevstate & IKBD_JOY_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); + } + if (!(curstate & IKBD_JOY_FIRE) && (prevstate & IKBD_JOY_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_PAD0: + case PORTA_PAD1: + case PORTA_PAD2: + case PORTA_PAD3: + case PORTB_PAD0: + case PORTB_PAD1: + case PORTB_PAD2: + case PORTB_PAD3: + { + int numjoypad,i,numport; + + numjoypad = numport = 0; + switch(numjoystick) { + case PORTA_PAD0: + numjoypad = 0; break; + case PORTA_PAD1: + numjoypad = 1; break; + case PORTA_PAD2: + numjoypad = 2; break; + case PORTA_PAD3: + numjoypad = 3; break; + case PORTB_PAD0: + numjoypad = 4; numport = 1; break; + case PORTB_PAD1: + numjoypad = 5; numport = 1; break; + case PORTB_PAD2: + numjoypad = 6; numport = 1; break; + case PORTB_PAD3: + numjoypad = 7; numport = 1; break; + } + + jp_joypads[numjoypad] &= 0xabffff; + + if (has_teamtap[numport]==TEAMTAP_MAYBE) { + detect_teamtap(numport); + } + /* No events for PORTX_PAD[1,2,3] if no teamtap detected */ + if (has_teamtap[numport] == TEAMTAP_NO) { + if ((numjoypad & 3)!=0) { + return; + } + } + + curstate=jp_joypads[numjoypad]; + if (curstate!=prevstate) { + hatstate = SDL_HAT_CENTERED; + if (curstate & (1<<JP_LEFT)) { + hatstate |= SDL_HAT_LEFT; + } + if (curstate & (1<<JP_RIGHT)) { + hatstate |= SDL_HAT_RIGHT; + } + if (curstate & (1<<JP_UP)) { + hatstate |= SDL_HAT_UP; + } + if (curstate & (1<<JP_DOWN)) { + hatstate |= SDL_HAT_DOWN; + } + SDL_PrivateJoystickHat(joystick, 0, hatstate); + + /* Buttons */ + for (i=0;i<JP_NUM_BUTTONS;i++) { + int button; + + button=1<<jp_buttons[i]; + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_JOY0: + case PORTA_JOY1: + case PORTB_JOY0: + case PORTB_JOY1: + { + int fire_shift=0,dir_shift=0; + + if (numjoystick==PORTA_JOY0) { fire_shift=0; dir_shift=0; } + if (numjoystick==PORTA_JOY1) { fire_shift=1; dir_shift=4; } + if (numjoystick==PORTB_JOY0) { fire_shift=2; dir_shift=8; } + if (numjoystick==PORTB_JOY1) { fire_shift=3; dir_shift=12; } + + curstate = (jp_directions>>dir_shift) & 15; + curstate |= ((jp_fires>>fire_shift) & 1)<<4; + + if (curstate != prevstate) { + hatstate = SDL_HAT_CENTERED; + if (curstate & PORT_JS_LEFT) { + hatstate |= SDL_HAT_LEFT; + } + if (curstate & PORT_JS_RIGHT) { + hatstate |= SDL_HAT_RIGHT; + } + if (curstate & PORT_JS_UP) { + hatstate |= SDL_HAT_UP; + } + if (curstate & PORT_JS_DOWN) { + hatstate |= SDL_HAT_DOWN; + } + SDL_PrivateJoystickHat(joystick, 0, hatstate); + + /* Button */ + if ((curstate & PORT_JS_FIRE) && !(prevstate & PORT_JS_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED); + } + if (!(curstate & PORT_JS_FIRE) && (prevstate & PORT_JS_FIRE)) { + SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED); + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_LP: + { + int i; + + curstate = jp_lightpens[0]>>1; + curstate |= (jp_lightpens[1]>>1)<<15; + curstate |= (jp_fires & 3)<<30; + + if (curstate != prevstate) { + /* X axis */ + SDL_PrivateJoystickAxis(joystick,0,jp_lightpens[0] ^ 0x8000); + /* Y axis */ + SDL_PrivateJoystickAxis(joystick,1,jp_lightpens[1] ^ 0x8000); + /* Buttons */ + for (i=0;i<2;i++) { + int button; + + button=1<<(30+i); + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; + case PORTA_ANPAD: + case PORTB_ANPAD: + { + int numpaddle, i; + + numpaddle=0<<1; + if (numjoystick==PORTB_ANPAD) numpaddle=1<<1; + + curstate = jp_paddles[numpaddle]>>1; + curstate |= (jp_paddles[numpaddle+1]>>1)<<15; + curstate |= ((jp_fires>>numpaddle) & 3)<<30; + + if (curstate != prevstate) { + /* X axis */ + SDL_PrivateJoystickAxis(joystick,0,jp_paddles[numpaddle] ^ 0x8000); + /* Y axis */ + SDL_PrivateJoystickAxis(joystick,1,jp_paddles[numpaddle+1] ^ 0x8000); + /* Buttons */ + for (i=0;i<2;i++) { + int button; + + button=1<<(30+i); + + if ((curstate & button) && !(prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + } + if (!(curstate & button) && (prevstate & button)) { + SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + atarijoysticks[numjoystick].prevstate = curstate; + } + break; +#if 0 + case PARA_JOY0: + case PARA_JOY1: + break; +#endif + }; + + return; +} + +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + return; +} + +void SDL_SYS_JoystickQuit(void) +{ + SDL_numjoysticks=0; + return; +} + +/*--- Joypad I/O read/write interface ---*/ + +#define JOYPAD_IO_BASE (0xffff9200) +struct JOYPAD_IO_S { + Uint16 fires; + Uint16 directions; + Uint16 dummy1[6]; + Uint16 paddles[4]; + Uint16 dummy2[4]; + Uint16 lightpens[2]; +}; +#define JOYPAD_IO ((*(volatile struct JOYPAD_IO_S *)JOYPAD_IO_BASE)) + +static const Uint16 joypad_masks[8*4]={ + 0xfffe, 0xfffd, 0xfffb, 0xfff7, + 0xfff0, 0xfff1, 0xfff2, 0xfff3, + 0xfff4, 0xfff5, 0xfff6, 0xfff8, + 0xfff9, 0xfffa, 0xfffc, 0xffff, + 0xffef, 0xffdf, 0xffbf, 0xff7f, + 0xff0f, 0xff1f, 0xff2f, 0xff3f, + 0xff4f, 0xff5f, 0xff6f, 0xff8f, + 0xff9f, 0xffaf, 0xffcf, 0xffff +}; + +static void UpdateJoypads(void) +{ + Uint16 tmp, i, j; + Uint32 cur_fire, cur_dir; + + /*--- This function is called in supervisor mode ---*/ + + /* Update joysticks */ + jp_fires = (~(JOYPAD_IO.fires)) & 15; + jp_directions = (~(JOYPAD_IO.directions)); + + /* Update lightpen */ + tmp = JOYPAD_IO.lightpens[0] & 1023; + jp_lightpens[0] = (tmp<<6) | (tmp>>4); + tmp = JOYPAD_IO.lightpens[1] & 1023; + jp_lightpens[1] = (tmp<<6) | (tmp>>4); + + /* Update paddles */ + tmp = (JOYPAD_IO.paddles[0] & 255); + jp_paddles[0] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[1] & 255); + jp_paddles[1] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[2] & 255); + jp_paddles[2] = (tmp<<8) | tmp; + tmp = (JOYPAD_IO.paddles[3] & 255); + jp_paddles[3] = (tmp<<8) | tmp; + + /* Update joypads on teamtap port A */ + for (i=0; i<4; i++) { + jp_joypads[i] = 0; + for (j=0; j<4; j++) { + JOYPAD_IO.directions = joypad_masks[(i*4)+j]; + + cur_fire = (~(JOYPAD_IO.fires) & 3)<<16; + cur_dir = (~(JOYPAD_IO.directions)>>8) & 15; + + jp_joypads[i] |= cur_fire<<(j*2); + jp_joypads[i] |= cur_dir<<(j*4); + } + } + + /* Update joypads on teamtap port B */ + for (i=4; i<8; i++) { + jp_joypads[i] = 0; + for (j=0; j<4; j++) { + JOYPAD_IO.directions = joypad_masks[(i*4)+j]; + + cur_fire = (~(JOYPAD_IO.fires) & 0xc)<<14; + cur_dir = (~(JOYPAD_IO.directions)>>12) & 15; + + jp_joypads[i] |= cur_fire<<(j*2); + jp_joypads[i] |= cur_dir<<(j*4); + } + } + + JOYPAD_IO.directions=0xffff; +} + +#endif /* SDL_JOYSTICK_MINT */ diff --git a/3rdparty/SDL/src/joystick/nds/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/nds/SDL_sysjoystick.c new file mode 100644 index 0000000..122f48d --- /dev/null +++ b/3rdparty/SDL/src/joystick/nds/SDL_sysjoystick.c @@ -0,0 +1,150 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the system specific header for the SDL joystick API */ +#include <nds.h> +//#include <nds/registers_alt.h> + +#include "SDL_error.h" +#include "SDL_events.h" +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#include "../../video/nds/SDL_ndsevents_c.h" + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + SDL_numjoysticks = 1; + //keysInit(); + + return(1); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + if(!index) + return "NDS builtin joypad"; + SDL_SetError("No joystick available with that index"); + return (NULL); +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + joystick->nbuttons=8; + joystick->nhats=0; + joystick->nballs=0; + joystick->naxes=2; + return 0; +} + + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ + +int prevbutton=0; +int prevkey=0; + +int dc=0;int ldc=0; +u32 keysd,keysu=0; +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + //dc=keysd; + //if (dc) + //{ + //fprintf(stderr,"heartbeat= %d\n",REG_VCOUNT); + //swiWaitForVBlank(); + //scanKeys(); + //keysd = keysDown(); + //keysu = keysUp(); + //ldc=keysd; + + //} + /*if (prevkey && prevbutton) + { + scanKeys(); + } + */ + + //scanKeys(); + keysd = keysDown(); + keysu = keysUp(); + + + short ax=0,v=0,h=0; + if((keysd&KEY_UP)) {ax=1;v=-10;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=KEY_UP;}//fprintf(stderr,"KEY_UP\n");} + if((keysd&KEY_DOWN)) {ax=1;v=10;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=KEY_DOWN;}//fprintf(stderr,"KEY_DOWN\n");} + if((keysd&KEY_LEFT)) {ax=0;h=-10;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=KEY_LEFT;}//fprintf(stderr,"KEY_LEFT\n");} + if((keysd&KEY_RIGHT)) {ax=0;h=10;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=KEY_RIGHT;}//fprintf(stderr,"KEY_RIGHT\n");} + + if((keysu&KEY_UP)) {ax=1;v=0;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=0;}//fprintf(stderr,"KEY_UP\n");} + if((keysu&KEY_DOWN)) {ax=1;v=0;SDL_PrivateJoystickAxis(joystick,ax,v);prevkey=0;}//fprintf(stderr,"KEY_DOWN\n");} + if((keysu&KEY_LEFT)) {ax=0;h=0;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=0;}//fprintf(stderr,"KEY_LEFT\n");} + if((keysu&KEY_RIGHT)) {ax=0;h=0;SDL_PrivateJoystickAxis(joystick,ax,h);prevkey=0;}//fprintf(stderr,"KEY_RIGHT\n");} + + if((keysd&KEY_A)) {SDL_PrivateJoystickButton(joystick,0,SDL_PRESSED);prevbutton=KEY_A;} + if((keysd&KEY_B)) {SDL_PrivateJoystickButton(joystick,1,SDL_PRESSED);prevbutton=KEY_B;} + if((keysd&KEY_X)) {SDL_PrivateJoystickButton(joystick,2,SDL_PRESSED);prevbutton=KEY_X;} + if((keysd&KEY_Y)) {SDL_PrivateJoystickButton(joystick,3,SDL_PRESSED);prevbutton=KEY_Y;} + if((keysd&KEY_SELECT)) {SDL_PrivateJoystickButton(joystick,6,SDL_PRESSED);prevbutton=KEY_SELECT;} + if((keysd&KEY_START)) {SDL_PrivateJoystickButton(joystick,7,SDL_PRESSED);prevbutton=KEY_START;} + if((keysd&KEY_L)) {SDL_PrivateJoystickButton(joystick,4,SDL_PRESSED);prevbutton=KEY_L;} + if((keysd&KEY_R)) {SDL_PrivateJoystickButton(joystick,5,SDL_PRESSED);prevbutton=KEY_R;} + + if((keysu&KEY_A)) {SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_B)) {SDL_PrivateJoystickButton(joystick,1,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_X)) {SDL_PrivateJoystickButton(joystick,2,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_Y)) {SDL_PrivateJoystickButton(joystick,3,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_SELECT)) {SDL_PrivateJoystickButton(joystick,6,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_START)) {SDL_PrivateJoystickButton(joystick,7,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_L)) {SDL_PrivateJoystickButton(joystick,4,SDL_RELEASED);prevbutton=0;} + if((keysu&KEY_R)) {SDL_PrivateJoystickButton(joystick,5,SDL_RELEASED);prevbutton=0;} + + + +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ +} + diff --git a/3rdparty/SDL/src/joystick/riscos/SDL_sysjoystick.c b/3rdparty/SDL/src/joystick/riscos/SDL_sysjoystick.c new file mode 100644 index 0000000..214d4c7 --- /dev/null +++ b/3rdparty/SDL/src/joystick/riscos/SDL_sysjoystick.c @@ -0,0 +1,176 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_RISCOS + +/* + RISC OS - Joystick support by Alan Buckley (alan_baa@hotmail.com) - 10 April 2003 + + Note: Currently assumes joystick is present if joystick module is loaded + and that there is one joystick with four buttons. +*/ + +/* This is the system specific header for the SDL joystick API */ + +#include "SDL_events.h" +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#include "kernel.h" + +#define JOYSTICK_READ 0x43F40 + +struct joystick_hwdata +{ + int joystate; +}; + + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return number of joysticks, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + _kernel_swi_regs regs; + + /* Try to read joystick 0 */ + regs.r[0] = 0; + if (_kernel_swi(JOYSTICK_READ, ®s, ®s) == NULL) + { + /* Switch works so assume we've got a joystick */ + return 1; + } + /* Switch fails so it looks like there's no joystick here */ + + return(0); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + if (index == 0) + { + return "RISC OS Joystick 0"; + } + + SDL_SetError("No joystick available with that index"); + return(NULL); +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + _kernel_swi_regs regs; + + if(!(joystick->hwdata=SDL_malloc(sizeof(struct joystick_hwdata)))) + return -1; + + regs.r[0] = joystick->index; + + /* Don't know how to get exact count of buttons so assume max of 4 for now */ + joystick->nbuttons=4; + + joystick->nhats=0; + joystick->nballs=0; + joystick->naxes=2; + joystick->hwdata->joystate=0; + + return 0; + +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + _kernel_swi_regs regs; + regs.r[0] = joystick->index; + + if (_kernel_swi(JOYSTICK_READ, ®s, ®s) == NULL) + { + int newstate = regs.r[0]; + int oldstate = joystick->hwdata->joystate; + if (newstate != oldstate) + { + if ((newstate & 0xFF) != (oldstate & 0xFF)) + { + int y = regs.r[0] & 0xFF; + /* Convert to signed values */ + if (y >= 128) y -= 256; + SDL_PrivateJoystickAxis(joystick,1,-y * 256); /* Up and down opposite to result in SDL */ + } + if ((newstate & 0xFF00) != (oldstate & 0xFF00)) + { + int x = (regs.r[0] & 0xFF00) >> 8; + if (x >= 128) x -= 256; + SDL_PrivateJoystickAxis(joystick,0,x * 256); + } + + if ((newstate & 0xFF0000) != (oldstate & 0xFF0000)) + { + int buttons = (regs.r[0] & 0xFF0000) >> 16; + int oldbuttons = (oldstate & 0xFF0000) >> 16; + int i; + for (i = 0; i < joystick->nbuttons; i++) + { + if ((buttons & (1<<i)) != (oldbuttons & (1<<i))) + { + if (buttons & (1<<i)) SDL_PrivateJoystickButton(joystick,i,SDL_PRESSED); + else SDL_PrivateJoystickButton(joystick,i,SDL_RELEASED); + } + } + } + joystick->hwdata->joystate = newstate; + } + } + + return; +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + if(joystick->hwdata) + SDL_free(joystick->hwdata); + return; +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + SDL_numjoysticks=0; + + return; +} + +#endif /* SDL_JOYSTICK_RISCOS */ diff --git a/3rdparty/SDL/src/joystick/win32/SDL_mmjoystick.c b/3rdparty/SDL/src/joystick/win32/SDL_mmjoystick.c new file mode 100644 index 0000000..8c53f9e --- /dev/null +++ b/3rdparty/SDL/src/joystick/win32/SDL_mmjoystick.c @@ -0,0 +1,407 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_JOYSTICK_WINMM + +/* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> +#include <regstr.h> + +#include "SDL_events.h" +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#define MAX_JOYSTICKS 16 +#define MAX_AXES 6 /* each joystick can have up to 6 axes */ +#define MAX_BUTTONS 32 /* and 32 buttons */ +#define AXIS_MIN -32768 /* minimum value for axis coordinate */ +#define AXIS_MAX 32767 /* maximum value for axis coordinate */ +/* limit axis to 256 possible positions to filter out noise */ +#define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256) +#define JOY_BUTTON_FLAG(n) (1<<n) + + +/* array to hold joystick ID values */ +static UINT SYS_JoystickID[MAX_JOYSTICKS]; +static JOYCAPS SYS_Joystick[MAX_JOYSTICKS]; +static char *SYS_JoystickName[MAX_JOYSTICKS]; + +/* The private structure used to keep track of a joystick */ +struct joystick_hwdata +{ + /* joystick ID */ + UINT id; + + /* values used to translate device-specific coordinates into + SDL-standard ranges */ + struct _transaxis { + int offset; + float scale; + } transaxis[6]; +}; + +/* Convert a win32 Multimedia API return code to a text message */ +static void SetMMerror(char *function, int code); + + +static char *GetJoystickName(int index, const char *szRegKey) +{ + /* added 7/24/2004 by Eckhard Stolberg */ + /* + see if there is a joystick for the current + index (1-16) listed in the registry + */ + char *name = NULL; + HKEY hTopKey; + HKEY hKey; + DWORD regsize; + LONG regresult; + char regkey[256]; + char regvalue[256]; + char regname[256]; + + SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s\\%s", + REGSTR_PATH_JOYCONFIG, szRegKey, REGSTR_KEY_JOYCURR); + hTopKey = HKEY_LOCAL_MACHINE; + regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); + if (regresult != ERROR_SUCCESS) { + hTopKey = HKEY_CURRENT_USER; + regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); + } + if (regresult != ERROR_SUCCESS) { + return NULL; + } + + /* find the registry key name for the joystick's properties */ + regsize = sizeof(regname); + SDL_snprintf(regvalue, SDL_arraysize(regvalue), "Joystick%d%s", index+1, REGSTR_VAL_JOYOEMNAME); + regresult = RegQueryValueExA(hKey, regvalue, 0, 0, (LPBYTE)regname, ®size); + RegCloseKey(hKey); + + if (regresult != ERROR_SUCCESS) { + return NULL; + } + + /* open that registry key */ + SDL_snprintf(regkey, SDL_arraysize(regkey), "%s\\%s", REGSTR_PATH_JOYOEM, regname); + regresult = RegOpenKeyExA(hTopKey, regkey, 0, KEY_READ, &hKey); + if (regresult != ERROR_SUCCESS) { + return NULL; + } + + /* find the size for the OEM name text */ + regsize = sizeof(regvalue); + regresult = RegQueryValueExA(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, NULL, ®size); + if (regresult == ERROR_SUCCESS) { + /* allocate enough memory for the OEM name text ... */ + name = (char *) SDL_malloc(regsize); + if ( name ) { + /* ... and read it from the registry */ + regresult = RegQueryValueExA(hKey, + REGSTR_VAL_JOYOEMNAME, 0, 0, + (LPBYTE) name, ®size); + } + } + RegCloseKey(hKey); + + return(name); +} + +/* Function to scan the system for joysticks. + * This function should set SDL_numjoysticks to the number of available + * joysticks. Joystick 0 should be the system default joystick. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) +{ + int i; + int maxdevs; + int numdevs; + JOYINFOEX joyinfo; + JOYCAPS joycaps; + MMRESULT result; + + /* Reset the joystick ID & name mapping tables */ + for ( i = 0; i < MAX_JOYSTICKS; ++i ) { + SYS_JoystickID[i] = 0; + SYS_JoystickName[i] = NULL; + } + + /* Loop over all potential joystick devices */ + numdevs = 0; + maxdevs = joyGetNumDevs(); + for ( i = JOYSTICKID1; i < maxdevs && numdevs < MAX_JOYSTICKS; ++i ) { + + joyinfo.dwSize = sizeof(joyinfo); + joyinfo.dwFlags = JOY_RETURNALL; + result = joyGetPosEx(i, &joyinfo); + if ( result == JOYERR_NOERROR ) { + result = joyGetDevCaps(i, &joycaps, sizeof(joycaps)); + if ( result == JOYERR_NOERROR ) { + SYS_JoystickID[numdevs] = i; + SYS_Joystick[numdevs] = joycaps; + SYS_JoystickName[numdevs] = GetJoystickName(i, joycaps.szRegKey); + numdevs++; + } + } + } + return(numdevs); +} + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickName(int index) +{ + if ( SYS_JoystickName[index] != NULL ) { + return(SYS_JoystickName[index]); + } else { + return(SYS_Joystick[index].szPname); + } +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) +{ + int index, i; + int caps_flags[MAX_AXES-2] = + { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; + int axis_min[MAX_AXES], axis_max[MAX_AXES]; + + + /* shortcut */ + index = joystick->index; + axis_min[0] = SYS_Joystick[index].wXmin; + axis_max[0] = SYS_Joystick[index].wXmax; + axis_min[1] = SYS_Joystick[index].wYmin; + axis_max[1] = SYS_Joystick[index].wYmax; + axis_min[2] = SYS_Joystick[index].wZmin; + axis_max[2] = SYS_Joystick[index].wZmax; + axis_min[3] = SYS_Joystick[index].wRmin; + axis_max[3] = SYS_Joystick[index].wRmax; + axis_min[4] = SYS_Joystick[index].wUmin; + axis_max[4] = SYS_Joystick[index].wUmax; + axis_min[5] = SYS_Joystick[index].wVmin; + axis_max[5] = SYS_Joystick[index].wVmax; + + /* allocate memory for system specific hardware data */ + joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); + if (joystick->hwdata == NULL) + { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); + + /* set hardware data */ + joystick->hwdata->id = SYS_JoystickID[index]; + for ( i = 0; i < MAX_AXES; ++i ) { + if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { + joystick->hwdata->transaxis[i].offset = + AXIS_MIN - axis_min[i]; + joystick->hwdata->transaxis[i].scale = + (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); + } else { + joystick->hwdata->transaxis[i].offset = 0; + joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ + } + } + + /* fill nbuttons, naxes, and nhats fields */ + joystick->nbuttons = SYS_Joystick[index].wNumButtons; + joystick->naxes = SYS_Joystick[index].wNumAxes; + if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { + joystick->nhats = 1; + } else { + joystick->nhats = 0; + } + return(0); +} + +static Uint8 TranslatePOV(DWORD value) +{ + Uint8 pos; + + pos = SDL_HAT_CENTERED; + if ( value != JOY_POVCENTERED ) { + if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { + pos |= SDL_HAT_UP; + } + if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { + pos |= SDL_HAT_RIGHT; + } + if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { + pos |= SDL_HAT_DOWN; + } + if ( value > JOY_POVBACKWARD ) { + pos |= SDL_HAT_LEFT; + } + } + return(pos); +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) +{ + MMRESULT result; + int i; + DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, + JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; + DWORD pos[MAX_AXES]; + struct _transaxis *transaxis; + int value, change; + JOYINFOEX joyinfo; + + joyinfo.dwSize = sizeof(joyinfo); + joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; + if ( ! joystick->hats ) { + joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); + } + result = joyGetPosEx(joystick->hwdata->id, &joyinfo); + if ( result != JOYERR_NOERROR ) { + SetMMerror("joyGetPosEx", result); + return; + } + + /* joystick motion events */ + pos[0] = joyinfo.dwXpos; + pos[1] = joyinfo.dwYpos; + pos[2] = joyinfo.dwZpos; + pos[3] = joyinfo.dwRpos; + pos[4] = joyinfo.dwUpos; + pos[5] = joyinfo.dwVpos; + + transaxis = joystick->hwdata->transaxis; + for (i = 0; i < joystick->naxes; i++) { + if (joyinfo.dwFlags & flags[i]) { + value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); + change = (value - joystick->axes[i]); + if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { + SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); + } + } + } + + /* joystick button events */ + if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { + for ( i = 0; i < joystick->nbuttons; ++i ) { + if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { + if ( ! joystick->buttons[i] ) { + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + } + } else { + if ( joystick->buttons[i] ) { + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + } + } + } + } + + /* joystick hat events */ + if ( joyinfo.dwFlags & JOY_RETURNPOV ) { + Uint8 pos; + + pos = TranslatePOV(joyinfo.dwPOV); + if ( pos != joystick->hats[0] ) { + SDL_PrivateJoystickHat(joystick, 0, pos); + } + } +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick *joystick) +{ + if (joystick->hwdata != NULL) { + /* free system specific hardware data */ + SDL_free(joystick->hwdata); + joystick->hwdata = NULL; + } +} + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) +{ + int i; + for (i = 0; i < MAX_JOYSTICKS; i++) { + if ( SYS_JoystickName[i] != NULL ) { + SDL_free(SYS_JoystickName[i]); + SYS_JoystickName[i] = NULL; + } + } +} + + +/* implementation functions */ +void SetMMerror(char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) + { + case MMSYSERR_NODRIVER: + error = "Joystick driver not present"; + break; + + case MMSYSERR_INVALPARAM: + case JOYERR_PARMS: + error = "Invalid parameter(s)"; + break; + + case MMSYSERR_BADDEVICEID: + error = "Bad device ID"; + break; + + case JOYERR_UNPLUGGED: + error = "Joystick not attached"; + break; + + case JOYERR_NOCANDO: + error = "Can't capture joystick input"; + break; + + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown Multimedia system error: 0x%x", + function, code); + break; + } + + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); +} + +#endif /* SDL_JOYSTICK_WINMM */ diff --git a/3rdparty/SDL/src/loadso/beos/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/beos/SDL_sysloadso.c new file mode 100644 index 0000000..28267b7 --- /dev/null +++ b/3rdparty/SDL/src/loadso/beos/SDL_sysloadso.c @@ -0,0 +1,72 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_BEOS + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include <stdio.h> +#include <be/kernel/image.h> + +#include "SDL_loadso.h" + +void * +SDL_LoadObject(const char *sofile) +{ + void *handle = NULL; + image_id library_id = load_add_on(sofile); + if (library_id < 0) { + SDL_SetError(strerror((int) library_id)); + } else { + handle = (void *) (library_id); + } + return (handle); +} + +void * +SDL_LoadFunction(void *handle, const char *name) +{ + void *sym = NULL; + image_id library_id = (image_id) handle; + status_t rc = get_image_symbol(library_id, name, B_SYMBOL_TYPE_TEXT, &sym); + if (rc != B_NO_ERROR) { + SDL_SetError(strerror(rc)); + } + return (sym); +} + +void +SDL_UnloadObject(void *handle) +{ + image_id library_id; + if (handle != NULL) { + library_id = (image_id) handle; + unload_add_on(library_id); + } +} + +#endif /* SDL_LOADSO_BEOS */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/3rdparty/SDL/src/loadso/dlopen/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/dlopen/SDL_sysloadso.c new file mode 100644 index 0000000..7985ee7 --- /dev/null +++ b/3rdparty/SDL/src/loadso/dlopen/SDL_sysloadso.c @@ -0,0 +1,69 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_DLOPEN + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include <stdio.h> +#include <dlfcn.h> + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + void *handle = dlopen(sofile, RTLD_NOW); + const char *loaderror = (char *)dlerror(); + if ( handle == NULL ) { + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + } + return(handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + void *symbol = dlsym(handle, name); + if ( symbol == NULL ) { + /* append an underscore for platforms that need that. */ + size_t len = 1+SDL_strlen(name)+1; + char *_name = SDL_stack_alloc(char, len); + _name[0] = '_'; + SDL_strlcpy(&_name[1], name, len); + symbol = dlsym(handle, _name); + SDL_stack_free(_name); + if ( symbol == NULL ) { + SDL_SetError("Failed loading %s: %s", name, (const char *)dlerror()); + } + } + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + if ( handle != NULL ) { + dlclose(handle); + } +} + +#endif /* SDL_LOADSO_DLOPEN */ diff --git a/3rdparty/SDL/src/loadso/dummy/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/dummy/SDL_sysloadso.c new file mode 100644 index 0000000..f8c9af9 --- /dev/null +++ b/3rdparty/SDL/src/loadso/dummy/SDL_sysloadso.c @@ -0,0 +1,50 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(SDL_LOADSO_DUMMY) || defined(SDL_LOADSO_DISABLED) + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + const char *loaderror = "SDL_LoadObject() not implemented"; + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + return(NULL); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + const char *loaderror = "SDL_LoadFunction() not implemented"; + SDL_SetError("Failed loading %s: %s", name, loaderror); + return(NULL); +} + +void SDL_UnloadObject(void *handle) +{ + /* no-op. */ +} + +#endif /* SDL_LOADSO_DUMMY || SDL_LOADSO_DISABLED */ diff --git a/3rdparty/SDL/src/loadso/macos/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/macos/SDL_sysloadso.c new file mode 100644 index 0000000..c035b17 --- /dev/null +++ b/3rdparty/SDL/src/loadso/macos/SDL_sysloadso.c @@ -0,0 +1,106 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_MACOS + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include <stdio.h> +#include <string.h> +#define OLDP2C 1 +#include <Strings.h> +#include <CodeFragments.h> +#include <Errors.h> + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + void *handle = NULL; + const char *loaderror = NULL; + CFragConnectionID library_id; + Ptr mainAddr; + Str255 errName; + OSErr error; + char psofile[512]; + + SDL_strlcpy(psofile, sofile, SDL_arraysize(psofile)); + error = GetSharedLibrary(C2PStr(psofile), kCompiledCFragArch, + kLoadCFrag, &library_id, &mainAddr, errName); + switch (error) { + case noErr: + loaderror = NULL; + break; + case cfragNoLibraryErr: + loaderror = "Library not found"; + break; + case cfragUnresolvedErr: + loaderror = "Unabled to resolve symbols"; + break; + case cfragNoPrivateMemErr: + case cfragNoClientMemErr: + loaderror = "Out of memory"; + break; + default: + loaderror = "Unknown Code Fragment Manager error"; + break; + } + if ( loaderror == NULL ) { + handle = (void *)(library_id); + } else { + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + } + return(handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + void *symbol = NULL; + const char *loaderror = NULL; + CFragSymbolClass class; + CFragConnectionID library_id = (CFragConnectionID)handle; + char pname[512]; + + SDL_strlcpy(pname, name, SDL_arraysize(pname)); + if ( FindSymbol(library_id, C2PStr(pname), + (char **)&symbol, &class) != noErr ) { + loaderror = "Symbol not found"; + } + + if ( symbol == NULL ) { + SDL_SetError("Failed loading %s: %s", name, loaderror); + } + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + CFragConnectionID library_id; + if ( handle != NULL ) { + library_id = (CFragConnectionID)handle; + CloseConnection(&library_id); + } +} + +#endif /* SDL_LOADSO_MACOS */ diff --git a/3rdparty/SDL/src/loadso/macosx/SDL_dlcompat.c b/3rdparty/SDL/src/loadso/macosx/SDL_dlcompat.c new file mode 100644 index 0000000..091947f --- /dev/null +++ b/3rdparty/SDL/src/loadso/macosx/SDL_dlcompat.c @@ -0,0 +1,1407 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_DLCOMPAT + +/* Please note that dlcompat apparently ships in current Mac OS X versions + * as a system library that provides compatibility with the Unix "dlopen" + * interface. In order to allow SDL to work on older OS X releases and also + * not conflict with the system lib on newer versions, we include dlcompat + * in SDL and change the symbols to prevent symbol clash with any existing + * system libraries. --ryan. + */ + +/* here is the dlcompat license: */ + +/* +Copyright (c) 2002 Jorge Acereda <jacereda@users.sourceforge.net> & + Peter O'Gorman <ogorman@users.sourceforge.net> + +Portions may be copyright others, see the AUTHORS file included with this +distribution. + +Maintained by Peter O'Gorman <ogorman@users.sourceforge.net> + +Bug Reports and other queries should go to <ogorman@users.sourceforge.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> +#include <limits.h> +#include <mach-o/dyld.h> +#include <mach-o/nlist.h> +#include <mach-o/getsect.h> + +#include "SDL_stdinc.h" + +/* Just playing to see if it would compile with the freebsd headers, it does, + * but because of the different values for RTLD_LOCAL etc, it would break binary + * compat... oh well + */ +#ifndef __BSD_VISIBLE +#define __BSD_VISIBLE 1 +#endif + +/*include "dlfcn.h"*/ +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__GNUC__) && __GNUC__ > 3 +#define dl_restrict __restrict +#else +#define dl_restrict +#endif + +#if 0 +#ifndef _POSIX_SOURCE +/* + * Structure filled in by dladdr(). + */ +typedef struct SDL_OSX_dl_info { + const char *dli_fname; /* Pathname of shared object */ + void *dli_fbase; /* Base address of shared object */ + const char *dli_sname; /* Name of nearest symbol */ + void *dli_saddr; /* Address of nearest symbol */ +} SDL_OSX_Dl_info; + +static int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict); +#endif /* ! _POSIX_SOURCE */ +#endif /* 0 */ + +static int SDL_OSX_dlclose(void * handle); +static const char * SDL_OSX_dlerror(void); +static void * SDL_OSX_dlopen(const char *path, int mode); +static void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol); + +#define RTLD_LAZY 0x1 +#define RTLD_NOW 0x2 +#define RTLD_LOCAL 0x4 +#define RTLD_GLOBAL 0x8 + +#ifndef _POSIX_SOURCE +#define RTLD_NOLOAD 0x10 +#define RTLD_NODELETE 0x80 + +/* + * Special handle arguments for SDL_OSX_dlsym(). + */ +#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ +#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ +#endif /* ! _POSIX_SOURCE */ + +#ifdef __cplusplus +} +#endif + +#ifndef dl_restrict +#define dl_restrict __restrict +#endif +/* This is not available on 10.1 */ +#ifndef LC_LOAD_WEAK_DYLIB +#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) +#endif + +/* With this stuff here, this thing may actually compile/run on 10.0 systems + * Not that I have a 10.0 system to test it on anylonger + */ +#ifndef LC_REQ_DYLD +#define LC_REQ_DYLD 0x80000000 +#endif +#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4 +#endif +#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR +#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND +#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0 +#endif +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR +#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 +#endif +/* These symbols will be looked for in dyld */ +static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0; +static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0; +static NSSymbol(*dyld_NSLookupSymbolInImage) + (const struct mach_header *, const char *, unsigned long) = 0; + +/* Define this to make dlcompat reuse data block. This way in theory we save + * a little bit of overhead. However we then couldn't correctly catch excess + * calls to SDL_OSX_dlclose(). Hence we don't use this feature + */ +#undef REUSE_STATUS + +/* Size of the internal error message buffer (used by dlerror()) */ +#define ERR_STR_LEN 251 + +/* Maximum number of search paths supported by getSearchPath */ +#define MAX_SEARCH_PATHS 32 + + +#define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF') +#define MAGIC_DYLIB_MOD ((NSModule) 'DYMO') + +/* internal flags */ +#define DL_IN_LIST 0x01 + +/* our mutex */ +static pthread_mutex_t dlcompat_mutex; +/* Our thread specific storage + */ +static pthread_key_t dlerror_key; + +struct dlthread +{ + int lockcnt; + unsigned char errset; + char errstr[ERR_STR_LEN]; +}; + +/* This is our central data structure. Whenever a module is loaded via + * SDL_OSX_dlopen(), we create such a struct. + */ +struct dlstatus +{ + struct dlstatus *next; /* pointer to next element in the linked list */ + NSModule module; + const struct mach_header *lib; + int refs; /* reference count */ + int mode; /* mode in which this module was loaded */ + dev_t device; + ino_t inode; + int flags; /* Any internal flags we may need */ +}; + +/* Head node of the dlstatus list */ +static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }; +static struct dlstatus *stqueue = &mainStatus; + + +/* Storage for the last error message (used by dlerror()) */ +/* static char err_str[ERR_STR_LEN]; */ +/* static int err_filled = 0; */ + +/* Prototypes to internal functions */ +static void debug(const char *fmt, ...); +static void error(const char *str, ...); +static const char *safegetenv(const char *s); +static const char *searchList(void); +static const char *getSearchPath(int i); +static const char *getFullPath(int i, const char *file); +static const struct stat *findFile(const char *file, const char **fullPath); +static int isValidStatus(struct dlstatus *status); +static inline int isFlagSet(int mode, int flag); +static struct dlstatus *lookupStatus(const struct stat *sbuf); +static void insertStatus(struct dlstatus *dls, const struct stat *sbuf); +static int promoteLocalToGlobal(struct dlstatus *dls); +static void *reference(struct dlstatus *dls, int mode); +static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError); +static struct dlstatus *allocStatus(void); +static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode); +static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol); +static const char *get_lib_name(const struct mach_header *mh); +static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); +static void dlcompat_init_func(void); +static inline void dlcompat_init_check(void); +static inline void dolock(void); +static inline void dounlock(void); +static void dlerrorfree(void *data); +static void resetdlerror(void); +static const struct mach_header *my_find_image(const char *name); +static const struct mach_header *image_for_address(const void *address); +static inline char *dyld_error_str(void); + +#if FINK_BUILD +/* Two Global Functions */ +static void *dlsym_prepend_underscore(void *handle, const char *symbol); +static void *dlsym_auto_underscore(void *handle, const char *symbol); + +/* And their _intern counterparts */ +static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol); +static void *dlsym_auto_underscore_intern(void *handle, const char *symbol); +#endif + +/* Functions */ + +static void debug(const char *fmt, ...) +{ +#if DEBUG > 1 + va_list arg; + va_start(arg, fmt); + fprintf(stderr, "DLDEBUG: "); + vfprintf(stderr, fmt, arg); + fprintf(stderr, "\n"); + fflush(stderr); + va_end(arg); +#endif +} + +static void error(const char *str, ...) +{ + va_list arg; + struct dlthread *tss; + char * err_str; + va_start(arg, str); + tss = pthread_getspecific(dlerror_key); + err_str = tss->errstr; + SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN); + vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg); + va_end(arg); + debug("ERROR: %s\n", err_str); + tss->errset = 1; +} + +static void warning(const char *str) +{ +#if DEBUG > 0 + fprintf(stderr, "WARNING: dlcompat: %s\n", str); +#endif +} + +static const char *safegetenv(const char *s) +{ + const char *ss = SDL_getenv(s); + return ss ? ss : ""; +} + +/* because this is only used for debugging and error reporting functions, we + * don't really care about how elegant it is... it could use the load + * commands to find the install name of the library, but... + */ +static const char *get_lib_name(const struct mach_header *mh) +{ + unsigned long count = _dyld_image_count(); + unsigned long i; + const char *val = NULL; + if (mh) + { + for (i = 0; i < count; i++) + { + if (mh == _dyld_get_image_header(i)) + { + val = _dyld_get_image_name(i); + break; + } + } + } + return val; +} + +/* Returns the mach_header for the module bu going through all the loaded images + * and finding the one with the same name as the module. There really ought to be + * an api for doing this, would be faster, but there isn't one right now + */ +static const struct mach_header *get_mach_header_from_NSModule(NSModule mod) +{ + const char *mod_name = NSNameOfModule(mod); + const struct mach_header *mh = NULL; + unsigned long count = _dyld_image_count(); + unsigned long i; + debug("Module name: %s", mod_name); + for (i = 0; i < count; i++) + { + if (!SDL_strcmp(mod_name, _dyld_get_image_name(i))) + { + mh = _dyld_get_image_header(i); + break; + } + } + return mh; +} + + +/* Compute and return a list of all directories that we should search when + * trying to locate a module. We first look at the values of LD_LIBRARY_PATH + * and DYLD_LIBRARY_PATH, and then finally fall back to looking into + * /usr/lib and /lib. Since both of the environments variables can contain a + * list of colon seperated paths, we simply concat them and the two other paths + * into one big string, which we then can easily parse. + * Splitting this string into the actual path list is done by getSearchPath() + */ +static const char *searchList() +{ + size_t buf_size; + static char *buf=NULL; + const char *ldlp = safegetenv("LD_LIBRARY_PATH"); + const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH"); + const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH"); + if (!stdpath) + stdpath = "/usr/local/lib:/lib:/usr/lib"; + if (!buf) + { + buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4; + buf = SDL_malloc(buf_size); + SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), + stdpath, '\0'); + } + return buf; +} + +/* Returns the ith search path from the list as computed by searchList() */ +static const char *getSearchPath(int i) +{ + static const char *list = 0; + static char **path = (char **)0; + static int end = 0; + static int numsize = MAX_SEARCH_PATHS; + static char **tmp; + /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */ + if (i == -1) + { + return (const char*)path; + } + if (!path) + { + path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); + } + if (!list && !end) + list = searchList(); + if (i >= (numsize)) + { + debug("Increasing size for long PATH"); + tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **)); + if (tmp) + { + SDL_memcpy(tmp, path, sizeof(char **) * numsize); + SDL_free(path); + path = tmp; + numsize += MAX_SEARCH_PATHS; + } + else + { + return 0; + } + } + + while (!path[i] && !end) + { + path[i] = strsep((char **)&list, ":"); + + if (path[i][0] == 0) + path[i] = 0; + end = (list == 0); + } + return path[i]; +} + +static const char *getFullPath(int i, const char *file) +{ + static char buf[PATH_MAX]; + const char *path = getSearchPath(i); + if (path) + { + SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file); + } + return path ? buf : 0; +} + +/* Given a file name, try to determine the full path for that file. Starts + * its search in the current directory, and then tries all paths in the + * search list in the order they are specified there. + */ +static const struct stat *findFile(const char *file, const char **fullPath) +{ + int i = 0; + static struct stat sbuf; + char *fileName; + debug("finding file %s", file); + *fullPath = file; + if (0 == stat(file, &sbuf)) + return &sbuf; + if (SDL_strchr(file, '/')) + return 0; /* If the path had a / we don't look in env var places */ + fileName = NULL; + if (!fileName) + fileName = (char *)file; + while ((*fullPath = getFullPath(i++, fileName))) + { + if (0 == stat(*fullPath, &sbuf)) + return &sbuf; + } + ; + return 0; +} + +/* Determine whether a given dlstatus is valid or not */ +static int isValidStatus(struct dlstatus *status) +{ + /* Walk the list to verify status is contained in it */ + struct dlstatus *dls = stqueue; + while (dls && status != dls) + dls = dls->next; + if (dls == 0) + error("invalid handle"); + else if ((dls->module == 0) || (dls->refs == 0)) + error("handle to closed library"); + else + return TRUE; + return FALSE; +} + +static inline int isFlagSet(int mode, int flag) +{ + return (mode & flag) == flag; +} + +static struct dlstatus *lookupStatus(const struct stat *sbuf) +{ + struct dlstatus *dls = stqueue; + debug("looking for status"); + while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 + || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode)) + dls = dls->next; + return dls; +} + +static void insertStatus(struct dlstatus *dls, const struct stat *sbuf) +{ + debug("inserting status"); + dls->inode = sbuf->st_ino; + dls->device = sbuf->st_dev; + dls->refs = 0; + dls->mode = 0; + if ((dls->flags & DL_IN_LIST) == 0) + { + dls->next = stqueue; + stqueue = dls; + dls->flags |= DL_IN_LIST; + } +} + +static struct dlstatus *allocStatus() +{ + struct dlstatus *dls; +#ifdef REUSE_STATUS + dls = stqueue; + while (dls && dls->module) + dls = dls->next; + if (!dls) +#endif + dls = SDL_calloc(sizeof(*dls),1); + return dls; +} + +static int promoteLocalToGlobal(struct dlstatus *dls) +{ + static int (*p) (NSModule module) = 0; + debug("promoting"); + if (!p) + _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p); + return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); +} + +static void *reference(struct dlstatus *dls, int mode) +{ + if (dls) + { + if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) + { + warning("trying to open a .dylib with RTLD_LOCAL"); + error("unable to open a .dylib with RTLD_LOCAL"); + return NULL; + } + if (isFlagSet(mode, RTLD_GLOBAL) && + !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls)) + { + error("unable to promote local module to global"); + return NULL; + } + dls->mode |= mode; + dls->refs++; + } + else + debug("reference called with NULL argument"); + + return dls; +} + +static const struct mach_header *my_find_image(const char *name) +{ + const struct mach_header *mh = 0; + const char *id = NULL; + int i = _dyld_image_count(); + int j; + mh = (struct mach_header *) + dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + if (!mh) + { + for (j = 0; j < i; j++) + { + id = _dyld_get_image_name(j); + if (!SDL_strcmp(id, name)) + { + mh = _dyld_get_image_header(j); + break; + } + } + } + return mh; +} + +/* + * dyld adds libraries by first adding the directly dependant libraries in link order, and + * then adding the dependencies for those libraries, so we should do the same... but we don't + * bother adding the extra dependencies, if the symbols are neither in the loaded image nor + * any of it's direct dependencies, then it probably isn't there. + */ +static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol) +{ + unsigned int n; + struct load_command *lc = 0; + struct mach_header *wh; + NSSymbol nssym = 0; + if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) + { + lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); + for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) + { + if ((wh = (struct mach_header *) + my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + + (char *)lc)))) + { + if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) + { + nssym = dyld_NSLookupSymbolInImage(wh, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + break; + } + } + } + } + if ((!nssym) && NSIsSymbolNameDefined(symbol)) + { + /* I've never seen this debug message...*/ + debug("Symbol \"%s\" is defined but was not found", symbol); + } + } + return nssym; +} + +/* Up to the caller to SDL_free() returned string */ +static inline char *dyld_error_str() +{ + NSLinkEditErrors dylder; + int dylderno; + const char *dylderrstr; + const char *dyldfile; + char* retStr = NULL; + NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); + if (dylderrstr && *dylderrstr) + { + retStr = SDL_strdup(dylderrstr); + } + return retStr; +} + +static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) +{ + NSSymbol nssym = 0; +#ifdef __GCC__ + void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ +#else + void *caller = NULL; +#endif + const struct mach_header *caller_mh = 0; + char *savedErrorStr = NULL; + resetdlerror(); +#ifndef RTLD_SELF +#define RTLD_SELF ((void *) -3) +#endif + if (NULL == dls) + dls = RTLD_SELF; + if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) + { + if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller) + { + caller_mh = image_for_address(caller); + if (RTLD_SELF == dls) + { + /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE + * But it appears to work anyway, and looking at the code in dyld_libfuncs.c + * this is acceptable. + */ + if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) + { + nssym = dyld_NSLookupSymbolInImage(caller_mh, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + } + if (!nssym) + { + if (RTLD_SELF == dls) + savedErrorStr = dyld_error_str(); + nssym = search_linked_libs(caller_mh, symbol); + } + } + else + { + if (canSetError) + error("RTLD_SELF and RTLD_NEXT are not supported"); + return NULL; + } + } + if (!nssym) + { + + if (RTLD_DEFAULT == dls) + { + dls = &mainStatus; + } + if (!isValidStatus(dls)) + return NULL; + + if (dls->module != MAGIC_DYLIB_MOD) + { + nssym = NSLookupSymbolInModule(dls->module, symbol); + if (!nssym && NSIsSymbolNameDefined(symbol)) + { + debug("Searching dependencies"); + savedErrorStr = dyld_error_str(); + nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol); + } + } + else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) + { + if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) + { + nssym = dyld_NSLookupSymbolInImage(dls->lib, + symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + else if (NSIsSymbolNameDefined(symbol)) + { + debug("Searching dependencies"); + savedErrorStr = dyld_error_str(); + nssym = search_linked_libs(dls->lib, symbol); + } + } + else if (dls->module == MAGIC_DYLIB_MOD) + { + /* Global context, use NSLookupAndBindSymbol */ + if (NSIsSymbolNameDefined(symbol)) + { + /* There doesn't seem to be a return on error option for this call??? + this is potentially broken, if binding fails, it will improperly + exit the application. */ + nssym = NSLookupAndBindSymbol(symbol); + } + else + { + if (savedErrorStr) + SDL_free(savedErrorStr); + savedErrorStr = SDL_malloc(256); + SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol); + } + } + } + /* Error reporting */ + if (!nssym) + { + if (!savedErrorStr || !SDL_strlen(savedErrorStr)) + { + if (savedErrorStr) + SDL_free(savedErrorStr); + savedErrorStr = SDL_malloc(256); + SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol); + } + if (canSetError) + { + error(savedErrorStr); + } + else + { + debug(savedErrorStr); + } + if (savedErrorStr) + SDL_free(savedErrorStr); + return NULL; + } + return NSAddressOfSymbol(nssym); +} + +static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) +{ + NSObjectFileImage ofi = 0; + NSObjectFileImageReturnCode ofirc; + struct dlstatus *dls; + NSLinkEditErrors ler; + int lerno; + const char *errstr; + const char *file; + void (*init) (void); + + ofirc = NSCreateObjectFileImageFromFile(path, &ofi); + switch (ofirc) + { + case NSObjectFileImageSuccess: + break; + case NSObjectFileImageInappropriateFile: + if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) + { + if (isFlagSet(mode, RTLD_LOCAL)) + { + warning("trying to open a .dylib with RTLD_LOCAL"); + error("unable to open this file with RTLD_LOCAL"); + return NULL; + } + } + else + { + error("opening this file is unsupported on this system"); + return NULL; + } + break; + case NSObjectFileImageFailure: + error("object file setup failure"); + return NULL; + case NSObjectFileImageArch: + error("no object for this architecture"); + return NULL; + case NSObjectFileImageFormat: + error("bad object file format"); + return NULL; + case NSObjectFileImageAccess: + error("can't read object file"); + return NULL; + default: + error("unknown error from NSCreateObjectFileImageFromFile()"); + return NULL; + } + dls = lookupStatus(sbuf); + if (!dls) + { + dls = allocStatus(); + } + if (!dls) + { + error("unable to allocate memory"); + return NULL; + } + // dls->lib = 0; + if (ofirc == NSObjectFileImageInappropriateFile) + { + if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) + { + debug("Dynamic lib loaded at %ld", dls->lib); + ofi = MAGIC_DYLIB_OFI; + dls->module = MAGIC_DYLIB_MOD; + ofirc = NSObjectFileImageSuccess; + /* Although it is possible with a bit of work to modify this so it works and + functions with RTLD_NOW, I don't deem it necessary at the moment */ + } + if (!(dls->module)) + { + NSLinkEditError(&ler, &lerno, &file, &errstr); + if (!errstr || (!SDL_strlen(errstr))) + error("Can't open this file type"); + else + error(errstr); + if ((dls->flags & DL_IN_LIST) == 0) + { + SDL_free(dls); + } + return NULL; + } + } + else + { + dls->module = NSLinkModule(ofi, path, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_PRIVATE | + (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); + NSDestroyObjectFileImage(ofi); + if (dls->module) + { + dls->lib = get_mach_header_from_NSModule(dls->module); + } + } + if (!dls->module) + { + NSLinkEditError(&ler, &lerno, &file, &errstr); + if ((dls->flags & DL_IN_LIST) == 0) + { + SDL_free(dls); + } + error(errstr); + return NULL; + } + + insertStatus(dls, sbuf); + dls = reference(dls, mode); + if ((init = dlsymIntern(dls, "__init", 0))) + { + debug("calling _init()"); + init(); + } + return dls; +} + +inline static void dlcompat_init_check(void) +{ + static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; + static int init_done = 0; + + pthread_mutex_lock(&l); + if (!init_done) { + dlcompat_init_func(); + init_done = 1; + } + pthread_mutex_unlock(&l); +} + +static void dlcompat_init_func(void) +{ + _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage); + _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", + (void **)&dyld_NSIsSymbolNameDefinedInImage); + _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage); + if (pthread_mutex_init(&dlcompat_mutex, NULL)) + exit(1); + if (pthread_key_create(&dlerror_key, &dlerrorfree)) + exit(1); +} + +static void resetdlerror() +{ + struct dlthread *tss; + tss = pthread_getspecific(dlerror_key); + tss->errset = 0; +} + +static void dlerrorfree(void *data) +{ + SDL_free(data); +} + +/* We kind of want a recursive lock here, but meet a little trouble + * because they are not available pre OS X 10.2, so we fake it + * using thread specific storage to keep a lock count + */ +static inline void dolock(void) +{ + int err = 0; + struct dlthread *tss; + dlcompat_init_check(); + tss = pthread_getspecific(dlerror_key); + if (!tss) + { + tss = SDL_malloc(sizeof(struct dlthread)); + tss->lockcnt = 0; + tss->errset = 0; + if (pthread_setspecific(dlerror_key, tss)) + { + fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); + exit(1); + } + } + if (!tss->lockcnt) + err = pthread_mutex_lock(&dlcompat_mutex); + tss->lockcnt = tss->lockcnt +1; + if (err) + exit(err); +} + +static inline void dounlock(void) +{ + int err = 0; + struct dlthread *tss; + tss = pthread_getspecific(dlerror_key); + tss->lockcnt = tss->lockcnt -1; + if (!tss->lockcnt) + err = pthread_mutex_unlock(&dlcompat_mutex); + if (err) + exit(err); +} + +static void *SDL_OSX_dlopen(const char *path, int mode) +{ + const struct stat *sbuf; + struct dlstatus *dls; + const char *fullPath; + + dolock(); + resetdlerror(); + if (!path) + { + dls = &mainStatus; + goto dlopenok; + } + if (!(sbuf = findFile(path, &fullPath))) + { + error("file \"%s\" not found", path); + goto dlopenerror; + } + /* Now checks that it hasn't been closed already */ + if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) + { + /* debug("status found"); */ + dls = reference(dls, mode); + goto dlopenok; + } +#ifdef RTLD_NOLOAD + if (isFlagSet(mode, RTLD_NOLOAD)) + { + error("no existing handle and RTLD_NOLOAD specified"); + goto dlopenerror; + } +#endif + if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) + { + error("how can I load something both RTLD_LAZY and RTLD_NOW?"); + goto dlopenerror; + } + dls = loadModule(fullPath, sbuf, mode); + + dlopenok: + dounlock(); + return (void *)dls; + dlopenerror: + dounlock(); + return NULL; +} + +#if !FINK_BUILD +static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) +{ + int sym_len = SDL_strlen(symbol); + void *value = NULL; + char *malloc_sym = NULL; + dolock(); + malloc_sym = SDL_malloc(sym_len + 2); + if (malloc_sym) + { + SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); + value = dlsymIntern(handle, malloc_sym, 1); + SDL_free(malloc_sym); + } + else + { + error("Unable to allocate memory"); + goto dlsymerror; + } + dounlock(); + return value; + dlsymerror: + dounlock(); + return NULL; +} +#endif + +#if FINK_BUILD + +static void *dlsym_prepend_underscore(void *handle, const char *symbol) +{ + void *answer; + dolock(); + answer = dlsym_prepend_underscore_intern(handle, symbol); + dounlock(); + return answer; +} + +static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol) +{ +/* + * A quick and easy way for porting packages which call dlsym(handle,"sym") + * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then + * this function will be called, and will add the required underscore. + * + * Note that I haven't figured out yet which should be "standard", prepend + * the underscore always, or not at all. These global functions need to go away + * for opendarwin. + */ + int sym_len = SDL_strlen(symbol); + void *value = NULL; + char *malloc_sym = NULL; + malloc_sym = SDL_malloc(sym_len + 2); + if (malloc_sym) + { + SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); + value = dlsymIntern(handle, malloc_sym, 1); + SDL_free(malloc_sym); + } + else + { + error("Unable to allocate memory"); + } + return value; +} + +static void *dlsym_auto_underscore(void *handle, const char *symbol) +{ + void *answer; + dolock(); + answer = dlsym_auto_underscore_intern(handle, symbol); + dounlock(); + return answer; + +} +static void *dlsym_auto_underscore_intern(void *handle, const char *symbol) +{ + struct dlstatus *dls = handle; + void *addr = 0; + addr = dlsymIntern(dls, symbol, 0); + if (!addr) + addr = dlsym_prepend_underscore_intern(handle, symbol); + return addr; +} + + +static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) +{ + struct dlstatus *dls = handle; + void *addr = 0; + dolock(); + addr = dlsymIntern(dls, symbol, 1); + dounlock(); + return addr; +} +#endif + +static int SDL_OSX_dlclose(void *handle) +{ + struct dlstatus *dls = handle; + dolock(); + resetdlerror(); + if (!isValidStatus(dls)) + { + goto dlcloseerror; + } + if (dls->module == MAGIC_DYLIB_MOD) + { + const char *name; + if (!dls->lib) + { + name = "global context"; + } + else + { + name = get_lib_name(dls->lib); + } + warning("trying to close a .dylib!"); + error("Not closing \"%s\" - dynamic libraries cannot be closed", name); + goto dlcloseerror; + } + if (!dls->module) + { + error("module already closed"); + goto dlcloseerror; + } + + if (dls->refs == 1) + { + unsigned long options = 0; + void (*fini) (void); + if ((fini = dlsymIntern(dls, "__fini", 0))) + { + debug("calling _fini()"); + fini(); + } + options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; +#ifdef RTLD_NODELETE + if (isFlagSet(dls->mode, RTLD_NODELETE)) + options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; +#endif + if (!NSUnLinkModule(dls->module, options)) + { + error("unable to unlink module"); + goto dlcloseerror; + } + dls->refs--; + dls->module = 0; + /* Note: the dlstatus struct dls is neither removed from the list + * nor is the memory it occupies freed. This shouldn't pose a + * problem in mostly all cases, though. + */ + } + dounlock(); + return 0; + dlcloseerror: + dounlock(); + return 1; +} + +static const char *SDL_OSX_dlerror(void) +{ + struct dlthread *tss; + const char * err_str = NULL; + dlcompat_init_check(); + tss = pthread_getspecific(dlerror_key); + if (tss != NULL && tss->errset != 0) { + tss->errset = 0; + err_str = tss->errstr; + } + return (err_str); +} + +/* Given an address, return the mach_header for the image containing it + * or zero if the given address is not contained in any loaded images. + */ +static const struct mach_header *image_for_address(const void *address) +{ + unsigned long i; + unsigned long j; + unsigned long count = _dyld_image_count(); + const struct mach_header *mh = 0; + struct load_command *lc = 0; + unsigned long addr = 0; + for (i = 0; i < count; i++) + { + addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); + mh = _dyld_get_image_header(i); + if (mh) + { + lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); + for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if (LC_SEGMENT == lc->cmd && + addr >= ((struct segment_command *)lc)->vmaddr && + addr < + ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) + { + goto image_found; + } + } + } + mh = 0; + } + image_found: + return mh; +} + +#if 0 /* unused */ +static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) +{ +/* + FIXME: USe the routine image_for_address. +*/ + unsigned long i; + unsigned long j; + unsigned long count = _dyld_image_count(); + struct mach_header *mh = 0; + struct load_command *lc = 0; + unsigned long addr = NULL; + unsigned long table_off = (unsigned long)0; + int found = 0; + if (!info) + return 0; + dolock(); + resetdlerror(); + info->dli_fname = 0; + info->dli_fbase = 0; + info->dli_sname = 0; + info->dli_saddr = 0; +/* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> + * to darwin-development AT lists DOT apple DOT com and slightly modified + */ + for (i = 0; i < count; i++) + { + addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); + mh = _dyld_get_image_header(i); + if (mh) + { + lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); + for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if (LC_SEGMENT == lc->cmd && + addr >= ((struct segment_command *)lc)->vmaddr && + addr < + ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) + { + info->dli_fname = _dyld_get_image_name(i); + info->dli_fbase = (void *)mh; + found = 1; + break; + } + } + if (found) + break; + } + } + if (!found) + { + dounlock(); + return 0; + } + lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); + for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if (LC_SEGMENT == lc->cmd) + { + if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) + break; + } + } + table_off = + ((unsigned long)((struct segment_command *)lc)->vmaddr) - + ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); + debug("table off %x", table_off); + + lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); + for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) + { + if (LC_SYMTAB == lc->cmd) + { + + struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); + unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; + struct nlist *nearest = NULL; + unsigned long diff = 0xffffffff; + unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); + debug("symtable %x", symtable); + for (i = 0; i < numsyms; i++) + { + /* Ignore the following kinds of Symbols */ + if ((!symtable->n_value) /* Undefined */ + || (symtable->n_type >= N_PEXT) /* Debug symbol */ + || (!(symtable->n_type & N_EXT)) /* Local Symbol */ + ) + { + symtable++; + continue; + } + if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) + { + diff = (unsigned long)symtable->n_value - addr; + nearest = symtable; + } + symtable++; + } + if (nearest) + { + info->dli_saddr = nearest->n_value + ((void *)p - addr); + info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); + } + } + } + dounlock(); + return 1; +} +#endif + +/* + * Implement the dlfunc() interface, which behaves exactly the same as + * dlsym() except that it returns a function pointer instead of a data + * pointer. This can be used by applications to avoid compiler warnings + * about undefined behavior, and is intended as prior art for future + * POSIX standardization. This function requires that all pointer types + * have the same representation, which is true on all platforms FreeBSD + * runs on, but is not guaranteed by the C standard. + */ +#if 0 +static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol) +{ + union + { + void *d; + dlfunc_t f; + } rv; + int sym_len = SDL_strlen(symbol); + char *malloc_sym = NULL; + dolock(); + malloc_sym = SDL_malloc(sym_len + 2); + if (malloc_sym) + { + SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); + rv.d = dlsymIntern(handle, malloc_sym, 1); + SDL_free(malloc_sym); + } + else + { + error("Unable to allocate memory"); + goto dlfuncerror; + } + dounlock(); + return rv.f; + dlfuncerror: + dounlock(); + return NULL; +} +#endif + + + +/* dlcompat ends, here's the SDL interface... --ryan. */ + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); + const char *loaderror = SDL_OSX_dlerror(); + if ( handle == NULL ) { + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + } + return(handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + void *symbol = SDL_OSX_dlsym(handle, name); + if ( symbol == NULL ) { + SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); + } + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + if ( handle != NULL ) { + SDL_OSX_dlclose(handle); + } +} + +#endif /* SDL_LOADSO_DLCOMPAT */ diff --git a/3rdparty/SDL/src/loadso/mint/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/mint/SDL_sysloadso.c new file mode 100644 index 0000000..d6dd732 --- /dev/null +++ b/3rdparty/SDL/src/loadso/mint/SDL_sysloadso.c @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_LDG + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include <stdio.h> +#include <gem.h> +#include <ldg.h> + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + const char *loaderror = "Unknown error"; + void *handle = (void *)ldg_open((char *)sofile, ldg_global); + if ( handle == NULL ) { + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + } + return(handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + const char *loaderror = "Unknown error"; + void *symbol = (void *)ldg_find((char *)name, (LDG *)handle); + if ( symbol == NULL ) { + SDL_SetError("Failed loading %s: %s", name, loaderror); + } + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + if ( handle != NULL ) { + ldg_close((LDG *)handle, ldg_global); + } +} + +#endif /* SDL_LOADSO_LDG */ diff --git a/3rdparty/SDL/src/loadso/os2/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/os2/SDL_sysloadso.c new file mode 100644 index 0000000..62ea536 --- /dev/null +++ b/3rdparty/SDL/src/loadso/os2/SDL_sysloadso.c @@ -0,0 +1,71 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_OS2 + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include <stdio.h> +#define INCL_DOSERRORS +#define INCL_DOSMODULEMGR +#include <os2.h> + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + HMODULE handle = NULL; + char buf[512]; + APIRET ulrc = DosLoadModule(buf, sizeof (buf), (char *) sofile, &handle); + + /* Generate an error message if all loads failed */ + if ((ulrc != NO_ERROR) || (handle == NULL)) + SDL_SetError("Failed loading %s: %s", sofile, buf); + + return((void *) handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + const char *loaderror = "Unknown error"; + void *symbol = NULL; + APIRET ulrc = DosQueryProcAddr((HMODULE)handle, 0, (char *)name, &symbol); + if (ulrc == ERROR_INVALID_HANDLE) + loaderror = "Invalid module handle"; + else if (ulrc == ERROR_INVALID_NAME) + loaderror = "Symbol not found"; + + if (symbol == NULL) + SDL_SetError("Failed loading %s: %s", name, loaderror); + + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + if ( handle != NULL ) + DosFreeModule((HMODULE) handle); +} + +#endif /* SDL_LOADSO_OS2 */ diff --git a/3rdparty/SDL/src/loadso/win32/SDL_sysloadso.c b/3rdparty/SDL/src/loadso/win32/SDL_sysloadso.c new file mode 100644 index 0000000..784c7e7 --- /dev/null +++ b/3rdparty/SDL/src/loadso/win32/SDL_sysloadso.c @@ -0,0 +1,139 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_LOADSO_WIN32 + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + void *handle = NULL; + const char *loaderror = "Unknown error"; + +#if defined(_WIN32_WCE) + char errbuf[512]; + + wchar_t *errbuf_t = SDL_malloc(512 * sizeof(wchar_t)); + wchar_t *sofile_t = SDL_malloc((MAX_PATH+1) * sizeof(wchar_t)); + + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sofile, -1, sofile_t, MAX_PATH); + handle = (void *)LoadLibrary(sofile_t); + + /* Generate an error message if all loads failed */ + if ( handle == NULL ) { + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errbuf_t, SDL_arraysize(errbuf), NULL); + WideCharToMultiByte(CP_ACP, 0, errbuf_t, -1, errbuf, 511, NULL, NULL); + loaderror = errbuf; + } + + SDL_free(sofile_t); + SDL_free(errbuf_t); + +#else /*if defined(__WIN32__)*/ + char errbuf[512]; + + handle = (void *)LoadLibrary(sofile); + + /* Generate an error message if all loads failed */ + if ( handle == NULL ) { + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errbuf, SDL_arraysize(errbuf), NULL); + loaderror = errbuf; + } +#endif + + if ( handle == NULL ) { + SDL_SetError("Failed loading %s: %s", sofile, loaderror); + } + return(handle); +} + +void *SDL_LoadFunction(void *handle, const char *name) +{ + void *symbol = NULL; + const char *loaderror = "Unknown error"; + +#if defined(_WIN32_WCE) + char errbuf[512]; + int length = SDL_strlen(name); + + wchar_t *name_t = SDL_malloc((length + 1) * sizeof(wchar_t)); + wchar_t *errbuf_t = SDL_malloc(512 * sizeof(wchar_t)); + + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, name_t, length+1); + + symbol = (void *)GetProcAddress((HMODULE)handle, name_t); + if ( symbol == NULL ) { + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errbuf_t, SDL_arraysize(errbuf), NULL); + WideCharToMultiByte(CP_ACP, 0, errbuf_t, -1, errbuf, 511, NULL, NULL); + loaderror = errbuf; + } + + SDL_free(name_t); + SDL_free(errbuf_t); + +#else /*if defined(WIN32)*/ + char errbuf[512]; + + symbol = (void *)GetProcAddress((HMODULE)handle, name); + if ( symbol == NULL ) { + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM), + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errbuf, SDL_arraysize(errbuf), NULL); + loaderror = errbuf; + } +#endif + + if ( symbol == NULL ) { + SDL_SetError("Failed loading %s: %s", name, loaderror); + } + return(symbol); +} + +void SDL_UnloadObject(void *handle) +{ + if ( handle != NULL ) { + FreeLibrary((HMODULE)handle); + } +} + +#endif /* SDL_LOADSO_WIN32 */ diff --git a/3rdparty/SDL/src/main/beos/SDL_BeApp.cc b/3rdparty/SDL/src/main/beos/SDL_BeApp.cc new file mode 100644 index 0000000..8b79377 --- /dev/null +++ b/3rdparty/SDL/src/main/beos/SDL_BeApp.cc @@ -0,0 +1,111 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the BeApp specific portions of the application */ + +#include <AppKit.h> +#include <storage/Path.h> +#include <storage/Entry.h> +#include <unistd.h> + +#include "SDL_BeApp.h" +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" + +/* Flag to tell whether or not the Be application is active or not */ +int SDL_BeAppActive = 0; +static SDL_Thread *SDL_AppThread = NULL; + +static int StartBeApp(void *unused) +{ + if(!be_app) { + BApplication *App; + + App = new BApplication("application/x-SDL-executable"); + + App->Run(); + delete App; + } + return(0); +} + +/* Initialize the Be Application, if it's not already started */ +int SDL_InitBeApp(void) +{ + /* Create the BApplication that handles appserver interaction */ + if ( SDL_BeAppActive <= 0 ) { + SDL_AppThread = SDL_CreateThread(StartBeApp, NULL); + if ( SDL_AppThread == NULL ) { + SDL_SetError("Couldn't create BApplication thread"); + return(-1); + } + + /* Change working to directory to that of executable */ + app_info info; + if (B_OK == be_app->GetAppInfo(&info)) { + entry_ref ref = info.ref; + BEntry entry; + if (B_OK == entry.SetTo(&ref)) { + BPath path; + if (B_OK == path.SetTo(&entry)) { + if (B_OK == path.GetParent(&path)) { + chdir(path.Path()); + } + } + } + } + + do { + SDL_Delay(10); + } while ( (be_app == NULL) || be_app->IsLaunching() ); + + /* Mark the application active */ + SDL_BeAppActive = 0; + } + + /* Increment the application reference count */ + ++SDL_BeAppActive; + + /* The app is running, and we're ready to go */ + return(0); +} + +/* Quit the Be Application, if there's nothing left to do */ +void SDL_QuitBeApp(void) +{ + /* Decrement the application reference count */ + --SDL_BeAppActive; + + /* If the reference count reached zero, clean up the app */ + if ( SDL_BeAppActive == 0 ) { + if ( SDL_AppThread != NULL ) { + if ( be_app != NULL ) { /* Not tested */ + be_app->PostMessage(B_QUIT_REQUESTED); + } + SDL_WaitThread(SDL_AppThread, NULL); + SDL_AppThread = NULL; + } + /* be_app should now be NULL since be_app has quit */ + } +} diff --git a/3rdparty/SDL/src/main/beos/SDL_BeApp.h b/3rdparty/SDL/src/main/beos/SDL_BeApp.h new file mode 100644 index 0000000..9f88212 --- /dev/null +++ b/3rdparty/SDL/src/main/beos/SDL_BeApp.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the BeApp specific portions of the application */ + +/* Initialize the Be Application, if it's not already started */ +extern int SDL_InitBeApp(void); + +/* Quit the Be Application, if there's nothing left to do */ +extern void SDL_QuitBeApp(void); + +/* Flag to tell whether the app is active or not */ +extern int SDL_BeAppActive; diff --git a/3rdparty/SDL/src/main/dummy/SDL_dummy_main.c b/3rdparty/SDL/src/main/dummy/SDL_dummy_main.c new file mode 100644 index 0000000..da47d06 --- /dev/null +++ b/3rdparty/SDL/src/main/dummy/SDL_dummy_main.c @@ -0,0 +1,13 @@ + +/* Include the SDL main definition header */ +#include "SDL_main.h" + +#ifdef main +#undef main +int main(int argc, char *argv[]) +{ + return(SDL_main(argc, argv)); +} +#else +/* Nothing to do on this platform */ +#endif diff --git a/3rdparty/SDL/src/main/macos/SDL.r b/3rdparty/SDL/src/main/macos/SDL.r new file mode 100644 index 0000000..438f687 --- /dev/null +++ b/3rdparty/SDL/src/main/macos/SDL.r @@ -0,0 +1 @@ +data 'DLOG' (1000) {
$"0072 0040 00EA 01B3 0001 0100 0000 0000 0000 03E8 0C43 6F6D 6D61 6E64 204C 696E" /* .r.@..............Command Lin */
$"6500 280A" /* e.( */
};
data 'DLOG' (1001) {
$"0072 0040 00DB 01AC 0001 0100 0000 0000 0000 03E9 0C45 7272 6F72 2057 696E 646F" /* .r.@..............Error Windo */
$"7700 280A" /* w.( */
};
data 'DLOG' (1002) {
$"00B8 00BE 0147 01D8 0005 0100 0000 0000 0000 03EA 1643 6F6E 6669 726D 2044 6973" /* ...G.............Confirm Dis */
$"706C 6179 2043 6861 6E67 6510 280A" /* play Change.( */
};
data 'DITL' (1000) {
$"0005 0000 0000 0052 0113 0066 0158 0402 4F4B 0000 0000 0052 00C2 0066 0107 0406" /* .......R...f.X..OK.....R..f.... */
$"4361 6E63 656C 0000 0000 000F 0084 001F 0155 1000 0000 0000 0054 0019 0066 007D" /* Cancel..........U.......T...f.} */
$"050E 4F75 7470 7574 2074 6F20 6669 6C65 0000 0000 000F 0018 001F 007F 080D 436F" /* ..Output to file..............Co */
$"6D6D 616E 6420 4C69 6E65 3A00 0000 0000 0030 0018 0040 0158 0702 0080" /* mmand Line:......0...@.X... */
};
data 'DITL' (1001) {
$"0001 0000 0000 0046 0120 005A 015A 0402 4F4B 0000 0000 0010 000A 0038 0160 0800" /* .......F. .Z.Z..OK........8.`.. */
};
data 'DITL' (1002) {
$"0002 0000 0000 006F 001E 0083 0058 0406 4361 6E63 656C 0000 0000 006E 00C0 0082" /* .......o....X..Cancel.....n.. */
$"00FA 0402 4F4B 0000 0000 000E 000F 005F 010C 88B3 5468 6520 7365 7474 696E 6720" /* ...OK........._..The setting */
$"666F 7220 796F 7572 206D 6F6E 6974 6F72 2068 6173 2062 6565 6E20 6368 616E 6765" /* for your monitor has been change */
$"642C 2061 6E64 2069 7420 6D61 7920 6E6F 7420 6265 2064 6973 706C 6179 6564 2063" /* d, and it may not be displayed c */
$"6F72 7265 6374 6C79 2E20 546F 2063 6F6E 6669 726D 2074 6865 2064 6973 706C 6179" /* orrectly. To confirm the display */
$"2069 7320 636F 7272 6563 742C 2063 6C69 636B 204F 4B2E 2054 6F20 7265 7475 726E" /* is correct, click OK. To return */
$"2074 6F20 7468 6520 6F72 6967 696E 616C 2073 6574 7469 6E67 2C20 636C 6963 6B20" /* to the original setting, click */
$"4361 6E63 656C 2E00" /* Cancel.. */
};
data 'MENU' (128, preload) {
$"0080 0000 0000 0000 0000 FFFF FFFB 0114 0C41 626F 7574 2053 444C 2E2E 2E00 0000" /* ............About SDL...... */
$"0001 2D00 0000 0000" /* ..-..... */
};
data 'MENU' (129) {
$"0081 0000 0000 0000 0000 FFFF FFFF 0C56 6964 656F 2044 7269 7665 7219 4472 6177" /* ..........Video Driver.Draw */
$"5370 726F 636B 6574 2028 4675 6C6C 7363 7265 656E 2900 0000 001E 546F 6F6C 426F" /* Sprocket (Fullscreen).....ToolBo */
$"7820 2028 4675 6C6C 7363 7265 656E 2F57 696E 646F 7765 6429 0000 0000 00" /* x (Fullscreen/Windowed)..... */
};
data 'CNTL' (128) {
$"0000 0000 0010 0140 0000 0100 0064 0081 03F0 0000 0000 0D56 6964 656F 2044 7269" /* .......@.....d.......Video Dri */
$"7665 723A" /* ver: */
};
data 'TMPL' (128, "CLne") {
$"0C43 6F6D 6D61 6E64 204C 696E 6550 5354 520C 5669 6465 6F20 4472 6976 6572 5053" /* .Command LinePSTR.Video DriverPS */
$"5452 0C53 6176 6520 546F 2046 696C 6542 4F4F 4C" /* TR.Save To FileBOOL */
};
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/macos/SDL.shlib.r b/3rdparty/SDL/src/main/macos/SDL.shlib.r new file mode 100644 index 0000000..313c794 --- /dev/null +++ b/3rdparty/SDL/src/main/macos/SDL.shlib.r @@ -0,0 +1 @@ +
#ifndef __TYPES_R__
#include "Types.r"
#endif
#ifndef __BALLOONS_R__
#include "Balloons.r"
#endif
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define REVISION 13
#define STATE release /* development | alpha | beta | release */
#define RELEASE_NO 0 /* number after letter, or zero for release */
#define COUNTRY verUS
#define VERSION_STRING "1.2.13"
#define NAME "SDL"
#define SHORT_DESCRIPTION "Simple DirectMedia Layer by Sam Lantinga"
#define LONG_DESCRIPTION "A cross-platform multimedia library.\n\nhttp://www.libsdl.org"
resource 'vers' (1) {
VERSION_MAJOR,
(VERSION_MINOR << 4) | REVISION,
STATE,
RELEASE_NO,
COUNTRY,
VERSION_STRING,
VERSION_STRING
};
resource 'vers' (2) {
VERSION_MAJOR,
(VERSION_MINOR << 4) | REVISION,
STATE,
RELEASE_NO,
COUNTRY,
VERSION_STRING,
SHORT_DESCRIPTION
};
/* Extension Manager info */
data 'CCI' (128) {
NAME "\n\n"
LONG_DESCRIPTION
};
/* Finder help balloon */
resource 'hfdr' (kHMHelpID) {
HelpMgrVersion,
hmDefaultOptions,
0,
0,
{
HMStringItem
{
NAME "\n\n"
LONG_DESCRIPTION
}
}
};
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/macos/SDL_main.c b/3rdparty/SDL/src/main/macos/SDL_main.c new file mode 100644 index 0000000..ff1ffdc --- /dev/null +++ b/3rdparty/SDL/src/main/macos/SDL_main.c @@ -0,0 +1,610 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* This file takes care of command line argument parsing, and stdio redirection + in the MacOS environment. (stdio/stderr is *not* directed for Mach-O builds) + */ + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Dialogs.h> +#include <Fonts.h> +#include <Events.h> +#include <Resources.h> +#include <Folders.h> +#endif + +/* Include the SDL main definition header */ +#include "SDL.h" +#include "SDL_main.h" +#ifdef main +#undef main +#endif + +#if !(defined(__APPLE__) && defined(__MACH__)) +/* The standard output files */ +#define STDOUT_FILE "stdout.txt" +#define STDERR_FILE "stderr.txt" +#endif + +#if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON + /* In MPW, the qd global has been removed from the libraries */ + QDGlobals qd; +#endif + +/* Structure for keeping prefs in 1 variable */ +typedef struct { + Str255 command_line; + Str255 video_driver_name; + Boolean output_to_file; +} PrefsRecord; + +/* See if the command key is held down at startup */ +static Boolean CommandKeyIsDown(void) +{ + KeyMap theKeyMap; + + GetKeys(theKeyMap); + + if (((unsigned char *) theKeyMap)[6] & 0x80) { + return(true); + } + return(false); +} + +#if !(defined(__APPLE__) && defined(__MACH__)) + +/* Parse a command line buffer into arguments */ +static int ParseCommandLine(char *cmdline, char **argv) +{ + char *bufp; + int argc; + + argc = 0; + for ( bufp = cmdline; *bufp; ) { + /* Skip leading whitespace */ + while ( SDL_isspace(*bufp) ) { + ++bufp; + } + /* Skip over argument */ + if ( *bufp == '"' ) { + ++bufp; + if ( *bufp ) { + if ( argv ) { + argv[argc] = bufp; + } + ++argc; + } + /* Skip over word */ + while ( *bufp && (*bufp != '"') ) { + ++bufp; + } + } else { + if ( *bufp ) { + if ( argv ) { + argv[argc] = bufp; + } + ++argc; + } + /* Skip over word */ + while ( *bufp && ! SDL_isspace(*bufp) ) { + ++bufp; + } + } + if ( *bufp ) { + if ( argv ) { + *bufp = '\0'; + } + ++bufp; + } + } + if ( argv ) { + argv[argc] = NULL; + } + return(argc); +} + +/* Remove the output files if there was no output written */ +static void cleanup_output(void) +{ + FILE *file; + int empty; + + /* Flush the output in case anything is queued */ + fclose(stdout); + fclose(stderr); + + /* See if the files have any output in them */ + file = fopen(STDOUT_FILE, "rb"); + if ( file ) { + empty = (fgetc(file) == EOF) ? 1 : 0; + fclose(file); + if ( empty ) { + remove(STDOUT_FILE); + } + } + file = fopen(STDERR_FILE, "rb"); + if ( file ) { + empty = (fgetc(file) == EOF) ? 1 : 0; + fclose(file); + if ( empty ) { + remove(STDERR_FILE); + } + } +} + +#endif //!(defined(__APPLE__) && defined(__MACH__)) + +static int getCurrentAppName (StrFileName name) { + + ProcessSerialNumber process; + ProcessInfoRec process_info; + FSSpec process_fsp; + + process.highLongOfPSN = 0; + process.lowLongOfPSN = kCurrentProcess; + process_info.processInfoLength = sizeof (process_info); + process_info.processName = NULL; + process_info.processAppSpec = &process_fsp; + + if ( noErr != GetProcessInformation (&process, &process_info) ) + return 0; + + SDL_memcpy(name, process_fsp.name, process_fsp.name[0] + 1); + return 1; +} + +static int getPrefsFile (FSSpec *prefs_fsp, int create) { + + /* The prefs file name is the application name, possibly truncated, */ + /* plus " Preferences */ + + #define SUFFIX " Preferences" + #define MAX_NAME 19 /* 31 - strlen (SUFFIX) */ + + short volume_ref_number; + long directory_id; + StrFileName prefs_name; + StrFileName app_name; + + /* Get Preferences folder - works with Multiple Users */ + if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, + &volume_ref_number, &directory_id) ) + exit (-1); + + if ( ! getCurrentAppName (app_name) ) + exit (-1); + + /* Truncate if name is too long */ + if (app_name[0] > MAX_NAME ) + app_name[0] = MAX_NAME; + + SDL_memcpy(prefs_name + 1, app_name + 1, app_name[0]); + SDL_memcpy(prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX)); + prefs_name[0] = app_name[0] + strlen (SUFFIX); + + /* Make the file spec for prefs file */ + if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) ) { + if ( !create ) + return 0; + else { + /* Create the prefs file */ + SDL_memcpy(prefs_fsp->name, prefs_name, prefs_name[0] + 1); + prefs_fsp->parID = directory_id; + prefs_fsp->vRefNum = volume_ref_number; + + FSpCreateResFile (prefs_fsp, 0x3f3f3f3f, 'pref', 0); // '????' parsed as trigraph + + if ( noErr != ResError () ) + return 0; + } + } + return 1; +} + +static int readPrefsResource (PrefsRecord *prefs) { + + Handle prefs_handle; + + prefs_handle = Get1Resource( 'CLne', 128 ); + + if (prefs_handle != NULL) { + int offset = 0; +// int j = 0; + + HLock(prefs_handle); + + /* Get command line string */ + SDL_memcpy(prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1); + + /* Get video driver name */ + offset += (*prefs_handle)[0] + 1; + SDL_memcpy(prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1); + + /* Get save-to-file option (1 or 0) */ + offset += (*prefs_handle)[offset] + 1; + prefs->output_to_file = (*prefs_handle)[offset]; + + ReleaseResource( prefs_handle ); + + return ResError() == noErr; + } + + return 0; +} + +static int writePrefsResource (PrefsRecord *prefs, short resource_file) { + + Handle prefs_handle; + + UseResFile (resource_file); + + prefs_handle = Get1Resource ( 'CLne', 128 ); + if (prefs_handle != NULL) + RemoveResource (prefs_handle); + + prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 ); + if (prefs_handle != NULL) { + + int offset; + + HLock (prefs_handle); + + /* Command line text */ + offset = 0; + SDL_memcpy(*prefs_handle, prefs->command_line, prefs->command_line[0] + 1); + + /* Video driver name */ + offset += prefs->command_line[0] + 1; + SDL_memcpy(*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1); + + /* Output-to-file option */ + offset += prefs->video_driver_name[0] + 1; + *( *((char**)prefs_handle) + offset) = (char)prefs->output_to_file; + *( *((char**)prefs_handle) + offset + 1) = 0; + + AddResource (prefs_handle, 'CLne', 128, "\pCommand Line"); + WriteResource (prefs_handle); + UpdateResFile (resource_file); + DisposeHandle (prefs_handle); + + return ResError() == noErr; + } + + return 0; +} + +static int readPreferences (PrefsRecord *prefs) { + + int no_error = 1; + FSSpec prefs_fsp; + + /* Check for prefs file first */ + if ( getPrefsFile (&prefs_fsp, 0) ) { + + short prefs_resource; + + prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm); + if ( prefs_resource == -1 ) /* this shouldn't happen, but... */ + return 0; + + UseResFile (prefs_resource); + no_error = readPrefsResource (prefs); + CloseResFile (prefs_resource); + } + + /* Fall back to application's resource fork (reading only, so this is safe) */ + else { + + no_error = readPrefsResource (prefs); + } + + return no_error; +} + +static int writePreferences (PrefsRecord *prefs) { + + int no_error = 1; + FSSpec prefs_fsp; + + /* Get prefs file, create if it doesn't exist */ + if ( getPrefsFile (&prefs_fsp, 1) ) { + + short prefs_resource; + + prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm); + if (prefs_resource == -1) + return 0; + no_error = writePrefsResource (prefs, prefs_resource); + CloseResFile (prefs_resource); + } + + return no_error; +} + +/* This is where execution begins */ +int main(int argc, char *argv[]) +{ + +#if !(defined(__APPLE__) && defined(__MACH__)) +#pragma unused(argc, argv) +#endif + +#define DEFAULT_ARGS "\p" /* pascal string for default args */ +#define DEFAULT_VIDEO_DRIVER "\ptoolbox" /* pascal string for default video driver name */ +#define DEFAULT_OUTPUT_TO_FILE 1 /* 1 == output to file, 0 == no output */ + +#define VIDEO_ID_DRAWSPROCKET 1 /* these correspond to popup menu choices */ +#define VIDEO_ID_TOOLBOX 2 + + PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE }; + +#if !(defined(__APPLE__) && defined(__MACH__)) + int nargs; + char **args; + char *commandLine; + + StrFileName appNameText; +#endif + int videodriver = VIDEO_ID_TOOLBOX; + int settingsChanged = 0; + + long i; + + /* Kyle's SDL command-line dialog code ... */ +#if !TARGET_API_MAC_CARBON + InitGraf (&qd.thePort); + InitFonts (); + InitWindows (); + InitMenus (); + InitDialogs (nil); +#endif + InitCursor (); + FlushEvents(everyEvent,0); +#if !TARGET_API_MAC_CARBON + MaxApplZone (); +#endif + MoreMasters (); + MoreMasters (); +#if 0 + /* Intialize SDL, and put up a dialog if we fail */ + if ( SDL_Init (0) < 0 ) { + +#define kErr_OK 1 +#define kErr_Text 2 + + DialogPtr errorDialog; + short dummyType; + Rect dummyRect; + Handle dummyHandle; + short itemHit; + + errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1); + if (errorDialog == NULL) + return -1; + DrawDialog (errorDialog); + + GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect); + SetDialogItemText (dummyHandle, "\pError Initializing SDL"); + +#if TARGET_API_MAC_CARBON + SetPort (GetDialogPort(errorDialog)); +#else + SetPort (errorDialog); +#endif + do { + ModalDialog (nil, &itemHit); + } while (itemHit != kErr_OK); + + DisposeDialog (errorDialog); + exit (-1); + } + atexit(cleanup_output); + atexit(SDL_Quit); +#endif + +/* Set up SDL's QuickDraw environment */ +#if !TARGET_API_MAC_CARBON + SDL_InitQuickDraw(&qd); +#endif + + if ( readPreferences (&prefs) ) { + + if (SDL_memcmp(prefs.video_driver_name+1, "DSp", 3) == 0) + videodriver = 1; + else if (SDL_memcmp(prefs.video_driver_name+1, "toolbox", 7) == 0) + videodriver = 2; + } + + if ( CommandKeyIsDown() ) { + +#define kCL_OK 1 +#define kCL_Cancel 2 +#define kCL_Text 3 +#define kCL_File 4 +#define kCL_Video 6 + + DialogPtr commandDialog; + short dummyType; + Rect dummyRect; + Handle dummyHandle; + short itemHit; + #if TARGET_API_MAC_CARBON + ControlRef control; + #endif + + /* Assume that they will change settings, rather than do exhaustive check */ + settingsChanged = 1; + + /* Create dialog and display it */ + commandDialog = GetNewDialog (1000, nil, (WindowPtr)-1); + #if TARGET_API_MAC_CARBON + SetPort ( GetDialogPort(commandDialog) ); + #else + SetPort (commandDialog); + #endif + + /* Setup controls */ + #if TARGET_API_MAC_CARBON + GetDialogItemAsControl(commandDialog, kCL_File, &control); + SetControlValue (control, prefs.output_to_file); + #else + GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ + SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file ); + #endif + + GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); + SetDialogItemText (dummyHandle, prefs.command_line); + + #if TARGET_API_MAC_CARBON + GetDialogItemAsControl(commandDialog, kCL_Video, &control); + SetControlValue (control, videodriver); + #else + GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect); + SetControlValue ((ControlRef)dummyHandle, videodriver); + #endif + + SetDialogDefaultItem (commandDialog, kCL_OK); + SetDialogCancelItem (commandDialog, kCL_Cancel); + + do { + + ModalDialog(nil, &itemHit); /* wait for user response */ + + /* Toggle command-line output checkbox */ + if ( itemHit == kCL_File ) { + #if TARGET_API_MAC_CARBON + GetDialogItemAsControl(commandDialog, kCL_File, &control); + SetControlValue (control, !GetControlValue(control)); + #else + GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ + SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) ); + #endif + } + + } while (itemHit != kCL_OK && itemHit != kCL_Cancel); + + /* Get control values, even if they did not change */ + GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */ + GetDialogItemText (dummyHandle, prefs.command_line); + + #if TARGET_API_MAC_CARBON + GetDialogItemAsControl(commandDialog, kCL_File, &control); + prefs.output_to_file = GetControlValue(control); + #else + GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ + prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle); + #endif + + #if TARGET_API_MAC_CARBON + GetDialogItemAsControl(commandDialog, kCL_Video, &control); + videodriver = GetControlValue(control); + #else + GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect); + videodriver = GetControlValue ((ControlRef)dummyHandle); + #endif + + DisposeDialog (commandDialog); + + if (itemHit == kCL_Cancel ) { + exit (0); + } + } + + /* Set pseudo-environment variables for video driver, update prefs */ + switch ( videodriver ) { + case VIDEO_ID_DRAWSPROCKET: + SDL_putenv("SDL_VIDEODRIVER=DSp"); + SDL_memcpy(prefs.video_driver_name, "\pDSp", 4); + break; + case VIDEO_ID_TOOLBOX: + SDL_putenv("SDL_VIDEODRIVER=toolbox"); + SDL_memcpy(prefs.video_driver_name, "\ptoolbox", 8); + break; + } + +#if !(defined(__APPLE__) && defined(__MACH__)) + /* Redirect standard I/O to files */ + if ( prefs.output_to_file ) { + freopen (STDOUT_FILE, "w", stdout); + freopen (STDERR_FILE, "w", stderr); + } else { + fclose (stdout); + fclose (stderr); + } +#endif + + if (settingsChanged) { + /* Save the prefs, even if they might not have changed (but probably did) */ + if ( ! writePreferences (&prefs) ) + fprintf (stderr, "WARNING: Could not save preferences!\n"); + } + +#if !(defined(__APPLE__) && defined(__MACH__)) + appNameText[0] = 0; + getCurrentAppName (appNameText); /* check for error here ? */ + + commandLine = (char*) malloc (appNameText[0] + prefs.command_line[0] + 2); + if ( commandLine == NULL ) { + exit(-1); + } + + /* Rather than rewrite ParseCommandLine method, let's replace */ + /* any spaces in application name with underscores, */ + /* so that the app name is only 1 argument */ + for (i = 1; i < 1+appNameText[0]; i++) + if ( appNameText[i] == ' ' ) appNameText[i] = '_'; + + /* Copy app name & full command text to command-line C-string */ + SDL_memcpy(commandLine, appNameText + 1, appNameText[0]); + commandLine[appNameText[0]] = ' '; + SDL_memcpy(commandLine + appNameText[0] + 1, prefs.command_line + 1, prefs.command_line[0]); + commandLine[ appNameText[0] + 1 + prefs.command_line[0] ] = '\0'; + + /* Parse C-string into argv and argc */ + nargs = ParseCommandLine (commandLine, NULL); + args = (char **)malloc((nargs+1)*(sizeof *args)); + if ( args == NULL ) { + exit(-1); + } + ParseCommandLine (commandLine, args); + + /* Run the main application code */ + SDL_main(nargs, args); + free (args); + free (commandLine); + + /* Remove useless stdout.txt and stderr.txt */ + cleanup_output (); +#else // defined(__APPLE__) && defined(__MACH__) + SDL_main(argc, argv); +#endif + + /* Exit cleanly, calling atexit() functions */ + exit (0); + + /* Never reached, but keeps the compiler quiet */ + return (0); +} diff --git a/3rdparty/SDL/src/main/macos/SIZE.r b/3rdparty/SDL/src/main/macos/SIZE.r new file mode 100644 index 0000000..940f37f --- /dev/null +++ b/3rdparty/SDL/src/main/macos/SIZE.r @@ -0,0 +1 @@ +
#include "Processes.r"
resource 'SIZE' (-1) {
reserved,
acceptSuspendResumeEvents,
reserved,
canBackground,
doesActivateOnFGSwitch,
backgroundAndForeground,
getFrontClicks,
ignoreAppDiedEvents,
is32BitCompatible,
isHighLevelEventAware,
onlyLocalHLEvents,
notStationeryAware,
useTextEditServices,
reserved,
reserved,
reserved,
5242880, // 5 megs minimum
5242880 // 5 megs maximum
};
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/macos/exports/Makefile b/3rdparty/SDL/src/main/macos/exports/Makefile new file mode 100644 index 0000000..5f37ae0 --- /dev/null +++ b/3rdparty/SDL/src/main/macos/exports/Makefile @@ -0,0 +1,39 @@ + +EXPORTS = SDL.x +HEADERS = \ + ../../../../include/SDL.h \ + ../../../../include/SDL_active.h \ + ../../../../include/SDL_audio.h \ + ../../../../include/SDL_byteorder.h \ + ../../../../include/SDL_cdrom.h \ + ../../../../include/SDL_copying.h \ + ../../../../include/SDL_cpuinfo.h \ + ../../../../include/SDL_endian.h \ + ../../../../include/SDL_error.h \ + ../../../../include/SDL_events.h \ + ../../../../include/SDL_getenv.h \ + ../../../../include/SDL_joystick.h \ + ../../../../include/SDL_keyboard.h \ + ../../../../include/SDL_keysym.h \ + ../../../../include/SDL_loadso.h \ + ../../../../include/SDL_mouse.h \ + ../../../../include/SDL_mutex.h \ + ../../../../include/SDL_name.h \ + ../../../../include/SDL_platform.h \ + ../../../../include/SDL_quit.h \ + ../../../../include/SDL_rwops.h \ + ../../../../include/SDL_syswm.h \ + ../../../../include/SDL_thread.h \ + ../../../../include/SDL_timer.h \ + ../../../../include/SDL_types.h \ + ../../../../include/SDL_version.h \ + ../../../../include/SDL_video.h + + +all: $(EXPORTS) + +$(EXPORTS): Makefile gendef.pl $(HEADERS) + perl gendef.pl $(HEADERS) >$@ || rm $@ + +clean: + rm -f $(EXPORTS) diff --git a/3rdparty/SDL/src/main/macos/exports/SDL.x b/3rdparty/SDL/src/main/macos/exports/SDL.x new file mode 100644 index 0000000..4830c43 --- /dev/null +++ b/3rdparty/SDL/src/main/macos/exports/SDL.x @@ -0,0 +1 @@ + SDL_Init
SDL_InitSubSystem
SDL_QuitSubSystem
SDL_WasInit
SDL_Quit
SDL_GetAppState
SDL_AudioInit
SDL_AudioQuit
SDL_AudioDriverName
SDL_OpenAudio
SDL_GetAudioStatus
SDL_PauseAudio
SDL_LoadWAV_RW
SDL_FreeWAV
SDL_BuildAudioCVT
SDL_ConvertAudio
SDL_MixAudio
SDL_LockAudio
SDL_UnlockAudio
SDL_CloseAudio
SDL_CDNumDrives
SDL_CDName
SDL_CDOpen
SDL_CDStatus
SDL_CDPlayTracks
SDL_CDPlay
SDL_CDPause
SDL_CDResume
SDL_CDStop
SDL_CDEject
SDL_CDClose
SDL_HasRDTSC
SDL_HasMMX
SDL_HasMMXExt
SDL_Has3DNow
SDL_Has3DNowExt
SDL_HasSSE
SDL_HasSSE2
SDL_HasAltiVec
SDL_SetError
SDL_GetError
SDL_ClearError
SDL_Error
SDL_PumpEvents
SDL_PeepEvents
SDL_PollEvent
SDL_WaitEvent
SDL_PushEvent
SDL_SetEventFilter
SDL_GetEventFilter
SDL_EventState
SDL_NumJoysticks
SDL_JoystickName
SDL_JoystickOpen
SDL_JoystickOpened
SDL_JoystickIndex
SDL_JoystickNumAxes
SDL_JoystickNumBalls
SDL_JoystickNumHats
SDL_JoystickNumButtons
SDL_JoystickUpdate
SDL_JoystickEventState
SDL_JoystickGetAxis
SDL_JoystickGetHat
SDL_JoystickGetBall
SDL_JoystickGetButton
SDL_JoystickClose
SDL_EnableUNICODE
SDL_EnableKeyRepeat
SDL_GetKeyRepeat
SDL_GetKeyState
SDL_GetModState
SDL_SetModState
SDL_GetKeyName
SDL_LoadObject
SDL_LoadFunction
SDL_UnloadObject
SDL_GetMouseState
SDL_GetRelativeMouseState
SDL_WarpMouse
SDL_CreateCursor
SDL_SetCursor
SDL_GetCursor
SDL_FreeCursor
SDL_ShowCursor
SDL_CreateMutex
SDL_mutexP
SDL_mutexV
SDL_DestroyMutex
SDL_CreateSemaphore
SDL_DestroySemaphore
SDL_SemWait
SDL_SemTryWait
SDL_SemWaitTimeout
SDL_SemPost
SDL_SemValue
SDL_CreateCond
SDL_DestroyCond
SDL_CondSignal
SDL_CondBroadcast
SDL_CondWait
SDL_CondWaitTimeout
SDL_RWFromFile
SDL_RWFromFP
SDL_RWFromMem
SDL_RWFromConstMem
SDL_AllocRW
SDL_FreeRW
SDL_ReadLE16
SDL_ReadBE16
SDL_ReadLE32
SDL_ReadBE32
SDL_ReadLE64
SDL_ReadBE64
SDL_WriteLE16
SDL_WriteBE16
SDL_WriteLE32
SDL_WriteBE32
SDL_WriteLE64
SDL_WriteBE64
SDL_GetWMInfo
SDL_CreateThread
SDL_CreateThread
SDL_ThreadID
SDL_GetThreadID
SDL_WaitThread
SDL_KillThread
SDL_GetTicks
SDL_Delay
SDL_SetTimer
SDL_AddTimer
SDL_RemoveTimer
SDL_Linked_Version
SDL_VideoInit
SDL_VideoQuit
SDL_VideoDriverName
SDL_GetVideoSurface
SDL_GetVideoInfo
SDL_VideoModeOK
SDL_ListModes
SDL_SetVideoMode
SDL_UpdateRects
SDL_UpdateRect
SDL_Flip
SDL_SetGamma
SDL_SetGammaRamp
SDL_GetGammaRamp
SDL_SetColors
SDL_SetPalette
SDL_MapRGB
SDL_MapRGBA
SDL_GetRGB
SDL_GetRGBA
SDL_CreateRGBSurface
SDL_CreateRGBSurfaceFrom
SDL_FreeSurface
SDL_LockSurface
SDL_UnlockSurface
SDL_LoadBMP_RW
SDL_SaveBMP_RW
SDL_SetColorKey
SDL_SetAlpha
SDL_SetClipRect
SDL_GetClipRect
SDL_ConvertSurface
SDL_UpperBlit
SDL_LowerBlit
SDL_FillRect
SDL_DisplayFormat
SDL_DisplayFormatAlpha
SDL_CreateYUVOverlay
SDL_LockYUVOverlay
SDL_UnlockYUVOverlay
SDL_DisplayYUVOverlay
SDL_FreeYUVOverlay
SDL_GL_LoadLibrary
SDL_GL_GetProcAddress
SDL_GL_SetAttribute
SDL_GL_GetAttribute
SDL_GL_SwapBuffers
SDL_GL_UpdateRects
SDL_GL_Lock
SDL_GL_Unlock
SDL_WM_SetCaption
SDL_WM_GetCaption
SDL_WM_SetIcon
SDL_WM_IconifyWindow
SDL_WM_ToggleFullScreen
SDL_WM_GrabInput
SDL_SoftStretch
SDL_putenv
SDL_getenv
SDL_qsort
SDL_revcpy
SDL_strlcpy
SDL_strlcat
SDL_strdup
SDL_strrev
SDL_strupr
SDL_strlwr
SDL_ltoa
SDL_ultoa
SDL_strcasecmp
SDL_strncasecmp
SDL_snprintf
SDL_vsnprintf
SDL_iconv
SDL_iconv_string
SDL_InitQuickDraw
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/macos/exports/gendef.pl b/3rdparty/SDL/src/main/macos/exports/gendef.pl new file mode 100644 index 0000000..9cffca9 --- /dev/null +++ b/3rdparty/SDL/src/main/macos/exports/gendef.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl +# +# Program to take a set of header files and generate DLL export definitions + +# Special exports to ignore for this platform + +while ( ($file = shift(@ARGV)) ) { + if ( ! defined(open(FILE, $file)) ) { + warn "Couldn't open $file: $!\n"; + next; + } + $printed_header = 0; + $file =~ s,.*/,,; + while (<FILE>) { + if ( / DECLSPEC.* SDLCALL ([^\s\(]+)/ ) { + if ( not $exclude{$1} ) { + print "\t$1\r"; + } + } + } + close(FILE); +} + +# Special exports to include for this platform +print "\tSDL_putenv\r"; +print "\tSDL_getenv\r"; +print "\tSDL_qsort\r"; +print "\tSDL_revcpy\r"; +print "\tSDL_strlcpy\r"; +print "\tSDL_strlcat\r"; +print "\tSDL_strdup\r"; +print "\tSDL_strrev\r"; +print "\tSDL_strupr\r"; +print "\tSDL_strlwr\r"; +print "\tSDL_ltoa\r"; +print "\tSDL_ultoa\r"; +print "\tSDL_strcasecmp\r"; +print "\tSDL_strncasecmp\r"; +print "\tSDL_snprintf\r"; +print "\tSDL_vsnprintf\r"; +print "\tSDL_iconv\r"; +print "\tSDL_iconv_string\r"; +print "\tSDL_InitQuickDraw\r"; diff --git a/3rdparty/SDL/src/main/macosx/Info.plist.in b/3rdparty/SDL/src/main/macosx/Info.plist.in new file mode 100644 index 0000000..b3d69ab --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/Info.plist.in @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> +<plist version="0.9"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>@EXECUTABLE_NAME@</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>@PACKAGE@</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>@VERSION@</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>NSMainNibFile</key> + <string>SDLMain.nib</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/3rdparty/SDL/src/main/macosx/SDLMain.h b/3rdparty/SDL/src/main/macosx/SDLMain.h new file mode 100644 index 0000000..c56d90c --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/SDLMain.h @@ -0,0 +1,16 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser <dwaliss1@purdue.edu> + Non-NIB-Code & other changes: Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs +*/ + +#ifndef _SDLMain_h_ +#define _SDLMain_h_ + +#import <Cocoa/Cocoa.h> + +@interface SDLMain : NSObject +@end + +#endif /* _SDLMain_h_ */ diff --git a/3rdparty/SDL/src/main/macosx/SDLMain.m b/3rdparty/SDL/src/main/macosx/SDLMain.m new file mode 100644 index 0000000..2434f81 --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/SDLMain.m @@ -0,0 +1,381 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser <dwaliss1@purdue.edu> + Non-NIB-Code & other changes: Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs +*/ + +#include "SDL.h" +#include "SDLMain.h" +#include <sys/param.h> /* for MAXPATHLEN */ +#include <unistd.h> + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ +@interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; +@end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + const NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end +#endif + +@interface NSApplication (SDLApplication) +@end + +@implementation NSApplication (SDLApplication) +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { + chdir(parentdir); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [NSApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [NSApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} + diff --git a/3rdparty/SDL/src/main/macosx/SDLMain.nib/classes.nib b/3rdparty/SDL/src/main/macosx/SDLMain.nib/classes.nib new file mode 100644 index 0000000..f8f4e9a --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/SDLMain.nib/classes.nib @@ -0,0 +1,12 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {makeFullscreen = id; quit = id; }; + CLASS = SDLMain; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +} diff --git a/3rdparty/SDL/src/main/macosx/SDLMain.nib/info.nib b/3rdparty/SDL/src/main/macosx/SDLMain.nib/info.nib new file mode 100644 index 0000000..2211cf9 --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/SDLMain.nib/info.nib @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> +<plist version="0.9"> +<dict> + <key>IBDocumentLocation</key> + <string>49 97 356 240 0 0 987 746 </string> + <key>IBMainMenuLocation</key> + <string>20 515 195 44 0 46 800 532 </string> + <key>IBUserGuides</key> + <dict/> +</dict> +</plist> diff --git a/3rdparty/SDL/src/main/macosx/SDLMain.nib/objects.nib b/3rdparty/SDL/src/main/macosx/SDLMain.nib/objects.nib Binary files differnew file mode 100644 index 0000000..9f697b0 --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/SDLMain.nib/objects.nib diff --git a/3rdparty/SDL/src/main/macosx/info.nib b/3rdparty/SDL/src/main/macosx/info.nib new file mode 100644 index 0000000..d13726f --- /dev/null +++ b/3rdparty/SDL/src/main/macosx/info.nib @@ -0,0 +1 @@ +// This is just a stub file to force automake to create the install directory diff --git a/3rdparty/SDL/src/main/qtopia/SDL_qtopia_main.cc b/3rdparty/SDL/src/main/qtopia/SDL_qtopia_main.cc new file mode 100644 index 0000000..46fd518 --- /dev/null +++ b/3rdparty/SDL/src/main/qtopia/SDL_qtopia_main.cc @@ -0,0 +1,47 @@ + +/* Include the SDL main definition header */ +#include "SDL_main.h" +#include <stdlib.h> +#include <unistd.h> +#ifdef main +#undef main +#endif +#ifdef QWS +#include <qpe/qpeapplication.h> +#include <qapplication.h> +#include <qpe/qpeapplication.h> +#include <stdlib.h> + +// Workaround for OPIE to remove taskbar icon. Also fixes +// some issues in Qtopia where there are left-over qcop files in /tmp/. +// I'm guessing this will also clean up the taskbar in the Sharp version +// of Qtopia. +static inline void cleanupQCop() { + QString appname(qApp->argv()[0]); + int slash = appname.findRev("/"); + if(slash != -1) { appname = appname.mid(slash+1); } + QString cmd = QPEApplication::qpeDir() + "bin/qcop QPE/System 'closing(QString)' '"+appname+"'"; + system(cmd.latin1()); + cmd = "/tmp/qcop-msg-"+appname; + unlink(cmd.latin1()); +} + +static QPEApplication *app; +#endif + +extern int SDL_main(int argc, char *argv[]); + +int main(int argc, char *argv[]) +{ +#ifdef QWS + // This initializes the Qtopia application. It needs to be done here + // because it parses command line options. + app = new QPEApplication(argc, argv); + QWidget dummy; + app->showMainWidget(&dummy); + atexit(cleanupQCop); +#endif + // Exit here because if return is used, the application + // doesn't seem to quit correctly. + exit(SDL_main(argc, argv)); +} diff --git a/3rdparty/SDL/src/main/symbian/EKA1/SDL_main.cpp b/3rdparty/SDL/src/main/symbian/EKA1/SDL_main.cpp new file mode 100644 index 0000000..683db87 --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA1/SDL_main.cpp @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_main.cpp + The Epoc executable startup functions + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) +*/ + +#include <e32std.h> +#include <e32def.h> +#include <e32svr.h> +#include <e32base.h> +#include <estlib.h> +#include <stdlib.h> +#include <stdio.h> +#include <w32std.h> +#include <apgtask.h> + +#include "SDL_error.h" + +#if defined(__WINS__) +#include <estw32.h> +IMPORT_C void RegisterWsExe(const TDesC &aName); +#endif + +/* The prototype for the application's main() function */ +#define main SDL_main +extern "C" int main (int argc, char *argv[], char *envp[]); +extern "C" void exit (int ret); + + +/* Epoc main function */ + +#ifdef __WINS__ + + +void GetCmdLine(int& aArgc, char**& aArgv) + { + RChunk chunk; + + if(chunk.OpenGlobal(RThread().Name(), ETrue) != KErrNone) + return; + + TUint* ptr = (TUint*) chunk.Base(); + if(ptr != NULL) + { + aArgc = (int) *(ptr); // count + aArgv = (char**) *(ptr + 1); + } + chunk.Close(); + } + +#endif + + +TInt E32Main() + { + /* Get the clean-up stack */ + CTrapCleanup* cleanup = CTrapCleanup::New(); + + /* Arrange for multi-threaded operation */ + SpawnPosixServerThread(); + + /* Get args and environment */ + int argc=0; + char** argv=0; + char** envp=0; + +#ifndef __WINS__ + __crt0(argc,argv,envp); +#else + GetCmdLine(argc, argv); +#endif + /* Start the application! */ + + /* Create stdlib */ + _REENT; + + /* Set process and thread priority and name */ + + RThread currentThread; + RProcess thisProcess; + TParse exeName; + exeName.Set(thisProcess.FileName(), NULL, NULL); + currentThread.Rename(exeName.Name()); + currentThread.SetProcessPriority(EPriorityLow); + currentThread.SetPriority(EPriorityMuchLess); + + /* Call stdlib main */ + int ret = main(argc, argv, envp); /* !! process exits here if there is "exit()" in main! */ + + /* Call exit */ + //exit(ret); /* !! process exits here! */ + //Markus: I do not understand above + //I commented it at let this function + //to return ret value - was it purpose + //that cleanup below is not called at all - why? + + /* Free resources and return */ + + _cleanup(); //this is normally called at exit, I call it here, Markus + + CloseSTDLIB(); + delete cleanup; +#ifdef __WINS__ +// User::Panic(_L("exit"), ret); + // RThread().Kill(ret); //Markus get rid of this thread + // RThread().RaiseException(EExcKill); +#endif + return ret;//Markus, or exit(ret); ?? + //return(KErrNone); + } + + +#ifdef __WINS__ +EXPORT_C TInt WinsMain() + { + return E32Main(); + // return WinsMain(0, 0, 0); + } +#endif + +/* Epoc dll entry point */ +#if defined(__WINS__) +GLDEF_C TInt E32Dll(TDllReason) + { + return(KErrNone); + } +#endif + + diff --git a/3rdparty/SDL/src/main/symbian/EKA2/SDL_main.cpp b/3rdparty/SDL/src/main/symbian/EKA2/SDL_main.cpp new file mode 100644 index 0000000..3dc69d4 --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA2/SDL_main.cpp @@ -0,0 +1,1035 @@ +/* + SDL_Main.cpp + Symbian OS services for SDL + + Markus Mertama +*/ + + +#include "epoc_sdl.h" + +#include"sdlepocapi.h" +#include <e32base.h> +#include <estlib.h> +#include <stdio.h> +#include <badesca.h> + +#include "vectorbuffer.h" +#include <w32std.h> +#include <aknappui.h> +#include <aknapp.h> +#include "SDL_epocevents_c.h" +#include "SDL_keysym.h" +#include "dsa.h" + + +#ifdef SYMBIANC +#include <reent.h> +#endif + +//Markus Mertama + + +extern SDLKey* KeyMap(); +extern void ResetKeyMap(); + +class CCurrentAppUi; + +//const TUid KSDLUid = { 0xF01F3D69 }; + +NONSHARABLE_CLASS(EnvUtils) + { + public: + static void DisableKeyBlocking(); + static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus); + }; + +TInt Panic(TInt aErr, TInt aLine) + { + TBuf<64> b; + b.Format(_L("Main at %d"), aLine); + User::Panic(b, aErr); + return 0; + } + + +NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi + { + public: + static CCurrentAppUi* Cast(CEikAppUi* aUi); + void DisableKeyBlocking(); + }; + + +CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi) + { + return static_cast<CCurrentAppUi*>(aUi); + } + +void CCurrentAppUi::DisableKeyBlocking() + { + SetKeyBlockMode(ENoKeyBlock); + } + + +class CEventQueue : public CBase, public MEventQueue + { + public: + static CEventQueue* NewL(); + ~CEventQueue(); + public: + TInt Append(const TWsEvent& aEvent); + const TWsEvent& Shift(); + void Lock(); + void Unlock(); + TBool HasData(); + private: + TVector<TWsEvent, 64> iVector; + RCriticalSection iCS; + }; + + CEventQueue* CEventQueue::NewL() + { + CEventQueue* q = new (ELeave) CEventQueue(); + CleanupStack::PushL(q); + User::LeaveIfError(q->iCS.CreateLocal()); + CleanupStack::Pop(); + return q; + } + +CEventQueue::~CEventQueue() + { + iCS.Close(); + } + +TInt CEventQueue::Append(const TWsEvent& aEvent) + { + iCS.Wait(); + const TInt err = iVector.Append(aEvent); + iCS.Signal(); + return err; + } + + +TBool CEventQueue::HasData() + { + return iVector.Size() > 0; + } + + +void CEventQueue::Lock() + { + iCS.Wait(); + } + +void CEventQueue::Unlock() + { + iCS.Signal(); + } + +const TWsEvent& CEventQueue::Shift() + { + const TWsEvent& event = iVector.Shift(); + return event; + } + + +TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) : +iOperation(aOperation), iItem(aItem), iThread(RThread().Id()) + { + } + +class CEikonEnv; +class CSdlAppServ; + + +NONSHARABLE_CLASS(EpocSdlEnvData) + { + public: + void Free(); + CEventQueue* iEventQueue; + TMainFunc iMain; + TInt iEpocEnvFlags; + int iArgc; + char** iArgv; + CDsa* iDsa; + CSdlAppServ* iAppSrv; + TThreadId iId; + CArrayFix<TSdlCleanupItem>* iCleanupItems; + CEikAppUi* iAppUi; + CSDL* iSdl; + }; + + +EpocSdlEnvData* gEpocEnv; + +#define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;} + +MAINFUNC(1) +MAINFUNC(2) +MAINFUNC(3) +MAINFUNC(4) +MAINFUNC(5) +MAINFUNC(6) + +EXPORT_C TMainFunc::TMainFunc() + { + Mem::FillZ(iMainFunc, sizeof(iMainFunc)); + } + + +const void* TMainFunc::operator[](TInt aIndex) const + { + return iMainFunc[aIndex]; + } + + +NONSHARABLE_CLASS(CSdlAppServ) : public CActive + { + public: + enum + { + EAppSrvNoop = CDsa::ELastDsaRequest, + EAppSrvWindowWidth, + EAppSrvWindowHeight, + EAppSrvWindowDisplayMode, + EAppSrvWindowPointerCursorMode, + EAppSrvDsaStatus, + EAppSrvStopThread, + EAppSrvWaitDsa + }; + CSdlAppServ(); + void ConstructL(); + ~CSdlAppServ(); + TInt Request(TInt aService); + TInt RequestValue(TInt aService); + void Init(); + void PanicMain(TInt aReason); + void PanicMain(const TDesC& aInfo, TInt aReason); + void SetObserver(MSDLObserver* aObserver); + TInt ObserverEvent(TInt aEvent, TInt aParam); + void SetParam(TInt aParam); + void HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread); + MSDLObserver* Observer(); + private: + void RunL(); + void DoCancel(); + private: + const TThreadId iMainId; + RThread iAppThread; + TInt iService; + TInt iReturnValue; + RSemaphore iSema; + MSDLObserver* iObserver; + TRequestStatus* iStatusPtr; + }; + +CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id()) + { + } + + + +MSDLObserver* CSdlAppServ::Observer() + { + return iObserver; + } + + +void CSdlAppServ::SetObserver(MSDLObserver* aObserver) + { + iObserver = aObserver; + } + +TInt CSdlAppServ::ObserverEvent(TInt aEvent, TInt aParam) + { + if(iObserver != NULL) + { + if(RThread().Id() == gEpocEnv->iId) + { + return iObserver->SdlThreadEvent(aEvent, aParam); + } + else if(RThread().Id() == iMainId) + { + return iObserver->SdlEvent(aEvent, aParam); + } + PANIC(KErrNotSupported); + } + return 0; + } + +void CSdlAppServ::PanicMain(TInt aReason) + { + iAppThread.Panic(RThread().Name(), aReason); + } + +void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason) + { + iAppThread.Panic(aInfo, aReason); + } + +void CSdlAppServ::ConstructL() + { + CActiveScheduler::Add(this); + User::LeaveIfError(iSema.CreateLocal(1)); + iStatus = KRequestPending; + iStatusPtr = &iStatus; + SetActive(); + } + + CSdlAppServ::~CSdlAppServ() + { + Cancel(); + if(iSema.Handle() != NULL) + iSema.Signal(); + iSema.Close(); + iAppThread.Close(); + } + +TInt CSdlAppServ::Request(TInt aService) + { + if(RThread().Id() != iAppThread.Id()) + { + iSema.Wait(); + iService = aService; + iAppThread.RequestComplete(iStatusPtr, KErrNone); + return KErrNone; + } + return KErrBadHandle; + } + +TInt CSdlAppServ::RequestValue(TInt aService) + { + Request(aService); + Request(EAppSrvNoop); + return iReturnValue; + } + +void CSdlAppServ::Init() + { + PANIC_IF_ERROR(iAppThread.Open(iMainId)); + } + +void CSdlAppServ::SetParam(TInt aParam) + { + iReturnValue = aParam; + } + +void CSdlAppServ::HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread) + { + if(iObserver != NULL && aMainThread) + { + switch(aService) + { + case MSDLObserver::EEventScreenSizeChanged: + if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette) + EpocSdlEnv::LockPalette(EFalse); + break; + } + } + if(!aMainThread && aService == MSDLObserver::EEventSuspend) + { + if(iObserver == NULL || + (gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend)) + { + EpocSdlEnv::Suspend(); + } + } + } + +void CSdlAppServ::RunL() + { + if(iStatus == KErrNone) + { + switch(iService) + { + case CSdlAppServ::EAppSrvWaitDsa: + EpocSdlEnv::SetWaitDsa(); + iReturnValue = EpocSdlEnv::IsDsaAvailable(); + // } + // gEpocEnv->iDsa->Stop(); + // gEpocEnv->iDsa->RestartL(); + break; + case CSdlAppServ::EAppSrvStopThread: + gEpocEnv->iDsa->SetSuspend(); + break; + case EpocSdlEnv::EDisableKeyBlocking: + EnvUtils::DisableKeyBlocking(); + break; + + case EAppSrvWindowPointerCursorMode: + iReturnValue = gEpocEnv->iDsa != NULL ? + gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady; + break; + case EAppSrvDsaStatus: + gEpocEnv->iDsa->Stop(); + iReturnValue = KErrNone; + break; + case CDsa::ERequestUpdate: + gEpocEnv->iDsa->UnlockHWSurfaceRequestComplete(); + break; + case EAppSrvNoop: + break; + case MSDLObserver::EEventResume: + case MSDLObserver::EEventSuspend: + case MSDLObserver::EEventScreenSizeChanged: + case MSDLObserver::EEventWindowReserved: + case MSDLObserver::EEventKeyMapInit: + case MSDLObserver::EEventWindowNotAvailable: + case MSDLObserver::EEventMainExit: + iReturnValue = ObserverEvent(iService, iReturnValue); + HandleObserverValue(iService, iReturnValue, ETrue); + break; + default: + PANIC(KErrNotSupported); + } + iStatus = KRequestPending; + iStatusPtr = &iStatus; + SetActive(); + } + iSema.Signal(); + } + +void CSdlAppServ::DoCancel() + { + iSema.Wait(); + TRequestStatus* s = &iStatus; + iAppThread.RequestComplete(s, KErrCancel); + } + + + +MEventQueue& EpocSdlEnv::EventQueue() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return *gEpocEnv->iEventQueue; + } + + +TBool EpocSdlEnv::Flags(TInt aFlag) + { + const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag; + return flag == aFlag; + } + +TInt EpocSdlEnv::Argc() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iArgc; + } + + +char** EpocSdlEnv::Argv() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iArgv; + } + + +TBool EpocSdlEnv::IsDsaAvailable() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable(); + } + + +void EpocSdlEnv::WaitDsaAvailable() + { + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0); + gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread); + if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) + { + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0); + } + } + +void EpocSdlEnv::Suspend() + { + if(gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) + { + // gEpocEnv->iDsa->ReleaseStop(); + gEpocEnv->iDsa->SetSuspend(); + RThread().Suspend(); + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0); + } + } + +void EpocSdlEnv::SetWaitDsa() + { + if(!IsDsaAvailable()) + { + RThread th; + th.Open(gEpocEnv->iId); + th.Suspend(); + th.Close(); + gEpocEnv->iDsa->SetSuspend(); + } + } + +void EpocSdlEnv::Resume() + { + gEpocEnv->iDsa->Resume(); + RThread th; + th.Open(gEpocEnv->iId); + th.Resume(); + th.Close(); + + const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0); + gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue); + } + + +TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode) + { + return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode); + } + +TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode) + { + return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode); + } + + +void EpocSdlEnv::UnlockHwSurface() + { + gEpocEnv->iDsa->UnlockHwSurface(); + } + +TUint8* EpocSdlEnv::LockHwSurface() + { + return gEpocEnv->iDsa->LockHwSurface(); + } + + +void EpocSdlEnv::UpdateSwSurface() + { + gEpocEnv->iDsa->UpdateSwSurface(); + } + +TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect) + { + return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect); + } + +void EpocSdlEnv::Request(TInt aService) + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + gEpocEnv->iAppSrv->Request(aService); + } + + +TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize) + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + if(EpocSdlEnv::Flags(CSDL::EAllowImageResize) && gEpocEnv->iDsa->WindowSize() != aRequestedSize) + { + TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize)); + } + return gEpocEnv->iDsa->WindowSize(); + } + + TSize EpocSdlEnv::WindowSize() + { + __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); + return gEpocEnv->iDsa->WindowSize(); + } + +TDisplayMode EpocSdlEnv::DisplayMode() + { + return gEpocEnv->iDsa->DisplayMode(); + } + +TPointerCursorMode EpocSdlEnv::PointerMode() + { + return static_cast<TPointerCursorMode> + (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode)); + } + +TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette) + { + return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette); + } + +void EpocSdlEnv::PanicMain(TInt aErr) + { + gEpocEnv->iAppSrv->PanicMain(aErr); + } + + +TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem) + { + TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem)); + return err; + } + +void EpocSdlEnv::RemoveCleanupItem(TAny* aItem) + { + for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++) + { + if(gEpocEnv->iCleanupItems->At(i).iItem == aItem) + gEpocEnv->iCleanupItems->Delete(i); + } + } + +void EpocSdlEnv::CleanupItems() + { + const TThreadId id = RThread().Id(); + TInt last = gEpocEnv->iCleanupItems->Count() - 1; + TInt i; + for(i = last; i >= 0 ; i--) + { + TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); + if(item.iThread == id) + { + item.iThread = TThreadId(0); + item.iOperation(item.iItem); + } + } + last = gEpocEnv->iCleanupItems->Count() - 1; + for(i = last; i >= 0 ; i--) + { + TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); + if(item.iThread == TThreadId(0)) + { + gEpocEnv->iCleanupItems->Delete(i); + } + } + } + +void EpocSdlEnv::FreeSurface() + { + Request(CSdlAppServ::EAppSrvDsaStatus); + gEpocEnv->iDsa->Free(); + } + +void EpocSdlEnv::LockPalette(TBool aLock) + { + gEpocEnv->iDsa->LockPalette(aLock); + } + +void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam) + { + const TBool sdlThread = RThread().Id() == gEpocEnv->iId; + const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam); + gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread); + if(sdlThread) + { + gEpocEnv->iAppSrv->SetParam(aParam); + const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService); + gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse); + } + } + + +TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint) + { + return gEpocEnv->iDsa->WindowCoordinates(aPoint); + } + +void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr) + { + gEpocEnv->iAppSrv->PanicMain(aInfo, aErr); + } +//Dsa is a low priority ao, it has to wait if its pending event, but ws +//event has been prioritized before it +//this is not called from app thread! +void EpocSdlEnv::WaitDeviceChange() + { + LockPalette(ETrue); + gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa); + const TSize sz = WindowSize(); + const TInt param = reinterpret_cast<TInt>(&sz); + ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param); + + // RThread().Suspend(); + } + +LOCAL_C TBool CheckSdl() + { + TInt isExit = ETrue; + RThread sdl; + if(sdl.Open(gEpocEnv->iId) == KErrNone) + { + if(sdl.ExitType() == EExitPending) + { + isExit = EFalse; + } + sdl.Close(); + } + return isExit; + } + +void EpocSdlEnvData::Free() + { + if(RThread().Id() == gEpocEnv->iId) + { + iDsa->Free(); + return; + } + + __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady)); + + for(TInt i = 0; i < iArgc; i++) + User::Free( iArgv[i] ); + + User::Free(iArgv); + + + delete iEventQueue; + + if(iDsa != NULL) + iDsa->Free(); + + delete iDsa; + delete iAppSrv; + } + +_LIT(KSDLMain, "SDLMain"); + +LOCAL_C int MainL() + { + gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat<TSdlCleanupItem>(8); + + char** envp=0; + /* !! process exits here if there is "exit()" in main! */ + int ret = 0; + for(TInt i = 0; i < 6; i++) + { + void* f = (void*) gEpocEnv->iMain[i]; + if(f != NULL) + { + switch(i) + { + case 0: + ret = ((mainfunc1)f)(); + return ret; + case 3: + ((mainfunc1)f)(); + return ret; + case 1: + ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); + return ret; + case 4: + ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); + return ret; + case 2: + ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); + return ret; + case 5: + ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); + return ret; + } + } + } + PANIC(KErrNotFound); + return 0; + } + +LOCAL_C TInt DoMain(TAny* /*aParam*/) + { + + + CTrapCleanup* cleanup = CTrapCleanup::New(); + + TBool fbsconnected = EFalse; + if(RFbsSession::GetSession() == NULL) + { + PANIC_IF_ERROR(RFbsSession::Connect()); + fbsconnected = ETrue; + } + + gEpocEnv->iAppSrv->Init(); + +#ifdef SYMBIANC + // Create stdlib + _REENT; +#endif + + // Call stdlib main + int ret = 0; + + //completes waiting rendesvous + RThread::Rendezvous(KErrNone); + + TRAPD(err, err = MainL()); + + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err); + + // Free resources and return + + EpocSdlEnv::CleanupItems(); + + gEpocEnv->iCleanupItems->Reset(); + delete gEpocEnv->iCleanupItems; + gEpocEnv->iCleanupItems = NULL; + + gEpocEnv->Free(); //free up in thread resources + +#ifdef SYMBIANC + _cleanup(); //this is normally called at exit, I call it here +#endif + + if(fbsconnected) + RFbsSession::Disconnect(); + +#ifdef SYMBIANC + CloseSTDLIB(); +#endif + + // delete as; + delete cleanup; + + return err == KErrNone ? ret : err;; + } + + + +EXPORT_C CSDL::~CSDL() + { + gEpocEnv->Free(); + User::Free(gEpocEnv); + gEpocEnv->iSdl = NULL; + } + +EXPORT_C CSDL* CSDL::NewL(TInt aFlags) + { + __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists)); + gEpocEnv = (EpocSdlEnvData*) User::AllocL(sizeof(EpocSdlEnvData)); + Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData)); + + gEpocEnv->iEpocEnvFlags = aFlags; + gEpocEnv->iEventQueue = CEventQueue::NewL(); + + gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ(); + gEpocEnv->iAppSrv->ConstructL(); + + CSDL* sdl = new (ELeave) CSDL(); + + gEpocEnv->iSdl = sdl; + + return sdl; + } + + /* +EXPORT_C void CSDL::ReInitL(TFlags aFlags) + { + const TFlags prevFlags = gEpocEnv->iEpocEnvFlags; + gEpocEnv->iEpocEnvFlags = aFlags; + TInt err = KErrNone; + if(((prevFlags & EDrawModeDSB) != (aFlags & EDrawModeDSB)) && gEpocEnv->iDsa) + { + delete gEpocEnv->iDsa; + gEpocEnv->iDsa = NULL; + gEpocEnv->iDsa = CDsa::RecreateL(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)); + } + } + */ + + +EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice) + { + if(gEpocEnv->iDsa == NULL) + gEpocEnv->iDsa = CDsa::CreateL(aSession); + gEpocEnv->iDsa->ConstructL(aWindow, aDevice); + } + + +EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, TInt aFlags, TInt aStackSize) + { + ASSERT(gEpocEnv != NULL); + gEpocEnv->iMain = aFunc; + const TBool args = aArg != NULL; + + gEpocEnv->iArgc = aArg->Count() + 1; + gEpocEnv->iArgv = (char**) User::AllocL(sizeof(char*) * (gEpocEnv->iArgc + 1)); + + TInt k = 0; + const TFileName processName = RProcess().FileName(); + const TInt len = processName.Length(); + gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); + Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len); + gEpocEnv->iArgv[k][len] = 0; + + for(TInt i = 0; args && (i < aArg->Count()); i++) + { + k++; + const TInt len = aArg->MdcaPoint(i).Length(); + gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); + Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len); + gEpocEnv->iArgv[k][len] = 0; + } + + gEpocEnv->iArgv[gEpocEnv->iArgc] = NULL; + + RThread thread; + User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL)); + + if(aStatus != NULL) + { + thread.Logon(*aStatus); + } + + gEpocEnv->iId = thread.Id(); + thread.SetPriority(EPriorityLess); + if((aFlags & CSDL::ERequestResume) == 0) + { + thread.Resume(); + } + thread.Close(); + return gEpocEnv->iId; + } + +EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent) + { + return EpocSdlEnv::EventQueue().Append(aEvent); + } + +EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr) + { + EpocSdlEnv::PanicMain(aInfo, aErr); + } + +EXPORT_C TInt CSDL::GetSDLCode(TInt aScanCode) + { + if(aScanCode < 0) + return MAX_SCANCODE; + if(aScanCode >= MAX_SCANCODE) + return -1; + return KeyMap()[aScanCode]; + } + +EXPORT_C TInt CSDL::SDLCodesCount() const + { + return MAX_SCANCODE; + } + +EXPORT_C void CSDL::ResetSDLCodes() + { + ResetKeyMap(); + } + +EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode) + { + gEpocEnv->iDsa->SetOrientation(aMode); + } + +EXPORT_C TInt CSDL::SetSDLCode(TInt aScanCode, TInt aSDLCode) + { + const TInt current = GetSDLCode(aScanCode); + if(aScanCode >= 0 && aScanCode < MAX_SCANCODE) + KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode); + return current; + } + + +EXPORT_C MSDLObserver* CSDL::Observer() + { + return gEpocEnv->iAppSrv->Observer(); + } + +EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver) + { + gEpocEnv->iAppSrv->SetObserver(aObserver); + } + +EXPORT_C void CSDL::Resume() + { + EpocSdlEnv::Resume(); + } + +EXPORT_C void CSDL::Suspend() + { + gEpocEnv->iDsa->DoStop(); + } + +EXPORT_C CSDL::CSDL() + { + } + +EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const + { + gEpocEnv->iAppUi = &aAppUi; + EnvUtils::DisableKeyBlocking(); + } + +EXPORT_C TInt CSDL::SetBlitter(MBlitter* aBlitter) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + gEpocEnv->iDsa->SetBlitter(aBlitter); + return KErrNone; + } + return KErrNotReady; + } + + +EXPORT_C TInt CSDL::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->AppendOverlay(aOverlay, aPriority); + } + return KErrNotReady; + } + +EXPORT_C TInt CSDL::RemoveOverlay(MOverlay& aOverlay) + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->RemoveOverlay(aOverlay); + } + return KErrNotReady; + } + +EXPORT_C TInt CSDL::RedrawRequest() + { + if(gEpocEnv && gEpocEnv->iDsa) + { + return gEpocEnv->iDsa->RedrawRequest(); + } + return KErrNotReady; + } + +/* +EXPORT_C CSDL* CSDL::Current() + { + return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL; + } + + +EXPORT_C TInt CSDL::SetVolume(TInt aVolume) + { + return EpocSdlEnv::SetVolume(aVolume); + } + +EXPORT_C TInt CSDL::Volume() const + { + return EpocSdlEnv::Volume(); + } + +EXPORT_C TInt CSDL::MaxVolume() const + { + return EpocSdlEnv::MaxVolume(); + } +*/ + +void EnvUtils::DisableKeyBlocking() + { + if(gEpocEnv->iAppUi != NULL) + return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking(); + } + +TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus) + { + if(gEpocEnv->iId != TThreadId(0) && + aThread.Open(gEpocEnv->iId) && + aThread.ExitType() == EExitPending) + { + aThread.Rendezvous(aStatus); + return ETrue; + } + return EFalse; + } + + + diff --git a/3rdparty/SDL/src/main/symbian/EKA2/sdlexe.cpp b/3rdparty/SDL/src/main/symbian/EKA2/sdlexe.cpp new file mode 100644 index 0000000..bb160c4 --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA2/sdlexe.cpp @@ -0,0 +1,809 @@ +// INCLUDES +#include <aknapp.h> +#include <aknappui.h> +#include <eikdoc.h> +#include <sdlepocapi.h> +#include <bautils.h> +#include <eikstart.h> +#include <badesca.h> +#include <bautils.h> +#include <apgcli.h> +#include <sdlmain.h> +#include <eikedwin.h> +#include <eiklabel.h> +#include <sdlexe.rsg> +#include <aknglobalmsgquery.h> +#include <apgwgnam.h> + + + +// FORWARD DECLARATIONS +class CApaDocument; + + +//const TUid KSDLUID = { 0xF01F605E }; + +LOCAL_C void MakeCCmdLineL(const TDesC8& aParam, CDesC8Array& aArray) + { + + const TChar dq('\"'); + + TLex8 lex(aParam); + TBool in = EFalse; + + lex.SkipSpaceAndMark(); + + while(!lex.Eos()) + { + TPtrC8 ptr; + if(in) + { + const TPtrC8 rem = lex.RemainderFromMark(); + const TInt pos = rem.Locate(dq); + if(pos > 0) + { + lex.Inc(pos); + ptr.Set(lex.MarkedToken()); + lex.SkipAndMark(1); + } + else + { + ptr.Set(rem); + } + in = EFalse; + } + else + { + ptr.Set(lex.NextToken()); + const TInt pos = ptr.Locate(dq); + if(pos == 0) + { + lex.UnGetToMark(); + lex.SkipAndMark(1); + in = ETrue; + continue; // back to in brace + } + else + lex.SkipSpaceAndMark(); + } + + aArray.AppendL(ptr); + + } + } + +NONSHARABLE_CLASS(TVirtualCursor) : public MOverlay + { + public: + TVirtualCursor(); + void Set(const TRect& aRect, CFbsBitmap* aBmp, CFbsBitmap* aAlpha); + void Move(TInt aX, TInt aY); + void MakeEvent(TWsEvent& aEvent, const TPoint& aBasePos) const; + void Toggle(); + TBool IsOn() const; + private: + void Draw(CBitmapContext& aGc, const TRect& aTargetRect, const TSize& aSize); + private: + TRect iRect; + TPoint iInc; + TPoint iPos; + TBool iIsOn; + CFbsBitmap* iCBmp; + CFbsBitmap* iAlpha; + }; + + +TVirtualCursor::TVirtualCursor() : iInc(0, 0), iIsOn(EFalse), iCBmp(NULL) + { + } + +const TInt KMaxMove = 10; + +void TVirtualCursor::Move(TInt aX, TInt aY) + { + if(aX > 0 && iInc.iX > 0) + ++iInc.iX; + else if(aX < 0 && iInc.iX < 0) + --iInc.iX; + else + iInc.iX = aX; + + if(aY > 0 && iInc.iY > 0) + ++iInc.iY; + else if(aY < 0 && iInc.iY < 0) + --iInc.iY; + else + iInc.iY = aY; + + iInc.iX = Min(KMaxMove, iInc.iX); + + iInc.iX = Max(-KMaxMove, iInc.iX); + + iInc.iY = Min(KMaxMove, iInc.iY); + + iInc.iY =Max(-KMaxMove, iInc.iY); + + const TPoint pos = iPos + iInc; + if(iRect.Contains(pos)) + { + iPos = pos; + } + else + { + iInc = TPoint(0, 0); + } + } + + +void TVirtualCursor::Toggle() + { + iIsOn = !iIsOn; + } + + +TBool TVirtualCursor::IsOn() const + { + return iIsOn; + } + +void TVirtualCursor::Set(const TRect& aRect, CFbsBitmap* aBmp, CFbsBitmap* aAlpha) + { + iRect = aRect; + iCBmp = aBmp; + iAlpha = aAlpha; + } + + +void TVirtualCursor::MakeEvent(TWsEvent& aEvent, const TPoint& aBasePos) const + { + aEvent.SetType(EEventPointer), + aEvent.SetTimeNow(); + TPointerEvent& pointer = *aEvent.Pointer(); + pointer.iType = TPointerEvent::EButton1Down; + pointer.iPosition = iPos; + pointer.iParentPosition = aBasePos; + } + + +void TVirtualCursor::Draw(CBitmapContext& aGc, const TRect& /*aTargetRect*/, const TSize& /*aSize*/) + { + if(iIsOn && iCBmp != NULL) + { + const TRect rect(TPoint(0, 0), iCBmp->SizeInPixels()); + aGc.AlphaBlendBitmaps(iPos, iCBmp, rect, iAlpha, TPoint(0, 0)); + } + + } + +NONSHARABLE_CLASS(TSdlClass) + { + public: + TSdlClass(); + void SetMain(const TMainFunc& aFunc, TInt aFlags, MSDLMainObs* aObs, TInt aExeFlags); + TInt SdlFlags() const; + const TMainFunc& Main() const; + void SendEvent(TInt aEvent, TInt aParam, CSDL* aSDL); + TInt AppFlags() const; + void AppFlags(TInt aFlags); + private: + TMainFunc iFunc; + TInt iSdlFlags; + TInt iExeFlags; + MSDLMainObs* iObs; + }; + + +void TSdlClass::AppFlags(TInt aFlags) + { + iExeFlags |= aFlags; + } + +void TSdlClass::SendEvent(TInt aEvent, TInt aParam, CSDL* aSDL) + { + if(iObs != NULL) + iObs->SDLMainEvent(aEvent, aParam, aSDL); + } + +TInt TSdlClass::AppFlags() const + { + return iExeFlags; + } + +void TSdlClass::SetMain(const TMainFunc& aFunc, TInt aFlags, MSDLMainObs* aObs, TInt aExeFlags) + { + iFunc = aFunc; + iSdlFlags = aFlags; + iExeFlags = aExeFlags; + iObs = aObs; + } + +const TMainFunc& TSdlClass::Main() const + { + return iFunc; + } + + + TInt TSdlClass::SdlFlags() const + { + return iSdlFlags; + } + + + +TSdlClass::TSdlClass() + { + Mem::FillZ(this, sizeof(this)); + } + +TSdlClass gSDLClass; + + +//////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CSDLApplication) : public CAknApplication + { + public: + CSDLApplication(); + private: + CApaDocument* CreateDocumentL(); + TFileName ResourceFileName() const; + TUid AppDllUid() const; + void FindMeL(); + TUid iUid; + }; + +NONSHARABLE_CLASS(CSDLDocument) : public CEikDocument + { + public: + CSDLDocument(CEikApplication& aApp); + private: + CEikAppUi* CreateAppUiL(); + + }; + + //////////////////////////////////////////////////////////////////// + + +NONSHARABLE_CLASS(MExitWait) + { + public: + virtual void DoExit(TInt aErr) = 0; + }; + +///////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CExitWait) : public CActive + { + public: + CExitWait(MExitWait& aWait); + ~CExitWait(); + private: + void RunL(); + void DoCancel(); + private: + MExitWait& iWait; + TRequestStatus* iStatusPtr; + }; + +//////////////////////////////////////////////////////////////////////// + + +NONSHARABLE_CLASS(CSDLWin) : public CCoeControl + { + public: + void ConstructL(const TRect& aRect); + RWindow& GetWindow() const; + void SetNoDraw(); + private: + void Draw(const TRect& aRect) const; + private: + TBool iNoDraw; + }; + + +//////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CSDLAppUi) : public CAknAppUi, public MExitWait, MSDLObserver + { + public: + ~CSDLAppUi(); + private: // New functions + void ConstructL(); + void HandleCommandL(TInt aCommand); + void HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination); + void HandleResourceChangeL(TInt aType); + + void DoExit(TInt aErr); + + TInt SdlEvent(TInt aEvent, TInt aParam); + TInt SdlThreadEvent(TInt aEvent, TInt aParam); + + void StartL(); + static TBool StartL(TAny* aThis); + + TBool ParamEditorL(TDes& aCheat); + + TBool ProcessCommandParametersL(CApaCommandLine &aCommandLine); + + void PrepareToExit(); + void HandleConsoleWindowL(); + void HandleConsoleWindow(); + void HandleForegroundEventL(TBool aForeground); + + static TBool IdleRequestL(TAny* aThis); + + TBool HandleKeyL(const TWsEvent& aEvent); + + + private: + CExitWait* iWait; + CSDLWin* iSDLWin; + CSDL* iSdl; + CIdle* iStarter; + TBool iExitRequest; + CDesC8Array* iParams; + TInt iResOffset; + CIdle* iIdle; + TInt iStdOut; + TVirtualCursor iCursor; + CFbsBitmap* iCBmp; + CFbsBitmap* iAlpha; + // TTime iLastPress; + // CSDL::TOrientationMode iOrientation; + }; + +////////////////////////////////////////////////////////////////////////////////////////7 + +CApaDocument* CSDLApplication::CreateDocumentL() + { + return new (ELeave) CSDLDocument(*this); + } + +TUid CSDLApplication::AppDllUid() const + { + return iUid; + } + + +CSDLApplication::CSDLApplication() + { + TRAPD(err, FindMeL()); + ASSERT(err == KErrNone); + } + +void CSDLApplication::FindMeL() + { + RApaLsSession apa; + User::LeaveIfError(apa.Connect()); + CleanupClosePushL(apa); + User::LeaveIfError(apa.GetAllApps()); + TFileName name = RProcess().FileName(); + TApaAppInfo info; + while(apa.GetNextApp(info) == KErrNone) + { + if(info.iFullName.CompareF(name) == 0) + { + iUid = info.iUid; + break; + } + } + CleanupStack::PopAndDestroy(); + } + +TFileName CSDLApplication::ResourceFileName() const + { + return KNullDesC(); + } + +/////////////////////////////////////////////////////////////////////////////////////////// + +CExitWait::CExitWait(MExitWait& aWait) : CActive(CActive::EPriorityStandard), iWait(aWait) + { + CActiveScheduler::Add(this); + SetActive(); + iStatusPtr = &iStatus; + } + +CExitWait::~CExitWait() + { + Cancel(); + } + +void CExitWait::RunL() + { + if(iStatusPtr != NULL ) + iWait.DoExit(iStatus.Int()); + } + +void CExitWait::DoCancel() + { + if(iStatusPtr != NULL ) + User::RequestComplete(iStatusPtr , KErrCancel); + } + + +////////////////////////////////////////////////////////////////////////////////////////////// + +CSDLDocument::CSDLDocument(CEikApplication& aApp) : CEikDocument(aApp) + {} + +CEikAppUi* CSDLDocument::CreateAppUiL() + { + return new (ELeave) CSDLAppUi; + } + +/////////////////////////////////////////////////////////////////////////// + +void CSDLWin:: ConstructL(const TRect& aRect) + { + CreateWindowL(); + SetRect(aRect); + ActivateL(); + } + + +RWindow& CSDLWin::GetWindow() const + { + return Window(); + } + + +void CSDLWin::Draw(const TRect& /*aRect*/) const + { + if(!iNoDraw) + { + CWindowGc& gc = SystemGc(); + gc.SetPenStyle(CGraphicsContext::ESolidPen); + gc.SetPenColor(KRgbGray); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetBrushColor(0xaaaaaa); + gc.DrawRect(Rect()); + } + } + +void CSDLWin::SetNoDraw() + { + iNoDraw = ETrue; + } + +///////////////////////////////////////////////////////////////////////// + +CSDLAppUi::~CSDLAppUi() + { + if(iIdle) + iIdle->Cancel(); + delete iIdle; + if(iStarter != NULL) + iStarter->Cancel(); + delete iStarter; + delete iWait; + delete iSdl; + delete iSDLWin; + delete iParams; + delete iCBmp; + delete iAlpha; + } + + +void CSDLAppUi::ConstructL() + { + BaseConstructL(ENoAppResourceFile | ENoScreenFurniture); + + + RLibrary lib; + User::LeaveIfError(lib.Load(_L("sdlexe.dll"))); + TFileName name = lib.FileName(); + lib.Close(); + name.Replace(3, name.Length() - 3, _L("resource\\apps\\sdlexe.rsc")); + BaflUtils::NearestLanguageFile(iEikonEnv->FsSession(), name); + iResOffset = iCoeEnv->AddResourceFileL(name); + + name.Replace(name.Length() - 3, 3, _L("mbm")); + + TEntry e; + const TInt err = iEikonEnv->FsSession().Entry(name, e); + + iCBmp = iEikonEnv->CreateBitmapL(name, 0); + iAlpha = iEikonEnv->CreateBitmapL(name, 1); + + iIdle = CIdle::NewL(CActive::EPriorityIdle); + + iSDLWin = new (ELeave) CSDLWin; + iSDLWin->ConstructL(ApplicationRect()); + + iSdl = CSDL::NewL(gSDLClass.SdlFlags()); + + gSDLClass.SendEvent(MSDLMainObs::ESDLCreated, 0, iSdl); + + iSdl->SetObserver(this); + iSdl->DisableKeyBlocking(*this); + iSdl->SetContainerWindowL( + iSDLWin->GetWindow(), + iEikonEnv->WsSession(), + *iEikonEnv->ScreenDevice()); + iSdl->AppendOverlay(iCursor, 0); + + iCursor.Set(TRect(TPoint(0, 0), iSDLWin->Size()), iCBmp, iAlpha); + + iStarter = CIdle::NewL(CActive::EPriorityLow); + iStarter->Start(TCallBack(StartL, this)); + + + } + + + +TBool CSDLAppUi::StartL(TAny* aThis) + { + static_cast<CSDLAppUi*>(aThis)->StartL(); + return EFalse; + } + + +void CSDLAppUi::PrepareToExit() + { + CAknAppUiBase::PrepareToExit(); //aknappu::PrepareToExit crashes + iCoeEnv->DeleteResourceFile(iResOffset); + } + +TBool CSDLAppUi::ProcessCommandParametersL(CApaCommandLine &aCommandLine) + { + const TPtrC8 cmdLine = aCommandLine.TailEnd(); + iParams = new (ELeave) CDesC8ArrayFlat(8); + MakeCCmdLineL(cmdLine, *iParams); + return EFalse; + } + + + TBool CSDLAppUi::ParamEditorL(TDes& aCheat) + { + CAknTextQueryDialog* query = CAknTextQueryDialog::NewL(aCheat); + CleanupStack::PushL(query); + query->SetPromptL(_L("Enter parameters")); + CleanupStack::Pop(); + return query->ExecuteLD(R_PARAMEDITOR); + } + + void CSDLAppUi::StartL() + { + if(gSDLClass.AppFlags() & SDLEnv::EParamQuery) + { + TBuf8<256> cmd; + RFile file; + TInt err = file.Open(iEikonEnv->FsSession(), _L("sdl_param.txt"),EFileRead); + if(err == KErrNone) + { + file.Read(cmd); + file.Close(); + MakeCCmdLineL(cmd, *iParams); + } + if(err != KErrNone || gSDLClass.AppFlags() & (SDLEnv::EParamQueryDialog ^ SDLEnv::EParamQuery)) + { + TBuf<256> buffer; + if(ParamEditorL(buffer)) + { + cmd.Copy(buffer); + MakeCCmdLineL(cmd, *iParams); + } + } + } + iWait = new (ELeave) CExitWait(*this); + iSdl->CallMainL(gSDLClass.Main(), &iWait->iStatus, iParams, CSDL::ENoParamFlags, 0xA000); + } + +void CSDLAppUi::HandleCommandL(TInt aCommand) + { + switch(aCommand) + { + case EAknSoftkeyBack: + case EAknSoftkeyExit: + case EAknCmdExit: + case EEikCmdExit: + gSDLClass.AppFlags(SDLEnv::EAllowConsoleView); + if(iWait == NULL || !iWait->IsActive() || iSdl == NULL) + { + Exit(); + } + else if(!iExitRequest) + { + iExitRequest = ETrue; //trick how SDL can be closed! + iSdl->Suspend(); + } + break; + } + } + + + +TBool CSDLAppUi::HandleKeyL(const TWsEvent& aEvent) + { + const TInt type = aEvent.Type(); + if(!(type == EEventKey || type == EEventKeyUp || type == EEventKeyDown)) + { + return ETrue; + } + const TKeyEvent& key = *aEvent.Key(); + if((key.iScanCode == EStdKeyYes) && (gSDLClass.AppFlags() & SDLEnv::EVirtualMouse)) + { + if(type == EEventKeyUp) + { + iCursor.Toggle(); + iSdl->RedrawRequest(); + } + return EFalse; + } + if(iCursor.IsOn()) + { + switch(key.iScanCode) + { + case EStdKeyUpArrow: + iCursor.Move(0, -1); + break; + case EStdKeyDownArrow: + iCursor.Move(0, 1); + break; + case EStdKeyLeftArrow: + iCursor.Move(-1, 0); + break; + case EStdKeyRightArrow: + iCursor.Move(1, 0); + break; + case EStdKeyDevice3: + if(type == EEventKeyUp) + { + TWsEvent event; + iCursor.MakeEvent(event, iSDLWin->Position()); + iSdl->AppendWsEvent(event); + } + return EFalse; + default: + return ETrue; + } + iSdl->RedrawRequest(); + return EFalse; + } + return ETrue; + } + + void CSDLAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination) + { + if(iSdl && iWait && HandleKeyL(aEvent)) + iSdl->AppendWsEvent(aEvent); + CAknAppUi::HandleWsEventL(aEvent, aDestination); + } + + void CSDLAppUi::HandleResourceChangeL(TInt aType) + { + CAknAppUi::HandleResourceChangeL(aType); + if(aType == KEikDynamicLayoutVariantSwitch) + { + iSDLWin->SetRect(ApplicationRect()); + iSdl->SetContainerWindowL( + iSDLWin->GetWindow(), + iEikonEnv->WsSession(), + *iEikonEnv->ScreenDevice()); + } + } + + +void CSDLAppUi::DoExit(TInt/*Err*/) + { + iExitRequest = ETrue; + Exit(); + } + + + TInt CSDLAppUi::SdlThreadEvent(TInt aEvent, TInt /*aParam*/) + { + switch(aEvent) + { + case MSDLObserver::EEventResume: + break; + case MSDLObserver::EEventSuspend: + if(iExitRequest) + return MSDLObserver::ESuspendNoSuspend; + break; + case MSDLObserver::EEventWindowReserved: + break; + case MSDLObserver::EEventWindowNotAvailable: + break; + case MSDLObserver::EEventScreenSizeChanged: + break; + } + return MSDLObserver::EParameterNone; + } + +TInt CSDLAppUi::SdlEvent(TInt aEvent, TInt /*aParam*/) + { + switch(aEvent) + { + case MSDLObserver::EEventResume: + break; + case MSDLObserver::EEventSuspend: + if(iExitRequest) + return MSDLObserver::ESuspendNoSuspend; + break; + case MSDLObserver::EEventWindowReserved: + break; + case MSDLObserver::EEventWindowNotAvailable: + { + TRAP_IGNORE(HandleConsoleWindowL()); + } + break; + case MSDLObserver::EEventScreenSizeChanged: + break; + case MSDLObserver::EEventKeyMapInit: + break; + case MSDLObserver::EEventMainExit: + if(iStdOut != 0) + { + gSDLClass.AppFlags(SDLEnv::EAllowConsoleView); + iEikonEnv->WsSession().SetWindowGroupOrdinalPosition(iStdOut, 0); + } + break; + } + return MSDLObserver::EParameterNone; + } + +void CSDLAppUi::HandleForegroundEventL(TBool aForeground) + { + CAknAppUi::HandleForegroundEventL(aForeground); + if(!aForeground) + HandleConsoleWindow(); + } + +void CSDLAppUi::HandleConsoleWindow() + { + if(!iIdle->IsActive()) + iIdle->Start(TCallBack(IdleRequestL, this)); + } + +TBool CSDLAppUi::IdleRequestL(TAny* aThis) + { + static_cast<CSDLAppUi*>(aThis)->HandleConsoleWindowL(); + return EFalse; + } + +void CSDLAppUi::HandleConsoleWindowL() + { + if(gSDLClass.AppFlags() & SDLEnv::EAllowConsoleView) + { + return; + } + RWsSession& ses = iEikonEnv->WsSession(); + const TInt focus = ses.GetFocusWindowGroup(); + CApaWindowGroupName* name = CApaWindowGroupName::NewLC(ses, focus); + const TPtrC caption = name->Caption(); + if(0 == caption.CompareF(_L("STDOUT"))) + { + iStdOut = focus; + ses.SetWindowGroupOrdinalPosition(iEikonEnv->RootWin().Identifier(), 0); + } + CleanupStack::PopAndDestroy(); //name + } + + +//////////////////////////////////////////////////////////////////////// + + +CApaApplication* NewApplication() + { + return new CSDLApplication(); + } + + +EXPORT_C TInt SDLEnv::SetMain(const TMainFunc& aFunc, TInt aSdlFlags, MSDLMainObs* aObs, TInt aSdlExeFlags) + { + gSDLClass.SetMain(aFunc, aSdlFlags, aObs, aSdlExeFlags); + return EikStart::RunApplication(NewApplication); + } + +////////////////////////////////////////////////////////////////////// + +TInt SDLUiPrint(const TDesC8& /*aInfo*/) + { + return KErrNotFound; + } + + + diff --git a/3rdparty/SDL/src/main/symbian/EKA2/sdllib.cpp b/3rdparty/SDL/src/main/symbian/EKA2/sdllib.cpp new file mode 100644 index 0000000..7c09996 --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA2/sdllib.cpp @@ -0,0 +1,12 @@ +#include<eikstart.h> +#include<sdlmain.h> +#include<sdlepocapi.h> + + +GLREF_C TInt E32Main() + { + return SDLEnv::SetMain(SDL_main, CSDL::EEnableFocusStop | CSDL::EAllowImageResize, + NULL, SDLEnv::EParamQuery | SDLEnv::EVirtualMouse); + } + +
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.cpp b/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.cpp new file mode 100644 index 0000000..72c3b3e --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.cpp @@ -0,0 +1,62 @@ +/* + vectorbuffer.cpp + yet another circle buffer + + Markus Mertama +*/ + +#include"vectorbuffer.h" + + + +void VectorPanic(TInt aErr, TInt aLine) + { + TBuf<64> b; + b.Format(_L("vector buffer at % d "), aLine); + User::Panic(b, aErr); + } + +void TNodeBuffer::TNode::Terminator(TNodeBuffer::TNode* aNode) + { + Mem::Copy(iSucc, &aNode, sizeof(TNode*)); + } + +TInt TNodeBuffer::TNode::Size() const + { + return reinterpret_cast<const TUint8*>(iSucc) - Ptr(); + } + +const TUint8* TNodeBuffer::TNode::Ptr() const + { + return reinterpret_cast<const TUint8*>(this) + sizeof(TNode); + } + +TNodeBuffer::TNode* TNodeBuffer::TNode::Empty(TUint8* aBuffer) + { + TNode* node = reinterpret_cast<TNode*>(aBuffer); + node->iSucc = node + 1; + return node; + } + + TNodeBuffer::TNode* TNodeBuffer::TNode::New(TNode* aPred, const TDesC8& aData) + { + TNode* node = aPred->Size() == 0 ? aPred : aPred->iSucc; + + + TUint8* start = reinterpret_cast<TUint8*>(node) + sizeof(TNode); + node->iSucc = reinterpret_cast<TNode*>(start + aData.Size()); + node->iSucc->iSucc = NULL; //terminator + + __ASSERT_DEBUG(node->Size() == aData.Size(), VECPANIC(KErrCorrupt)); + + Mem::Copy(start, aData.Ptr(), aData.Size()); + return node; + } + + + + + + + +
\ No newline at end of file diff --git a/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.h b/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.h new file mode 100644 index 0000000..3d8be58 --- /dev/null +++ b/3rdparty/SDL/src/main/symbian/EKA2/vectorbuffer.h @@ -0,0 +1,240 @@ +/* + vectorbuffer.cpp + yet another circle buffer + + Markus Mertama +*/ + +#ifndef __VECTORBUFFER_H__ +#define __VECTORBUFFER_H__ + +#include<e32std.h> +#define VLOG(x) +#define VECPANIC(x) VectorPanic(x, __LINE__) +void VectorPanic(TInt, TInt); + + +//int DEBUG_INT; + +NONSHARABLE_CLASS(TNodeBuffer) + { + public: + protected: + NONSHARABLE_CLASS(TNode) + { + public: + static TNode* Empty(TUint8* iBuffer); + static TNode* New(TNode* aPrev, const TDesC8& aData); + const TUint8* Ptr() const; + TInt Size() const; + inline TNode* Succ(); + static void SetSucc(TNode*& aNode); + void Terminator(TNode* aNode); + private: + TNode* iSucc; + }; + }; + +inline TNodeBuffer::TNode* TNodeBuffer::TNode::Succ() + { + return iSucc; + } + +template <TInt C> +NONSHARABLE_CLASS(TVectorBuffer) : public TNodeBuffer + { + public: + TVectorBuffer(); + TInt Append(const TDesC8& aData); + // TInt AppendOverwrite(const TDesC8& aData); + TPtrC8 Shift(); + TPtrC8 operator[](TInt aIndex) const; + TInt Size() const; + private: + TInt GetRoom(TInt aSize) const; + TInt Unreserved() const; + private: + TNode* iTop; + TNode* iBottom; + TInt iSize; + TUint8 iBuffer[C]; + }; + +template <TInt C> +TVectorBuffer<C>::TVectorBuffer() : iSize(0) + { + Mem::FillZ(iBuffer, C); + iTop = TNode::Empty(iBuffer); //these points to buffer + iBottom = TNode::Empty(iBuffer); + } + +template<TInt C > +TInt TVectorBuffer<C>::Unreserved() const + { + __ASSERT_DEBUG(iBottom < iBottom->Succ(), VECPANIC(KErrCorrupt)); + const TInt bytesbetween = + reinterpret_cast<const TUint8*>(iBottom->Succ()) - + reinterpret_cast<const TUint8*>(iTop); + const TInt topsize = sizeof(TNode); + if(bytesbetween > 0) //bytesbetween is room between bottom and top + { //therefore free room is subracted from free space + + const TInt room = C - bytesbetween - topsize; + return room; + } + if(bytesbetween == 0) + { + + if(Size() > 0) + return 0; + else + return C - topsize; + } + const TInt room = -bytesbetween - topsize; //free is space between pointers + return room; + } + +template <TInt C> +TInt TVectorBuffer<C>::GetRoom(TInt aSize) const + { + const TInt bytesnew = sizeof(TNode) + aSize; + const TInt room = Unreserved() - bytesnew; + return room; + } + +template <TInt C> +TInt TVectorBuffer<C>::Append(const TDesC8& aData) //ei ole ok! + { + const TInt len = aData.Length(); + if(GetRoom(len) < 0) + { + return KErrOverflow; + } + if(iBottom->Succ()->Ptr() - iBuffer > (C - (len + TInt(sizeof(TNode))))) + { + VLOG("rc"); + // RDebug::Print(_L("vector: append")); + TNode* p = TNode::Empty(iBuffer); + iBottom->Terminator(p); + iBottom = p; + return Append(aData); + // Append(); + // iBottom = TNode::New(p, aData); //just append something into end + } + + //DEBUG_INT++; + + iBottom = TNode::New(iBottom, aData); + + iSize += len; + return KErrNone; + } + +/* +template <TInt C> +TInt TVectorBuffer<C>::AppendOverwrite(const TDesC8& aData) //ei ole ok! + { + while(Append(aData) == KErrOverflow) + { + if(iTop->Succ() == NULL) + { + return KErrUnderflow; + } + //Shift(); //data is lost + } + return KErrNone; + } +*/ +template <TInt C> +TPtrC8 TVectorBuffer<C>::Shift() + { + __ASSERT_ALWAYS(iTop->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom + TNode* node = iTop; + iTop = iTop->Succ(); + if(iTop > node) + { + // DEBUG_INT--; + iSize -= node->Size(); + return TPtrC8(node->Ptr(), node->Size()); + } + else + { + // RDebug::Print(_L("vector: shift")); + return Shift(); //this happens when buffer is terminated, and data lies in next + } + } + +template <TInt C> +TInt TVectorBuffer<C>::Size() const + { + return iSize; + } + +template <TInt C> +TPtrC8 TVectorBuffer<C>::operator[](TInt aIndex) const + { + TInt index = 0; + TNode* t = iTop->Size() > 0 ? iTop : iTop->Succ(); //eliminate terminator + while(index < aIndex) + { + TNode* nt = t->Succ(); + if(nt < t) + { + nt = nt->Succ(); + } + t = nt; + if(t->Size() > 0) + index++; + __ASSERT_ALWAYS(t->Succ() != NULL, VECPANIC(KErrUnderflow)); //can never pass-by bottom + } + return t->Ptr(); + } + + +template <class T, TInt C> +NONSHARABLE_CLASS(TVector) : public TVectorBuffer<C * sizeof(T)> + { + public: + TVector(); + TInt Append(const T& aData); + const T& Shift(); + TInt Size() const; + const T& operator[](TInt aIndex) const; + }; + +template <class T, TInt C> +TVector<T, C>::TVector() : TVectorBuffer<C * sizeof(T)>() + { + } + +template <class T, TInt C> +TInt TVector<T, C>::Append(const T& aData) + { + const TPckgC<T> data(aData); + return TVectorBuffer<C * sizeof(T)>::Append(data); + } + +template <class T, TInt C> +const T& TVector<T, C>::Shift() + { + const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::Shift(); + return *(reinterpret_cast<const T*>(ptr.Ptr())); + } + + +template <class T, TInt C> +TInt TVector<T, C>::Size() const + { + return TVectorBuffer<C * sizeof(T)>::Size() / sizeof(T); + } + +template <class T, TInt C> +const T& TVector<T, C>::operator[](TInt aIndex) const + { + const TPtrC8 ptr = TVectorBuffer<C * sizeof(T)>::operator[](aIndex); + return *(reinterpret_cast<const T*>(ptr.Ptr())); + } + +#endif + + diff --git a/3rdparty/SDL/src/main/win32/SDL_win32_main.c b/3rdparty/SDL/src/main/win32/SDL_win32_main.c new file mode 100644 index 0000000..672b48c --- /dev/null +++ b/3rdparty/SDL/src/main/win32/SDL_win32_main.c @@ -0,0 +1,402 @@ +/* + SDL_main.c, placed in the public domain by Sam Lantinga 4/13/98 + + The WinMain function -- calls your program's main() function +*/ + +#include <stdio.h> +#include <stdlib.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#ifdef _WIN32_WCE +# define DIR_SEPERATOR TEXT("\\") +# undef _getcwd +# define _getcwd(str,len) wcscpy(str,TEXT("")) +# define setbuf(f,b) +# define setvbuf(w,x,y,z) +# define fopen _wfopen +# define freopen _wfreopen +# define remove(x) DeleteFile(x) +#else +# define DIR_SEPERATOR TEXT("/") +# include <direct.h> +#endif + +/* Include the SDL main definition header */ +#include "SDL.h" +#include "SDL_main.h" + +#ifdef main +# ifndef _WIN32_WCE_EMULATION +# undef main +# endif /* _WIN32_WCE_EMULATION */ +#endif /* main */ + +/* The standard output files */ +#define STDOUT_FILE TEXT("stdout.txt") +#define STDERR_FILE TEXT("stderr.txt") + +/* Set a variable to tell if the stdio redirect has been enabled. */ +static int stdioRedirectEnabled = 0; + +#ifdef _WIN32_WCE + static wchar_t stdoutPath[MAX_PATH]; + static wchar_t stderrPath[MAX_PATH]; +#else + static char stdoutPath[MAX_PATH]; + static char stderrPath[MAX_PATH]; +#endif + +#if defined(_WIN32_WCE) && _WIN32_WCE < 300 +/* seems to be undefined in Win CE although in online help */ +#define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t')) +#endif /* _WIN32_WCE < 300 */ + +static void UnEscapeQuotes( char *arg ) +{ + char *last = NULL; + + while( *arg ) { + if( *arg == '"' && *last == '\\' ) { + char *c_curr = arg; + char *c_last = last; + + while( *c_curr ) { + *c_last = *c_curr; + c_last = c_curr; + c_curr++; + } + *c_last = '\0'; + } + last = arg; + arg++; + } +} + +/* Parse a command line buffer into arguments */ +static int ParseCommandLine(char *cmdline, char **argv) +{ + char *bufp; + char *lastp = NULL; + int argc, last_argc; + + argc = last_argc = 0; + for ( bufp = cmdline; *bufp; ) { + /* Skip leading whitespace */ + while ( isspace(*bufp) ) { + ++bufp; + } + /* Skip over argument */ + if ( *bufp == '"' ) { + ++bufp; + if ( *bufp ) { + if ( argv ) { + argv[argc] = bufp; + } + ++argc; + } + /* Skip over word */ + while ( *bufp && ( *bufp != '"' || (lastp && *lastp == '\\') ) ) { + lastp = bufp; + ++bufp; + } + } else { + if ( *bufp ) { + if ( argv ) { + argv[argc] = bufp; + } + ++argc; + } + /* Skip over word */ + while ( *bufp && ! isspace(*bufp) ) { + ++bufp; + } + } + if ( *bufp ) { + if ( argv ) { + *bufp = '\0'; + } + ++bufp; + } + + /* Strip out \ from \" sequences */ + if( argv && last_argc != argc ) { + UnEscapeQuotes( argv[last_argc] ); + } + last_argc = argc; + } + if ( argv ) { + argv[argc] = NULL; + } + return(argc); +} + +/* Show an error message */ +static void ShowError(const char *title, const char *message) +{ +/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */ +#ifdef USE_MESSAGEBOX + MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK); +#else + fprintf(stderr, "%s: %s\n", title, message); +#endif +} + +/* Pop up an out of memory message, returns to Windows */ +static BOOL OutOfMemory(void) +{ + ShowError("Fatal Error", "Out of memory - aborting"); + return FALSE; +} + +/* SDL_Quit() shouldn't be used with atexit() directly because + calling conventions may differ... */ +static void cleanup(void) +{ + SDL_Quit(); +} + +/* Remove the output files if there was no output written */ +static void cleanup_output(void) { + FILE *file; + int empty; + + /* Flush the output in case anything is queued */ + fclose(stdout); + fclose(stderr); + + /* Without redirection we're done */ + if (!stdioRedirectEnabled) { + return; + } + + /* See if the files have any output in them */ + if ( stdoutPath[0] ) { + file = fopen(stdoutPath, TEXT("rb")); + if ( file ) { + empty = (fgetc(file) == EOF) ? 1 : 0; + fclose(file); + if ( empty ) { + remove(stdoutPath); + } + } + } + if ( stderrPath[0] ) { + file = fopen(stderrPath, TEXT("rb")); + if ( file ) { + empty = (fgetc(file) == EOF) ? 1 : 0; + fclose(file); + if ( empty ) { + remove(stderrPath); + } + } + } +} + +/* Redirect the output (stdout and stderr) to a file */ +static void redirect_output(void) +{ + DWORD pathlen; +#ifdef _WIN32_WCE + wchar_t path[MAX_PATH]; +#else + char path[MAX_PATH]; +#endif + FILE *newfp; + + pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path)); + while ( pathlen > 0 && path[pathlen] != '\\' ) { + --pathlen; + } + path[pathlen] = '\0'; + +#ifdef _WIN32_WCE + wcsncpy( stdoutPath, path, SDL_arraysize(stdoutPath) ); + wcsncat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) ); +#else + SDL_strlcpy( stdoutPath, path, SDL_arraysize(stdoutPath) ); + SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) ); +#endif + + /* Redirect standard input and standard output */ + newfp = freopen(stdoutPath, TEXT("w"), stdout); + +#ifndef _WIN32_WCE + if ( newfp == NULL ) { /* This happens on NT */ +#if !defined(stdout) + stdout = fopen(stdoutPath, TEXT("w")); +#else + newfp = fopen(stdoutPath, TEXT("w")); + if ( newfp ) { + *stdout = *newfp; + } +#endif + } +#endif /* _WIN32_WCE */ + +#ifdef _WIN32_WCE + wcsncpy( stderrPath, path, SDL_arraysize(stdoutPath) ); + wcsncat( stderrPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) ); +#else + SDL_strlcpy( stderrPath, path, SDL_arraysize(stderrPath) ); + SDL_strlcat( stderrPath, DIR_SEPERATOR STDERR_FILE, SDL_arraysize(stderrPath) ); +#endif + + newfp = freopen(stderrPath, TEXT("w"), stderr); +#ifndef _WIN32_WCE + if ( newfp == NULL ) { /* This happens on NT */ +#if !defined(stderr) + stderr = fopen(stderrPath, TEXT("w")); +#else + newfp = fopen(stderrPath, TEXT("w")); + if ( newfp ) { + *stderr = *newfp; + } +#endif + } +#endif /* _WIN32_WCE */ + + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ + setbuf(stderr, NULL); /* No buffering */ + stdioRedirectEnabled = 1; +} + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +/* The VC++ compiler needs main defined */ +#define console_main main +#endif + +/* This is where execution begins [console apps] */ +int console_main(int argc, char *argv[]) +{ + size_t n; + char *bufp, *appname; + int status; + + /* Get the class name from argv[0] */ + appname = argv[0]; + if ( (bufp=SDL_strrchr(argv[0], '\\')) != NULL ) { + appname = bufp+1; + } else + if ( (bufp=SDL_strrchr(argv[0], '/')) != NULL ) { + appname = bufp+1; + } + + if ( (bufp=SDL_strrchr(appname, '.')) == NULL ) + n = SDL_strlen(appname); + else + n = (bufp-appname); + + bufp = SDL_stack_alloc(char, n+1); + if ( bufp == NULL ) { + return OutOfMemory(); + } + SDL_strlcpy(bufp, appname, n+1); + appname = bufp; + + /* Load SDL dynamic link library */ + if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) { + ShowError("WinMain() error", SDL_GetError()); + return(FALSE); + } + atexit(cleanup_output); + atexit(cleanup); + + /* Sam: + We still need to pass in the application handle so that + DirectInput will initialize properly when SDL_RegisterApp() + is called later in the video initialization. + */ + SDL_SetModuleHandle(GetModuleHandle(NULL)); + + /* Run the application main() code */ + status = SDL_main(argc, argv); + + /* Exit cleanly, calling atexit() functions */ + exit(status); + + /* Hush little compiler, don't you cry... */ + return 0; +} + +/* This is where execution begins [windowed apps] */ +#ifdef _WIN32_WCE +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw) +#else +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) +#endif +{ + HMODULE handle; + char **argv; + int argc; + char *cmdline; + char *env_str; +#ifdef _WIN32_WCE + wchar_t *bufp; + int nLen; +#else + char *bufp; + size_t nLen; +#endif + + /* Start up DDHELP.EXE before opening any files, so DDHELP doesn't + keep them open. This is a hack.. hopefully it will be fixed + someday. DDHELP.EXE starts up the first time DDRAW.DLL is loaded. + */ + handle = LoadLibrary(TEXT("DDRAW.DLL")); + if ( handle != NULL ) { + FreeLibrary(handle); + } + + /* Check for stdio redirect settings and do the redirection */ + if ((env_str = SDL_getenv("SDL_STDIO_REDIRECT"))) { + if (SDL_atoi(env_str)) { + redirect_output(); + } + } +#ifndef NO_STDIO_REDIRECT + else { + redirect_output(); + } +#endif + +#ifdef _WIN32_WCE + nLen = wcslen(szCmdLine)+128+1; + bufp = SDL_stack_alloc(wchar_t, nLen*2); + wcscpy (bufp, TEXT("\"")); + GetModuleFileName(NULL, bufp+1, 128-3); + wcscpy (bufp+wcslen(bufp), TEXT("\" ")); + wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp)); + nLen = wcslen(bufp)+1; + cmdline = SDL_stack_alloc(char, nLen); + if ( cmdline == NULL ) { + return OutOfMemory(); + } + WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL); +#else + /* Grab the command line */ + bufp = GetCommandLine(); + nLen = SDL_strlen(bufp)+1; + cmdline = SDL_stack_alloc(char, nLen); + if ( cmdline == NULL ) { + return OutOfMemory(); + } + SDL_strlcpy(cmdline, bufp, nLen); +#endif + + /* Parse it into argv and argc */ + argc = ParseCommandLine(cmdline, NULL); + argv = SDL_stack_alloc(char*, argc+1); + if ( argv == NULL ) { + return OutOfMemory(); + } + ParseCommandLine(cmdline, argv); + + /* Run the main program (after a little SDL initialization) */ + console_main(argc, argv); + + /* Hush little compiler, don't you cry... */ + return 0; +} diff --git a/3rdparty/SDL/src/main/win32/version.rc b/3rdparty/SDL/src/main/win32/version.rc new file mode 100644 index 0000000..38fb642 --- /dev/null +++ b/3rdparty/SDL/src/main/win32/version.rc @@ -0,0 +1,38 @@ + +#include "winresrc.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,14,0 + PRODUCTVERSION 1,2,14,0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "SDL\0" + VALUE "FileVersion", "1, 2, 14, 0\0" + VALUE "InternalName", "SDL\0" + VALUE "LegalCopyright", "Copyright 2009 Sam Lantinga\0" + VALUE "OriginalFilename", "SDL.dll\0" + VALUE "ProductName", "Simple DirectMedia Layer\0" + VALUE "ProductVersion", "1, 2, 14, 0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/3rdparty/SDL/src/stdlib/SDL_getenv.c b/3rdparty/SDL/src/stdlib/SDL_getenv.c new file mode 100644 index 0000000..30aba12 --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_getenv.c @@ -0,0 +1,247 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_stdinc.h" + +#ifndef HAVE_GETENV + +#if defined(__WIN32__) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Note this isn't thread-safe! */ + +static char *SDL_envmem = NULL; /* Ugh, memory leak */ +static size_t SDL_envmemlen = 0; + +/* Put a variable of the form "name=value" into the environment */ +int SDL_putenv(const char *variable) +{ + size_t bufferlen; + char *value; + const char *sep; + + sep = SDL_strchr(variable, '='); + if ( sep == NULL ) { + return -1; + } + bufferlen = SDL_strlen(variable)+1; + if ( bufferlen > SDL_envmemlen ) { + char *newmem = (char *)SDL_realloc(SDL_envmem, bufferlen); + if ( newmem == NULL ) { + return -1; + } + SDL_envmem = newmem; + SDL_envmemlen = bufferlen; + } + SDL_strlcpy(SDL_envmem, variable, bufferlen); + value = SDL_envmem + (sep - variable); + *value++ = '\0'; + if ( !SetEnvironmentVariable(SDL_envmem, *value ? value : NULL) ) { + return -1; + } + return 0; +} + +/* Retrieve a variable named "name" from the environment */ +char *SDL_getenv(const char *name) +{ + size_t bufferlen; + + bufferlen = GetEnvironmentVariable(name, SDL_envmem, (DWORD)SDL_envmemlen); + if ( bufferlen == 0 ) { + return NULL; + } + if ( bufferlen > SDL_envmemlen ) { + char *newmem = (char *)SDL_realloc(SDL_envmem, bufferlen); + if ( newmem == NULL ) { + return NULL; + } + SDL_envmem = newmem; + SDL_envmemlen = bufferlen; + GetEnvironmentVariable(name, SDL_envmem, (DWORD)SDL_envmemlen); + } + return SDL_envmem; +} + +#else /* roll our own */ + +static char **SDL_env = (char **)0; + +/* Put a variable of the form "name=value" into the environment */ +int SDL_putenv(const char *variable) +{ + const char *name, *value; + int added; + int len, i; + char **new_env; + char *new_variable; + + /* A little error checking */ + if ( ! variable ) { + return(-1); + } + name = variable; + for ( value=variable; *value && (*value != '='); ++value ) { + /* Keep looking for '=' */ ; + } + if ( *value ) { + ++value; + } else { + return(-1); + } + + /* Allocate memory for the variable */ + new_variable = SDL_strdup(variable); + if ( ! new_variable ) { + return(-1); + } + + /* Actually put it into the environment */ + added = 0; + i = 0; + if ( SDL_env ) { + /* Check to see if it's already there... */ + len = (value - name); + for ( ; SDL_env[i]; ++i ) { + if ( SDL_strncmp(SDL_env[i], name, len) == 0 ) { + break; + } + } + /* If we found it, just replace the entry */ + if ( SDL_env[i] ) { + SDL_free(SDL_env[i]); + SDL_env[i] = new_variable; + added = 1; + } + } + + /* Didn't find it in the environment, expand and add */ + if ( ! added ) { + new_env = SDL_realloc(SDL_env, (i+2)*sizeof(char *)); + if ( new_env ) { + SDL_env = new_env; + SDL_env[i++] = new_variable; + SDL_env[i++] = (char *)0; + added = 1; + } else { + SDL_free(new_variable); + } + } + return (added ? 0 : -1); +} + +/* Retrieve a variable named "name" from the environment */ +char *SDL_getenv(const char *name) +{ + int len, i; + char *value; + + value = (char *)0; + if ( SDL_env ) { + len = SDL_strlen(name); + for ( i=0; SDL_env[i] && !value; ++i ) { + if ( (SDL_strncmp(SDL_env[i], name, len) == 0) && + (SDL_env[i][len] == '=') ) { + value = &SDL_env[i][len+1]; + } + } + } + return value; +} + +#endif /* __WIN32__ */ + +#endif /* !HAVE_GETENV */ + +#ifdef TEST_MAIN +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + char *value; + + printf("Checking for non-existent variable... "); + fflush(stdout); + if ( ! SDL_getenv("EXISTS") ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Setting FIRST=VALUE1 in the environment... "); + fflush(stdout); + if ( SDL_putenv("FIRST=VALUE1") == 0 ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Getting FIRST from the environment... "); + fflush(stdout); + value = SDL_getenv("FIRST"); + if ( value && (SDL_strcmp(value, "VALUE1") == 0) ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Setting SECOND=VALUE2 in the environment... "); + fflush(stdout); + if ( SDL_putenv("SECOND=VALUE2") == 0 ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Getting SECOND from the environment... "); + fflush(stdout); + value = SDL_getenv("SECOND"); + if ( value && (SDL_strcmp(value, "VALUE2") == 0) ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Setting FIRST=NOVALUE in the environment... "); + fflush(stdout); + if ( SDL_putenv("FIRST=NOVALUE") == 0 ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Getting FIRST from the environment... "); + fflush(stdout); + value = SDL_getenv("FIRST"); + if ( value && (SDL_strcmp(value, "NOVALUE") == 0) ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + printf("Checking for non-existent variable... "); + fflush(stdout); + if ( ! SDL_getenv("EXISTS") ) { + printf("okay\n"); + } else { + printf("failed\n"); + } + return(0); +} +#endif /* TEST_MAIN */ + diff --git a/3rdparty/SDL/src/stdlib/SDL_iconv.c b/3rdparty/SDL/src/stdlib/SDL_iconv.c new file mode 100644 index 0000000..fa56a99 --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_iconv.c @@ -0,0 +1,881 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file contains portable iconv functions for SDL */ + +#include "SDL_stdinc.h" +#include "SDL_endian.h" + +#ifdef HAVE_ICONV + +/* Depending on which standard the iconv() was implemented with, + iconv() may or may not use const char ** for the inbuf param. + If we get this wrong, it's just a warning, so no big deal. +*/ +#if defined(_XGP6) || \ + defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) +#define ICONV_INBUF_NONCONST +#endif + +#include <errno.h> + +size_t SDL_iconv(SDL_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + size_t retCode; +#ifdef ICONV_INBUF_NONCONST + retCode = iconv(cd, (char **)inbuf, inbytesleft, outbuf, outbytesleft); +#else + retCode = iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft); +#endif + if ( retCode == (size_t)-1 ) { + switch(errno) { + case E2BIG: + return SDL_ICONV_E2BIG; + case EILSEQ: + return SDL_ICONV_EILSEQ; + case EINVAL: + return SDL_ICONV_EINVAL; + default: + return SDL_ICONV_ERROR; + } + } + return retCode; +} + +#else + +/* Lots of useful information on Unicode at: + http://www.cl.cam.ac.uk/~mgk25/unicode.html +*/ + +#define UNICODE_BOM 0xFEFF + +#define UNKNOWN_ASCII '?' +#define UNKNOWN_UNICODE 0xFFFD + +enum { + ENCODING_UNKNOWN, + ENCODING_ASCII, + ENCODING_LATIN1, + ENCODING_UTF8, + ENCODING_UTF16, /* Needs byte order marker */ + ENCODING_UTF16BE, + ENCODING_UTF16LE, + ENCODING_UTF32, /* Needs byte order marker */ + ENCODING_UTF32BE, + ENCODING_UTF32LE, + ENCODING_UCS2, /* Native byte order assumed */ + ENCODING_UCS4, /* Native byte order assumed */ +}; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define ENCODING_UTF16NATIVE ENCODING_UTF16BE +#define ENCODING_UTF32NATIVE ENCODING_UTF32BE +#else +#define ENCODING_UTF16NATIVE ENCODING_UTF16LE +#define ENCODING_UTF32NATIVE ENCODING_UTF32LE +#endif + +struct _SDL_iconv_t +{ + int src_fmt; + int dst_fmt; +}; + +static struct { + const char *name; + int format; +} encodings[] = { + { "ASCII", ENCODING_ASCII }, + { "US-ASCII", ENCODING_ASCII }, + { "8859-1", ENCODING_LATIN1 }, + { "ISO-8859-1", ENCODING_LATIN1 }, + { "UTF8", ENCODING_UTF8 }, + { "UTF-8", ENCODING_UTF8 }, + { "UTF16", ENCODING_UTF16 }, + { "UTF-16", ENCODING_UTF16 }, + { "UTF16BE", ENCODING_UTF16BE }, + { "UTF-16BE", ENCODING_UTF16BE }, + { "UTF16LE", ENCODING_UTF16LE }, + { "UTF-16LE", ENCODING_UTF16LE }, + { "UTF32", ENCODING_UTF32 }, + { "UTF-32", ENCODING_UTF32 }, + { "UTF32BE", ENCODING_UTF32BE }, + { "UTF-32BE", ENCODING_UTF32BE }, + { "UTF32LE", ENCODING_UTF32LE }, + { "UTF-32LE", ENCODING_UTF32LE }, + { "UCS2", ENCODING_UCS2 }, + { "UCS-2", ENCODING_UCS2 }, + { "UCS4", ENCODING_UCS4 }, + { "UCS-4", ENCODING_UCS4 }, +}; + +static const char *getlocale(char *buffer, size_t bufsize) +{ + const char *lang; + char *ptr; + + lang = SDL_getenv("LC_ALL"); + if ( !lang ) { + lang = SDL_getenv("LC_CTYPE"); + } + if ( !lang ) { + lang = SDL_getenv("LC_MESSAGES"); + } + if ( !lang ) { + lang = SDL_getenv("LANG"); + } + if ( !lang || !*lang || SDL_strcmp(lang, "C") == 0 ) { + lang = "ASCII"; + } + + /* We need to trim down strings like "en_US.UTF-8@blah" to "UTF-8" */ + ptr = SDL_strchr(lang, '.'); + if (ptr != NULL) { + lang = ptr + 1; + } + + SDL_strlcpy(buffer, lang, bufsize); + ptr = SDL_strchr(buffer, '@'); + if (ptr != NULL) { + *ptr = '\0'; /* chop end of string. */ + } + + return buffer; +} + +SDL_iconv_t SDL_iconv_open(const char *tocode, const char *fromcode) +{ + int src_fmt = ENCODING_UNKNOWN; + int dst_fmt = ENCODING_UNKNOWN; + int i; + char fromcode_buffer[64]; + char tocode_buffer[64]; + + if ( !fromcode || !*fromcode ) { + fromcode = getlocale(fromcode_buffer, sizeof(fromcode_buffer)); + } + if ( !tocode || !*tocode ) { + tocode = getlocale(tocode_buffer, sizeof(tocode_buffer)); + } + for ( i = 0; i < SDL_arraysize(encodings); ++i ) { + if ( SDL_strcasecmp(fromcode, encodings[i].name) == 0 ) { + src_fmt = encodings[i].format; + if ( dst_fmt != ENCODING_UNKNOWN ) { + break; + } + } + if ( SDL_strcasecmp(tocode, encodings[i].name) == 0 ) { + dst_fmt = encodings[i].format; + if ( src_fmt != ENCODING_UNKNOWN ) { + break; + } + } + } + if ( src_fmt != ENCODING_UNKNOWN && dst_fmt != ENCODING_UNKNOWN ) { + SDL_iconv_t cd = (SDL_iconv_t)SDL_malloc(sizeof(*cd)); + if ( cd ) { + cd->src_fmt = src_fmt; + cd->dst_fmt = dst_fmt; + return cd; + } + } + return (SDL_iconv_t)-1; +} + +size_t SDL_iconv(SDL_iconv_t cd, + const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + /* For simplicity, we'll convert everything to and from UCS-4 */ + const char *src; + char *dst; + size_t srclen, dstlen; + Uint32 ch = 0; + size_t total; + + if ( !inbuf || !*inbuf ) { + /* Reset the context */ + return 0; + } + if ( !outbuf || !*outbuf || !outbytesleft || !*outbytesleft ) { + return SDL_ICONV_E2BIG; + } + src = *inbuf; + srclen = (inbytesleft ? *inbytesleft : 0); + dst = *outbuf; + dstlen = *outbytesleft; + + switch ( cd->src_fmt ) { + case ENCODING_UTF16: + /* Scan for a byte order marker */ + { + Uint8 *p = (Uint8 *)src; + size_t n = srclen / 2; + while ( n ) { + if ( p[0] == 0xFF && p[1] == 0xFE ) { + cd->src_fmt = ENCODING_UTF16BE; + break; + } else if ( p[0] == 0xFE && p[1] == 0xFF ) { + cd->src_fmt = ENCODING_UTF16LE; + break; + } + p += 2; + --n; + } + if ( n == 0 ) { + /* We can't tell, default to host order */ + cd->src_fmt = ENCODING_UTF16NATIVE; + } + } + break; + case ENCODING_UTF32: + /* Scan for a byte order marker */ + { + Uint8 *p = (Uint8 *)src; + size_t n = srclen / 4; + while ( n ) { + if ( p[0] == 0xFF && p[1] == 0xFE && + p[2] == 0x00 && p[3] == 0x00 ) { + cd->src_fmt = ENCODING_UTF32BE; + break; + } else if ( p[0] == 0x00 && p[1] == 0x00 && + p[2] == 0xFE && p[3] == 0xFF ) { + cd->src_fmt = ENCODING_UTF32LE; + break; + } + p += 4; + --n; + } + if ( n == 0 ) { + /* We can't tell, default to host order */ + cd->src_fmt = ENCODING_UTF32NATIVE; + } + } + break; + } + + switch ( cd->dst_fmt ) { + case ENCODING_UTF16: + /* Default to host order, need to add byte order marker */ + if ( dstlen < 2 ) { + return SDL_ICONV_E2BIG; + } + *(Uint16 *)dst = UNICODE_BOM; + dst += 2; + dstlen -= 2; + cd->dst_fmt = ENCODING_UTF16NATIVE; + break; + case ENCODING_UTF32: + /* Default to host order, need to add byte order marker */ + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + *(Uint32 *)dst = UNICODE_BOM; + dst += 4; + dstlen -= 4; + cd->dst_fmt = ENCODING_UTF32NATIVE; + break; + } + + total = 0; + while ( srclen > 0 ) { + /* Decode a character */ + switch ( cd->src_fmt ) { + case ENCODING_ASCII: + { + Uint8 *p = (Uint8 *)src; + ch = (Uint32)(p[0] & 0x7F); + ++src; + --srclen; + } + break; + case ENCODING_LATIN1: + { + Uint8 *p = (Uint8 *)src; + ch = (Uint32)p[0]; + ++src; + --srclen; + } + break; + case ENCODING_UTF8: /* RFC 3629 */ + { + Uint8 *p = (Uint8 *)src; + size_t left = 0; + SDL_bool overlong = SDL_FALSE; + if ( p[0] >= 0xFC ) { + if ( (p[0] & 0xFE) != 0xFC ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ( p[0] == 0xFC ) { + overlong = SDL_TRUE; + } + ch = (Uint32)(p[0] & 0x01); + left = 5; + } + } else if ( p[0] >= 0xF8 ) { + if ( (p[0] & 0xFC) != 0xF8 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ( p[0] == 0xF8 ) { + overlong = SDL_TRUE; + } + ch = (Uint32)(p[0] & 0x03); + left = 4; + } + } else if ( p[0] >= 0xF0 ) { + if ( (p[0] & 0xF8) != 0xF0 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ( p[0] == 0xF0 ) { + overlong = SDL_TRUE; + } + ch = (Uint32)(p[0] & 0x07); + left = 3; + } + } else if ( p[0] >= 0xE0 ) { + if ( (p[0] & 0xF0) != 0xE0 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ( p[0] == 0xE0 ) { + overlong = SDL_TRUE; + } + ch = (Uint32)(p[0] & 0x0F); + left = 2; + } + } else if ( p[0] >= 0xC0 ) { + if ( (p[0] & 0xE0) != 0xC0 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ( (p[0] & 0xDE) == 0xC0 ) { + overlong = SDL_TRUE; + } + ch = (Uint32)(p[0] & 0x1F); + left = 1; + } + } else { + if ( (p[0] & 0x80) != 0x00 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + ch = (Uint32)p[0]; + } + } + ++src; + --srclen; + if ( srclen < left ) { + return SDL_ICONV_EINVAL; + } + while ( left-- ) { + ++p; + if ( (p[0] & 0xC0) != 0x80 ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + ch <<= 6; + ch |= (p[0] & 0x3F); + ++src; + --srclen; + } + if ( overlong ) { + /* Potential security risk + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } + if ( (ch >= 0xD800 && ch <= 0xDFFF) || + (ch == 0xFFFE || ch == 0xFFFF) || + ch > 0x10FFFF ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } + } + break; + case ENCODING_UTF16BE: /* RFC 2781 */ + { + Uint8 *p = (Uint8 *)src; + Uint16 W1, W2; + if ( srclen < 2 ) { + return SDL_ICONV_EINVAL; + } + W1 = ((Uint16)p[0] << 8) | + (Uint16)p[1]; + src += 2; + srclen -= 2; + if ( W1 < 0xD800 || W1 > 0xDFFF ) { + ch = (Uint32)W1; + break; + } + if ( W1 > 0xDBFF ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + if ( srclen < 2 ) { + return SDL_ICONV_EINVAL; + } + p = (Uint8 *)src; + W2 = ((Uint16)p[0] << 8) | + (Uint16)p[1]; + src += 2; + srclen -= 2; + if ( W2 < 0xDC00 || W2 > 0xDFFF ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + ch = (((Uint32)(W1 & 0x3FF) << 10) | + (Uint32)(W2 & 0x3FF)) + 0x10000; + } + break; + case ENCODING_UTF16LE: /* RFC 2781 */ + { + Uint8 *p = (Uint8 *)src; + Uint16 W1, W2; + if ( srclen < 2 ) { + return SDL_ICONV_EINVAL; + } + W1 = ((Uint16)p[1] << 8) | + (Uint16)p[0]; + src += 2; + srclen -= 2; + if ( W1 < 0xD800 || W1 > 0xDFFF ) { + ch = (Uint32)W1; + break; + } + if ( W1 > 0xDBFF ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + if ( srclen < 2 ) { + return SDL_ICONV_EINVAL; + } + p = (Uint8 *)src; + W2 = ((Uint16)p[1] << 8) | + (Uint16)p[0]; + src += 2; + srclen -= 2; + if ( W2 < 0xDC00 || W2 > 0xDFFF ) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + ch = (((Uint32)(W1 & 0x3FF) << 10) | + (Uint32)(W2 & 0x3FF)) + 0x10000; + } + break; + case ENCODING_UTF32BE: + { + Uint8 *p = (Uint8 *)src; + if ( srclen < 4 ) { + return SDL_ICONV_EINVAL; + } + ch = ((Uint32)p[0] << 24) | + ((Uint32)p[1] << 16) | + ((Uint32)p[2] << 8) | + (Uint32)p[3]; + src += 4; + srclen -= 4; + } + break; + case ENCODING_UTF32LE: + { + Uint8 *p = (Uint8 *)src; + if ( srclen < 4 ) { + return SDL_ICONV_EINVAL; + } + ch = ((Uint32)p[3] << 24) | + ((Uint32)p[2] << 16) | + ((Uint32)p[1] << 8) | + (Uint32)p[0]; + src += 4; + srclen -= 4; + } + break; + case ENCODING_UCS2: + { + Uint16 *p = (Uint16 *)src; + if ( srclen < 2 ) { + return SDL_ICONV_EINVAL; + } + ch = *p; + src += 2; + srclen -= 2; + } + break; + case ENCODING_UCS4: + { + Uint32 *p = (Uint32 *)src; + if ( srclen < 4 ) { + return SDL_ICONV_EINVAL; + } + ch = *p; + src += 4; + srclen -= 4; + } + break; + } + + /* Encode a character */ + switch ( cd->dst_fmt ) { + case ENCODING_ASCII: + { + Uint8 *p = (Uint8 *)dst; + if ( dstlen < 1 ) { + return SDL_ICONV_E2BIG; + } + if ( ch > 0x7F ) { + *p = UNKNOWN_ASCII; + } else { + *p = (Uint8)ch; + } + ++dst; + --dstlen; + } + break; + case ENCODING_LATIN1: + { + Uint8 *p = (Uint8 *)dst; + if ( dstlen < 1 ) { + return SDL_ICONV_E2BIG; + } + if ( ch > 0xFF ) { + *p = UNKNOWN_ASCII; + } else { + *p = (Uint8)ch; + } + ++dst; + --dstlen; + } + break; + case ENCODING_UTF8: /* RFC 3629 */ + { + Uint8 *p = (Uint8 *)dst; + if ( ch > 0x10FFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( ch <= 0x7F ) { + if ( dstlen < 1 ) { + return SDL_ICONV_E2BIG; + } + *p = (Uint8)ch; + ++dst; + --dstlen; + } else if ( ch <= 0x7FF ) { + if ( dstlen < 2 ) { + return SDL_ICONV_E2BIG; + } + p[0] = 0xC0 | (Uint8)((ch >> 6) & 0x1F); + p[1] = 0x80 | (Uint8)(ch & 0x3F); + dst += 2; + dstlen -= 2; + } else if ( ch <= 0xFFFF ) { + if ( dstlen < 3 ) { + return SDL_ICONV_E2BIG; + } + p[0] = 0xE0 | (Uint8)((ch >> 12) & 0x0F); + p[1] = 0x80 | (Uint8)((ch >> 6) & 0x3F); + p[2] = 0x80 | (Uint8)(ch & 0x3F); + dst += 3; + dstlen -= 3; + } else if ( ch <= 0x1FFFFF ) { + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + p[0] = 0xF0 | (Uint8)((ch >> 18) & 0x07); + p[1] = 0x80 | (Uint8)((ch >> 12) & 0x3F); + p[2] = 0x80 | (Uint8)((ch >> 6) & 0x3F); + p[3] = 0x80 | (Uint8)(ch & 0x3F); + dst += 4; + dstlen -= 4; + } else if ( ch <= 0x3FFFFFF ) { + if ( dstlen < 5 ) { + return SDL_ICONV_E2BIG; + } + p[0] = 0xF8 | (Uint8)((ch >> 24) & 0x03); + p[1] = 0x80 | (Uint8)((ch >> 18) & 0x3F); + p[2] = 0x80 | (Uint8)((ch >> 12) & 0x3F); + p[3] = 0x80 | (Uint8)((ch >> 6) & 0x3F); + p[4] = 0x80 | (Uint8)(ch & 0x3F); + dst += 5; + dstlen -= 5; + } else { + if ( dstlen < 6 ) { + return SDL_ICONV_E2BIG; + } + p[0] = 0xFC | (Uint8)((ch >> 30) & 0x01); + p[1] = 0x80 | (Uint8)((ch >> 24) & 0x3F); + p[2] = 0x80 | (Uint8)((ch >> 18) & 0x3F); + p[3] = 0x80 | (Uint8)((ch >> 12) & 0x3F); + p[4] = 0x80 | (Uint8)((ch >> 6) & 0x3F); + p[5] = 0x80 | (Uint8)(ch & 0x3F); + dst += 6; + dstlen -= 6; + } + } + break; + case ENCODING_UTF16BE: /* RFC 2781 */ + { + Uint8 *p = (Uint8 *)dst; + if ( ch > 0x10FFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( ch < 0x10000 ) { + if ( dstlen < 2 ) { + return SDL_ICONV_E2BIG; + } + p[0] = (Uint8)(ch >> 8); + p[1] = (Uint8)ch; + dst += 2; + dstlen -= 2; + } else { + Uint16 W1, W2; + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + ch = ch - 0x10000; + W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF); + W2 = 0xDC00 | (Uint16)(ch & 0x3FF); + p[0] = (Uint8)(W1 >> 8); + p[1] = (Uint8)W1; + p[2] = (Uint8)(W2 >> 8); + p[3] = (Uint8)W2; + dst += 4; + dstlen -= 4; + } + } + break; + case ENCODING_UTF16LE: /* RFC 2781 */ + { + Uint8 *p = (Uint8 *)dst; + if ( ch > 0x10FFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( ch < 0x10000 ) { + if ( dstlen < 2 ) { + return SDL_ICONV_E2BIG; + } + p[1] = (Uint8)(ch >> 8); + p[0] = (Uint8)ch; + dst += 2; + dstlen -= 2; + } else { + Uint16 W1, W2; + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + ch = ch - 0x10000; + W1 = 0xD800 | (Uint16)((ch >> 10) & 0x3FF); + W2 = 0xDC00 | (Uint16)(ch & 0x3FF); + p[1] = (Uint8)(W1 >> 8); + p[0] = (Uint8)W1; + p[3] = (Uint8)(W2 >> 8); + p[2] = (Uint8)W2; + dst += 4; + dstlen -= 4; + } + } + break; + case ENCODING_UTF32BE: + { + Uint8 *p = (Uint8 *)dst; + if ( ch > 0x10FFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + p[0] = (Uint8)(ch >> 24); + p[1] = (Uint8)(ch >> 16); + p[2] = (Uint8)(ch >> 8); + p[3] = (Uint8)ch; + dst += 4; + dstlen -= 4; + } + break; + case ENCODING_UTF32LE: + { + Uint8 *p = (Uint8 *)dst; + if ( ch > 0x10FFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + p[3] = (Uint8)(ch >> 24); + p[2] = (Uint8)(ch >> 16); + p[1] = (Uint8)(ch >> 8); + p[0] = (Uint8)ch; + dst += 4; + dstlen -= 4; + } + break; + case ENCODING_UCS2: + { + Uint16 *p = (Uint16 *)dst; + if ( ch > 0xFFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( dstlen < 2 ) { + return SDL_ICONV_E2BIG; + } + *p = (Uint16)ch; + dst += 2; + dstlen -= 2; + } + break; + case ENCODING_UCS4: + { + Uint32 *p = (Uint32 *)dst; + if ( ch > 0x7FFFFFFF ) { + ch = UNKNOWN_UNICODE; + } + if ( dstlen < 4 ) { + return SDL_ICONV_E2BIG; + } + *p = ch; + dst += 4; + dstlen -= 4; + } + break; + } + + /* Update state */ + *inbuf = src; + *inbytesleft = srclen; + *outbuf = dst; + *outbytesleft = dstlen; + ++total; + } + return total; +} + +int SDL_iconv_close(SDL_iconv_t cd) +{ + if ( cd && cd != (SDL_iconv_t)-1 ) { + SDL_free(cd); + } + return 0; +} + +#endif /* !HAVE_ICONV */ + +char *SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft) +{ + SDL_iconv_t cd; + char *string; + size_t stringsize; + char *outbuf; + size_t outbytesleft; + size_t retCode = 0; + + cd = SDL_iconv_open(tocode, fromcode); + if ( cd == (SDL_iconv_t)-1 ) { + /* See if we can recover here (fixes iconv on Solaris 11) */ + if ( !tocode || !*tocode ) { + tocode = "UTF-8"; + } + if ( !fromcode || !*fromcode ) { + fromcode = "UTF-8"; + } + cd = SDL_iconv_open(tocode, fromcode); + } + if ( cd == (SDL_iconv_t)-1 ) { + return NULL; + } + + stringsize = inbytesleft > 4 ? inbytesleft : 4; + string = SDL_malloc(stringsize); + if ( !string ) { + SDL_iconv_close(cd); + return NULL; + } + outbuf = string; + outbytesleft = stringsize; + SDL_memset(outbuf, 0, 4); + + while ( inbytesleft > 0 ) { + retCode = SDL_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + switch (retCode) { + case SDL_ICONV_E2BIG: + { + char *oldstring = string; + stringsize *= 2; + string = SDL_realloc(string, stringsize); + if ( !string ) { + SDL_iconv_close(cd); + return NULL; + } + outbuf = string + (outbuf - oldstring); + outbytesleft = stringsize - (outbuf - string); + SDL_memset(outbuf, 0, 4); + } + break; + case SDL_ICONV_EILSEQ: + /* Try skipping some input data - not perfect, but... */ + ++inbuf; + --inbytesleft; + break; + case SDL_ICONV_EINVAL: + case SDL_ICONV_ERROR: + /* We can't continue... */ + inbytesleft = 0; + break; + } + } + SDL_iconv_close(cd); + + return string; +} diff --git a/3rdparty/SDL/src/stdlib/SDL_malloc.c b/3rdparty/SDL/src/stdlib/SDL_malloc.c new file mode 100644 index 0000000..f025e43 --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_malloc.c @@ -0,0 +1,5111 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file contains portable memory management functions for SDL */ + +#include "SDL_stdinc.h" + +#ifndef HAVE_MALLOC + +#define LACKS_SYS_TYPES_H +#define LACKS_STDIO_H +#define LACKS_STRINGS_H +#define LACKS_STRING_H +#define LACKS_STDLIB_H +#define ABORT + +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain, as explained at + http://creativecommons.org/licenses/publicdomain. Send questions, + comments, complaints, performance data, etc to dl@cs.oswego.edu + +* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + +* Quickstart + + This library is all in one file to simplify the most common usage: + ftp it, compile it (-O3), and link it into another program. All of + the compile-time options default to reasonable values for use on + most platforms. You might later want to step through various + compile-time and dynamic tuning options. + + For convenience, an include file for code using this malloc is at: + ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h + You don't really need this .h file unless you call functions not + defined in your system include files. The .h file contains only the + excerpts from this file needed for using this malloc on ANSI C/C++ + systems, so long as you haven't changed compile-time options about + naming and tuning parameters. If you do, then you can create your + own malloc.h that does include all settings by cutting at the point + indicated below. Note that you may already by default be using a C + library containing a malloc that is based on some version of this + malloc (for example in linux). You might still want to use the one + in this file to customize settings or to avoid overheads associated + with library versions. + +* Vital statistics: + + Supported pointer/size_t representation: 4 or 8 bytes + size_t MUST be an unsigned type of the same width as + pointers. (If you are using an ancient system that declares + size_t as a signed type, or need it to be a different width + than pointers, you can use a previous release of this malloc + (e.g. 2.7.2) supporting these.) + + Alignment: 8 bytes (default) + This suffices for nearly all current machines and C compilers. + However, you can define MALLOC_ALIGNMENT to be wider than this + if necessary (up to 128bytes), at the expense of using more space. + + Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) + 8 or 16 bytes (if 8byte sizes) + Each malloced chunk has a hidden word of overhead holding size + and status information, and additional cross-check word + if FOOTERS is defined. + + Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) + 8-byte ptrs: 32 bytes (including overhead) + + Even a request for zero bytes (i.e., malloc(0)) returns a + pointer to something of the minimum allocatable size. + The maximum overhead wastage (i.e., number of extra bytes + allocated than were requested in malloc) is less than or equal + to the minimum size, except for requests >= mmap_threshold that + are serviced via mmap(), where the worst case wastage is about + 32 bytes plus the remainder from a system page (the minimal + mmap unit); typically 4096 or 8192 bytes. + + Security: static-safe; optionally more or less + The "security" of malloc refers to the ability of malicious + code to accentuate the effects of errors (for example, freeing + space that is not currently malloc'ed or overwriting past the + ends of chunks) in code that calls malloc. This malloc + guarantees not to modify any memory locations below the base of + heap, i.e., static variables, even in the presence of usage + errors. The routines additionally detect most improper frees + and reallocs. All this holds as long as the static bookkeeping + for malloc itself is not corrupted by some other means. This + is only one aspect of security -- these checks do not, and + cannot, detect all possible programming errors. + + If FOOTERS is defined nonzero, then each allocated chunk + carries an additional check word to verify that it was malloced + from its space. These check words are the same within each + execution of a program using malloc, but differ across + executions, so externally crafted fake chunks cannot be + freed. This improves security by rejecting frees/reallocs that + could corrupt heap memory, in addition to the checks preventing + writes to statics that are always on. This may further improve + security at the expense of time and space overhead. (Note that + FOOTERS may also be worth using with MSPACES.) + + By default detected errors cause the program to abort (calling + "abort()"). You can override this to instead proceed past + errors by defining PROCEED_ON_ERROR. In this case, a bad free + has no effect, and a malloc that encounters a bad address + caused by user overwrites will ignore the bad address by + dropping pointers and indices to all known memory. This may + be appropriate for programs that should continue if at all + possible in the face of programming errors, although they may + run out of memory because dropped memory is never reclaimed. + + If you don't like either of these options, you can define + CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything + else. And if if you are sure that your program using malloc has + no errors or vulnerabilities, you can define INSECURE to 1, + which might (or might not) provide a small performance improvement. + + Thread-safety: NOT thread-safe unless USE_LOCKS defined + When USE_LOCKS is defined, each public call to malloc, free, + etc is surrounded with either a pthread mutex or a win32 + spinlock (depending on WIN32). This is not especially fast, and + can be a major bottleneck. It is designed only to provide + minimal protection in concurrent environments, and to provide a + basis for extensions. If you are using malloc in a concurrent + program, consider instead using ptmalloc, which is derived from + a version of this malloc. (See http://www.malloc.de). + + System requirements: Any combination of MORECORE and/or MMAP/MUNMAP + This malloc can use unix sbrk or any emulation (invoked using + the CALL_MORECORE macro) and/or mmap/munmap or any emulation + (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system + memory. On most unix systems, it tends to work best if both + MORECORE and MMAP are enabled. On Win32, it uses emulations + based on VirtualAlloc. It also uses common C library functions + like memset. + + Compliance: I believe it is compliant with the Single Unix Specification + (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably + others as well. + +* Overview of algorithms + + This is not the fastest, most space-conserving, most portable, or + most tunable malloc ever written. However it is among the fastest + while also being among the most space-conserving, portable and + tunable. Consistent balance across these factors results in a good + general-purpose allocator for malloc-intensive programs. + + In most ways, this malloc is a best-fit allocator. Generally, it + chooses the best-fitting existing chunk for a request, with ties + broken in approximately least-recently-used order. (This strategy + normally maintains low fragmentation.) However, for requests less + than 256bytes, it deviates from best-fit when there is not an + exactly fitting available chunk by preferring to use space adjacent + to that used for the previous small request, as well as by breaking + ties in approximately most-recently-used order. (These enhance + locality of series of small allocations.) And for very large requests + (>= 256Kb by default), it relies on system memory mapping + facilities, if supported. (This helps avoid carrying around and + possibly fragmenting memory used only for large chunks.) + + All operations (except malloc_stats and mallinfo) have execution + times that are bounded by a constant factor of the number of bits in + a size_t, not counting any clearing in calloc or copying in realloc, + or actions surrounding MORECORE and MMAP that have times + proportional to the number of non-contiguous regions returned by + system allocation routines, which is often just 1. + + The implementation is not very modular and seriously overuses + macros. Perhaps someday all C compilers will do as good a job + inlining modular code as can now be done by brute-force expansion, + but now, enough of them seem not to. + + Some compilers issue a lot of warnings about code that is + dead/unreachable only on some platforms, and also about intentional + uses of negation on unsigned types. All known cases of each can be + ignored. + + For a longer but out of date high-level description, see + http://gee.cs.oswego.edu/dl/html/malloc.html + +* MSPACES + If MSPACES is defined, then in addition to malloc, free, etc., + this file also defines mspace_malloc, mspace_free, etc. These + are versions of malloc routines that take an "mspace" argument + obtained using create_mspace, to control all internal bookkeeping. + If ONLY_MSPACES is defined, only these versions are compiled. + So if you would like to use this allocator for only some allocations, + and your system malloc for others, you can compile with + ONLY_MSPACES and then do something like... + static mspace mymspace = create_mspace(0,0); // for example + #define mymalloc(bytes) mspace_malloc(mymspace, bytes) + + (Note: If you only need one instance of an mspace, you can instead + use "USE_DL_PREFIX" to relabel the global malloc.) + + You can similarly create thread-local allocators by storing + mspaces as thread-locals. For example: + static __thread mspace tlms = 0; + void* tlmalloc(size_t bytes) { + if (tlms == 0) tlms = create_mspace(0, 0); + return mspace_malloc(tlms, bytes); + } + void tlfree(void* mem) { mspace_free(tlms, mem); } + + Unless FOOTERS is defined, each mspace is completely independent. + You cannot allocate from one and free to another (although + conformance is only weakly checked, so usage errors are not always + caught). If FOOTERS is defined, then each chunk carries around a tag + indicating its originating mspace, and frees are directed to their + originating spaces. + + ------------------------- Compile-time options --------------------------- + +Be careful in setting #define values for numerical constants of type +size_t. On some systems, literal values are not automatically extended +to size_t precision unless they are explicitly casted. + +WIN32 default: defined if _WIN32 defined + Defining WIN32 sets up defaults for MS environment and compilers. + Otherwise defaults are for unix. + +MALLOC_ALIGNMENT default: (size_t)8 + Controls the minimum alignment for malloc'ed chunks. It must be a + power of two and at least 8, even on machines for which smaller + alignments would suffice. It may be defined as larger than this + though. Note however that code and data structures are optimized for + the case of 8-byte alignment. + +MSPACES default: 0 (false) + If true, compile in support for independent allocation spaces. + This is only supported if HAVE_MMAP is true. + +ONLY_MSPACES default: 0 (false) + If true, only compile in mspace versions, not regular versions. + +USE_LOCKS default: 0 (false) + Causes each call to each public routine to be surrounded with + pthread or WIN32 mutex lock/unlock. (If set true, this can be + overridden on a per-mspace basis for mspace versions.) + +FOOTERS default: 0 + If true, provide extra checking and dispatching by placing + information in the footers of allocated chunks. This adds + space and time overhead. + +INSECURE default: 0 + If true, omit checks for usage errors and heap space overwrites. + +USE_DL_PREFIX default: NOT defined + Causes compiler to prefix all public routines with the string 'dl'. + This can be useful when you only want to use this malloc in one part + of a program, using your regular system malloc elsewhere. + +ABORT default: defined as abort() + Defines how to abort on failed checks. On most systems, a failed + check cannot die with an "assert" or even print an informative + message, because the underlying print routines in turn call malloc, + which will fail again. Generally, the best policy is to simply call + abort(). It's not very useful to do more than this because many + errors due to overwriting will show up as address faults (null, odd + addresses etc) rather than malloc-triggered checks, so will also + abort. Also, most compilers know that abort() does not return, so + can better optimize code conditionally calling it. + +PROCEED_ON_ERROR default: defined as 0 (false) + Controls whether detected bad addresses cause them to bypassed + rather than aborting. If set, detected bad arguments to free and + realloc are ignored. And all bookkeeping information is zeroed out + upon a detected overwrite of freed heap space, thus losing the + ability to ever return it from malloc again, but enabling the + application to proceed. If PROCEED_ON_ERROR is defined, the + static variable malloc_corruption_error_count is compiled in + and can be examined to see if errors have occurred. This option + generates slower code than the default abort policy. + +DEBUG default: NOT defined + The DEBUG setting is mainly intended for people trying to modify + this code or diagnose problems when porting to new platforms. + However, it may also be able to better isolate user errors than just + using runtime checks. The assertions in the check routines spell + out in more detail the assumptions and invariants underlying the + algorithms. The checking is fairly extensive, and will slow down + execution noticeably. Calling malloc_stats or mallinfo with DEBUG + set will attempt to check every non-mmapped allocated and free chunk + in the course of computing the summaries. + +ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) + Debugging assertion failures can be nearly impossible if your + version of the assert macro causes malloc to be called, which will + lead to a cascade of further failures, blowing the runtime stack. + ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), + which will usually make debugging easier. + +MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 + The action to take before "return 0" when malloc fails to be able to + return memory because there is none available. + +HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES + True if this system supports sbrk or an emulation of it. + +MORECORE default: sbrk + The name of the sbrk-style system routine to call to obtain more + memory. See below for guidance on writing custom MORECORE + functions. The type of the argument to sbrk/MORECORE varies across + systems. It cannot be size_t, because it supports negative + arguments, so it is normally the signed type of the same width as + size_t (sometimes declared as "intptr_t"). It doesn't much matter + though. Internally, we only call it with arguments less than half + the max value of a size_t, which should work across all reasonable + possibilities, although sometimes generating compiler warnings. See + near the end of this file for guidelines for creating a custom + version of MORECORE. + +MORECORE_CONTIGUOUS default: 1 (true) + If true, take advantage of fact that consecutive calls to MORECORE + with positive arguments always return contiguous increasing + addresses. This is true of unix sbrk. It does not hurt too much to + set it true anyway, since malloc copes with non-contiguities. + Setting it false when definitely non-contiguous saves time + and possibly wasted space it would take to discover this though. + +MORECORE_CANNOT_TRIM default: NOT defined + True if MORECORE cannot release space back to the system when given + negative arguments. This is generally necessary only if you are + using a hand-crafted MORECORE function that cannot handle negative + arguments. + +HAVE_MMAP default: 1 (true) + True if this system supports mmap or an emulation of it. If so, and + HAVE_MORECORE is not true, MMAP is used for all system + allocation. If set and HAVE_MORECORE is true as well, MMAP is + primarily used to directly allocate very large blocks. It is also + used as a backup strategy in cases where MORECORE fails to provide + space from system. Note: A single call to MUNMAP is assumed to be + able to unmap memory that may have be allocated using multiple calls + to MMAP, so long as they are adjacent. + +HAVE_MREMAP default: 1 on linux, else 0 + If true realloc() uses mremap() to re-allocate large blocks and + extend or shrink allocation spaces. + +MMAP_CLEARS default: 1 on unix + True if mmap clears memory so calloc doesn't need to. This is true + for standard unix mmap using /dev/zero. + +USE_BUILTIN_FFS default: 0 (i.e., not used) + Causes malloc to use the builtin ffs() function to compute indices. + Some compilers may recognize and intrinsify ffs to be faster than the + supplied C version. Also, the case of x86 using gcc is special-cased + to an asm instruction, so is already as fast as it can be, and so + this setting has no effect. (On most x86s, the asm version is only + slightly faster than the C version.) + +malloc_getpagesize default: derive from system includes, or 4096. + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. This may be (and + usually is) a function rather than a constant. This is ignored + if WIN32, where page size is determined using getSystemInfo during + initialization. + +USE_DEV_RANDOM default: 0 (i.e., not used) + Causes malloc to use /dev/random to initialize secure magic seed for + stamping footers. Otherwise, the current time is used. + +NO_MALLINFO default: 0 + If defined, don't compile "mallinfo". This can be a simple way + of dealing with mismatches between system declarations and + those in this file. + +MALLINFO_FIELD_TYPE default: size_t + The type of the fields in the mallinfo struct. This was originally + defined as "int" in SVID etc, but is more usefully defined as + size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set + +REALLOC_ZERO_BYTES_FREES default: not defined + This should be set if a call to realloc with zero bytes should + be the same as a call to free. Some people think it should. Otherwise, + since this malloc returns a unique pointer for malloc(0), so does + realloc(p, 0). + +LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H +LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H +LACKS_STDLIB_H default: NOT defined unless on WIN32 + Define these if your system does not have these header files. + You might need to manually insert some of the declarations they provide. + +DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, + system_info.dwAllocationGranularity in WIN32, + otherwise 64K. + Also settable using mallopt(M_GRANULARITY, x) + The unit for allocating and deallocating memory from the system. On + most systems with contiguous MORECORE, there is no reason to + make this more than a page. However, systems with MMAP tend to + either require or encourage larger granularities. You can increase + this value to prevent system allocation functions to be called so + often, especially if they are slow. The value must be at least one + page and must be a power of two. Setting to 0 causes initialization + to either page size or win32 region size. (Note: In previous + versions of malloc, the equivalent of this option was called + "TOP_PAD") + +DEFAULT_TRIM_THRESHOLD default: 2MB + Also settable using mallopt(M_TRIM_THRESHOLD, x) + The maximum amount of unused top-most memory to keep before + releasing via malloc_trim in free(). Automatic trimming is mainly + useful in long-lived programs using contiguous MORECORE. Because + trimming via sbrk can be slow on some systems, and can sometimes be + wasteful (in cases where programs immediately afterward allocate + more large chunks) the value should be high enough so that your + overall system performance would improve by releasing this much + memory. As a rough guide, you might set to a value close to the + average size of a process (program) running on your system. + Releasing this much memory would allow such a process to run in + memory. Generally, it is worth tuning trim thresholds when a + program undergoes phases where several large chunks are allocated + and released in ways that can reuse each other's storage, perhaps + mixed with phases where there are no such chunks at all. The trim + value must be greater than page size to have any useful effect. To + disable trimming completely, you can set to MAX_SIZE_T. Note that the trick + some people use of mallocing a huge space and then freeing it at + program startup, in an attempt to reserve system memory, doesn't + have the intended effect under automatic trimming, since that memory + will immediately be returned to the system. + +DEFAULT_MMAP_THRESHOLD default: 256K + Also settable using mallopt(M_MMAP_THRESHOLD, x) + The request size threshold for using MMAP to directly service a + request. Requests of at least this size that cannot be allocated + using already-existing space will be serviced via mmap. (If enough + normal freed space already exists it is used instead.) Using mmap + segregates relatively large chunks of memory so that they can be + individually obtained and released from the host system. A request + serviced through mmap is never reused by any other request (at least + not directly; the system may just so happen to remap successive + requests to the same locations). Segregating space in this way has + the benefits that: Mmapped space can always be individually released + back to the system, which helps keep the system level memory demands + of a long-lived program low. Also, mapped memory doesn't become + `locked' between other chunks, as can happen with normally allocated + chunks, which means that even trimming via malloc_trim would not + release them. However, it has the disadvantage that the space + cannot be reclaimed, consolidated, and then used to service later + requests, as happens with normal chunks. The advantages of mmap + nearly always outweigh disadvantages for "large" chunks, but the + value of "large" may vary across systems. The default is an + empirically derived value that works well in most systems. You can + disable mmap by setting to MAX_SIZE_T. + +*/ + +#ifndef WIN32 +#ifdef _WIN32 +#define WIN32 1 +#endif /* _WIN32 */ +#endif /* WIN32 */ +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#define HAVE_MMAP 1 +#define HAVE_MORECORE 0 +#define LACKS_UNISTD_H +#define LACKS_SYS_PARAM_H +#define LACKS_SYS_MMAN_H +#define LACKS_STRING_H +#define LACKS_STRINGS_H +#define LACKS_SYS_TYPES_H +#define LACKS_ERRNO_H +#define LACKS_FCNTL_H +#define MALLOC_FAILURE_ACTION +#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */ +#endif /* WIN32 */ + +#if defined(DARWIN) || defined(_DARWIN) +/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ +#ifndef HAVE_MORECORE +#define HAVE_MORECORE 0 +#define HAVE_MMAP 1 +#endif /* HAVE_MORECORE */ +#endif /* DARWIN */ + +#ifndef LACKS_SYS_TYPES_H +#include <sys/types.h> /* For size_t */ +#endif /* LACKS_SYS_TYPES_H */ + +/* The maximum possible size_t value has all bits set */ +#define MAX_SIZE_T (~(size_t)0) + +#ifndef ONLY_MSPACES +#define ONLY_MSPACES 0 +#endif /* ONLY_MSPACES */ +#ifndef MSPACES +#if ONLY_MSPACES +#define MSPACES 1 +#else /* ONLY_MSPACES */ +#define MSPACES 0 +#endif /* ONLY_MSPACES */ +#endif /* MSPACES */ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT ((size_t)8U) +#endif /* MALLOC_ALIGNMENT */ +#ifndef FOOTERS +#define FOOTERS 0 +#endif /* FOOTERS */ +#ifndef ABORT +#define ABORT abort() +#endif /* ABORT */ +#ifndef ABORT_ON_ASSERT_FAILURE +#define ABORT_ON_ASSERT_FAILURE 1 +#endif /* ABORT_ON_ASSERT_FAILURE */ +#ifndef PROCEED_ON_ERROR +#define PROCEED_ON_ERROR 0 +#endif /* PROCEED_ON_ERROR */ +#ifndef USE_LOCKS +#define USE_LOCKS 0 +#endif /* USE_LOCKS */ +#ifndef INSECURE +#define INSECURE 0 +#endif /* INSECURE */ +#ifndef HAVE_MMAP +#define HAVE_MMAP 1 +#endif /* HAVE_MMAP */ +#ifndef MMAP_CLEARS +#define MMAP_CLEARS 1 +#endif /* MMAP_CLEARS */ +#ifndef HAVE_MREMAP +#ifdef linux +#define HAVE_MREMAP 1 +#else /* linux */ +#define HAVE_MREMAP 0 +#endif /* linux */ +#endif /* HAVE_MREMAP */ +#ifndef MALLOC_FAILURE_ACTION +#define MALLOC_FAILURE_ACTION errno = ENOMEM; +#endif /* MALLOC_FAILURE_ACTION */ +#ifndef HAVE_MORECORE +#if ONLY_MSPACES +#define HAVE_MORECORE 0 +#else /* ONLY_MSPACES */ +#define HAVE_MORECORE 1 +#endif /* ONLY_MSPACES */ +#endif /* HAVE_MORECORE */ +#if !HAVE_MORECORE +#define MORECORE_CONTIGUOUS 0 +#else /* !HAVE_MORECORE */ +#ifndef MORECORE +#define MORECORE sbrk +#endif /* MORECORE */ +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif /* MORECORE_CONTIGUOUS */ +#endif /* HAVE_MORECORE */ +#ifndef DEFAULT_GRANULARITY +#if MORECORE_CONTIGUOUS +#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ +#else /* MORECORE_CONTIGUOUS */ +#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) +#endif /* MORECORE_CONTIGUOUS */ +#endif /* DEFAULT_GRANULARITY */ +#ifndef DEFAULT_TRIM_THRESHOLD +#ifndef MORECORE_CANNOT_TRIM +#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) +#else /* MORECORE_CANNOT_TRIM */ +#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T +#endif /* MORECORE_CANNOT_TRIM */ +#endif /* DEFAULT_TRIM_THRESHOLD */ +#ifndef DEFAULT_MMAP_THRESHOLD +#if HAVE_MMAP +#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) +#else /* HAVE_MMAP */ +#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T +#endif /* HAVE_MMAP */ +#endif /* DEFAULT_MMAP_THRESHOLD */ +#ifndef USE_BUILTIN_FFS +#define USE_BUILTIN_FFS 0 +#endif /* USE_BUILTIN_FFS */ +#ifndef USE_DEV_RANDOM +#define USE_DEV_RANDOM 0 +#endif /* USE_DEV_RANDOM */ +#ifndef NO_MALLINFO +#define NO_MALLINFO 0 +#endif /* NO_MALLINFO */ +#ifndef MALLINFO_FIELD_TYPE +#define MALLINFO_FIELD_TYPE size_t +#endif /* MALLINFO_FIELD_TYPE */ + +#define memset SDL_memset +#define memcpy SDL_memcpy +#define malloc SDL_malloc +#define calloc SDL_calloc +#define realloc SDL_realloc +#define free SDL_free + +/* + mallopt tuning options. SVID/XPG defines four standard parameter + numbers for mallopt, normally defined in malloc.h. None of these + are used in this malloc, so setting them has no effect. But this + malloc does support the following options. +*/ + +#define M_TRIM_THRESHOLD (-1) +#define M_GRANULARITY (-2) +#define M_MMAP_THRESHOLD (-3) + +/* ------------------------ Mallinfo declarations ------------------------ */ + +#if !NO_MALLINFO +/* + This version of malloc supports the standard SVID/XPG mallinfo + routine that returns a struct containing usage properties and + statistics. It should work on any system that has a + /usr/include/malloc.h defining struct mallinfo. The main + declaration needed is the mallinfo struct that is returned (by-copy) + by mallinfo(). The malloinfo struct contains a bunch of fields that + are not even meaningful in this version of malloc. These fields are + are instead filled by mallinfo() with other numbers that might be of + interest. + + HAVE_USR_INCLUDE_MALLOC_H should be set if you have a + /usr/include/malloc.h file that includes a declaration of struct + mallinfo. If so, it is included; else a compliant version is + declared below. These must be precisely the same for mallinfo() to + work. The original SVID version of this struct, defined on most + systems with mallinfo, declares all fields as ints. But some others + define as unsigned long. If your system defines the fields using a + type of different width than listed here, you MUST #include your + system version and #define HAVE_USR_INCLUDE_MALLOC_H. +*/ + +/* #define HAVE_USR_INCLUDE_MALLOC_H */ + +#ifdef HAVE_USR_INCLUDE_MALLOC_H +#include "/usr/include/malloc.h" +#else /* HAVE_USR_INCLUDE_MALLOC_H */ + +struct mallinfo { + MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ + MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ + MALLINFO_FIELD_TYPE smblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblks; /* always 0 */ + MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ + MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ + MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ + MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ + MALLINFO_FIELD_TYPE fordblks; /* total free space */ + MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ +}; + +#endif /* HAVE_USR_INCLUDE_MALLOC_H */ +#endif /* NO_MALLINFO */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if !ONLY_MSPACES + +/* ------------------- Declarations of public routines ------------------- */ + +#ifndef USE_DL_PREFIX +#define dlcalloc calloc +#define dlfree free +#define dlmalloc malloc +#define dlmemalign memalign +#define dlrealloc realloc +#define dlvalloc valloc +#define dlpvalloc pvalloc +#define dlmallinfo mallinfo +#define dlmallopt mallopt +#define dlmalloc_trim malloc_trim +#define dlmalloc_stats malloc_stats +#define dlmalloc_usable_size malloc_usable_size +#define dlmalloc_footprint malloc_footprint +#define dlmalloc_max_footprint malloc_max_footprint +#define dlindependent_calloc independent_calloc +#define dlindependent_comalloc independent_comalloc +#endif /* USE_DL_PREFIX */ + + +/* + malloc(size_t n) + Returns a pointer to a newly allocated chunk of at least n bytes, or + null if no space is available, in which case errno is set to ENOMEM + on ANSI C systems. + + If n is zero, malloc returns a minimum-sized chunk. (The minimum + size is 16 bytes on most 32bit systems, and 32 bytes on 64bit + systems.) Note that size_t is an unsigned type, so calls with + arguments that would be negative if signed are interpreted as + requests for huge amounts of space, which will often fail. The + maximum supported value of n differs across systems, but is in all + cases less than the maximum representable value of a size_t. +*/ +void* dlmalloc(size_t); + +/* + free(void* p) + Releases the chunk of memory pointed to by p, that had been previously + allocated using malloc or a related routine such as realloc. + It has no effect if p is null. If p was not malloced or already + freed, free(p) will by default cause the current program to abort. +*/ +void dlfree(void*); + +/* + calloc(size_t n_elements, size_t element_size); + Returns a pointer to n_elements * element_size bytes, with all locations + set to zero. +*/ +void* dlcalloc(size_t, size_t); + +/* + realloc(void* p, size_t n) + Returns a pointer to a chunk of size n that contains the same data + as does chunk p up to the minimum of (n, p's size) bytes, or null + if no space is available. + + The returned pointer may or may not be the same as p. The algorithm + prefers extending p in most cases when possible, otherwise it + employs the equivalent of a malloc-copy-free sequence. + + If p is null, realloc is equivalent to malloc. + + If space is not available, realloc returns null, errno is set (if on + ANSI) and p is NOT freed. + + if n is for fewer bytes than already held by p, the newly unused + space is lopped off and freed if possible. realloc with a size + argument of zero (re)allocates a minimum-sized chunk. + + The old unix realloc convention of allowing the last-free'd chunk + to be used as an argument to realloc is not supported. +*/ + +void* dlrealloc(void*, size_t); + +/* + memalign(size_t alignment, size_t n); + Returns a pointer to a newly allocated chunk of n bytes, aligned + in accord with the alignment argument. + + The alignment argument should be a power of two. If the argument is + not a power of two, the nearest greater power is used. + 8-byte alignment is guaranteed by normal malloc calls, so don't + bother calling memalign with an argument of 8 or less. + + Overreliance on memalign is a sure way to fragment space. +*/ +void* dlmemalign(size_t, size_t); + +/* + valloc(size_t n); + Equivalent to memalign(pagesize, n), where pagesize is the page + size of the system. If the pagesize is unknown, 4096 is used. +*/ +void* dlvalloc(size_t); + +/* + mallopt(int parameter_number, int parameter_value) + Sets tunable parameters The format is to provide a + (parameter-number, parameter-value) pair. mallopt then sets the + corresponding parameter to the argument value if it can (i.e., so + long as the value is meaningful), and returns 1 if successful else + 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, + normally defined in malloc.h. None of these are use in this malloc, + so setting them has no effect. But this malloc also supports other + options in mallopt. See below for details. Briefly, supported + parameters are as follows (listed defaults are for "typical" + configurations). + + Symbol param # default allowed param values + M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables) + M_GRANULARITY -2 page size any power of 2 >= page size + M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) +*/ +int dlmallopt(int, int); + +/* + malloc_footprint(); + Returns the number of bytes obtained from the system. The total + number of bytes allocated by malloc, realloc etc., is less than this + value. Unlike mallinfo, this function returns only a precomputed + result, so can be called frequently to monitor memory consumption. + Even if locks are otherwise defined, this function does not use them, + so results might not be up to date. +*/ +size_t dlmalloc_footprint(void); + +/* + malloc_max_footprint(); + Returns the maximum number of bytes obtained from the system. This + value will be greater than current footprint if deallocated space + has been reclaimed by the system. The peak number of bytes allocated + by malloc, realloc etc., is less than this value. Unlike mallinfo, + this function returns only a precomputed result, so can be called + frequently to monitor memory consumption. Even if locks are + otherwise defined, this function does not use them, so results might + not be up to date. +*/ +size_t dlmalloc_max_footprint(void); + +#if !NO_MALLINFO +/* + mallinfo() + Returns (by copy) a struct containing various summary statistics: + + arena: current total non-mmapped bytes allocated from system + ordblks: the number of free chunks + smblks: always zero. + hblks: current number of mmapped regions + hblkhd: total bytes held in mmapped regions + usmblks: the maximum total allocated space. This will be greater + than current total if trimming has occurred. + fsmblks: always zero + uordblks: current total allocated space (normal or mmapped) + fordblks: total free space + keepcost: the maximum number of bytes that could ideally be released + back to system via malloc_trim. ("ideally" means that + it ignores page restrictions etc.) + + Because these fields are ints, but internal bookkeeping may + be kept as longs, the reported values may wrap around zero and + thus be inaccurate. +*/ +struct mallinfo dlmallinfo(void); +#endif /* NO_MALLINFO */ + +/* + independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); + + independent_calloc is similar to calloc, but instead of returning a + single cleared space, it returns an array of pointers to n_elements + independent elements that can hold contents of size elem_size, each + of which starts out cleared, and can be independently freed, + realloc'ed etc. The elements are guaranteed to be adjacently + allocated (this is not guaranteed to occur with multiple callocs or + mallocs), which may also improve cache locality in some + applications. + + The "chunks" argument is optional (i.e., may be null, which is + probably the most typical usage). If it is null, the returned array + is itself dynamically allocated and should also be freed when it is + no longer needed. Otherwise, the chunks array must be of at least + n_elements in length. It is filled in with the pointers to the + chunks. + + In either case, independent_calloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and "chunks" + is null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be individually freed when it is no longer + needed. If you'd like to instead be able to free all at once, you + should instead use regular calloc and assign pointers into this + space to represent elements. (In this case though, you cannot + independently free elements.) + + independent_calloc simplifies and speeds up implementations of many + kinds of pools. It may also be useful when constructing large data + structures that initially have a fixed number of fixed-sized nodes, + but the number is not known at compile time, and some of the nodes + may later need to be freed. For example: + + struct Node { int item; struct Node* next; }; + + struct Node* build_list() { + struct Node** pool; + int n = read_number_of_nodes_needed(); + if (n <= 0) return 0; + pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); + if (pool == 0) die(); + // organize into a linked list... + struct Node* first = pool[0]; + for (i = 0; i < n-1; ++i) + pool[i]->next = pool[i+1]; + free(pool); // Can now free the array (or not, if it is needed later) + return first; + } +*/ +void** dlindependent_calloc(size_t, size_t, void**); + +/* + independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); + + independent_comalloc allocates, all at once, a set of n_elements + chunks with sizes indicated in the "sizes" array. It returns + an array of pointers to these elements, each of which can be + independently freed, realloc'ed etc. The elements are guaranteed to + be adjacently allocated (this is not guaranteed to occur with + multiple callocs or mallocs), which may also improve cache locality + in some applications. + + The "chunks" argument is optional (i.e., may be null). If it is null + the returned array is itself dynamically allocated and should also + be freed when it is no longer needed. Otherwise, the chunks array + must be of at least n_elements in length. It is filled in with the + pointers to the chunks. + + In either case, independent_comalloc returns this pointer array, or + null if the allocation failed. If n_elements is zero and chunks is + null, it returns a chunk representing an array with zero elements + (which should be freed if not wanted). + + Each element must be individually freed when it is no longer + needed. If you'd like to instead be able to free all at once, you + should instead use a single regular malloc, and assign pointers at + particular offsets in the aggregate space. (In this case though, you + cannot independently free elements.) + + independent_comallac differs from independent_calloc in that each + element may have a different size, and also that it does not + automatically clear elements. + + independent_comalloc can be used to speed up allocation in cases + where several structs or objects must always be allocated at the + same time. For example: + + struct Head { ... } + struct Foot { ... } + + void send_message(char* msg) { + int msglen = strlen(msg); + size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; + void* chunks[3]; + if (independent_comalloc(3, sizes, chunks) == 0) + die(); + struct Head* head = (struct Head*)(chunks[0]); + char* body = (char*)(chunks[1]); + struct Foot* foot = (struct Foot*)(chunks[2]); + // ... + } + + In general though, independent_comalloc is worth using only for + larger values of n_elements. For small values, you probably won't + detect enough difference from series of malloc calls to bother. + + Overuse of independent_comalloc can increase overall memory usage, + since it cannot reuse existing noncontiguous small chunks that + might be available for some of the elements. +*/ +void** dlindependent_comalloc(size_t, size_t*, void**); + + +/* + pvalloc(size_t n); + Equivalent to valloc(minimum-page-that-holds(n)), that is, + round up n to nearest pagesize. + */ +void* dlpvalloc(size_t); + +/* + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative arguments + to sbrk) if there is unused memory at the `high' end of the malloc + pool or in unused MMAP segments. You can call this after freeing + large blocks of memory to potentially reduce the system-level memory + requirements of a program. However, it cannot guarantee to reduce + memory. Under some allocation patterns, some large free blocks of + memory will be locked between two used chunks, so they cannot be + given back to the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, only + the minimum amount of memory to maintain internal data structures + will be left. Non-zero arguments can be supplied to maintain enough + trailing space to service future expected allocations without having + to re-obtain memory from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. +*/ +int dlmalloc_trim(size_t); + +/* + malloc_usable_size(void* p); + + Returns the number of bytes you can actually use in + an allocated chunk, which may be more than you requested (although + often not) due to alignment and minimum size constraints. + You can use this many bytes without worrying about + overwriting other allocated objects. This is not a particularly great + programming practice. malloc_usable_size can be more useful in + debugging and assertions, for example: + + p = malloc(n); + assert(malloc_usable_size(p) >= 256); +*/ +size_t dlmalloc_usable_size(void*); + +/* + malloc_stats(); + Prints on stderr the amount of space obtained from the system (both + via sbrk and mmap), the maximum amount (which may be more than + current if malloc_trim and/or munmap got called), and the current + number of bytes allocated via malloc (or realloc, etc) but not yet + freed. Note that this is the number of bytes allocated, not the + number requested. It will be larger than the number requested + because of alignment and bookkeeping overhead. Because it includes + alignment wastage as being in use, this figure may be greater than + zero even when no user-level chunks are allocated. + + The reported current and maximum system memory can be inaccurate if + a program makes other calls to system memory allocation functions + (normally sbrk) outside of malloc. + + malloc_stats prints only the most commonly interesting statistics. + More information can be obtained by calling mallinfo. +*/ +void dlmalloc_stats(void); + +#endif /* ONLY_MSPACES */ + +#if MSPACES + +/* + mspace is an opaque type representing an independent + region of space that supports mspace_malloc, etc. +*/ +typedef void* mspace; + +/* + create_mspace creates and returns a new independent space with the + given initial capacity, or, if 0, the default granularity size. It + returns null if there is no system memory available to create the + space. If argument locked is non-zero, the space uses a separate + lock to control access. The capacity of the space will grow + dynamically as needed to service mspace_malloc requests. You can + control the sizes of incremental increases of this space by + compiling with a different DEFAULT_GRANULARITY or dynamically + setting with mallopt(M_GRANULARITY, value). +*/ +mspace create_mspace(size_t capacity, int locked); + +/* + destroy_mspace destroys the given space, and attempts to return all + of its memory back to the system, returning the total number of + bytes freed. After destruction, the results of access to all memory + used by the space become undefined. +*/ +size_t destroy_mspace(mspace msp); + +/* + create_mspace_with_base uses the memory supplied as the initial base + of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this + space is used for bookkeeping, so the capacity must be at least this + large. (Otherwise 0 is returned.) When this initial space is + exhausted, additional memory will be obtained from the system. + Destroying this space will deallocate all additionally allocated + space (if possible) but not the initial base. +*/ +mspace create_mspace_with_base(void* base, size_t capacity, int locked); + +/* + mspace_malloc behaves as malloc, but operates within + the given space. +*/ +void* mspace_malloc(mspace msp, size_t bytes); + +/* + mspace_free behaves as free, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_free is not actually needed. + free may be called instead of mspace_free because freed chunks from + any space are handled by their originating spaces. +*/ +void mspace_free(mspace msp, void* mem); + +/* + mspace_realloc behaves as realloc, but operates within + the given space. + + If compiled with FOOTERS==1, mspace_realloc is not actually + needed. realloc may be called instead of mspace_realloc because + realloced chunks from any space are handled by their originating + spaces. +*/ +void* mspace_realloc(mspace msp, void* mem, size_t newsize); + +/* + mspace_calloc behaves as calloc, but operates within + the given space. +*/ +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); + +/* + mspace_memalign behaves as memalign, but operates within + the given space. +*/ +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); + +/* + mspace_independent_calloc behaves as independent_calloc, but + operates within the given space. +*/ +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]); + +/* + mspace_independent_comalloc behaves as independent_comalloc, but + operates within the given space. +*/ +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]); + +/* + mspace_footprint() returns the number of bytes obtained from the + system for this space. +*/ +size_t mspace_footprint(mspace msp); + +/* + mspace_max_footprint() returns the peak number of bytes obtained from the + system for this space. +*/ +size_t mspace_max_footprint(mspace msp); + + +#if !NO_MALLINFO +/* + mspace_mallinfo behaves as mallinfo, but reports properties of + the given space. +*/ +struct mallinfo mspace_mallinfo(mspace msp); +#endif /* NO_MALLINFO */ + +/* + mspace_malloc_stats behaves as malloc_stats, but reports + properties of the given space. +*/ +void mspace_malloc_stats(mspace msp); + +/* + mspace_trim behaves as malloc_trim, but + operates within the given space. +*/ +int mspace_trim(mspace msp, size_t pad); + +/* + An alias for mallopt. +*/ +int mspace_mallopt(int, int); + +#endif /* MSPACES */ + +#ifdef __cplusplus +}; /* end of extern "C" */ +#endif /* __cplusplus */ + +/* + ======================================================================== + To make a fully customizable malloc.h header file, cut everything + above this line, put into file malloc.h, edit to suit, and #include it + on the next line, as well as in programs that use this malloc. + ======================================================================== +*/ + +/* #include "malloc.h" */ + +/*------------------------------ internal #includes ---------------------- */ + +#ifdef _MSC_VER +#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ +#endif /* _MSC_VER */ + +#ifndef LACKS_STDIO_H +#include <stdio.h> /* for printing in malloc_stats */ +#endif + +#ifndef LACKS_ERRNO_H +#include <errno.h> /* for MALLOC_FAILURE_ACTION */ +#endif /* LACKS_ERRNO_H */ +#if FOOTERS +#include <time.h> /* for magic initialization */ +#endif /* FOOTERS */ +#ifndef LACKS_STDLIB_H +#include <stdlib.h> /* for abort() */ +#endif /* LACKS_STDLIB_H */ +#ifdef DEBUG +#if ABORT_ON_ASSERT_FAILURE +#define assert(x) if(!(x)) ABORT +#else /* ABORT_ON_ASSERT_FAILURE */ +#include <assert.h> +#endif /* ABORT_ON_ASSERT_FAILURE */ +#else /* DEBUG */ +#define assert(x) +#endif /* DEBUG */ +#ifndef LACKS_STRING_H +#include <string.h> /* for memset etc */ +#endif /* LACKS_STRING_H */ +#if USE_BUILTIN_FFS +#ifndef LACKS_STRINGS_H +#include <strings.h> /* for ffs */ +#endif /* LACKS_STRINGS_H */ +#endif /* USE_BUILTIN_FFS */ +#if HAVE_MMAP +#ifndef LACKS_SYS_MMAN_H +#include <sys/mman.h> /* for mmap */ +#endif /* LACKS_SYS_MMAN_H */ +#ifndef LACKS_FCNTL_H +#include <fcntl.h> +#endif /* LACKS_FCNTL_H */ +#endif /* HAVE_MMAP */ +#if HAVE_MORECORE +#ifndef LACKS_UNISTD_H +#include <unistd.h> /* for sbrk */ +#else /* LACKS_UNISTD_H */ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +extern void* sbrk(ptrdiff_t); +#endif /* FreeBSD etc */ +#endif /* LACKS_UNISTD_H */ +#endif /* HAVE_MMAP */ + +#ifndef WIN32 +#ifndef malloc_getpagesize +# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ +# ifndef _SC_PAGE_SIZE +# define _SC_PAGE_SIZE _SC_PAGESIZE +# endif +# endif +# ifdef _SC_PAGE_SIZE +# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) +# else +# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) + extern size_t getpagesize(); +# define malloc_getpagesize getpagesize() +# else +# ifdef WIN32 /* use supplied emulation of getpagesize */ +# define malloc_getpagesize getpagesize() +# else +# ifndef LACKS_SYS_PARAM_H +# include <sys/param.h> +# endif +# ifdef EXEC_PAGESIZE +# define malloc_getpagesize EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define malloc_getpagesize NBPG +# else +# define malloc_getpagesize (NBPG * CLSIZE) +# endif +# else +# ifdef NBPC +# define malloc_getpagesize NBPC +# else +# ifdef PAGESIZE +# define malloc_getpagesize PAGESIZE +# else /* just guess */ +# define malloc_getpagesize ((size_t)4096U) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif +#endif + +/* ------------------- size_t and alignment properties -------------------- */ + +/* The byte and bit size of a size_t */ +#define SIZE_T_SIZE (sizeof(size_t)) +#define SIZE_T_BITSIZE (sizeof(size_t) << 3) + +/* Some constants coerced to size_t */ +/* Annoying but necessary to avoid errors on some plaftorms */ +#define SIZE_T_ZERO ((size_t)0) +#define SIZE_T_ONE ((size_t)1) +#define SIZE_T_TWO ((size_t)2) +#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) +#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) +#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) +#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) + +/* The bit mask value corresponding to MALLOC_ALIGNMENT */ +#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) + +/* True if address a has acceptable alignment */ +#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) + +/* the number of bytes to offset an address to align it */ +#define align_offset(A)\ + ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ + ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) + +/* -------------------------- MMAP preliminaries ------------------------- */ + +/* + If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and + checks to fail so compiler optimizer can delete code rather than + using so many "#if"s. +*/ + + +/* MORECORE and MMAP must return MFAIL on failure */ +#define MFAIL ((void*)(MAX_SIZE_T)) +#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ + +#if !HAVE_MMAP +#define IS_MMAPPED_BIT (SIZE_T_ZERO) +#define USE_MMAP_BIT (SIZE_T_ZERO) +#define CALL_MMAP(s) MFAIL +#define CALL_MUNMAP(a, s) (-1) +#define DIRECT_MMAP(s) MFAIL + +#else /* HAVE_MMAP */ +#define IS_MMAPPED_BIT (SIZE_T_ONE) +#define USE_MMAP_BIT (SIZE_T_ONE) + +#ifndef WIN32 +#define CALL_MUNMAP(a, s) munmap((a), (s)) +#define MMAP_PROT (PROT_READ|PROT_WRITE) +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANON */ +#ifdef MAP_ANONYMOUS +#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) +#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) +#else /* MAP_ANONYMOUS */ +/* + Nearly all versions of mmap support MAP_ANONYMOUS, so the following + is unlikely to be needed, but is supplied just in case. +*/ +#define MMAP_FLAGS (MAP_PRIVATE) +static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ +#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \ + (dev_zero_fd = open("/dev/zero", O_RDWR), \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ + mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) +#endif /* MAP_ANONYMOUS */ + +#define DIRECT_MMAP(s) CALL_MMAP(s) +#else /* WIN32 */ + +/* Win32 MMAP via VirtualAlloc */ +static void* win32mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ +static void* win32direct_mmap(size_t size) { + void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, + PAGE_READWRITE); + return (ptr != 0)? ptr: MFAIL; +} + +/* This function supports releasing coalesed segments */ +static int win32munmap(void* ptr, size_t size) { + MEMORY_BASIC_INFORMATION minfo; + char* cptr = ptr; + while (size) { + if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) + return -1; + if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || + minfo.State != MEM_COMMIT || minfo.RegionSize > size) + return -1; + if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) + return -1; + cptr += minfo.RegionSize; + size -= minfo.RegionSize; + } + return 0; +} + +#define CALL_MMAP(s) win32mmap(s) +#define CALL_MUNMAP(a, s) win32munmap((a), (s)) +#define DIRECT_MMAP(s) win32direct_mmap(s) +#endif /* WIN32 */ +#endif /* HAVE_MMAP */ + +#if HAVE_MMAP && HAVE_MREMAP +#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) +#else /* HAVE_MMAP && HAVE_MREMAP */ +#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL +#endif /* HAVE_MMAP && HAVE_MREMAP */ + +#if HAVE_MORECORE +#define CALL_MORECORE(S) MORECORE(S) +#else /* HAVE_MORECORE */ +#define CALL_MORECORE(S) MFAIL +#endif /* HAVE_MORECORE */ + +/* mstate bit set if continguous morecore disabled or failed */ +#define USE_NONCONTIGUOUS_BIT (4U) + +/* segment bit set in create_mspace_with_base */ +#define EXTERN_BIT (8U) + + +/* --------------------------- Lock preliminaries ------------------------ */ + +#if USE_LOCKS + +/* + When locks are defined, there are up to two global locks: + + * If HAVE_MORECORE, morecore_mutex protects sequences of calls to + MORECORE. In many cases sys_alloc requires two calls, that should + not be interleaved with calls by other threads. This does not + protect against direct calls to MORECORE by other threads not + using this lock, so there is still code to cope the best we can on + interference. + + * magic_init_mutex ensures that mparams.magic and other + unique mparams values are initialized only once. +*/ + +#ifndef WIN32 +/* By default use posix locks */ +#include <pthread.h> +#define MLOCK_T pthread_mutex_t +#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL) +#define ACQUIRE_LOCK(l) pthread_mutex_lock(l) +#define RELEASE_LOCK(l) pthread_mutex_unlock(l) + +#if HAVE_MORECORE +static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif /* HAVE_MORECORE */ + +static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER; + +#else /* WIN32 */ +/* + Because lock-protected regions have bounded times, and there + are no recursive lock calls, we can use simple spinlocks. +*/ + +#define MLOCK_T long +static int win32_acquire_lock (MLOCK_T *sl) { + for (;;) { +#ifdef InterlockedCompareExchangePointer + if (!InterlockedCompareExchange(sl, 1, 0)) + return 0; +#else /* Use older void* version */ + if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0)) + return 0; +#endif /* InterlockedCompareExchangePointer */ + Sleep (0); + } +} + +static void win32_release_lock (MLOCK_T *sl) { + InterlockedExchange (sl, 0); +} + +#define INITIAL_LOCK(l) *(l)=0 +#define ACQUIRE_LOCK(l) win32_acquire_lock(l) +#define RELEASE_LOCK(l) win32_release_lock(l) +#if HAVE_MORECORE +static MLOCK_T morecore_mutex; +#endif /* HAVE_MORECORE */ +static MLOCK_T magic_init_mutex; +#endif /* WIN32 */ + +#define USE_LOCK_BIT (2U) +#else /* USE_LOCKS */ +#define USE_LOCK_BIT (0U) +#define INITIAL_LOCK(l) +#endif /* USE_LOCKS */ + +#if USE_LOCKS && HAVE_MORECORE +#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex); +#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex); +#else /* USE_LOCKS && HAVE_MORECORE */ +#define ACQUIRE_MORECORE_LOCK() +#define RELEASE_MORECORE_LOCK() +#endif /* USE_LOCKS && HAVE_MORECORE */ + +#if USE_LOCKS +#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); +#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); +#else /* USE_LOCKS */ +#define ACQUIRE_MAGIC_INIT_LOCK() +#define RELEASE_MAGIC_INIT_LOCK() +#endif /* USE_LOCKS */ + + +/* ----------------------- Chunk representations ------------------------ */ + +/* + (The following includes lightly edited explanations by Colin Plumb.) + + The malloc_chunk declaration below is misleading (but accurate and + necessary). It declares a "view" into memory allowing access to + necessary fields at known offsets from a given base. + + Chunks of memory are maintained using a `boundary tag' method as + originally described by Knuth. (See the paper by Paul Wilson + ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such + techniques.) Sizes of free chunks are stored both in the front of + each chunk and at the end. This makes consolidating fragmented + chunks into bigger chunks fast. The head fields also hold bits + representing whether chunks are free or in use. + + Here are some pictures to make it clearer. They are "exploded" to + show that the state of a chunk can be thought of as extending from + the high 31 bits of the head field of its header through the + prev_foot and PINUSE_BIT bit of the following chunk header. + + A chunk that's in use looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk (if P = 1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 1| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +- -+ + | | + +- -+ + | : + +- size - sizeof(size_t) available payload bytes -+ + : | + chunk-> +- -+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| + | Size of next chunk (may or may not be in use) | +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + And if it's free, it looks like this: + + chunk-> +- -+ + | User payload (must be in use, or we would have merged!) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| + | Size of this chunk 0| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Prev pointer | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- size - sizeof(struct chunk) unused bytes -+ + : | + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| + | Size of next chunk (must be in use, or we would have merged)| +-+ + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | : + +- User payload -+ + : | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0| + +-+ + Note that since we always merge adjacent free chunks, the chunks + adjacent to a free chunk must be in use. + + Given a pointer to a chunk (which can be derived trivially from the + payload pointer) we can, in O(1) time, find out whether the adjacent + chunks are free, and if so, unlink them from the lists that they + are on and merge them with the current chunk. + + Chunks always begin on even word boundaries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + The P (PINUSE_BIT) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, preventing + access to non-existent (or non-owned) memory. If pinuse is set for + any given chunk, then you CANNOT determine the size of the + previous chunk, and might even get a memory addressing fault when + trying to do so. + + The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of + the chunk size redundantly records whether the current chunk is + inuse. This redundancy enables usage checks within free and realloc, + and reduces indirection when freeing and consolidating chunks. + + Each freshly allocated chunk must have both cinuse and pinuse set. + That is, each allocated chunk borders either a previously allocated + and still in-use chunk, or the base of its memory arena. This is + ensured by making all allocations from the the `lowest' part of any + found chunk. Further, no free chunk physically borders another one, + so each free chunk is known to be preceded and followed by either + inuse chunks or the ends of memory. + + Note that the `foot' of the current chunk is actually represented + as the prev_foot of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The exceptions to all this are + + 1. The special chunk `top' is the top-most available chunk (i.e., + the one bordering the end of available memory). It is treated + specially. Top is never included in any bin, is used only if + no other chunk is available, and is released back to the + system if it is very large (see M_TRIM_THRESHOLD). In effect, + the top chunk is treated as larger (and thus less well + fitting) than any other available chunk. The top chunk + doesn't update its trailing size field since there is no next + contiguous chunk that would have to index off it. However, + space is still allocated for it (TOP_FOOT_SIZE) to enable + separation or merging when space is extended. + + 3. Chunks allocated via mmap, which have the lowest-order bit + (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set + PINUSE_BIT in their head fields. Because they are allocated + one-by-one, each must carry its own prev_foot field, which is + also used to hold the offset this chunk has within its mmapped + region, which is needed to preserve alignment. Each mmapped + chunk is trailed by the first two fields of a fake next-chunk + for sake of usage checks. + +*/ + +struct malloc_chunk { + size_t prev_foot; /* Size of previous chunk (if free). */ + size_t head; /* Size and inuse bits. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + +typedef struct malloc_chunk mchunk; +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ +typedef size_t bindex_t; /* Described below */ +typedef unsigned int binmap_t; /* Described below */ +typedef unsigned int flag_t; /* The type of various bit flag sets */ + +/* ------------------- Chunks sizes and alignments ----------------------- */ + +#define MCHUNK_SIZE (sizeof(mchunk)) + +#if FOOTERS +#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +#else /* FOOTERS */ +#define CHUNK_OVERHEAD (SIZE_T_SIZE) +#endif /* FOOTERS */ + +/* MMapped chunks need a second word of overhead ... */ +#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) +/* ... and additional padding for fake next-chunk at foot */ +#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) + +/* The smallest size we can malloc is an aligned minimal chunk */ +#define MIN_CHUNK_SIZE\ + ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) +/* chunk associated with aligned address A */ +#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) + +/* Bounds on request (not chunk) sizes. */ +#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) +#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) + +/* pad request bytes into a usable size */ +#define pad_request(req) \ + (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) + +/* pad request, checking for minimum (but not maximum) */ +#define request2size(req) \ + (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) + + +/* ------------------ Operations on head and foot fields ----------------- */ + +/* + The head field of a chunk is or'ed with PINUSE_BIT when previous + adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in + use. If the chunk was obtained with mmap, the prev_foot field has + IS_MMAPPED_BIT set, otherwise holding the offset of the base of the + mmapped region to the base of the chunk. +*/ + +#define PINUSE_BIT (SIZE_T_ONE) +#define CINUSE_BIT (SIZE_T_TWO) +#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) + +/* Head value for fenceposts */ +#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) + +/* extraction of fields from head words */ +#define cinuse(p) ((p)->head & CINUSE_BIT) +#define pinuse(p) ((p)->head & PINUSE_BIT) +#define chunksize(p) ((p)->head & ~(INUSE_BITS)) + +#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) +#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) + +/* Treat space at ptr +/- offset as a chunk */ +#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) +#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) + +/* Ptr to next or previous physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) + +/* extract next chunk's pinuse bit */ +#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) + +/* Get/set size at footer */ +#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) + +/* Set size, pinuse bit, and foot */ +#define set_size_and_pinuse_of_free_chunk(p, s)\ + ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) + +/* Set size, pinuse bit, foot, and clear next pinuse */ +#define set_free_with_pinuse(p, s, n)\ + (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) + +#define is_mmapped(p)\ + (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT)) + +/* Get the internal overhead associated with chunk p */ +#define overhead_for(p)\ + (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) + +/* Return true if malloced space is not necessarily cleared */ +#if MMAP_CLEARS +#define calloc_must_clear(p) (!is_mmapped(p)) +#else /* MMAP_CLEARS */ +#define calloc_must_clear(p) (1) +#endif /* MMAP_CLEARS */ + +/* ---------------------- Overlaid data structures ----------------------- */ + +/* + When chunks are not in use, they are treated as nodes of either + lists or trees. + + "Small" chunks are stored in circular doubly-linked lists, and look + like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Larger chunks are kept in a form of bitwise digital trees (aka + tries) keyed on chunksizes. Because malloc_tree_chunks are only for + free chunks greater than 256 bytes, their size doesn't impose any + constraints on user chunk sizes. Each node looks like: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk of same size | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to left child (child[0]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to right child (child[1]) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Pointer to parent | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | bin index of this chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + Each tree holding treenodes is a tree of unique chunk sizes. Chunks + of the same size are arranged in a circularly-linked list, with only + the oldest chunk (the next to be used, in our FIFO ordering) + actually in the tree. (Tree members are distinguished by a non-null + parent pointer.) If a chunk with the same size an an existing node + is inserted, it is linked off the existing node using pointers that + work in the same way as fd/bk pointers of small chunks. + + Each tree contains a power of 2 sized range of chunk sizes (the + smallest is 0x100 <= x < 0x180), which is is divided in half at each + tree level, with the chunks in the smaller half of the range (0x100 + <= x < 0x140 for the top nose) in the left subtree and the larger + half (0x140 <= x < 0x180) in the right subtree. This is, of course, + done by inspecting individual bits. + + Using these rules, each node's left subtree contains all smaller + sizes than its right subtree. However, the node at the root of each + subtree has no particular ordering relationship to either. (The + dividing line between the subtree sizes is based on trie relation.) + If we remove the last chunk of a given size from the interior of the + tree, we need to replace it with a leaf node. The tree ordering + rules permit a node to be replaced by any leaf below it. + + The smallest chunk in a tree (a common operation in a best-fit + allocator) can be found by walking a path to the leftmost leaf in + the tree. Unlike a usual binary tree, where we follow left child + pointers until we reach a null, here we follow the right child + pointer any time the left one is null, until we reach a leaf with + both child pointers null. The smallest chunk in the tree will be + somewhere along that path. + + The worst case number of steps to add, find, or remove a node is + bounded by the number of bits differentiating chunks within + bins. Under current bin calculations, this ranges from 6 up to 21 + (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case + is of course much better. +*/ + +struct malloc_tree_chunk { + /* The first four fields must be compatible with malloc_chunk */ + size_t prev_foot; + size_t head; + struct malloc_tree_chunk* fd; + struct malloc_tree_chunk* bk; + + struct malloc_tree_chunk* child[2]; + struct malloc_tree_chunk* parent; + bindex_t index; +}; + +typedef struct malloc_tree_chunk tchunk; +typedef struct malloc_tree_chunk* tchunkptr; +typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ + +/* A little helper macro for trees */ +#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) + +/* ----------------------------- Segments -------------------------------- */ + +/* + Each malloc space may include non-contiguous segments, held in a + list headed by an embedded malloc_segment record representing the + top-most space. Segments also include flags holding properties of + the space. Large chunks that are directly allocated by mmap are not + included in this list. They are instead independently created and + destroyed without otherwise keeping track of them. + + Segment management mainly comes into play for spaces allocated by + MMAP. Any call to MMAP might or might not return memory that is + adjacent to an existing segment. MORECORE normally contiguously + extends the current space, so this space is almost always adjacent, + which is simpler and faster to deal with. (This is why MORECORE is + used preferentially to MMAP when both are available -- see + sys_alloc.) When allocating using MMAP, we don't use any of the + hinting mechanisms (inconsistently) supported in various + implementations of unix mmap, or distinguish reserving from + committing memory. Instead, we just ask for space, and exploit + contiguity when we get it. It is probably possible to do + better than this on some systems, but no general scheme seems + to be significantly better. + + Management entails a simpler variant of the consolidation scheme + used for chunks to reduce fragmentation -- new adjacent memory is + normally prepended or appended to an existing segment. However, + there are limitations compared to chunk consolidation that mostly + reflect the fact that segment processing is relatively infrequent + (occurring only when getting memory from system) and that we + don't expect to have huge numbers of segments: + + * Segments are not indexed, so traversal requires linear scans. (It + would be possible to index these, but is not worth the extra + overhead and complexity for most programs on most platforms.) + * New segments are only appended to old ones when holding top-most + memory; if they cannot be prepended to others, they are held in + different segments. + + Except for the top-most segment of an mstate, each segment record + is kept at the tail of its segment. Segments are added by pushing + segment records onto the list headed by &mstate.seg for the + containing mstate. + + Segment flags control allocation/merge/deallocation policies: + * If EXTERN_BIT set, then we did not allocate this segment, + and so should not try to deallocate or merge with others. + (This currently holds only for the initial segment passed + into create_mspace_with_base.) + * If IS_MMAPPED_BIT set, the segment may be merged with + other surrounding mmapped segments and trimmed/de-allocated + using munmap. + * If neither bit is set, then the segment was obtained using + MORECORE so can be merged with surrounding MORECORE'd segments + and deallocated/trimmed using MORECORE with negative arguments. +*/ + +struct malloc_segment { + char* base; /* base address */ + size_t size; /* allocated size */ + struct malloc_segment* next; /* ptr to next segment */ + flag_t sflags; /* mmap and extern flag */ +}; + +#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT) +#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) + +typedef struct malloc_segment msegment; +typedef struct malloc_segment* msegmentptr; + +/* ---------------------------- malloc_state ----------------------------- */ + +/* + A malloc_state holds all of the bookkeeping for a space. + The main fields are: + + Top + The topmost chunk of the currently active segment. Its size is + cached in topsize. The actual size of topmost space is + topsize+TOP_FOOT_SIZE, which includes space reserved for adding + fenceposts and segment records if necessary when getting more + space from the system. The size at which to autotrim top is + cached from mparams in trim_check, except that it is disabled if + an autotrim fails. + + Designated victim (dv) + This is the preferred chunk for servicing small requests that + don't have exact fits. It is normally the chunk split off most + recently to service another small request. Its size is cached in + dvsize. The link fields of this chunk are not maintained since it + is not kept in a bin. + + SmallBins + An array of bin headers for free chunks. These bins hold chunks + with sizes less than MIN_LARGE_SIZE bytes. Each bin contains + chunks of all the same size, spaced 8 bytes apart. To simplify + use in double-linked lists, each bin header acts as a malloc_chunk + pointing to the real first node, if it exists (else pointing to + itself). This avoids special-casing for headers. But to avoid + waste, we allocate only the fd/bk pointers of bins, and then use + repositioning tricks to treat these as the fields of a chunk. + + TreeBins + Treebins are pointers to the roots of trees holding a range of + sizes. There are 2 equally spaced treebins for each power of two + from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything + larger. + + Bin maps + There is one bit map for small bins ("smallmap") and one for + treebins ("treemap). Each bin sets its bit when non-empty, and + clears the bit when empty. Bit operations are then used to avoid + bin-by-bin searching -- nearly all "search" is done without ever + looking at bins that won't be selected. The bit maps + conservatively use 32 bits per map word, even if on 64bit system. + For a good description of some of the bit-based techniques used + here, see Henry S. Warren Jr's book "Hacker's Delight" (and + supplement at http://hackersdelight.org/). Many of these are + intended to reduce the branchiness of paths through malloc etc, as + well as to reduce the number of memory locations read or written. + + Segments + A list of segments headed by an embedded malloc_segment record + representing the initial space. + + Address check support + The least_addr field is the least address ever obtained from + MORECORE or MMAP. Attempted frees and reallocs of any address less + than this are trapped (unless INSECURE is defined). + + Magic tag + A cross-check field that should always hold same value as mparams.magic. + + Flags + Bits recording whether to use MMAP, locks, or contiguous MORECORE + + Statistics + Each space keeps track of current and maximum system memory + obtained via MORECORE or MMAP. + + Locking + If USE_LOCKS is defined, the "mutex" lock is acquired and released + around every public call using this mspace. +*/ + +/* Bin types, widths and sizes */ +#define NSMALLBINS (32U) +#define NTREEBINS (32U) +#define SMALLBIN_SHIFT (3U) +#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) +#define TREEBIN_SHIFT (8U) +#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) +#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) +#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) + +struct malloc_state { + binmap_t smallmap; + binmap_t treemap; + size_t dvsize; + size_t topsize; + char* least_addr; + mchunkptr dv; + mchunkptr top; + size_t trim_check; + size_t magic; + mchunkptr smallbins[(NSMALLBINS+1)*2]; + tbinptr treebins[NTREEBINS]; + size_t footprint; + size_t max_footprint; + flag_t mflags; +#if USE_LOCKS + MLOCK_T mutex; /* locate lock among fields that rarely change */ +#endif /* USE_LOCKS */ + msegment seg; +}; + +typedef struct malloc_state* mstate; + +/* ------------- Global malloc_state and malloc_params ------------------- */ + +/* + malloc_params holds global properties, including those that can be + dynamically set using mallopt. There is a single instance, mparams, + initialized in init_mparams. +*/ + +struct malloc_params { + size_t magic; + size_t page_size; + size_t granularity; + size_t mmap_threshold; + size_t trim_threshold; + flag_t default_mflags; +}; + +static struct malloc_params mparams; + +/* The global malloc_state used for all non-"mspace" calls */ +static struct malloc_state _gm_; +#define gm (&_gm_) +#define is_global(M) ((M) == &_gm_) +#define is_initialized(M) ((M)->top != 0) + +/* -------------------------- system alloc setup ------------------------- */ + +/* Operations on mflags */ + +#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) +#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) +#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) + +#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) +#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) +#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) + +#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) +#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) + +#define set_lock(M,L)\ + ((M)->mflags = (L)?\ + ((M)->mflags | USE_LOCK_BIT) :\ + ((M)->mflags & ~USE_LOCK_BIT)) + +/* page-align a size */ +#define page_align(S)\ + (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) + +/* granularity-align a size */ +#define granularity_align(S)\ + (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) + +#define is_page_aligned(S)\ + (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) +#define is_granularity_aligned(S)\ + (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) + +/* True if segment S holds address A */ +#define segment_holds(S, A)\ + ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) + +/* Return segment holding given address */ +static msegmentptr segment_holding(mstate m, char* addr) { + msegmentptr sp = &m->seg; + for (;;) { + if (addr >= sp->base && addr < sp->base + sp->size) + return sp; + if ((sp = sp->next) == 0) + return 0; + } +} + +/* Return true if segment contains a segment link */ +static int has_segment_link(mstate m, msegmentptr ss) { + msegmentptr sp = &m->seg; + for (;;) { + if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) + return 1; + if ((sp = sp->next) == 0) + return 0; + } +} + +#ifndef MORECORE_CANNOT_TRIM +#define should_trim(M,s) ((s) > (M)->trim_check) +#else /* MORECORE_CANNOT_TRIM */ +#define should_trim(M,s) (0) +#endif /* MORECORE_CANNOT_TRIM */ + +/* + TOP_FOOT_SIZE is padding at the end of a segment, including space + that may be needed to place segment records and fenceposts when new + noncontiguous segments are added. +*/ +#define TOP_FOOT_SIZE\ + (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) + + +/* ------------------------------- Hooks -------------------------------- */ + +/* + PREACTION should be defined to return 0 on success, and nonzero on + failure. If you are not using locking, you can redefine these to do + anything you like. +*/ + +#if USE_LOCKS + +/* Ensure locks are initialized */ +#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) + +#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) +#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } +#else /* USE_LOCKS */ + +#ifndef PREACTION +#define PREACTION(M) (0) +#endif /* PREACTION */ + +#ifndef POSTACTION +#define POSTACTION(M) +#endif /* POSTACTION */ + +#endif /* USE_LOCKS */ + +/* + CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. + USAGE_ERROR_ACTION is triggered on detected bad frees and + reallocs. The argument p is an address that might have triggered the + fault. It is ignored by the two predefined actions, but might be + useful in custom actions that try to help diagnose errors. +*/ + +#if PROCEED_ON_ERROR + +/* A count of the number of corruption errors causing resets */ +int malloc_corruption_error_count; + +/* default corruption action */ +static void reset_on_error(mstate m); + +#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) +#define USAGE_ERROR_ACTION(m, p) + +#else /* PROCEED_ON_ERROR */ + +#ifndef CORRUPTION_ERROR_ACTION +#define CORRUPTION_ERROR_ACTION(m) ABORT +#endif /* CORRUPTION_ERROR_ACTION */ + +#ifndef USAGE_ERROR_ACTION +#define USAGE_ERROR_ACTION(m,p) ABORT +#endif /* USAGE_ERROR_ACTION */ + +#endif /* PROCEED_ON_ERROR */ + +/* -------------------------- Debugging setup ---------------------------- */ + +#if ! DEBUG + +#define check_free_chunk(M,P) +#define check_inuse_chunk(M,P) +#define check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) +#define check_malloc_state(M) +#define check_top_chunk(M,P) + +#else /* DEBUG */ +#define check_free_chunk(M,P) do_check_free_chunk(M,P) +#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) +#define check_top_chunk(M,P) do_check_top_chunk(M,P) +#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) +#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) +#define check_malloc_state(M) do_check_malloc_state(M) + +static void do_check_any_chunk(mstate m, mchunkptr p); +static void do_check_top_chunk(mstate m, mchunkptr p); +static void do_check_mmapped_chunk(mstate m, mchunkptr p); +static void do_check_inuse_chunk(mstate m, mchunkptr p); +static void do_check_free_chunk(mstate m, mchunkptr p); +static void do_check_malloced_chunk(mstate m, void* mem, size_t s); +static void do_check_tree(mstate m, tchunkptr t); +static void do_check_treebin(mstate m, bindex_t i); +static void do_check_smallbin(mstate m, bindex_t i); +static void do_check_malloc_state(mstate m); +static int bin_find(mstate m, mchunkptr x); +static size_t traverse_and_check(mstate m); +#endif /* DEBUG */ + +/* ---------------------------- Indexing Bins ---------------------------- */ + +#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) +#define small_index(s) ((s) >> SMALLBIN_SHIFT) +#define small_index2size(i) ((i) << SMALLBIN_SHIFT) +#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) + +/* addressing by index. See above about smallbin repositioning */ +#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) +#define treebin_at(M,i) (&((M)->treebins[i])) + +/* assign tree index for size S to variable I */ +#if defined(__GNUC__) && defined(i386) +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int K;\ + __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ + I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ + }\ +} +#else /* GNUC */ +#define compute_tree_index(S, I)\ +{\ + size_t X = S >> TREEBIN_SHIFT;\ + if (X == 0)\ + I = 0;\ + else if (X > 0xFFFF)\ + I = NTREEBINS-1;\ + else {\ + unsigned int Y = (unsigned int)X;\ + unsigned int N = ((Y - 0x100) >> 16) & 8;\ + unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ + N += K;\ + N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ + K = 14 - N + ((Y <<= K) >> 15);\ + I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ + }\ +} +#endif /* GNUC */ + +/* Bit representing maximum resolved size in a treebin at i */ +#define bit_for_tree_index(i) \ + (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) + +/* Shift placing maximum resolved bit in a treebin at i as sign bit */ +#define leftshift_for_tree_index(i) \ + ((i == NTREEBINS-1)? 0 : \ + ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) + +/* The size of the smallest chunk held in bin with index i */ +#define minsize_for_tree_index(i) \ + ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ + (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) + + +/* ------------------------ Operations on bin maps ----------------------- */ + +/* bit corresponding to given index */ +#define idx2bit(i) ((binmap_t)(1) << (i)) + +/* Mark/Clear bits with given index */ +#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) +#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) +#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) + +#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) +#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) +#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) + +/* index corresponding to given bit */ + +#if defined(__GNUC__) && defined(i386) +#define compute_bit2idx(X, I)\ +{\ + unsigned int J;\ + __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ + I = (bindex_t)J;\ +} + +#else /* GNUC */ +#if USE_BUILTIN_FFS +#define compute_bit2idx(X, I) I = ffs(X)-1 + +#else /* USE_BUILTIN_FFS */ +#define compute_bit2idx(X, I)\ +{\ + unsigned int Y = X - 1;\ + unsigned int K = Y >> (16-4) & 16;\ + unsigned int N = K; Y >>= K;\ + N += K = Y >> (8-3) & 8; Y >>= K;\ + N += K = Y >> (4-2) & 4; Y >>= K;\ + N += K = Y >> (2-1) & 2; Y >>= K;\ + N += K = Y >> (1-0) & 1; Y >>= K;\ + I = (bindex_t)(N + Y);\ +} +#endif /* USE_BUILTIN_FFS */ +#endif /* GNUC */ + +/* isolate the least set bit of a bitmap */ +#define least_bit(x) ((x) & -(x)) + +/* mask with all bits to left of least bit of x on */ +#define left_bits(x) ((x<<1) | -(x<<1)) + +/* mask with all bits to left of or equal to least bit of x on */ +#define same_or_left_bits(x) ((x) | -(x)) + + +/* ----------------------- Runtime Check Support ------------------------- */ + +/* + For security, the main invariant is that malloc/free/etc never + writes to a static address other than malloc_state, unless static + malloc_state itself has been corrupted, which cannot occur via + malloc (because of these checks). In essence this means that we + believe all pointers, sizes, maps etc held in malloc_state, but + check all of those linked or offsetted from other embedded data + structures. These checks are interspersed with main code in a way + that tends to minimize their run-time cost. + + When FOOTERS is defined, in addition to range checking, we also + verify footer fields of inuse chunks, which can be used guarantee + that the mstate controlling malloc/free is intact. This is a + streamlined version of the approach described by William Robertson + et al in "Run-time Detection of Heap-based Overflows" LISA'03 + http://www.usenix.org/events/lisa03/tech/robertson.html The footer + of an inuse chunk holds the xor of its mstate and a random seed, + that is checked upon calls to free() and realloc(). This is + (probablistically) unguessable from outside the program, but can be + computed by any code successfully malloc'ing any chunk, so does not + itself provide protection against code that has already broken + security through some other means. Unlike Robertson et al, we + always dynamically check addresses of all offset chunks (previous, + next, etc). This turns out to be cheaper than relying on hashes. +*/ + +#if !INSECURE +/* Check if address a is at least as high as any from MORECORE or MMAP */ +#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) +/* Check if address of next chunk n is higher than base chunk p */ +#define ok_next(p, n) ((char*)(p) < (char*)(n)) +/* Check if p has its cinuse bit on */ +#define ok_cinuse(p) cinuse(p) +/* Check if p has its pinuse bit on */ +#define ok_pinuse(p) pinuse(p) + +#else /* !INSECURE */ +#define ok_address(M, a) (1) +#define ok_next(b, n) (1) +#define ok_cinuse(p) (1) +#define ok_pinuse(p) (1) +#endif /* !INSECURE */ + +#if (FOOTERS && !INSECURE) +/* Check if (alleged) mstate m has expected magic field */ +#define ok_magic(M) ((M)->magic == mparams.magic) +#else /* (FOOTERS && !INSECURE) */ +#define ok_magic(M) (1) +#endif /* (FOOTERS && !INSECURE) */ + + +/* In gcc, use __builtin_expect to minimize impact of checks */ +#if !INSECURE +#if defined(__GNUC__) && __GNUC__ >= 3 +#define RTCHECK(e) __builtin_expect(e, 1) +#else /* GNUC */ +#define RTCHECK(e) (e) +#endif /* GNUC */ +#else /* !INSECURE */ +#define RTCHECK(e) (1) +#endif /* !INSECURE */ + +/* macros to set up inuse chunks with or without footers */ + +#if !FOOTERS + +#define mark_inuse_foot(M,p,s) + +/* Set cinuse bit and pinuse bit of next chunk */ +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) + +/* Set size, cinuse and pinuse bit of this chunk */ +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) + +#else /* FOOTERS */ + +/* Set foot of inuse chunk to be xor of mstate and seed */ +#define mark_inuse_foot(M,p,s)\ + (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) + +#define get_mstate_for(p)\ + ((mstate)(((mchunkptr)((char*)(p) +\ + (chunksize(p))))->prev_foot ^ mparams.magic)) + +#define set_inuse(M,p,s)\ + ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ + mark_inuse_foot(M,p,s)) + +#define set_inuse_and_pinuse(M,p,s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ + mark_inuse_foot(M,p,s)) + +#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ + ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ + mark_inuse_foot(M, p, s)) + +#endif /* !FOOTERS */ + +/* ---------------------------- setting mparams -------------------------- */ + +/* Initialize mparams */ +static int init_mparams(void) { + if (mparams.page_size == 0) { + size_t s; + + mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; + mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; +#if MORECORE_CONTIGUOUS + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; +#else /* MORECORE_CONTIGUOUS */ + mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; +#endif /* MORECORE_CONTIGUOUS */ + +#if (FOOTERS && !INSECURE) + { +#if USE_DEV_RANDOM + int fd; + unsigned char buf[sizeof(size_t)]; + /* Try to use /dev/urandom, else fall back on using time */ + if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && + read(fd, buf, sizeof(buf)) == sizeof(buf)) { + s = *((size_t *) buf); + close(fd); + } + else +#endif /* USE_DEV_RANDOM */ + s = (size_t)(time(0) ^ (size_t)0x55555555U); + + s |= (size_t)8U; /* ensure nonzero */ + s &= ~(size_t)7U; /* improve chances of fault for bad values */ + + } +#else /* (FOOTERS && !INSECURE) */ + s = (size_t)0x58585858U; +#endif /* (FOOTERS && !INSECURE) */ + ACQUIRE_MAGIC_INIT_LOCK(); + if (mparams.magic == 0) { + mparams.magic = s; + /* Set up lock for main malloc area */ + INITIAL_LOCK(&gm->mutex); + gm->mflags = mparams.default_mflags; + } + RELEASE_MAGIC_INIT_LOCK(); + +#ifndef WIN32 + mparams.page_size = malloc_getpagesize; + mparams.granularity = ((DEFAULT_GRANULARITY != 0)? + DEFAULT_GRANULARITY : mparams.page_size); +#else /* WIN32 */ + { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + mparams.page_size = system_info.dwPageSize; + mparams.granularity = system_info.dwAllocationGranularity; + } +#endif /* WIN32 */ + + /* Sanity-check configuration: + size_t must be unsigned and as wide as pointer type. + ints must be at least 4 bytes. + alignment must be at least 8. + Alignment, min chunk size, and page size must all be powers of 2. + */ + if ((sizeof(size_t) != sizeof(char*)) || + (MAX_SIZE_T < MIN_CHUNK_SIZE) || + (sizeof(int) < 4) || + (MALLOC_ALIGNMENT < (size_t)8U) || + ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || + ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || + ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || + ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) + ABORT; + } + return 0; +} + +/* support for mallopt */ +static int change_mparam(int param_number, int value) { + size_t val = (size_t)value; + init_mparams(); + switch(param_number) { + case M_TRIM_THRESHOLD: + mparams.trim_threshold = val; + return 1; + case M_GRANULARITY: + if (val >= mparams.page_size && ((val & (val-1)) == 0)) { + mparams.granularity = val; + return 1; + } + else + return 0; + case M_MMAP_THRESHOLD: + mparams.mmap_threshold = val; + return 1; + default: + return 0; + } +} + +#if DEBUG +/* ------------------------- Debugging Support --------------------------- */ + +/* Check properties of any chunk, whether free, inuse, mmapped etc */ +static void do_check_any_chunk(mstate m, mchunkptr p) { + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); +} + +/* Check properties of top chunk */ +static void do_check_top_chunk(mstate m, mchunkptr p) { + msegmentptr sp = segment_holding(m, (char*)p); + size_t sz = chunksize(p); + assert(sp != 0); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(sz == m->topsize); + assert(sz > 0); + assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); + assert(pinuse(p)); + assert(!next_pinuse(p)); +} + +/* Check properties of (inuse) mmapped chunks */ +static void do_check_mmapped_chunk(mstate m, mchunkptr p) { + size_t sz = chunksize(p); + size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD); + assert(is_mmapped(p)); + assert(use_mmap(m)); + assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); + assert(ok_address(m, p)); + assert(!is_small(sz)); + assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); + assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); + assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); +} + +/* Check properties of inuse chunks */ +static void do_check_inuse_chunk(mstate m, mchunkptr p) { + do_check_any_chunk(m, p); + assert(cinuse(p)); + assert(next_pinuse(p)); + /* If not pinuse and not mmapped, previous chunk has OK offset */ + assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); + if (is_mmapped(p)) + do_check_mmapped_chunk(m, p); +} + +/* Check properties of free chunks */ +static void do_check_free_chunk(mstate m, mchunkptr p) { + size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + mchunkptr next = chunk_plus_offset(p, sz); + do_check_any_chunk(m, p); + assert(!cinuse(p)); + assert(!next_pinuse(p)); + assert (!is_mmapped(p)); + if (p != m->dv && p != m->top) { + if (sz >= MIN_CHUNK_SIZE) { + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(is_aligned(chunk2mem(p))); + assert(next->prev_foot == sz); + assert(pinuse(p)); + assert (next == m->top || cinuse(next)); + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size SIZE_T_SIZE */ + assert(sz == SIZE_T_SIZE); + } +} + +/* Check properties of malloced chunks at the point they are malloced */ +static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); + do_check_inuse_chunk(m, p); + assert((sz & CHUNK_ALIGN_MASK) == 0); + assert(sz >= MIN_CHUNK_SIZE); + assert(sz >= s); + /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ + assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); + } +} + +/* Check a tree and its subtrees. */ +static void do_check_tree(mstate m, tchunkptr t) { + tchunkptr head = 0; + tchunkptr u = t; + bindex_t tindex = t->index; + size_t tsize = chunksize(t); + bindex_t idx; + compute_tree_index(tsize, idx); + assert(tindex == idx); + assert(tsize >= MIN_LARGE_SIZE); + assert(tsize >= minsize_for_tree_index(idx)); + assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); + + do { /* traverse through chain of same-sized nodes */ + do_check_any_chunk(m, ((mchunkptr)u)); + assert(u->index == tindex); + assert(chunksize(u) == tsize); + assert(!cinuse(u)); + assert(!next_pinuse(u)); + assert(u->fd->bk == u); + assert(u->bk->fd == u); + if (u->parent == 0) { + assert(u->child[0] == 0); + assert(u->child[1] == 0); + } + else { + assert(head == 0); /* only one node on chain has parent */ + head = u; + assert(u->parent != u); + assert (u->parent->child[0] == u || + u->parent->child[1] == u || + *((tbinptr*)(u->parent)) == u); + if (u->child[0] != 0) { + assert(u->child[0]->parent == u); + assert(u->child[0] != u); + do_check_tree(m, u->child[0]); + } + if (u->child[1] != 0) { + assert(u->child[1]->parent == u); + assert(u->child[1] != u); + do_check_tree(m, u->child[1]); + } + if (u->child[0] != 0 && u->child[1] != 0) { + assert(chunksize(u->child[0]) < chunksize(u->child[1])); + } + } + u = u->fd; + } while (u != t); + assert(head != 0); +} + +/* Check all the chunks in a treebin. */ +static void do_check_treebin(mstate m, bindex_t i) { + tbinptr* tb = treebin_at(m, i); + tchunkptr t = *tb; + int empty = (m->treemap & (1U << i)) == 0; + if (t == 0) + assert(empty); + if (!empty) + do_check_tree(m, t); +} + +/* Check all the chunks in a smallbin. */ +static void do_check_smallbin(mstate m, bindex_t i) { + sbinptr b = smallbin_at(m, i); + mchunkptr p = b->bk; + unsigned int empty = (m->smallmap & (1U << i)) == 0; + if (p == b) + assert(empty); + if (!empty) { + for (; p != b; p = p->bk) { + size_t size = chunksize(p); + mchunkptr q; + /* each chunk claims to be free */ + do_check_free_chunk(m, p); + /* chunk belongs in bin */ + assert(small_index(size) == i); + assert(p->bk == b || chunksize(p->bk) == chunksize(p)); + /* chunk is followed by an inuse chunk */ + q = next_chunk(p); + if (q->head != FENCEPOST_HEAD) + do_check_inuse_chunk(m, q); + } + } +} + +/* Find x in a bin. Used in other check functions. */ +static int bin_find(mstate m, mchunkptr x) { + size_t size = chunksize(x); + if (is_small(size)) { + bindex_t sidx = small_index(size); + sbinptr b = smallbin_at(m, sidx); + if (smallmap_is_marked(m, sidx)) { + mchunkptr p = b; + do { + if (p == x) + return 1; + } while ((p = p->fd) != b); + } + } + else { + bindex_t tidx; + compute_tree_index(size, tidx); + if (treemap_is_marked(m, tidx)) { + tchunkptr t = *treebin_at(m, tidx); + size_t sizebits = size << leftshift_for_tree_index(tidx); + while (t != 0 && chunksize(t) != size) { + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + sizebits <<= 1; + } + if (t != 0) { + tchunkptr u = t; + do { + if (u == (tchunkptr)x) + return 1; + } while ((u = u->fd) != t); + } + } + } + return 0; +} + +/* Traverse each chunk and check it; return total */ +static size_t traverse_and_check(mstate m) { + size_t sum = 0; + if (is_initialized(m)) { + msegmentptr s = &m->seg; + sum += m->topsize + TOP_FOOT_SIZE; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + mchunkptr lastq = 0; + assert(pinuse(q)); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + sum += chunksize(q); + if (cinuse(q)) { + assert(!bin_find(m, q)); + do_check_inuse_chunk(m, q); + } + else { + assert(q == m->dv || bin_find(m, q)); + assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */ + do_check_free_chunk(m, q); + } + lastq = q; + q = next_chunk(q); + } + s = s->next; + } + } + return sum; +} + +/* Check all properties of malloc_state. */ +static void do_check_malloc_state(mstate m) { + bindex_t i; + size_t total; + /* check bins */ + for (i = 0; i < NSMALLBINS; ++i) + do_check_smallbin(m, i); + for (i = 0; i < NTREEBINS; ++i) + do_check_treebin(m, i); + + if (m->dvsize != 0) { /* check dv chunk */ + do_check_any_chunk(m, m->dv); + assert(m->dvsize == chunksize(m->dv)); + assert(m->dvsize >= MIN_CHUNK_SIZE); + assert(bin_find(m, m->dv) == 0); + } + + if (m->top != 0) { /* check top chunk */ + do_check_top_chunk(m, m->top); + assert(m->topsize == chunksize(m->top)); + assert(m->topsize > 0); + assert(bin_find(m, m->top) == 0); + } + + total = traverse_and_check(m); + assert(total <= m->footprint); + assert(m->footprint <= m->max_footprint); +} +#endif /* DEBUG */ + +/* ----------------------------- statistics ------------------------------ */ + +#if !NO_MALLINFO +static struct mallinfo internal_mallinfo(mstate m) { + struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + if (!PREACTION(m)) { + check_malloc_state(m); + if (is_initialized(m)) { + size_t nfree = SIZE_T_ONE; /* top always free */ + size_t mfree = m->topsize + TOP_FOOT_SIZE; + size_t sum = mfree; + msegmentptr s = &m->seg; + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + size_t sz = chunksize(q); + sum += sz; + if (!cinuse(q)) { + mfree += sz; + ++nfree; + } + q = next_chunk(q); + } + s = s->next; + } + + nm.arena = sum; + nm.ordblks = nfree; + nm.hblkhd = m->footprint - sum; + nm.usmblks = m->max_footprint; + nm.uordblks = m->footprint - mfree; + nm.fordblks = mfree; + nm.keepcost = m->topsize; + } + + POSTACTION(m); + } + return nm; +} +#endif /* !NO_MALLINFO */ + +static void internal_malloc_stats(mstate m) { + if (!PREACTION(m)) { + size_t maxfp = 0; + size_t fp = 0; + size_t used = 0; + check_malloc_state(m); + if (is_initialized(m)) { + msegmentptr s = &m->seg; + maxfp = m->max_footprint; + fp = m->footprint; + used = fp - (m->topsize + TOP_FOOT_SIZE); + + while (s != 0) { + mchunkptr q = align_as_chunk(s->base); + while (segment_holds(s, q) && + q != m->top && q->head != FENCEPOST_HEAD) { + if (!cinuse(q)) + used -= chunksize(q); + q = next_chunk(q); + } + s = s->next; + } + } + +#ifndef LACKS_STDIO_H + fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); + fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); + fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); +#endif + + POSTACTION(m); + } +} + +/* ----------------------- Operations on smallbins ----------------------- */ + +/* + Various forms of linking and unlinking are defined as macros. Even + the ones for trees, which are very long but have very short typical + paths. This is ugly but reduces reliance on inlining support of + compilers. +*/ + +/* Link a free chunk into a smallbin */ +#define insert_small_chunk(M, P, S) {\ + bindex_t I = small_index(S);\ + mchunkptr B = smallbin_at(M, I);\ + mchunkptr F = B;\ + assert(S >= MIN_CHUNK_SIZE);\ + if (!smallmap_is_marked(M, I))\ + mark_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, B->fd)))\ + F = B->fd;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + B->fd = P;\ + F->bk = P;\ + P->fd = F;\ + P->bk = B;\ +} + +/* Unlink a chunk from a smallbin */ +#define unlink_small_chunk(M, P, S) {\ + mchunkptr F = P->fd;\ + mchunkptr B = P->bk;\ + bindex_t I = small_index(S);\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (F == B)\ + clear_smallmap(M, I);\ + else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ + (B == smallbin_at(M,I) || ok_address(M, B)))) {\ + F->bk = B;\ + B->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Unlink the first chunk from a smallbin */ +#define unlink_first_small_chunk(M, B, P, I) {\ + mchunkptr F = P->fd;\ + assert(P != B);\ + assert(P != F);\ + assert(chunksize(P) == small_index2size(I));\ + if (B == F)\ + clear_smallmap(M, I);\ + else if (RTCHECK(ok_address(M, F))) {\ + B->fd = F;\ + F->bk = B;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ +} + +/* Replace dv node, binning the old one */ +/* Used only when dvsize known to be small */ +#define replace_dv(M, P, S) {\ + size_t DVS = M->dvsize;\ + if (DVS != 0) {\ + mchunkptr DV = M->dv;\ + assert(is_small(DVS));\ + insert_small_chunk(M, DV, DVS);\ + }\ + M->dvsize = S;\ + M->dv = P;\ +} + +/* ------------------------- Operations on trees ------------------------- */ + +/* Insert chunk into tree */ +#define insert_large_chunk(M, X, S) {\ + tbinptr* H;\ + bindex_t I;\ + compute_tree_index(S, I);\ + H = treebin_at(M, I);\ + X->index = I;\ + X->child[0] = X->child[1] = 0;\ + if (!treemap_is_marked(M, I)) {\ + mark_treemap(M, I);\ + *H = X;\ + X->parent = (tchunkptr)H;\ + X->fd = X->bk = X;\ + }\ + else {\ + tchunkptr T = *H;\ + size_t K = S << leftshift_for_tree_index(I);\ + for (;;) {\ + if (chunksize(T) != S) {\ + tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ + K <<= 1;\ + if (*C != 0)\ + T = *C;\ + else if (RTCHECK(ok_address(M, C))) {\ + *C = X;\ + X->parent = T;\ + X->fd = X->bk = X;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + else {\ + tchunkptr F = T->fd;\ + if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ + T->fd = F->bk = X;\ + X->fd = F;\ + X->bk = T;\ + X->parent = 0;\ + break;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + break;\ + }\ + }\ + }\ + }\ +} + +/* + Unlink steps: + + 1. If x is a chained node, unlink it from its same-sized fd/bk links + and choose its bk node as its replacement. + 2. If x was the last node of its size, but not a leaf node, it must + be replaced with a leaf node (not merely one with an open left or + right), to make sure that lefts and rights of descendents + correspond properly to bit masks. We use the rightmost descendent + of x. We could use any other leaf, but this is easy to locate and + tends to counteract removal of leftmosts elsewhere, and so keeps + paths shorter than minimally guaranteed. This doesn't loop much + because on average a node in a tree is near the bottom. + 3. If x is the base of a chain (i.e., has parent links) relink + x's parent and children to x's replacement (or null if none). +*/ + +#define unlink_large_chunk(M, X) {\ + tchunkptr XP = X->parent;\ + tchunkptr R;\ + if (X->bk != X) {\ + tchunkptr F = X->fd;\ + R = X->bk;\ + if (RTCHECK(ok_address(M, F))) {\ + F->bk = R;\ + R->fd = F;\ + }\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else {\ + tchunkptr* RP;\ + if (((R = *(RP = &(X->child[1]))) != 0) ||\ + ((R = *(RP = &(X->child[0]))) != 0)) {\ + tchunkptr* CP;\ + while ((*(CP = &(R->child[1])) != 0) ||\ + (*(CP = &(R->child[0])) != 0)) {\ + R = *(RP = CP);\ + }\ + if (RTCHECK(ok_address(M, RP)))\ + *RP = 0;\ + else {\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + }\ + if (XP != 0) {\ + tbinptr* H = treebin_at(M, X->index);\ + if (X == *H) {\ + if ((*H = R) == 0) \ + clear_treemap(M, X->index);\ + }\ + else if (RTCHECK(ok_address(M, XP))) {\ + if (XP->child[0] == X) \ + XP->child[0] = R;\ + else \ + XP->child[1] = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + if (R != 0) {\ + if (RTCHECK(ok_address(M, R))) {\ + tchunkptr C0, C1;\ + R->parent = XP;\ + if ((C0 = X->child[0]) != 0) {\ + if (RTCHECK(ok_address(M, C0))) {\ + R->child[0] = C0;\ + C0->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + if ((C1 = X->child[1]) != 0) {\ + if (RTCHECK(ok_address(M, C1))) {\ + R->child[1] = C1;\ + C1->parent = R;\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ + else\ + CORRUPTION_ERROR_ACTION(M);\ + }\ + }\ +} + +/* Relays to large vs small bin operations */ + +#define insert_chunk(M, P, S)\ + if (is_small(S)) insert_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } + +#define unlink_chunk(M, P, S)\ + if (is_small(S)) unlink_small_chunk(M, P, S)\ + else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } + + +/* Relays to internal calls to malloc/free from realloc, memalign etc */ + +#if ONLY_MSPACES +#define internal_malloc(m, b) mspace_malloc(m, b) +#define internal_free(m, mem) mspace_free(m,mem); +#else /* ONLY_MSPACES */ +#if MSPACES +#define internal_malloc(m, b)\ + (m == gm)? dlmalloc(b) : mspace_malloc(m, b) +#define internal_free(m, mem)\ + if (m == gm) dlfree(mem); else mspace_free(m,mem); +#else /* MSPACES */ +#define internal_malloc(m, b) dlmalloc(b) +#define internal_free(m, mem) dlfree(mem) +#endif /* MSPACES */ +#endif /* ONLY_MSPACES */ + +/* ----------------------- Direct-mmapping chunks ----------------------- */ + +/* + Directly mmapped chunks are set up with an offset to the start of + the mmapped region stored in the prev_foot field of the chunk. This + allows reconstruction of the required argument to MUNMAP when freed, + and also allows adjustment of the returned chunk to meet alignment + requirements (especially in memalign). There is also enough space + allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain + the PINUSE bit so frees can be checked. +*/ + +/* Malloc using mmap */ +static void* mmap_alloc(mstate m, size_t nb) { + size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + if (mmsize > nb) { /* Check for wrap around 0 */ + char* mm = (char*)(DIRECT_MMAP(mmsize)); + if (mm != CMFAIL) { + size_t offset = align_offset(chunk2mem(mm)); + size_t psize = mmsize - offset - MMAP_FOOT_PAD; + mchunkptr p = (mchunkptr)(mm + offset); + p->prev_foot = offset | IS_MMAPPED_BIT; + (p)->head = (psize|CINUSE_BIT); + mark_inuse_foot(m, p, psize); + chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; + + if (mm < m->least_addr) + m->least_addr = mm; + if ((m->footprint += mmsize) > m->max_footprint) + m->max_footprint = m->footprint; + assert(is_aligned(chunk2mem(p))); + check_mmapped_chunk(m, p); + return chunk2mem(p); + } + } + return 0; +} + +/* Realloc using mmap */ +static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { + size_t oldsize = chunksize(oldp); + if (is_small(nb)) /* Can't shrink mmap regions below small size */ + return 0; + /* Keep old chunk if big enough but not too big */ + if (oldsize >= nb + SIZE_T_SIZE && + (oldsize - nb) <= (mparams.granularity << 1)) + return oldp; + else { + size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT; + size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; + size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES + + CHUNK_ALIGN_MASK); + char* cp = (char*)CALL_MREMAP((char*)oldp - offset, + oldmmsize, newmmsize, 1); + if (cp != CMFAIL) { + mchunkptr newp = (mchunkptr)(cp + offset); + size_t psize = newmmsize - offset - MMAP_FOOT_PAD; + newp->head = (psize|CINUSE_BIT); + mark_inuse_foot(m, newp, psize); + chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; + chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; + + if (cp < m->least_addr) + m->least_addr = cp; + if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) + m->max_footprint = m->footprint; + check_mmapped_chunk(m, newp); + return newp; + } + } + return 0; +} + +/* -------------------------- mspace management -------------------------- */ + +/* Initialize top chunk and its size */ +static void init_top(mstate m, mchunkptr p, size_t psize) { + /* Ensure alignment */ + size_t offset = align_offset(chunk2mem(p)); + p = (mchunkptr)((char*)p + offset); + psize -= offset; + + m->top = p; + m->topsize = psize; + p->head = psize | PINUSE_BIT; + /* set size of fake trailing chunk holding overhead space only once */ + chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; + m->trim_check = mparams.trim_threshold; /* reset on each update */ +} + +/* Initialize bins for a new mstate that is otherwise zeroed out */ +static void init_bins(mstate m) { + /* Establish circular links for smallbins */ + bindex_t i; + for (i = 0; i < NSMALLBINS; ++i) { + sbinptr bin = smallbin_at(m,i); + bin->fd = bin->bk = bin; + } +} + +#if PROCEED_ON_ERROR + +/* default corruption action */ +static void reset_on_error(mstate m) { + int i; + ++malloc_corruption_error_count; + /* Reinitialize fields to forget about all memory */ + m->smallbins = m->treebins = 0; + m->dvsize = m->topsize = 0; + m->seg.base = 0; + m->seg.size = 0; + m->seg.next = 0; + m->top = m->dv = 0; + for (i = 0; i < NTREEBINS; ++i) + *treebin_at(m, i) = 0; + init_bins(m); +} +#endif /* PROCEED_ON_ERROR */ + +/* Allocate chunk and prepend remainder with chunk in successor base. */ +static void* prepend_alloc(mstate m, char* newbase, char* oldbase, + size_t nb) { + mchunkptr p = align_as_chunk(newbase); + mchunkptr oldfirst = align_as_chunk(oldbase); + size_t psize = (char*)oldfirst - (char*)p; + mchunkptr q = chunk_plus_offset(p, nb); + size_t qsize = psize - nb; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + + assert((char*)oldfirst > (char*)q); + assert(pinuse(oldfirst)); + assert(qsize >= MIN_CHUNK_SIZE); + + /* consolidate remainder with first chunk of old base */ + if (oldfirst == m->top) { + size_t tsize = m->topsize += qsize; + m->top = q; + q->head = tsize | PINUSE_BIT; + check_top_chunk(m, q); + } + else if (oldfirst == m->dv) { + size_t dsize = m->dvsize += qsize; + m->dv = q; + set_size_and_pinuse_of_free_chunk(q, dsize); + } + else { + if (!cinuse(oldfirst)) { + size_t nsize = chunksize(oldfirst); + unlink_chunk(m, oldfirst, nsize); + oldfirst = chunk_plus_offset(oldfirst, nsize); + qsize += nsize; + } + set_free_with_pinuse(q, qsize, oldfirst); + insert_chunk(m, q, qsize); + check_free_chunk(m, q); + } + + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); +} + + +/* Add a segment to hold a new noncontiguous region */ +static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { + /* Determine locations and sizes of segment, fenceposts, old top */ + char* old_top = (char*)m->top; + msegmentptr oldsp = segment_holding(m, old_top); + char* old_end = oldsp->base + oldsp->size; + size_t ssize = pad_request(sizeof(struct malloc_segment)); + char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); + size_t offset = align_offset(chunk2mem(rawsp)); + char* asp = rawsp + offset; + char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; + mchunkptr sp = (mchunkptr)csp; + msegmentptr ss = (msegmentptr)(chunk2mem(sp)); + mchunkptr tnext = chunk_plus_offset(sp, ssize); + mchunkptr p = tnext; + int nfences = 0; + + /* reset top to new space */ + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + + /* Set up segment record */ + assert(is_aligned(ss)); + set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); + *ss = m->seg; /* Push current record */ + m->seg.base = tbase; + m->seg.size = tsize; + m->seg.sflags = mmapped; + m->seg.next = ss; + + /* Insert trailing fenceposts */ + for (;;) { + mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); + p->head = FENCEPOST_HEAD; + ++nfences; + if ((char*)(&(nextp->head)) < old_end) + p = nextp; + else + break; + } + assert(nfences >= 2); + + /* Insert the rest of old top into a bin as an ordinary free chunk */ + if (csp != old_top) { + mchunkptr q = (mchunkptr)old_top; + size_t psize = csp - old_top; + mchunkptr tn = chunk_plus_offset(q, psize); + set_free_with_pinuse(q, psize, tn); + insert_chunk(m, q, psize); + } + + check_top_chunk(m, m->top); +} + +/* -------------------------- System allocation -------------------------- */ + +/* Get memory from system using MORECORE or MMAP */ +static void* sys_alloc(mstate m, size_t nb) { + char* tbase = CMFAIL; + size_t tsize = 0; + flag_t mmap_flag = 0; + + init_mparams(); + + /* Directly map large chunks */ + if (use_mmap(m) && nb >= mparams.mmap_threshold) { + void* mem = mmap_alloc(m, nb); + if (mem != 0) + return mem; + } + + /* + Try getting memory in any of three ways (in most-preferred to + least-preferred order): + 1. A call to MORECORE that can normally contiguously extend memory. + (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or + or main space is mmapped or a previous contiguous call failed) + 2. A call to MMAP new space (disabled if not HAVE_MMAP). + Note that under the default settings, if MORECORE is unable to + fulfill a request, and HAVE_MMAP is true, then mmap is + used as a noncontiguous system allocator. This is a useful backup + strategy for systems with holes in address spaces -- in this case + sbrk cannot contiguously expand the heap, but mmap may be able to + find space. + 3. A call to MORECORE that cannot usually contiguously extend memory. + (disabled if not HAVE_MORECORE) + */ + + if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { + char* br = CMFAIL; + msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); + size_t asize = 0; + ACQUIRE_MORECORE_LOCK(); + + if (ss == 0) { /* First time through or recovery */ + char* base = (char*)CALL_MORECORE(0); + if (base != CMFAIL) { + asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE); + /* Adjust to end on a page boundary */ + if (!is_page_aligned(base)) + asize += (page_align((size_t)base) - (size_t)base); + /* Can't call MORECORE if size is negative when treated as signed */ + if (asize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(asize))) == base) { + tbase = base; + tsize = asize; + } + } + } + else { + /* Subtract out existing available top space from MORECORE request. */ + asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE); + /* Use mem here only if it did continuously extend old space */ + if (asize < HALF_MAX_SIZE_T && + (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { + tbase = br; + tsize = asize; + } + } + + if (tbase == CMFAIL) { /* Cope with partial failure */ + if (br != CMFAIL) { /* Try to use/extend the space we did get */ + if (asize < HALF_MAX_SIZE_T && + asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) { + size_t esize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE - asize); + if (esize < HALF_MAX_SIZE_T) { + char* end = (char*)CALL_MORECORE(esize); + if (end != CMFAIL) + asize += esize; + else { /* Can't use; try to release */ + end = (char*)CALL_MORECORE(-asize); + br = CMFAIL; + } + } + } + } + if (br != CMFAIL) { /* Use the space we did get */ + tbase = br; + tsize = asize; + } + else + disable_contiguous(m); /* Don't try contiguous path in the future */ + } + + RELEASE_MORECORE_LOCK(); + } + + if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ + size_t req = nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE; + size_t rsize = granularity_align(req); + if (rsize > nb) { /* Fail if wraps around zero */ + char* mp = (char*)(CALL_MMAP(rsize)); + if (mp != CMFAIL) { + tbase = mp; + tsize = rsize; + mmap_flag = IS_MMAPPED_BIT; + } + } + } + + if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ + size_t asize = granularity_align(nb + TOP_FOOT_SIZE + MALLOC_ALIGNMENT + SIZE_T_ONE); + if (asize < HALF_MAX_SIZE_T) { + char* br = CMFAIL; + char* end = CMFAIL; + ACQUIRE_MORECORE_LOCK(); + br = (char*)(CALL_MORECORE(asize)); + end = (char*)(CALL_MORECORE(0)); + RELEASE_MORECORE_LOCK(); + if (br != CMFAIL && end != CMFAIL && br < end) { + size_t ssize = end - br; + if (ssize > nb + TOP_FOOT_SIZE) { + tbase = br; + tsize = ssize; + } + } + } + } + + if (tbase != CMFAIL) { + + if ((m->footprint += tsize) > m->max_footprint) + m->max_footprint = m->footprint; + + if (!is_initialized(m)) { /* first-time initialization */ + m->seg.base = m->least_addr = tbase; + m->seg.size = tsize; + m->seg.sflags = mmap_flag; + m->magic = mparams.magic; + init_bins(m); + if (is_global(m)) + init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); + else { + /* Offset top by embedded malloc_state */ + mchunkptr mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); + } + } + + else { + /* Try to merge with an existing segment */ + msegmentptr sp = &m->seg; + while (sp != 0 && tbase != sp->base + sp->size) + sp = sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & IS_MMAPPED_BIT) == mmap_flag && + segment_holds(sp, m->top)) { /* append */ + sp->size += tsize; + init_top(m, m->top, m->topsize + tsize); + } + else { + if (tbase < m->least_addr) + m->least_addr = tbase; + sp = &m->seg; + while (sp != 0 && sp->base != tbase + tsize) + sp = sp->next; + if (sp != 0 && + !is_extern_segment(sp) && + (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) { + char* oldbase = sp->base; + sp->base = tbase; + sp->size += tsize; + return prepend_alloc(m, tbase, oldbase, nb); + } + else + add_segment(m, tbase, tsize, mmap_flag); + } + } + + if (nb < m->topsize) { /* Allocate from new or extended top space */ + size_t rsize = m->topsize -= nb; + mchunkptr p = m->top; + mchunkptr r = m->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(m, p, nb); + check_top_chunk(m, m->top); + check_malloced_chunk(m, chunk2mem(p), nb); + return chunk2mem(p); + } + } + + MALLOC_FAILURE_ACTION; + return 0; +} + +/* ----------------------- system deallocation -------------------------- */ + +/* Unmap and unlink any mmapped segments that don't contain used chunks */ +static size_t release_unused_segments(mstate m) { + size_t released = 0; + msegmentptr pred = &m->seg; + msegmentptr sp = pred->next; + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + msegmentptr next = sp->next; + if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { + mchunkptr p = align_as_chunk(base); + size_t psize = chunksize(p); + /* Can unmap if first chunk holds entire segment and not pinned */ + if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { + tchunkptr tp = (tchunkptr)p; + assert(segment_holds(sp, (char*)sp)); + if (p == m->dv) { + m->dv = 0; + m->dvsize = 0; + } + else { + unlink_large_chunk(m, tp); + } + if (CALL_MUNMAP(base, size) == 0) { + released += size; + m->footprint -= size; + /* unlink obsoleted record */ + sp = pred; + sp->next = next; + } + else { /* back out if cannot unmap */ + insert_large_chunk(m, tp, psize); + } + } + } + pred = sp; + sp = next; + } + return released; +} + +static int sys_trim(mstate m, size_t pad) { + size_t released = 0; + if (pad < MAX_REQUEST && is_initialized(m)) { + pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ + + if (m->topsize > pad) { + /* Shrink top space in granularity-size units, keeping at least one */ + size_t unit = mparams.granularity; + size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - + SIZE_T_ONE) * unit; + msegmentptr sp = segment_holding(m, (char*)m->top); + + if (!is_extern_segment(sp)) { + if (is_mmapped_segment(sp)) { + if (HAVE_MMAP && + sp->size >= extra && + !has_segment_link(m, sp)) { /* can't shrink if pinned */ + size_t newsize = sp->size - extra; + /* Prefer mremap, fall back to munmap */ + if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || + (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { + released = extra; + } + } + } + else if (HAVE_MORECORE) { + if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ + extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; + ACQUIRE_MORECORE_LOCK(); + { + /* Make sure end of memory is where we last set it. */ + char* old_br = (char*)(CALL_MORECORE(0)); + if (old_br == sp->base + sp->size) { + char* rel_br = (char*)(CALL_MORECORE(-extra)); + char* new_br = (char*)(CALL_MORECORE(0)); + if (rel_br != CMFAIL && new_br < old_br) + released = old_br - new_br; + } + } + RELEASE_MORECORE_LOCK(); + } + } + + if (released != 0) { + sp->size -= released; + m->footprint -= released; + init_top(m, m->top, m->topsize - released); + check_top_chunk(m, m->top); + } + } + + /* Unmap any unused mmapped segments */ + if (HAVE_MMAP) + released += release_unused_segments(m); + + /* On failure, disable autotrim to avoid repeated failed future calls */ + if (released == 0) + m->trim_check = MAX_SIZE_T; + } + + return (released != 0)? 1 : 0; +} + +/* ---------------------------- malloc support --------------------------- */ + +/* allocate a large request from the best fitting chunk in a treebin */ +static void* tmalloc_large(mstate m, size_t nb) { + tchunkptr v = 0; + size_t rsize = -nb; /* Unsigned negation */ + tchunkptr t; + bindex_t idx; + compute_tree_index(nb, idx); + + if ((t = *treebin_at(m, idx)) != 0) { + /* Traverse tree for this bin looking for node with size == nb */ + size_t sizebits = nb << leftshift_for_tree_index(idx); + tchunkptr rst = 0; /* The deepest untaken right subtree */ + for (;;) { + tchunkptr rt; + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + v = t; + if ((rsize = trem) == 0) + break; + } + rt = t->child[1]; + t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; + if (rt != 0 && rt != t) + rst = rt; + if (t == 0) { + t = rst; /* set t to least subtree holding sizes > nb */ + break; + } + sizebits <<= 1; + } + } + + if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ + binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; + if (leftbits != 0) { + bindex_t i; + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + t = *treebin_at(m, i); + } + } + + while (t != 0) { /* find smallest of tree or subtree */ + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + t = leftmost_child(t); + } + + /* If dv is a better fit, return 0 so malloc will use it */ + if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { + if (RTCHECK(ok_address(m, v))) { /* split */ + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + insert_chunk(m, r, rsize); + } + return chunk2mem(v); + } + } + CORRUPTION_ERROR_ACTION(m); + } + return 0; +} + +/* allocate a small request from the best fitting chunk in a treebin */ +static void* tmalloc_small(mstate m, size_t nb) { + tchunkptr t, v; + size_t rsize; + bindex_t i; + binmap_t leastbit = least_bit(m->treemap); + compute_bit2idx(leastbit, i); + + v = t = *treebin_at(m, i); + rsize = chunksize(t) - nb; + + while ((t = leftmost_child(t)) != 0) { + size_t trem = chunksize(t) - nb; + if (trem < rsize) { + rsize = trem; + v = t; + } + } + + if (RTCHECK(ok_address(m, v))) { + mchunkptr r = chunk_plus_offset(v, nb); + assert(chunksize(v) == rsize + nb); + if (RTCHECK(ok_next(v, r))) { + unlink_large_chunk(m, v); + if (rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(m, v, (rsize + nb)); + else { + set_size_and_pinuse_of_inuse_chunk(m, v, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(m, r, rsize); + } + return chunk2mem(v); + } + } + + CORRUPTION_ERROR_ACTION(m); + return 0; +} + +/* --------------------------- realloc support --------------------------- */ + +static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { + if (bytes >= MAX_REQUEST) { + MALLOC_FAILURE_ACTION; + return 0; + } + if (!PREACTION(m)) { + mchunkptr oldp = mem2chunk(oldmem); + size_t oldsize = chunksize(oldp); + mchunkptr next = chunk_plus_offset(oldp, oldsize); + mchunkptr newp = 0; + void* extra = 0; + + /* Try to either shrink or extend into top. Else malloc-copy-free */ + + if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && + ok_next(oldp, next) && ok_pinuse(next))) { + size_t nb = request2size(bytes); + if (is_mmapped(oldp)) + newp = mmap_resize(m, oldp, nb); + else if (oldsize >= nb) { /* already big enough */ + size_t rsize = oldsize - nb; + newp = oldp; + if (rsize >= MIN_CHUNK_SIZE) { + mchunkptr remainder = chunk_plus_offset(newp, nb); + set_inuse(m, newp, nb); + set_inuse(m, remainder, rsize); + extra = chunk2mem(remainder); + } + } + else if (next == m->top && oldsize + m->topsize > nb) { + /* Expand into top */ + size_t newsize = oldsize + m->topsize; + size_t newtopsize = newsize - nb; + mchunkptr newtop = chunk_plus_offset(oldp, nb); + set_inuse(m, oldp, nb); + newtop->head = newtopsize |PINUSE_BIT; + m->top = newtop; + m->topsize = newtopsize; + newp = oldp; + } + } + else { + USAGE_ERROR_ACTION(m, oldmem); + POSTACTION(m); + return 0; + } + + POSTACTION(m); + + if (newp != 0) { + if (extra != 0) { + internal_free(m, extra); + } + check_inuse_chunk(m, newp); + return chunk2mem(newp); + } + else { + void* newmem = internal_malloc(m, bytes); + if (newmem != 0) { + size_t oc = oldsize - overhead_for(oldp); + memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); + internal_free(m, oldmem); + } + return newmem; + } + } + return 0; +} + +/* --------------------------- memalign support -------------------------- */ + +static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { + if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ + return internal_malloc(m, bytes); + if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ + alignment = MIN_CHUNK_SIZE; + if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ + size_t a = MALLOC_ALIGNMENT << 1; + while (a < alignment) a <<= 1; + alignment = a; + } + + if (bytes >= MAX_REQUEST - alignment) { + if (m != 0) { /* Test isn't needed but avoids compiler warning */ + MALLOC_FAILURE_ACTION; + } + } + else { + size_t nb = request2size(bytes); + size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; + char* mem = (char*)internal_malloc(m, req); + if (mem != 0) { + void* leader = 0; + void* trailer = 0; + mchunkptr p = mem2chunk(mem); + + if (PREACTION(m)) return 0; + if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ + /* + Find an aligned spot inside chunk. Since we need to give + back leading space in a chunk of at least MIN_CHUNK_SIZE, if + the first calculation places us at a spot with less than + MIN_CHUNK_SIZE leader, we can move to the next aligned spot. + We've allocated enough total room so that this is always + possible. + */ + char* br = (char*)mem2chunk((size_t)(((size_t)(mem + + alignment - + SIZE_T_ONE)) & + -alignment)); + char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? + br : br+alignment; + mchunkptr newp = (mchunkptr)pos; + size_t leadsize = pos - (char*)(p); + size_t newsize = chunksize(p) - leadsize; + + if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ + newp->prev_foot = p->prev_foot + leadsize; + newp->head = (newsize|CINUSE_BIT); + } + else { /* Otherwise, give back leader, use the rest */ + set_inuse(m, newp, newsize); + set_inuse(m, p, leadsize); + leader = chunk2mem(p); + } + p = newp; + } + + /* Give back spare room at the end */ + if (!is_mmapped(p)) { + size_t size = chunksize(p); + if (size > nb + MIN_CHUNK_SIZE) { + size_t remainder_size = size - nb; + mchunkptr remainder = chunk_plus_offset(p, nb); + set_inuse(m, p, nb); + set_inuse(m, remainder, remainder_size); + trailer = chunk2mem(remainder); + } + } + + assert (chunksize(p) >= nb); + assert((((size_t)(chunk2mem(p))) % alignment) == 0); + check_inuse_chunk(m, p); + POSTACTION(m); + if (leader != 0) { + internal_free(m, leader); + } + if (trailer != 0) { + internal_free(m, trailer); + } + return chunk2mem(p); + } + } + return 0; +} + +/* ------------------------ comalloc/coalloc support --------------------- */ + +static void** ialloc(mstate m, + size_t n_elements, + size_t* sizes, + int opts, + void* chunks[]) { + /* + This provides common support for independent_X routines, handling + all of the combinations that can result. + + The opts arg has: + bit 0 set if all elements are same size (using sizes[0]) + bit 1 set if elements should be zeroed + */ + + size_t element_size; /* chunksize of each element, if all same */ + size_t contents_size; /* total size of elements */ + size_t array_size; /* request size of pointer array */ + void* mem; /* malloced aggregate space */ + mchunkptr p; /* corresponding chunk */ + size_t remainder_size; /* remaining bytes while splitting */ + void** marray; /* either "chunks" or malloced ptr array */ + mchunkptr array_chunk; /* chunk for malloced ptr array */ + flag_t was_enabled; /* to disable mmap */ + size_t size; + size_t i; + + /* compute array length, if needed */ + if (chunks != 0) { + if (n_elements == 0) + return chunks; /* nothing to do */ + marray = chunks; + array_size = 0; + } + else { + /* if empty req, must still return chunk representing empty array */ + if (n_elements == 0) + return (void**)internal_malloc(m, 0); + marray = 0; + array_size = request2size(n_elements * (sizeof(void*))); + } + + /* compute total element size */ + if (opts & 0x1) { /* all-same-size */ + element_size = request2size(*sizes); + contents_size = n_elements * element_size; + } + else { /* add up all the sizes */ + element_size = 0; + contents_size = 0; + for (i = 0; i != n_elements; ++i) + contents_size += request2size(sizes[i]); + } + + size = contents_size + array_size; + + /* + Allocate the aggregate chunk. First disable direct-mmapping so + malloc won't use it, since we would not be able to later + free/realloc space internal to a segregated mmap region. + */ + was_enabled = use_mmap(m); + disable_mmap(m); + mem = internal_malloc(m, size - CHUNK_OVERHEAD); + if (was_enabled) + enable_mmap(m); + if (mem == 0) + return 0; + + if (PREACTION(m)) return 0; + p = mem2chunk(mem); + remainder_size = chunksize(p); + + assert(!is_mmapped(p)); + + if (opts & 0x2) { /* optionally clear the elements */ + memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); + } + + /* If not provided, allocate the pointer array as final part of chunk */ + if (marray == 0) { + size_t array_chunk_size; + array_chunk = chunk_plus_offset(p, contents_size); + array_chunk_size = remainder_size - contents_size; + marray = (void**) (chunk2mem(array_chunk)); + set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); + remainder_size = contents_size; + } + + /* split out elements */ + for (i = 0; ; ++i) { + marray[i] = chunk2mem(p); + if (i != n_elements-1) { + if (element_size != 0) + size = element_size; + else + size = request2size(sizes[i]); + remainder_size -= size; + set_size_and_pinuse_of_inuse_chunk(m, p, size); + p = chunk_plus_offset(p, size); + } + else { /* the final element absorbs any overallocation slop */ + set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); + break; + } + } + +#if DEBUG + if (marray != chunks) { + /* final element must have exactly exhausted chunk */ + if (element_size != 0) { + assert(remainder_size == element_size); + } + else { + assert(remainder_size == request2size(sizes[i])); + } + check_inuse_chunk(m, mem2chunk(marray)); + } + for (i = 0; i != n_elements; ++i) + check_inuse_chunk(m, mem2chunk(marray[i])); + +#endif /* DEBUG */ + + POSTACTION(m); + return marray; +} + + +/* -------------------------- public routines ---------------------------- */ + +#if !ONLY_MSPACES + +void* dlmalloc(size_t bytes) { + /* + Basic algorithm: + If a small request (< 256 bytes minus per-chunk overhead): + 1. If one exists, use a remainderless chunk in associated smallbin. + (Remainderless means that there are too few excess bytes to + represent as a chunk.) + 2. If it is big enough, use the dv chunk, which is normally the + chunk adjacent to the one used for the most recent small request. + 3. If one exists, split the smallest available chunk in a bin, + saving remainder in dv. + 4. If it is big enough, use the top chunk. + 5. If available, get memory from system and use it + Otherwise, for a large request: + 1. Find the smallest available binned chunk that fits, and use it + if it is better fitting than dv chunk, splitting if necessary. + 2. If better fitting than any binned chunk, use the dv chunk. + 3. If it is big enough, use the top chunk. + 4. If request size >= mmap threshold, try to directly mmap this chunk. + 5. If available, get memory from system and use it + + The ugly goto's here ensure that postaction occurs along all paths. + */ + + if (!PREACTION(gm)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = gm->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(gm, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(gm, b, p, idx); + set_inuse_and_pinuse(gm, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb > gm->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(gm, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(gm, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(gm, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(gm, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + } + + if (nb <= gm->dvsize) { + size_t rsize = gm->dvsize - nb; + mchunkptr p = gm->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = gm->dv = chunk_plus_offset(p, nb); + gm->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + } + else { /* exhaust dv */ + size_t dvs = gm->dvsize; + gm->dvsize = 0; + gm->dv = 0; + set_inuse_and_pinuse(gm, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + else if (nb < gm->topsize) { /* Split top */ + size_t rsize = gm->topsize -= nb; + mchunkptr p = gm->top; + mchunkptr r = gm->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(gm, p, nb); + mem = chunk2mem(p); + check_top_chunk(gm, gm->top); + check_malloced_chunk(gm, mem, nb); + goto postaction; + } + + mem = sys_alloc(gm, nb); + + postaction: + POSTACTION(gm); + return mem; + } + + return 0; +} + +void dlfree(void* mem) { + /* + Consolidate freed chunks with preceeding or succeeding bordering + free chunks, if they exist, and then place in a bin. Intermixed + with special cases for top, dv, mmapped chunks, and usage errors. + */ + + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } +#else /* FOOTERS */ +#define fm gm +#endif /* FOOTERS */ + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if ((prevsize & IS_MMAPPED_BIT) != 0) { + prevsize &= ~IS_MMAPPED_BIT; + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + insert_chunk(fm, p, psize); + check_free_chunk(fm, p); + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +#if !FOOTERS +#undef fm +#endif /* FOOTERS */ +} + +void* dlcalloc(size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = dlmalloc(req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +void* dlrealloc(void* oldmem, size_t bytes) { + if (oldmem == 0) + return dlmalloc(bytes); +#ifdef REALLOC_ZERO_BYTES_FREES + if (bytes == 0) { + dlfree(oldmem); + return 0; + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { +#if ! FOOTERS + mstate m = gm; +#else /* FOOTERS */ + mstate m = get_mstate_for(mem2chunk(oldmem)); + if (!ok_magic(m)) { + USAGE_ERROR_ACTION(m, oldmem); + return 0; + } +#endif /* FOOTERS */ + return internal_realloc(m, oldmem, bytes); + } +} + +void* dlmemalign(size_t alignment, size_t bytes) { + return internal_memalign(gm, alignment, bytes); +} + +void** dlindependent_calloc(size_t n_elements, size_t elem_size, + void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + return ialloc(gm, n_elements, &sz, 3, chunks); +} + +void** dlindependent_comalloc(size_t n_elements, size_t sizes[], + void* chunks[]) { + return ialloc(gm, n_elements, sizes, 0, chunks); +} + +void* dlvalloc(size_t bytes) { + size_t pagesz; + init_mparams(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, bytes); +} + +void* dlpvalloc(size_t bytes) { + size_t pagesz; + init_mparams(); + pagesz = mparams.page_size; + return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); +} + +int dlmalloc_trim(size_t pad) { + int result = 0; + if (!PREACTION(gm)) { + result = sys_trim(gm, pad); + POSTACTION(gm); + } + return result; +} + +size_t dlmalloc_footprint(void) { + return gm->footprint; +} + +size_t dlmalloc_max_footprint(void) { + return gm->max_footprint; +} + +#if !NO_MALLINFO +struct mallinfo dlmallinfo(void) { + return internal_mallinfo(gm); +} +#endif /* NO_MALLINFO */ + +void dlmalloc_stats() { + internal_malloc_stats(gm); +} + +size_t dlmalloc_usable_size(void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); + if (cinuse(p)) + return chunksize(p) - overhead_for(p); + } + return 0; +} + +int dlmallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +#endif /* !ONLY_MSPACES */ + +/* ----------------------------- user mspaces ---------------------------- */ + +#if MSPACES + +static mstate init_user_mstate(char* tbase, size_t tsize) { + size_t msize = pad_request(sizeof(struct malloc_state)); + mchunkptr mn; + mchunkptr msp = align_as_chunk(tbase); + mstate m = (mstate)(chunk2mem(msp)); + memset(m, 0, msize); + INITIAL_LOCK(&m->mutex); + msp->head = (msize|PINUSE_BIT|CINUSE_BIT); + m->seg.base = m->least_addr = tbase; + m->seg.size = m->footprint = m->max_footprint = tsize; + m->magic = mparams.magic; + m->mflags = mparams.default_mflags; + disable_contiguous(m); + init_bins(m); + mn = next_chunk(mem2chunk(m)); + init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); + check_top_chunk(m, m->top); + return m; +} + +mspace create_mspace(size_t capacity, int locked) { + mstate m = 0; + size_t msize = pad_request(sizeof(struct malloc_state)); + init_mparams(); /* Ensure pagesize etc initialized */ + + if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + size_t rs = ((capacity == 0)? mparams.granularity : + (capacity + TOP_FOOT_SIZE + msize)); + size_t tsize = granularity_align(rs); + char* tbase = (char*)(CALL_MMAP(tsize)); + if (tbase != CMFAIL) { + m = init_user_mstate(tbase, tsize); + m->seg.sflags = IS_MMAPPED_BIT; + set_lock(m, locked); + } + } + return (mspace)m; +} + +mspace create_mspace_with_base(void* base, size_t capacity, int locked) { + mstate m = 0; + size_t msize = pad_request(sizeof(struct malloc_state)); + init_mparams(); /* Ensure pagesize etc initialized */ + + if (capacity > msize + TOP_FOOT_SIZE && + capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { + m = init_user_mstate((char*)base, capacity); + m->seg.sflags = EXTERN_BIT; + set_lock(m, locked); + } + return (mspace)m; +} + +size_t destroy_mspace(mspace msp) { + size_t freed = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + msegmentptr sp = &ms->seg; + while (sp != 0) { + char* base = sp->base; + size_t size = sp->size; + flag_t flag = sp->sflags; + sp = sp->next; + if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) && + CALL_MUNMAP(base, size) == 0) + freed += size; + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return freed; +} + +/* + mspace versions of routines are near-clones of the global + versions. This is not so nice but better than the alternatives. +*/ + + +void* mspace_malloc(mspace msp, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (!PREACTION(ms)) { + void* mem; + size_t nb; + if (bytes <= MAX_SMALL_REQUEST) { + bindex_t idx; + binmap_t smallbits; + nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); + idx = small_index(nb); + smallbits = ms->smallmap >> idx; + + if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ + mchunkptr b, p; + idx += ~smallbits & 1; /* Uses next bin if idx empty */ + b = smallbin_at(ms, idx); + p = b->fd; + assert(chunksize(p) == small_index2size(idx)); + unlink_first_small_chunk(ms, b, p, idx); + set_inuse_and_pinuse(ms, p, small_index2size(idx)); + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb > ms->dvsize) { + if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ + mchunkptr b, p, r; + size_t rsize; + bindex_t i; + binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); + binmap_t leastbit = least_bit(leftbits); + compute_bit2idx(leastbit, i); + b = smallbin_at(ms, i); + p = b->fd; + assert(chunksize(p) == small_index2size(i)); + unlink_first_small_chunk(ms, b, p, i); + rsize = small_index2size(i) - nb; + /* Fit here cannot be remainderless if 4byte sizes */ + if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) + set_inuse_and_pinuse(ms, p, small_index2size(i)); + else { + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + r = chunk_plus_offset(p, nb); + set_size_and_pinuse_of_free_chunk(r, rsize); + replace_dv(ms, r, rsize); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + } + else if (bytes >= MAX_REQUEST) + nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ + else { + nb = pad_request(bytes); + if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + } + + if (nb <= ms->dvsize) { + size_t rsize = ms->dvsize - nb; + mchunkptr p = ms->dv; + if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ + mchunkptr r = ms->dv = chunk_plus_offset(p, nb); + ms->dvsize = rsize; + set_size_and_pinuse_of_free_chunk(r, rsize); + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + } + else { /* exhaust dv */ + size_t dvs = ms->dvsize; + ms->dvsize = 0; + ms->dv = 0; + set_inuse_and_pinuse(ms, p, dvs); + } + mem = chunk2mem(p); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + else if (nb < ms->topsize) { /* Split top */ + size_t rsize = ms->topsize -= nb; + mchunkptr p = ms->top; + mchunkptr r = ms->top = chunk_plus_offset(p, nb); + r->head = rsize | PINUSE_BIT; + set_size_and_pinuse_of_inuse_chunk(ms, p, nb); + mem = chunk2mem(p); + check_top_chunk(ms, ms->top); + check_malloced_chunk(ms, mem, nb); + goto postaction; + } + + mem = sys_alloc(ms, nb); + + postaction: + POSTACTION(ms); + return mem; + } + + return 0; +} + +void mspace_free(mspace msp, void* mem) { + if (mem != 0) { + mchunkptr p = mem2chunk(mem); +#if FOOTERS + mstate fm = get_mstate_for(p); +#else /* FOOTERS */ + mstate fm = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(fm)) { + USAGE_ERROR_ACTION(fm, p); + return; + } + if (!PREACTION(fm)) { + check_inuse_chunk(fm, p); + if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { + size_t psize = chunksize(p); + mchunkptr next = chunk_plus_offset(p, psize); + if (!pinuse(p)) { + size_t prevsize = p->prev_foot; + if ((prevsize & IS_MMAPPED_BIT) != 0) { + prevsize &= ~IS_MMAPPED_BIT; + psize += prevsize + MMAP_FOOT_PAD; + if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) + fm->footprint -= psize; + goto postaction; + } + else { + mchunkptr prev = chunk_minus_offset(p, prevsize); + psize += prevsize; + p = prev; + if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ + if (p != fm->dv) { + unlink_chunk(fm, p, prevsize); + } + else if ((next->head & INUSE_BITS) == INUSE_BITS) { + fm->dvsize = psize; + set_free_with_pinuse(p, psize, next); + goto postaction; + } + } + else + goto erroraction; + } + } + + if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { + if (!cinuse(next)) { /* consolidate forward */ + if (next == fm->top) { + size_t tsize = fm->topsize += psize; + fm->top = p; + p->head = tsize | PINUSE_BIT; + if (p == fm->dv) { + fm->dv = 0; + fm->dvsize = 0; + } + if (should_trim(fm, tsize)) + sys_trim(fm, 0); + goto postaction; + } + else if (next == fm->dv) { + size_t dsize = fm->dvsize += psize; + fm->dv = p; + set_size_and_pinuse_of_free_chunk(p, dsize); + goto postaction; + } + else { + size_t nsize = chunksize(next); + psize += nsize; + unlink_chunk(fm, next, nsize); + set_size_and_pinuse_of_free_chunk(p, psize); + if (p == fm->dv) { + fm->dvsize = psize; + goto postaction; + } + } + } + else + set_free_with_pinuse(p, psize, next); + insert_chunk(fm, p, psize); + check_free_chunk(fm, p); + goto postaction; + } + } + erroraction: + USAGE_ERROR_ACTION(fm, p); + postaction: + POSTACTION(fm); + } + } +} + +void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { + void* mem; + size_t req = 0; + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + if (n_elements != 0) { + req = n_elements * elem_size; + if (((n_elements | elem_size) & ~(size_t)0xffff) && + (req / n_elements != elem_size)) + req = MAX_SIZE_T; /* force downstream failure on overflow */ + } + mem = internal_malloc(ms, req); + if (mem != 0 && calloc_must_clear(mem2chunk(mem))) + memset(mem, 0, req); + return mem; +} + +void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { + if (oldmem == 0) + return mspace_malloc(msp, bytes); +#ifdef REALLOC_ZERO_BYTES_FREES + if (bytes == 0) { + mspace_free(msp, oldmem); + return 0; + } +#endif /* REALLOC_ZERO_BYTES_FREES */ + else { +#if FOOTERS + mchunkptr p = mem2chunk(oldmem); + mstate ms = get_mstate_for(p); +#else /* FOOTERS */ + mstate ms = (mstate)msp; +#endif /* FOOTERS */ + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return internal_realloc(ms, oldmem, bytes); + } +} + +void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return internal_memalign(ms, alignment, bytes); +} + +void** mspace_independent_calloc(mspace msp, size_t n_elements, + size_t elem_size, void* chunks[]) { + size_t sz = elem_size; /* serves as 1-element array */ + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, &sz, 3, chunks); +} + +void** mspace_independent_comalloc(mspace msp, size_t n_elements, + size_t sizes[], void* chunks[]) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + return 0; + } + return ialloc(ms, n_elements, sizes, 0, chunks); +} + +int mspace_trim(mspace msp, size_t pad) { + int result = 0; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + if (!PREACTION(ms)) { + result = sys_trim(ms, pad); + POSTACTION(ms); + } + } + else { + USAGE_ERROR_ACTION(ms,ms); + } + return result; +} + +void mspace_malloc_stats(mspace msp) { + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + internal_malloc_stats(ms); + } + else { + USAGE_ERROR_ACTION(ms,ms); + } +} + +size_t mspace_footprint(mspace msp) { + size_t result; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->footprint; + } + USAGE_ERROR_ACTION(ms,ms); + return result; +} + + +size_t mspace_max_footprint(mspace msp) { + size_t result; + mstate ms = (mstate)msp; + if (ok_magic(ms)) { + result = ms->max_footprint; + } + USAGE_ERROR_ACTION(ms,ms); + return result; +} + + +#if !NO_MALLINFO +struct mallinfo mspace_mallinfo(mspace msp) { + mstate ms = (mstate)msp; + if (!ok_magic(ms)) { + USAGE_ERROR_ACTION(ms,ms); + } + return internal_mallinfo(ms); +} +#endif /* NO_MALLINFO */ + +int mspace_mallopt(int param_number, int value) { + return change_mparam(param_number, value); +} + +#endif /* MSPACES */ + +/* -------------------- Alternative MORECORE functions ------------------- */ + +/* + Guidelines for creating a custom version of MORECORE: + + * For best performance, MORECORE should allocate in multiples of pagesize. + * MORECORE may allocate more memory than requested. (Or even less, + but this will usually result in a malloc failure.) + * MORECORE must not allocate memory when given argument zero, but + instead return one past the end address of memory from previous + nonzero call. + * For best performance, consecutive calls to MORECORE with positive + arguments should return increasing addresses, indicating that + space has been contiguously extended. + * Even though consecutive calls to MORECORE need not return contiguous + addresses, it must be OK for malloc'ed chunks to span multiple + regions in those cases where they do happen to be contiguous. + * MORECORE need not handle negative arguments -- it may instead + just return MFAIL when given negative arguments. + Negative arguments are always multiples of pagesize. MORECORE + must not misinterpret negative args as large positive unsigned + args. You can suppress all such calls from even occurring by defining + MORECORE_CANNOT_TRIM, + + As an example alternative MORECORE, here is a custom allocator + kindly contributed for pre-OSX macOS. It uses virtually but not + necessarily physically contiguous non-paged memory (locked in, + present and won't get swapped out). You can use it by uncommenting + this section, adding some #includes, and setting up the appropriate + defines above: + + #define MORECORE osMoreCore + + There is also a shutdown routine that should somehow be called for + cleanup upon program exit. + + #define MAX_POOL_ENTRIES 100 + #define MINIMUM_MORECORE_SIZE (64 * 1024U) + static int next_os_pool; + void *our_os_pools[MAX_POOL_ENTRIES]; + + void *osMoreCore(int size) + { + void *ptr = 0; + static void *sbrk_top = 0; + + if (size > 0) + { + if (size < MINIMUM_MORECORE_SIZE) + size = MINIMUM_MORECORE_SIZE; + if (CurrentExecutionLevel() == kTaskLevel) + ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); + if (ptr == 0) + { + return (void *) MFAIL; + } + // save ptrs so they can be freed during cleanup + our_os_pools[next_os_pool] = ptr; + next_os_pool++; + ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); + sbrk_top = (char *) ptr + size; + return ptr; + } + else if (size < 0) + { + // we don't currently support shrink behavior + return (void *) MFAIL; + } + else + { + return sbrk_top; + } + } + + // cleanup any allocated memory pools + // called as last thing before shutting down driver + + void osCleanupMem(void) + { + void **ptr; + + for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) + if (*ptr) + { + PoolDeallocate(*ptr); + *ptr = 0; + } + } + +*/ + + +/* ----------------------------------------------------------------------- +History: + V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) + * Add max_footprint functions + * Ensure all appropriate literals are size_t + * Fix conditional compilation problem for some #define settings + * Avoid concatenating segments with the one provided + in create_mspace_with_base + * Rename some variables to avoid compiler shadowing warnings + * Use explicit lock initialization. + * Better handling of sbrk interference. + * Simplify and fix segment insertion, trimming and mspace_destroy + * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x + * Thanks especially to Dennis Flanagan for help on these. + + V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) + * Fix memalign brace error. + + V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) + * Fix improper #endif nesting in C++ + * Add explicit casts needed for C++ + + V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) + * Use trees for large bins + * Support mspaces + * Use segments to unify sbrk-based and mmap-based system allocation, + removing need for emulation on most platforms without sbrk. + * Default safety checks + * Optional footer checks. Thanks to William Robertson for the idea. + * Internal code refactoring + * Incorporate suggestions and platform-specific changes. + Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, + Aaron Bachmann, Emery Berger, and others. + * Speed up non-fastbin processing enough to remove fastbins. + * Remove useless cfree() to avoid conflicts with other apps. + * Remove internal memcpy, memset. Compilers handle builtins better. + * Remove some options that no one ever used and rename others. + + V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + * Fix malloc_state bitmap array misdeclaration + + V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) + * Allow tuning of FIRST_SORTED_BIN_SIZE + * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. + * Better detection and support for non-contiguousness of MORECORE. + Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger + * Bypass most of malloc if no frees. Thanks To Emery Berger. + * Fix freeing of old top non-contiguous chunk im sysmalloc. + * Raised default trim and map thresholds to 256K. + * Fix mmap-related #defines. Thanks to Lubos Lunak. + * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. + * Branch-free bin calculation + * Default trim and mmap thresholds now 256K. + + V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) + * Introduce independent_comalloc and independent_calloc. + Thanks to Michael Pachos for motivation and help. + * Make optional .h file available + * Allow > 2GB requests on 32bit systems. + * new WIN32 sbrk, mmap, munmap, lock code from <Walter@GeNeSys-e.de>. + Thanks also to Andreas Mueller <a.mueller at paradatec.de>, + and Anonymous. + * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for + helping test this.) + * memalign: check alignment arg + * realloc: don't try to shift chunks backwards, since this + leads to more fragmentation in some programs and doesn't + seem to help in any others. + * Collect all cases in malloc requiring system memory into sysmalloc + * Use mmap as backup to sbrk + * Place all internal state in malloc_state + * Introduce fastbins (although similar to 2.5.1) + * Many minor tunings and cosmetic improvements + * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK + * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS + Thanks to Tony E. Bennett <tbennett@nvidia.com> and others. + * Include errno.h to support default failure action. + + V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) + * return null for negative arguments + * Added Several WIN32 cleanups from Martin C. Fong <mcfong at yahoo.com> + * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' + (e.g. WIN32 platforms) + * Cleanup header file inclusion for WIN32 platforms + * Cleanup code to avoid Microsoft Visual C++ compiler complaints + * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing + memory allocation routines + * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) + * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to + usage of 'assert' in non-WIN32 code + * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to + avoid infinite loop + * Always call 'fREe()' rather than 'free()' + + V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) + * Fixed ordering problem with boundary-stamping + + V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) + * Added pvalloc, as recommended by H.J. Liu + * Added 64bit pointer support mainly from Wolfram Gloger + * Added anonymously donated WIN32 sbrk emulation + * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen + * malloc_extend_top: fix mask error that caused wastage after + foreign sbrks + * Add linux mremap support code from HJ Liu + + V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) + * Integrated most documentation with the code. + * Add support for mmap, with help from + Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Use last_remainder in more cases. + * Pack bins using idea from colin@nyx10.cs.du.edu + * Use ordered bins instead of best-fit threshhold + * Eliminate block-local decls to simplify tracing and debugging. + * Support another case of realloc via move into top + * Fix error occuring when initial sbrk_base not word-aligned. + * Rely on page size for units instead of SBRK_UNIT to + avoid surprises about sbrk alignment conventions. + * Add mallinfo, mallopt. Thanks to Raymond Nijssen + (raymond@es.ele.tue.nl) for the suggestion. + * Add `pad' argument to malloc_trim and top_pad mallopt parameter. + * More precautions for cases where other routines call sbrk, + courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). + * Added macros etc., allowing use in linux libc from + H.J. Lu (hjl@gnu.ai.mit.edu) + * Inverted this history list + + V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) + * Re-tuned and fixed to behave more nicely with V2.6.0 changes. + * Removed all preallocation code since under current scheme + the work required to undo bad preallocations exceeds + the work saved in good cases for most test programs. + * No longer use return list or unconsolidated bins since + no scheme using them consistently outperforms those that don't + given above changes. + * Use best fit for very large chunks to prevent some worst-cases. + * Added some support for debugging + + V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) + * Removed footers when chunks are in use. Thanks to + Paul Wilson (wilson@cs.texas.edu) for the suggestion. + + V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) + * Added malloc_trim, with help from Wolfram Gloger + (wmglo@Dent.MED.Uni-Muenchen.DE). + + V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) + + V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) + * realloc: try to expand in both directions + * malloc: swap order of clean-bin strategy; + * realloc: only conditionally expand backwards + * Try not to scavenge used bins + * Use bin counts as a guide to preallocation + * Occasionally bin return list chunks in first scan + * Add a few optimizations from colin@nyx10.cs.du.edu + + V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) + * faster bin computation & slightly different binning + * merged all consolidations to one part of malloc proper + (eliminating old malloc_find_space & malloc_clean_bin) + * Scan 2 returns chunks (not just 1) + * Propagate failure in realloc if malloc returns 0 + * Add stuff to allow compilation on non-ANSI compilers + from kpv@research.att.com + + V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) + * removed potential for odd address access in prev_chunk + * removed dependency on getpagesize.h + * misc cosmetics and a bit more internal documentation + * anticosmetics: mangled names in macros to evade debugger strangeness + * tested on sparc, hp-700, dec-mips, rs6000 + with gcc & native cc (hp, dec only) allowing + Detlefs & Zorn comparison study (in SIGPLAN Notices.) + + Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) + * Based loosely on libg++-1.2X malloc. (It retains some of the overall + structure of old version, but most details differ.) + +*/ + +#endif /* !HAVE_MALLOC */ diff --git a/3rdparty/SDL/src/stdlib/SDL_qsort.c b/3rdparty/SDL/src/stdlib/SDL_qsort.c new file mode 100644 index 0000000..2b5abea --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_qsort.c @@ -0,0 +1,443 @@ +/* qsort.c + * (c) 1998 Gareth McCaughan + * + * This is a drop-in replacement for the C library's |qsort()| routine. + * + * Features: + * - Median-of-three pivoting (and more) + * - Truncation and final polishing by a single insertion sort + * - Early truncation when no swaps needed in pivoting step + * - Explicit recursion, guaranteed not to overflow + * - A few little wrinkles stolen from the GNU |qsort()|. + * - separate code for non-aligned / aligned / word-size objects + * + * This code may be reproduced freely provided + * - this file is retained unaltered apart from minor + * changes for portability and efficiency + * - no changes are made to this comment + * - any changes that *are* made are clearly flagged + * - the _ID string below is altered by inserting, after + * the date, the string " altered" followed at your option + * by other material. (Exceptions: you may change the name + * of the exported routine without changing the ID string. + * You may change the values of the macros TRUNC_* and + * PIVOT_THRESHOLD without changing the ID string, provided + * they remain constants with TRUNC_nonaligned, TRUNC_aligned + * and TRUNC_words/WORD_BYTES between 8 and 24, and + * PIVOT_THRESHOLD between 32 and 200.) + * + * You may use it in anything you like; you may make money + * out of it; you may distribute it in object form or as + * part of an executable without including source code; + * you don't have to credit me. (But it would be nice if + * you did.) + * + * If you find problems with this code, or find ways of + * making it significantly faster, please let me know! + * My e-mail address, valid as of early 1998 and certainly + * OK for at least the next 18 months, is + * gjm11@dpmms.cam.ac.uk + * Thanks! + * + * Gareth McCaughan Peterhouse Cambridge 1998 + */ +#include "SDL_config.h" + +/* +#include <assert.h> +#include <stdlib.h> +#include <string.h> +*/ +#include "SDL_stdinc.h" + +#ifdef assert +#undef assert +#endif +#define assert(X) +#ifdef malloc +#undef malloc +#endif +#define malloc SDL_malloc +#ifdef free +#undef free +#endif +#define free SDL_free +#ifdef memcpy +#undef memcpy +#endif +#define memcpy SDL_memcpy +#ifdef memmove +#undef memmove +#endif +#define memmove SDL_memmove +#ifdef qsort +#undef qsort +#endif +#define qsort SDL_qsort + + +#ifndef HAVE_QSORT + +static char _ID[]="<qsort.c gjm 1.12 1998-03-19>"; + +/* How many bytes are there per word? (Must be a power of 2, + * and must in fact equal sizeof(int).) + */ +#define WORD_BYTES sizeof(int) + +/* How big does our stack need to be? Answer: one entry per + * bit in a |size_t|. + */ +#define STACK_SIZE (8*sizeof(size_t)) + +/* Different situations have slightly different requirements, + * and we make life epsilon easier by using different truncation + * points for the three different cases. + * So far, I have tuned TRUNC_words and guessed that the same + * value might work well for the other two cases. Of course + * what works well on my machine might work badly on yours. + */ +#define TRUNC_nonaligned 12 +#define TRUNC_aligned 12 +#define TRUNC_words 12*WORD_BYTES /* nb different meaning */ + +/* We use a simple pivoting algorithm for shortish sub-arrays + * and a more complicated one for larger ones. The threshold + * is PIVOT_THRESHOLD. + */ +#define PIVOT_THRESHOLD 40 + +typedef struct { char * first; char * last; } stack_entry; +#define pushLeft {stack[stacktop].first=ffirst;stack[stacktop++].last=last;} +#define pushRight {stack[stacktop].first=first;stack[stacktop++].last=llast;} +#define doLeft {first=ffirst;llast=last;continue;} +#define doRight {ffirst=first;last=llast;continue;} +#define pop {if (--stacktop<0) break;\ + first=ffirst=stack[stacktop].first;\ + last=llast=stack[stacktop].last;\ + continue;} + +/* Some comments on the implementation. + * 1. When we finish partitioning the array into "low" + * and "high", we forget entirely about short subarrays, + * because they'll be done later by insertion sort. + * Doing lots of little insertion sorts might be a win + * on large datasets for locality-of-reference reasons, + * but it makes the code much nastier and increases + * bookkeeping overhead. + * 2. We always save the shorter and get to work on the + * longer. This guarantees that every time we push + * an item onto the stack its size is <= 1/2 of that + * of its parent; so the stack can't need more than + * log_2(max-array-size) entries. + * 3. We choose a pivot by looking at the first, last + * and middle elements. We arrange them into order + * because it's easy to do that in conjunction with + * choosing the pivot, and it makes things a little + * easier in the partitioning step. Anyway, the pivot + * is the middle of these three. It's still possible + * to construct datasets where the algorithm takes + * time of order n^2, but it simply never happens in + * practice. + * 3' Newsflash: On further investigation I find that + * it's easy to construct datasets where median-of-3 + * simply isn't good enough. So on large-ish subarrays + * we do a more sophisticated pivoting: we take three + * sets of 3 elements, find their medians, and then + * take the median of those. + * 4. We copy the pivot element to a separate place + * because that way we can always do our comparisons + * directly against a pointer to that separate place, + * and don't have to wonder "did we move the pivot + * element?". This makes the inner loop better. + * 5. It's possible to make the pivoting even more + * reliable by looking at more candidates when n + * is larger. (Taking this to its logical conclusion + * results in a variant of quicksort that doesn't + * have that n^2 worst case.) However, the overhead + * from the extra bookkeeping means that it's just + * not worth while. + * 6. This is pretty clean and portable code. Here are + * all the potential portability pitfalls and problems + * I know of: + * - In one place (the insertion sort) I construct + * a pointer that points just past the end of the + * supplied array, and assume that (a) it won't + * compare equal to any pointer within the array, + * and (b) it will compare equal to a pointer + * obtained by stepping off the end of the array. + * These might fail on some segmented architectures. + * - I assume that there are 8 bits in a |char| when + * computing the size of stack needed. This would + * fail on machines with 9-bit or 16-bit bytes. + * - I assume that if |((int)base&(sizeof(int)-1))==0| + * and |(size&(sizeof(int)-1))==0| then it's safe to + * get at array elements via |int*|s, and that if + * actually |size==sizeof(int)| as well then it's + * safe to treat the elements as |int|s. This might + * fail on systems that convert pointers to integers + * in non-standard ways. + * - I assume that |8*sizeof(size_t)<=INT_MAX|. This + * would be false on a machine with 8-bit |char|s, + * 16-bit |int|s and 4096-bit |size_t|s. :-) + */ + +/* The recursion logic is the same in each case: */ +#define Recurse(Trunc) \ + { size_t l=last-ffirst,r=llast-first; \ + if (l<Trunc) { \ + if (r>=Trunc) doRight \ + else pop \ + } \ + else if (l<=r) { pushLeft; doRight } \ + else if (r>=Trunc) { pushRight; doLeft }\ + else doLeft \ + } + +/* and so is the pivoting logic: */ +#define Pivot(swapper,sz) \ + if ((size_t)(last-first)>PIVOT_THRESHOLD*sz) mid=pivot_big(first,mid,last,sz,compare);\ + else { \ + if (compare(first,mid)<0) { \ + if (compare(mid,last)>0) { \ + swapper(mid,last); \ + if (compare(first,mid)>0) swapper(first,mid);\ + } \ + } \ + else { \ + if (compare(mid,last)>0) swapper(first,last)\ + else { \ + swapper(first,mid); \ + if (compare(mid,last)>0) swapper(mid,last);\ + } \ + } \ + first+=sz; last-=sz; \ + } + +#ifdef DEBUG_QSORT +#include <stdio.h> +#endif + +/* and so is the partitioning logic: */ +#define Partition(swapper,sz) { \ + int swapped=0; \ + do { \ + while (compare(first,pivot)<0) first+=sz; \ + while (compare(pivot,last)<0) last-=sz; \ + if (first<last) { \ + swapper(first,last); swapped=1; \ + first+=sz; last-=sz; } \ + else if (first==last) { first+=sz; last-=sz; break; }\ + } while (first<=last); \ + if (!swapped) pop \ +} + +/* and so is the pre-insertion-sort operation of putting + * the smallest element into place as a sentinel. + * Doing this makes the inner loop nicer. I got this + * idea from the GNU implementation of qsort(). + */ +#define PreInsertion(swapper,limit,sz) \ + first=base; \ + last=first + (nmemb>limit ? limit : nmemb-1)*sz;\ + while (last!=base) { \ + if (compare(first,last)>0) first=last; \ + last-=sz; } \ + if (first!=base) swapper(first,(char*)base); + +/* and so is the insertion sort, in the first two cases: */ +#define Insertion(swapper) \ + last=((char*)base)+nmemb*size; \ + for (first=((char*)base)+size;first!=last;first+=size) { \ + char *test; \ + /* Find the right place for |first|. \ + * My apologies for var reuse. */ \ + for (test=first-size;compare(test,first)>0;test-=size) ; \ + test+=size; \ + if (test!=first) { \ + /* Shift everything in [test,first) \ + * up by one, and place |first| \ + * where |test| is. */ \ + memcpy(pivot,first,size); \ + memmove(test+size,test,first-test); \ + memcpy(test,pivot,size); \ + } \ + } + +#define SWAP_nonaligned(a,b) { \ + register char *aa=(a),*bb=(b); \ + register size_t sz=size; \ + do { register char t=*aa; *aa++=*bb; *bb++=t; } while (--sz); } + +#define SWAP_aligned(a,b) { \ + register int *aa=(int*)(a),*bb=(int*)(b); \ + register size_t sz=size; \ + do { register int t=*aa;*aa++=*bb; *bb++=t; } while (sz-=WORD_BYTES); } + +#define SWAP_words(a,b) { \ + register int t=*((int*)a); *((int*)a)=*((int*)b); *((int*)b)=t; } + +/* ---------------------------------------------------------------------- */ + +static char * pivot_big(char *first, char *mid, char *last, size_t size, + int compare(const void *, const void *)) { + size_t d=(((last-first)/size)>>3)*size; + char *m1,*m2,*m3; + { char *a=first, *b=first+d, *c=first+2*d; +#ifdef DEBUG_QSORT +fprintf(stderr,"< %d %d %d\n",*(int*)a,*(int*)b,*(int*)c); +#endif + m1 = compare(a,b)<0 ? + (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a)) + : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b)); + } + { char *a=mid-d, *b=mid, *c=mid+d; +#ifdef DEBUG_QSORT +fprintf(stderr,". %d %d %d\n",*(int*)a,*(int*)b,*(int*)c); +#endif + m2 = compare(a,b)<0 ? + (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a)) + : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b)); + } + { char *a=last-2*d, *b=last-d, *c=last; +#ifdef DEBUG_QSORT +fprintf(stderr,"> %d %d %d\n",*(int*)a,*(int*)b,*(int*)c); +#endif + m3 = compare(a,b)<0 ? + (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a)) + : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b)); + } +#ifdef DEBUG_QSORT +fprintf(stderr,"-> %d %d %d\n",*(int*)m1,*(int*)m2,*(int*)m3); +#endif + return compare(m1,m2)<0 ? + (compare(m2,m3)<0 ? m2 : (compare(m1,m3)<0 ? m3 : m1)) + : (compare(m1,m3)<0 ? m1 : (compare(m2,m3)<0 ? m3 : m2)); +} + +/* ---------------------------------------------------------------------- */ + +static void qsort_nonaligned(void *base, size_t nmemb, size_t size, + int (*compare)(const void *, const void *)) { + + stack_entry stack[STACK_SIZE]; + int stacktop=0; + char *first,*last; + char *pivot=malloc(size); + size_t trunc=TRUNC_nonaligned*size; + assert(pivot!=0); + + first=(char*)base; last=first+(nmemb-1)*size; + + if ((size_t)(last-first)>trunc) { + char *ffirst=first, *llast=last; + while (1) { + /* Select pivot */ + { char * mid=first+size*((last-first)/size >> 1); + Pivot(SWAP_nonaligned,size); + memcpy(pivot,mid,size); + } + /* Partition. */ + Partition(SWAP_nonaligned,size); + /* Prepare to recurse/iterate. */ + Recurse(trunc) + } + } + PreInsertion(SWAP_nonaligned,TRUNC_nonaligned,size); + Insertion(SWAP_nonaligned); + free(pivot); +} + +static void qsort_aligned(void *base, size_t nmemb, size_t size, + int (*compare)(const void *, const void *)) { + + stack_entry stack[STACK_SIZE]; + int stacktop=0; + char *first,*last; + char *pivot=malloc(size); + size_t trunc=TRUNC_aligned*size; + assert(pivot!=0); + + first=(char*)base; last=first+(nmemb-1)*size; + + if ((size_t)(last-first)>trunc) { + char *ffirst=first,*llast=last; + while (1) { + /* Select pivot */ + { char * mid=first+size*((last-first)/size >> 1); + Pivot(SWAP_aligned,size); + memcpy(pivot,mid,size); + } + /* Partition. */ + Partition(SWAP_aligned,size); + /* Prepare to recurse/iterate. */ + Recurse(trunc) + } + } + PreInsertion(SWAP_aligned,TRUNC_aligned,size); + Insertion(SWAP_aligned); + free(pivot); +} + +static void qsort_words(void *base, size_t nmemb, + int (*compare)(const void *, const void *)) { + + stack_entry stack[STACK_SIZE]; + int stacktop=0; + char *first,*last; + char *pivot=malloc(WORD_BYTES); + assert(pivot!=0); + + first=(char*)base; last=first+(nmemb-1)*WORD_BYTES; + + if (last-first>TRUNC_words) { + char *ffirst=first, *llast=last; + while (1) { +#ifdef DEBUG_QSORT +fprintf(stderr,"Doing %d:%d: ", + (first-(char*)base)/WORD_BYTES, + (last-(char*)base)/WORD_BYTES); +#endif + /* Select pivot */ + { char * mid=first+WORD_BYTES*((last-first) / (2*WORD_BYTES)); + Pivot(SWAP_words,WORD_BYTES); + *(int*)pivot=*(int*)mid; + } +#ifdef DEBUG_QSORT +fprintf(stderr,"pivot=%d\n",*(int*)pivot); +#endif + /* Partition. */ + Partition(SWAP_words,WORD_BYTES); + /* Prepare to recurse/iterate. */ + Recurse(TRUNC_words) + } + } + PreInsertion(SWAP_words,(TRUNC_words/WORD_BYTES),WORD_BYTES); + /* Now do insertion sort. */ + last=((char*)base)+nmemb*WORD_BYTES; + for (first=((char*)base)+WORD_BYTES;first!=last;first+=WORD_BYTES) { + /* Find the right place for |first|. My apologies for var reuse */ + int *pl=(int*)(first-WORD_BYTES),*pr=(int*)first; + *(int*)pivot=*(int*)first; + for (;compare(pl,pivot)>0;pr=pl,--pl) { + *pr=*pl; } + if (pr!=(int*)first) *pr=*(int*)pivot; + } + free(pivot); +} + +/* ---------------------------------------------------------------------- */ + +void qsort(void *base, size_t nmemb, size_t size, + int (*compare)(const void *, const void *)) { + + if (nmemb<=1) return; + if (((uintptr_t)base|size)&(WORD_BYTES-1)) + qsort_nonaligned(base,nmemb,size,compare); + else if (size!=WORD_BYTES) + qsort_aligned(base,nmemb,size,compare); + else + qsort_words(base,nmemb,compare); +} + +#endif /* !HAVE_QSORT */ diff --git a/3rdparty/SDL/src/stdlib/SDL_stdlib.c b/3rdparty/SDL/src/stdlib/SDL_stdlib.c new file mode 100644 index 0000000..5c88fe7 --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_stdlib.c @@ -0,0 +1,620 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file contains portable stdlib functions for SDL */ + +#include "SDL_stdinc.h" + +#ifndef HAVE_LIBC +/* These are some C runtime intrinsics that need to be defined */ + +#if defined(_MSC_VER) + +#ifndef __FLTUSED__ +#define __FLTUSED__ +#ifdef __cplusplus + extern "C" +#endif + __declspec(selectany) int _fltused=1; +#endif + +/* Float to long */ +void __declspec(naked) _ftol() +{ + __asm { + push ebp + mov ebp,esp + sub esp,20h + and esp,0FFFFFFF0h + fld st(0) + fst dword ptr [esp+18h] + fistp qword ptr [esp+10h] + fild qword ptr [esp+10h] + mov edx,dword ptr [esp+18h] + mov eax,dword ptr [esp+10h] + test eax,eax + je integer_QnaN_or_zero +arg_is_not_integer_QnaN: + fsubp st(1),st + test edx,edx + jns positive + fstp dword ptr [esp] + mov ecx,dword ptr [esp] + xor ecx,80000000h + add ecx,7FFFFFFFh + adc eax,0 + mov edx,dword ptr [esp+14h] + adc edx,0 + jmp localexit +positive: + fstp dword ptr [esp] + mov ecx,dword ptr [esp] + add ecx,7FFFFFFFh + sbb eax,0 + mov edx,dword ptr [esp+14h] + sbb edx,0 + jmp localexit +integer_QnaN_or_zero: + mov edx,dword ptr [esp+14h] + test edx,7FFFFFFFh + jne arg_is_not_integer_QnaN + fstp dword ptr [esp+18h] + fstp dword ptr [esp+18h] +localexit: + leave + ret + } +} +void __declspec(naked) _ftol2_sse() +{ + _ftol(); +} + +/* 64-bit math operators for 32-bit systems */ +void __declspec(naked) _allmul() +{ + __asm { + push ebp + mov ebp,esp + push edi + push esi + push ebx + sub esp,0Ch + mov eax,dword ptr [ebp+10h] + mov edi,dword ptr [ebp+8] + mov ebx,eax + mov esi,eax + sar esi,1Fh + mov eax,dword ptr [ebp+8] + mul ebx + imul edi,esi + mov ecx,edx + mov dword ptr [ebp-18h],eax + mov edx,dword ptr [ebp+0Ch] + add ecx,edi + imul ebx,edx + mov eax,dword ptr [ebp-18h] + lea ebx,[ebx+ecx] + mov dword ptr [ebp-14h],ebx + mov edx,dword ptr [ebp-14h] + add esp,0Ch + pop ebx + pop esi + pop edi + pop ebp + ret + } +} +void __declspec(naked) _alldiv() +{ + __asm { + push edi + push esi + push ebx + xor edi,edi + mov eax,dword ptr [esp+14h] + or eax,eax + jge L1 + inc edi + mov edx,dword ptr [esp+10h] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+14h],eax + mov dword ptr [esp+10h],edx +L1: + mov eax,dword ptr [esp+1Ch] + or eax,eax + jge L2 + inc edi + mov edx,dword ptr [esp+18h] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+1Ch],eax + mov dword ptr [esp+18h],edx +L2: + or eax,eax + jne L3 + mov ecx,dword ptr [esp+18h] + mov eax,dword ptr [esp+14h] + xor edx,edx + div ecx + mov ebx,eax + mov eax,dword ptr [esp+10h] + div ecx + mov edx,ebx + jmp L4 +L3: + mov ebx,eax + mov ecx,dword ptr [esp+18h] + mov edx,dword ptr [esp+14h] + mov eax,dword ptr [esp+10h] +L5: + shr ebx,1 + rcr ecx,1 + shr edx,1 + rcr eax,1 + or ebx,ebx + jne L5 + div ecx + mov esi,eax + mul dword ptr [esp+1Ch] + mov ecx,eax + mov eax,dword ptr [esp+18h] + mul esi + add edx,ecx + jb L6 + cmp edx,dword ptr [esp+14h] + ja L6 + jb L7 + cmp eax,dword ptr [esp+10h] + jbe L7 +L6: + dec esi +L7: + xor edx,edx + mov eax,esi +L4: + dec edi + jne L8 + neg edx + neg eax + sbb edx,0 +L8: + pop ebx + pop esi + pop edi + ret 10h + } +} +void __declspec(naked) _aulldiv() +{ + __asm { + push ebx + push esi + mov eax,dword ptr [esp+18h] + or eax,eax + jne L1 + mov ecx,dword ptr [esp+14h] + mov eax,dword ptr [esp+10h] + xor edx,edx + div ecx + mov ebx,eax + mov eax,dword ptr [esp+0Ch] + div ecx + mov edx,ebx + jmp L2 +L1: + mov ecx,eax + mov ebx,dword ptr [esp+14h] + mov edx,dword ptr [esp+10h] + mov eax,dword ptr [esp+0Ch] +L3: + shr ecx,1 + rcr ebx,1 + shr edx,1 + rcr eax,1 + or ecx,ecx + jne L3 + div ebx + mov esi,eax + mul dword ptr [esp+18h] + mov ecx,eax + mov eax,dword ptr [esp+14h] + mul esi + add edx,ecx + jb L4 + cmp edx,dword ptr [esp+10h] + ja L4 + jb L5 + cmp eax,dword ptr [esp+0Ch] + jbe L5 +L4: + dec esi +L5: + xor edx,edx + mov eax,esi +L2: + pop esi + pop ebx + ret 10h + } +} +void __declspec(naked) _allrem() +{ + __asm { + push ebx + push edi + xor edi,edi + mov eax,dword ptr [esp+10h] + or eax,eax + jge L1 + inc edi + mov edx,dword ptr [esp+0Ch] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+10h],eax + mov dword ptr [esp+0Ch],edx +L1: + mov eax,dword ptr [esp+18h] + or eax,eax + jge L2 + mov edx,dword ptr [esp+14h] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+18h],eax + mov dword ptr [esp+14h],edx +L2: + or eax,eax + jne L3 + mov ecx,dword ptr [esp+14h] + mov eax,dword ptr [esp+10h] + xor edx,edx + div ecx + mov eax,dword ptr [esp+0Ch] + div ecx + mov eax,edx + xor edx,edx + dec edi + jns L4 + jmp L8 +L3: + mov ebx,eax + mov ecx,dword ptr [esp+14h] + mov edx,dword ptr [esp+10h] + mov eax,dword ptr [esp+0Ch] +L5: + shr ebx,1 + rcr ecx,1 + shr edx,1 + rcr eax,1 + or ebx,ebx + jne L5 + div ecx + mov ecx,eax + mul dword ptr [esp+18h] + xchg eax,ecx + mul dword ptr [esp+14h] + add edx,ecx + jb L6 + cmp edx,dword ptr [esp+10h] + ja L6 + jb L7 + cmp eax,dword ptr [esp+0Ch] + jbe L7 +L6: + sub eax,dword ptr [esp+14h] + sbb edx,dword ptr [esp+18h] +L7: + sub eax,dword ptr [esp+0Ch] + sbb edx,dword ptr [esp+10h] + dec edi + jns L8 +L4: + neg edx + neg eax + sbb edx,0 +L8: + pop edi + pop ebx + ret 10h + } +} +void __declspec(naked) _aullrem() +{ + __asm { + push ebx + mov eax,dword ptr [esp+14h] + or eax,eax + jne L1 + mov ecx,dword ptr [esp+10h] + mov eax,dword ptr [esp+0Ch] + xor edx,edx + div ecx + mov eax,dword ptr [esp+8] + div ecx + mov eax,edx + xor edx,edx + jmp L2 +L1: + mov ecx,eax + mov ebx,dword ptr [esp+10h] + mov edx,dword ptr [esp+0Ch] + mov eax,dword ptr [esp+8] +L3: + shr ecx,1 + rcr ebx,1 + shr edx,1 + rcr eax,1 + or ecx,ecx + jne L3 + div ebx + mov ecx,eax + mul dword ptr [esp+14h] + xchg eax,ecx + mul dword ptr [esp+10h] + add edx,ecx + jb L4 + cmp edx,dword ptr [esp+0Ch] + ja L4 + jb L5 + cmp eax,dword ptr [esp+8] + jbe L5 +L4: + sub eax,dword ptr [esp+10h] + sbb edx,dword ptr [esp+14h] +L5: + sub eax,dword ptr [esp+8] + sbb edx,dword ptr [esp+0Ch] + neg edx + neg eax + sbb edx,0 +L2: + pop ebx + ret 10h + } +} +void __declspec(naked) _alldvrm() +{ + __asm { + push edi + push esi + push ebp + xor edi,edi + xor ebp,ebp + mov eax,dword ptr [esp+14h] + or eax,eax + jge L1 + inc edi + inc ebp + mov edx,dword ptr [esp+10h] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+14h],eax + mov dword ptr [esp+10h],edx +L1: + mov eax,dword ptr [esp+1Ch] + or eax,eax + jge L2 + inc edi + mov edx,dword ptr [esp+18h] + neg eax + neg edx + sbb eax,0 + mov dword ptr [esp+1Ch],eax + mov dword ptr [esp+18h],edx +L2: + or eax,eax + jne L3 + mov ecx,dword ptr [esp+18h] + mov eax,dword ptr [esp+14h] + xor edx,edx + div ecx + mov ebx,eax + mov eax,dword ptr [esp+10h] + div ecx + mov esi,eax + mov eax,ebx + mul dword ptr [esp+18h] + mov ecx,eax + mov eax,esi + mul dword ptr [esp+18h] + add edx,ecx + jmp L4 +L3: + mov ebx,eax + mov ecx,dword ptr [esp+18h] + mov edx,dword ptr [esp+14h] + mov eax,dword ptr [esp+10h] +L5: + shr ebx,1 + rcr ecx,1 + shr edx,1 + rcr eax,1 + or ebx,ebx + jne L5 + div ecx + mov esi,eax + mul dword ptr [esp+1Ch] + mov ecx,eax + mov eax,dword ptr [esp+18h] + mul esi + add edx,ecx + jb L6 + cmp edx,dword ptr [esp+14h] + ja L6 + jb L7 + cmp eax,dword ptr [esp+10h] + jbe L7 +L6: + dec esi + sub eax,dword ptr [esp+18h] + sbb edx,dword ptr [esp+1Ch] +L7: + xor ebx,ebx +L4: + sub eax,dword ptr [esp+10h] + sbb edx,dword ptr [esp+14h] + dec ebp + jns L9 + neg edx + neg eax + sbb edx,0 +L9: + mov ecx,edx + mov edx,ebx + mov ebx,ecx + mov ecx,eax + mov eax,esi + dec edi + jne L8 + neg edx + neg eax + sbb edx,0 +L8: + pop ebp + pop esi + pop edi + ret 10h + } +} +void __declspec(naked) _aulldvrm() +{ + __asm { + push esi + mov eax,dword ptr [esp+14h] + or eax,eax + jne L1 + mov ecx,dword ptr [esp+10h] + mov eax,dword ptr [esp+0Ch] + xor edx,edx + div ecx + mov ebx,eax + mov eax,dword ptr [esp+8] + div ecx + mov esi,eax + mov eax,ebx + mul dword ptr [esp+10h] + mov ecx,eax + mov eax,esi + mul dword ptr [esp+10h] + add edx,ecx + jmp L2 +L1: + mov ecx,eax + mov ebx,dword ptr [esp+10h] + mov edx,dword ptr [esp+0Ch] + mov eax,dword ptr [esp+8] +L3: + shr ecx,1 + rcr ebx,1 + shr edx,1 + rcr eax,1 + or ecx,ecx + jne L3 + div ebx + mov esi,eax + mul dword ptr [esp+14h] + mov ecx,eax + mov eax,dword ptr [esp+10h] + mul esi + add edx,ecx + jb L4 + cmp edx,dword ptr [esp+0Ch] + ja L4 + jb L5 + cmp eax,dword ptr [esp+8] + jbe L5 +L4: + dec esi + sub eax,dword ptr [esp+10h] + sbb edx,dword ptr [esp+14h] +L5: + xor ebx,ebx +L2: + sub eax,dword ptr [esp+8] + sbb edx,dword ptr [esp+0Ch] + neg edx + neg eax + sbb edx,0 + mov ecx,edx + mov edx,ebx + mov ebx,ecx + mov ecx,eax + mov eax,esi + pop esi + ret 10h + } +} +void __declspec(naked) _allshl() +{ + __asm { + cmp cl,40h + jae RETZERO + cmp cl,20h + jae MORE32 + shld edx,eax,cl + shl eax,cl + ret +MORE32: + mov edx,eax + xor eax,eax + and cl,1Fh + shl edx,cl + ret +RETZERO: + xor eax,eax + xor edx,edx + ret + } +} +void __declspec(naked) _aullshr() +{ + __asm { + cmp cl,40h + jae RETZERO + cmp cl,20h + jae MORE32 + shrd eax,edx,cl + shr edx,cl + ret +MORE32: + mov eax,edx + xor edx,edx + and cl,1Fh + shr eax,cl + ret +RETZERO: + xor eax,eax + xor edx,edx + ret + } +} + +#endif /* MSC_VER */ + +#endif /* !HAVE_LIBC */ diff --git a/3rdparty/SDL/src/stdlib/SDL_string.c b/3rdparty/SDL/src/stdlib/SDL_string.c new file mode 100644 index 0000000..550a623 --- /dev/null +++ b/3rdparty/SDL/src/stdlib/SDL_string.c @@ -0,0 +1,1248 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This file contains portable string manipulation functions for SDL */ + +#include "SDL_stdinc.h" + + +#define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) +#define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) + +#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL) +static size_t SDL_ScanLong(const char *text, int radix, long *valuep) +{ + const char *textstart = text; + long value = 0; + SDL_bool negative = SDL_FALSE; + + if ( *text == '-' ) { + negative = SDL_TRUE; + ++text; + } + if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { + text += 2; + } + for ( ; ; ) { + int v; + if ( SDL_isdigit((unsigned char) *text) ) { + v = *text - '0'; + } else if ( radix == 16 && SDL_isupperhex(*text) ) { + v = 10 + (*text - 'A'); + } else if ( radix == 16 && SDL_islowerhex(*text) ) { + v = 10 + (*text - 'a'); + } else { + break; + } + value *= radix; + value += v; + ++text; + } + if ( valuep ) { + if ( negative && value ) { + *valuep = -value; + } else { + *valuep = value; + } + } + return (text - textstart); +} +#endif + +#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD) +static size_t SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep) +{ + const char *textstart = text; + unsigned long value = 0; + + if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { + text += 2; + } + for ( ; ; ) { + int v; + if ( SDL_isdigit((unsigned char) *text) ) { + v = *text - '0'; + } else if ( radix == 16 && SDL_isupperhex(*text) ) { + v = 10 + (*text - 'A'); + } else if ( radix == 16 && SDL_islowerhex(*text) ) { + v = 10 + (*text - 'a'); + } else { + break; + } + value *= radix; + value += v; + ++text; + } + if ( valuep ) { + *valuep = value; + } + return (text - textstart); +} +#endif + +#ifndef HAVE_SSCANF +static size_t SDL_ScanUintPtrT(const char *text, int radix, uintptr_t *valuep) +{ + const char *textstart = text; + uintptr_t value = 0; + + if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { + text += 2; + } + for ( ; ; ) { + int v; + if ( SDL_isdigit((unsigned char) *text) ) { + v = *text - '0'; + } else if ( radix == 16 && SDL_isupperhex(*text) ) { + v = 10 + (*text - 'A'); + } else if ( radix == 16 && SDL_islowerhex(*text) ) { + v = 10 + (*text - 'a'); + } else { + break; + } + value *= radix; + value += v; + ++text; + } + if ( valuep ) { + *valuep = value; + } + return (text - textstart); +} +#endif + +#ifdef SDL_HAS_64BIT_TYPE +#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOLL) +static size_t SDL_ScanLongLong(const char *text, int radix, Sint64 *valuep) +{ + const char *textstart = text; + Sint64 value = 0; + SDL_bool negative = SDL_FALSE; + + if ( *text == '-' ) { + negative = SDL_TRUE; + ++text; + } + if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { + text += 2; + } + for ( ; ; ) { + int v; + if ( SDL_isdigit((unsigned char) *text) ) { + v = *text - '0'; + } else if ( radix == 16 && SDL_isupperhex(*text) ) { + v = 10 + (*text - 'A'); + } else if ( radix == 16 && SDL_islowerhex(*text) ) { + v = 10 + (*text - 'a'); + } else { + break; + } + value *= radix; + value += v; + ++text; + } + if ( valuep ) { + if ( negative && value ) { + *valuep = -value; + } else { + *valuep = value; + } + } + return (text - textstart); +} +#endif + +#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOULL) +static size_t SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 *valuep) +{ + const char *textstart = text; + Uint64 value = 0; + + if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) { + text += 2; + } + for ( ; ; ) { + int v; + if ( SDL_isdigit((unsigned char) *text) ) { + v = *text - '0'; + } else if ( radix == 16 && SDL_isupperhex(*text) ) { + v = 10 + (*text - 'A'); + } else if ( radix == 16 && SDL_islowerhex(*text) ) { + v = 10 + (*text - 'a'); + } else { + break; + } + value *= radix; + value += v; + ++text; + } + if ( valuep ) { + *valuep = value; + } + return (text - textstart); +} +#endif +#endif /* SDL_HAS_64BIT_TYPE */ + +#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOD) +static size_t SDL_ScanFloat(const char *text, double *valuep) +{ + const char *textstart = text; + unsigned long lvalue = 0; + double value = 0.0; + SDL_bool negative = SDL_FALSE; + + if ( *text == '-' ) { + negative = SDL_TRUE; + ++text; + } + text += SDL_ScanUnsignedLong(text, 10, &lvalue); + value += lvalue; + if ( *text == '.' ) { + int mult = 10; + ++text; + while ( SDL_isdigit((unsigned char) *text) ) { + lvalue = *text - '0'; + value += (double)lvalue / mult; + mult *= 10; + ++text; + } + } + if ( valuep ) { + if ( negative && value ) { + *valuep = -value; + } else { + *valuep = value; + } + } + return (text - textstart); +} +#endif + +#ifndef SDL_memset +void *SDL_memset(void *dst, int c, size_t len) +{ + size_t left = (len % 4); + if ( len >= 4 ) { + Uint32 value = 0; + Uint32 *dstp = (Uint32 *)dst; + int i; + for (i = 0; i < 4; ++i) { + value <<= 8; + value |= c; + } + len /= 4; + while ( len-- ) { + *dstp++ = value; + } + } + if ( left > 0 ) { + Uint8 value = (Uint8)c; + Uint8 *dstp = (Uint8 *)dst; + switch(left) { + case 3: + *dstp++ = value; + case 2: + *dstp++ = value; + case 1: + *dstp++ = value; + } + } + return dst; +} +#endif + +#ifndef SDL_memcpy +void *SDL_memcpy(void *dst, const void *src, size_t len) +{ + char *srcp = (char *)src; + char *dstp = (char *)dst; + while ( len-- ) { + *dstp++ = *srcp++; + } + return dst; +} +#endif + +#ifndef SDL_revcpy +void *SDL_revcpy(void *dst, const void *src, size_t len) +{ + char *srcp = (char *)src; + char *dstp = (char *)dst; + srcp += len-1; + dstp += len-1; + while ( len-- ) { + *dstp-- = *srcp--; + } + return dst; +} +#endif + +#ifndef SDL_memcmp +int SDL_memcmp(const void *s1, const void *s2, size_t len) +{ + char *s1p = (char *)s1; + char *s2p = (char *)s2; + while ( len-- ) { + if ( *s1p != *s2p ) { + return (*s1p - *s2p); + } + ++s1p; + ++s2p; + } + return 0; +} +#endif + +#ifndef HAVE_STRLEN +size_t SDL_strlen(const char *string) +{ + size_t len = 0; + while ( *string++ ) { + ++len; + } + return len; +} +#endif + +#ifndef HAVE_STRLCPY +size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen) +{ + size_t srclen = SDL_strlen(src); + if ( maxlen > 0 ) { + size_t len = SDL_min(srclen, maxlen-1); + SDL_memcpy(dst, src, len); + dst[len] = '\0'; + } + return srclen; +} +#endif + +#ifndef HAVE_STRLCAT +size_t SDL_strlcat(char *dst, const char *src, size_t maxlen) +{ + size_t dstlen = SDL_strlen(dst); + size_t srclen = SDL_strlen(src); + if ( dstlen < maxlen ) { + SDL_strlcpy(dst+dstlen, src, maxlen-dstlen); + } + return dstlen+srclen; +} +#endif + +#ifndef HAVE_STRDUP +char *SDL_strdup(const char *string) +{ + size_t len = SDL_strlen(string)+1; + char *newstr = SDL_malloc(len); + if ( newstr ) { + SDL_strlcpy(newstr, string, len); + } + return newstr; +} +#endif + +#ifndef HAVE__STRREV +char *SDL_strrev(char *string) +{ + size_t len = SDL_strlen(string); + char *a = &string[0]; + char *b = &string[len-1]; + len /= 2; + while ( len-- ) { + char c = *a; + *a++ = *b; + *b-- = c; + } + return string; +} +#endif + +#ifndef HAVE__STRUPR +char *SDL_strupr(char *string) +{ + char *bufp = string; + while ( *bufp ) { + *bufp = SDL_toupper((unsigned char) *bufp); + ++bufp; + } + return string; +} +#endif + +#ifndef HAVE__STRLWR +char *SDL_strlwr(char *string) +{ + char *bufp = string; + while ( *bufp ) { + *bufp = SDL_tolower((unsigned char) *bufp); + ++bufp; + } + return string; +} +#endif + +#ifndef HAVE_STRCHR +char *SDL_strchr(const char *string, int c) +{ + while ( *string ) { + if ( *string == c ) { + return (char *)string; + } + ++string; + } + return NULL; +} +#endif + +#ifndef HAVE_STRRCHR +char *SDL_strrchr(const char *string, int c) +{ + const char *bufp = string + SDL_strlen(string) - 1; + while ( bufp >= string ) { + if ( *bufp == c ) { + return (char *)bufp; + } + --bufp; + } + return NULL; +} +#endif + +#ifndef HAVE_STRSTR +char *SDL_strstr(const char *haystack, const char *needle) +{ + size_t length = SDL_strlen(needle); + while ( *haystack ) { + if ( SDL_strncmp(haystack, needle, length) == 0 ) { + return (char *)haystack; + } + ++haystack; + } + return NULL; +} +#endif + +#if !defined(HAVE__LTOA) || !defined(HAVE__I64TOA) || \ + !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA) +static const char ntoa_table[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z' +}; +#endif /* ntoa() conversion table */ + +#ifndef HAVE__LTOA +char *SDL_ltoa(long value, char *string, int radix) +{ + char *bufp = string; + + if ( value < 0 ) { + *bufp++ = '-'; + value = -value; + } + if ( value ) { + while ( value > 0 ) { + *bufp++ = ntoa_table[value % radix]; + value /= radix; + } + } else { + *bufp++ = '0'; + } + *bufp = '\0'; + + /* The numbers went into the string backwards. :) */ + if ( *string == '-' ) { + SDL_strrev(string+1); + } else { + SDL_strrev(string); + } + + return string; +} +#endif + +#ifndef HAVE__ULTOA +char *SDL_ultoa(unsigned long value, char *string, int radix) +{ + char *bufp = string; + + if ( value ) { + while ( value > 0 ) { + *bufp++ = ntoa_table[value % radix]; + value /= radix; + } + } else { + *bufp++ = '0'; + } + *bufp = '\0'; + + /* The numbers went into the string backwards. :) */ + SDL_strrev(string); + + return string; +} +#endif + +#ifndef HAVE_STRTOL +long SDL_strtol(const char *string, char **endp, int base) +{ + size_t len; + long value; + + if ( !base ) { + if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { + base = 16; + } else { + base = 10; + } + } + + len = SDL_ScanLong(string, base, &value); + if ( endp ) { + *endp = (char *)string + len; + } + return value; +} +#endif + +#ifndef HAVE_STRTOUL +unsigned long SDL_strtoul(const char *string, char **endp, int base) +{ + size_t len; + unsigned long value; + + if ( !base ) { + if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { + base = 16; + } else { + base = 10; + } + } + + len = SDL_ScanUnsignedLong(string, base, &value); + if ( endp ) { + *endp = (char *)string + len; + } + return value; +} +#endif + +#ifdef SDL_HAS_64BIT_TYPE + +#ifndef HAVE__I64TOA +char *SDL_lltoa(Sint64 value, char *string, int radix) +{ + char *bufp = string; + + if ( value < 0 ) { + *bufp++ = '-'; + value = -value; + } + if ( value ) { + while ( value > 0 ) { + *bufp++ = ntoa_table[value % radix]; + value /= radix; + } + } else { + *bufp++ = '0'; + } + *bufp = '\0'; + + /* The numbers went into the string backwards. :) */ + if ( *string == '-' ) { + SDL_strrev(string+1); + } else { + SDL_strrev(string); + } + + return string; +} +#endif + +#ifndef HAVE__UI64TOA +char *SDL_ulltoa(Uint64 value, char *string, int radix) +{ + char *bufp = string; + + if ( value ) { + while ( value > 0 ) { + *bufp++ = ntoa_table[value % radix]; + value /= radix; + } + } else { + *bufp++ = '0'; + } + *bufp = '\0'; + + /* The numbers went into the string backwards. :) */ + SDL_strrev(string); + + return string; +} +#endif + +#ifndef HAVE_STRTOLL +Sint64 SDL_strtoll(const char *string, char **endp, int base) +{ + size_t len; + Sint64 value; + + if ( !base ) { + if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { + base = 16; + } else { + base = 10; + } + } + + len = SDL_ScanLongLong(string, base, &value); + if ( endp ) { + *endp = (char *)string + len; + } + return value; +} +#endif + +#ifndef HAVE_STRTOULL +Uint64 SDL_strtoull(const char *string, char **endp, int base) +{ + size_t len; + Uint64 value; + + if ( !base ) { + if ( (SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0) ) { + base = 16; + } else { + base = 10; + } + } + + len = SDL_ScanUnsignedLongLong(string, base, &value); + if ( endp ) { + *endp = (char *)string + len; + } + return value; +} +#endif + +#endif /* SDL_HAS_64BIT_TYPE */ + +#ifndef HAVE_STRTOD +double SDL_strtod(const char *string, char **endp) +{ + size_t len; + double value; + + len = SDL_ScanFloat(string, &value); + if ( endp ) { + *endp = (char *)string + len; + } + return value; +} +#endif + +#ifndef HAVE_STRCMP +int SDL_strcmp(const char *str1, const char *str2) +{ + while (*str1 && *str2) { + if ( *str1 != *str2 ) + break; + ++str1; + ++str2; + } + return (int)((unsigned char)*str1 - (unsigned char)*str2); +} +#endif + +#ifndef HAVE_STRNCMP +int SDL_strncmp(const char *str1, const char *str2, size_t maxlen) +{ + while ( *str1 && *str2 && maxlen ) { + if ( *str1 != *str2 ) + break; + ++str1; + ++str2; + --maxlen; + } + if ( ! maxlen ) { + return 0; + } + return (int)((unsigned char)*str1 - (unsigned char)*str2); +} +#endif + +#if !defined(HAVE_STRCASECMP) && !defined(HAVE__STRICMP) +int SDL_strcasecmp(const char *str1, const char *str2) +{ + char a = 0; + char b = 0; + while ( *str1 && *str2 ) { + a = SDL_tolower((unsigned char) *str1); + b = SDL_tolower((unsigned char) *str2); + if ( a != b ) + break; + ++str1; + ++str2; + } + return (int)((unsigned char)a - (unsigned char)b); +} +#endif + +#if !defined(HAVE_STRNCASECMP) && !defined(HAVE__STRNICMP) +int SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen) +{ + char a = 0; + char b = 0; + while ( *str1 && *str2 && maxlen ) { + a = SDL_tolower((unsigned char) *str1); + b = SDL_tolower((unsigned char) *str2); + if ( a != b ) + break; + ++str1; + ++str2; + --maxlen; + } + return (int)((unsigned char)a - (unsigned char)b); +} +#endif + +#ifndef HAVE_SSCANF +int SDL_sscanf(const char *text, const char *fmt, ...) +{ + va_list ap; + int retval = 0; + + va_start(ap, fmt); + while ( *fmt ) { + if ( *fmt == ' ' ) { + while ( SDL_isspace((unsigned char) *text) ) { + ++text; + } + ++fmt; + continue; + } + if ( *fmt == '%' ) { + SDL_bool done = SDL_FALSE; + long count = 0; + int radix = 10; + enum { + DO_SHORT, + DO_INT, + DO_LONG, + DO_LONGLONG + } inttype = DO_INT; + SDL_bool suppress = SDL_FALSE; + + ++fmt; + if ( *fmt == '%' ) { + if ( *text == '%' ) { + ++text; + ++fmt; + continue; + } + break; + } + if ( *fmt == '*' ) { + suppress = SDL_TRUE; + ++fmt; + } + fmt += SDL_ScanLong(fmt, 10, &count); + + if ( *fmt == 'c' ) { + if ( ! count ) { + count = 1; + } + if ( suppress ) { + while ( count-- ) { + ++text; + } + } else { + char *valuep = va_arg(ap, char*); + while ( count-- ) { + *valuep++ = *text++; + } + ++retval; + } + continue; + } + + while ( SDL_isspace((unsigned char) *text) ) { + ++text; + } + + /* FIXME: implement more of the format specifiers */ + while (!done) { + switch(*fmt) { + case '*': + suppress = SDL_TRUE; + break; + case 'h': + if ( inttype > DO_SHORT ) { + ++inttype; + } + break; + case 'l': + if ( inttype < DO_LONGLONG ) { + ++inttype; + } + break; + case 'I': + if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { + fmt += 2; + inttype = DO_LONGLONG; + } + break; + case 'i': + { + int index = 0; + if ( text[index] == '-' ) { + ++index; + } + if ( text[index] == '0' ) { + if ( SDL_tolower((unsigned char) text[index+1]) == 'x' ) { + radix = 16; + } else { + radix = 8; + } + } + } + /* Fall through to %d handling */ + case 'd': +#ifdef SDL_HAS_64BIT_TYPE + if ( inttype == DO_LONGLONG ) { + Sint64 value; + text += SDL_ScanLongLong(text, radix, &value); + if ( ! suppress ) { + Sint64 *valuep = va_arg(ap, Sint64*); + *valuep = value; + ++retval; + } + } + else +#endif /* SDL_HAS_64BIT_TYPE */ + { + long value; + text += SDL_ScanLong(text, radix, &value); + if ( ! suppress ) { + switch (inttype) { + case DO_SHORT: + { short* valuep = va_arg(ap, short*); + *valuep = (short)value; + } + break; + case DO_INT: + { int* valuep = va_arg(ap, int*); + *valuep = (int)value; + } + break; + case DO_LONG: + { long* valuep = va_arg(ap, long*); + *valuep = value; + } + break; + case DO_LONGLONG: + /* Handled above */ + break; + } + ++retval; + } + } + done = SDL_TRUE; + break; + case 'o': + if ( radix == 10 ) { + radix = 8; + } + /* Fall through to unsigned handling */ + case 'x': + case 'X': + if ( radix == 10 ) { + radix = 16; + } + /* Fall through to unsigned handling */ + case 'u': +#ifdef SDL_HAS_64BIT_TYPE + if ( inttype == DO_LONGLONG ) { + Uint64 value; + text += SDL_ScanUnsignedLongLong(text, radix, &value); + if ( ! suppress ) { + Uint64 *valuep = va_arg(ap, Uint64*); + *valuep = value; + ++retval; + } + } + else +#endif /* SDL_HAS_64BIT_TYPE */ + { + unsigned long value; + text += SDL_ScanUnsignedLong(text, radix, &value); + if ( ! suppress ) { + switch (inttype) { + case DO_SHORT: + { short* valuep = va_arg(ap, short*); + *valuep = (short)value; + } + break; + case DO_INT: + { int* valuep = va_arg(ap, int*); + *valuep = (int)value; + } + break; + case DO_LONG: + { long* valuep = va_arg(ap, long*); + *valuep = value; + } + break; + case DO_LONGLONG: + /* Handled above */ + break; + } + ++retval; + } + } + done = SDL_TRUE; + break; + case 'p': + { + uintptr_t value; + text += SDL_ScanUintPtrT(text, 16, &value); + if ( ! suppress ) { + void** valuep = va_arg(ap, void**); + *valuep = (void*)value; + ++retval; + } + } + done = SDL_TRUE; + break; + case 'f': + { + double value; + text += SDL_ScanFloat(text, &value); + if ( ! suppress ) { + float* valuep = va_arg(ap, float*); + *valuep = (float)value; + ++retval; + } + } + done = SDL_TRUE; + break; + case 's': + if ( suppress ) { + while ( !SDL_isspace((unsigned char) *text) ) { + ++text; + if ( count ) { + if ( --count == 0 ) { + break; + } + } + } + } else { + char *valuep = va_arg(ap, char*); + while ( !SDL_isspace((unsigned char) *text) ) { + *valuep++ = *text++; + if ( count ) { + if ( --count == 0 ) { + break; + } + } + } + *valuep = '\0'; + ++retval; + } + done = SDL_TRUE; + break; + default: + done = SDL_TRUE; + break; + } + ++fmt; + } + continue; + } + if ( *text == *fmt ) { + ++text; + ++fmt; + continue; + } + /* Text didn't match format specifier */ + break; + } + va_end(ap); + + return retval; +} +#endif + +#ifndef HAVE_SNPRINTF +int SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...) +{ + va_list ap; + int retval; + + va_start(ap, fmt); + retval = SDL_vsnprintf(text, maxlen, fmt, ap); + va_end(ap); + + return retval; +} +#endif + +#ifndef HAVE_VSNPRINTF +static size_t SDL_PrintLong(char *text, long value, int radix, size_t maxlen) +{ + char num[130]; + size_t size; + + SDL_ltoa(value, num, radix); + size = SDL_strlen(num); + if ( size >= maxlen ) { + size = maxlen-1; + } + SDL_strlcpy(text, num, size+1); + + return size; +} +static size_t SDL_PrintUnsignedLong(char *text, unsigned long value, int radix, size_t maxlen) +{ + char num[130]; + size_t size; + + SDL_ultoa(value, num, radix); + size = SDL_strlen(num); + if ( size >= maxlen ) { + size = maxlen-1; + } + SDL_strlcpy(text, num, size+1); + + return size; +} +#ifdef SDL_HAS_64BIT_TYPE +static size_t SDL_PrintLongLong(char *text, Sint64 value, int radix, size_t maxlen) +{ + char num[130]; + size_t size; + + SDL_lltoa(value, num, radix); + size = SDL_strlen(num); + if ( size >= maxlen ) { + size = maxlen-1; + } + SDL_strlcpy(text, num, size+1); + + return size; +} +static size_t SDL_PrintUnsignedLongLong(char *text, Uint64 value, int radix, size_t maxlen) +{ + char num[130]; + size_t size; + + SDL_ulltoa(value, num, radix); + size = SDL_strlen(num); + if ( size >= maxlen ) { + size = maxlen-1; + } + SDL_strlcpy(text, num, size+1); + + return size; +} +#endif /* SDL_HAS_64BIT_TYPE */ +static size_t SDL_PrintFloat(char *text, double arg, size_t maxlen) +{ + char *textstart = text; + if ( arg ) { + /* This isn't especially accurate, but hey, it's easy. :) */ + const double precision = 0.00000001; + size_t len; + unsigned long value; + + if ( arg < 0 ) { + *text++ = '-'; + --maxlen; + arg = -arg; + } + value = (unsigned long)arg; + len = SDL_PrintUnsignedLong(text, value, 10, maxlen); + text += len; + maxlen -= len; + arg -= value; + if ( arg > precision && maxlen ) { + int mult = 10; + *text++ = '.'; + while ( (arg > precision) && maxlen ) { + value = (unsigned long)(arg * mult); + len = SDL_PrintUnsignedLong(text, value, 10, maxlen); + text += len; + maxlen -= len; + arg -= (double)value / mult; + mult *= 10; + } + } + } else { + *text++ = '0'; + } + return (text - textstart); +} +static size_t SDL_PrintString(char *text, const char *string, size_t maxlen) +{ + char *textstart = text; + while ( *string && maxlen-- ) { + *text++ = *string++; + } + return (text - textstart); +} +int SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap) +{ + char *textstart = text; + if ( maxlen <= 0 ) { + return 0; + } + --maxlen; /* For the trailing '\0' */ + while ( *fmt && maxlen ) { + if ( *fmt == '%' ) { + SDL_bool done = SDL_FALSE; + size_t len = 0; + SDL_bool do_lowercase = SDL_FALSE; + int radix = 10; + enum { + DO_INT, + DO_LONG, + DO_LONGLONG + } inttype = DO_INT; + + ++fmt; + /* FIXME: implement more of the format specifiers */ + while ( *fmt == '.' || (*fmt >= '0' && *fmt <= '9') ) { + ++fmt; + } + while (!done) { + switch(*fmt) { + case '%': + *text = '%'; + len = 1; + done = SDL_TRUE; + break; + case 'c': + /* char is promoted to int when passed through (...) */ + *text = (char)va_arg(ap, int); + len = 1; + done = SDL_TRUE; + break; + case 'h': + /* short is promoted to int when passed through (...) */ + break; + case 'l': + if ( inttype < DO_LONGLONG ) { + ++inttype; + } + break; + case 'I': + if ( SDL_strncmp(fmt, "I64", 3) == 0 ) { + fmt += 2; + inttype = DO_LONGLONG; + } + break; + case 'i': + case 'd': + switch (inttype) { + case DO_INT: + len = SDL_PrintLong(text, (long)va_arg(ap, int), radix, maxlen); + break; + case DO_LONG: + len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); + break; + case DO_LONGLONG: +#ifdef SDL_HAS_64BIT_TYPE + len = SDL_PrintLongLong(text, va_arg(ap, Sint64), radix, maxlen); +#else + len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen); +#endif + break; + } + done = SDL_TRUE; + break; + case 'p': + case 'x': + do_lowercase = SDL_TRUE; + /* Fall through to 'X' handling */ + case 'X': + if ( radix == 10 ) { + radix = 16; + } + if ( *fmt == 'p' ) { + inttype = DO_LONG; + } + /* Fall through to unsigned handling */ + case 'o': + if ( radix == 10 ) { + radix = 8; + } + /* Fall through to unsigned handling */ + case 'u': + switch (inttype) { + case DO_INT: + len = SDL_PrintUnsignedLong(text, (unsigned long)va_arg(ap, unsigned int), radix, maxlen); + break; + case DO_LONG: + len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); + break; + case DO_LONGLONG: +#ifdef SDL_HAS_64BIT_TYPE + len = SDL_PrintUnsignedLongLong(text, va_arg(ap, Uint64), radix, maxlen); +#else + len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen); +#endif + break; + } + if ( do_lowercase ) { + SDL_strlwr(text); + } + done = SDL_TRUE; + break; + case 'f': + len = SDL_PrintFloat(text, va_arg(ap, double), maxlen); + done = SDL_TRUE; + break; + case 's': + len = SDL_PrintString(text, va_arg(ap, char*), maxlen); + done = SDL_TRUE; + break; + default: + done = SDL_TRUE; + break; + } + ++fmt; + } + text += len; + maxlen -= len; + } else { + *text++ = *fmt++; + --maxlen; + } + } + *text = '\0'; + + return (text - textstart); +} +#endif diff --git a/3rdparty/SDL/src/thread/SDL_systhread.h b/3rdparty/SDL/src/thread/SDL_systhread.h new file mode 100644 index 0000000..a59ac50 --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_systhread.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* These are functions that need to be implemented by a port of SDL */ + +#ifndef _SDL_systhread_h +#define _SDL_systhread_h + +#include "SDL_thread.h" + +/* This function creates a thread, passing args to SDL_RunThread(), + saves a system-dependent thread id in thread->id, and returns 0 + on success. +*/ +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread); +#else +extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args); +#endif + +/* This function does any necessary setup in the child thread */ +extern void SDL_SYS_SetupThread(void); + +/* This function waits for the thread to finish and frees any data + allocated by SDL_SYS_CreateThread() + */ +extern void SDL_SYS_WaitThread(SDL_Thread *thread); + +/* This function kills the thread and returns */ +extern void SDL_SYS_KillThread(SDL_Thread *thread); + +#endif /* _SDL_systhread_h */ diff --git a/3rdparty/SDL/src/thread/SDL_thread.c b/3rdparty/SDL/src/thread/SDL_thread.c new file mode 100644 index 0000000..250371d --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_thread.c @@ -0,0 +1,300 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* System independent thread management routines for SDL */ + +#include "SDL_mutex.h" +#include "SDL_thread.h" +#include "SDL_thread_c.h" +#include "SDL_systhread.h" + +#define ARRAY_CHUNKSIZE 32 +/* The array of threads currently active in the application + (except the main thread) + The manipulation of an array here is safer than using a linked list. +*/ +static int SDL_maxthreads = 0; +static int SDL_numthreads = 0; +static SDL_Thread **SDL_Threads = NULL; +static SDL_mutex *thread_lock = NULL; + +int SDL_ThreadsInit(void) +{ + int retval; + + retval = 0; + thread_lock = SDL_CreateMutex(); + if ( thread_lock == NULL ) { + retval = -1; + } + return(retval); +} + +/* This should never be called... + If this is called by SDL_Quit(), we don't know whether or not we should + clean up threads here. If any threads are still running after this call, + they will no longer have access to any per-thread data. + */ +void SDL_ThreadsQuit(void) +{ + SDL_mutex *mutex; + + mutex = thread_lock; + thread_lock = NULL; + if ( mutex != NULL ) { + SDL_DestroyMutex(mutex); + } +} + +/* Routines for manipulating the thread list */ +static void SDL_AddThread(SDL_Thread *thread) +{ + /* WARNING: + If the very first threads are created simultaneously, then + there could be a race condition causing memory corruption. + In practice, this isn't a problem because by definition there + is only one thread running the first time this is called. + */ + if ( !thread_lock ) { + if ( SDL_ThreadsInit() < 0 ) { + return; + } + } + SDL_mutexP(thread_lock); + + /* Expand the list of threads, if necessary */ +#ifdef DEBUG_THREADS + printf("Adding thread (%d already - %d max)\n", + SDL_numthreads, SDL_maxthreads); +#endif + if ( SDL_numthreads == SDL_maxthreads ) { + SDL_Thread **threads; + threads = (SDL_Thread **)SDL_realloc(SDL_Threads, + (SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads)); + if ( threads == NULL ) { + SDL_OutOfMemory(); + goto done; + } + SDL_maxthreads += ARRAY_CHUNKSIZE; + SDL_Threads = threads; + } + SDL_Threads[SDL_numthreads++] = thread; +done: + SDL_mutexV(thread_lock); +} + +static void SDL_DelThread(SDL_Thread *thread) +{ + int i; + + if ( !thread_lock ) { + return; + } + SDL_mutexP(thread_lock); + for ( i=0; i<SDL_numthreads; ++i ) { + if ( thread == SDL_Threads[i] ) { + break; + } + } + if ( i < SDL_numthreads ) { + if ( --SDL_numthreads > 0 ) { + while ( i < SDL_numthreads ) { + SDL_Threads[i] = SDL_Threads[i+1]; + ++i; + } + } else { + SDL_maxthreads = 0; + SDL_free(SDL_Threads); + SDL_Threads = NULL; + } +#ifdef DEBUG_THREADS + printf("Deleting thread (%d left - %d max)\n", + SDL_numthreads, SDL_maxthreads); +#endif + } + SDL_mutexV(thread_lock); + +#if 0 /* There could be memory corruption if another thread is starting */ + if ( SDL_Threads == NULL ) { + SDL_ThreadsQuit(); + } +#endif +} + +/* The default (non-thread-safe) global error variable */ +static SDL_error SDL_global_error; + +/* Routine to get the thread-specific error variable */ +SDL_error *SDL_GetErrBuf(void) +{ + SDL_error *errbuf; + + errbuf = &SDL_global_error; + if ( SDL_Threads ) { + int i; + Uint32 this_thread; + + this_thread = SDL_ThreadID(); + SDL_mutexP(thread_lock); + for ( i=0; i<SDL_numthreads; ++i ) { + if ( this_thread == SDL_Threads[i]->threadid ) { + errbuf = &SDL_Threads[i]->errbuf; + break; + } + } + SDL_mutexV(thread_lock); + } + return(errbuf); +} + + +/* Arguments and callback to setup and run the user thread function */ +typedef struct { + int (SDLCALL *func)(void *); + void *data; + SDL_Thread *info; + SDL_sem *wait; +} thread_args; + +void SDL_RunThread(void *data) +{ + thread_args *args; + int (SDLCALL *userfunc)(void *); + void *userdata; + int *statusloc; + + /* Perform any system-dependent setup + - this function cannot fail, and cannot use SDL_SetError() + */ + SDL_SYS_SetupThread(); + + /* Get the thread id */ + args = (thread_args *)data; + args->info->threadid = SDL_ThreadID(); + + /* Figure out what function to run */ + userfunc = args->func; + userdata = args->data; + statusloc = &args->info->status; + + /* Wake up the parent thread */ + SDL_SemPost(args->wait); + + /* Run the function */ + *statusloc = userfunc(userdata); +} + +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +#undef SDL_CreateThread +DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) +#else +DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data) +#endif +{ + SDL_Thread *thread; + thread_args *args; + int ret; + + /* Allocate memory for the thread info structure */ + thread = (SDL_Thread *)SDL_malloc(sizeof(*thread)); + if ( thread == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(thread, 0, (sizeof *thread)); + thread->status = -1; + + /* Set up the arguments for the thread */ + args = (thread_args *)SDL_malloc(sizeof(*args)); + if ( args == NULL ) { + SDL_OutOfMemory(); + SDL_free(thread); + return(NULL); + } + args->func = fn; + args->data = data; + args->info = thread; + args->wait = SDL_CreateSemaphore(0); + if ( args->wait == NULL ) { + SDL_free(thread); + SDL_free(args); + return(NULL); + } + + /* Add the thread to the list of available threads */ + SDL_AddThread(thread); + + /* Create the thread and go! */ +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD + ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread); +#else + ret = SDL_SYS_CreateThread(thread, args); +#endif + if ( ret >= 0 ) { + /* Wait for the thread function to use arguments */ + SDL_SemWait(args->wait); + } else { + /* Oops, failed. Gotta free everything */ + SDL_DelThread(thread); + SDL_free(thread); + thread = NULL; + } + SDL_DestroySemaphore(args->wait); + SDL_free(args); + + /* Everything is running now */ + return(thread); +} + +void SDL_WaitThread(SDL_Thread *thread, int *status) +{ + if ( thread ) { + SDL_SYS_WaitThread(thread); + if ( status ) { + *status = thread->status; + } + SDL_DelThread(thread); + SDL_free(thread); + } +} + +Uint32 SDL_GetThreadID(SDL_Thread *thread) +{ + Uint32 id; + + if ( thread ) { + id = thread->threadid; + } else { + id = SDL_ThreadID(); + } + return(id); +} + +void SDL_KillThread(SDL_Thread *thread) +{ + if ( thread ) { + SDL_SYS_KillThread(thread); + SDL_WaitThread(thread, NULL); + } +} + diff --git a/3rdparty/SDL/src/thread/SDL_thread_c.h b/3rdparty/SDL/src/thread/SDL_thread_c.h new file mode 100644 index 0000000..8af6e52 --- /dev/null +++ b/3rdparty/SDL/src/thread/SDL_thread_c.h @@ -0,0 +1,64 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_thread_c_h +#define _SDL_thread_c_h + +/* Need the definitions of SYS_ThreadHandle */ +#if SDL_THREADS_DISABLED +#include "generic/SDL_systhread_c.h" +#elif SDL_THREAD_BEOS +#include "beos/SDL_systhread_c.h" +#elif SDL_THREAD_DC +#include "dc/SDL_systhread_c.h" +#elif SDL_THREAD_OS2 +#include "os2/SDL_systhread_c.h" +#elif SDL_THREAD_PTH +#include "pth/SDL_systhread_c.h" +#elif SDL_THREAD_PTHREAD +#include "pthread/SDL_systhread_c.h" +#elif SDL_THREAD_SPROC +#include "irix/SDL_systhread_c.h" +#elif SDL_THREAD_WIN32 +#include "win32/SDL_systhread_c.h" +#elif SDL_THREAD_SYMBIAN +#include "symbian/SDL_systhread_c.h" +#else +#error Need thread implementation for this platform +#include "generic/SDL_systhread_c.h" +#endif +#include "../SDL_error_c.h" + +/* This is the system-independent thread info structure */ +struct SDL_Thread { + Uint32 threadid; + SYS_ThreadHandle handle; + int status; + SDL_error errbuf; + void *data; +}; + +/* This is the function called to run a thread */ +extern void SDL_RunThread(void *data); + +#endif /* _SDL_thread_c_h */ diff --git a/3rdparty/SDL/src/thread/beos/SDL_syssem.c b/3rdparty/SDL/src/thread/beos/SDL_syssem.c new file mode 100644 index 0000000..eba1944 --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_syssem.c @@ -0,0 +1,142 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Semaphores in the BeOS environment */ + +#include <be/kernel/OS.h> + +#include "SDL_thread.h" + + +struct SDL_semaphore { + sem_id id; +}; + +/* Create a counting semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + sem->id = create_sem(initial_value, "SDL semaphore"); + if ( sem->id < B_NO_ERROR ) { + SDL_SetError("create_sem() failed"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id >= B_NO_ERROR ) { + delete_sem(sem->id); + } + SDL_free(sem); + } +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int32 val; + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + tryagain: + if ( timeout == SDL_MUTEX_MAXWAIT ) { + val = acquire_sem(sem->id); + } else { + timeout *= 1000; /* BeOS uses a timeout in microseconds */ + val = acquire_sem_etc(sem->id, 1, B_RELATIVE_TIMEOUT, timeout); + } + switch (val) { + case B_INTERRUPTED: + goto tryagain; + case B_NO_ERROR: + retval = 0; + break; + case B_TIMED_OUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + case B_WOULD_BLOCK: + retval = SDL_MUTEX_TIMEDOUT; + break; + default: + SDL_SetError("acquire_sem() failed"); + retval = -1; + break; + } + + return retval; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int32 count; + Uint32 value; + + value = 0; + if ( sem ) { + get_sem_count(sem->id, &count); + if ( count > 0 ) { + value = (Uint32)count; + } + } + return value; +} + +/* Atomically increases the semaphore's count (not blocking) */ +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + if ( release_sem(sem->id) != B_NO_ERROR ) { + SDL_SetError("release_sem() failed"); + return -1; + } + return 0; +} diff --git a/3rdparty/SDL/src/thread/beos/SDL_systhread.c b/3rdparty/SDL/src/thread/beos/SDL_systhread.c new file mode 100644 index 0000000..63b5207 --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_systhread.c @@ -0,0 +1,96 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* BeOS thread management routines for SDL */ + +#include <stdio.h> +#include <signal.h> +#include <be/kernel/OS.h> + +#include "SDL_mutex.h" +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + + +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0 +}; + +void SDL_MaskSignals(sigset_t *omask) +{ + sigset_t mask; + int i; + + sigemptyset(&mask); + for ( i=0; sig_list[i]; ++i ) { + sigaddset(&mask, sig_list[i]); + } + sigprocmask(SIG_BLOCK, &mask, omask); +} +void SDL_UnmaskSignals(sigset_t *omask) +{ + sigprocmask(SIG_SETMASK, omask, NULL); +} + +static int32 RunThread(void *data) +{ + SDL_RunThread(data); + return(0); +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + /* Create the thread and go! */ + thread->handle=spawn_thread(RunThread, "SDL", B_NORMAL_PRIORITY, args); + if ( (thread->handle == B_NO_MORE_THREADS) || + (thread->handle == B_NO_MEMORY) ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + resume_thread(thread->handle); + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + /* Mask asynchronous signals for this thread */ + SDL_MaskSignals(NULL); +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)find_thread(NULL)); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + status_t the_status; + + wait_for_thread(thread->handle, &the_status); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + kill_thread(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h b/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h new file mode 100644 index 0000000..f82548e --- /dev/null +++ b/3rdparty/SDL/src/thread/beos/SDL_systhread_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <signal.h> +#include <be/kernel/OS.h> + +typedef thread_id SYS_ThreadHandle; + +/* Functions needed to work with system threads in other portions of SDL */ +extern void SDL_MaskSignals(sigset_t *omask); +extern void SDL_UnmaskSignals(sigset_t *omask); diff --git a/3rdparty/SDL/src/thread/dc/SDL_syscond.c b/3rdparty/SDL/src/thread/dc/SDL_syscond.c new file mode 100644 index 0000000..f6e7223 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 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! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + 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 ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + 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_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(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_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + 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); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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 */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* 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_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(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; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h b/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syscond_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c b/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c new file mode 100644 index 0000000..c6c4651 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_sysmutex.c @@ -0,0 +1,122 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* An implementation of mutexes using semaphores */ + +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + +#include <arch/spinlock.h> + +struct SDL_mutex { + int recursive; + Uint32 owner; + spinlock_t mutex; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + spinlock_init(&mutex->mutex); + mutex->recursive = 0; + mutex->owner = 0; + } else { + SDL_OutOfMemory(); + } + return mutex; +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + SDL_free(mutex); + } +} + +/* Lock the semaphore */ +int SDL_mutexP(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return SDL_arraysize(return ),0; +#else + Uint32 this_thread; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + if ( mutex->owner == this_thread ) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + spinlock_lock(&mutex->mutex); + mutex->owner = this_thread; + mutex->recursive = 0; + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + /* If we don't own the mutex, we can't unlock it */ + if ( SDL_ThreadID() != mutex->owner ) { + SDL_SetError("mutex not owned by this thread"); + return -1; + } + + if ( mutex->recursive ) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + spinlock_unlock(&mutex->mutex); + } + return 0; +#endif /* SDL_THREADS_DISABLED */ +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_sysmutex_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_syssem.c b/3rdparty/SDL/src/thread/dc/SDL_syssem.c new file mode 100644 index 0000000..9831ccd --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syssem.c @@ -0,0 +1,173 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include <errno.h> + +#include "SDL_config.h" + +/* An implementation of semaphores using mutexes and condition variables */ + +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + + +#if SDL_THREADS_DISABLED + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_SetError("SDL not configured with thread support"); + return (SDL_sem *)0; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + return; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + return 0; +} + +int SDL_SemPost(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +#else + +#include <kos/sem.h> + +struct SDL_semaphore +{ + semaphore_t sem; +}; + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + return (SDL_sem *)sem_create(initial_value); +} + +/* WARNING: + You cannot call this function when another thread is using the semaphore. +*/ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return; + } + + sem_destroy(&sem->sem); +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_trywait(&sem->sem); + if (retval==0) return 0; + else return SDL_MUTEX_TIMEDOUT; + + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* A timeout of 0 is an easy case */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + + retval = sem_wait_timed(&sem->sem,timeout); + if (retval==-1) retval= SDL_MUTEX_TIMEDOUT; + + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + return sem_count(&sem->sem); +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + sem_signal(&sem->sem); + return 0; +} + +#endif /* SDL_THREADS_DISABLED */ diff --git a/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h b/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_syssem_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + diff --git a/3rdparty/SDL/src/thread/dc/SDL_systhread.c b/3rdparty/SDL/src/thread/dc/SDL_systhread.c new file mode 100644 index 0000000..dd26675 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_systhread.c @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Thread management routines for SDL */ + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +#include <kos/thread.h> + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + thread->handle = thd_create(SDL_RunThread,args); + if (thread->handle == NULL) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return (Uint32)thd_get_current(); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + thd_wait(thread->handle); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + thd_destroy(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h b/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h new file mode 100644 index 0000000..3cda1a4 --- /dev/null +++ b/3rdparty/SDL/src/thread/dc/SDL_systhread_c.h @@ -0,0 +1,24 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +typedef struct kthread* SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/generic/SDL_syscond.c b/3rdparty/SDL/src/thread/generic/SDL_syscond.c new file mode 100644 index 0000000..f6e7223 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 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! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + 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 ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + 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_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(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_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + 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); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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 */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* 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_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(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; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c b/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c new file mode 100644 index 0000000..ecfea87 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_sysmutex.c @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* An implementation of mutexes using semaphores */ + +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + + +struct SDL_mutex { + int recursive; + Uint32 owner; + SDL_sem *sem; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + /* Create the mutex semaphore, with initial value 1 */ + mutex->sem = SDL_CreateSemaphore(1); + mutex->recursive = 0; + mutex->owner = 0; + if ( ! mutex->sem ) { + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return mutex; +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + if ( mutex->sem ) { + SDL_DestroySemaphore(mutex->sem); + } + SDL_free(mutex); + } +} + +/* Lock the semaphore */ +int SDL_mutexP(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + Uint32 this_thread; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + if ( mutex->owner == this_thread ) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + SDL_SemWait(mutex->sem); + mutex->owner = this_thread; + mutex->recursive = 0; + } + + return 0; +#endif /* SDL_THREADS_DISABLED */ +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + /* If we don't own the mutex, we can't unlock it */ + if ( SDL_ThreadID() != mutex->owner ) { + SDL_SetError("mutex not owned by this thread"); + return -1; + } + + if ( mutex->recursive ) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + SDL_SemPost(mutex->sem); + } + return 0; +#endif /* SDL_THREADS_DISABLED */ +} diff --git a/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_sysmutex_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + diff --git a/3rdparty/SDL/src/thread/generic/SDL_syssem.c b/3rdparty/SDL/src/thread/generic/SDL_syssem.c new file mode 100644 index 0000000..1d289c0 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_syssem.c @@ -0,0 +1,211 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* An implementation of semaphores using mutexes and condition variables */ + +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + + +#if SDL_THREADS_DISABLED + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_SetError("SDL not configured with thread support"); + return (SDL_sem *)0; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + return; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + return 0; +} + +int SDL_SemPost(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +#else + +struct SDL_semaphore +{ + Uint32 count; + Uint32 waiters_count; + SDL_mutex *count_lock; + SDL_cond *count_nonzero; +}; + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( ! sem ) { + SDL_OutOfMemory(); + return NULL; + } + sem->count = initial_value; + sem->waiters_count = 0; + + sem->count_lock = SDL_CreateMutex(); + sem->count_nonzero = SDL_CreateCond(); + if ( ! sem->count_lock || ! sem->count_nonzero ) { + SDL_DestroySemaphore(sem); + return NULL; + } + + return sem; +} + +/* WARNING: + You cannot call this function when another thread is using the semaphore. +*/ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem->count = 0xFFFFFFFF; + while ( sem->waiters_count > 0) { + SDL_CondSignal(sem->count_nonzero); + SDL_Delay(10); + } + SDL_DestroyCond(sem->count_nonzero); + if ( sem->count_lock ) { + SDL_mutexP(sem->count_lock); + SDL_mutexV(sem->count_lock); + SDL_DestroyMutex(sem->count_lock); + } + SDL_free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = SDL_MUTEX_TIMEDOUT; + SDL_LockMutex(sem->count_lock); + if ( sem->count > 0 ) { + --sem->count; + retval = 0; + } + SDL_UnlockMutex(sem->count_lock); + + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* A timeout of 0 is an easy case */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + + SDL_LockMutex(sem->count_lock); + ++sem->waiters_count; + retval = 0; + while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) { + retval = SDL_CondWaitTimeout(sem->count_nonzero, + sem->count_lock, timeout); + } + --sem->waiters_count; + if (retval == 0) { + --sem->count; + } + SDL_UnlockMutex(sem->count_lock); + + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + Uint32 value; + + value = 0; + if ( sem ) { + SDL_LockMutex(sem->count_lock); + value = sem->count; + SDL_UnlockMutex(sem->count_lock); + } + return value; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + SDL_LockMutex(sem->count_lock); + if ( sem->waiters_count > 0 ) { + SDL_CondSignal(sem->count_nonzero); + } + ++sem->count; + SDL_UnlockMutex(sem->count_lock); + + return 0; +} + +#endif /* SDL_THREADS_DISABLED */ diff --git a/3rdparty/SDL/src/thread/generic/SDL_systhread.c b/3rdparty/SDL/src/thread/generic/SDL_systhread.c new file mode 100644 index 0000000..c380121 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_systhread.c @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Thread management routines for SDL */ + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + SDL_SetError("Threads are not supported on this platform"); + return(-1); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return(0); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + return; +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + return; +} + diff --git a/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h b/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h new file mode 100644 index 0000000..1535b50 --- /dev/null +++ b/3rdparty/SDL/src/thread/generic/SDL_systhread_c.h @@ -0,0 +1,25 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Stub until we implement threads on this platform */ +typedef int SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/irix/SDL_syssem.c b/3rdparty/SDL/src/thread/irix/SDL_syssem.c new file mode 100644 index 0000000..208c379 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_syssem.c @@ -0,0 +1,219 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_thread.h" +#include "SDL_timer.h" + + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <errno.h> + +#include "SDL_error.h" +#include "SDL_thread.h" + + +struct SDL_semaphore { + int id; +}; + +/* Not defined by many operating systems, use configure to detect */ +/* +#if !defined(HAVE_SEMUN) +union semun { + int val; + struct semid_ds *buf; + ushort *array; +}; +#endif +*/ + +static struct sembuf op_trywait[2] = { + { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */ +}; +static struct sembuf op_wait[2] = { + { 0, -1, SEM_UNDO } /* Decrement semaphore */ +}; +static struct sembuf op_post[1] = { + { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */ +}; + +/* Create a blockable semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + extern int _creating_thread_lock; /* SDL_threads.c */ + SDL_sem *sem; + union semun init; + + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT)); + if ( sem->id < 0 ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + return(NULL); + } + init.val = initial_value; /* Initialize semaphore */ + semctl(sem->id, 0, SETVAL, init); + return(sem); +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { +#ifdef __IRIX__ + semctl(sem->id, 0, IPC_RMID); +#else + union semun dummy; + dummy.val = 0; + semctl(sem->id, 0, IPC_RMID, dummy); +#endif + SDL_free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_trywait, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + retval = SDL_MUTEX_TIMEDOUT; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_wait, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + SDL_SetError("Semaphore operation error"); + retval = -1; + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + + /* Ack! We have to busy wait... */ + timeout += SDL_GetTicks(); + do { + retval = SDL_SemTryWait(sem); + if ( retval == 0 ) { + break; + } + SDL_Delay(1); + } while ( SDL_GetTicks() < timeout ); + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int semval; + Uint32 value; + + value = 0; + if ( sem ) { + tryagain: +#ifdef __IRIX__ + semval = semctl(sem->id, 0, GETVAL); +#else + { + union semun arg; + arg.val = 0; + semval = semctl(sem->id, 0, GETVAL, arg); + } +#endif + if ( semval < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + } else { + value = (Uint32)semval; + } + } + return value; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = 0; + tryagain: + if ( semop(sem->id, op_post, 1) < 0 ) { + if ( errno == EINTR ) { + goto tryagain; + } + SDL_SetError("Semaphore operation error"); + retval = -1; + } + return retval; +} diff --git a/3rdparty/SDL/src/thread/irix/SDL_systhread.c b/3rdparty/SDL/src/thread/irix/SDL_systhread.c new file mode 100644 index 0000000..7ae7fc6 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_systhread.c @@ -0,0 +1,85 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* IRIX thread management routines for SDL */ + +#include <errno.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/prctl.h> + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + + +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + /* Create the thread and go! */ + if ( sproc(SDL_RunThread, PR_SALL, args) < 0 ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + + /* Mask asynchronous signals for this thread */ + sigemptyset(&mask); + for ( i=0; sig_list[i]; ++i ) { + sigaddset(&mask, sig_list[i]); + } + sigprocmask(SIG_BLOCK, &mask, NULL); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)getpid()); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +void SDL_WaitThread(SDL_Thread *thread, int *status) +{ + errno = 0; + while ( errno != ECHILD ) { + waitpid(thread->handle, NULL, 0); + } +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +void SDL_KillThread(SDL_Thread *thread) +{ + kill(thread->handle, SIGKILL); +} + diff --git a/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h b/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h new file mode 100644 index 0000000..ee28634 --- /dev/null +++ b/3rdparty/SDL/src/thread/irix/SDL_systhread_c.h @@ -0,0 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> + +typedef pid_t SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/os2/SDL_syscond.c b/3rdparty/SDL/src/thread/os2/SDL_syscond.c new file mode 100644 index 0000000..3e80594 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syscond.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 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! + */ + +#include "SDL_thread.h" + +struct SDL_cond +{ + SDL_mutex *lock; + int waiting; + int signals; + SDL_sem *wait_sem; + SDL_sem *wait_done; +}; + +/* Create a condition variable */ +DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + 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 ) { + SDL_DestroyCond(cond); + cond = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(cond); +} + +/* Destroy a condition variable */ +DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + 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 */ +DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(cond->wait_sem); + SDL_UnlockMutex(cond->lock); + SDL_SemWait(cond->wait_done); + } else { + SDL_UnlockMutex(cond->lock); + } + + return 0; +} + +/* Restart all threads that are waiting on the condition variable */ +DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond) +{ + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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_SemPost(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_SemWait(cond->wait_done); + } + } else { + SDL_UnlockMutex(cond->lock); + } + + 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); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + /* 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 */ + if ( ms == SDL_MUTEX_MAXWAIT ) { + retval = SDL_SemWait(cond->wait_sem); + } else { + retval = SDL_SemWaitTimeout(cond->wait_sem, ms); + } + + /* 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_SemWait(cond->wait_sem); + } + /* We always notify the signal thread that we are done */ + SDL_SemPost(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; +} + +/* Wait on the condition variable forever */ +DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h b/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h new file mode 100644 index 0000000..1120b2d --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syscond_c.h @@ -0,0 +1,23 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + diff --git a/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c b/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c new file mode 100644 index 0000000..1e21897 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_sysmutex.c @@ -0,0 +1,108 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Mutex functions using the OS/2 API */ + +#define INCL_DOSERRORS +#define INCL_DOSSEMAPHORES +#include <os2.h> + +#include "SDL_mutex.h" + + +struct SDL_mutex { + HMTX hmtxID; +}; + +/* Create a mutex */ +DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + APIRET ulrc; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if (mutex) + { + /* Create the mutex, with initial value signaled */ + ulrc = DosCreateMutexSem(NULL, // Create unnamed semaphore + &(mutex->hmtxID), // Pointer to handle + 0L, // Flags: create it private (not shared) + FALSE); // Initial value: unowned + if (ulrc!=NO_ERROR) + { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) + { + if ( mutex->hmtxID ) + { + DosCloseMutexSem(mutex->hmtxID); + mutex->hmtxID = 0; + } + SDL_free(mutex); + } +} + +/* Lock the mutex */ +DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) + { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR ) + { + SDL_SetError("Couldn't wait on mutex"); + return -1; + } + return(0); +} + +/* Unlock the mutex */ +DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) + { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR ) + { + SDL_SetError("Couldn't release mutex"); + return -1; + } + return(0); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_syssem.c b/3rdparty/SDL/src/thread/os2/SDL_syssem.c new file mode 100644 index 0000000..d6dfba6 --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_syssem.c @@ -0,0 +1,192 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Semaphore functions using the OS/2 API */ + +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_DOSSEMAPHORES +#include <os2.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" + + +struct SDL_semaphore { + HMTX id; + HEV changed; + Uint32 value; +}; + + +/* Create a semaphore */ +DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + ULONG ulrc; + + /* Allocate sem memory */ + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + /* Create the mutex semaphore */ + ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE); + if ( ulrc ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + sem = NULL; + } else + { + DosCreateEventSem(NULL, &(sem->changed), 0, FALSE); + sem->value = initial_value; + DosReleaseMutexSem(sem->id); + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id ) { + DosCloseEventSem(sem->changed); + DosCloseMutexSem(sem->id); + sem->id = 0; + } + SDL_free(sem); + } +} + +DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + ULONG ulrc; + + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) { + while (1) { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc) { + /* if error waiting mutex */ + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } else if (sem->value) { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else { + ULONG ulPostCount; + DosResetEventSem(sem->changed, &ulPostCount); + DosReleaseMutexSem(sem->id); + /* continue waiting until somebody posts the semaphore */ + DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT); + } + } + } else + if ( timeout == 0 ) + { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc==NO_ERROR) + { + if (sem->value) + { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else + { + DosReleaseMutexSem(sem->id); + return SDL_MUTEX_TIMEDOUT; + } + } else + { + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } + } else { + ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); + if (ulrc) { + /* if error waiting mutex */ + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } else + if (sem->value) { + sem->value--; + DosReleaseMutexSem(sem->id); + return 0; + } else { + ULONG ulPostCount; + DosResetEventSem(sem->changed, &ulPostCount); + DosReleaseMutexSem(sem->id); + /* continue waiting until somebody posts the semaphore */ + ulrc = DosWaitEventSem(sem->changed, timeout); + if (ulrc==NO_ERROR) + return 0; + else + return SDL_MUTEX_TIMEDOUT; + } + } + /* never reached */ + return -1; +} + +DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return sem->value; +} + +DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) { + SDL_SetError("DosRequestMutexSem() failed"); + return -1; + } + sem->value++; + DosPostEventSem(sem->changed); + DosReleaseMutexSem(sem->id); + return 0; +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_systhread.c b/3rdparty/SDL/src/thread/os2/SDL_systhread.c new file mode 100644 index 0000000..33f815a --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_systhread.c @@ -0,0 +1,108 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* OS/2 thread management routines for SDL */ + +#include <process.h> +#define INCL_DOSERRORS +#define INCL_DOSPROCESS +#include <os2.h> + +#include "SDL_thread.h" +#include "../SDL_systhread.h" +#include "../SDL_thread_c.h" + +typedef struct ThreadStartParms +{ + void *args; + pfnSDL_CurrentEndThread pfnCurrentEndThread; +} tThreadStartParms, *pThreadStartParms; + +static void threadfunc(void *pparm) +{ + pThreadStartParms pThreadParms = pparm; + pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; + + // Call the thread function! + SDL_RunThread(pThreadParms->args); + + // Get the current endthread we have to use! + if (pThreadParms) + { + pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; + SDL_free(pThreadParms); + } + // Call endthread! + if (pfnCurrentEndThread) + (*pfnCurrentEndThread)(); +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) +{ + pThreadStartParms pThreadParms = SDL_malloc(sizeof(tThreadStartParms)); + if (!pThreadParms) + { + SDL_SetError("Not enough memory to create thread"); + return(-1); + } + + // Save the function which we will have to call to clear the RTL of calling app! + pThreadParms->pfnCurrentEndThread = pfnEndThread; + // Also save the real parameters we have to pass to thread function + pThreadParms->args = args; + // Start the thread using the runtime library of calling app! + thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, NULL, 512*1024, pThreadParms); + if ((int)thread->threadid <= 0) + { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +DECLSPEC Uint32 SDLCALL SDL_ThreadID(void) +{ + PTIB tib; + DosGetInfoBlocks(&tib, NULL); + return((Uint32) (tib->tib_ptib2->tib2_ultid)); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + TID tid = thread->handle; + DosWaitThread(&tid, DCWW_WAIT); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + DosKillThread(thread->handle); +} diff --git a/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h b/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h new file mode 100644 index 0000000..3b94dfe --- /dev/null +++ b/3rdparty/SDL/src/thread/os2/SDL_systhread_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define INCL_DOSPROCESS +#include <os2.h> + +typedef TID SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/pth/SDL_syscond.c b/3rdparty/SDL/src/thread/pth/SDL_syscond.c new file mode 100644 index 0000000..ede74aa --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_syscond.c @@ -0,0 +1,164 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GNU pth conditions variables + * + * Patrice Mandin + */ + +#include <pth.h> + +#include "SDL_thread.h" +#include "SDL_sysmutex_c.h" + +struct SDL_cond +{ + pth_cond_t condpth_p; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + if ( pth_cond_init(&(cond->condpth_p)) < 0 ) { + SDL_SetError("pthread_cond_init() failed"); + SDL_free(cond); + cond = NULL; + } + } 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) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_notify(&(cond->condpth_p), FALSE) != 0 ) { + SDL_SetError("pth_cond_notify() failed"); + retval = -1; + } + return retval; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_notify(&(cond->condpth_p), TRUE) != 0 ) { + SDL_SetError("pth_cond_notify() failed"); + retval = -1; + } + return retval; +} + +/* 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); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_UnlockMutex(lock); + */ +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + pth_event_t ev; + int sec; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + + sec = ms/1000; + ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000)); + + if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + + pth_event_free(ev, PTH_FREE_ALL); + + return retval; +} + +/* Wait on the condition variable forever */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0 ) { + SDL_SetError("pth_cond_await() failed"); + retval = -1; + } + return retval; +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c b/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c new file mode 100644 index 0000000..ca83b92 --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_sysmutex.c @@ -0,0 +1,87 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GNU pth mutexes + * + * Patrice Mandin + */ + +#include <pth.h> + +#include "SDL_mutex.h" +#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 ) { + /* Create the mutex, with initial value signaled */ + if (!pth_mutex_init(&(mutex->mutexpth_p))) { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL); + + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + pth_mutex_release(&(mutex->mutexpth_p)); + + return(0); +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h new file mode 100644 index 0000000..d29060e --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_sysmutex_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_SYSMUTEX_C_H_ +#define _SDL_SYSMUTEX_C_H_ + +struct SDL_mutex { + pth_mutex_t mutexpth_p; +}; + +#endif /* _SDL_SYSMUTEX_C_H_ */ diff --git a/3rdparty/SDL/src/thread/pth/SDL_systhread.c b/3rdparty/SDL/src/thread/pth/SDL_systhread.c new file mode 100644 index 0000000..bfccaf3 --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_systhread.c @@ -0,0 +1,103 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GNU pth threads + * + * Patrice Mandin + */ + +#include <pth.h> +#include <signal.h> + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +/* List of signals to mask in the subthreads */ +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +static void *RunThread(void *data) +{ + SDL_RunThread(data); + pth_exit((void*)0); + return((void *)0); /* Prevent compiler warning */ +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + pth_attr_t type; + + /* Create a new attribute */ + type = pth_attr_new(); + if ( type == NULL ) { + SDL_SetError("Couldn't initialize pth attributes"); + return(-1); + } + pth_attr_set(type, PTH_ATTR_JOINABLE, TRUE); + + /* Create the thread and go! */ + thread->handle = pth_spawn(type, RunThread, args); + if ( thread->handle == NULL ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + int oldstate; + + /* Mask asynchronous signals for this thread */ + sigemptyset(&mask); + for ( i=0; sig_list[i]; ++i ) { + sigaddset(&mask, sig_list[i]); + } + pth_sigmask(SIG_BLOCK, &mask, 0); + + /* Allow ourselves to be asynchronously cancelled */ + pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, &oldstate); +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)pth_self()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pth_join(thread->handle, NULL); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + pth_cancel(thread->handle); + pth_join(thread->handle, NULL); +} diff --git a/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h b/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h new file mode 100644 index 0000000..50bb26d --- /dev/null +++ b/3rdparty/SDL/src/thread/pth/SDL_systhread_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_SYSTHREAD_C_H_ +#define _SDL_SYSTHREAD_C_H_ + +#include <pth.h> + +typedef pth_t SYS_ThreadHandle; + +#endif /* _SDL_SYSTHREAD_C_H_ */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_syscond.c b/3rdparty/SDL/src/thread/pthread/SDL_syscond.c new file mode 100644 index 0000000..15bce96 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_syscond.c @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/time.h> +#include <unistd.h> +#include <errno.h> +#include <pthread.h> + +#include "SDL_thread.h" +#include "SDL_sysmutex_c.h" + +struct SDL_cond +{ + pthread_cond_t cond; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + if ( pthread_cond_init(&cond->cond, NULL) < 0 ) { + SDL_SetError("pthread_cond_init() failed"); + SDL_free(cond); + cond = NULL; + } + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + pthread_cond_destroy(&cond->cond); + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int SDL_CondSignal(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_signal(&cond->cond) != 0 ) { + SDL_SetError("pthread_cond_signal() failed"); + retval = -1; + } + return retval; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_broadcast(&cond->cond) != 0 ) { + SDL_SetError("pthread_cond_broadcast() failed"); + retval = -1; + } + return retval; +} + +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + struct timeval delta; + struct timespec abstime; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + gettimeofday(&delta, NULL); + + abstime.tv_sec = delta.tv_sec + (ms/1000); + abstime.tv_nsec = (delta.tv_usec + (ms%1000) * 1000) * 1000; + if ( abstime.tv_nsec > 1000000000 ) { + abstime.tv_sec += 1; + abstime.tv_nsec -= 1000000000; + } + + tryagain: + retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); + switch (retval) { + case EINTR: + goto tryagain; + break; + case ETIMEDOUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + case 0: + break; + default: + SDL_SetError("pthread_cond_timedwait() failed"); + retval = -1; + break; + } + return retval; +} + +/* Wait on the condition variable, unlocking the provided mutex. + The mutex must be locked before entering this function! + */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) { + SDL_SetError("pthread_cond_wait() failed"); + retval = -1; + } + return retval; +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c new file mode 100644 index 0000000..c3b8ce2 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex.c @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <pthread.h> + +#include "SDL_thread.h" + +#if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \ + !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP +#define FAKE_RECURSIVE_MUTEX +#endif + +struct SDL_mutex { + pthread_mutex_t id; +#if FAKE_RECURSIVE_MUTEX + int recursive; + pthread_t owner; +#endif +}; + +SDL_mutex *SDL_CreateMutex (void) +{ + SDL_mutex *mutex; + pthread_mutexattr_t attr; + + /* Allocate the structure */ + mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex)); + if ( mutex ) { + pthread_mutexattr_init(&attr); +#if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP + pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); +#else + /* No extra attributes necessary */ +#endif + if ( pthread_mutex_init(&mutex->id, &attr) != 0 ) { + SDL_SetError("pthread_mutex_init() failed"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + pthread_mutex_destroy(&mutex->id); + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + int retval; +#if FAKE_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if FAKE_RECURSIVE_MUTEX + this_thread = pthread_self(); + if ( mutex->owner == this_thread ) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + if ( pthread_mutex_lock(&mutex->id) == 0 ) { + mutex->owner = this_thread; + mutex->recursive = 0; + } else { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } + } +#else + if ( pthread_mutex_lock(&mutex->id) < 0 ) { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } +#endif + return retval; +} + +int SDL_mutexV(SDL_mutex *mutex) +{ + int retval; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if FAKE_RECURSIVE_MUTEX + /* We can only unlock the mutex if we own it */ + if ( pthread_self() == mutex->owner ) { + if ( mutex->recursive ) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + pthread_mutex_unlock(&mutex->id); + } + } else { + SDL_SetError("mutex not owned by this thread"); + retval = -1; + } + +#else + if ( pthread_mutex_unlock(&mutex->id) < 0 ) { + SDL_SetError("pthread_mutex_unlock() failed"); + retval = -1; + } +#endif /* FAKE_RECURSIVE_MUTEX */ + + return retval; +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h new file mode 100644 index 0000000..5258890 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_sysmutex_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_mutex_c_h +#define _SDL_mutex_c_h + +struct SDL_mutex { + pthread_mutex_t id; +}; + +#endif /* _SDL_mutex_c_h */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_syssem.c b/3rdparty/SDL/src/thread/pthread/SDL_syssem.c new file mode 100644 index 0000000..a03870f --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_syssem.c @@ -0,0 +1,190 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <pthread.h> +#include <semaphore.h> +#include <errno.h> +#include <sys/time.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" + +/* Wrapper around POSIX 1003.1b semaphores */ + +#ifdef __MACOSX__ +/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */ +#include "../generic/SDL_syssem.c" +#else + +struct SDL_semaphore { + sem_t sem; +}; + +/* Create a semaphore, initialized with value */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); + if ( sem ) { + if ( sem_init(&sem->sem, 0, initial_value) < 0 ) { + SDL_SetError("sem_init() failed"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return sem; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem_destroy(&sem->sem); + SDL_free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + retval = SDL_MUTEX_TIMEDOUT; + if ( sem_trywait(&sem->sem) == 0 ) { + retval = 0; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} + if ( retval < 0 ) { + SDL_SetError("sem_wait() failed"); + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; +#ifdef HAVE_SEM_TIMEDWAIT + struct timeval now; + struct timespec ts_timeout; +#else + Uint32 end; +#endif + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + +#ifdef HAVE_SEM_TIMEDWAIT + /* Setup the timeout. sem_timedwait doesn't wait for + * a lapse of time, but until we reach a certain time. + * This time is now plus the timeout. + */ + gettimeofday(&now, NULL); + + /* Add our timeout to current time */ + now.tv_usec += (timeout % 1000) * 1000; + now.tv_sec += timeout / 1000; + + /* Wrap the second if needed */ + if ( now.tv_usec >= 1000000 ) { + now.tv_usec -= 1000000; + now.tv_sec ++; + } + + /* Convert to timespec */ + ts_timeout.tv_sec = now.tv_sec; + ts_timeout.tv_nsec = now.tv_usec * 1000; + + /* Wait. */ + do + retval = sem_timedwait(&sem->sem, &ts_timeout); + while (retval == -1 && errno == EINTR); + + if (retval == -1) + SDL_SetError(strerror(errno)); +#else + end = SDL_GetTicks() + timeout; + while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) { + if ((SDL_GetTicks() - end) >= 0) { + break; + } + SDL_Delay(0); + } +#endif /* HAVE_SEM_TIMEDWAIT */ + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int ret = 0; + if ( sem ) { + sem_getvalue(&sem->sem, &ret); + if ( ret < 0 ) { + ret = 0; + } + } + return (Uint32)ret; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_post(&sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_post() failed"); + } + return retval; +} + +#endif /* __MACOSX__ */ diff --git a/3rdparty/SDL/src/thread/pthread/SDL_systhread.c b/3rdparty/SDL/src/thread/pthread/SDL_systhread.c new file mode 100644 index 0000000..40cc3b7 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_systhread.c @@ -0,0 +1,120 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <pthread.h> +#include <signal.h> + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +/* List of signals to mask in the subthreads */ +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +#ifdef __RISCOS__ +/* RISC OS needs to know the main thread for + * it's timer and event processing. */ +int riscos_using_threads = 0; +Uint32 riscos_main_thread = 0; /* Thread running events */ +#endif + + +static void *RunThread(void *data) +{ + SDL_RunThread(data); + pthread_exit((void*)0); + return((void *)0); /* Prevent compiler warning */ +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + pthread_attr_t type; + + /* Set the thread attributes */ + if ( pthread_attr_init(&type) != 0 ) { + SDL_SetError("Couldn't initialize pthread attributes"); + return(-1); + } + pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); + + /* Create the thread and go! */ + if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + +#ifdef __RISCOS__ + if (riscos_using_threads == 0) { + riscos_using_threads = 1; + riscos_main_thread = SDL_ThreadID(); + } +#endif + + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + + /* 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); + +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + /* Allow ourselves to be asynchronously cancelled */ + { int oldstate; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); + } +#endif +} + +/* WARNING: This may not work for systems with 64-bit pid_t */ +Uint32 SDL_ThreadID(void) +{ + return((Uint32)((size_t)pthread_self())); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pthread_join(thread->handle, 0); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_cancel(thread->handle); +#else +#ifdef __FREEBSD__ +#warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2 +#endif + pthread_kill(thread->handle, SIGKILL); +#endif +} diff --git a/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h b/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h new file mode 100644 index 0000000..33ed750 --- /dev/null +++ b/3rdparty/SDL/src/thread/pthread/SDL_systhread_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <pthread.h> + +typedef pthread_t SYS_ThreadHandle; diff --git a/3rdparty/SDL/src/thread/riscos/SDL_syscond.c b/3rdparty/SDL/src/thread/riscos/SDL_syscond.c new file mode 100644 index 0000000..ee55666 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_syscond.c @@ -0,0 +1,160 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* RISC OS implementations uses pthreads based on linux code */ + +#if SDL_THREADS_DISABLED +#include "../generic/SDL_syscond.c" +#else +#include <sys/time.h> +#include <unistd.h> +#include <pthread.h> + +#include "SDL_thread.h" +#include "SDL_sysmutex_c.h" + +struct SDL_cond +{ + pthread_cond_t cond; +}; + +/* Create a condition variable */ +SDL_cond * SDL_CreateCond(void) +{ + SDL_cond *cond; + + cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + if ( cond ) { + if ( pthread_cond_init(&cond->cond, NULL) < 0 ) { + SDL_SetError("pthread_cond_init() failed"); + SDL_free(cond); + cond = NULL; + } + } + return(cond); +} + +/* Destroy a condition variable */ +void SDL_DestroyCond(SDL_cond *cond) +{ + if ( cond ) { + pthread_cond_destroy(&cond->cond); + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int SDL_CondSignal(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_signal(&cond->cond) != 0 ) { + SDL_SetError("pthread_cond_signal() failed"); + retval = -1; + } + return retval; +} + +/* Restart all threads that are waiting on the condition variable */ +int SDL_CondBroadcast(SDL_cond *cond) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_broadcast(&cond->cond) != 0 ) { + SDL_SetError("pthread_cond_broadcast() failed"); + retval = -1; + } + return retval; +} + +int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) +{ + int retval; + struct timeval delta; + struct timespec abstime; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + gettimeofday(&delta, NULL); + + abstime.tv_sec = delta.tv_sec + (ms/1000); + abstime.tv_nsec = (delta.tv_usec + (ms%1000) * 1000) * 1000; + if ( abstime.tv_nsec > 1000000000 ) { + abstime.tv_sec += 1; + abstime.tv_nsec -= 1000000000; + } + + tryagain: + retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); + switch (retval) { + case EINTR: + goto tryagain; + break; + case ETIMEDOUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + case 0: + break; + default: + SDL_SetError("pthread_cond_timedwait() failed"); + retval = -1; + break; + } + return retval; +} + +/* Wait on the condition variable, unlocking the provided mutex. + The mutex must be locked before entering this function! + */ +int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) +{ + int retval; + + if ( ! cond ) { + SDL_SetError("Passed a NULL condition variable"); + return -1; + } + + retval = 0; + if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) { + SDL_SetError("pthread_cond_wait() failed"); + retval = -1; + } + return retval; +} +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c new file mode 100644 index 0000000..e9ac139 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex.c @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* RISC OS implementations uses pthreads based on linux code */ + +#include "SDL_thread.h" + +#if SDL_THREADS_DISABLED +#include "../generic/SDL_sysmutex.c" +#else + +#include <pthread.h> + +struct SDL_mutex { + pthread_mutex_t id; +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + int recursive; + pthread_t owner; +#endif +}; + +SDL_mutex *SDL_CreateMutex (void) +{ + SDL_mutex *mutex; + pthread_mutexattr_t attr; + + /* Allocate the structure */ + mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex)); + if ( mutex ) { + pthread_mutexattr_init(&attr); +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + /* No extra attributes necessary */ +#else + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ + if ( pthread_mutex_init(&mutex->id, &attr) != 0 ) { + SDL_SetError("pthread_mutex_init() failed"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + pthread_mutex_destroy(&mutex->id); + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + int retval; +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + this_thread = pthread_self(); + if ( mutex->owner == this_thread ) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + if ( pthread_mutex_lock(&mutex->id) == 0 ) { + mutex->owner = this_thread; + mutex->recursive = 0; + } else { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } + } +#else + if ( pthread_mutex_lock(&mutex->id) < 0 ) { + SDL_SetError("pthread_mutex_lock() failed"); + retval = -1; + } +#endif + return retval; +} + +int SDL_mutexV(SDL_mutex *mutex) +{ + int retval; + + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX + /* We can only unlock the mutex if we own it */ + if ( pthread_self() == mutex->owner ) { + if ( mutex->recursive ) { + --mutex->recursive; + } else { + /* The order of operations is important. + First reset the owner so another thread doesn't lock + the mutex and set the ownership before we reset it, + then release the lock semaphore. + */ + mutex->owner = 0; + pthread_mutex_unlock(&mutex->id); + } + } else { + SDL_SetError("mutex not owned by this thread"); + retval = -1; + } + +#else + if ( pthread_mutex_unlock(&mutex->id) < 0 ) { + SDL_SetError("pthread_mutex_unlock() failed"); + retval = -1; + } +#endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ + + return retval; +} +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h new file mode 100644 index 0000000..2391c3c --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_sysmutex_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_mutex_c_h +#define _SDL_mutex_c_h + +#if !SDL_THREADS_DISABLED +struct SDL_mutex { + pthread_mutex_t id; +}; +#endif + + +#endif /* _SDL_mutex_c_h */ diff --git a/3rdparty/SDL/src/thread/riscos/SDL_syssem.c b/3rdparty/SDL/src/thread/riscos/SDL_syssem.c new file mode 100644 index 0000000..127211b --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_syssem.c @@ -0,0 +1,203 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include <errno.h> + +#include "SDL_config.h" + +/* RISC OS semiphores based on linux code */ + + +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + +#if !SDL_THREADS_DISABLED + +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_SetError("SDL not configured with thread support"); + return (SDL_sem *)0; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + return; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +int SDL_SemWait(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + return 0; +} + +int SDL_SemPost(SDL_sem *sem) +{ + SDL_SetError("SDL not configured with thread support"); + return -1; +} + +#else + + +#include <unistd.h> /* For getpid() */ +#include <pthread.h> +#include <semaphore.h> + +struct SDL_semaphore { + sem_t *sem; + sem_t sem_data; +}; + +/* Create a semaphore, initialized with value */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); + if ( sem ) { + if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { + SDL_SetError("sem_init() failed"); + SDL_free(sem); + sem = NULL; + } else { + sem->sem = &sem->sem_data; + } + } else { + SDL_OutOfMemory(); + } + return sem; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem_destroy(sem->sem); + SDL_free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + retval = SDL_MUTEX_TIMEDOUT; + if ( sem_trywait(sem->sem) == 0 ) { + retval = 0; + } + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + while ( ((retval = sem_wait(sem->sem)) == -1) && (errno == EINTR) ) {} + if ( retval < 0 ) { + SDL_SetError("sem_wait() failed"); + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + + /* Ack! We have to busy wait... */ + timeout += SDL_GetTicks(); + do { + retval = SDL_SemTryWait(sem); + if ( retval == 0 ) { + break; + } + SDL_Delay(1); + } while ( SDL_GetTicks() < timeout ); + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int ret = 0; + if ( sem ) { + sem_getvalue(sem->sem, &ret); + if ( ret < 0 ) { + ret = 0; + } + } + return (Uint32)ret; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_post(sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_post() failed"); + } + return retval; +} + +#endif /* !SDL_THREADS_DISABLED */ diff --git a/3rdparty/SDL/src/thread/riscos/SDL_systhread.c b/3rdparty/SDL/src/thread/riscos/SDL_systhread.c new file mode 100644 index 0000000..38fc333 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_systhread.c @@ -0,0 +1,144 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* RISC OS version based on pthreads linux source */ + +#include "SDL_thread.h" +#include "../SDL_systhread.h" + +#if SDL_THREADS_DISABLED + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + SDL_SetError("Threads have not been compiled into this version of the library"); + return(-1); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return(0); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + return; +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + return; +} + +#else + +#include <signal.h> + +/* List of signals to mask in the subthreads */ +static int sig_list[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, + SIGVTALRM, SIGPROF, 0 +}; + +#include <pthread.h> + +int riscos_using_threads = 0; +Uint32 riscos_main_thread = 0; /* Thread running events */ + +static void *RunThread(void *data) +{ + SDL_RunThread(data); + pthread_exit((void*)0); + return((void *)0); /* Prevent compiler warning */ +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + pthread_attr_t type; + + /* Set the thread attributes */ + if ( pthread_attr_init(&type) != 0 ) { + SDL_SetError("Couldn't initialize pthread attributes"); + return(-1); + } + pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); + + /* Create the thread and go! */ + if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + + if (riscos_using_threads == 0) + { + riscos_using_threads = 1; + riscos_main_thread = SDL_ThreadID(); + } + + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + int i; + sigset_t mask; + + /* 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); + +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + /* Allow ourselves to be asynchronously cancelled */ + { int oldstate; + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); + } +#endif +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)pthread_self()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + pthread_join(thread->handle, 0); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ +#ifdef PTHREAD_CANCEL_ASYNCHRONOUS + pthread_cancel(thread->handle); +#else + pthread_kill(thread->handle, SIGKILL); +#endif +} + +#endif diff --git a/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h b/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h new file mode 100644 index 0000000..9e1d2c8 --- /dev/null +++ b/3rdparty/SDL/src/thread/riscos/SDL_systhread_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if SDL_THREADS_DISABLED + +typedef int SYS_ThreadHandle; + +#else + +#include <pthread.h> + +typedef pthread_t SYS_ThreadHandle; + +#endif diff --git a/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp b/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp new file mode 100644 index 0000000..f4b1aea --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_sysmutex.cpp @@ -0,0 +1,130 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_sysmutex.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_sysmutex.c,v 1.1.2.3 2000/06/22 15:25:23 hercules Exp $"; +#endif + +/* Mutex functions using the Win32 API */ + +//#include <stdio.h> +//#include <stdlib.h> + +#include <e32std.h> + +#include "epoc_sdl.h" + +#include "SDL_error.h" +#include "SDL_mutex.h" + + +#ifdef EKA2 //??? +struct SDL_mutex + { + TInt handle; + }; +#else +struct _SDL_mutex + { + TInt handle; + }; +#endif + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); + +TInt NewMutex(const TDesC& aName, TAny* aPtr1, TAny*) + { + return ((RMutex*)aPtr1)->CreateGlobal(aName); + } + +void DeleteMutex(TAny* aMutex) + { + SDL_DestroyMutex ((SDL_mutex*) aMutex); + } + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + RMutex rmutex; + + TInt status = CreateUnique(NewMutex, &rmutex, NULL); + if(status != KErrNone) + { + SDL_SetError("Couldn't create mutex"); + } + SDL_mutex* mutex = new /*(ELeave)*/ SDL_mutex; + mutex->handle = rmutex.Handle(); + EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem(DeleteMutex, mutex)); + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) + { + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + if(rmutex.IsHeld()) + { + rmutex.Signal(); + } + rmutex.Close(); + EpocSdlEnv::RemoveCleanupItem(mutex); + delete(mutex); + mutex = NULL; + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Wait(); + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + RMutex rmutex; + rmutex.SetHandle(mutex->handle); + rmutex.Signal(); + return(0); +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp b/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp new file mode 100644 index 0000000..00f9901 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_syssem.cpp @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_syssem.cpp + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_syssem.c,v 1.1.2.4 2000/06/22 15:24:48 hercules Exp $"; +#endif + +/* Semaphore functions using the Win32 API */ + +//#include <stdio.h> +//#include <stdlib.h> +#include <e32std.h> + +#include "SDL_error.h" +#include "SDL_thread.h" + + +#define SDL_MUTEX_TIMEOUT -2 + +struct SDL_semaphore + { + TInt handle; + TInt count; + }; + + +extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); +#ifndef EKA2 +extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2); +#endif + +TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + TInt value = *((TInt*) aPtr2); + return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value); + } + +/* Create a semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + RSemaphore s; + TInt status = CreateUnique(NewSema, &s, &initial_value); + if(status != KErrNone) + { + SDL_SetError("Couldn't create semaphore"); + } + SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore; + sem->handle = s.Handle(); + sem->count = initial_value; + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) + { + RSemaphore sema; + sema.SetHandle(sem->handle); + while(--sem->count) + sema.Signal(); + sema.Close(); + delete sem; + sem = NULL; + } +} + +#ifndef EKA2 + + struct TInfo + { + TInfo(TInt aTime, TInt aHandle) : + iTime(aTime), iHandle(aHandle), iVal(0) {} + TInt iTime; + TInt iHandle; + TInt iVal; + }; + + + +TBool ThreadRun(TAny* aInfo) + { + TInfo* info = STATIC_CAST(TInfo*, aInfo); + User::After(info->iTime); + RSemaphore sema; + sema.SetHandle(info->iHandle); + sema.Signal(); + info->iVal = SDL_MUTEX_TIMEOUT; + return 0; + } + +#endif + + +void _WaitAll(SDL_sem *sem) + { + //since SemTryWait may changed the counter. + //this may not be atomic, but hopes it works. + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Wait(); + while(sem->count < 0) + { + sema.Wait(); + } + } + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) + { + _WaitAll(sem); + return SDL_MUTEX_MAXWAIT; + } + +#ifdef EKA2 + + RSemaphore sema; + sema.SetHandle(sem->handle); + if(KErrNone == sema.Wait(timeout)) + return 0; + return -1; +#else + RThread thread; + + TInfo* info = new (ELeave)TInfo(timeout, sem->handle); + + TInt status = CreateUnique(NewThread, &thread, info); + + if(status != KErrNone) + return status; + + thread.Resume(); + + _WaitAll(sem); + + if(thread.ExitType() == EExitPending) + { + thread.Kill(SDL_MUTEX_TIMEOUT); + } + + thread.Close(); + + return info->iVal; +#endif +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + if(sem->count > 0) + { + sem->count--; + } + return SDL_MUTEX_TIMEOUT; +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return sem->count; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + sem->count++; + RSemaphore sema; + sema.SetHandle(sem->handle); + sema.Signal(); + return 0; +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp b/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp new file mode 100644 index 0000000..5e7adc5 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_systhread.cpp @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread.cpp + Epoc thread management routines for SDL + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +#include "epoc_sdl.h" + +//#include <stdlib.h> +//#include <stdio.h> + + + +extern "C" { +#undef NULL +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_systhread.h" +#include "SDL_thread_c.h" + } + +#include <e32std.h> +#include "epoc_sdl.h" + + +static int object_count; + +int RunThread(TAny* data) +{ + CTrapCleanup* cleanup = CTrapCleanup::New(); + TRAPD(err, SDL_RunThread(data)); + EpocSdlEnv::CleanupItems(); + delete cleanup; + return(err); +} + + +TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) + { + return ((RThread*)(aPtr1))->Create(aName, + RunThread, + KDefaultStackSize, + NULL, + aPtr2); + } + +int CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny* aPtr1, TAny* aPtr2) + { + TBuf<16> name; + TInt status = KErrNone; + do + { + object_count++; + name.Format(_L("SDL_%x"), object_count); + status = aFunc(name, aPtr1, aPtr2); + } + while(status == KErrAlreadyExists); + return status; + } + + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + RThread rthread; + + const TInt status = CreateUnique(NewThread, &rthread, args); + if (status != KErrNone) + { + delete(((RThread*)(thread->handle))); + thread->handle = NULL; + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + rthread.Resume(); + thread->handle = rthread.Handle(); + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + RThread current; + const TThreadId id = current.Id(); + return id; +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + SDL_TRACE1("Close thread", thread); + RThread t; + const TInt err = t.Open(thread->threadid); + if(err == KErrNone && t.ExitType() == EExitPending) + { + TRequestStatus status; + t.Logon(status); + User::WaitForRequest(status); + } + t.Close(); + + /* RUndertaker taker; + taker.Create(); + TRequestStatus status; + taker.Logon(status, thread->handle); + User::WaitForRequest(status); + taker.Close();*/ + SDL_TRACE1("Closed thread", thread); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + RThread rthread; + rthread.SetHandle(thread->handle); + rthread.Kill(0); + rthread.Close(); +} diff --git a/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h b/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h new file mode 100644 index 0000000..f5f1729 --- /dev/null +++ b/3rdparty/SDL/src/thread/symbian/SDL_systhread_c.h @@ -0,0 +1,30 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systhread_c.h + + Epoc version by Markus Mertama (w@iki.fi) +*/ + +typedef int SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c b/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c new file mode 100644 index 0000000..1d7805c --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_sysmutex.c @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Mutex functions using the Win32 API */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_mutex.h" + + +struct SDL_mutex { + HANDLE id; +}; + +/* Create a mutex */ +SDL_mutex *SDL_CreateMutex(void) +{ + SDL_mutex *mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); + if ( mutex ) { + /* Create the mutex, with initial value signaled */ + mutex->id = CreateMutex(NULL, FALSE, NULL); + if ( ! mutex->id ) { + SDL_SetError("Couldn't create mutex"); + SDL_free(mutex); + mutex = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(mutex); +} + +/* Free the mutex */ +void SDL_DestroyMutex(SDL_mutex *mutex) +{ + if ( mutex ) { + if ( mutex->id ) { + CloseHandle(mutex->id); + mutex->id = 0; + } + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int SDL_mutexP(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( WaitForSingleObject(mutex->id, INFINITE) == WAIT_FAILED ) { + SDL_SetError("Couldn't wait on mutex"); + return -1; + } + return(0); +} + +/* Unlock the mutex */ +int SDL_mutexV(SDL_mutex *mutex) +{ + if ( mutex == NULL ) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + if ( ReleaseMutex(mutex->id) == FALSE ) { + SDL_SetError("Couldn't release mutex"); + return -1; + } + return(0); +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_syssem.c b/3rdparty/SDL/src/thread/win32/SDL_syssem.c new file mode 100644 index 0000000..261d24c --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_syssem.c @@ -0,0 +1,164 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Semaphore functions using the Win32 API */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_thread.h" +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) +#include "win_ce_semaphore.h" +#endif + + +struct SDL_semaphore { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + SYNCHHANDLE id; +#else + HANDLE id; +#endif + volatile LONG count; +}; + + +/* Create a semaphore */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + /* Allocate sem memory */ + sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); + if ( sem ) { + /* Create the semaphore, with max value 32K */ +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL); +#else + sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL); +#endif + sem->count = (LONG) initial_value; + if ( ! sem->id ) { + SDL_SetError("Couldn't create semaphore"); + SDL_free(sem); + sem = NULL; + } + } else { + SDL_OutOfMemory(); + } + return(sem); +} + +/* Free the semaphore */ +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + if ( sem->id ) { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + CloseSynchHandle(sem->id); +#else + CloseHandle(sem->id); +#endif + sem->id = 0; + } + SDL_free(sem); + } +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + DWORD dwMilliseconds; + + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + + if ( timeout == SDL_MUTEX_MAXWAIT ) { + dwMilliseconds = INFINITE; + } else { + dwMilliseconds = (DWORD)timeout; + } +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) { +#else + switch (WaitForSingleObject(sem->id, dwMilliseconds)) { +#endif + case WAIT_OBJECT_0: + InterlockedDecrement(&sem->count); + retval = 0; + break; + case WAIT_TIMEOUT: + retval = SDL_MUTEX_TIMEDOUT; + break; + default: + SDL_SetError("WaitForSingleObject() failed"); + retval = -1; + break; + } + return retval; +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +int SDL_SemWait(SDL_sem *sem) +{ + return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); +} + +/* Returns the current count of the semaphore */ +Uint32 SDL_SemValue(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return 0; + } + return (Uint32) sem->count; +} + +int SDL_SemPost(SDL_sem *sem) +{ + if ( ! sem ) { + SDL_SetError("Passed a NULL sem"); + return -1; + } + /* Increase the counter in the first place, because + * after a successful release the semaphore may + * immediately get destroyed by another thread which + * is waiting for this semaphore. + */ + InterlockedIncrement(&sem->count); +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) { +#else + if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) { +#endif + InterlockedDecrement(&sem->count); /* restore */ + SDL_SetError("ReleaseSemaphore() failed"); + return -1; + } + return 0; +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_systhread.c b/3rdparty/SDL/src/thread/win32/SDL_systhread.c new file mode 100644 index 0000000..55cb88a --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_systhread.c @@ -0,0 +1,162 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Win32 thread management routines for SDL */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" + +#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD +#ifndef _WIN32_WCE +/* We'll use the C library from this DLL */ +#include <process.h> +#endif + +#if defined(__WATCOMC__) +/* This is for Watcom targets except OS2 */ +#if __WATCOMC__ < 1240 +#define __watcall +#endif +typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code); +#elif (defined(__MINGW32__) && (__GNUC__ < 4)) +typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); +#else +typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, + unsigned (__stdcall *func)(void *), void *arg, + unsigned, unsigned *threadID); +typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); +#endif +#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ + + +typedef struct ThreadStartParms +{ + void *args; + pfnSDL_CurrentEndThread pfnCurrentEndThread; +} tThreadStartParms, *pThreadStartParms; + +static DWORD RunThread(void *data) +{ + pThreadStartParms pThreadParms = (pThreadStartParms)data; + pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; + + // Call the thread function! + SDL_RunThread(pThreadParms->args); + + // Get the current endthread we have to use! + if (pThreadParms) + { + pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; + SDL_free(pThreadParms); + } + // Call endthread! + if (pfnCurrentEndThread) + (*pfnCurrentEndThread)(0); + return(0); +} + +static DWORD WINAPI RunThreadViaCreateThread(LPVOID data) +{ + return RunThread(data); +} + +static unsigned __stdcall RunThreadViaBeginThreadEx(void *data) +{ + return (unsigned) RunThread(data); +} + +#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) +{ +#else +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ +#ifdef _WIN32_WCE + pfnSDL_CurrentBeginThread pfnBeginThread = NULL; + pfnSDL_CurrentEndThread pfnEndThread = NULL; +#else + pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex; + pfnSDL_CurrentEndThread pfnEndThread = _endthreadex; +#endif +#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ + pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms)); + if (!pThreadParms) { + SDL_OutOfMemory(); + return(-1); + } + + // Save the function which we will have to call to clear the RTL of calling app! + pThreadParms->pfnCurrentEndThread = pfnEndThread; + // Also save the real parameters we have to pass to thread function + pThreadParms->args = args; + + if (pfnBeginThread) { + unsigned threadid = 0; + thread->handle = (SYS_ThreadHandle) + ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx, + pThreadParms, 0, &threadid)); + } else { + DWORD threadid = 0; + thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread, pThreadParms, 0, &threadid); + } + if (thread->handle == NULL) { + SDL_SetError("Not enough resources to create thread"); + return(-1); + } + return(0); +} + +void SDL_SYS_SetupThread(void) +{ + return; +} + +Uint32 SDL_ThreadID(void) +{ + return((Uint32)GetCurrentThreadId()); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + WaitForSingleObject(thread->handle, INFINITE); + CloseHandle(thread->handle); +} + +/* WARNING: This function is really a last resort. + * Threads should be signaled and then exit by themselves. + * TerminateThread() doesn't perform stack and DLL cleanup. + */ +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + TerminateThread(thread->handle, FALSE); +} diff --git a/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h b/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h new file mode 100644 index 0000000..10b0a7d --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/SDL_systhread_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +typedef HANDLE SYS_ThreadHandle; + diff --git a/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c new file mode 100644 index 0000000..9db45c4 --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.c @@ -0,0 +1,216 @@ +/* win_ce_semaphore.c + + Copyright (c) 1998, Johnson M. Hart + (with corrections 2001 by Rainer Loritz) + Permission is granted for any and all use providing that this + copyright is properly acknowledged. + There are no assurances of suitability for any use whatsoever. + + WINDOWS CE: There is a collection of Windows CE functions to simulate + semaphores using only a mutex and an event. As Windows CE events cannot + be named, these simulated semaphores cannot be named either. + + Implementation notes: + 1. All required internal data structures are allocated on the process's heap. + 2. Where appropriate, a new error code is returned (see the header + file), or, if the error is a Win32 error, that code is unchanged. + 3. Notice the new handle type "SYNCHHANDLE" that has handles, counters, + and other information. This structure will grow as new objects are added + to this set; some members are specific to only one or two of the objects. + 4. Mutexes are used for critical sections. These could be replaced with + CRITICAL_SECTION objects but then this would give up the time out + capability. + 5. The implementation shows several interesting aspects of synchronization, some + of which are specific to Win32 and some of which are general. These are pointed + out in the comments as appropriate. + 6. The wait function emulates WaitForSingleObject only. An emulation of + WaitForMultipleObjects is much harder to implement outside the kernel, + and it is not clear how to handle a mixture of WCE semaphores and normal + events and mutexes. */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "win_ce_semaphore.h" + +static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); + +SYNCHHANDLE CreateSemaphoreCE ( + + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ + LONG lInitialCount, /* initial count */ + LONG lMaximumCount, /* maximum count */ + LPCTSTR lpName ) + +/* Semaphore for use with Windows CE that does not support them directly. + Requires a counter, a mutex to protect the counter, and an + autoreset event. + + Here are the rules that must always hold between the autoreset event + and the mutex (any violation of these rules by the CE semaphore functions + will, in all likelihood, result in a defect): + 1. No thread can set, pulse, or reset the event, + nor can it access any part of the SYNCHHANDLE structure, + without first gaining ownership of the mutex. + BUT, a thread can wait on the event without owning the mutex + (this is clearly necessary or else the event could never be set). + 2. The event is in a signaled state if and only if the current semaphore + count ("CurCount") is greater than zero. + 3. The semaphore count is always >= 0 and <= the maximum count */ + +{ + SYNCHHANDLE hSynch = NULL, result = NULL; + + __try + { + if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0) + { + /* Bad parameters */ + SetLastError (SYNCH_ERROR); + __leave; + } + + hSynch = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE); + if (hSynch == NULL) __leave; + + hSynch->MaxCount = lMaximumCount; + hSynch->CurCount = lInitialCount; + hSynch->lpName = lpName; + + hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); + + WaitForSingleObject (hSynch->hMutex, INFINITE); + /* Create the event. It is initially signaled if and only if the + initial count is > 0 */ + hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, + lInitialCount > 0, NULL); + ReleaseMutex (hSynch->hMutex); + hSynch->hSemph = NULL; + } + __finally + { + /* Return with the handle, or, if there was any error, return + a null after closing any open handles and freeing any allocated memory. */ + result=CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */); + } + + return result; +} + +BOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount) +/* Windows CE equivalent to ReleaseSemaphore. */ +{ + BOOL Result = TRUE; + + /* Gain access to the object to assure that the release count + would not cause the total count to exceed the maximum. */ + + __try + { + WaitForSingleObject (hSemCE->hMutex, INFINITE); + /* reply only if asked to */ + if (lpPreviousCount!=NULL) + *lpPreviousCount = hSemCE->CurCount; + if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount || cReleaseCount <= 0) + { + SetLastError (SYNCH_ERROR); + Result = FALSE; + __leave; + } + hSemCE->CurCount += cReleaseCount; + + /* Set the autoreset event, releasing exactly one waiting thread, now or + in the future. */ + + SetEvent (hSemCE->hEvent); + } + __finally + { + ReleaseMutex (hSemCE->hMutex); + } + + return Result; +} + +DWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) + /* Windows CE semaphore equivalent of WaitForSingleObject. */ +{ + DWORD WaitResult; + + WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; + while (hSemCE->CurCount <= 0) + { + + /* The count is 0, and the thread must wait on the event (which, by + the rules, is currently reset) for semaphore resources to become + available. First, of course, the mutex must be released so that another + thread will be capable of setting the event. */ + + ReleaseMutex (hSemCE->hMutex); + + /* Wait for the event to be signaled, indicating a semaphore state change. + The event is autoreset and signaled with a SetEvent (not PulseEvent) + so exactly one waiting thread (whether or not there is currently + a waiting thread) is released as a result of the SetEvent. */ + + WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0) return WaitResult; + + /* This is where the properties of setting of an autoreset event is critical + to assure that, even if the semaphore state changes between the + preceding Wait and the next, and even if NO threads are waiting + on the event at the time of the SetEvent, at least one thread + will be released. + Pulsing a manual reset event would appear to work, but it would have + a defect which could appear if the semaphore state changed between + the two waits. */ + + WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); + if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; + + } + /* The count is not zero and this thread owns the mutex. */ + + hSemCE->CurCount--; + /* The event is now unsignaled, BUT, the semaphore count may not be + zero, in which case the event should be signaled again + before releasing the mutex. */ + + if (hSemCE->CurCount > 0) SetEvent (hSemCE->hEvent); + ReleaseMutex (hSemCE->hMutex); + return WaitResult; +} + +BOOL CloseSynchHandle (SYNCHHANDLE hSynch) +/* Close a synchronization handle. + Improvement: Test for a valid handle before dereferencing the handle. */ +{ + BOOL Result = TRUE; + if (hSynch->hEvent != NULL) Result = Result && CloseHandle (hSynch->hEvent); + if (hSynch->hMutex != NULL) Result = Result && CloseHandle (hSynch->hMutex); + if (hSynch->hSemph != NULL) Result = Result && CloseHandle (hSynch->hSemph); + HeapFree (GetProcessHeap (), 0, hSynch); + return (Result); +} + +static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags) +{ /* Prepare to return from a create of a synchronization handle. + If there was any failure, free any allocated resources. + "Flags" indicates which Win32 objects are required in the + synchronization handle. */ + + BOOL ok = TRUE; + + if (hSynch == NULL) return NULL; + if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; + if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE; + if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; + if (!ok) + { + CloseSynchHandle (hSynch); + return NULL; + } + /* Everything worked */ + return hSynch; +} diff --git a/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h new file mode 100644 index 0000000..af2d7b6 --- /dev/null +++ b/3rdparty/SDL/src/thread/win32/win_ce_semaphore.h @@ -0,0 +1,22 @@ +/* win_ce_semaphore.h - header file to go with win_ce_semaphore.c */ + +typedef struct _SYNCH_HANDLE_STRUCTURE { + HANDLE hEvent; + HANDLE hMutex; + HANDLE hSemph; + LONG MaxCount; + volatile LONG CurCount; + LPCTSTR lpName; +} SYNCH_HANDLE_STRUCTURE, *SYNCHHANDLE; + +#define SYNCH_HANDLE_SIZE sizeof (SYNCH_HANDLE_STRUCTURE) + + /* Error codes - all must have bit 29 set */ +#define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */ + +extern SYNCHHANDLE CreateSemaphoreCE (LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR); + +extern BOOL ReleaseSemaphoreCE (SYNCHHANDLE, LONG, LPLONG); +extern DWORD WaitForSemaphoreCE (SYNCHHANDLE, DWORD); + +extern BOOL CloseSynchHandle (SYNCHHANDLE); diff --git a/3rdparty/SDL/src/timer/SDL_systimer.h b/3rdparty/SDL/src/timer/SDL_systimer.h new file mode 100644 index 0000000..d19b679 --- /dev/null +++ b/3rdparty/SDL/src/timer/SDL_systimer.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* The system dependent timer handling functions */ + +#include "SDL_timer.h" +#include "SDL_timer_c.h" + + +/* Initialize the system dependent timer subsystem */ +extern int SDL_SYS_TimerInit(void); + +/* Quit the system dependent timer subsystem */ +extern void SDL_SYS_TimerQuit(void); + +/* Start a timer set up by SDL_SetTimer() */ +extern int SDL_SYS_StartTimer(void); + +/* Stop a previously started timer */ +extern void SDL_SYS_StopTimer(void); diff --git a/3rdparty/SDL/src/timer/SDL_timer.c b/3rdparty/SDL/src/timer/SDL_timer.c new file mode 100644 index 0000000..8d137e1 --- /dev/null +++ b/3rdparty/SDL/src/timer/SDL_timer.c @@ -0,0 +1,285 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_timer.h" +#include "SDL_timer_c.h" +#include "SDL_mutex.h" +#include "SDL_systimer.h" + +/* #define DEBUG_TIMERS */ + +int SDL_timer_started = 0; +int SDL_timer_running = 0; + +/* Data to handle a single periodic alarm */ +Uint32 SDL_alarm_interval = 0; +SDL_TimerCallback SDL_alarm_callback; + +/* Data used for a thread-based timer */ +static int SDL_timer_threaded = 0; + +struct _SDL_TimerID { + Uint32 interval; + SDL_NewTimerCallback cb; + void *param; + Uint32 last_alarm; + struct _SDL_TimerID *next; +}; + +static SDL_TimerID SDL_timers = NULL; +static SDL_mutex *SDL_timer_mutex; +static volatile SDL_bool list_changed = SDL_FALSE; + +/* Set whether or not the timer should use a thread. + This should not be called while the timer subsystem is running. +*/ +int SDL_SetTimerThreaded(int value) +{ + int retval; + + if ( SDL_timer_started ) { + SDL_SetError("Timer already initialized"); + retval = -1; + } else { + retval = 0; + SDL_timer_threaded = value; + } + return retval; +} + +int SDL_TimerInit(void) +{ + int retval; + + retval = 0; + if ( SDL_timer_started ) { + SDL_TimerQuit(); + } + if ( ! SDL_timer_threaded ) { + retval = SDL_SYS_TimerInit(); + } + if ( SDL_timer_threaded ) { + SDL_timer_mutex = SDL_CreateMutex(); + } + if ( retval == 0 ) { + SDL_timer_started = 1; + } + return(retval); +} + +void SDL_TimerQuit(void) +{ + SDL_SetTimer(0, NULL); + if ( SDL_timer_threaded < 2 ) { + SDL_SYS_TimerQuit(); + } + if ( SDL_timer_threaded ) { + SDL_DestroyMutex(SDL_timer_mutex); + SDL_timer_mutex = NULL; + } + SDL_timer_started = 0; + SDL_timer_threaded = 0; +} + +void SDL_ThreadedTimerCheck(void) +{ + Uint32 now, ms; + SDL_TimerID t, prev, next; + SDL_bool removed; + + SDL_mutexP(SDL_timer_mutex); + list_changed = SDL_FALSE; + now = SDL_GetTicks(); + for ( prev = NULL, t = SDL_timers; t; t = next ) { + removed = SDL_FALSE; + ms = t->interval - SDL_TIMESLICE; + next = t->next; + if ( (int)(now - t->last_alarm) > (int)ms ) { + struct _SDL_TimerID timer; + + if ( (now - t->last_alarm) < t->interval ) { + t->last_alarm += t->interval; + } else { + t->last_alarm = now; + } +#ifdef DEBUG_TIMERS + printf("Executing timer %p (thread = %d)\n", + t, SDL_ThreadID()); +#endif + timer = *t; + SDL_mutexV(SDL_timer_mutex); + ms = timer.cb(timer.interval, timer.param); + SDL_mutexP(SDL_timer_mutex); + if ( list_changed ) { + /* Abort, list of timers modified */ + /* FIXME: what if ms was changed? */ + break; + } + if ( ms != t->interval ) { + if ( ms ) { + t->interval = ROUND_RESOLUTION(ms); + } else { + /* Remove timer from the list */ +#ifdef DEBUG_TIMERS + printf("SDL: Removing timer %p\n", t); +#endif + if ( prev ) { + prev->next = next; + } else { + SDL_timers = next; + } + SDL_free(t); + --SDL_timer_running; + removed = SDL_TRUE; + } + } + } + /* Don't update prev if the timer has disappeared */ + if ( ! removed ) { + prev = t; + } + } + SDL_mutexV(SDL_timer_mutex); +} + +static SDL_TimerID SDL_AddTimerInternal(Uint32 interval, SDL_NewTimerCallback callback, void *param) +{ + SDL_TimerID t; + t = (SDL_TimerID) SDL_malloc(sizeof(struct _SDL_TimerID)); + if ( t ) { + t->interval = ROUND_RESOLUTION(interval); + t->cb = callback; + t->param = param; + t->last_alarm = SDL_GetTicks(); + t->next = SDL_timers; + SDL_timers = t; + ++SDL_timer_running; + list_changed = SDL_TRUE; + } +#ifdef DEBUG_TIMERS + printf("SDL_AddTimer(%d) = %08x num_timers = %d\n", interval, (Uint32)t, SDL_timer_running); +#endif + return t; +} + +SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param) +{ + SDL_TimerID t; + if ( ! SDL_timer_mutex ) { + if ( SDL_timer_started ) { + SDL_SetError("This platform doesn't support multiple timers"); + } else { + SDL_SetError("You must call SDL_Init(SDL_INIT_TIMER) first"); + } + return NULL; + } + if ( ! SDL_timer_threaded ) { + SDL_SetError("Multiple timers require threaded events!"); + return NULL; + } + SDL_mutexP(SDL_timer_mutex); + t = SDL_AddTimerInternal(interval, callback, param); + SDL_mutexV(SDL_timer_mutex); + return t; +} + +SDL_bool SDL_RemoveTimer(SDL_TimerID id) +{ + SDL_TimerID t, prev = NULL; + SDL_bool removed; + + removed = SDL_FALSE; + SDL_mutexP(SDL_timer_mutex); + /* Look for id in the linked list of timers */ + for (t = SDL_timers; t; prev=t, t = t->next ) { + if ( t == id ) { + if(prev) { + prev->next = t->next; + } else { + SDL_timers = t->next; + } + SDL_free(t); + --SDL_timer_running; + removed = SDL_TRUE; + list_changed = SDL_TRUE; + break; + } + } +#ifdef DEBUG_TIMERS + printf("SDL_RemoveTimer(%08x) = %d num_timers = %d thread = %d\n", (Uint32)id, removed, SDL_timer_running, SDL_ThreadID()); +#endif + SDL_mutexV(SDL_timer_mutex); + return removed; +} + +/* Old style callback functions are wrapped through this */ +static Uint32 SDLCALL callback_wrapper(Uint32 ms, void *param) +{ + SDL_TimerCallback func = (SDL_TimerCallback) param; + return (*func)(ms); +} + +int SDL_SetTimer(Uint32 ms, SDL_TimerCallback callback) +{ + int retval; + +#ifdef DEBUG_TIMERS + printf("SDL_SetTimer(%d)\n", ms); +#endif + retval = 0; + + if ( SDL_timer_threaded ) { + SDL_mutexP(SDL_timer_mutex); + } + if ( SDL_timer_running ) { /* Stop any currently running timer */ + if ( SDL_timer_threaded ) { + while ( SDL_timers ) { + SDL_TimerID freeme = SDL_timers; + SDL_timers = SDL_timers->next; + SDL_free(freeme); + } + SDL_timer_running = 0; + list_changed = SDL_TRUE; + } else { + SDL_SYS_StopTimer(); + SDL_timer_running = 0; + } + } + if ( ms ) { + if ( SDL_timer_threaded ) { + if ( SDL_AddTimerInternal(ms, callback_wrapper, (void *)callback) == NULL ) { + retval = -1; + } + } else { + SDL_timer_running = 1; + SDL_alarm_interval = ms; + SDL_alarm_callback = callback; + retval = SDL_SYS_StartTimer(); + } + } + if ( SDL_timer_threaded ) { + SDL_mutexV(SDL_timer_mutex); + } + + return retval; +} diff --git a/3rdparty/SDL/src/timer/SDL_timer_c.h b/3rdparty/SDL/src/timer/SDL_timer_c.h new file mode 100644 index 0000000..9618108 --- /dev/null +++ b/3rdparty/SDL/src/timer/SDL_timer_c.h @@ -0,0 +1,46 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_timer.c */ +#include "SDL_timer.h" + +#define ROUND_RESOLUTION(X) \ + (((X+TIMER_RESOLUTION-1)/TIMER_RESOLUTION)*TIMER_RESOLUTION) + +extern int SDL_timer_started; +extern int SDL_timer_running; + +/* Data to handle a single periodic alarm */ +extern Uint32 SDL_alarm_interval; +extern SDL_TimerCallback SDL_alarm_callback; + +/* Set whether or not the timer should use a thread. + This should be called while the timer subsystem is running. +*/ +extern int SDL_SetTimerThreaded(int value); + +extern int SDL_TimerInit(void); +extern void SDL_TimerQuit(void); + +/* This function is called from the SDL event thread if it is available */ +extern void SDL_ThreadedTimerCheck(void); diff --git a/3rdparty/SDL/src/timer/beos/SDL_systimer.c b/3rdparty/SDL/src/timer/beos/SDL_systimer.c new file mode 100644 index 0000000..f4cf6c7 --- /dev/null +++ b/3rdparty/SDL/src/timer/beos/SDL_systimer.c @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_BEOS + +#include <be/kernel/OS.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +static bigtime_t start; + +void SDL_StartTicks(void) +{ + /* Set first ticks value */ + start = system_time(); +} + +Uint32 SDL_GetTicks(void) +{ + return((system_time()-start)/1000); +} + +void SDL_Delay(Uint32 ms) +{ + snooze(ms*1000); +} + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) +{ + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(10); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: BeOS uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_BEOS */ diff --git a/3rdparty/SDL/src/timer/dc/SDL_systimer.c b/3rdparty/SDL/src/timer/dc/SDL_systimer.c new file mode 100644 index 0000000..386e158 --- /dev/null +++ b/3rdparty/SDL/src/timer/dc/SDL_systimer.c @@ -0,0 +1,100 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_DC + +#include <kos.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +static unsigned start; + +/* + jif = ms * HZ /1000 + ms = jif * 1000/HZ +*/ + +void SDL_StartTicks(void) +{ + /* Set first ticks value */ + start = jiffies; +} + +Uint32 SDL_GetTicks(void) +{ + return((jiffies-start)*1000/HZ); +} + +void SDL_Delay(Uint32 ms) +{ + thd_sleep(ms); +} + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) +{ + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(10); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: DC uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_DC */ diff --git a/3rdparty/SDL/src/timer/dummy/SDL_systimer.c b/3rdparty/SDL/src/timer/dummy/SDL_systimer.c new file mode 100644 index 0000000..cc266bc --- /dev/null +++ b/3rdparty/SDL/src/timer/dummy/SDL_systimer.c @@ -0,0 +1,91 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(SDL_TIMER_DUMMY) || defined(SDL_TIMERS_DISABLED) + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +void SDL_StartTicks(void) +{ +} + +Uint32 SDL_GetTicks (void) +{ + SDL_Unsupported(); + return 0; +} + +void SDL_Delay (Uint32 ms) +{ + SDL_Unsupported(); +} + +#include "SDL_thread.h" + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) +{ + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(1); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: threaded timer in use"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_DUMMY || SDL_TIMERS_DISABLED */ diff --git a/3rdparty/SDL/src/timer/macos/FastTimes.c b/3rdparty/SDL/src/timer/macos/FastTimes.c new file mode 100644 index 0000000..2da74b7 --- /dev/null +++ b/3rdparty/SDL/src/timer/macos/FastTimes.c @@ -0,0 +1,352 @@ +/* File "FastTimes.c" - Original code by Matt Slot <fprefect@ambrosiasw.com> */ +/* Created 4/24/99 - This file is hereby placed in the public domain */ +/* Updated 5/21/99 - Calibrate to VIA, add TBR support, renamed functions */ +/* Updated 10/4/99 - Use AbsoluteToNanoseconds() in case Absolute = double */ +/* Updated 2/15/00 - Check for native Time Manager, no need to calibrate */ +/* Updated 2/19/00 - Fixed default value for gScale under native Time Mgr */ +/* Updated 3/21/00 - Fixed ns conversion, create 2 different scale factors */ +/* Updated 5/03/00 - Added copyright and placed into PD. No code changes */ +/* Updated 8/01/00 - Made "Carbon-compatible" by replacing LMGetTicks() */ + +/* This file is Copyright (C) Matt Slot, 1999-2012. It is hereby placed into + the public domain. The author makes no warranty as to fitness or stability */ + +#include <Gestalt.h> +#include <LowMem.h> +#include <CodeFragments.h> +#include <DriverServices.h> +#include <Timer.h> + +#include "FastTimes.h" + +#ifdef TARGET_CPU_PPC +#undef GENERATINGPOWERPC /* stop whining */ +#define GENERATINGPOWERPC TARGET_CPU_PPC +#endif + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* + On 680x0 machines, we just use Microseconds(). + + On PowerPC machines, we try several methods: + * DriverServicesLib is available on all PCI PowerMacs, and perhaps + some NuBus PowerMacs. If it is, we use UpTime() : Overhead = 2.1 sec. + * The PowerPC 601 has a built-in "real time clock" RTC, and we fall + back to that, accessing it directly from asm. Overhead = 1.3 sec. + * Later PowerPCs have an accurate "time base register" TBR, and we + fall back to that, access it from PowerPC asm. Overhead = 1.3 sec. + * We can also try Microseconds() which is emulated : Overhead = 36 sec. + + On PowerPC machines, we avoid the following: + * OpenTransport is available on all PCI and some NuBus PowerMacs, but it + uses UpTime() if available and falls back to Microseconds() otherwise. + * InputSprocket is available on many PowerMacs, but again it uses + UpTime() if available and falls back to Microseconds() otherwise. + + Another PowerPC note: certain configurations, especially 3rd party upgrade + cards, may return inaccurate timings for the CPU or memory bus -- causing + skew in various system routines (up to 20% drift!). The VIA chip is very + accurate, and it's the basis for the Time Manager and Microseconds(). + Unfortunately, it's also very slow because the MacOS has to (a) switch to + 68K and (b) poll for a VIA event. + + We compensate for the drift by calibrating a floating point scale factor + between our fast method and the accurate timer at startup, then convert + each sample quickly on the fly. I'd rather not have the initialization + overhead -- but it's simply necessary for accurate timing. You can drop + it down to 30 ticks if you prefer, but that's as low as I'd recommend. + + Under MacOS 9, "new world" Macs (iMacs, B+W G3s and G+W G4s) have a native + Time Manager implementation: UpTime(), Microseconds(), and TickCount() are + all based on the same underlying counter. This makes it silly to calibrate + UpTime() against TickCount(). We now check for this feature using Gestalt(), + and skip the whole calibration step if possible. + +*/ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +#define RTCToNano(w) ((double) (w).hi * 1000000000.0 + (double) (w).lo) +#define WideTo64bit(w) (*(UInt64 *) &(w)) + +/* LMGetTicks() is not in Carbon and TickCount() has a fair bit of overhead, + so for speed we always read lowmem directly. This is a Mac OS X no-no, but + it always work on those systems that don't have a native Time Manager (ie, + anything before MacOS 9) -- regardless whether we are in Carbon or not! */ +#define MyLMGetTicks() (*(volatile UInt32 *) 0x16A) + +#if GENERATINGPOWERPC + +static asm UnsignedWide PollRTC(void); +static asm UnsignedWide PollTBR(void); +static Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName); + +static Boolean gInited = false; +static Boolean gNative = false; +static Boolean gUseRTC = false; +static Boolean gUseTBR = false; +static double gScaleUSec = 1.0 / 1000.0; /* 1 / ( nsec / usec) */ +static double gScaleMSec = 1.0 / 1000000.0; /* 1 / ( nsec / msec) */ + +/* Functions loaded from DriverServicesLib */ +typedef AbsoluteTime (*UpTimeProcPtr)(void); +typedef Nanoseconds (*A2NSProcPtr)(AbsoluteTime); +static UpTimeProcPtr gUpTime = NULL; +static A2NSProcPtr gA2NS = NULL; + +#endif /* GENERATINGPOWERPC */ + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +void FastInitialize() { + SInt32 result; + + if (!gInited) { + +#if GENERATINGPOWERPC + + /* Initialize the feature flags */ + gNative = gUseRTC = gUseTBR = false; + + /* We use CFM to find and load needed symbols from shared libraries, so + the application doesn't have to weak-link them, for convenience. */ + gUpTime = (UpTimeProcPtr) FindFunctionInSharedLib( + "\pDriverServicesLib", "\pUpTime"); + if (gUpTime) gA2NS = (A2NSProcPtr) FindFunctionInSharedLib( + "\pDriverServicesLib", "\pAbsoluteToNanoseconds"); + if (!gA2NS) gUpTime = nil; /* Pedantic but necessary */ + + if (gUpTime) { + /* If we loaded UpTime(), then we need to know if the system has + a native implementation of the Time Manager. If so, then it's + pointless to calculate a scale factor against the missing VIA */ + + /* gestaltNativeTimeMgr = 4 in some future version of the headers */ + if (!Gestalt(gestaltTimeMgrVersion, &result) && + (result > gestaltExtendedTimeMgr)) + gNative = true; + } + else { + /* If no DriverServicesLib, use Gestalt() to get the processor type. + Only NuBus PowerMacs with old System Software won't have DSL, so + we know it should either be a 601 or 603. */ + + /* Use the processor gestalt to determine which register to use */ + if (!Gestalt(gestaltNativeCPUtype, &result)) { + if (result == gestaltCPU601) gUseRTC = true; + else if (result > gestaltCPU601) gUseTBR = true; + } + } + + /* Now calculate a scale factor to keep us accurate. */ + if ((gUpTime && !gNative) || gUseRTC || gUseTBR) { + UInt64 tick, usec1, usec2; + UnsignedWide wide; + + /* Wait for the beginning of the very next tick */ + for(tick = MyLMGetTicks() + 1; tick > MyLMGetTicks(); ); + + /* Poll the selected timer and prepare it (since we have time) */ + wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : + ((gUseRTC) ? PollRTC() : PollTBR()); + usec1 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); + + /* Wait for the exact 60th tick to roll over */ + while(tick + 60 > MyLMGetTicks()); + + /* Poll the selected timer again and prepare it */ + wide = (gUpTime) ? (*gA2NS)((*gUpTime)()) : + ((gUseRTC) ? PollRTC() : PollTBR()); + usec2 = (gUseRTC) ? RTCToNano(wide) : WideTo64bit(wide); + + /* Calculate a scale value that will give microseconds per second. + Remember, there are actually 60.15 ticks in a second, not 60. */ + gScaleUSec = (60.0 * 1000000.0) / ((usec2 - usec1) * 60.15); + gScaleMSec = gScaleUSec / 1000.0; + } + +#endif /* GENERATINGPOWERPC */ + + /* We've initialized our globals */ + gInited = true; + } + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +UInt64 FastMicroseconds() { + UnsignedWide wide; + UInt64 usec; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + wide = PollTBR(); + usec = (double) WideTo64bit(wide) * gScaleUSec + 0.5; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + wide = PollRTC(); + usec = (double) RTCToNano(wide) * gScaleUSec + 0.5; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + Microseconds(&wide); + usec = WideTo64bit(wide); + } + + return(usec); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +UInt64 FastMilliseconds() { + UnsignedWide wide; + UInt64 msec; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + wide = (*gA2NS)((*gUpTime)()); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + wide = PollTBR(); + msec = (double) WideTo64bit(wide) * gScaleMSec + 0.5; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + wide = PollRTC(); + msec = (double) RTCToNano(wide) * gScaleMSec + 0.5; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + Microseconds(&wide); + msec = ((double) WideTo64bit(wide) + 500.0) / 1000.0; + } + + return(msec); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +StringPtr FastMethod() { + StringPtr method = "\p<Unknown>"; + +#if GENERATINGPOWERPC + /* Initialize globals the first time we are called */ + if (!gInited) FastInitialize(); + + if (gNative) { + /* The Time Manager and UpTime() are entirely native on this machine */ + method = "\pNative UpTime()"; + } + else if (gUpTime) { + /* Use DriverServices if it's available -- it's fast and compatible */ + method = "\pUpTime()"; + } + else if (gUseTBR) { + /* On a recent PowerPC, we poll the TBR directly */ + method = "\pPowerPC TBR"; + } + else if (gUseRTC) { + /* On a 601, we can poll the RTC instead */ + method = "\pPowerPC RTC"; + } + else +#endif /* GENERATINGPOWERPC */ + { + /* If all else fails, suffer the mixed mode overhead */ + method = "\pMicroseconds()"; + } + + return(method); + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +#pragma mark - + +#if GENERATINGPOWERPC +asm static UnsignedWide PollRTC_() { +entry PollRTC /* Avoid CodeWarrior glue */ + machine 601 +@AGAIN: + mfrtcu r4 /* RTCU = SPR 4 */ + mfrtcl r5 /* RTCL = SPR 5 */ + mfrtcu r6 + cmpw r4,r6 + bne @AGAIN + stw r4,0(r3) + stw r5,4(r3) + blr + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +asm static UnsignedWide PollTBR_() { +entry PollTBR /* Avoid CodeWarrior glue */ + machine 604 +@AGAIN: + mftbu r4 /* TBRU = SPR 268 */ + mftb r5 /* TBRL = SPR 269 */ + mftbu r6 + cmpw r4,r6 + bne @AGAIN + stw r4,0(r3) + stw r5,4(r3) + blr + } + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +static Ptr FindFunctionInSharedLib(StringPtr libName, StringPtr funcName) { + OSErr error = noErr; + Str255 errorStr; + Ptr func = NULL; + Ptr entry = NULL; + CFragSymbolClass symClass; + CFragConnectionID connID; + + /* Find CFM containers for the current archecture -- CFM-PPC or CFM-68K */ + if (/* error = */ GetSharedLibrary(libName, kCompiledCFragArch, + kLoadCFrag, &connID, &entry, errorStr)) return(NULL); + if (/* error = */ FindSymbol(connID, funcName, &func, &symClass)) + return(NULL); + + return(func); + } +#endif /* GENERATINGPOWERPC */ diff --git a/3rdparty/SDL/src/timer/macos/FastTimes.h b/3rdparty/SDL/src/timer/macos/FastTimes.h new file mode 100644 index 0000000..d25744c --- /dev/null +++ b/3rdparty/SDL/src/timer/macos/FastTimes.h @@ -0,0 +1,27 @@ +/* File "FastTimes.h" - Original code by Matt Slot <fprefect@ambrosiasw.com> */ +#include "SDL_config.h" +/* Created 4/24/99 - This file is hereby placed in the public domain */ +/* Updated 5/21/99 - Calibrate to VIA, add TBR support, renamed functions */ +/* Updated 10/4/99 - Use AbsoluteToNanoseconds() in case Absolute = double */ +/* Updated 2/15/00 - Check for native Time Manager, no need to calibrate */ +/* Updated 3/21/00 - Fixed ns conversion, create 2 different scale factors */ +/* Updated 5/03/00 - Added copyright and placed into PD. No code changes */ + +/* This file is Copyright (C) Matt Slot, 1999-2012. It is hereby placed into + the public domain. The author makes no warranty as to fitness or stability */ + +#ifndef __FAST_TIMES_HEADER__ +#define __FAST_TIMES_HEADER__ + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +extern void FastInitialize(void); +extern UInt64 FastMicroseconds(void); +extern UInt64 FastMilliseconds(void); +extern StringPtr FastMethod(void); + +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ +/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ + +#endif /* __FAST_TIMES_HEADER__ */ diff --git a/3rdparty/SDL/src/timer/macos/SDL_MPWtimer.c b/3rdparty/SDL/src/timer/macos/SDL_MPWtimer.c new file mode 100644 index 0000000..114b6c7 --- /dev/null +++ b/3rdparty/SDL/src/timer/macos/SDL_MPWtimer.c @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_MACOS + +#include <Types.h> +#include <Timer.h> +#include <OSUtils.h> +#include <Gestalt.h> +#include <Processes.h> + +#include <LowMem.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#define MS_PER_TICK (1000/60) /* MacOS tick = 1/60 second */ + +/* Note: This is only a step above the original 1/60s implementation. + * For a good implementation, see FastTimes.[ch], by Matt Slot. + */ +#define USE_MICROSECONDS +#define WideTo64bit(w) (*(UInt64 *) &(w)) + +UInt64 start; + +void SDL_StartTicks(void) +{ +#ifdef USE_MICROSECONDS + UnsignedWide now; + + Microseconds(&now); + start = WideTo64bit(now); +#else + /* FIXME: Should we implement a wrapping algorithm, like Win32? */ +#endif +} + +Uint32 SDL_GetTicks(void) +{ +#ifdef USE_MICROSECONDS + UnsignedWide now; + + Microseconds(&now); + return (Uint32)((WideTo64bit(now)-start)/1000); +#else + return(LMGetTicks()*MS_PER_TICK); +#endif +} + +void SDL_Delay(Uint32 ms) +{ +#ifdef USE_MICROSECONDS + Uint32 end_ms; + + end_ms = SDL_GetTicks() + ms; + do { + /* FIXME: Yield CPU? */ ; + } while ( SDL_GetTicks() < end_ms ); +#else + UInt32 unused; /* MJS */ + Delay(ms/MS_PER_TICK, &unused); +#endif +} + + +/* Data to handle a single periodic alarm */ +typedef struct _ExtendedTimerRec +{ + TMTask tmTask; + ProcessSerialNumber taskPSN; +} ExtendedTimerRec, *ExtendedTimerPtr; + +static ExtendedTimerRec gExtendedTimerRec; + + +int SDL_SYS_TimerInit(void) +{ + /* We don't need a setup? */ + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + /* We don't need a cleanup? */ + return; +} + +/* Our Stub routine to set up and then call the real routine. */ +pascal void TimerCallbackProc(TMTaskPtr tmTaskPtr) +{ + Uint32 ms; + + WakeUpProcess(&((ExtendedTimerPtr) tmTaskPtr)->taskPSN); + + ms = SDL_alarm_callback(SDL_alarm_interval); + if ( ms ) { + SDL_alarm_interval = ROUND_RESOLUTION(ms); + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, + SDL_alarm_interval); + } else { + SDL_alarm_interval = 0; + } +} + +int SDL_SYS_StartTimer(void) +{ + /* + * Configure the global structure that stores the timing information. + */ + gExtendedTimerRec.tmTask.qLink = NULL; + gExtendedTimerRec.tmTask.qType = 0; + gExtendedTimerRec.tmTask.tmAddr = NewTimerUPP(TimerCallbackProc); + gExtendedTimerRec.tmTask.tmCount = 0; + gExtendedTimerRec.tmTask.tmWakeUp = 0; + gExtendedTimerRec.tmTask.tmReserved = 0; + GetCurrentProcess(&gExtendedTimerRec.taskPSN); + + /* Install the task record */ + InsXTime((QElemPtr)&gExtendedTimerRec.tmTask); + + /* Go! */ + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, SDL_alarm_interval); + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + RmvTime((QElemPtr)&gExtendedTimerRec.tmTask); +} + +#endif /* SDL_TIMER_MACOS */ diff --git a/3rdparty/SDL/src/timer/macos/SDL_systimer.c b/3rdparty/SDL/src/timer/macos/SDL_systimer.c new file mode 100644 index 0000000..7a8063e --- /dev/null +++ b/3rdparty/SDL/src/timer/macos/SDL_systimer.c @@ -0,0 +1,186 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_MACOS + +#include <Types.h> +#include <Timer.h> +#include <OSUtils.h> +#include <Gestalt.h> +#include <Processes.h> + +#include <LowMem.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#include "FastTimes.h" + +#if TARGET_API_MAC_CARBON +#define NewTimerProc NewTimerUPP +#endif + +#define MS_PER_TICK (1000.0/60.0) /* MacOS tick = 1/60 second */ + + +#define kTwoPower32 (4294967296.0) /* 2^32 */ + +static double start_tick; +static int is_fast_inited = 0; + +void SDL_StartTicks(void) +{ + if ( ! is_fast_inited ) // important to check or FastTime may hang machine! + SDL_SYS_TimerInit(); + + start_tick = FastMicroseconds(); +} + +Uint32 SDL_GetTicks(void) +{ + + if ( ! is_fast_inited ) + SDL_SYS_TimerInit(); + + return FastMilliseconds(); +} + +void SDL_Delay(Uint32 ms) +{ + Uint32 stop, now; + + stop = SDL_GetTicks() + ms; + do { + #if TARGET_API_MAC_CARBON + MPYield(); + #else + SystemTask(); + #endif + + now = SDL_GetTicks(); + + } while ( stop > now ); +} + +/* +void SDL_StartTicks(void) +{ + // FIXME: Should we implement a wrapping algorithm, like Win32? +} + +Uint32 SDL_GetTicks(void) +{ + UnsignedWide ms; + + Microseconds (&ms); + + return ( ms.lo / 1000 ); +} + +void SDL_Delay(Uint32 ms) +{ + + UnsignedWide microsecs; + UInt32 stop; + + Microseconds (µsecs); + + stop = microsecs.lo + (ms * 1000); + + while ( stop > microsecs.lo ) { + + SystemTask (); + + Microseconds (µsecs); + } + +}*/ + +/* Data to handle a single periodic alarm */ +typedef struct _ExtendedTimerRec +{ + TMTask tmTask; + ProcessSerialNumber taskPSN; +} ExtendedTimerRec, *ExtendedTimerPtr; + +static ExtendedTimerRec gExtendedTimerRec; + + +int SDL_SYS_TimerInit(void) +{ + FastInitialize (); + is_fast_inited = 1; + + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + /* We don't need a cleanup? */ + return; +} + +/* Our Stub routine to set up and then call the real routine. */ +pascal void TimerCallbackProc(TMTaskPtr tmTaskPtr) +{ + Uint32 ms; + + WakeUpProcess(&((ExtendedTimerPtr) tmTaskPtr)->taskPSN); + + ms = SDL_alarm_callback(SDL_alarm_interval); + if ( ms ) { + SDL_alarm_interval = ROUND_RESOLUTION(ms); + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, + SDL_alarm_interval); + } else { + SDL_alarm_interval = 0; + } +} + +int SDL_SYS_StartTimer(void) +{ + /* + * Configure the global structure that stores the timing information. + */ + gExtendedTimerRec.tmTask.qLink = NULL; + gExtendedTimerRec.tmTask.qType = 0; + gExtendedTimerRec.tmTask.tmAddr = NewTimerProc(TimerCallbackProc); + gExtendedTimerRec.tmTask.tmCount = 0; + gExtendedTimerRec.tmTask.tmWakeUp = 0; + gExtendedTimerRec.tmTask.tmReserved = 0; + GetCurrentProcess(&gExtendedTimerRec.taskPSN); + + /* Install the task record */ + InsXTime((QElemPtr)&gExtendedTimerRec.tmTask); + + /* Go! */ + PrimeTime((QElemPtr)&gExtendedTimerRec.tmTask, SDL_alarm_interval); + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + RmvTime((QElemPtr)&gExtendedTimerRec.tmTask); +} + +#endif /* SDL_TIMER_MACOS */ diff --git a/3rdparty/SDL/src/timer/mint/SDL_systimer.c b/3rdparty/SDL/src/timer/mint/SDL_systimer.c new file mode 100644 index 0000000..01e7a41 --- /dev/null +++ b/3rdparty/SDL/src/timer/mint/SDL_systimer.c @@ -0,0 +1,149 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_MINT + +/* + * TOS/MiNT timer driver + * based on vbl vector + * + * Patrice Mandin + */ + +#include <stdio.h> +#include <sys/time.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <mint/cookie.h> +#include <mint/sysvars.h> +#include <mint/osbind.h> +#include <mint/mintbind.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" +#include "SDL_thread.h" + +#include "../../video/ataricommon/SDL_atarisuper.h" + +#include "SDL_vbltimer_s.h" + +/* from audio/mint */ +void SDL_MintAudio_CheckFpu(void); + +/* The first ticks value of the application */ +static Uint32 start; +static SDL_bool read_hz200_from_vbl = SDL_FALSE; +static int mint_present; /* can we use Syield() ? */ + +void SDL_StartTicks(void) +{ + void *old_stack; + long dummy; + + /* Set first ticks value */ + old_stack = (void *)Super(0); + start = *((volatile long *)_hz_200); + SuperToUser(old_stack); + + start *= 5; /* One _hz_200 tic is 5ms */ + + mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); +} + +Uint32 SDL_GetTicks (void) +{ + Uint32 now = start; + + if (read_hz200_from_vbl) { + now = SDL_Atari_hz200; + } else { + void *old_stack = (void *)Super(0); + now = *((volatile long *)_hz_200); + SuperToUser(old_stack); + } + + return((now*5)-start); +} + +void SDL_Delay (Uint32 ms) +{ + Uint32 now; + + now = SDL_GetTicks(); + while ((SDL_GetTicks()-now)<ms){ + if (mint_present) { + Syield(); + } + } +} + +/* Data to handle a single periodic alarm */ +static SDL_bool timer_installed=SDL_FALSE; + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + void *old_stack; + + SDL_MintAudio_CheckFpu(); + + /* Install RunTimer in vbl vector */ + old_stack = (void *)Super(0); + timer_installed = !SDL_AtariVblInstall(SDL_ThreadedTimerCheck); + SuperToUser(old_stack); + + if (!timer_installed) { + return(-1); + } + + read_hz200_from_vbl = SDL_TRUE; + return(SDL_SetTimerThreaded(0)); +} + +void SDL_SYS_TimerQuit(void) +{ + /* Uninstall RunTimer vbl vector */ + if (timer_installed) { + void *old_stack = (void *)Super(0); + SDL_AtariVblUninstall(SDL_ThreadedTimerCheck); + SuperToUser(old_stack); + timer_installed = SDL_FALSE; + } + read_hz200_from_vbl = SDL_FALSE; +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: MiNT uses vbl timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_MINT */ diff --git a/3rdparty/SDL/src/timer/mint/SDL_vbltimer.S b/3rdparty/SDL/src/timer/mint/SDL_vbltimer.S new file mode 100644 index 0000000..7837afc --- /dev/null +++ b/3rdparty/SDL/src/timer/mint/SDL_vbltimer.S @@ -0,0 +1,228 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * VBL queue routine + * + * Patrice Mandin + */ + +#define _vbl_queue 0x456 +#define _hz_200 0x4ba + + .text + + .globl _SDL_AtariVblInstall + .globl _SDL_AtariVblUninstall + + .globl _SDL_MintAudio_hasfpu + +/*--- Save/restore FPU context ---*/ + +#if defined(__mcoldfire__) + +#define SAVE_FPU_CONTEXT \ + lea sp@(-216),sp; \ + fsave sp@; \ + fmovel fpiar,sp@-; \ + lea sp@(-64),sp; \ + fmovemd fp0-fp7,sp@ + +#define RESTORE_FPU_CONTEXT \ + fmovemd sp@,fp0-fp7; \ + lea sp@(64),sp; \ + fmovel sp@+,fpiar; \ + frestore sp@; \ + lea sp@(216),sp + +#else + +#define SAVE_FPU_CONTEXT \ + .chip 68k/68881; \ + fsave sp@-; \ + fmoveml fpcr/fpsr/fpiar,sp@-; \ + fmovemx fp0-fp7,sp@-; \ + .chip 68k + +#define RESTORE_FPU_CONTEXT \ + .chip 68k/68881; \ + fmovemx sp@+,fp0-fp7; \ + fmoveml sp@+,fpcr/fpsr/fpiar; \ + frestore sp@+; \ + .chip 68k + +#endif + +/*--- Vector installer ---*/ + +_SDL_AtariVblInstall: +#if defined(__mcoldfire__) + movel sp@(4),d0 + movel d0,my_vector +#else + movel sp@(4),my_vector +#endif + + lea _my_vbl,a0 + + clrw vbl_mutex +#if defined(__mcoldfire__) + movel _hz_200.w,d0 + movel d0, _SDL_Atari_hz200 +#else + movel _hz_200.w, _SDL_Atari_hz200 +#endif + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Read vbl_queue pointer */ + movel _vbl_queue.w,a1 + + /* Search a free place */ + moveq #7,d0 +bcl_search_place: + movel (a1),d1 + beqs place_found + addql #4,a1 +#if defined(__mcoldfire__) + subql #1,d0 + bpls bcl_search_place +#else + dbra d0,bcl_search_place +#endif + + /* Not found */ + moveq #1,d0 + bras exit_vbl_queue + + /* Then install ourselves */ +place_found: + movel a0,(a1) + moveq #0,d0 + +exit_vbl_queue: + /* Restart interrupts */ + movew #0x2300,sr + + rts + +/*--- Vector uninstaller ---*/ + +_SDL_AtariVblUninstall: + movel sp@(4),d0 + cmpl my_vector,d0 + bnes badvector + + movel #_my_vbl,d0 + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Read vbl_queue pointer */ + movel _vbl_queue.w,a1 + + /* Search where we are */ + moveq #7,d1 +bcl2_search_place: + cmpl (a1),d0 + bnes next_place + clrl (a1) + moveq #0,d1 +next_place: + addql #4,a1 +#if defined(__mcoldfire__) + subql #1,d1 + bpls bcl_search_place +#else + dbra d1,bcl2_search_place +#endif + + /* Restart interrupts */ + movew #0x2300,sr +badvector: + rts + +/*--- Our vbl ---*/ + +_my_vbl: +#if defined(__mcoldfire__) + lea sp@(-60),sp + moveml d0-d7/a0-a6,sp@ +#else + moveml d0-d7/a0-a6,sp@- +#endif + + /* Update _hz_200 */ +#if defined(__mcoldfire__) + movel _hz_200.w,d0 + movel d0, _SDL_Atari_hz200 +#else + movel _hz_200.w, _SDL_Atari_hz200 +#endif + + /* Verify if this is not already running */ + + tstw vbl_mutex + bnes vbl_end +#if defined(__mcoldfire__) + movew vbl_mutex,d0 + notl d0 + movew d0,vbl_mutex +#else + notw vbl_mutex +#endif + + /* Save FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_AtariVbl_nofpu1 + SAVE_FPU_CONTEXT +SDL_AtariVbl_nofpu1: + + movel my_vector,a0 + jsr a0@ + + /* Restore FPU if needed */ + tstw _SDL_MintAudio_hasfpu + beqs SDL_AtariVbl_Xbios_nofpu2 + RESTORE_FPU_CONTEXT +SDL_AtariVbl_Xbios_nofpu2: + + clrw vbl_mutex +vbl_end: +#if defined(__mcoldfire__) + moveml sp@,d0-d7/a0-a6 + lea sp@(60),sp +#else + moveml sp@+,d0-d7/a0-a6 +#endif + rts + + .data + .even + .comm _SDL_Atari_hz200,4*1 + .even + .comm vbl_mutex,2*1 + .even + .comm my_vector,4*1 diff --git a/3rdparty/SDL/src/timer/mint/SDL_vbltimer_s.h b/3rdparty/SDL/src/timer/mint/SDL_vbltimer_s.h new file mode 100644 index 0000000..011c138 --- /dev/null +++ b/3rdparty/SDL/src/timer/mint/SDL_vbltimer_s.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * TOS/MiNT timer driver + * based on vbl vector + * + * Patrice Mandin + */ + +extern volatile long SDL_Atari_hz200; + +/* Functions prototypes */ +extern int SDL_AtariVblInstall(void *newvector); +extern void SDL_AtariVblUninstall(void *newvector); diff --git a/3rdparty/SDL/src/timer/nds/SDL_systimer.c b/3rdparty/SDL/src/timer/nds/SDL_systimer.c new file mode 100644 index 0000000..bf54f42 --- /dev/null +++ b/3rdparty/SDL/src/timer/nds/SDL_systimer.c @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" +#include "../SDL_timer_c.h" + +#include <nds.h> + +#define timers2ms(tlow,thigh)(tlow | (thigh<<16)) >> 5 + + +void SDL_StartTicks(void) +{ + TIMER0_DATA=0; + TIMER1_DATA=0; + TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024; + TIMER1_CR=TIMER_ENABLE|TIMER_CASCADE; +} + +Uint32 SDL_GetTicks(void) +{ + return timers2ms(TIMER0_DATA, TIMER1_DATA); +} + +void SDL_Delay(Uint32 ms) +{ + Uint32 now; + now=timers2ms(TIMER0_DATA, TIMER1_DATA); + while((Uint32)timers2ms(TIMER0_DATA, TIMER1_DATA)<now+ms); + +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + return 0; +} + +void SDL_SYS_TimerQuit(void) +{ +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Timers not implemented on NDS"); + return -1; +} + +void SDL_SYS_StopTimer(void) +{ +} diff --git a/3rdparty/SDL/src/timer/os2/SDL_systimer.c b/3rdparty/SDL/src/timer/os2/SDL_systimer.c new file mode 100644 index 0000000..c82d531 --- /dev/null +++ b/3rdparty/SDL/src/timer/os2/SDL_systimer.c @@ -0,0 +1,227 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_OS2 + +#define INCL_DOSMISC +#define INCL_DOSERRORS +#define INCL_DOSSEMAPHORES +#define INCL_DOSDATETIME +#define INCL_DOSPROCESS +#define INCL_DOSPROFILE +#define INCL_DOSEXCEPTIONS +#include <os2.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + + +#define TIME_WRAP_VALUE (~(DWORD)0) + +/* The first high-resolution ticks value of the application */ +static long long hires_start_ticks; +/* The number of ticks per second of the high-resolution performance counter */ +static ULONG hires_ticks_per_second; + +void SDL_StartTicks(void) +{ + DosTmrQueryFreq(&hires_ticks_per_second); + DosTmrQueryTime((PQWORD)&hires_start_ticks); +} + +DECLSPEC Uint32 SDLCALL SDL_GetTicks(void) +{ + long long hires_now; + ULONG ticks = ticks; + + DosTmrQueryTime((PQWORD)&hires_now); +/* + hires_now -= hires_start_ticks; + hires_now *= 1000; + hires_now /= hires_ticks_per_second; +*/ + /* inline asm to avoid runtime inclusion */ + _asm { + push edx + push eax + mov eax, dword ptr hires_now + mov edx, dword ptr hires_now+4 + sub eax, dword ptr hires_start_ticks + sbb edx, dword ptr hires_start_ticks+4 + mov ebx,1000 + mov ecx,edx + mul ebx + push eax + push edx + mov eax,ecx + mul ebx + pop eax + add edx,eax + pop eax + mov ebx, dword ptr hires_ticks_per_second + div ebx + mov dword ptr ticks, eax + pop edx + pop eax + } + + return ticks; + +} + +/* High resolution sleep, originally made by Ilya Zakharevich */ +DECLSPEC void SDLCALL SDL_Delay(Uint32 ms) +{ + /* This is similar to DosSleep(), but has 8ms granularity in time-critical + threads even on Warp3. */ + HEV hevEvent1 = 0; /* Event semaphore handle */ + HTIMER htimerEvent1 = 0; /* Timer handle */ + APIRET rc = NO_ERROR; /* Return code */ + int ret = 1; + ULONG priority = 0, nesting; /* Shut down the warnings */ + PPIB pib; + PTIB tib; + char *e = NULL; + APIRET badrc; + int switch_priority = 50; + + DosCreateEventSem(NULL, /* Unnamed */ + &hevEvent1, /* Handle of semaphore returned */ + DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */ + FALSE); /* Semaphore is in RESET state */ + + if (ms >= switch_priority) + switch_priority = 0; + if (switch_priority) + { + if (DosGetInfoBlocks(&tib, &pib)!=NO_ERROR) + switch_priority = 0; + else + { + /* In Warp3, to switch scheduling to 8ms step, one needs to do + DosAsyncTimer() in time-critical thread. On laters versions, + more and more cases of wait-for-something are covered. + + It turns out that on Warp3fp42 it is the priority at the time + of DosAsyncTimer() which matters. Let's hope that this works + with later versions too... XXXX + */ + priority = (tib->tib_ptib2->tib2_ulpri); + if ((priority & 0xFF00) == 0x0300) /* already time-critical */ + switch_priority = 0; + /* Make us time-critical. Just modifying TIB is not enough... */ + /* tib->tib_ptib2->tib2_ulpri = 0x0300;*/ + /* We do not want to run at high priority if a signal causes us + to longjmp() out of this section... */ + if (DosEnterMustComplete(&nesting)) + switch_priority = 0; + else + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); + } + } + + if ((badrc = DosAsyncTimer(ms, + (HSEM) hevEvent1, /* Semaphore to post */ + &htimerEvent1))) /* Timer handler (returned) */ + e = "DosAsyncTimer"; + + if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300) + { + /* Nobody switched priority while we slept... Ignore errors... */ + /* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */ + if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0))) + rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0); + } + if (switch_priority) + rc = DosExitMustComplete(&nesting); /* Ignore errors */ + + /* The actual blocking call is made with "normal" priority. This way we + should not bother with DosSleep(0) etc. to compensate for us interrupting + higher-priority threads. The goal is to prohibit the system spending too + much time halt()ing, not to run us "no matter what". */ + if (!e) /* Wait for AsyncTimer event */ + badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT); + + if (e) ; /* Do nothing */ + else if (badrc == ERROR_INTERRUPT) + ret = 0; + else if (badrc) + e = "DosWaitEventSem"; + if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */ + e = "DosCloseEventSem"; + badrc = rc; + } + if (e) + { + SDL_SetError("[SDL_Delay] : Had error in %s(), rc is 0x%x\n", e, badrc); + } +} + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int SDLCALL RunTimer(void *unused) +{ + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(10); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: OS/2 uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_OS2 */ diff --git a/3rdparty/SDL/src/timer/riscos/SDL_systimer.c b/3rdparty/SDL/src/timer/riscos/SDL_systimer.c new file mode 100644 index 0000000..25ba65f --- /dev/null +++ b/3rdparty/SDL/src/timer/riscos/SDL_systimer.c @@ -0,0 +1,233 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_RISCOS + +#include <stdio.h> +#include <time.h> +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#if SDL_THREADS_DISABLED +/* Timer SDL_arraysize(Timer ),start/reset time */ +static Uint32 timerStart; +/* Timer running function */ +void RISCOS_CheckTimer(); +#else +#include <pthread.h> +extern Uint32 riscos_main_thread; +extern int riscos_using_threads; +extern Uint32 SDL_ThreadID(); +extern Uint32 SDL_EventThreadID(void); +#endif + + +extern void RISCOS_BackgroundTasks(void); + +/* The first ticks value of the application */ +clock_t start; + +void SDL_StartTicks(void) +{ + /* Set first ticks value */ + start = clock(); +} + +Uint32 SDL_GetTicks (void) +{ + clock_t ticks; + + ticks=clock()-start; + + +#if CLOCKS_PER_SEC == 1000 + + return(ticks); + +#elif CLOCKS_PER_SEC == 100 + + return (ticks * 10); + +#else + + return ticks*(1000/CLOCKS_PER_SEC); + +#endif + +} + +void SDL_Delay (Uint32 ms) +{ + Uint32 now,then,elapsed; +#if !SDL_THREADS_DISABLED + int is_event_thread; + if (riscos_using_threads) + { + is_event_thread = 0; + if (SDL_EventThreadID()) + { + if (SDL_EventThreadID() == SDL_ThreadID()) is_event_thread = 1; + } else if (SDL_ThreadID() == riscos_main_thread) is_event_thread = 1; + } else is_event_thread = 1; +#endif + + /*TODO: Next version of Unixlib may allow us to use usleep here */ + /* for non event threads */ + + /* Set the timeout interval - Linux only needs to do this once */ + then = SDL_GetTicks(); + + do { + /* Do background tasks required while sleeping as we are not multithreaded */ +#if SDL_THREADS_DISABLED + RISCOS_BackgroundTasks(); +#else + /* For threaded build only run background tasks in event thread */ + if (is_event_thread) RISCOS_BackgroundTasks(); +#endif + + /* Calculate the time interval left (in case of interrupt) */ + now = SDL_GetTicks(); + elapsed = (now-then); + then = now; + if ( elapsed >= ms ) { + break; + } + ms -= elapsed; +#if !SDL_THREADS_DISABLED + /* Need to yield to let other threads have a go */ + if (riscos_using_threads) pthread_yield(); +#endif + + } while ( 1 ); +} + +#if SDL_THREADS_DISABLED + +/* Non-threaded version of timer */ + +int SDL_SYS_TimerInit(void) +{ + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + SDL_SetTimer(0, NULL); +} + +int SDL_SYS_StartTimer(void) +{ + timerStart = SDL_GetTicks(); + + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + /* Don't need to do anything as we use SDL_timer_running + to detect if we need to check the timer */ +} + + +void RISCOS_CheckTimer() +{ + if (SDL_timer_running && SDL_GetTicks() - timerStart >= SDL_alarm_interval) + { + Uint32 ms; + + ms = SDL_alarm_callback(SDL_alarm_interval); + if ( ms != SDL_alarm_interval ) + { + if ( ms ) + { + SDL_alarm_interval = ROUND_RESOLUTION(ms); + } else + { + SDL_alarm_interval = 0; + SDL_timer_running = 0; + } + } + if (SDL_alarm_interval) timerStart = SDL_GetTicks(); + } +} + +#else + +/* Threaded version of timer - based on code for linux */ + +#include "SDL_thread.h" + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) +{ + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(1); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: RISC OS uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_THREADS_DISABLED */ + +#endif /* SDL_TIMER_RISCOS */ diff --git a/3rdparty/SDL/src/timer/symbian/SDL_systimer.cpp b/3rdparty/SDL/src/timer/symbian/SDL_systimer.cpp new file mode 100644 index 0000000..a5bb749 --- /dev/null +++ b/3rdparty/SDL/src/timer/symbian/SDL_systimer.cpp @@ -0,0 +1,114 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_systimer.cpp + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) + Markus Mertama +*/ + +#include <e32std.h> +#include <e32hal.h> + +extern "C" { +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_timer_c.h" + +static TUint start = 0; +static TInt tickPeriodMilliSeconds; + + +void SDL_StartTicks(void) + { + /* Set first ticks value */ + start = User::TickCount(); + + TTimeIntervalMicroSeconds32 period; + TInt tmp = UserHal::TickPeriod(period); + tickPeriodMilliSeconds = period.Int() / 1000; + } + +Uint32 SDL_GetTicks(void) + { + TUint deltaTics = User::TickCount() - start; + return(deltaTics * tickPeriodMilliSeconds); + } + +void SDL_Delay(Uint32 ms) + { + User::After(TTimeIntervalMicroSeconds32(ms*1000)); + } + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) + { + while ( timer_alive ) + { + if (SDL_timer_running) + { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(10); + } + return(0); + } + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) + { + if(timer != NULL) + return (-1); + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); + } + +void SDL_SYS_TimerQuit(void) + { + timer_alive = 0; + if ( timer ) + { + SDL_WaitThread(timer, NULL); + timer = NULL; + } + } + +int SDL_SYS_StartTimer(void) + { + SDL_SetError("Internal logic error: Epoc uses threaded timer"); + return(-1); + } + +void SDL_SYS_StopTimer(void) + { + return; + } + +} // extern "C" diff --git a/3rdparty/SDL/src/timer/unix/SDL_systimer.c b/3rdparty/SDL/src/timer/unix/SDL_systimer.c new file mode 100644 index 0000000..80b2228 --- /dev/null +++ b/3rdparty/SDL/src/timer/unix/SDL_systimer.c @@ -0,0 +1,240 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_UNIX + +#include <stdio.h> +#include <sys/time.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +/* The clock_gettime provides monotonous time, so we should use it if + it's available. The clock_gettime function is behind ifdef + for __USE_POSIX199309 + Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005 +*/ +#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME +#include <time.h> +#endif + +#if SDL_THREAD_PTH +#include <pth.h> +#endif + +#if SDL_THREADS_DISABLED +#define USE_ITIMER +#endif + +/* The first ticks value of the application */ +#ifdef HAVE_CLOCK_GETTIME +static struct timespec start; +#else +static struct timeval start; +#endif /* HAVE_CLOCK_GETTIME */ + + +void SDL_StartTicks(void) +{ + /* Set first ticks value */ +#if HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_MONOTONIC,&start); +#else + gettimeofday(&start, NULL); +#endif +} + +Uint32 SDL_GetTicks (void) +{ +#if HAVE_CLOCK_GETTIME + Uint32 ticks; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC,&now); + ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_nsec-start.tv_nsec)/1000000; + return(ticks); +#else + Uint32 ticks; + struct timeval now; + gettimeofday(&now, NULL); + ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000; + return(ticks); +#endif +} + +void SDL_Delay (Uint32 ms) +{ +#if SDL_THREAD_PTH + pth_time_t tv; + tv.tv_sec = ms/1000; + tv.tv_usec = (ms%1000)*1000; + pth_nap(tv); +#else + int was_error; + +#if HAVE_NANOSLEEP + struct timespec elapsed, tv; +#else + struct timeval tv; + Uint32 then, now, elapsed; +#endif + + /* Set the timeout interval */ +#if HAVE_NANOSLEEP + elapsed.tv_sec = ms/1000; + elapsed.tv_nsec = (ms%1000)*1000000; +#else + then = SDL_GetTicks(); +#endif + do { + errno = 0; + +#if HAVE_NANOSLEEP + tv.tv_sec = elapsed.tv_sec; + tv.tv_nsec = elapsed.tv_nsec; + was_error = nanosleep(&tv, &elapsed); +#else + /* Calculate the time interval left (in case of interrupt) */ + now = SDL_GetTicks(); + elapsed = (now-then); + then = now; + if ( elapsed >= ms ) { + break; + } + ms -= elapsed; + tv.tv_sec = ms/1000; + tv.tv_usec = (ms%1000)*1000; + + was_error = select(0, NULL, NULL, NULL, &tv); +#endif /* HAVE_NANOSLEEP */ + } while ( was_error && (errno == EINTR) ); +#endif /* SDL_THREAD_PTH */ +} + +#ifdef USE_ITIMER + +static void HandleAlarm(int sig) +{ + Uint32 ms; + + if ( SDL_alarm_callback ) { + ms = (*SDL_alarm_callback)(SDL_alarm_interval); + if ( ms != SDL_alarm_interval ) { + SDL_SetTimer(ms, SDL_alarm_callback); + } + } +} + +int SDL_SYS_TimerInit(void) +{ + struct sigaction action; + + /* Set the alarm handler (Linux specific) */ + SDL_memset(&action, 0, sizeof(action)); + action.sa_handler = HandleAlarm; + action.sa_flags = SA_RESTART; + sigemptyset(&action.sa_mask); + sigaction(SIGALRM, &action, NULL); + return(0); +} + +void SDL_SYS_TimerQuit(void) +{ + SDL_SetTimer(0, NULL); +} + +int SDL_SYS_StartTimer(void) +{ + struct itimerval timer; + + timer.it_value.tv_sec = (SDL_alarm_interval/1000); + timer.it_value.tv_usec = (SDL_alarm_interval%1000)*1000; + timer.it_interval.tv_sec = (SDL_alarm_interval/1000); + timer.it_interval.tv_usec = (SDL_alarm_interval%1000)*1000; + setitimer(ITIMER_REAL, &timer, NULL); + return(0); +} + +void SDL_SYS_StopTimer(void) +{ + struct itimerval timer; + + SDL_memset(&timer, 0, (sizeof timer)); + setitimer(ITIMER_REAL, &timer, NULL); +} + +#else /* USE_ITIMER */ + +#include "SDL_thread.h" + +/* Data to handle a single periodic alarm */ +static int timer_alive = 0; +static SDL_Thread *timer = NULL; + +static int RunTimer(void *unused) +{ + while ( timer_alive ) { + if ( SDL_timer_running ) { + SDL_ThreadedTimerCheck(); + } + SDL_Delay(1); + } + return(0); +} + +/* This is only called if the event thread is not running */ +int SDL_SYS_TimerInit(void) +{ + timer_alive = 1; + timer = SDL_CreateThread(RunTimer, NULL); + if ( timer == NULL ) + return(-1); + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + timer_alive = 0; + if ( timer ) { + SDL_WaitThread(timer, NULL); + timer = NULL; + } +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: Linux uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* USE_ITIMER */ + +#endif /* SDL_TIMER_UNIX */ diff --git a/3rdparty/SDL/src/timer/win32/SDL_systimer.c b/3rdparty/SDL/src/timer/win32/SDL_systimer.c new file mode 100644 index 0000000..b025e2e --- /dev/null +++ b/3rdparty/SDL/src/timer/win32/SDL_systimer.c @@ -0,0 +1,160 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_WIN32 + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> + +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +#ifdef _WIN32_WCE + #error This is WinCE. Please use src/timer/wince/SDL_systimer.c instead. +#endif + +#define TIME_WRAP_VALUE (~(DWORD)0) + +/* The first (low-resolution) ticks value of the application */ +static DWORD start; + +#ifndef USE_GETTICKCOUNT +/* Store if a high-resolution performance counter exists on the system */ +static BOOL hires_timer_available; +/* The first high-resolution ticks value of the application */ +static LARGE_INTEGER hires_start_ticks; +/* The number of ticks per second of the high-resolution performance counter */ +static LARGE_INTEGER hires_ticks_per_second; +#endif + +void SDL_StartTicks(void) +{ + /* Set first ticks value */ +#ifdef USE_GETTICKCOUNT + start = GetTickCount(); +#else +#if 0 /* Apparently there are problems with QPC on Win2K */ + if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) + { + hires_timer_available = TRUE; + QueryPerformanceCounter(&hires_start_ticks); + } + else +#endif + { + hires_timer_available = FALSE; + timeBeginPeriod(1); /* use 1 ms timer precision */ + start = timeGetTime(); + } +#endif +} + +Uint32 SDL_GetTicks(void) +{ + DWORD now, ticks; +#ifndef USE_GETTICKCOUNT + LARGE_INTEGER hires_now; +#endif + +#ifdef USE_GETTICKCOUNT + now = GetTickCount(); +#else + if (hires_timer_available) + { + QueryPerformanceCounter(&hires_now); + + hires_now.QuadPart -= hires_start_ticks.QuadPart; + hires_now.QuadPart *= 1000; + hires_now.QuadPart /= hires_ticks_per_second.QuadPart; + + return (DWORD)hires_now.QuadPart; + } + else + { + now = timeGetTime(); + } +#endif + + if ( now < start ) { + ticks = (TIME_WRAP_VALUE-start) + now; + } else { + ticks = (now - start); + } + return(ticks); +} + +void SDL_Delay(Uint32 ms) +{ + Sleep(ms); +} + +/* Data to handle a single periodic alarm */ +static UINT timerID = 0; + +static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD_PTR dwUser, + DWORD_PTR dw1, DWORD_PTR dw2) +{ + SDL_ThreadedTimerCheck(); +} + + +int SDL_SYS_TimerInit(void) +{ + MMRESULT result; + + /* Set timer resolution */ + result = timeBeginPeriod(TIMER_RESOLUTION); + if ( result != TIMERR_NOERROR ) { + SDL_SetError("Warning: Can't set %d ms timer resolution", + TIMER_RESOLUTION); + } + /* Allow 10 ms of drift so we don't chew on CPU */ + timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC); + if ( ! timerID ) { + SDL_SetError("timeSetEvent() failed"); + return(-1); + } + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + if ( timerID ) { + timeKillEvent(timerID); + } + timeEndPeriod(TIMER_RESOLUTION); +} + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: Win32 uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_WIN32 */ diff --git a/3rdparty/SDL/src/timer/wince/SDL_systimer.c b/3rdparty/SDL/src/timer/wince/SDL_systimer.c new file mode 100644 index 0000000..2b018b0 --- /dev/null +++ b/3rdparty/SDL/src/timer/wince/SDL_systimer.c @@ -0,0 +1,198 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifdef SDL_TIMER_WINCE + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "../SDL_timer_c.h" + +static Uint64 start_date; +static Uint64 start_ticks; + +static Uint64 wce_ticks(void) +{ + return((Uint64)GetTickCount()); +} + +static Uint64 wce_date(void) +{ + union + { + FILETIME ftime; + Uint64 itime; + } ftime; + SYSTEMTIME stime; + + GetSystemTime(&stime); + SystemTimeToFileTime(&stime,&ftime.ftime); + ftime.itime/=10000; // Convert 100ns intervals to 1ms intervals + // Remove ms portion, which can't be relied on + ftime.itime -= (ftime.itime % 1000); + return(ftime.itime); +} + +static Sint32 wce_rel_ticks(void) +{ + return((Sint32)(wce_ticks()-start_ticks)); +} + +static Sint32 wce_rel_date(void) +{ + return((Sint32)(wce_date()-start_date)); +} + +/* Return time in ms relative to when SDL was started */ +Uint32 SDL_GetTicks() +{ + Sint32 offset=wce_rel_date()-wce_rel_ticks(); + if((offset < -1000) || (offset > 1000)) + { +// fprintf(stderr,"Time desync(%+d), resyncing\n",offset/1000); + start_ticks-=offset; + } + + return((Uint32)wce_rel_ticks()); +} + +/* Give up approx. givem milliseconds to the OS. */ +void SDL_Delay(Uint32 ms) +{ + Sleep(ms); +} + +/* Recard start-time of application for reference */ +void SDL_StartTicks(void) +{ + start_date=wce_date(); + start_ticks=wce_ticks(); +} + +static UINT WIN_timer; + +#if ( _WIN32_WCE <= 420 ) + +static HANDLE timersThread = 0; +static HANDLE timersQuitEvent = 0; + +DWORD TimersThreadProc(void *data) +{ + while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT) + { + SDL_ThreadedTimerCheck(); + } + return 0; +} + +int SDL_SYS_TimerInit(void) +{ + // create a thread to process a threaded timers + // SetTimer does not suit the needs because + // TimerCallbackProc will be called only when WM_TIMER occured + + timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0); + if( !timersQuitEvent ) + { + SDL_SetError("Cannot create event for timers thread"); + return -1; + } + timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0); + if( !timersThread ) + { + SDL_SetError("Cannot create timers thread, check amount of RAM available"); + return -1; + } + SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST); + + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + SetEvent(timersQuitEvent); + if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT ) + TerminateThread(timersThread, 0); + CloseHandle(timersThread); + CloseHandle(timersQuitEvent); + return; +} + +#else + +#pragma comment(lib, "mmtimer.lib") + +/* Data to handle a single periodic alarm */ +static UINT timerID = 0; + +static void CALLBACK HandleAlarm(UINT uID, UINT uMsg, DWORD dwUser, + DWORD dw1, DWORD dw2) +{ + SDL_ThreadedTimerCheck(); +} + + +int SDL_SYS_TimerInit(void) +{ + MMRESULT result; + + /* Set timer resolution */ + result = timeBeginPeriod(TIMER_RESOLUTION); + if ( result != TIMERR_NOERROR ) { + SDL_SetError("Warning: Can't set %d ms timer resolution", + TIMER_RESOLUTION); + } + /* Allow 10 ms of drift so we don't chew on CPU */ + timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC); + if ( ! timerID ) { + SDL_SetError("timeSetEvent() failed"); + return(-1); + } + return(SDL_SetTimerThreaded(1)); +} + +void SDL_SYS_TimerQuit(void) +{ + if ( timerID ) { + timeKillEvent(timerID); + } + timeEndPeriod(TIMER_RESOLUTION); +} + +#endif + +int SDL_SYS_StartTimer(void) +{ + SDL_SetError("Internal logic error: WinCE uses threaded timer"); + return(-1); +} + +void SDL_SYS_StopTimer(void) +{ + return; +} + +#endif /* SDL_TIMER_WINCE */ diff --git a/3rdparty/SDL/src/video/SDL_RLEaccel.c b/3rdparty/SDL/src/video/SDL_RLEaccel.c new file mode 100644 index 0000000..d4b191c --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_RLEaccel.c @@ -0,0 +1,1941 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * RLE encoding for software colorkey and alpha-channel acceleration + * + * Original version by Sam Lantinga + * + * Mattias Engdegrd (Yorick): Rewrite. New encoding format, encoder and + * decoder. Added per-surface alpha blitter. Added per-pixel alpha + * format, encoder and blitter. + * + * Many thanks to Xark and johns for hints, benchmarks and useful comments + * leading to this code. + * + * Welcome to Macro Mayhem. + */ + +/* + * The encoding translates the image data to a stream of segments of the form + * + * <skip> <run> <data> + * + * where <skip> is the number of transparent pixels to skip, + * <run> is the number of opaque pixels to blit, + * and <data> are the pixels themselves. + * + * This basic structure is used both for colorkeyed surfaces, used for simple + * binary transparency and for per-surface alpha blending, and for surfaces + * with per-pixel alpha. The details differ, however: + * + * Encoding of colorkeyed surfaces: + * + * Encoded pixels always have the same format as the target surface. + * <skip> and <run> are unsigned 8 bit integers, except for 32 bit depth + * where they are 16 bit. This makes the pixel data aligned at all times. + * Segments never wrap around from one scan line to the next. + * + * The end of the sequence is marked by a zero <skip>,<run> pair at the * + * beginning of a line. + * + * Encoding of surfaces with per-pixel alpha: + * + * The sequence begins with a struct RLEDestFormat describing the target + * pixel format, to provide reliable un-encoding. + * + * Each scan line is encoded twice: First all completely opaque pixels, + * encoded in the target format as described above, and then all + * partially transparent (translucent) pixels (where 1 <= alpha <= 254), + * in the following 32-bit format: + * + * For 32-bit targets, each pixel has the target RGB format but with + * the alpha value occupying the highest 8 bits. The <skip> and <run> + * counts are 16 bit. + * + * For 16-bit targets, each pixel has the target RGB format, but with + * the middle component (usually green) shifted 16 steps to the left, + * and the hole filled with the 5 most significant bits of the alpha value. + * i.e. if the target has the format rrrrrggggggbbbbb, + * the encoded pixel will be 00000gggggg00000rrrrr0aaaaabbbbb. + * The <skip> and <run> counts are 8 bit for the opaque lines, 16 bit + * for the translucent lines. Two padding bytes may be inserted + * before each translucent line to keep them 32-bit aligned. + * + * The end of the sequence is marked by a zero <skip>,<run> pair at the + * beginning of an opaque line. + */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" + +/* Force MMX to 0; this blows up on almost every major compiler now. --ryan. */ +#if 0 && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES +#define MMX_ASMBLIT +#endif + +#ifdef MMX_ASMBLIT +#include "mmx.h" +#include "SDL_cpuinfo.h" +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define PIXEL_COPY(to, from, len, bpp) \ +do { \ + if(bpp == 4) { \ + SDL_memcpy4(to, from, (size_t)(len)); \ + } else { \ + SDL_memcpy(to, from, (size_t)(len) * (bpp)); \ + } \ +} while(0) + +/* + * Various colorkey blit methods, for opaque and per-surface alpha + */ + +#define OPAQUE_BLIT(to, from, length, bpp, alpha) \ + PIXEL_COPY(to, from, length, bpp) + +#ifdef MMX_ASMBLIT + +#define ALPHA_BLIT32_888MMX(to, from, length, bpp, alpha) \ + do { \ + Uint32 *srcp = (Uint32 *)(from); \ + Uint32 *dstp = (Uint32 *)(to); \ + int i = 0x00FF00FF; \ + movd_m2r(*(&i), mm3); \ + punpckldq_r2r(mm3, mm3); \ + i = 0xFF000000; \ + movd_m2r(*(&i), mm7); \ + punpckldq_r2r(mm7, mm7); \ + i = alpha | alpha << 16; \ + movd_m2r(*(&i), mm4); \ + punpckldq_r2r(mm4, mm4); \ + pcmpeqd_r2r(mm5,mm5); /* set mm5 to "1" */ \ + pxor_r2r(mm7, mm5); /* make clear alpha mask */ \ + i = length; \ + if(i & 1) { \ + movd_m2r((*srcp), mm1); /* src -> mm1 */ \ + punpcklbw_r2r(mm1, mm1); \ + pand_r2r(mm3, mm1); \ + movd_m2r((*dstp), mm2); /* dst -> mm2 */ \ + punpcklbw_r2r(mm2, mm2); \ + pand_r2r(mm3, mm2); \ + psubw_r2r(mm2, mm1); \ + pmullw_r2r(mm4, mm1); \ + psrlw_i2r(8, mm1); \ + paddw_r2r(mm1, mm2); \ + pand_r2r(mm3, mm2); \ + packuswb_r2r(mm2, mm2); \ + pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */ \ + movd_r2m(mm2, *dstp); \ + ++srcp; \ + ++dstp; \ + i--; \ + } \ + for(; i > 0; --i) { \ + movq_m2r((*srcp), mm0); \ + movq_r2r(mm0, mm1); \ + punpcklbw_r2r(mm0, mm0); \ + movq_m2r((*dstp), mm2); \ + punpckhbw_r2r(mm1, mm1); \ + movq_r2r(mm2, mm6); \ + pand_r2r(mm3, mm0); \ + punpcklbw_r2r(mm2, mm2); \ + pand_r2r(mm3, mm1); \ + punpckhbw_r2r(mm6, mm6); \ + pand_r2r(mm3, mm2); \ + psubw_r2r(mm2, mm0); \ + pmullw_r2r(mm4, mm0); \ + pand_r2r(mm3, mm6); \ + psubw_r2r(mm6, mm1); \ + pmullw_r2r(mm4, mm1); \ + psrlw_i2r(8, mm0); \ + paddw_r2r(mm0, mm2); \ + psrlw_i2r(8, mm1); \ + paddw_r2r(mm1, mm6); \ + pand_r2r(mm3, mm2); \ + pand_r2r(mm3, mm6); \ + packuswb_r2r(mm2, mm2); \ + packuswb_r2r(mm6, mm6); \ + psrlq_i2r(32, mm2); \ + psllq_i2r(32, mm6); \ + por_r2r(mm6, mm2); \ + pand_r2r(mm5, mm2); /* 00000RGB -> mm2 */ \ + movq_r2m(mm2, *dstp); \ + srcp += 2; \ + dstp += 2; \ + i--; \ + } \ + emms(); \ + } while(0) + +#define ALPHA_BLIT16_565MMX(to, from, length, bpp, alpha) \ + do { \ + int i, n = 0; \ + Uint16 *srcp = (Uint16 *)(from); \ + Uint16 *dstp = (Uint16 *)(to); \ + Uint32 ALPHA = 0xF800; \ + movd_m2r(*(&ALPHA), mm1); \ + punpcklwd_r2r(mm1, mm1); \ + punpcklwd_r2r(mm1, mm1); \ + ALPHA = 0x07E0; \ + movd_m2r(*(&ALPHA), mm4); \ + punpcklwd_r2r(mm4, mm4); \ + punpcklwd_r2r(mm4, mm4); \ + ALPHA = 0x001F; \ + movd_m2r(*(&ALPHA), mm7); \ + punpcklwd_r2r(mm7, mm7); \ + punpcklwd_r2r(mm7, mm7); \ + alpha &= ~(1+2+4); \ + i = (Uint32)alpha | (Uint32)alpha << 16; \ + movd_m2r(*(&i), mm0); \ + punpckldq_r2r(mm0, mm0); \ + ALPHA = alpha >> 3; \ + i = ((int)(length) & 3); \ + for(; i > 0; --i) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + s = (s | s << 16) & 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x07e0f81f; \ + *dstp++ = d | d >> 16; \ + n++; \ + } \ + i = (int)(length) - n; \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm3); \ + movq_m2r((*srcp), mm2); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm1 , mm5); \ + psrlq_i2r(11, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm1 , mm6); \ + psrlq_i2r(11, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(11, mm6); \ + pand_r2r(mm1, mm6); \ + movq_r2r(mm4, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm4 , mm5); \ + psrlq_i2r(5, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm4 , mm6); \ + psrlq_i2r(5, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(5, mm6); \ + pand_r2r(mm4, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm7 , mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm7 , mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + pand_r2r(mm7, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm4, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2m(mm3, *dstp); \ + srcp += 4; \ + dstp += 4; \ + i -= 3; \ + } \ + emms(); \ + } while(0) + +#define ALPHA_BLIT16_555MMX(to, from, length, bpp, alpha) \ + do { \ + int i, n = 0; \ + Uint16 *srcp = (Uint16 *)(from); \ + Uint16 *dstp = (Uint16 *)(to); \ + Uint32 ALPHA = 0x7C00; \ + movd_m2r(*(&ALPHA), mm1); \ + punpcklwd_r2r(mm1, mm1); \ + punpcklwd_r2r(mm1, mm1); \ + ALPHA = 0x03E0; \ + movd_m2r(*(&ALPHA), mm4); \ + punpcklwd_r2r(mm4, mm4); \ + punpcklwd_r2r(mm4, mm4); \ + ALPHA = 0x001F; \ + movd_m2r(*(&ALPHA), mm7); \ + punpcklwd_r2r(mm7, mm7); \ + punpcklwd_r2r(mm7, mm7); \ + alpha &= ~(1+2+4); \ + i = (Uint32)alpha | (Uint32)alpha << 16; \ + movd_m2r(*(&i), mm0); \ + punpckldq_r2r(mm0, mm0); \ + i = ((int)(length) & 3); \ + ALPHA = alpha >> 3; \ + for(; i > 0; --i) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + s = (s | s << 16) & 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x03e07c1f; \ + *dstp++ = d | d >> 16; \ + n++; \ + } \ + i = (int)(length) - n; \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm3); \ + movq_m2r((*srcp), mm2); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm1 , mm5); \ + psrlq_i2r(10, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm1 , mm6); \ + psrlq_i2r(10, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(10, mm6); \ + pand_r2r(mm1, mm6); \ + movq_r2r(mm4, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm4 , mm5); \ + psrlq_i2r(5, mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm4 , mm6); \ + psrlq_i2r(5, mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + psllq_i2r(5, mm6); \ + pand_r2r(mm4, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm7, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2r(mm2, mm5); \ + pand_r2r(mm7 , mm5); \ + movq_r2r(mm3, mm6); \ + pand_r2r(mm7 , mm6); \ + psubw_r2r(mm6, mm5); \ + pmullw_r2r(mm0, mm5); \ + psrlw_i2r(8, mm5); \ + paddw_r2r(mm5, mm6); \ + pand_r2r(mm7, mm6); \ + movq_r2r(mm1, mm5); \ + por_r2r(mm4, mm5); \ + pand_r2r(mm5, mm3); \ + por_r2r(mm6, mm3); \ + movq_r2m(mm3, *dstp); \ + srcp += 4; \ + dstp += 4; \ + i -= 3; \ + } \ + emms(); \ + } while(0) + +#endif + +/* + * For 32bpp pixels on the form 0x00rrggbb: + * If we treat the middle component separately, we can process the two + * remaining in parallel. This is safe to do because of the gap to the left + * of each component, so the bits from the multiplication don't collide. + * This can be used for any RGB permutation of course. + */ +#define ALPHA_BLIT32_888(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint32 *src = (Uint32 *)(from); \ + Uint32 *dst = (Uint32 *)(to); \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dst++ = d1 | d; \ + } \ + } while(0) + +/* + * For 16bpp pixels we can go a step further: put the middle component + * in the high 16 bits of a 32 bit word, and process all three RGB + * components at the same time. Since the smallest gap is here just + * 5 bits, we have to scale alpha down to 5 bits as well. + */ +#define ALPHA_BLIT16_565(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + Uint32 ALPHA = alpha >> 3; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + s = (s | s << 16) & 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x07e0f81f; \ + *dst++ = (Uint16)(d | d >> 16); \ + } \ + } while(0) + +#define ALPHA_BLIT16_555(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + Uint32 ALPHA = alpha >> 3; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + s = (s | s << 16) & 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * ALPHA >> 5; \ + d &= 0x03e07c1f; \ + *dst++ = (Uint16)(d | d >> 16); \ + } \ + } while(0) + +/* + * The general slow catch-all function, for remaining depths and formats + */ +#define ALPHA_BLIT_ANY(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint8 *src = from; \ + Uint8 *dst = to; \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s, d; \ + unsigned rs, gs, bs, rd, gd, bd; \ + switch(bpp) { \ + case 2: \ + s = *(Uint16 *)src; \ + d = *(Uint16 *)dst; \ + break; \ + case 3: \ + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ + s = (src[0] << 16) | (src[1] << 8) | src[2]; \ + d = (dst[0] << 16) | (dst[1] << 8) | dst[2]; \ + } else { \ + s = (src[2] << 16) | (src[1] << 8) | src[0]; \ + d = (dst[2] << 16) | (dst[1] << 8) | dst[0]; \ + } \ + break; \ + case 4: \ + s = *(Uint32 *)src; \ + d = *(Uint32 *)dst; \ + break; \ + } \ + RGB_FROM_PIXEL(s, fmt, rs, gs, bs); \ + RGB_FROM_PIXEL(d, fmt, rd, gd, bd); \ + rd += (rs - rd) * alpha >> 8; \ + gd += (gs - gd) * alpha >> 8; \ + bd += (bs - bd) * alpha >> 8; \ + PIXEL_FROM_RGB(d, fmt, rd, gd, bd); \ + switch(bpp) { \ + case 2: \ + *(Uint16 *)dst = (Uint16)d; \ + break; \ + case 3: \ + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { \ + dst[0] = (Uint8)(d >> 16); \ + dst[1] = (Uint8)(d >> 8); \ + dst[2] = (Uint8)(d); \ + } else { \ + dst[0] = (Uint8)d; \ + dst[1] = (Uint8)(d >> 8); \ + dst[2] = (Uint8)(d >> 16); \ + } \ + break; \ + case 4: \ + *(Uint32 *)dst = d; \ + break; \ + } \ + src += bpp; \ + dst += bpp; \ + } \ + } while(0) + +#ifdef MMX_ASMBLIT + +#define ALPHA_BLIT32_888_50MMX(to, from, length, bpp, alpha) \ + do { \ + Uint32 *srcp = (Uint32 *)(from); \ + Uint32 *dstp = (Uint32 *)(to); \ + int i = 0x00fefefe; \ + movd_m2r(*(&i), mm4); \ + punpckldq_r2r(mm4, mm4); \ + i = 0x00010101; \ + movd_m2r(*(&i), mm3); \ + punpckldq_r2r(mm3, mm3); \ + i = (int)(length); \ + if( i & 1 ) { \ + Uint32 s = *srcp++; \ + Uint32 d = *dstp; \ + *dstp++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \ + + (s & d & 0x00010101); \ + i--; \ + } \ + for(; i > 0; --i) { \ + movq_m2r((*dstp), mm2); /* dst -> mm2 */ \ + movq_r2r(mm2, mm6); /* dst -> mm6 */ \ + movq_m2r((*srcp), mm1); /* src -> mm1 */ \ + movq_r2r(mm1, mm5); /* src -> mm5 */ \ + pand_r2r(mm4, mm6); /* dst & 0x00fefefe -> mm6 */ \ + pand_r2r(mm4, mm5); /* src & 0x00fefefe -> mm5 */ \ + paddd_r2r(mm6, mm5); /* (dst & 0x00fefefe) + (dst & 0x00fefefe) -> mm5 */ \ + psrld_i2r(1, mm5); \ + pand_r2r(mm1, mm2); /* s & d -> mm2 */ \ + pand_r2r(mm3, mm2); /* s & d & 0x00010101 -> mm2 */ \ + paddd_r2r(mm5, mm2); \ + movq_r2m(mm2, (*dstp)); \ + dstp += 2; \ + srcp += 2; \ + i--; \ + } \ + emms(); \ + } while(0) + +#endif + +/* + * Special case: 50% alpha (alpha=128) + * This is treated specially because it can be optimized very well, and + * since it is good for many cases of semi-translucency. + * The theory is to do all three components at the same time: + * First zero the lowest bit of each component, which gives us room to + * add them. Then shift right and add the sum of the lowest bits. + */ +#define ALPHA_BLIT32_888_50(to, from, length, bpp, alpha) \ + do { \ + int i; \ + Uint32 *src = (Uint32 *)(from); \ + Uint32 *dst = (Uint32 *)(to); \ + for(i = 0; i < (int)(length); i++) { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + *dst++ = (((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) \ + + (s & d & 0x00010101); \ + } \ + } while(0) + +/* + * For 16bpp, we can actually blend two pixels in parallel, if we take + * care to shift before we add, not after. + */ + +/* helper: blend a single 16 bit pixel at 50% */ +#define BLEND16_50(dst, src, mask) \ + do { \ + Uint32 s = *src++; \ + Uint32 d = *dst; \ + *dst++ = (Uint16)((((s & mask) + (d & mask)) >> 1) + \ + (s & d & (~mask & 0xffff))); \ + } while(0) + +/* basic 16bpp blender. mask is the pixels to keep when adding. */ +#define ALPHA_BLIT16_50(to, from, length, bpp, alpha, mask) \ + do { \ + unsigned n = (length); \ + Uint16 *src = (Uint16 *)(from); \ + Uint16 *dst = (Uint16 *)(to); \ + if(((uintptr_t)src ^ (uintptr_t)dst) & 3) { \ + /* source and destination not in phase, blit one by one */ \ + while(n--) \ + BLEND16_50(dst, src, mask); \ + } else { \ + if((uintptr_t)src & 3) { \ + /* first odd pixel */ \ + BLEND16_50(dst, src, mask); \ + n--; \ + } \ + for(; n > 1; n -= 2) { \ + Uint32 s = *(Uint32 *)src; \ + Uint32 d = *(Uint32 *)dst; \ + *(Uint32 *)dst = ((s & (mask | mask << 16)) >> 1) \ + + ((d & (mask | mask << 16)) >> 1) \ + + (s & d & (~(mask | mask << 16))); \ + src += 2; \ + dst += 2; \ + } \ + if(n) \ + BLEND16_50(dst, src, mask); /* last odd pixel */ \ + } \ + } while(0) + +#define ALPHA_BLIT16_565_50(to, from, length, bpp, alpha) \ + ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xf7de) + +#define ALPHA_BLIT16_555_50(to, from, length, bpp, alpha) \ + ALPHA_BLIT16_50(to, from, length, bpp, alpha, 0xfbde) + +#ifdef MMX_ASMBLIT + +#define CHOOSE_BLIT(blitter, alpha, fmt) \ + do { \ + if(alpha == 255) { \ + switch(fmt->BytesPerPixel) { \ + case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \ + case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \ + case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \ + case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \ + } \ + } else { \ + switch(fmt->BytesPerPixel) { \ + case 1: \ + /* No 8bpp alpha blitting */ \ + break; \ + \ + case 2: \ + switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) { \ + case 0xffff: \ + if(fmt->Gmask == 0x07e0 \ + || fmt->Rmask == 0x07e0 \ + || fmt->Bmask == 0x07e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_565_50); \ + else { \ + if(SDL_HasMMX()) \ + blitter(2, Uint8, ALPHA_BLIT16_565MMX); \ + else \ + blitter(2, Uint8, ALPHA_BLIT16_565); \ + } \ + } else \ + goto general16; \ + break; \ + \ + case 0x7fff: \ + if(fmt->Gmask == 0x03e0 \ + || fmt->Rmask == 0x03e0 \ + || fmt->Bmask == 0x03e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_555_50); \ + else { \ + if(SDL_HasMMX()) \ + blitter(2, Uint8, ALPHA_BLIT16_555MMX); \ + else \ + blitter(2, Uint8, ALPHA_BLIT16_555); \ + } \ + break; \ + } \ + /* fallthrough */ \ + \ + default: \ + general16: \ + blitter(2, Uint8, ALPHA_BLIT_ANY); \ + } \ + break; \ + \ + case 3: \ + blitter(3, Uint8, ALPHA_BLIT_ANY); \ + break; \ + \ + case 4: \ + if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \ + && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \ + || fmt->Bmask == 0xff00)) { \ + if(alpha == 128) \ + { \ + if(SDL_HasMMX()) \ + blitter(4, Uint16, ALPHA_BLIT32_888_50MMX);\ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888_50);\ + } \ + else \ + { \ + if(SDL_HasMMX()) \ + blitter(4, Uint16, ALPHA_BLIT32_888MMX);\ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888); \ + } \ + } else \ + blitter(4, Uint16, ALPHA_BLIT_ANY); \ + break; \ + } \ + } \ + } while(0) + +#else + +#define CHOOSE_BLIT(blitter, alpha, fmt) \ + do { \ + if(alpha == 255) { \ + switch(fmt->BytesPerPixel) { \ + case 1: blitter(1, Uint8, OPAQUE_BLIT); break; \ + case 2: blitter(2, Uint8, OPAQUE_BLIT); break; \ + case 3: blitter(3, Uint8, OPAQUE_BLIT); break; \ + case 4: blitter(4, Uint16, OPAQUE_BLIT); break; \ + } \ + } else { \ + switch(fmt->BytesPerPixel) { \ + case 1: \ + /* No 8bpp alpha blitting */ \ + break; \ + \ + case 2: \ + switch(fmt->Rmask | fmt->Gmask | fmt->Bmask) { \ + case 0xffff: \ + if(fmt->Gmask == 0x07e0 \ + || fmt->Rmask == 0x07e0 \ + || fmt->Bmask == 0x07e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_565_50); \ + else { \ + blitter(2, Uint8, ALPHA_BLIT16_565); \ + } \ + } else \ + goto general16; \ + break; \ + \ + case 0x7fff: \ + if(fmt->Gmask == 0x03e0 \ + || fmt->Rmask == 0x03e0 \ + || fmt->Bmask == 0x03e0) { \ + if(alpha == 128) \ + blitter(2, Uint8, ALPHA_BLIT16_555_50); \ + else { \ + blitter(2, Uint8, ALPHA_BLIT16_555); \ + } \ + break; \ + } \ + /* fallthrough */ \ + \ + default: \ + general16: \ + blitter(2, Uint8, ALPHA_BLIT_ANY); \ + } \ + break; \ + \ + case 3: \ + blitter(3, Uint8, ALPHA_BLIT_ANY); \ + break; \ + \ + case 4: \ + if((fmt->Rmask | fmt->Gmask | fmt->Bmask) == 0x00ffffff \ + && (fmt->Gmask == 0xff00 || fmt->Rmask == 0xff00 \ + || fmt->Bmask == 0xff00)) { \ + if(alpha == 128) \ + blitter(4, Uint16, ALPHA_BLIT32_888_50); \ + else \ + blitter(4, Uint16, ALPHA_BLIT32_888); \ + } else \ + blitter(4, Uint16, ALPHA_BLIT_ANY); \ + break; \ + } \ + } \ + } while(0) + +#endif + +/* + * This takes care of the case when the surface is clipped on the left and/or + * right. Top clipping has already been taken care of. + */ +static void RLEClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, + Uint8 *dstbuf, SDL_Rect *srcrect, unsigned alpha) +{ + SDL_PixelFormat *fmt = dst->format; + +#define RLECLIPBLIT(bpp, Type, do_blit) \ + do { \ + int linecount = srcrect->h; \ + int ofs = 0; \ + int left = srcrect->x; \ + int right = left + srcrect->w; \ + dstbuf -= left * bpp; \ + for(;;) { \ + int run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Type); \ + if(run) { \ + /* clip to left and right borders */ \ + if(ofs < right) { \ + int start = 0; \ + int len = run; \ + int startcol; \ + if(left - ofs > 0) { \ + start = left - ofs; \ + len -= start; \ + if(len <= 0) \ + goto nocopy ## bpp ## do_blit; \ + } \ + startcol = ofs + start; \ + if(len > right - startcol) \ + len = right - startcol; \ + do_blit(dstbuf + startcol * bpp, srcbuf + start * bpp, \ + len, bpp, alpha); \ + } \ + nocopy ## bpp ## do_blit: \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + break; \ + if(ofs == w) { \ + ofs = 0; \ + dstbuf += dst->pitch; \ + if(!--linecount) \ + break; \ + } \ + } \ + } while(0) + + CHOOSE_BLIT(RLECLIPBLIT, alpha, fmt); + +#undef RLECLIPBLIT + +} + + +/* blit a colorkeyed RLE surface */ +int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + Uint8 *dstbuf; + Uint8 *srcbuf; + int x, y; + int w = src->w; + unsigned alpha; + + /* Lock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return(-1); + } + } + + /* Set up the source and destination pointers */ + x = dstrect->x; + y = dstrect->y; + dstbuf = (Uint8 *)dst->pixels + + y * dst->pitch + x * src->format->BytesPerPixel; + srcbuf = (Uint8 *)src->map->sw_data->aux_data; + + { + /* skip lines at the top if neccessary */ + int vskip = srcrect->y; + int ofs = 0; + if(vskip) { + +#define RLESKIP(bpp, Type) \ + for(;;) { \ + int run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += sizeof(Type) * 2; \ + if(run) { \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + goto done; \ + if(ofs == w) { \ + ofs = 0; \ + if(!--vskip) \ + break; \ + } \ + } + + switch(src->format->BytesPerPixel) { + case 1: RLESKIP(1, Uint8); break; + case 2: RLESKIP(2, Uint8); break; + case 3: RLESKIP(3, Uint8); break; + case 4: RLESKIP(4, Uint16); break; + } + +#undef RLESKIP + + } + } + + alpha = (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA + ? src->format->alpha : 255; + /* if left or right edge clipping needed, call clip blit */ + if ( srcrect->x || srcrect->w != src->w ) { + RLEClipBlit(w, srcbuf, dst, dstbuf, srcrect, alpha); + } else { + SDL_PixelFormat *fmt = src->format; + +#define RLEBLIT(bpp, Type, do_blit) \ + do { \ + int linecount = srcrect->h; \ + int ofs = 0; \ + for(;;) { \ + unsigned run; \ + ofs += *(Type *)srcbuf; \ + run = ((Type *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Type); \ + if(run) { \ + do_blit(dstbuf + ofs * bpp, srcbuf, run, bpp, alpha); \ + srcbuf += run * bpp; \ + ofs += run; \ + } else if(!ofs) \ + break; \ + if(ofs == w) { \ + ofs = 0; \ + dstbuf += dst->pitch; \ + if(!--linecount) \ + break; \ + } \ + } \ + } while(0) + + CHOOSE_BLIT(RLEBLIT, alpha, fmt); + +#undef RLEBLIT + } + +done: + /* Unlock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + return(0); +} + +#undef OPAQUE_BLIT + +/* + * Per-pixel blitting macros for translucent pixels: + * These use the same techniques as the per-surface blitting macros + */ + +/* + * For 32bpp pixels, we have made sure the alpha is stored in the top + * 8 bits, so proceed as usual + */ +#define BLIT_TRANSL_888(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = s >> 24; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + dst = d1 | d; \ + } while(0) + +/* + * For 16bpp pixels, we have stored the 5 most significant alpha bits in + * bits 5-10. As before, we can process all 3 RGB components at the same time. + */ +#define BLIT_TRANSL_565(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = (s & 0x3e0) >> 5; \ + s &= 0x07e0f81f; \ + d = (d | d << 16) & 0x07e0f81f; \ + d += (s - d) * alpha >> 5; \ + d &= 0x07e0f81f; \ + dst = (Uint16)(d | d >> 16); \ + } while(0) + +#define BLIT_TRANSL_555(src, dst) \ + do { \ + Uint32 s = src; \ + Uint32 d = dst; \ + unsigned alpha = (s & 0x3e0) >> 5; \ + s &= 0x03e07c1f; \ + d = (d | d << 16) & 0x03e07c1f; \ + d += (s - d) * alpha >> 5; \ + d &= 0x03e07c1f; \ + dst = (Uint16)(d | d >> 16); \ + } while(0) + +/* used to save the destination format in the encoding. Designed to be + macro-compatible with SDL_PixelFormat but without the unneeded fields */ +typedef struct { + Uint8 BytesPerPixel; + Uint8 Rloss; + Uint8 Gloss; + Uint8 Bloss; + Uint8 Rshift; + Uint8 Gshift; + Uint8 Bshift; + Uint8 Ashift; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + Uint32 Amask; +} RLEDestFormat; + +/* blit a pixel-alpha RLE surface clipped at the right and/or left edges */ +static void RLEAlphaClipBlit(int w, Uint8 *srcbuf, SDL_Surface *dst, + Uint8 *dstbuf, SDL_Rect *srcrect) +{ + SDL_PixelFormat *df = dst->format; + /* + * clipped blitter: Ptype is the destination pixel type, + * Ctype the translucent count type, and do_blend the macro + * to blend one pixel. + */ +#define RLEALPHACLIPBLIT(Ptype, Ctype, do_blend) \ + do { \ + int linecount = srcrect->h; \ + int left = srcrect->x; \ + int right = left + srcrect->w; \ + dstbuf -= left * sizeof(Ptype); \ + do { \ + int ofs = 0; \ + /* blit opaque pixels on one line */ \ + do { \ + unsigned run; \ + ofs += ((Ctype *)srcbuf)[0]; \ + run = ((Ctype *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Ctype); \ + if(run) { \ + /* clip to left and right borders */ \ + int cofs = ofs; \ + int crun = run; \ + if(left - cofs > 0) { \ + crun -= left - cofs; \ + cofs = left; \ + } \ + if(crun > right - cofs) \ + crun = right - cofs; \ + if(crun > 0) \ + PIXEL_COPY(dstbuf + cofs * sizeof(Ptype), \ + srcbuf + (cofs - ofs) * sizeof(Ptype), \ + (unsigned)crun, sizeof(Ptype)); \ + srcbuf += run * sizeof(Ptype); \ + ofs += run; \ + } else if(!ofs) \ + return; \ + } while(ofs < w); \ + /* skip padding if necessary */ \ + if(sizeof(Ptype) == 2) \ + srcbuf += (uintptr_t)srcbuf & 2; \ + /* blit translucent pixels on the same line */ \ + ofs = 0; \ + do { \ + unsigned run; \ + ofs += ((Uint16 *)srcbuf)[0]; \ + run = ((Uint16 *)srcbuf)[1]; \ + srcbuf += 4; \ + if(run) { \ + /* clip to left and right borders */ \ + int cofs = ofs; \ + int crun = run; \ + if(left - cofs > 0) { \ + crun -= left - cofs; \ + cofs = left; \ + } \ + if(crun > right - cofs) \ + crun = right - cofs; \ + if(crun > 0) { \ + Ptype *dst = (Ptype *)dstbuf + cofs; \ + Uint32 *src = (Uint32 *)srcbuf + (cofs - ofs); \ + int i; \ + for(i = 0; i < crun; i++) \ + do_blend(src[i], dst[i]); \ + } \ + srcbuf += run * 4; \ + ofs += run; \ + } \ + } while(ofs < w); \ + dstbuf += dst->pitch; \ + } while(--linecount); \ + } while(0) + + switch(df->BytesPerPixel) { + case 2: + if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 + || df->Bmask == 0x07e0) + RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_565); + else + RLEALPHACLIPBLIT(Uint16, Uint8, BLIT_TRANSL_555); + break; + case 4: + RLEALPHACLIPBLIT(Uint32, Uint16, BLIT_TRANSL_888); + break; + } +} + +/* blit a pixel-alpha RLE surface */ +int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int x, y; + int w = src->w; + Uint8 *srcbuf, *dstbuf; + SDL_PixelFormat *df = dst->format; + + /* Lock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + return -1; + } + } + + x = dstrect->x; + y = dstrect->y; + dstbuf = (Uint8 *)dst->pixels + + y * dst->pitch + x * df->BytesPerPixel; + srcbuf = (Uint8 *)src->map->sw_data->aux_data + sizeof(RLEDestFormat); + + { + /* skip lines at the top if necessary */ + int vskip = srcrect->y; + if(vskip) { + int ofs; + if(df->BytesPerPixel == 2) { + /* the 16/32 interleaved format */ + do { + /* skip opaque line */ + ofs = 0; + do { + int run; + ofs += srcbuf[0]; + run = srcbuf[1]; + srcbuf += 2; + if(run) { + srcbuf += 2 * run; + ofs += run; + } else if(!ofs) + goto done; + } while(ofs < w); + + /* skip padding */ + srcbuf += (uintptr_t)srcbuf & 2; + + /* skip translucent line */ + ofs = 0; + do { + int run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4 * (run + 1); + ofs += run; + } while(ofs < w); + } while(--vskip); + } else { + /* the 32/32 interleaved format */ + vskip <<= 1; /* opaque and translucent have same format */ + do { + ofs = 0; + do { + int run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + if(run) { + srcbuf += 4 * run; + ofs += run; + } else if(!ofs) + goto done; + } while(ofs < w); + } while(--vskip); + } + } + } + + /* if left or right edge clipping needed, call clip blit */ + if(srcrect->x || srcrect->w != src->w) { + RLEAlphaClipBlit(w, srcbuf, dst, dstbuf, srcrect); + } else { + + /* + * non-clipped blitter. Ptype is the destination pixel type, + * Ctype the translucent count type, and do_blend the + * macro to blend one pixel. + */ +#define RLEALPHABLIT(Ptype, Ctype, do_blend) \ + do { \ + int linecount = srcrect->h; \ + do { \ + int ofs = 0; \ + /* blit opaque pixels on one line */ \ + do { \ + unsigned run; \ + ofs += ((Ctype *)srcbuf)[0]; \ + run = ((Ctype *)srcbuf)[1]; \ + srcbuf += 2 * sizeof(Ctype); \ + if(run) { \ + PIXEL_COPY(dstbuf + ofs * sizeof(Ptype), srcbuf, \ + run, sizeof(Ptype)); \ + srcbuf += run * sizeof(Ptype); \ + ofs += run; \ + } else if(!ofs) \ + goto done; \ + } while(ofs < w); \ + /* skip padding if necessary */ \ + if(sizeof(Ptype) == 2) \ + srcbuf += (uintptr_t)srcbuf & 2; \ + /* blit translucent pixels on the same line */ \ + ofs = 0; \ + do { \ + unsigned run; \ + ofs += ((Uint16 *)srcbuf)[0]; \ + run = ((Uint16 *)srcbuf)[1]; \ + srcbuf += 4; \ + if(run) { \ + Ptype *dst = (Ptype *)dstbuf + ofs; \ + unsigned i; \ + for(i = 0; i < run; i++) { \ + Uint32 src = *(Uint32 *)srcbuf; \ + do_blend(src, *dst); \ + srcbuf += 4; \ + dst++; \ + } \ + ofs += run; \ + } \ + } while(ofs < w); \ + dstbuf += dst->pitch; \ + } while(--linecount); \ + } while(0) + + switch(df->BytesPerPixel) { + case 2: + if(df->Gmask == 0x07e0 || df->Rmask == 0x07e0 + || df->Bmask == 0x07e0) + RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_565); + else + RLEALPHABLIT(Uint16, Uint8, BLIT_TRANSL_555); + break; + case 4: + RLEALPHABLIT(Uint32, Uint16, BLIT_TRANSL_888); + break; + } + } + + done: + /* Unlock the destination if necessary */ + if ( SDL_MUSTLOCK(dst) ) { + SDL_UnlockSurface(dst); + } + return 0; +} + +/* + * Auxiliary functions: + * The encoding functions take 32bpp rgb + a, and + * return the number of bytes copied to the destination. + * The decoding functions copy to 32bpp rgb + a, and + * return the number of bytes copied from the source. + * These are only used in the encoder and un-RLE code and are therefore not + * highly optimised. + */ + +/* encode 32bpp rgb + a into 16bpp rgb, losing alpha */ +static int copy_opaque_16(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint16 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b; + RGB_FROM_PIXEL(*src, sfmt, r, g, b); + PIXEL_FROM_RGB(*d, dfmt, r, g, b); + src++; + d++; + } + return n * 2; +} + +/* decode opaque pixels from 16bpp to 32bpp rgb + a */ +static int uncopy_opaque_16(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint16 *s = src; + unsigned alpha = dfmt->Amask ? 255 : 0; + for(i = 0; i < n; i++) { + unsigned r, g, b; + RGB_FROM_PIXEL(*s, sfmt, r, g, b); + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, alpha); + s++; + dst++; + } + return n * 2; +} + + + +/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 565 */ +static int copy_transl_565(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint16 pix; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pix, dfmt, r, g, b); + *d = ((pix & 0x7e0) << 16) | (pix & 0xf81f) | ((a << 2) & 0x7e0); + src++; + d++; + } + return n * 4; +} + +/* encode 32bpp rgb + a into 32bpp G0RAB format for blitting into 555 */ +static int copy_transl_555(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint16 pix; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pix, dfmt, r, g, b); + *d = ((pix & 0x3e0) << 16) | (pix & 0xfc1f) | ((a << 2) & 0x3e0); + src++; + d++; + } + return n * 4; +} + +/* decode translucent pixels from 32bpp GORAB to 32bpp rgb + a */ +static int uncopy_transl_16(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *s = src; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pix = *s++; + a = (pix & 0x3e0) >> 2; + pix = (pix & ~0x3e0) | pix >> 16; + RGB_FROM_PIXEL(pix, sfmt, r, g, b); + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); + dst++; + } + return n * 4; +} + +/* encode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */ +static int copy_32(void *dst, Uint32 *src, int n, + SDL_PixelFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *d = dst; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pixel; + RGBA_FROM_8888(*src, sfmt, r, g, b, a); + PIXEL_FROM_RGB(pixel, dfmt, r, g, b); + *d++ = pixel | a << 24; + src++; + } + return n * 4; +} + +/* decode 32bpp rgba into 32bpp rgba, keeping alpha (dual purpose) */ +static int uncopy_32(Uint32 *dst, void *src, int n, + RLEDestFormat *sfmt, SDL_PixelFormat *dfmt) +{ + int i; + Uint32 *s = src; + for(i = 0; i < n; i++) { + unsigned r, g, b, a; + Uint32 pixel = *s++; + RGB_FROM_PIXEL(pixel, sfmt, r, g, b); + a = pixel >> 24; + PIXEL_FROM_RGBA(*dst, dfmt, r, g, b, a); + dst++; + } + return n * 4; +} + +#define ISOPAQUE(pixel, fmt) ((((pixel) & fmt->Amask) >> fmt->Ashift) == 255) + +#define ISTRANSL(pixel, fmt) \ + ((unsigned)((((pixel) & fmt->Amask) >> fmt->Ashift) - 1U) < 254U) + +/* convert surface to be quickly alpha-blittable onto dest, if possible */ +static int RLEAlphaSurface(SDL_Surface *surface) +{ + SDL_Surface *dest; + SDL_PixelFormat *df; + int maxsize = 0; + int max_opaque_run; + int max_transl_run = 65535; + unsigned masksum; + Uint8 *rlebuf, *dst; + int (*copy_opaque)(void *, Uint32 *, int, + SDL_PixelFormat *, SDL_PixelFormat *); + int (*copy_transl)(void *, Uint32 *, int, + SDL_PixelFormat *, SDL_PixelFormat *); + + dest = surface->map->dst; + if(!dest) + return -1; + df = dest->format; + if(surface->format->BitsPerPixel != 32) + return -1; /* only 32bpp source supported */ + + /* find out whether the destination is one we support, + and determine the max size of the encoded result */ + masksum = df->Rmask | df->Gmask | df->Bmask; + switch(df->BytesPerPixel) { + case 2: + /* 16bpp: only support 565 and 555 formats */ + switch(masksum) { + case 0xffff: + if(df->Gmask == 0x07e0 + || df->Rmask == 0x07e0 || df->Bmask == 0x07e0) { + copy_opaque = copy_opaque_16; + copy_transl = copy_transl_565; + } else + return -1; + break; + case 0x7fff: + if(df->Gmask == 0x03e0 + || df->Rmask == 0x03e0 || df->Bmask == 0x03e0) { + copy_opaque = copy_opaque_16; + copy_transl = copy_transl_555; + } else + return -1; + break; + default: + return -1; + } + max_opaque_run = 255; /* runs stored as bytes */ + + /* worst case is alternating opaque and translucent pixels, + with room for alignment padding between lines */ + maxsize = surface->h * (2 + (4 + 2) * (surface->w + 1)) + 2; + break; + case 4: + if(masksum != 0x00ffffff) + return -1; /* requires unused high byte */ + copy_opaque = copy_32; + copy_transl = copy_32; + max_opaque_run = 255; /* runs stored as short ints */ + + /* worst case is alternating opaque and translucent pixels */ + maxsize = surface->h * 2 * 4 * (surface->w + 1) + 4; + break; + default: + return -1; /* anything else unsupported right now */ + } + + maxsize += sizeof(RLEDestFormat); + rlebuf = (Uint8 *)SDL_malloc(maxsize); + if(!rlebuf) { + SDL_OutOfMemory(); + return -1; + } + { + /* save the destination format so we can undo the encoding later */ + RLEDestFormat *r = (RLEDestFormat *)rlebuf; + r->BytesPerPixel = df->BytesPerPixel; + r->Rloss = df->Rloss; + r->Gloss = df->Gloss; + r->Bloss = df->Bloss; + r->Rshift = df->Rshift; + r->Gshift = df->Gshift; + r->Bshift = df->Bshift; + r->Ashift = df->Ashift; + r->Rmask = df->Rmask; + r->Gmask = df->Gmask; + r->Bmask = df->Bmask; + r->Amask = df->Amask; + } + dst = rlebuf + sizeof(RLEDestFormat); + + /* Do the actual encoding */ + { + int x, y; + int h = surface->h, w = surface->w; + SDL_PixelFormat *sf = surface->format; + Uint32 *src = (Uint32 *)surface->pixels; + Uint8 *lastline = dst; /* end of last non-blank line */ + + /* opaque counts are 8 or 16 bits, depending on target depth */ +#define ADD_OPAQUE_COUNTS(n, m) \ + if(df->BytesPerPixel == 4) { \ + ((Uint16 *)dst)[0] = n; \ + ((Uint16 *)dst)[1] = m; \ + dst += 4; \ + } else { \ + dst[0] = n; \ + dst[1] = m; \ + dst += 2; \ + } + + /* translucent counts are always 16 bit */ +#define ADD_TRANSL_COUNTS(n, m) \ + (((Uint16 *)dst)[0] = n, ((Uint16 *)dst)[1] = m, dst += 4) + + for(y = 0; y < h; y++) { + int runstart, skipstart; + int blankline = 0; + /* First encode all opaque pixels of a scan line */ + x = 0; + do { + int run, skip, len; + skipstart = x; + while(x < w && !ISOPAQUE(src[x], sf)) + x++; + runstart = x; + while(x < w && ISOPAQUE(src[x], sf)) + x++; + skip = runstart - skipstart; + if(skip == w) + blankline = 1; + run = x - runstart; + while(skip > max_opaque_run) { + ADD_OPAQUE_COUNTS(max_opaque_run, 0); + skip -= max_opaque_run; + } + len = MIN(run, max_opaque_run); + ADD_OPAQUE_COUNTS(skip, len); + dst += copy_opaque(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + while(run) { + len = MIN(run, max_opaque_run); + ADD_OPAQUE_COUNTS(0, len); + dst += copy_opaque(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + } + } while(x < w); + + /* Make sure the next output address is 32-bit aligned */ + dst += (uintptr_t)dst & 2; + + /* Next, encode all translucent pixels of the same scan line */ + x = 0; + do { + int run, skip, len; + skipstart = x; + while(x < w && !ISTRANSL(src[x], sf)) + x++; + runstart = x; + while(x < w && ISTRANSL(src[x], sf)) + x++; + skip = runstart - skipstart; + blankline &= (skip == w); + run = x - runstart; + while(skip > max_transl_run) { + ADD_TRANSL_COUNTS(max_transl_run, 0); + skip -= max_transl_run; + } + len = MIN(run, max_transl_run); + ADD_TRANSL_COUNTS(skip, len); + dst += copy_transl(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + while(run) { + len = MIN(run, max_transl_run); + ADD_TRANSL_COUNTS(0, len); + dst += copy_transl(dst, src + runstart, len, sf, df); + runstart += len; + run -= len; + } + if(!blankline) + lastline = dst; + } while(x < w); + + src += surface->pitch >> 2; + } + dst = lastline; /* back up past trailing blank lines */ + ADD_OPAQUE_COUNTS(0, 0); + } + +#undef ADD_OPAQUE_COUNTS +#undef ADD_TRANSL_COUNTS + + /* Now that we have it encoded, release the original pixels */ + if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + SDL_free( surface->pixels ); + surface->pixels = NULL; + } + + /* realloc the buffer to release unused memory */ + { + Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); + if(!p) + p = rlebuf; + surface->map->sw_data->aux_data = p; + } + + return 0; +} + +static Uint32 getpix_8(Uint8 *srcbuf) +{ + return *srcbuf; +} + +static Uint32 getpix_16(Uint8 *srcbuf) +{ + return *(Uint16 *)srcbuf; +} + +static Uint32 getpix_24(Uint8 *srcbuf) +{ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + return srcbuf[0] + (srcbuf[1] << 8) + (srcbuf[2] << 16); +#else + return (srcbuf[0] << 16) + (srcbuf[1] << 8) + srcbuf[2]; +#endif +} + +static Uint32 getpix_32(Uint8 *srcbuf) +{ + return *(Uint32 *)srcbuf; +} + +typedef Uint32 (*getpix_func)(Uint8 *); + +static getpix_func getpixes[4] = { + getpix_8, getpix_16, getpix_24, getpix_32 +}; + +static int RLEColorkeySurface(SDL_Surface *surface) +{ + Uint8 *rlebuf, *dst; + int maxn; + int y; + Uint8 *srcbuf, *lastline; + int maxsize = 0; + int bpp = surface->format->BytesPerPixel; + getpix_func getpix; + Uint32 ckey, rgbmask; + int w, h; + + /* calculate the worst case size for the compressed surface */ + switch(bpp) { + case 1: + /* worst case is alternating opaque and transparent pixels, + starting with an opaque pixel */ + maxsize = surface->h * 3 * (surface->w / 2 + 1) + 2; + break; + case 2: + case 3: + /* worst case is solid runs, at most 255 pixels wide */ + maxsize = surface->h * (2 * (surface->w / 255 + 1) + + surface->w * bpp) + 2; + break; + case 4: + /* worst case is solid runs, at most 65535 pixels wide */ + maxsize = surface->h * (4 * (surface->w / 65535 + 1) + + surface->w * 4) + 4; + break; + } + + rlebuf = (Uint8 *)SDL_malloc(maxsize); + if ( rlebuf == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + + /* Set up the conversion */ + srcbuf = (Uint8 *)surface->pixels; + maxn = bpp == 4 ? 65535 : 255; + dst = rlebuf; + rgbmask = ~surface->format->Amask; + ckey = surface->format->colorkey & rgbmask; + lastline = dst; + getpix = getpixes[bpp - 1]; + w = surface->w; + h = surface->h; + +#define ADD_COUNTS(n, m) \ + if(bpp == 4) { \ + ((Uint16 *)dst)[0] = n; \ + ((Uint16 *)dst)[1] = m; \ + dst += 4; \ + } else { \ + dst[0] = n; \ + dst[1] = m; \ + dst += 2; \ + } + + for(y = 0; y < h; y++) { + int x = 0; + int blankline = 0; + do { + int run, skip, len; + int runstart; + int skipstart = x; + + /* find run of transparent, then opaque pixels */ + while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) == ckey) + x++; + runstart = x; + while(x < w && (getpix(srcbuf + x * bpp) & rgbmask) != ckey) + x++; + skip = runstart - skipstart; + if(skip == w) + blankline = 1; + run = x - runstart; + + /* encode segment */ + while(skip > maxn) { + ADD_COUNTS(maxn, 0); + skip -= maxn; + } + len = MIN(run, maxn); + ADD_COUNTS(skip, len); + SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp); + dst += len * bpp; + run -= len; + runstart += len; + while(run) { + len = MIN(run, maxn); + ADD_COUNTS(0, len); + SDL_memcpy(dst, srcbuf + runstart * bpp, len * bpp); + dst += len * bpp; + runstart += len; + run -= len; + } + if(!blankline) + lastline = dst; + } while(x < w); + + srcbuf += surface->pitch; + } + dst = lastline; /* back up bast trailing blank lines */ + ADD_COUNTS(0, 0); + +#undef ADD_COUNTS + + /* Now that we have it encoded, release the original pixels */ + if((surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + SDL_free( surface->pixels ); + surface->pixels = NULL; + } + + /* realloc the buffer to release unused memory */ + { + /* If realloc returns NULL, the original block is left intact */ + Uint8 *p = SDL_realloc(rlebuf, dst - rlebuf); + if(!p) + p = rlebuf; + surface->map->sw_data->aux_data = p; + } + + return(0); +} + +int SDL_RLESurface(SDL_Surface *surface) +{ + int retcode; + + /* Clear any previous RLE conversion */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + + /* We don't support RLE encoding of bitmaps */ + if ( surface->format->BitsPerPixel < 8 ) { + return(-1); + } + + /* Lock the surface if it's in hardware */ + if ( SDL_MUSTLOCK(surface) ) { + if ( SDL_LockSurface(surface) < 0 ) { + return(-1); + } + } + + /* Encode */ + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + retcode = RLEColorkeySurface(surface); + } else { + if((surface->flags & SDL_SRCALPHA) == SDL_SRCALPHA + && surface->format->Amask != 0) + retcode = RLEAlphaSurface(surface); + else + retcode = -1; /* no RLE for per-surface alpha sans ckey */ + } + + /* Unlock the surface if it's in hardware */ + if ( SDL_MUSTLOCK(surface) ) { + SDL_UnlockSurface(surface); + } + + if(retcode < 0) + return -1; + + /* The surface is now accelerated */ + surface->flags |= SDL_RLEACCEL; + + return(0); +} + +/* + * Un-RLE a surface with pixel alpha + * This may not give back exactly the image before RLE-encoding; all + * completely transparent pixels will be lost, and colour and alpha depth + * may have been reduced (when encoding for 16bpp targets). + */ +static SDL_bool UnRLEAlpha(SDL_Surface *surface) +{ + Uint8 *srcbuf; + Uint32 *dst; + SDL_PixelFormat *sf = surface->format; + RLEDestFormat *df = surface->map->sw_data->aux_data; + int (*uncopy_opaque)(Uint32 *, void *, int, + RLEDestFormat *, SDL_PixelFormat *); + int (*uncopy_transl)(Uint32 *, void *, int, + RLEDestFormat *, SDL_PixelFormat *); + int w = surface->w; + int bpp = df->BytesPerPixel; + + if(bpp == 2) { + uncopy_opaque = uncopy_opaque_16; + uncopy_transl = uncopy_transl_16; + } else { + uncopy_opaque = uncopy_transl = uncopy_32; + } + + surface->pixels = SDL_malloc(surface->h * surface->pitch); + if ( !surface->pixels ) { + return(SDL_FALSE); + } + /* fill background with transparent pixels */ + SDL_memset(surface->pixels, 0, surface->h * surface->pitch); + + dst = surface->pixels; + srcbuf = (Uint8 *)(df + 1); + for(;;) { + /* copy opaque pixels */ + int ofs = 0; + do { + unsigned run; + if(bpp == 2) { + ofs += srcbuf[0]; + run = srcbuf[1]; + srcbuf += 2; + } else { + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + } + if(run) { + srcbuf += uncopy_opaque(dst + ofs, srcbuf, run, df, sf); + ofs += run; + } else if(!ofs) + return(SDL_TRUE); + } while(ofs < w); + + /* skip padding if needed */ + if(bpp == 2) + srcbuf += (uintptr_t)srcbuf & 2; + + /* copy translucent pixels */ + ofs = 0; + do { + unsigned run; + ofs += ((Uint16 *)srcbuf)[0]; + run = ((Uint16 *)srcbuf)[1]; + srcbuf += 4; + if(run) { + srcbuf += uncopy_transl(dst + ofs, srcbuf, run, df, sf); + ofs += run; + } + } while(ofs < w); + dst += surface->pitch >> 2; + } + /* Make the compiler happy */ + return(SDL_TRUE); +} + +void SDL_UnRLESurface(SDL_Surface *surface, int recode) +{ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + surface->flags &= ~SDL_RLEACCEL; + + if(recode && (surface->flags & SDL_PREALLOC) != SDL_PREALLOC + && (surface->flags & SDL_HWSURFACE) != SDL_HWSURFACE) { + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + SDL_Rect full; + unsigned alpha_flag; + + /* re-create the original surface */ + surface->pixels = SDL_malloc(surface->h * surface->pitch); + if ( !surface->pixels ) { + /* Oh crap... */ + surface->flags |= SDL_RLEACCEL; + return; + } + + /* fill it with the background colour */ + SDL_FillRect(surface, NULL, surface->format->colorkey); + + /* now render the encoded surface */ + full.x = full.y = 0; + full.w = surface->w; + full.h = surface->h; + alpha_flag = surface->flags & SDL_SRCALPHA; + surface->flags &= ~SDL_SRCALPHA; /* opaque blit */ + SDL_RLEBlit(surface, &full, surface, &full); + surface->flags |= alpha_flag; + } else { + if ( !UnRLEAlpha(surface) ) { + /* Oh crap... */ + surface->flags |= SDL_RLEACCEL; + return; + } + } + } + + if ( surface->map && surface->map->sw_data->aux_data ) { + SDL_free(surface->map->sw_data->aux_data); + surface->map->sw_data->aux_data = NULL; + } + } +} + + diff --git a/3rdparty/SDL/src/video/SDL_RLEaccel_c.h b/3rdparty/SDL/src/video/SDL_RLEaccel_c.h new file mode 100644 index 0000000..daf0c53 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_RLEaccel_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_RLEaccel.c */ + +extern int SDL_RLESurface(SDL_Surface *surface); +extern int SDL_RLEBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +extern int SDL_RLEAlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +extern void SDL_UnRLESurface(SDL_Surface *surface, int recode); diff --git a/3rdparty/SDL/src/video/SDL_blit.c b/3rdparty/SDL/src/video/SDL_blit.c new file mode 100644 index 0000000..e3f194a --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit.c @@ -0,0 +1,360 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" +#include "SDL_pixels_c.h" + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES +#define MMX_ASMBLIT +#if (__GNUC__ > 2) /* SSE instructions aren't in GCC 2. */ +#define SSE_ASMBLIT +#endif +#endif + +#if defined(MMX_ASMBLIT) +#include "SDL_cpuinfo.h" +#include "mmx.h" +#endif + +/* The general purpose software blit routine */ +static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int okay; + int src_locked; + int dst_locked; + + /* Everything is okay at the beginning... */ + okay = 1; + + /* Lock the destination if it's in hardware */ + dst_locked = 0; + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + okay = 0; + } else { + dst_locked = 1; + } + } + /* Lock the source if it's in hardware */ + src_locked = 0; + if ( SDL_MUSTLOCK(src) ) { + if ( SDL_LockSurface(src) < 0 ) { + okay = 0; + } else { + src_locked = 1; + } + } + + /* Set up source and destination buffer pointers, and BLIT! */ + if ( okay && srcrect->w && srcrect->h ) { + SDL_BlitInfo info; + SDL_loblit RunBlit; + + /* Set up the blit information */ + info.s_pixels = (Uint8 *)src->pixels + + (Uint16)srcrect->y*src->pitch + + (Uint16)srcrect->x*src->format->BytesPerPixel; + info.s_width = srcrect->w; + info.s_height = srcrect->h; + info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; + info.d_pixels = (Uint8 *)dst->pixels + + (Uint16)dstrect->y*dst->pitch + + (Uint16)dstrect->x*dst->format->BytesPerPixel; + info.d_width = dstrect->w; + info.d_height = dstrect->h; + info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; + info.aux_data = src->map->sw_data->aux_data; + info.src = src->format; + info.table = src->map->table; + info.dst = dst->format; + RunBlit = src->map->sw_data->blit; + + /* Run the actual software blit */ + RunBlit(&info); + } + + /* We need to unlock the surfaces if they're locked */ + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + if ( src_locked ) { + SDL_UnlockSurface(src); + } + /* Blit is done! */ + return(okay ? 0 : -1); +} + +#ifdef MMX_ASMBLIT +static __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len) +{ + int i; + + for(i=0; i<len/8; i++) { + __asm__ __volatile__ ( + " movq (%0), %%mm0\n" + " movq %%mm0, (%1)\n" + : : "r" (from), "r" (to) : "memory"); + from+=8; + to+=8; + } + if (len&7) + SDL_memcpy(to, from, len&7); +} + +#ifdef SSE_ASMBLIT +static __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len) +{ + int i; + + __asm__ __volatile__ ( + " prefetchnta (%0)\n" + " prefetchnta 64(%0)\n" + " prefetchnta 128(%0)\n" + " prefetchnta 192(%0)\n" + : : "r" (from) ); + + for(i=0; i<len/8; i++) { + __asm__ __volatile__ ( + " prefetchnta 256(%0)\n" + " movq (%0), %%mm0\n" + " movntq %%mm0, (%1)\n" + : : "r" (from), "r" (to) : "memory"); + from+=8; + to+=8; + } + if (len&7) + SDL_memcpy(to, from, len&7); +} +#endif +#endif + +static void SDL_BlitCopy(SDL_BlitInfo *info) +{ + Uint8 *src, *dst; + int w, h; + int srcskip, dstskip; + + w = info->d_width*info->dst->BytesPerPixel; + h = info->d_height; + src = info->s_pixels; + dst = info->d_pixels; + srcskip = w+info->s_skip; + dstskip = w+info->d_skip; + +#ifdef SSE_ASMBLIT + if(SDL_HasSSE()) + { + while ( h-- ) { + SDL_memcpySSE(dst, src, w); + src += srcskip; + dst += dstskip; + } + __asm__ __volatile__ ( + " emms\n" + ::); + } + else +#endif +#ifdef MMX_ASMBLIT + if(SDL_HasMMX()) + { + while ( h-- ) { + SDL_memcpyMMX(dst, src, w); + src += srcskip; + dst += dstskip; + } + __asm__ __volatile__ ( + " emms\n" + ::); + } + else +#endif + while ( h-- ) { + SDL_memcpy(dst, src, w); + src += srcskip; + dst += dstskip; + } +} + +static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) +{ + Uint8 *src, *dst; + int w, h; + int srcskip, dstskip; + + w = info->d_width*info->dst->BytesPerPixel; + h = info->d_height; + src = info->s_pixels; + dst = info->d_pixels; + srcskip = w+info->s_skip; + dstskip = w+info->d_skip; + if ( dst < src ) { + while ( h-- ) { + SDL_memmove(dst, src, w); + src += srcskip; + dst += dstskip; + } + } else { + src += ((h-1) * srcskip); + dst += ((h-1) * dstskip); + while ( h-- ) { + SDL_revcpy(dst, src, w); + src -= srcskip; + dst -= dstskip; + } + } +} + +/* Figure out which of many blit routines to set up on a surface */ +int SDL_CalculateBlit(SDL_Surface *surface) +{ + int blit_index; + + /* Clean everything out to start */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + surface->map->sw_blit = NULL; + + /* Figure out if an accelerated hardware blit is possible */ + surface->flags &= ~SDL_HWACCEL; + if ( surface->map->identity ) { + int hw_blit_ok; + + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + /* We only support accelerated blitting to hardware */ + if ( surface->map->dst->flags & SDL_HWSURFACE ) { + hw_blit_ok = current_video->info.blit_hw; + } else { + hw_blit_ok = 0; + } + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { + hw_blit_ok = current_video->info.blit_hw_CC; + } + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { + hw_blit_ok = current_video->info.blit_hw_A; + } + } else { + /* We only support accelerated blitting to hardware */ + if ( surface->map->dst->flags & SDL_HWSURFACE ) { + hw_blit_ok = current_video->info.blit_sw; + } else { + hw_blit_ok = 0; + } + if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { + hw_blit_ok = current_video->info.blit_sw_CC; + } + if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { + hw_blit_ok = current_video->info.blit_sw_A; + } + } + if ( hw_blit_ok ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->CheckHWBlit(this, surface, surface->map->dst); + } + } + + /* if an alpha pixel format is specified, we can accelerate alpha blits */ + if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel)) + { + if ( (surface->flags & SDL_SRCALPHA) ) + if ( current_video->info.blit_hw_A ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->CheckHWBlit(this, surface, surface->map->dst); + } + } + + /* Get the blit function index, based on surface mode */ + /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ + blit_index = 0; + blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; + if ( surface->flags & SDL_SRCALPHA + && (surface->format->alpha != SDL_ALPHA_OPAQUE + || surface->format->Amask) ) { + blit_index |= 2; + } + + /* Check for special "identity" case -- copy blit */ + if ( surface->map->identity && blit_index == 0 ) { + surface->map->sw_data->blit = SDL_BlitCopy; + + /* Handle overlapping blits on the same surface */ + if ( surface == surface->map->dst ) { + surface->map->sw_data->blit = SDL_BlitCopyOverlap; + } + } else { + if ( surface->format->BitsPerPixel < 8 ) { + surface->map->sw_data->blit = + SDL_CalculateBlit0(surface, blit_index); + } else { + switch ( surface->format->BytesPerPixel ) { + case 1: + surface->map->sw_data->blit = + SDL_CalculateBlit1(surface, blit_index); + break; + case 2: + case 3: + case 4: + surface->map->sw_data->blit = + SDL_CalculateBlitN(surface, blit_index); + break; + default: + surface->map->sw_data->blit = NULL; + break; + } + } + } + /* Make sure we have a blit function */ + if ( surface->map->sw_data->blit == NULL ) { + SDL_InvalidateMap(surface->map); + SDL_SetError("Blit combination not supported"); + return(-1); + } + + /* Choose software blitting function */ + if(surface->flags & SDL_RLEACCELOK + && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { + + if(surface->map->identity + && (blit_index == 1 + || (blit_index == 3 && !surface->format->Amask))) { + if ( SDL_RLESurface(surface) == 0 ) + surface->map->sw_blit = SDL_RLEBlit; + } else if(blit_index == 2 && surface->format->Amask) { + if ( SDL_RLESurface(surface) == 0 ) + surface->map->sw_blit = SDL_RLEAlphaBlit; + } + } + + if ( surface->map->sw_blit == NULL ) { + surface->map->sw_blit = SDL_SoftBlit; + } + return(0); +} + diff --git a/3rdparty/SDL/src/video/SDL_blit.h b/3rdparty/SDL/src/video/SDL_blit.h new file mode 100644 index 0000000..d64c1e5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit.h @@ -0,0 +1,528 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_blit_h +#define _SDL_blit_h + +#include "SDL_endian.h" + +/* The structure passed to the low level blit functions */ +typedef struct { + Uint8 *s_pixels; + int s_width; + int s_height; + int s_skip; + Uint8 *d_pixels; + int d_width; + int d_height; + int d_skip; + void *aux_data; + SDL_PixelFormat *src; + Uint8 *table; + SDL_PixelFormat *dst; +} SDL_BlitInfo; + +/* The type definition for the low level blit functions */ +typedef void (*SDL_loblit)(SDL_BlitInfo *info); + +/* This is the private info structure for software accelerated blits */ +struct private_swaccel { + SDL_loblit blit; + void *aux_data; +}; + +/* Blit mapping definition */ +typedef struct SDL_BlitMap { + SDL_Surface *dst; + int identity; + Uint8 *table; + SDL_blit hw_blit; + SDL_blit sw_blit; + struct private_hwaccel *hw_data; + struct private_swaccel *sw_data; + + /* the version count matches the destination; mismatch indicates + an invalid mapping */ + unsigned int format_version; +} SDL_BlitMap; + + +/* Functions found in SDL_blit.c */ +extern int SDL_CalculateBlit(SDL_Surface *surface); + +/* Functions found in SDL_blit_{0,1,N,A}.c */ +extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex); +extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex); + +/* + * Useful macros for blitting routines + */ + +#define FORMAT_EQUAL(A, B) \ + ((A)->BitsPerPixel == (B)->BitsPerPixel \ + && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask)) + +/* Load pixel of the specified format from a buffer and get its R-G-B values */ +/* FIXME: rescale values to 0..255 here? */ +#define RGB_FROM_PIXEL(Pixel, fmt, r, g, b) \ +{ \ + r = (((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \ + g = (((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \ + b = (((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \ +} +#define RGB_FROM_RGB565(Pixel, r, g, b) \ +{ \ + r = (((Pixel&0xF800)>>11)<<3); \ + g = (((Pixel&0x07E0)>>5)<<2); \ + b = ((Pixel&0x001F)<<3); \ +} +#define RGB_FROM_RGB555(Pixel, r, g, b) \ +{ \ + r = (((Pixel&0x7C00)>>10)<<3); \ + g = (((Pixel&0x03E0)>>5)<<3); \ + b = ((Pixel&0x001F)<<3); \ +} +#define RGB_FROM_RGB888(Pixel, r, g, b) \ +{ \ + r = ((Pixel&0xFF0000)>>16); \ + g = ((Pixel&0xFF00)>>8); \ + b = (Pixel&0xFF); \ +} +#define RETRIEVE_RGB_PIXEL(buf, bpp, Pixel) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: { \ + Uint8 *B = (Uint8 *)(buf); \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ + } else { \ + Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* appease gcc */ \ + break; \ + } \ +} while(0) + +#define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: { \ + Uint8 *B = (Uint8 *)buf; \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ + } else { \ + Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* prevent gcc from complaining */ \ + break; \ + } \ + RGB_FROM_PIXEL(Pixel, fmt, r, g, b); \ +} while(0) + +/* Assemble R-G-B values into a specified pixel format and store them */ +#ifdef __NDS__ /* FIXME */ +#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift) | (1<<15); \ +} +#else +#define PIXEL_FROM_RGB(Pixel, fmt, r, g, b) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift); \ +} +#endif /* __NDS__ FIXME */ +#define RGB565_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \ +} +#define RGB555_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \ +} +#define RGB888_FROM_RGB(Pixel, r, g, b) \ +{ \ + Pixel = (r<<16)|(g<<8)|b; \ +} +#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 Pixel; \ + \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *((Uint16 *)(buf)) = Pixel; \ + } \ + break; \ + \ + case 3: { \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 Pixel; \ + \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *((Uint32 *)(buf)) = Pixel; \ + } \ + break; \ + } \ +} +#define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 *bufp; \ + Uint16 Pixel; \ + \ + bufp = (Uint16 *)buf; \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *bufp = Pixel | (*bufp & Amask); \ + } \ + break; \ + \ + case 3: { \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 *bufp; \ + Uint32 Pixel; \ + \ + bufp = (Uint32 *)buf; \ + PIXEL_FROM_RGB(Pixel, fmt, r, g, b); \ + *bufp = Pixel | (*bufp & Amask); \ + } \ + break; \ + } \ +} + +/* FIXME: Should we rescale alpha into 0..255 here? */ +#define RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a) \ +{ \ + r = ((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \ + g = ((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \ + b = ((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \ + a = ((Pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ +} +#define RGBA_FROM_8888(Pixel, fmt, r, g, b, a) \ +{ \ + r = (Pixel&fmt->Rmask)>>fmt->Rshift; \ + g = (Pixel&fmt->Gmask)>>fmt->Gshift; \ + b = (Pixel&fmt->Bmask)>>fmt->Bshift; \ + a = (Pixel&fmt->Amask)>>fmt->Ashift; \ +} +#define RGBA_FROM_RGBA8888(Pixel, r, g, b, a) \ +{ \ + r = (Pixel>>24); \ + g = ((Pixel>>16)&0xFF); \ + b = ((Pixel>>8)&0xFF); \ + a = (Pixel&0xFF); \ +} +#define RGBA_FROM_ARGB8888(Pixel, r, g, b, a) \ +{ \ + r = ((Pixel>>16)&0xFF); \ + g = ((Pixel>>8)&0xFF); \ + b = (Pixel&0xFF); \ + a = (Pixel>>24); \ +} +#define RGBA_FROM_ABGR8888(Pixel, r, g, b, a) \ +{ \ + r = (Pixel&0xFF); \ + g = ((Pixel>>8)&0xFF); \ + b = ((Pixel>>16)&0xFF); \ + a = (Pixel>>24); \ +} +#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \ +do { \ + switch (bpp) { \ + case 2: \ + Pixel = *((Uint16 *)(buf)); \ + break; \ + \ + case 3: {/* FIXME: broken code (no alpha) */ \ + Uint8 *b = (Uint8 *)buf; \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + Pixel = b[0] + (b[1] << 8) + (b[2] << 16); \ + } else { \ + Pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \ + } \ + } \ + break; \ + \ + case 4: \ + Pixel = *((Uint32 *)(buf)); \ + break; \ + \ + default: \ + Pixel = 0; /* stop gcc complaints */ \ + break; \ + } \ + RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a); \ + Pixel &= ~fmt->Amask; \ +} while(0) + +/* FIXME: this isn't correct, especially for Alpha (maximum != 255) */ +#ifdef __NDS__ /* FIXME */ +#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift)| \ + ((a>>fmt->Aloss)<<fmt->Ashift) | (1<<15); \ +} +#else +#define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a) \ +{ \ + Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ + ((g>>fmt->Gloss)<<fmt->Gshift)| \ + ((b>>fmt->Bloss)<<fmt->Bshift)| \ + ((a>>fmt->Aloss)<<fmt->Ashift); \ +} +#endif /* __NDS__ FIXME */ +#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ +{ \ + switch (bpp) { \ + case 2: { \ + Uint16 Pixel; \ + \ + PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \ + *((Uint16 *)(buf)) = Pixel; \ + } \ + break; \ + \ + case 3: { /* FIXME: broken code (no alpha) */ \ + if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ + *((buf)+fmt->Rshift/8) = r; \ + *((buf)+fmt->Gshift/8) = g; \ + *((buf)+fmt->Bshift/8) = b; \ + } else { \ + *((buf)+2-fmt->Rshift/8) = r; \ + *((buf)+2-fmt->Gshift/8) = g; \ + *((buf)+2-fmt->Bshift/8) = b; \ + } \ + } \ + break; \ + \ + case 4: { \ + Uint32 Pixel; \ + \ + PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a); \ + *((Uint32 *)(buf)) = Pixel; \ + } \ + break; \ + } \ +} + +/* Blend the RGB values of two Pixels based on a source alpha value */ +#define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ +do { \ + dR = (((sR-dR)*(A)+255)>>8)+dR; \ + dG = (((sG-dG)*(A)+255)>>8)+dG; \ + dB = (((sB-dB)*(A)+255)>>8)+dB; \ +} while(0) + + +/* This is a very useful loop for optimizing blitters */ +#if defined(_MSC_VER) && (_MSC_VER == 1300) +/* There's a bug in the Visual C++ 7 optimizer when compiling this code */ +#else +#define USE_DUFFS_LOOP +#endif +#ifdef USE_DUFFS_LOOP + +/* 8-times unrolled loop */ +#define DUFFS_LOOP8(pixel_copy_increment, width) \ +{ int n = (width+7)/8; \ + switch (width & 7) { \ + case 0: do { pixel_copy_increment; \ + case 7: pixel_copy_increment; \ + case 6: pixel_copy_increment; \ + case 5: pixel_copy_increment; \ + case 4: pixel_copy_increment; \ + case 3: pixel_copy_increment; \ + case 2: pixel_copy_increment; \ + case 1: pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ +} + +/* 4-times unrolled loop */ +#define DUFFS_LOOP4(pixel_copy_increment, width) \ +{ int n = (width+3)/4; \ + switch (width & 3) { \ + case 0: do { pixel_copy_increment; \ + case 3: pixel_copy_increment; \ + case 2: pixel_copy_increment; \ + case 1: pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ +} + +/* 2 - times unrolled loop */ +#define DUFFS_LOOP_DOUBLE2(pixel_copy_increment, \ + double_pixel_copy_increment, width) \ +{ int n, w = width; \ + if( w & 1 ) { \ + pixel_copy_increment; \ + w--; \ + } \ + if ( w > 0 ) { \ + n = ( w + 2) / 4; \ + switch( w & 2 ) { \ + case 0: do { double_pixel_copy_increment; \ + case 2: double_pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ + } \ +} + +/* 2 - times unrolled loop 4 pixels */ +#define DUFFS_LOOP_QUATRO2(pixel_copy_increment, \ + double_pixel_copy_increment, \ + quatro_pixel_copy_increment, width) \ +{ int n, w = width; \ + if(w & 1) { \ + pixel_copy_increment; \ + w--; \ + } \ + if(w & 2) { \ + double_pixel_copy_increment; \ + w -= 2; \ + } \ + if ( w > 0 ) { \ + n = ( w + 7 ) / 8; \ + switch( w & 4 ) { \ + case 0: do { quatro_pixel_copy_increment; \ + case 4: quatro_pixel_copy_increment; \ + } while ( --n > 0 ); \ + } \ + } \ +} + +/* Use the 8-times version of the loop by default */ +#define DUFFS_LOOP(pixel_copy_increment, width) \ + DUFFS_LOOP8(pixel_copy_increment, width) + +#else + +/* Don't use Duff's device to unroll loops */ +#define DUFFS_LOOP_DOUBLE2(pixel_copy_increment, \ + double_pixel_copy_increment, width) \ +{ int n = width; \ + if( n & 1 ) { \ + pixel_copy_increment; \ + n--; \ + } \ + n=n>>1; \ + for(; n > 0; --n) { \ + double_pixel_copy_increment; \ + } \ +} + +/* Don't use Duff's device to unroll loops */ +#define DUFFS_LOOP_QUATRO2(pixel_copy_increment, \ + double_pixel_copy_increment, \ + quatro_pixel_copy_increment, width) \ +{ int n = width; \ + if(n & 1) { \ + pixel_copy_increment; \ + n--; \ + } \ + if(n & 2) { \ + double_pixel_copy_increment; \ + n -= 2; \ + } \ + n=n>>2; \ + for(; n > 0; --n) { \ + quatro_pixel_copy_increment; \ + } \ +} + +/* 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; \ + } \ +} +#define DUFFS_LOOP8(pixel_copy_increment, width) \ + DUFFS_LOOP(pixel_copy_increment, width) +#define DUFFS_LOOP4(pixel_copy_increment, width) \ + DUFFS_LOOP(pixel_copy_increment, width) + +#endif /* USE_DUFFS_LOOP */ + +/* Prevent Visual C++ 6.0 from printing out stupid warnings */ +#if defined(_MSC_VER) && (_MSC_VER >= 600) +#pragma warning(disable: 4550) +#endif + +#endif /* _SDL_blit_h */ diff --git a/3rdparty/SDL/src/video/SDL_blit_0.c b/3rdparty/SDL/src/video/SDL_blit_0.c new file mode 100644 index 0000000..c1bc0eb --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_0.c @@ -0,0 +1,471 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* Functions to blit from bitmaps to other surfaces */ + +static void BlitBto1(SDL_BlitInfo *info) +{ + int c; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcskip += width-(width+7)/8; + + if ( map ) { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = bit; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } +} +static void BlitBto2(SDL_BlitInfo *info) +{ + int c; + int width, height; + Uint8 *src; + Uint16 *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + map = (Uint16 *)info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + byte <<= 1; + dst++; + } + src += srcskip; + dst += dstskip; + } +} +static void BlitBto3(SDL_BlitInfo *info) +{ + int c, o; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + o = bit * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + } + byte <<= 1; + dst += 3; + } + src += srcskip; + dst += dstskip; + } +} +static void BlitBto4(SDL_BlitInfo *info) +{ + int width, height; + Uint8 *src; + Uint32 *map, *dst; + int srcskip, dstskip; + int c; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + map = (Uint32 *)info->table; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + *dst = map[bit]; + } + byte <<= 1; + dst++; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBto1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + + if ( palmap ) { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dst = palmap[bit]; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dst = bit; + } + dst++; + byte <<= 1; + } + src += srcskip; + dst += dstskip; + } + } +} + +static void BlitBto2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + dstskip /= 2; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dstp=((Uint16 *)palmap)[bit]; + } + byte <<= 1; + dstp++; + } + src += srcskip; + dstp += dstskip; + } +} + +static void BlitBto3Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + SDL_memcpy(dst, &palmap[bit*4], 3); + } + byte <<= 1; + dst += 3; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBto4Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint8 *palmap = info->table; + int c; + + /* Set up some basic variables */ + srcskip += width-(width+7)/8; + dstskip /= 4; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + *dstp=((Uint32 *)palmap)[bit]; + } + byte <<= 1; + dstp++; + } + src += srcskip; + dstp += dstskip; + } +} + +static void BlitBtoNAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + const SDL_Color *srcpal = info->src->palette->colors; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp; + int c; + const int A = info->src->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( 1 ) { + Uint32 pixel; + unsigned sR, sG, sB; + unsigned dR, dG, dB; + sR = srcpal[bit].r; + sG = srcpal[bit].g; + sB = srcpal[bit].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + byte <<= 1; + dst += dstbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitBtoNAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + Uint8 *dst = info->d_pixels; + int srcskip = info->s_skip; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = srcfmt->palette->colors; + int dstbpp; + int c; + const int A = srcfmt->alpha; + Uint32 ckey = srcfmt->colorkey; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + srcskip += width-(width+7)/8; + + while ( height-- ) { + Uint8 byte = 0, bit; + for ( c=0; c<width; ++c ) { + if ( (c&7) == 0 ) { + byte = *src++; + } + bit = (byte&0x80)>>7; + if ( bit != ckey ) { + int sR, sG, sB; + int dR, dG, dB; + Uint32 pixel; + sR = srcpal[bit].r; + sG = srcpal[bit].g; + sB = srcpal[bit].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + byte <<= 1; + dst += dstbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static SDL_loblit bitmap_blit[] = { + NULL, BlitBto1, BlitBto2, BlitBto3, BlitBto4 +}; + +static SDL_loblit colorkey_blit[] = { + NULL, BlitBto1Key, BlitBto2Key, BlitBto3Key, BlitBto4Key +}; + +SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int blit_index) +{ + int which; + + if ( surface->format->BitsPerPixel != 1 ) { + /* We don't support sub 8-bit packed pixel modes */ + return NULL; + } + if ( surface->map->dst->format->BitsPerPixel < 8 ) { + which = 0; + } else { + which = surface->map->dst->format->BytesPerPixel; + } + switch(blit_index) { + case 0: /* copy */ + return bitmap_blit[which]; + + case 1: /* colorkey */ + return colorkey_blit[which]; + + case 2: /* alpha */ + return which >= 2 ? BlitBtoNAlpha : NULL; + + case 4: /* alpha + colorkey */ + return which >= 2 ? BlitBtoNAlphaKey : NULL; + } + return NULL; +} + diff --git a/3rdparty/SDL/src/video/SDL_blit_1.c b/3rdparty/SDL/src/video/SDL_blit_1.c new file mode 100644 index 0000000..7f95f5b --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_1.c @@ -0,0 +1,523 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" +#include "SDL_sysvideo.h" +#include "SDL_endian.h" + +/* Functions to blit from 8-bit surfaces to other surfaces */ + +static void Blit1to1(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + *dst = map[*src]; + } + dst++; + src++; + , width); +#else + for ( c=width; c; --c ) { + *dst = map[*src]; + dst++; + src++; + } +#endif + src += srcskip; + dst += dstskip; + } +} +/* This is now endian dependent */ +#if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) +#define HI 1 +#define LO 0 +#else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ +#define HI 0 +#define LO 1 +#endif +static void Blit1to2(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src, *dst; + Uint16 *map; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = (Uint16 *)info->table; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + { + *(Uint16 *)dst = map[*src++]; + dst += 2; + }, + width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + *(Uint16 *)dst = map[*src++]; + dst += 2; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *(Uint16 *)dst = map[*src++]; + dst += 2; + case 2: + *(Uint32 *)dst = + (map[src[HI]]<<16)|(map[src[LO]]); + src += 2; + dst += 4; + break; + case 1: + *(Uint16 *)dst = map[*src++]; + dst += 2; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} +static void Blit1to3(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int o; + int width, height; + Uint8 *src, *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + } + src++; + dst += 3; + , width); +#else + for ( c=width; c; --c ) { + o = *src * 4; + dst[0] = map[o++]; + dst[1] = map[o++]; + dst[2] = map[o++]; + src++; + dst += 3; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} +static void Blit1to4(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + Uint32 *map, *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + map = (Uint32 *)info->table; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + *dst++ = map[*src++]; + , width); +#else + for ( c=width/4; c; --c ) { + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + *dst++ = map[*src++]; + } + switch ( width & 3 ) { + case 3: + *dst++ = map[*src++]; + case 2: + *dst++ = map[*src++]; + case 1: + *dst++ = map[*src++]; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + + if ( palmap ) { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = palmap[*src]; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dst = *src; + } + dst++; + src++; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +static void Blit1to2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip; + Uint16 *palmap = (Uint16 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 2; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp=palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1to3Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + Uint32 ckey = info->src->colorkey; + int o; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + o = *src * 4; + dst[0] = palmap[o++]; + dst[1] = palmap[o++]; + dst[2] = palmap[o++]; + } + src++; + dst += 3; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1to4Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip; + Uint32 *palmap = (Uint32 *)info->table; + Uint32 ckey = info->src->colorkey; + + /* Set up some basic variables */ + dstskip /= 4; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( *src != ckey ) { + *dstp = palmap[*src]; + } + src++; + dstp++; + }, + width); + src += srcskip; + dstp += dstskip; + } +} + +static void Blit1toNAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + int dstbpp; + const int A = info->src->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP4( + { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void Blit1toNAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + const SDL_Color *srcpal = info->src->palette->colors; + Uint32 ckey = srcfmt->colorkey; + int dstbpp; + const int A = srcfmt->alpha; + + /* Set up some basic variables */ + dstbpp = dstfmt->BytesPerPixel; + + while ( height-- ) { + int sR, sG, sB; + int dR, dG, dB; + DUFFS_LOOP( + { + if ( *src != ckey ) { + Uint32 pixel; + sR = srcpal[*src].r; + sG = srcpal[*src].g; + sB = srcpal[*src].b; + DISEMBLE_RGB(dst, dstbpp, dstfmt, + pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB); + } + src++; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static SDL_loblit one_blit[] = { + NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 +}; + +static SDL_loblit one_blitkey[] = { + NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key +}; + +SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index) +{ + int which; + SDL_PixelFormat *dstfmt; + + dstfmt = surface->map->dst->format; + if ( dstfmt->BitsPerPixel < 8 ) { + which = 0; + } else { + which = dstfmt->BytesPerPixel; + } + switch(blit_index) { + case 0: /* copy */ + return one_blit[which]; + + case 1: /* colorkey */ + return one_blitkey[which]; + + case 2: /* alpha */ + /* Supporting 8bpp->8bpp alpha is doable but requires lots of + tables which consume space and takes time to precompute, + so is better left to the user */ + return which >= 2 ? Blit1toNAlpha : NULL; + + case 3: /* alpha + colorkey */ + return which >= 2 ? Blit1toNAlphaKey : NULL; + + } + return NULL; +} diff --git a/3rdparty/SDL/src/video/SDL_blit_A.c b/3rdparty/SDL/src/video/SDL_blit_A.c new file mode 100644 index 0000000..219cdcc --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_A.c @@ -0,0 +1,2873 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* + In Visual C, VC6 has mmintrin.h in the "Processor Pack" add-on. + Checking if _mm_free is #defined in malloc.h is is the only way to + determine if the Processor Pack is installed, as far as I can tell. +*/ + +#if SDL_ASSEMBLY_ROUTINES +# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + /* forced MMX to 0...it breaks on most compilers now. --ryan. */ +# define MMX_ASMBLIT 0 +# define GCC_ASMBLIT 0 +# elif defined(_MSC_VER) && defined(_M_IX86) +# if (_MSC_VER <= 1200) +# include <malloc.h> +# if defined(_mm_free) +# define HAVE_MMINTRIN_H 1 +# endif +# else /* Visual Studio > VC6 always has mmintrin.h */ +# define HAVE_MMINTRIN_H 1 +# endif +# if HAVE_MMINTRIN_H +# define MMX_ASMBLIT 1 +# define MSVC_ASMBLIT 1 +# endif +# endif +#endif /* SDL_ASSEMBLY_ROUTINES */ + +/* Function to check the CPU flags */ +#include "SDL_cpuinfo.h" +#if GCC_ASMBLIT +#include "mmx.h" +#elif MSVC_ASMBLIT +#include <mmintrin.h> +#include <mm3dnow.h> +#endif + +/* Functions to perform alpha blended blitting */ + +/* N->1 blending with per-surface alpha */ +static void BlitNto1SurfaceAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + + const unsigned A = srcfmt->alpha; + + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2))| + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0))]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* N->1 blending with pixel alpha */ +static void BlitNto1PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + + /* FIXME: fix alpha bit field expansion here too? */ + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned sA; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGBA(src,srcbpp,srcfmt,Pixel,sR,sG,sB,sA); + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2))| + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* colorkeyed N->1 blending with per-surface alpha */ +static void BlitNto1SurfaceAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint8 *palmap = info->table; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + Uint32 ckey = srcfmt->colorkey; + + const int A = srcfmt->alpha; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + if ( Pixel != ckey ) { + dR = dstfmt->palette->colors[*dst].r; + dG = dstfmt->palette->colors[*dst].g; + dB = dstfmt->palette->colors[*dst].b; + ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB); + dR &= 0xff; + dG &= 0xff; + dB &= 0xff; + /* Pack RGB into 8bit pixel */ + if ( palmap == NULL ) { + *dst =((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)); + } else { + *dst = palmap[((dR>>5)<<(3+2))| + ((dG>>5)<<(2)) | + ((dB>>6)<<(0)) ]; + } + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +#if GCC_ASMBLIT +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128MMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = info->dst->Amask; + Uint64 load; + + load = 0x00fefefe00fefefeULL;/* alpha128 mask */ + movq_m2r(load, mm4); /* alpha128 mask -> mm4 */ + load = 0x0001010100010101ULL;/* !alpha128 mask */ + movq_m2r(load, mm3); /* !alpha128 mask -> mm3 */ + movd_m2r(dalpha, mm7); /* dst alpha mask */ + punpckldq_r2r(mm7, mm7); /* dst alpha mask | dst alpha mask -> mm7 */ + while(height--) { + DUFFS_LOOP_DOUBLE2( + { + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | dalpha; + },{ + movq_m2r((*dstp), mm2);/* 2 x dst -> mm2(ARGBARGB) */ + movq_r2r(mm2, mm6); /* 2 x dst -> mm6(ARGBARGB) */ + + movq_m2r((*srcp), mm1);/* 2 x src -> mm1(ARGBARGB) */ + movq_r2r(mm1, mm5); /* 2 x src -> mm5(ARGBARGB) */ + + pand_r2r(mm4, mm6); /* dst & mask -> mm6 */ + pand_r2r(mm4, mm5); /* src & mask -> mm5 */ + paddd_r2r(mm6, mm5); /* mm6 + mm5 -> mm5 */ + pand_r2r(mm1, mm2); /* src & dst -> mm2 */ + psrld_i2r(1, mm5); /* mm5 >> 1 -> mm5 */ + pand_r2r(mm3, mm2); /* mm2 & !mask -> mm2 */ + paddd_r2r(mm5, mm2); /* mm5 + mm2 -> mm2 */ + + por_r2r(mm7, mm2); /* mm7(full alpha) | mm2 -> mm2 */ + movq_r2m(mm2, (*dstp));/* mm2 -> 2 x dst pixels */ + dstp += 2; + srcp += 2; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlphaMMX(SDL_BlitInfo *info) +{ + SDL_PixelFormat* df = info->dst; + unsigned alpha = info->src->alpha; + + if (alpha == 128 && (df->Rmask | df->Gmask | df->Bmask) == 0x00FFFFFF) { + /* only call a128 version when R,G,B occupy lower bits */ + BlitRGBtoRGBSurfaceAlpha128MMX(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + pxor_r2r(mm5, mm5); /* 0 -> mm5 */ + /* form the alpha mult */ + movd_m2r(alpha, mm4); /* 0000000A -> mm4 */ + punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */ + punpckldq_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */ + alpha = (0xff << df->Rshift) | (0xff << df->Gshift) | (0xff << df->Bshift); + movd_m2r(alpha, mm0); /* 00000FFF -> mm0 */ + punpcklbw_r2r(mm0, mm0); /* 00FFFFFF -> mm0 */ + pand_r2r(mm0, mm4); /* 0A0A0A0A -> mm4, minus 1 chan */ + /* at this point mm4 can be 000A0A0A or 0A0A0A00 or another combo */ + movd_m2r(df->Amask, mm7); /* dst alpha mask */ + punpckldq_r2r(mm7, mm7); /* dst alpha mask | dst alpha mask -> mm7 */ + + while(height--) { + DUFFS_LOOP_DOUBLE2({ + /* One Pixel Blend */ + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + punpcklbw_r2r(mm5, mm1); /* 0A0R0G0B -> mm1(src) */ + punpcklbw_r2r(mm5, mm2); /* 0A0R0G0B -> mm2(dst) */ + + psubw_r2r(mm2, mm1);/* src - dst -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */ + paddb_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */ + + packuswb_r2r(mm5, mm2); /* ARGBARGB -> mm2 */ + por_r2r(mm7, mm2); /* mm7(full alpha) | mm2 -> mm2 */ + movd_r2m(mm2, *dstp);/* mm2 -> pixel */ + ++srcp; + ++dstp; + },{ + /* Two Pixels Blend */ + movq_m2r((*srcp), mm0);/* 2 x src -> mm0(ARGBARGB)*/ + movq_m2r((*dstp), mm2);/* 2 x dst -> mm2(ARGBARGB) */ + movq_r2r(mm0, mm1); /* 2 x src -> mm1(ARGBARGB) */ + movq_r2r(mm2, mm6); /* 2 x dst -> mm6(ARGBARGB) */ + + punpcklbw_r2r(mm5, mm0); /* low - 0A0R0G0B -> mm0(src1) */ + punpckhbw_r2r(mm5, mm1); /* high - 0A0R0G0B -> mm1(src2) */ + punpcklbw_r2r(mm5, mm2); /* low - 0A0R0G0B -> mm2(dst1) */ + punpckhbw_r2r(mm5, mm6); /* high - 0A0R0G0B -> mm6(dst2) */ + + psubw_r2r(mm2, mm0);/* src1 - dst1 -> mm0 */ + pmullw_r2r(mm4, mm0); /* mm0 * alpha -> mm0 */ + psrlw_i2r(8, mm0); /* mm0 >> 8 -> mm1 */ + paddb_r2r(mm0, mm2); /* mm0 + mm2(dst1) -> mm2 */ + + psubw_r2r(mm6, mm1);/* src2 - dst2 -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */ + paddb_r2r(mm1, mm6); /* mm1 + mm6(dst2) -> mm6 */ + + packuswb_r2r(mm6, mm2); /* ARGBARGB -> mm2 */ + por_r2r(mm7, mm2); /* mm7(dst alpha) | mm2 -> mm2 */ + + movq_r2m(mm2, *dstp);/* mm2 -> 2 x pixel */ + + srcp += 2; + dstp += 2; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 amask = sf->Amask; + + pxor_r2r(mm6, mm6); /* 0 -> mm6 */ + /* form multiplication mask */ + movd_m2r(sf->Amask, mm7); /* 0000F000 -> mm7 */ + punpcklbw_r2r(mm7, mm7); /* FF000000 -> mm7 */ + pcmpeqb_r2r(mm0, mm0); /* FFFFFFFF -> mm0 */ + movq_r2r(mm0, mm3); /* FFFFFFFF -> mm3 (for later) */ + pxor_r2r(mm0, mm7); /* 00FFFFFF -> mm7 (mult mask) */ + /* form channel masks */ + movq_r2r(mm7, mm0); /* 00FFFFFF -> mm0 */ + packsswb_r2r(mm6, mm0); /* 00000FFF -> mm0 (channel mask) */ + packsswb_r2r(mm6, mm3); /* 0000FFFF -> mm3 */ + pxor_r2r(mm0, mm3); /* 0000F000 -> mm3 (~channel mask) */ + /* get alpha channel shift */ + __asm__ __volatile__ ( + "movd %0, %%mm5" + : : "rm" ((Uint32) sf->Ashift) ); /* Ashift -> mm5 */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha = *srcp & amask; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha == 0) { + /* do nothing */ + } else if(alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + /* using MMX here to free up regular registers for other things */ + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + pand_r2r(mm0, mm1); /* src & chanmask -> mm1 */ + pand_r2r(mm3, mm2); /* dst & ~chanmask -> mm2 */ + por_r2r(mm1, mm2); /* src | dst -> mm2 */ + movd_r2m(mm2, (*dstp)); /* mm2 -> dst */ + } else { + movd_m2r((*srcp), mm1);/* src(ARGB) -> mm1 (0000ARGB)*/ + punpcklbw_r2r(mm6, mm1); /* 0A0R0G0B -> mm1 */ + + movd_m2r((*dstp), mm2);/* dst(ARGB) -> mm2 (0000ARGB)*/ + punpcklbw_r2r(mm6, mm2); /* 0A0R0G0B -> mm2 */ + + __asm__ __volatile__ ( + "movd %0, %%mm4" + : : "r" (alpha) ); /* 0000A000 -> mm4 */ + psrld_r2r(mm5, mm4); /* mm4 >> mm5 -> mm4 (0000000A) */ + punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */ + punpcklwd_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */ + pand_r2r(mm7, mm4); /* 000A0A0A -> mm4, preserve dst alpha on add */ + + /* blend */ + psubw_r2r(mm2, mm1);/* src - dst -> mm1 */ + pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */ + psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1(000R0G0B) */ + paddb_r2r(mm1, mm2); /* mm1 + mm2(dst) -> mm2 */ + + packuswb_r2r(mm6, mm2); /* 0000ARGB -> mm2 */ + movd_r2m(mm2, *dstp);/* mm2 -> dst */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); +} +/* End GCC_ASMBLIT */ + +#elif MSVC_ASMBLIT +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128MMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = info->dst->Amask; + + __m64 src1, src2, dst1, dst2, lmask, hmask, dsta; + + hmask = _mm_set_pi32(0x00fefefe, 0x00fefefe); /* alpha128 mask -> hmask */ + lmask = _mm_set_pi32(0x00010101, 0x00010101); /* !alpha128 mask -> lmask */ + dsta = _mm_set_pi32(dalpha, dalpha); /* dst alpha mask -> dsta */ + + while (height--) { + int n = width; + if ( n & 1 ) { + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | dalpha; + n--; + } + + for (n >>= 1; n > 0; --n) { + dst1 = *(__m64*)dstp; /* 2 x dst -> dst1(ARGBARGB) */ + dst2 = dst1; /* 2 x dst -> dst2(ARGBARGB) */ + + src1 = *(__m64*)srcp; /* 2 x src -> src1(ARGBARGB) */ + src2 = src1; /* 2 x src -> src2(ARGBARGB) */ + + dst2 = _mm_and_si64(dst2, hmask); /* dst & mask -> dst2 */ + src2 = _mm_and_si64(src2, hmask); /* src & mask -> src2 */ + src2 = _mm_add_pi32(src2, dst2); /* dst2 + src2 -> src2 */ + src2 = _mm_srli_pi32(src2, 1); /* src2 >> 1 -> src2 */ + + dst1 = _mm_and_si64(dst1, src1); /* src & dst -> dst1 */ + dst1 = _mm_and_si64(dst1, lmask); /* dst1 & !mask -> dst1 */ + dst1 = _mm_add_pi32(dst1, src2); /* src2 + dst1 -> dst1 */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta(full alpha) | dst1 -> dst1 */ + + *(__m64*)dstp = dst1; /* dst1 -> 2 x dst pixels */ + dstp += 2; + srcp += 2; + } + + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlphaMMX(SDL_BlitInfo *info) +{ + SDL_PixelFormat* df = info->dst; + Uint32 chanmask = df->Rmask | df->Gmask | df->Bmask; + unsigned alpha = info->src->alpha; + + if (alpha == 128 && (df->Rmask | df->Gmask | df->Bmask) == 0x00FFFFFF) { + /* only call a128 version when R,G,B occupy lower bits */ + BlitRGBtoRGBSurfaceAlpha128MMX(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 dalpha = df->Amask; + Uint32 amult; + + __m64 src1, src2, dst1, dst2, mm_alpha, mm_zero, dsta; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + /* form the alpha mult */ + amult = alpha | (alpha << 8); + amult = amult | (amult << 16); + chanmask = (0xff << df->Rshift) | (0xff << df->Gshift) | (0xff << df->Bshift); + mm_alpha = _mm_set_pi32(0, amult & chanmask); /* 0000AAAA -> mm_alpha, minus 1 chan */ + mm_alpha = _mm_unpacklo_pi8(mm_alpha, mm_zero); /* 0A0A0A0A -> mm_alpha, minus 1 chan */ + /* at this point mm_alpha can be 000A0A0A or 0A0A0A00 or another combo */ + dsta = _mm_set_pi32(dalpha, dalpha); /* dst alpha mask -> dsta */ + + while (height--) { + int n = width; + if (n & 1) { + /* One Pixel Blend */ + src2 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src2 (0000ARGB)*/ + src2 = _mm_unpacklo_pi8(src2, mm_zero); /* 0A0R0G0B -> src2 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + src2 = _mm_sub_pi16(src2, dst1); /* src2 - dst2 -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 8); /* src2 >> 8 -> src2 */ + dst1 = _mm_add_pi8(src2, dst1); /* src2 + dst1 -> dst1 */ + + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta | dst1 -> dst1 */ + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + + ++srcp; + ++dstp; + + n--; + } + + for (n >>= 1; n > 0; --n) { + /* Two Pixels Blend */ + src1 = *(__m64*)srcp; /* 2 x src -> src1(ARGBARGB)*/ + src2 = src1; /* 2 x src -> src2(ARGBARGB) */ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* low - 0A0R0G0B -> src1 */ + src2 = _mm_unpackhi_pi8(src2, mm_zero); /* high - 0A0R0G0B -> src2 */ + + dst1 = *(__m64*)dstp;/* 2 x dst -> dst1(ARGBARGB) */ + dst2 = dst1; /* 2 x dst -> dst2(ARGBARGB) */ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* low - 0A0R0G0B -> dst1 */ + dst2 = _mm_unpackhi_pi8(dst2, mm_zero); /* high - 0A0R0G0B -> dst2 */ + + src1 = _mm_sub_pi16(src1, dst1);/* src1 - dst1 -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* src1 * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1 */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1(dst1) -> dst1 */ + + src2 = _mm_sub_pi16(src2, dst2);/* src2 - dst2 -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 8); /* src2 >> 8 -> src2 */ + dst2 = _mm_add_pi8(src2, dst2); /* src2 + dst2(dst2) -> dst2 */ + + dst1 = _mm_packs_pu16(dst1, dst2); /* 0A0R0G0B(res1), 0A0R0G0B(res2) -> dst1(ARGBARGB) */ + dst1 = _mm_or_si64(dst1, dsta); /* dsta | dst1 -> dst1 */ + + *(__m64*)dstp = dst1; /* dst1 -> 2 x pixel */ + + srcp += 2; + dstp += 2; + } + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 chanmask = sf->Rmask | sf->Gmask | sf->Bmask; + Uint32 amask = sf->Amask; + Uint32 ashift = sf->Ashift; + Uint64 multmask; + + __m64 src1, dst1, mm_alpha, mm_zero, dmask; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + multmask = ~(0xFFFFi64 << (ashift * 2)); + dmask = *(__m64*) &multmask; /* dst alpha mask -> dmask */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha = *srcp & amask; + if (alpha == 0) { + /* do nothing */ + } else if (alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + *dstp = (*srcp & chanmask) | (*dstp & ~chanmask); + } else { + src1 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src1 (0000ARGB)*/ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* 0A0R0G0B -> src1 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + mm_alpha = _mm_cvtsi32_si64(alpha); /* alpha -> mm_alpha (0000000A) */ + mm_alpha = _mm_srli_si64(mm_alpha, ashift); /* mm_alpha >> ashift -> mm_alpha(0000000A) */ + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + mm_alpha = _mm_and_si64(mm_alpha, dmask); /* 000A0A0A -> mm_alpha, preserve dst alpha on add */ + + /* blend */ + src1 = _mm_sub_pi16(src1, dst1);/* src1 - dst1 -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* (src1 - dst1) * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1(000R0G0B) */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1 -> dst1(0A0R0G0B) */ + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} +/* End MSVC_ASMBLIT */ + +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +#if SDL_ALTIVEC_BLITTERS +#if __MWERKS__ +#pragma altivec_model on +#endif +#if HAVE_ALTIVEC_H +#include <altivec.h> +#endif +#include <assert.h> + +#if (defined(__MACOSX__) && (__GNUC__ < 4)) + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) ( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p ) + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) ( a,b,c,d,e,f,g,h ) +#else + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p } + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) { a,b,c,d,e,f,g,h } +#endif + +#define UNALIGNED_PTR(x) (((size_t) x) & 0x0000000F) +#define VECPRINT(msg, v) do { \ + vector unsigned int tmpvec = (vector unsigned int)(v); \ + unsigned int *vp = (unsigned int *)&tmpvec; \ + printf("%s = %08X %08X %08X %08X\n", msg, vp[0], vp[1], vp[2], vp[3]); \ +} while (0) + +/* the permuation vector that takes the high bytes out of all the appropriate shorts + (vector unsigned char)( + 0x00, 0x10, 0x02, 0x12, + 0x04, 0x14, 0x06, 0x16, + 0x08, 0x18, 0x0A, 0x1A, + 0x0C, 0x1C, 0x0E, 0x1E ); +*/ +#define VEC_MERGE_PERMUTE() (vec_add(vec_lvsl(0, (int*)NULL), (vector unsigned char)vec_splat_u16(0x0F))) +#define VEC_U32_24() (vec_add(vec_splat_u32(12), vec_splat_u32(12))) +#define VEC_ALPHA_MASK() ((vector unsigned char)vec_sl((vector unsigned int)vec_splat_s8(-1), VEC_U32_24())) +#define VEC_ALIGNER(src) ((UNALIGNED_PTR(src)) \ + ? vec_lvsl(0, src) \ + : vec_add(vec_lvsl(8, src), vec_splat_u8(8))) + + +#define VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1_16, v8_16) do { \ + /* vtemp1 contains source AAGGAAGGAAGGAAGG */ \ + vector unsigned short vtemp1 = vec_mule(vs, valpha); \ + /* vtemp2 contains source RRBBRRBBRRBBRRBB */ \ + vector unsigned short vtemp2 = vec_mulo(vs, valpha); \ + /* valpha2 is 255-alpha */ \ + vector unsigned char valpha2 = vec_nor(valpha, valpha); \ + /* vtemp3 contains dest AAGGAAGGAAGGAAGG */ \ + vector unsigned short vtemp3 = vec_mule(vd, valpha2); \ + /* vtemp4 contains dest RRBBRRBBRRBBRRBB */ \ + vector unsigned short vtemp4 = vec_mulo(vd, valpha2); \ + /* add source and dest */ \ + vtemp1 = vec_add(vtemp1, vtemp3); \ + vtemp2 = vec_add(vtemp2, vtemp4); \ + /* vtemp1 = (vtemp1 + 1) + ((vtemp1 + 1) >> 8) */ \ + vtemp1 = vec_add(vtemp1, v1_16); \ + vtemp3 = vec_sr(vtemp1, v8_16); \ + vtemp1 = vec_add(vtemp1, vtemp3); \ + /* vtemp2 = (vtemp2 + 1) + ((vtemp2 + 1) >> 8) */ \ + vtemp2 = vec_add(vtemp2, v1_16); \ + vtemp4 = vec_sr(vtemp2, v8_16); \ + vtemp2 = vec_add(vtemp2, vtemp4); \ + /* (>>8) and get ARGBARGBARGBARGB */ \ + vd = (vector unsigned char)vec_perm(vtemp1, vtemp2, mergePermute); \ +} while (0) + +/* Calculate the permute vector used for 32->32 swizzling */ +static vector unsigned char calc_swizzle32(const SDL_PixelFormat *srcfmt, + const SDL_PixelFormat *dstfmt) +{ + /* + * We have to assume that the bits that aren't used by other + * colors is alpha, and it's one complete byte, since some formats + * leave alpha with a zero mask, but we should still swizzle the bits. + */ + /* ARGB */ + const static struct SDL_PixelFormat default_pixel_format = { + NULL, 0, 0, + 0, 0, 0, 0, + 16, 8, 0, 24, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, + 0, 0}; + if (!srcfmt) { + srcfmt = &default_pixel_format; + } + if (!dstfmt) { + dstfmt = &default_pixel_format; + } + const vector unsigned char plus = VECUINT8_LITERAL + ( 0x00, 0x00, 0x00, 0x00, + 0x04, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x08, 0x08, + 0x0C, 0x0C, 0x0C, 0x0C ); + vector unsigned char vswiz; + vector unsigned int srcvec; +#define RESHIFT(X) (3 - ((X) >> 3)) + Uint32 rmask = RESHIFT(srcfmt->Rshift) << (dstfmt->Rshift); + Uint32 gmask = RESHIFT(srcfmt->Gshift) << (dstfmt->Gshift); + Uint32 bmask = RESHIFT(srcfmt->Bshift) << (dstfmt->Bshift); + Uint32 amask; + /* Use zero for alpha if either surface doesn't have alpha */ + if (dstfmt->Amask) { + amask = ((srcfmt->Amask) ? RESHIFT(srcfmt->Ashift) : 0x10) << (dstfmt->Ashift); + } else { + amask = 0x10101010 & ((dstfmt->Rmask | dstfmt->Gmask | dstfmt->Bmask) ^ 0xFFFFFFFF); + } +#undef RESHIFT + ((unsigned int *)(char*)&srcvec)[0] = (rmask | gmask | bmask | amask); + vswiz = vec_add(plus, (vector unsigned char)vec_splat(srcvec, 0)); + return(vswiz); +} + +static void Blit32to565PixelAlphaAltivec(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint8 *src = (Uint8 *)info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *)info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + + vector unsigned char v0 = vec_splat_u8(0); + vector unsigned short v8_16 = vec_splat_u16(8); + vector unsigned short v1_16 = vec_splat_u16(1); + vector unsigned short v2_16 = vec_splat_u16(2); + vector unsigned short v3_16 = vec_splat_u16(3); + vector unsigned int v8_32 = vec_splat_u32(8); + vector unsigned int v16_32 = vec_add(v8_32, v8_32); + vector unsigned short v3f = VECUINT16_LITERAL( + 0x003f, 0x003f, 0x003f, 0x003f, + 0x003f, 0x003f, 0x003f, 0x003f); + vector unsigned short vfc = VECUINT16_LITERAL( + 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc); + + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char)( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8_32, v16_32)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8_32) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8_32, v8_32)) + ); + vector unsigned char vgmerge = VECUINT8_LITERAL( + 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x0e, + 0x00, 0x12, 0x00, 0x16, + 0x00, 0x1a, 0x00, 0x1e); + vector unsigned char mergePermute = VEC_MERGE_PERMUTE(); + vector unsigned char vpermute = calc_swizzle32(srcfmt, NULL); + vector unsigned char valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + + vector unsigned short vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + while(height--) { + int extrawidth; + vector unsigned char valigner; + vector unsigned char vsrc; + vector unsigned char voverflow; + int width = info->d_width; + +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB, sA; \ + DISEMBLE_RGBA(src, 4, srcfmt, Pixel, sR, sG, sB, sA); \ + if(sA) { \ + unsigned short dstpixel = *((unsigned short *)dst); \ + dR = (dstpixel >> 8) & 0xf8; \ + dG = (dstpixel >> 3) & 0xfc; \ + dB = (dstpixel << 3) & 0xf8; \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + *((unsigned short *)dst) = ( \ + ((dR & 0xf8) << 8) | ((dG & 0xfc) << 3) | (dB >> 3) \ + ); \ + } \ + src += 4; \ + dst += 2; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dst)) && (width), width); + extrawidth = (width % 8); + valigner = VEC_ALIGNER(src); + vsrc = (vector unsigned char)vec_ld(0, src); + width -= extrawidth; + while (width) { + vector unsigned char valpha; + vector unsigned char vsrc1, vsrc2; + vector unsigned char vdst1, vdst2; + vector unsigned short vR, vG, vB; + vector unsigned short vpixel, vrpixel, vgpixel, vbpixel; + + /* Load 8 pixels from src as ARGB */ + voverflow = (vector unsigned char)vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc1 = vec_perm(vsrc, vsrc, vpermute); + src += 16; + vsrc = (vector unsigned char)vec_ld(15, src); + voverflow = vec_perm(voverflow, vsrc, valigner); + vsrc2 = vec_perm(voverflow, voverflow, vpermute); + src += 16; + + /* Load 8 pixels from dst as XRGB */ + voverflow = vec_ld(0, dst); + vR = vec_and((vector unsigned short)voverflow, vf800); + vB = vec_sl((vector unsigned short)voverflow, v3_16); + vG = vec_sl(vB, v2_16); + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, (vector unsigned char)vR, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, (vector unsigned char)vR, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + + /* Alpha blend 8 pixels as ARGB */ + valpha = vec_perm(vsrc1, v0, valphaPermute); + VEC_MULTIPLY_ALPHA(vsrc1, vdst1, valpha, mergePermute, v1_16, v8_16); + valpha = vec_perm(vsrc2, v0, valphaPermute); + VEC_MULTIPLY_ALPHA(vsrc2, vdst2, valpha, mergePermute, v1_16, v8_16); + + /* Convert 8 pixels to 565 */ + vpixel = (vector unsigned short)vec_packpx((vector unsigned int)vdst1, (vector unsigned int)vdst2); + vgpixel = (vector unsigned short)vec_perm(vdst1, vdst2, vgmerge); + vgpixel = vec_and(vgpixel, vfc); + vgpixel = vec_sl(vgpixel, v3_16); + vrpixel = vec_sl(vpixel, v1_16); + vrpixel = vec_and(vrpixel, vf800); + vbpixel = vec_and(vpixel, v3f); + vdst1 = vec_or((vector unsigned char)vrpixel, (vector unsigned char)vgpixel); + vdst1 = vec_or(vdst1, (vector unsigned char)vbpixel); + + /* Store 8 pixels */ + vec_st(vdst1, 0, dst); + + width -= 8; + dst += 16; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + src += srcskip; + dst += dstskip; + } +} + +static void Blit32to32SurfaceAlphaKeyAltivec(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + Uint32 rgbmask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + Uint32 ckey = info->src->colorkey; + vector unsigned char mergePermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned char vbits; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + vector unsigned int vckey; + vector unsigned int vrgbmask; + + mergePermute = VEC_MERGE_PERMUTE(); + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + vbits = (vector unsigned char)vec_splat_s8(-1); + + ckey &= rgbmask; + ((unsigned int *)(char*)&vckey)[0] = ckey; + vckey = vec_splat(vckey, 0); + ((unsigned int *)(char*)&vrgbmask)[0] = rgbmask; + vrgbmask = vec_splat(vrgbmask, 0); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB; \ + RETRIEVE_RGB_PIXEL(((Uint8 *)srcp), 4, Pixel); \ + if(sA && Pixel != ckey) { \ + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); \ + DISEMBLE_RGB(((Uint8 *)dstp), 4, dstfmt, Pixel, dR, dG, dB); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA(((Uint8 *)dstp), 4, dstfmt, dR, dG, dB, dA); \ + } \ + dstp++; \ + srcp++; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char vsel; + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char vd_orig; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + /* vsel is set for items that match the key */ + vsel = (vector unsigned char)vec_and((vector unsigned int)vs, vrgbmask); + vsel = (vector unsigned char)vec_cmpeq((vector unsigned int)vsel, vckey); + + /* permute to source format */ + vs = vec_perm(vs, valpha, vsrcPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd_orig = vd = vec_perm(vd, v0, vsdstPermute); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + + /* mask out color key */ + vd = vec_sel(vd, vd_orig, vsel); + + /* permute to dest format */ + vd = vec_perm(vd, vbits, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } +} + + +static void Blit32to32PixelAlphaAltivec(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned char mergePermute; + vector unsigned char valphaPermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valphamask; + vector unsigned char vpixelmask; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + mergePermute = VEC_MERGE_PERMUTE(); + valphamask = VEC_ALPHA_MASK(); + valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + vpixelmask = vec_nor(valphamask, v0); + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + while ( height-- ) { + width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB, sA, dA; \ + DISEMBLE_RGBA((Uint8 *)srcp, 4, srcfmt, Pixel, sR, sG, sB, sA); \ + if(sA) { \ + DISEMBLE_RGBA((Uint8 *)dstp, 4, dstfmt, Pixel, dR, dG, dB, dA); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA((Uint8 *)dstp, 4, dstfmt, dR, dG, dB, dA); \ + } \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + /* vsrcPermute */ + /* vdstPermute */ + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char valpha; + vector unsigned char vdstalpha; + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + vs = vec_perm(vs, v0, vsrcPermute); + + valpha = vec_perm(vs, v0, valphaPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd = vec_perm(vd, v0, vsdstPermute); + vdstalpha = vec_and(vd, valphamask); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha to the dest alpha */ + vd = vec_and(vd, vpixelmask); + vd = vec_or(vd, vdstalpha); + vd = vec_perm(vd, v0, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } + srcp += srcskip; + dstp += dstskip; +#undef ONE_PIXEL_BLEND + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaAltivec(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + vector unsigned char mergePermute; + vector unsigned char valphaPermute; + vector unsigned char valphamask; + vector unsigned char vpixelmask; + vector unsigned char v0; + vector unsigned short v1; + vector unsigned short v8; + v0 = vec_splat_u8(0); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + mergePermute = VEC_MERGE_PERMUTE(); + valphamask = VEC_ALPHA_MASK(); + valphaPermute = vec_and(vec_lvsl(0, (int *)NULL), vec_splat_u8(0xC)); + + + vpixelmask = vec_nor(valphamask, v0); + while(height--) { + width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while ((condition)) { \ + Uint32 dalpha; \ + Uint32 d; \ + Uint32 s1; \ + Uint32 d1; \ + Uint32 s = *srcp; \ + Uint32 alpha = s >> 24; \ + if(alpha) { \ + if(alpha == SDL_ALPHA_OPAQUE) { \ + *dstp = (s & 0x00ffffff) | (*dstp & 0xff000000); \ + } else { \ + d = *dstp; \ + dalpha = d & 0xff000000; \ + s1 = s & 0xff00ff; \ + d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dstp = d1 | d | dalpha; \ + } \ + } \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + vector unsigned char valpha; + vector unsigned char vdstalpha; + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + valpha = vec_perm(vs, v0, valphaPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vdstalpha = vec_and(vd, valphamask); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha to the dest alpha */ + vd = vec_and(vd, vpixelmask); + vd = vec_or(vd, vdstalpha); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } + srcp += srcskip; + dstp += dstskip; + } +#undef ONE_PIXEL_BLEND +} + +static void Blit32to32SurfaceAlphaAltivec(SDL_BlitInfo *info) +{ + /* XXX : 6 */ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + vector unsigned char mergePermute; + vector unsigned char vsrcPermute; + vector unsigned char vdstPermute; + vector unsigned char vsdstPermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned char vbits; + vector unsigned short v1; + vector unsigned short v8; + + mergePermute = VEC_MERGE_PERMUTE(); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + vsrcPermute = calc_swizzle32(srcfmt, NULL); + vdstPermute = calc_swizzle32(NULL, dstfmt); + vsdstPermute = calc_swizzle32(dstfmt, NULL); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + vbits = (vector unsigned char)vec_splat_s8(-1); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, dR, dG, dB; \ + DISEMBLE_RGB(((Uint8 *)srcp), 4, srcfmt, Pixel, sR, sG, sB); \ + DISEMBLE_RGB(((Uint8 *)dstp), 4, dstfmt, Pixel, dR, dG, dB); \ + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); \ + ASSEMBLE_RGBA(((Uint8 *)dstp), 4, dstfmt, dR, dG, dB, dA); \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + vs = vec_perm(vs, valpha, vsrcPermute); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + vd = vec_perm(vd, vd, vsdstPermute); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + vd = vec_perm(vd, vbits, vdstPermute); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } + +} + + +/* fast RGB888->(A)RGB888 blending */ +static void BlitRGBtoRGBSurfaceAlphaAltivec(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + vector unsigned char mergePermute; + vector unsigned char valpha; + vector unsigned char valphamask; + vector unsigned short v1; + vector unsigned short v8; + + mergePermute = VEC_MERGE_PERMUTE(); + v1 = vec_splat_u16(1); + v8 = vec_splat_u16(8); + + /* set the alpha to 255 on the destination surf */ + valphamask = VEC_ALPHA_MASK(); + + /* set a vector full of alpha and 255-alpha */ + ((unsigned char *)&valpha)[0] = alpha; + valpha = vec_splat(valpha, 0); + + while(height--) { + int width = info->d_width; +#define ONE_PIXEL_BLEND(condition, widthvar) while ((condition)) { \ + Uint32 s = *srcp; \ + Uint32 d = *dstp; \ + Uint32 s1 = s & 0xff00ff; \ + Uint32 d1 = d & 0xff00ff; \ + d1 = (d1 + ((s1 - d1) * alpha >> 8)) \ + & 0xff00ff; \ + s &= 0xff00; \ + d &= 0xff00; \ + d = (d + ((s - d) * alpha >> 8)) & 0xff00; \ + *dstp = d1 | d | 0xff000000; \ + ++srcp; \ + ++dstp; \ + widthvar--; \ + } + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned char vs = (vector unsigned char)vec_ld(0, srcp); + width -= extrawidth; + while (width) { + vector unsigned char voverflow; + vector unsigned char vd; + + /* s = *srcp */ + voverflow = (vector unsigned char)vec_ld(15, srcp); + vs = vec_perm(vs, voverflow, valigner); + + /* d = *dstp */ + vd = (vector unsigned char)vec_ld(0, dstp); + + VEC_MULTIPLY_ALPHA(vs, vd, valpha, mergePermute, v1, v8); + + /* set the alpha channel to full on */ + vd = vec_or(vd, valphamask); + + /* *dstp = res */ + vec_st((vector unsigned int)vd, 0, dstp); + + srcp += 4; + dstp += 4; + width -= 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); + } +#undef ONE_PIXEL_BLEND + + srcp += srcskip; + dstp += dstskip; + } +} +#if __MWERKS__ +#pragma altivec_model off +#endif +#endif /* SDL_ALTIVEC_BLITTERS */ + +/* fast RGB888->(A)RGB888 blending with surface alpha=128 special case */ +static void BlitRGBtoRGBSurfaceAlpha128(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + *dstp++ = ((((s & 0x00fefefe) + (d & 0x00fefefe)) >> 1) + + (s & d & 0x00010101)) | 0xff000000; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* fast RGB888->(A)RGB888 blending with surface alpha */ +static void BlitRGBtoRGBSurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + BlitRGBtoRGBSurfaceAlpha128(info); + } else { + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + Uint32 s; + Uint32 d; + Uint32 s1; + Uint32 d1; + + while(height--) { + DUFFS_LOOP_DOUBLE2({ + /* One Pixel Blend */ + s = *srcp; + d = *dstp; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 = (d1 + ((s1 - d1) * alpha >> 8)) + & 0xff00ff; + s &= 0xff00; + d &= 0xff00; + d = (d + ((s - d) * alpha >> 8)) & 0xff00; + *dstp = d1 | d | 0xff000000; + ++srcp; + ++dstp; + },{ + /* Two Pixels Blend */ + s = *srcp; + d = *dstp; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 += (s1 - d1) * alpha >> 8; + d1 &= 0xff00ff; + + s = ((s & 0xff00) >> 8) | + ((srcp[1] & 0xff00) << 8); + d = ((d & 0xff00) >> 8) | + ((dstp[1] & 0xff00) << 8); + d += (s - d) * alpha >> 8; + d &= 0x00ff00ff; + + *dstp++ = d1 | ((d << 8) & 0xff00) | 0xff000000; + ++srcp; + + s1 = *srcp; + d1 = *dstp; + s1 &= 0xff00ff; + d1 &= 0xff00ff; + d1 += (s1 - d1) * alpha >> 8; + d1 &= 0xff00ff; + + *dstp = d1 | ((d >> 8) & 0xff00) | 0xff000000; + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + + while(height--) { + DUFFS_LOOP4({ + Uint32 dalpha; + Uint32 d; + Uint32 s1; + Uint32 d1; + Uint32 s = *srcp; + Uint32 alpha = s >> 24; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == SDL_ALPHA_OPAQUE) { + *dstp = (s & 0x00ffffff) | (*dstp & 0xff000000); + } else { + /* + * take out the middle component (green), and process + * the other two in parallel. One multiply less. + */ + d = *dstp; + dalpha = d & 0xff000000; + s1 = s & 0xff00ff; + d1 = d & 0xff00ff; + d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff; + s &= 0xff00; + d &= 0xff00; + d = (d + ((s - d) * alpha >> 8)) & 0xff00; + *dstp = d1 | d | dalpha; + } + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +#if GCC_ASMBLIT +/* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX3DNOW(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 amask = sf->Amask; + + __asm__ ( + /* make mm6 all zeros. */ + "pxor %%mm6, %%mm6\n" + + /* Make a mask to preserve the alpha. */ + "movd %0, %%mm7\n\t" /* 0000F000 -> mm7 */ + "punpcklbw %%mm7, %%mm7\n\t" /* FF000000 -> mm7 */ + "pcmpeqb %%mm4, %%mm4\n\t" /* FFFFFFFF -> mm4 */ + "movq %%mm4, %%mm3\n\t" /* FFFFFFFF -> mm3 (for later) */ + "pxor %%mm4, %%mm7\n\t" /* 00FFFFFF -> mm7 (mult mask) */ + + /* form channel masks */ + "movq %%mm7, %%mm4\n\t" /* 00FFFFFF -> mm4 */ + "packsswb %%mm6, %%mm4\n\t" /* 00000FFF -> mm4 (channel mask) */ + "packsswb %%mm6, %%mm3\n\t" /* 0000FFFF -> mm3 */ + "pxor %%mm4, %%mm3\n\t" /* 0000F000 -> mm3 (~channel mask) */ + + /* get alpha channel shift */ + "movd %1, %%mm5\n\t" /* Ashift -> mm5 */ + + : /* nothing */ : "rm" (amask), "rm" ((Uint32) sf->Ashift) ); + + while(height--) { + + DUFFS_LOOP4({ + Uint32 alpha; + + __asm__ ( + "prefetch 64(%0)\n" + "prefetch 64(%1)\n" + : : "r" (srcp), "r" (dstp) ); + + alpha = *srcp & amask; + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha == 0) { + /* do nothing */ + } + else if(alpha == amask) { + /* opaque alpha -- copy RGB, keep dst alpha */ + /* using MMX here to free up regular registers for other things */ + __asm__ ( + "movd (%0), %%mm0\n\t" /* src(ARGB) -> mm0 (0000ARGB)*/ + "movd (%1), %%mm1\n\t" /* dst(ARGB) -> mm1 (0000ARGB)*/ + "pand %%mm4, %%mm0\n\t" /* src & chanmask -> mm0 */ + "pand %%mm3, %%mm1\n\t" /* dst & ~chanmask -> mm2 */ + "por %%mm0, %%mm1\n\t" /* src | dst -> mm1 */ + "movd %%mm1, (%1) \n\t" /* mm1 -> dst */ + + : : "r" (srcp), "r" (dstp) ); + } + + else { + __asm__ ( + /* load in the source, and dst. */ + "movd (%0), %%mm0\n" /* mm0(s) = 0 0 0 0 | As Rs Gs Bs */ + "movd (%1), %%mm1\n" /* mm1(d) = 0 0 0 0 | Ad Rd Gd Bd */ + + /* Move the src alpha into mm2 */ + + /* if supporting pshufw */ + /*"pshufw $0x55, %%mm0, %%mm2\n" */ /* mm2 = 0 As 0 As | 0 As 0 As */ + /*"psrlw $8, %%mm2\n" */ + + /* else: */ + "movd %2, %%mm2\n" + "psrld %%mm5, %%mm2\n" /* mm2 = 0 0 0 0 | 0 0 0 As */ + "punpcklwd %%mm2, %%mm2\n" /* mm2 = 0 0 0 0 | 0 As 0 As */ + "punpckldq %%mm2, %%mm2\n" /* mm2 = 0 As 0 As | 0 As 0 As */ + "pand %%mm7, %%mm2\n" /* to preserve dest alpha */ + + /* move the colors into words. */ + "punpcklbw %%mm6, %%mm0\n" /* mm0 = 0 As 0 Rs | 0 Gs 0 Bs */ + "punpcklbw %%mm6, %%mm1\n" /* mm0 = 0 Ad 0 Rd | 0 Gd 0 Bd */ + + /* src - dst */ + "psubw %%mm1, %%mm0\n" /* mm0 = As-Ad Rs-Rd | Gs-Gd Bs-Bd */ + + /* A * (src-dst) */ + "pmullw %%mm2, %%mm0\n" /* mm0 = 0*As-d As*Rs-d | As*Gs-d As*Bs-d */ + "psrlw $8, %%mm0\n" /* mm0 = 0>>8 Rc>>8 | Gc>>8 Bc>>8 */ + "paddb %%mm1, %%mm0\n" /* mm0 = 0+Ad Rc+Rd | Gc+Gd Bc+Bd */ + + "packuswb %%mm0, %%mm0\n" /* mm0 = | Ac Rc Gc Bc */ + + "movd %%mm0, (%1)\n" /* result in mm0 */ + + : : "r" (srcp), "r" (dstp), "r" (alpha) ); + + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + + __asm__ ( + "emms\n" + : ); +} +/* End GCC_ASMBLIT*/ + +#elif MSVC_ASMBLIT +/* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */ +static void BlitRGBtoRGBPixelAlphaMMX3DNOW(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint32 *dstp = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip >> 2; + SDL_PixelFormat* sf = info->src; + Uint32 chanmask = sf->Rmask | sf->Gmask | sf->Bmask; + Uint32 amask = sf->Amask; + Uint32 ashift = sf->Ashift; + Uint64 multmask; + + __m64 src1, dst1, mm_alpha, mm_zero, dmask; + + mm_zero = _mm_setzero_si64(); /* 0 -> mm_zero */ + multmask = ~(0xFFFFi64 << (ashift * 2)); + dmask = *(__m64*) &multmask; /* dst alpha mask -> dmask */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 alpha; + + _m_prefetch(srcp + 16); + _m_prefetch(dstp + 16); + + alpha = *srcp & amask; + if (alpha == 0) { + /* do nothing */ + } else if (alpha == amask) { + /* copy RGB, keep dst alpha */ + *dstp = (*srcp & chanmask) | (*dstp & ~chanmask); + } else { + src1 = _mm_cvtsi32_si64(*srcp); /* src(ARGB) -> src1 (0000ARGB)*/ + src1 = _mm_unpacklo_pi8(src1, mm_zero); /* 0A0R0G0B -> src1 */ + + dst1 = _mm_cvtsi32_si64(*dstp); /* dst(ARGB) -> dst1 (0000ARGB)*/ + dst1 = _mm_unpacklo_pi8(dst1, mm_zero); /* 0A0R0G0B -> dst1 */ + + mm_alpha = _mm_cvtsi32_si64(alpha); /* alpha -> mm_alpha (0000000A) */ + mm_alpha = _mm_srli_si64(mm_alpha, ashift); /* mm_alpha >> ashift -> mm_alpha(0000000A) */ + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + mm_alpha = _mm_and_si64(mm_alpha, dmask); /* 000A0A0A -> mm_alpha, preserve dst alpha on add */ + + /* blend */ + src1 = _mm_sub_pi16(src1, dst1);/* src - dst -> src1 */ + src1 = _mm_mullo_pi16(src1, mm_alpha); /* (src - dst) * alpha -> src1 */ + src1 = _mm_srli_pi16(src1, 8); /* src1 >> 8 -> src1(000R0G0B) */ + dst1 = _mm_add_pi8(src1, dst1); /* src1 + dst1(dst) -> dst1(0A0R0G0B) */ + dst1 = _mm_packs_pu16(dst1, mm_zero); /* 0000ARGB -> dst1 */ + + *dstp = _mm_cvtsi64_si32(dst1); /* dst1 -> pixel */ + } + ++srcp; + ++dstp; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); +} +/* End MSVC_ASMBLIT */ + +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +/* 16bpp special case for per-surface alpha=50%: blend 2 pixels in parallel */ + +/* blend a single 16 bit pixel at 50% */ +#define BLEND16_50(d, s, mask) \ + ((((s & mask) + (d & mask)) >> 1) + (s & d & (~mask & 0xffff))) + +/* blend two 16 bit pixels at 50% */ +#define BLEND2x16_50(d, s, mask) \ + (((s & (mask | mask << 16)) >> 1) + ((d & (mask | mask << 16)) >> 1) \ + + (s & d & (~(mask | mask << 16)))) + +static void Blit16to16SurfaceAlpha128(SDL_BlitInfo *info, Uint16 mask) +{ + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + if(((uintptr_t)srcp ^ (uintptr_t)dstp) & 2) { + /* + * Source and destination not aligned, pipeline it. + * This is mostly a win for big blits but no loss for + * small ones + */ + Uint32 prev_sw; + int w = width; + + /* handle odd destination */ + if((uintptr_t)dstp & 2) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + dstp++; + srcp++; + w--; + } + srcp++; /* srcp is now 32-bit aligned */ + + /* bootstrap pipeline with first halfword */ + prev_sw = ((Uint32 *)srcp)[-1]; + + while(w > 1) { + Uint32 sw, dw, s; + sw = *(Uint32 *)srcp; + dw = *(Uint32 *)dstp; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + s = (prev_sw << 16) + (sw >> 16); +#else + s = (prev_sw >> 16) + (sw << 16); +#endif + prev_sw = sw; + *(Uint32 *)dstp = BLEND2x16_50(dw, s, mask); + dstp += 2; + srcp += 2; + w -= 2; + } + + /* final pixel if any */ + if(w) { + Uint16 d = *dstp, s; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + s = (Uint16)prev_sw; +#else + s = (Uint16)(prev_sw >> 16); +#endif + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + } + srcp += srcskip - 1; + dstp += dstskip; + } else { + /* source and destination are aligned */ + int w = width; + + /* first odd pixel? */ + if((uintptr_t)srcp & 2) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + w--; + } + /* srcp and dstp are now 32-bit aligned */ + + while(w > 1) { + Uint32 sw = *(Uint32 *)srcp; + Uint32 dw = *(Uint32 *)dstp; + *(Uint32 *)dstp = BLEND2x16_50(dw, sw, mask); + srcp += 2; + dstp += 2; + w -= 2; + } + + /* last odd pixel? */ + if(w) { + Uint16 d = *dstp, s = *srcp; + *dstp = BLEND16_50(d, s, mask); + srcp++; + dstp++; + } + srcp += srcskip; + dstp += dstskip; + } + } +} + +#if GCC_ASMBLIT +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + Uint64 load; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + load = alpha; + alpha >>= 3; /* downscale alpha to 5 bits */ + + movq_m2r(load, mm0); /* alpha(0000000A) -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + psllq_i2r(3, mm0); + + /* Setup the 565 color channel masks */ + load = 0x07E007E007E007E0ULL; + movq_m2r(load, mm4); /* MASKGREEN -> mm4 */ + load = 0x001F001F001F001FULL; + movq_m2r(load, mm7); /* MASKBLUE -> mm7 */ + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = d | d >> 16; + },{ + movq_m2r((*srcp), mm2);/* 4 src pixels -> mm2 */ + movq_m2r((*dstp), mm3);/* 4 dst pixels -> mm3 */ + + /* red -- does not need a mask since the right shift clears + the uninteresting bits */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 [000r 000r 000r 000r] */ + psrlw_i2r(11, mm6); /* mm6 >> 11 -> mm6 [000r 000r 000r 000r] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* alpha used is actually 11 bits + 11 + 5 = 16 bits, so the sign bits are lost */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + psllw_i2r(11, mm6); /* mm6 << 11 -> mm6 */ + + movq_r2r(mm6, mm1); /* save new reds in dsts */ + + /* green -- process the bits in place */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKGREEN -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKGREEN -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 11 - 16 = 6 bits, so all the lower uninteresting + bits are gone and the sign bits present */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + + por_r2r(mm6, mm1); /* save new greens in dsts */ + + /* blue */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm7, mm5); /* src & MASKBLUE -> mm5[000b 000b 000b 000b] */ + pand_r2r(mm7, mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 5 = 16 bits, so the sign bits are lost and + the interesting bits will need to be MASKed */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + por_r2r(mm6, mm1); /* save new blues in dsts */ + + movq_r2m(mm1, *dstp); /* mm1 -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + Uint64 load; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + load = alpha; + alpha >>= 3; /* downscale alpha to 5 bits */ + + movq_m2r(load, mm0); /* alpha(0000000A) -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 00000A0A -> mm0 */ + punpcklwd_r2r(mm0, mm0); /* 0A0A0A0A -> mm0 */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + psllq_i2r(3, mm0); + + /* Setup the 555 color channel masks */ + load = 0x03E003E003E003E0ULL; + movq_m2r(load, mm4); /* MASKGREEN -> mm4 */ + load = 0x001F001F001F001FULL; + movq_m2r(load, mm7); /* MASKBLUE -> mm7 */ + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = d | d >> 16; + },{ + movq_m2r((*srcp), mm2);/* 4 src pixels -> mm2 */ + movq_m2r((*dstp), mm3);/* 4 dst pixels -> mm3 */ + + /* red -- process the bits in place */ + psllq_i2r(5, mm4); /* turn MASKGREEN into MASKRED */ + /* by reusing the GREEN mask we free up another mmx + register to accumulate the result */ + + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKRED -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKRED -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 15 - 16 = 10 bits, uninteresting bits will be + cleared by a MASK below */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm4, mm6); /* mm6 & MASKRED -> mm6 */ + + psrlq_i2r(5, mm4); /* turn MASKRED back into MASKGREEN */ + + movq_r2r(mm6, mm1); /* save new reds in dsts */ + + /* green -- process the bits in place */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm4, mm5); /* src & MASKGREEN -> mm5 */ + pand_r2r(mm4, mm6); /* dst & MASKGREEN -> mm6 */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmulhw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 10 - 16 = 5 bits, so all the lower uninteresting + bits are gone and the sign bits present */ + psllw_i2r(5, mm5); /* mm5 << 5 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + + por_r2r(mm6, mm1); /* save new greens in dsts */ + + /* blue */ + movq_r2r(mm2, mm5); /* src -> mm5 */ + movq_r2r(mm3, mm6); /* dst -> mm6 */ + pand_r2r(mm7, mm5); /* src & MASKBLUE -> mm5[000b 000b 000b 000b] */ + pand_r2r(mm7, mm6); /* dst & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + /* blend */ + psubw_r2r(mm6, mm5);/* src - dst -> mm5 */ + pmullw_r2r(mm0, mm5); /* mm5 * alpha -> mm5 */ + /* 11 + 5 = 16 bits, so the sign bits are lost and + the interesting bits will need to be MASKed */ + psrlw_i2r(11, mm5); /* mm5 >> 11 -> mm5 */ + paddw_r2r(mm5, mm6); /* mm5 + mm6(dst) -> mm6 */ + pand_r2r(mm7, mm6); /* mm6 & MASKBLUE -> mm6[000b 000b 000b 000b] */ + + por_r2r(mm6, mm1); /* save new blues in dsts */ + + movq_r2m(mm1, *dstp);/* mm1 -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + emms(); + } +} +/* End GCC_ASMBLIT */ + +#elif MSVC_ASMBLIT +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + + __m64 src1, dst1, src2, dst2, gmask, bmask, mm_res, mm_alpha; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + mm_alpha = _mm_set_pi32(0, alpha); /* 0000000A -> mm_alpha */ + alpha >>= 3; /* downscale alpha to 5 bits */ + + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + mm_alpha = _mm_slli_si64(mm_alpha, 3); + + /* Setup the 565 color channel masks */ + gmask = _mm_set_pi32(0x07E007E0, 0x07E007E0); /* MASKGREEN -> gmask */ + bmask = _mm_set_pi32(0x001F001F, 0x001F001F); /* MASKBLUE -> bmask */ + + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + src1 = *(__m64*)srcp; /* 4 src pixels -> src1 */ + dst1 = *(__m64*)dstp; /* 4 dst pixels -> dst1 */ + + /* red */ + src2 = src1; + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 [000r 000r 000r 000r] */ + + dst2 = dst1; + dst2 = _mm_srli_pi16(dst2, 11); /* dst2 >> 11 -> dst2 [000r 000r 000r 000r] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_slli_pi16(dst2, 11); /* dst2 << 11 -> dst2 */ + + mm_res = dst2; /* RED -> mm_res */ + + /* green -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, gmask); /* dst & MASKGREEN -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN -> mm_res */ + + /* blue */ + src2 = src1; + src2 = _mm_and_si64(src2, bmask); /* src & MASKBLUE -> src2[000b 000b 000b 000b] */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, bmask); /* dst & MASKBLUE -> dst2[000b 000b 000b 000b] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst2 & MASKBLUE -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN | BLUE -> mm_res */ + + *(__m64*)dstp = mm_res; /* mm_res -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlphaMMX(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + Uint32 s, d; + + __m64 src1, dst1, src2, dst2, rmask, gmask, bmask, mm_res, mm_alpha; + + alpha &= ~(1+2+4); /* cut alpha to get the exact same behaviour */ + mm_alpha = _mm_set_pi32(0, alpha); /* 0000000A -> mm_alpha */ + alpha >>= 3; /* downscale alpha to 5 bits */ + + mm_alpha = _mm_unpacklo_pi16(mm_alpha, mm_alpha); /* 00000A0A -> mm_alpha */ + mm_alpha = _mm_unpacklo_pi32(mm_alpha, mm_alpha); /* 0A0A0A0A -> mm_alpha */ + /* position alpha to allow for mullo and mulhi on diff channels + to reduce the number of operations */ + mm_alpha = _mm_slli_si64(mm_alpha, 3); + + /* Setup the 555 color channel masks */ + rmask = _mm_set_pi32(0x7C007C00, 0x7C007C00); /* MASKRED -> rmask */ + gmask = _mm_set_pi32(0x03E003E0, 0x03E003E0); /* MASKGREEN -> gmask */ + bmask = _mm_set_pi32(0x001F001F, 0x001F001F); /* MASKBLUE -> bmask */ + + while(height--) { + DUFFS_LOOP_QUATRO2( + { + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + s = *srcp++; + d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + },{ + src1 = *(__m64*)srcp; /* 4 src pixels -> src1 */ + dst1 = *(__m64*)dstp; /* 4 dst pixels -> dst1 */ + + /* red -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, rmask); /* src & MASKRED -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, rmask); /* dst & MASKRED -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, rmask); /* dst2 & MASKRED -> dst2 */ + + mm_res = dst2; /* RED -> mm_res */ + + /* green -- process the bits in place */ + src2 = src1; + src2 = _mm_and_si64(src2, gmask); /* src & MASKGREEN -> src2 */ + + dst2 = dst1; + dst2 = _mm_and_si64(dst2, gmask); /* dst & MASKGREEN -> dst2 */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mulhi_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_slli_pi16(src2, 5); /* src2 << 5 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN -> mm_res */ + + /* blue */ + src2 = src1; /* src -> src2 */ + src2 = _mm_and_si64(src2, bmask); /* src & MASKBLUE -> src2[000b 000b 000b 000b] */ + + dst2 = dst1; /* dst -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst & MASKBLUE -> dst2[000b 000b 000b 000b] */ + + /* blend */ + src2 = _mm_sub_pi16(src2, dst2);/* src - dst -> src2 */ + src2 = _mm_mullo_pi16(src2, mm_alpha); /* src2 * alpha -> src2 */ + src2 = _mm_srli_pi16(src2, 11); /* src2 >> 11 -> src2 */ + dst2 = _mm_add_pi16(src2, dst2); /* src2 + dst2 -> dst2 */ + dst2 = _mm_and_si64(dst2, bmask); /* dst2 & MASKBLUE -> dst2 */ + + mm_res = _mm_or_si64(mm_res, dst2); /* RED | GREEN | BLUE -> mm_res */ + + *(__m64*)dstp = mm_res; /* mm_res -> 4 dst pixels */ + + srcp += 4; + dstp += 4; + }, width); + srcp += srcskip; + dstp += dstskip; + } + _mm_empty(); + } +} +#endif /* GCC_ASMBLIT, MSVC_ASMBLIT */ + +/* fast RGB565->RGB565 blending with surface alpha */ +static void Blit565to565SurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xf7de); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + alpha >>= 3; /* downscale alpha to 5 bits */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x07e0f81f; + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp++ = (Uint16)(d | d >> 16); + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast RGB555->RGB555 blending with surface alpha */ +static void Blit555to555SurfaceAlpha(SDL_BlitInfo *info) +{ + unsigned alpha = info->src->alpha; /* downscale alpha to 5 bits */ + if(alpha == 128) { + Blit16to16SurfaceAlpha128(info, 0xfbde); + } else { + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip >> 1; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + alpha >>= 3; /* downscale alpha to 5 bits */ + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp++; + Uint32 d = *dstp; + /* + * shift out the middle component (green) to + * the high 16 bits, and process all three RGB + * components at the same time. + */ + s = (s | s << 16) & 0x03e07c1f; + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp++ = (Uint16)(d | d >> 16); + }, width); + srcp += srcskip; + dstp += dstskip; + } + } +} + +/* fast ARGB8888->RGB565 blending with pixel alpha */ +static void BlitARGBto565PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + DUFFS_LOOP4({ + Uint32 s = *srcp; + unsigned alpha = s >> 27; /* downscale alpha to 5 bits */ + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == (SDL_ALPHA_OPAQUE >> 3)) { + *dstp = (Uint16)((s >> 8 & 0xf800) + (s >> 5 & 0x7e0) + (s >> 3 & 0x1f)); + } else { + Uint32 d = *dstp; + /* + * convert source and destination to G0RAB65565 + * and blend all components at the same time + */ + s = ((s & 0xfc00) << 11) + (s >> 8 & 0xf800) + + (s >> 3 & 0x1f); + d = (d | d << 16) & 0x07e0f81f; + d += (s - d) * alpha >> 5; + d &= 0x07e0f81f; + *dstp = (Uint16)(d | d >> 16); + } + } + srcp++; + dstp++; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* fast ARGB8888->RGB555 blending with pixel alpha */ +static void BlitARGBto555PixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *srcp = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip >> 2; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip >> 1; + + while(height--) { + DUFFS_LOOP4({ + unsigned alpha; + Uint32 s = *srcp; + alpha = s >> 27; /* downscale alpha to 5 bits */ + /* FIXME: Here we special-case opaque alpha since the + compositioning used (>>8 instead of /255) doesn't handle + it correctly. Also special-case alpha=0 for speed? + Benchmark this! */ + if(alpha) { + if(alpha == (SDL_ALPHA_OPAQUE >> 3)) { + *dstp = (Uint16)((s >> 9 & 0x7c00) + (s >> 6 & 0x3e0) + (s >> 3 & 0x1f)); + } else { + Uint32 d = *dstp; + /* + * convert source and destination to G0RAB65565 + * and blend all components at the same time + */ + s = ((s & 0xf800) << 10) + (s >> 9 & 0x7c00) + + (s >> 3 & 0x1f); + d = (d | d << 16) & 0x03e07c1f; + d += (s - d) * alpha >> 5; + d &= 0x03e07c1f; + *dstp = (Uint16)(d | d >> 16); + } + } + srcp++; + dstp++; + }, width); + srcp += srcskip; + dstp += dstskip; + } +} + +/* General (slow) N->N blending with per-surface alpha */ +static void BlitNtoNSurfaceAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + + if(sA) { + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + DISEMBLE_RGB(dst, dstbpp, dstfmt, Pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +/* General (slow) colorkeyed N->N blending with per-surface alpha */ +static void BlitNtoNSurfaceAlphaKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + Uint32 ckey = srcfmt->colorkey; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned sA = srcfmt->alpha; + unsigned dA = dstfmt->Amask ? SDL_ALPHA_OPAQUE : 0; + + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); + if(sA && Pixel != ckey) { + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); + DISEMBLE_RGB(dst, dstbpp, dstfmt, Pixel, dR, dG, dB); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + } + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* General (slow) N->N blending with pixel alpha */ +static void BlitNtoNPixelAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + + int srcbpp; + int dstbpp; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + dstbpp = dstfmt->BytesPerPixel; + + /* FIXME: for 8bpp source alpha, this doesn't get opaque values + quite right. for <8bpp source alpha, it gets them very wrong + (check all macros!) + It is unclear whether there is a good general solution that doesn't + need a branch (or a divide). */ + while ( height-- ) { + DUFFS_LOOP4( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + unsigned dR; + unsigned dG; + unsigned dB; + unsigned sA; + unsigned dA; + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA); + if(sA) { + DISEMBLE_RGBA(dst, dstbpp, dstfmt, Pixel, dR, dG, dB, dA); + ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); + } + src += srcbpp; + dst += dstbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + + +SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) +{ + SDL_PixelFormat *sf = surface->format; + SDL_PixelFormat *df = surface->map->dst->format; + + if(sf->Amask == 0) { + if((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { + if(df->BytesPerPixel == 1) + return BlitNto1SurfaceAlphaKey; + else +#if SDL_ALTIVEC_BLITTERS + if (sf->BytesPerPixel == 4 && df->BytesPerPixel == 4 && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32SurfaceAlphaKeyAltivec; + else +#endif + return BlitNtoNSurfaceAlphaKey; + } else { + /* Per-surface alpha blits */ + switch(df->BytesPerPixel) { + case 1: + return BlitNto1SurfaceAlpha; + + case 2: + if(surface->map->identity) { + if(df->Gmask == 0x7e0) + { +#if MMX_ASMBLIT + if(SDL_HasMMX()) + return Blit565to565SurfaceAlphaMMX; + else +#endif + return Blit565to565SurfaceAlpha; + } + else if(df->Gmask == 0x3e0) + { +#if MMX_ASMBLIT + if(SDL_HasMMX()) + return Blit555to555SurfaceAlphaMMX; + else +#endif + return Blit555to555SurfaceAlpha; + } + } + return BlitNtoNSurfaceAlpha; + + case 4: + if(sf->Rmask == df->Rmask + && sf->Gmask == df->Gmask + && sf->Bmask == df->Bmask + && sf->BytesPerPixel == 4) + { +#if MMX_ASMBLIT + if(sf->Rshift % 8 == 0 + && sf->Gshift % 8 == 0 + && sf->Bshift % 8 == 0 + && SDL_HasMMX()) + return BlitRGBtoRGBSurfaceAlphaMMX; +#endif + if((sf->Rmask | sf->Gmask | sf->Bmask) == 0xffffff) + { +#if SDL_ALTIVEC_BLITTERS + if(!(surface->map->dst->flags & SDL_HWSURFACE) + && SDL_HasAltiVec()) + return BlitRGBtoRGBSurfaceAlphaAltivec; +#endif + return BlitRGBtoRGBSurfaceAlpha; + } + } +#if SDL_ALTIVEC_BLITTERS + if((sf->BytesPerPixel == 4) && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32SurfaceAlphaAltivec; + else +#endif + return BlitNtoNSurfaceAlpha; + + case 3: + default: + return BlitNtoNSurfaceAlpha; + } + } + } else { + /* Per-pixel alpha blits */ + switch(df->BytesPerPixel) { + case 1: + return BlitNto1PixelAlpha; + + case 2: +#if SDL_ALTIVEC_BLITTERS + if(sf->BytesPerPixel == 4 && !(surface->map->dst->flags & SDL_HWSURFACE) && + df->Gmask == 0x7e0 && + df->Bmask == 0x1f && SDL_HasAltiVec()) + return Blit32to565PixelAlphaAltivec; + else +#endif + if(sf->BytesPerPixel == 4 && sf->Amask == 0xff000000 + && sf->Gmask == 0xff00 + && ((sf->Rmask == 0xff && df->Rmask == 0x1f) + || (sf->Bmask == 0xff && df->Bmask == 0x1f))) { + if(df->Gmask == 0x7e0) + return BlitARGBto565PixelAlpha; + else if(df->Gmask == 0x3e0) + return BlitARGBto555PixelAlpha; + } + return BlitNtoNPixelAlpha; + + case 4: + if(sf->Rmask == df->Rmask + && sf->Gmask == df->Gmask + && sf->Bmask == df->Bmask + && sf->BytesPerPixel == 4) + { +#if MMX_ASMBLIT + if(sf->Rshift % 8 == 0 + && sf->Gshift % 8 == 0 + && sf->Bshift % 8 == 0 + && sf->Ashift % 8 == 0 + && sf->Aloss == 0) + { + if(SDL_Has3DNow()) + return BlitRGBtoRGBPixelAlphaMMX3DNOW; + if(SDL_HasMMX()) + return BlitRGBtoRGBPixelAlphaMMX; + } +#endif + if(sf->Amask == 0xff000000) + { +#if SDL_ALTIVEC_BLITTERS + if(!(surface->map->dst->flags & SDL_HWSURFACE) + && SDL_HasAltiVec()) + return BlitRGBtoRGBPixelAlphaAltivec; +#endif + return BlitRGBtoRGBPixelAlpha; + } + } +#if SDL_ALTIVEC_BLITTERS + if (sf->Amask && sf->BytesPerPixel == 4 && + !(surface->map->dst->flags & SDL_HWSURFACE) && SDL_HasAltiVec()) + return Blit32to32PixelAlphaAltivec; + else +#endif + return BlitNtoNPixelAlpha; + + case 3: + default: + return BlitNtoNPixelAlpha; + } + } +} + diff --git a/3rdparty/SDL/src/video/SDL_blit_N.c b/3rdparty/SDL/src/video/SDL_blit_N.c new file mode 100644 index 0000000..858cee5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_blit_N.c @@ -0,0 +1,2492 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_endian.h" +#include "SDL_cpuinfo.h" +#include "SDL_blit.h" + +/* Functions to blit from N-bit surfaces to other surfaces */ + +#if SDL_ALTIVEC_BLITTERS +#if __MWERKS__ +#pragma altivec_model on +#endif +#ifdef HAVE_ALTIVEC_H +#include <altivec.h> +#endif +#define assert(X) +#ifdef __MACOSX__ +#include <sys/sysctl.h> +static size_t GetL3CacheSize( void ) +{ + const char key[] = "hw.l3cachesize"; + u_int64_t result = 0; + size_t typeSize = sizeof( result ); + + + int err = sysctlbyname( key, &result, &typeSize, NULL, 0 ); + if( 0 != err ) return 0; + + return result; +} +#else +static size_t GetL3CacheSize( void ) +{ + /* XXX: Just guess G4 */ + return 2097152; +} +#endif /* __MACOSX__ */ + +#if (defined(__MACOSX__) && (__GNUC__ < 4)) + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) ( a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p ) + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) ( a,b,c,d,e,f,g,h ) +#else + #define VECUINT8_LITERAL(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ + (vector unsigned char) { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p } + #define VECUINT16_LITERAL(a,b,c,d,e,f,g,h) \ + (vector unsigned short) { a,b,c,d,e,f,g,h } +#endif + +#define UNALIGNED_PTR(x) (((size_t) x) & 0x0000000F) +#define VSWIZZLE32(a,b,c,d) (vector unsigned char) \ + ( 0x00+a, 0x00+b, 0x00+c, 0x00+d, \ + 0x04+a, 0x04+b, 0x04+c, 0x04+d, \ + 0x08+a, 0x08+b, 0x08+c, 0x08+d, \ + 0x0C+a, 0x0C+b, 0x0C+c, 0x0C+d ) + +#define MAKE8888(dstfmt, r, g, b, a) \ + ( ((r<<dstfmt->Rshift)&dstfmt->Rmask) | \ + ((g<<dstfmt->Gshift)&dstfmt->Gmask) | \ + ((b<<dstfmt->Bshift)&dstfmt->Bmask) | \ + ((a<<dstfmt->Ashift)&dstfmt->Amask) ) + +/* + * Data Stream Touch...Altivec cache prefetching. + * + * Don't use this on a G5...however, the speed boost is very significant + * on a G4. + */ +#define DST_CHAN_SRC 1 +#define DST_CHAN_DEST 2 + +/* macro to set DST control word value... */ +#define DST_CTRL(size, count, stride) \ + (((size) << 24) | ((count) << 16) | (stride)) + +#define VEC_ALIGNER(src) ((UNALIGNED_PTR(src)) \ + ? vec_lvsl(0, src) \ + : vec_add(vec_lvsl(8, src), vec_splat_u8(8))) + +/* Calculate the permute vector used for 32->32 swizzling */ +static vector unsigned char calc_swizzle32(const SDL_PixelFormat *srcfmt, + const SDL_PixelFormat *dstfmt) +{ + /* + * We have to assume that the bits that aren't used by other + * colors is alpha, and it's one complete byte, since some formats + * leave alpha with a zero mask, but we should still swizzle the bits. + */ + /* ARGB */ + const static struct SDL_PixelFormat default_pixel_format = { + NULL, 0, 0, + 0, 0, 0, 0, + 16, 8, 0, 24, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, + 0, 0}; + if (!srcfmt) { + srcfmt = &default_pixel_format; + } + if (!dstfmt) { + dstfmt = &default_pixel_format; + } + const vector unsigned char plus = VECUINT8_LITERAL( + 0x00, 0x00, 0x00, 0x00, + 0x04, 0x04, 0x04, 0x04, + 0x08, 0x08, 0x08, 0x08, + 0x0C, 0x0C, 0x0C, 0x0C ); + vector unsigned char vswiz; + vector unsigned int srcvec; +#define RESHIFT(X) (3 - ((X) >> 3)) + Uint32 rmask = RESHIFT(srcfmt->Rshift) << (dstfmt->Rshift); + Uint32 gmask = RESHIFT(srcfmt->Gshift) << (dstfmt->Gshift); + Uint32 bmask = RESHIFT(srcfmt->Bshift) << (dstfmt->Bshift); + Uint32 amask; + /* Use zero for alpha if either surface doesn't have alpha */ + if (dstfmt->Amask) { + amask = ((srcfmt->Amask) ? RESHIFT(srcfmt->Ashift) : 0x10) << (dstfmt->Ashift); + } else { + amask = 0x10101010 & ((dstfmt->Rmask | dstfmt->Gmask | dstfmt->Bmask) ^ 0xFFFFFFFF); + } +#undef RESHIFT + ((unsigned int *)(char*)&srcvec)[0] = (rmask | gmask | bmask | amask); + vswiz = vec_add(plus, (vector unsigned char)vec_splat(srcvec, 0)); + return(vswiz); +} + +static void Blit_RGB888_RGB565(SDL_BlitInfo *info); +static void Blit_RGB888_RGB565Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + vector unsigned char valpha = vec_splat_u8(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, NULL); + vector unsigned char vgmerge = VECUINT8_LITERAL( + 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x0e, + 0x00, 0x12, 0x00, 0x16, + 0x00, 0x1a, 0x00, 0x1e); + vector unsigned short v1 = vec_splat_u16(1); + vector unsigned short v3 = vec_splat_u16(3); + vector unsigned short v3f = VECUINT16_LITERAL( + 0x003f, 0x003f, 0x003f, 0x003f, + 0x003f, 0x003f, 0x003f, 0x003f); + vector unsigned short vfc = VECUINT16_LITERAL( + 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc); + vector unsigned short vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, sA; \ + DISEMBLE_RGBA((Uint8 *)src, 4, srcfmt, Pixel, \ + sR, sG, sB, sA); \ + *(Uint16 *)(dst) = (((sR << 8) & 0x0000F800) | \ + ((sG << 3) & 0x000007E0) | \ + ((sB >> 3) & 0x0000001F)); \ + dst += 2; \ + src += 4; \ + widthvar--; \ + } + + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vpixel, vrpixel, vgpixel, vbpixel; + vector unsigned int vsrc1, vsrc2; + vector unsigned char vdst; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc1 = (vector unsigned int)vec_perm(vsrc, valpha, vpermute); + src += 16; + vsrc = voverflow; + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + vsrc2 = (vector unsigned int)vec_perm(vsrc, valpha, vpermute); + /* 1555 */ + vpixel = (vector unsigned short)vec_packpx(vsrc1, vsrc2); + vgpixel = (vector unsigned short)vec_perm(vsrc1, vsrc2, vgmerge); + vgpixel = vec_and(vgpixel, vfc); + vgpixel = vec_sl(vgpixel, v3); + vrpixel = vec_sl(vpixel, v1); + vrpixel = vec_and(vrpixel, vf800); + vbpixel = vec_and(vpixel, v3f); + vdst = vec_or((vector unsigned char)vrpixel, (vector unsigned char)vgpixel); + /* 565 */ + vdst = vec_or(vdst, (vector unsigned char)vbpixel); + vec_st(vdst, 0, dst); + + width -= 8; + src += 16; + dst += 16; + vsrc = voverflow; + } + + assert(width == 0); + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + + +} + +static void Blit_RGB565_32Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned alpha; + vector unsigned char valpha; + vector unsigned char vpermute; + vector unsigned short vf800; + vector unsigned int v8 = vec_splat_u32(8); + vector unsigned int v16 = vec_add(v8, v8); + vector unsigned short v2 = vec_splat_u16(2); + vector unsigned short v3 = vec_splat_u16(3); + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char) ( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8, v16)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8, v8)) + ); + + + assert(srcfmt->BytesPerPixel == 2); + assert(dstfmt->BytesPerPixel == 4); + + vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + if (dstfmt->Amask && srcfmt->alpha) { + ((unsigned char *)&valpha)[0] = alpha = srcfmt->alpha; + valpha = vec_splat(valpha, 0); + } else { + alpha = 0; + valpha = vec_splat_u8(0); + } + + vpermute = calc_swizzle32(NULL, dstfmt); + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + unsigned sR, sG, sB; \ + unsigned short Pixel = *((unsigned short *)src); \ + sR = (Pixel >> 8) & 0xf8; \ + sG = (Pixel >> 3) & 0xfc; \ + sB = (Pixel << 3) & 0xf8; \ + ASSEMBLE_RGBA(dst, 4, dstfmt, sR, sG, sB, alpha); \ + src += 2; \ + dst += 4; \ + widthvar--; \ + } + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vR, vG, vB; + vector unsigned char vdst1, vdst2; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + + vR = vec_and((vector unsigned short)vsrc, vf800); + vB = vec_sl((vector unsigned short)vsrc, v3); + vG = vec_sl(vB, v2); + + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst1 = vec_perm(vdst1, valpha, vpermute); + vec_st(vdst1, 0, dst); + + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + vdst2 = vec_perm(vdst2, valpha, vpermute); + vec_st(vdst2, 16, dst); + + width -= 8; + dst += 32; + src += 16; + vsrc = voverflow; + } + + assert(width == 0); + + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + +} + + +static void Blit_RGB555_32Altivec(SDL_BlitInfo *info) { + int height = info->d_height; + Uint8 *src = (Uint8 *) info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = (Uint8 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + unsigned alpha; + vector unsigned char valpha; + vector unsigned char vpermute; + vector unsigned short vf800; + vector unsigned int v8 = vec_splat_u32(8); + vector unsigned int v16 = vec_add(v8, v8); + vector unsigned short v1 = vec_splat_u16(1); + vector unsigned short v3 = vec_splat_u16(3); + /* + 0x10 - 0x1f is the alpha + 0x00 - 0x0e evens are the red + 0x01 - 0x0f odds are zero + */ + vector unsigned char vredalpha1 = VECUINT8_LITERAL( + 0x10, 0x00, 0x01, 0x01, + 0x10, 0x02, 0x01, 0x01, + 0x10, 0x04, 0x01, 0x01, + 0x10, 0x06, 0x01, 0x01 + ); + vector unsigned char vredalpha2 = (vector unsigned char)( + vec_add((vector unsigned int)vredalpha1, vec_sl(v8, v16)) + ); + /* + 0x00 - 0x0f is ARxx ARxx ARxx ARxx + 0x11 - 0x0f odds are blue + */ + vector unsigned char vblue1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x02, 0x11, + 0x04, 0x05, 0x06, 0x13, + 0x08, 0x09, 0x0a, 0x15, + 0x0c, 0x0d, 0x0e, 0x17 + ); + vector unsigned char vblue2 = (vector unsigned char)( + vec_add((vector unsigned int)vblue1, v8) + ); + /* + 0x00 - 0x0f is ARxB ARxB ARxB ARxB + 0x10 - 0x0e evens are green + */ + vector unsigned char vgreen1 = VECUINT8_LITERAL( + 0x00, 0x01, 0x10, 0x03, + 0x04, 0x05, 0x12, 0x07, + 0x08, 0x09, 0x14, 0x0b, + 0x0c, 0x0d, 0x16, 0x0f + ); + vector unsigned char vgreen2 = (vector unsigned char)( + vec_add((vector unsigned int)vgreen1, vec_sl(v8, v8)) + ); + + + assert(srcfmt->BytesPerPixel == 2); + assert(dstfmt->BytesPerPixel == 4); + + vf800 = (vector unsigned short)vec_splat_u8(-7); + vf800 = vec_sl(vf800, vec_splat_u16(8)); + + if (dstfmt->Amask && srcfmt->alpha) { + ((unsigned char *)&valpha)[0] = alpha = srcfmt->alpha; + valpha = vec_splat(valpha, 0); + } else { + alpha = 0; + valpha = vec_splat_u8(0); + } + + vpermute = calc_swizzle32(NULL, dstfmt); + while (height--) { + vector unsigned char valigner; + vector unsigned char voverflow; + vector unsigned char vsrc; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ +#define ONE_PIXEL_BLEND(condition, widthvar) \ + while (condition) { \ + unsigned sR, sG, sB; \ + unsigned short Pixel = *((unsigned short *)src); \ + sR = (Pixel >> 7) & 0xf8; \ + sG = (Pixel >> 2) & 0xf8; \ + sB = (Pixel << 3) & 0xf8; \ + ASSEMBLE_RGBA(dst, 4, dstfmt, sR, sG, sB, alpha); \ + src += 2; \ + dst += 4; \ + widthvar--; \ + } + ONE_PIXEL_BLEND(((UNALIGNED_PTR(dst)) && (width)), width); + + /* After all that work, here's the vector part! */ + extrawidth = (width % 8); /* trailing unaligned stores */ + width -= extrawidth; + vsrc = vec_ld(0, src); + valigner = VEC_ALIGNER(src); + + while (width) { + vector unsigned short vR, vG, vB; + vector unsigned char vdst1, vdst2; + + voverflow = vec_ld(15, src); + vsrc = vec_perm(vsrc, voverflow, valigner); + + vR = vec_and(vec_sl((vector unsigned short)vsrc,v1), vf800); + vB = vec_sl((vector unsigned short)vsrc, v3); + vG = vec_sl(vB, v3); + + vdst1 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vB, vblue1); + vdst1 = vec_perm(vdst1, (vector unsigned char)vG, vgreen1); + vdst1 = vec_perm(vdst1, valpha, vpermute); + vec_st(vdst1, 0, dst); + + vdst2 = (vector unsigned char)vec_perm((vector unsigned char)vR, valpha, vredalpha2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vB, vblue2); + vdst2 = vec_perm(vdst2, (vector unsigned char)vG, vgreen2); + vdst2 = vec_perm(vdst2, valpha, vpermute); + vec_st(vdst2, 16, dst); + + width -= 8; + dst += 32; + src += 16; + vsrc = voverflow; + } + + assert(width == 0); + + + /* do scalar until we can align... */ + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + + src += srcskip; /* move to next row, accounting for pitch. */ + dst += dstskip; + } + +} + +static void BlitNtoNKey(SDL_BlitInfo *info); +static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info); +static void Blit32to32KeyAltivec(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint32 *srcp = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dstp = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + int copy_alpha = (srcfmt->Amask && dstfmt->Amask); + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + Uint32 rgbmask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + Uint32 ckey = info->src->colorkey; + vector unsigned int valpha; + vector unsigned char vpermute; + vector unsigned char vzero; + vector unsigned int vckey; + vector unsigned int vrgbmask; + vpermute = calc_swizzle32(srcfmt, dstfmt); + if (info->d_width < 16) { + if(copy_alpha) { + BlitNtoNKeyCopyAlpha(info); + } else { + BlitNtoNKey(info); + } + return; + } + vzero = vec_splat_u8(0); + if (alpha) { + ((unsigned char *)&valpha)[0] = (unsigned char)alpha; + valpha = (vector unsigned int)vec_splat((vector unsigned char)valpha, 0); + } else { + valpha = (vector unsigned int)vzero; + } + ckey &= rgbmask; + ((unsigned int *)(char*)&vckey)[0] = ckey; + vckey = vec_splat(vckey, 0); + ((unsigned int *)(char*)&vrgbmask)[0] = rgbmask; + vrgbmask = vec_splat(vrgbmask, 0); + + while (height--) { +#define ONE_PIXEL_BLEND(condition, widthvar) \ + if (copy_alpha) { \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB, sA; \ + DISEMBLE_RGBA((Uint8 *)srcp, srcbpp, srcfmt, Pixel, \ + sR, sG, sB, sA); \ + if ( (Pixel & rgbmask) != ckey ) { \ + ASSEMBLE_RGBA((Uint8 *)dstp, dstbpp, dstfmt, \ + sR, sG, sB, sA); \ + } \ + dstp = (Uint32 *) (((Uint8 *) dstp) + dstbpp); \ + srcp = (Uint32 *) (((Uint8 *) srcp) + srcbpp); \ + widthvar--; \ + } \ + } else { \ + while (condition) { \ + Uint32 Pixel; \ + unsigned sR, sG, sB; \ + RETRIEVE_RGB_PIXEL((Uint8 *)srcp, srcbpp, Pixel); \ + if ( Pixel != ckey ) { \ + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); \ + ASSEMBLE_RGBA((Uint8 *)dstp, dstbpp, dstfmt, \ + sR, sG, sB, alpha); \ + } \ + dstp = (Uint32 *) (((Uint8 *)dstp) + dstbpp); \ + srcp = (Uint32 *) (((Uint8 *)srcp) + srcbpp); \ + widthvar--; \ + } \ + } + int width = info->d_width; + ONE_PIXEL_BLEND((UNALIGNED_PTR(dstp)) && (width), width); + assert(width > 0); + if (width > 0) { + int extrawidth = (width % 4); + vector unsigned char valigner = VEC_ALIGNER(srcp); + vector unsigned int vs = vec_ld(0, srcp); + width -= extrawidth; + assert(width >= 4); + while (width) { + vector unsigned char vsel; + vector unsigned int vd; + vector unsigned int voverflow = vec_ld(15, srcp); + /* load the source vec */ + vs = vec_perm(vs, voverflow, valigner); + /* vsel is set for items that match the key */ + vsel = (vector unsigned char)vec_and(vs, vrgbmask); + vsel = (vector unsigned char)vec_cmpeq(vs, vckey); + /* permute the src vec to the dest format */ + vs = vec_perm(vs, valpha, vpermute); + /* load the destination vec */ + vd = vec_ld(0, dstp); + /* select the source and dest into vs */ + vd = (vector unsigned int)vec_sel((vector unsigned char)vs, (vector unsigned char)vd, vsel); + + vec_st(vd, 0, dstp); + srcp += 4; + width -= 4; + dstp += 4; + vs = voverflow; + } + ONE_PIXEL_BLEND((extrawidth), extrawidth); +#undef ONE_PIXEL_BLEND + srcp += srcskip >> 2; + dstp += dstskip >> 2; + } + } +} + +/* Altivec code to swizzle one 32-bit surface to a different 32-bit format. */ +/* Use this on a G5 */ +static void ConvertAltivec32to32_noprefetch(SDL_BlitInfo *info) +{ + int height = info->d_height; + Uint32 *src = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned int vzero = vec_splat_u32(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, dstfmt); + if (dstfmt->Amask && !srcfmt->Amask) { + if (srcfmt->alpha) { + vector unsigned char valpha; + ((unsigned char *)&valpha)[0] = srcfmt->alpha; + vzero = (vector unsigned int)vec_splat(valpha, 0); + } + } + + assert(srcfmt->BytesPerPixel == 4); + assert(dstfmt->BytesPerPixel == 4); + + while (height--) { + vector unsigned char valigner; + vector unsigned int vbits; + vector unsigned int voverflow; + Uint32 bits; + Uint8 r, g, b, a; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ + while ((UNALIGNED_PTR(dst)) && (width)) { + bits = *(src++); + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + width--; + } + + /* After all that work, here's the vector part! */ + extrawidth = (width % 4); + width -= extrawidth; + valigner = VEC_ALIGNER(src); + vbits = vec_ld(0, src); + + while (width) { + voverflow = vec_ld(15, src); + src += 4; + width -= 4; + vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */ + vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */ + vec_st(vbits, 0, dst); /* store it back out. */ + dst += 4; + vbits = voverflow; + } + + assert(width == 0); + + /* cover pixels at the end of the row that didn't fit in 16 bytes. */ + while (extrawidth) { + bits = *(src++); /* max 7 pixels, don't bother with prefetch. */ + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + extrawidth--; + } + + src += srcskip >> 2; /* move to next row, accounting for pitch. */ + dst += dstskip >> 2; + } + +} + +/* Altivec code to swizzle one 32-bit surface to a different 32-bit format. */ +/* Use this on a G4 */ +static void ConvertAltivec32to32_prefetch(SDL_BlitInfo *info) +{ + const int scalar_dst_lead = sizeof (Uint32) * 4; + const int vector_dst_lead = sizeof (Uint32) * 16; + + int height = info->d_height; + Uint32 *src = (Uint32 *) info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *) info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + vector unsigned int vzero = vec_splat_u32(0); + vector unsigned char vpermute = calc_swizzle32(srcfmt, dstfmt); + if (dstfmt->Amask && !srcfmt->Amask) { + if (srcfmt->alpha) { + vector unsigned char valpha; + ((unsigned char *)&valpha)[0] = srcfmt->alpha; + vzero = (vector unsigned int)vec_splat(valpha, 0); + } + } + + assert(srcfmt->BytesPerPixel == 4); + assert(dstfmt->BytesPerPixel == 4); + + while (height--) { + vector unsigned char valigner; + vector unsigned int vbits; + vector unsigned int voverflow; + Uint32 bits; + Uint8 r, g, b, a; + + int width = info->d_width; + int extrawidth; + + /* do scalar until we can align... */ + while ((UNALIGNED_PTR(dst)) && (width)) { + vec_dstt(src+scalar_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_SRC); + vec_dstst(dst+scalar_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_DEST); + bits = *(src++); + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + width--; + } + + /* After all that work, here's the vector part! */ + extrawidth = (width % 4); + width -= extrawidth; + valigner = VEC_ALIGNER(src); + vbits = vec_ld(0, src); + + while (width) { + vec_dstt(src+vector_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_SRC); + vec_dstst(dst+vector_dst_lead, DST_CTRL(2,32,1024), DST_CHAN_DEST); + voverflow = vec_ld(15, src); + src += 4; + width -= 4; + vbits = vec_perm(vbits, voverflow, valigner); /* src is ready. */ + vbits = vec_perm(vbits, vzero, vpermute); /* swizzle it. */ + vec_st(vbits, 0, dst); /* store it back out. */ + dst += 4; + vbits = voverflow; + } + + assert(width == 0); + + /* cover pixels at the end of the row that didn't fit in 16 bytes. */ + while (extrawidth) { + bits = *(src++); /* max 7 pixels, don't bother with prefetch. */ + RGBA_FROM_8888(bits, srcfmt, r, g, b, a); + *(dst++) = MAKE8888(dstfmt, r, g, b, a); + extrawidth--; + } + + src += srcskip >> 2; /* move to next row, accounting for pitch. */ + dst += dstskip >> 2; + } + + vec_dss(DST_CHAN_SRC); + vec_dss(DST_CHAN_DEST); +} + +static Uint32 GetBlitFeatures( void ) +{ + static Uint32 features = 0xffffffff; + if (features == 0xffffffff) { + /* Provide an override for testing .. */ + char *override = SDL_getenv("SDL_ALTIVEC_BLIT_FEATURES"); + if (override) { + features = 0; + SDL_sscanf(override, "%u", &features); + } else { + features = ( 0 + /* Feature 1 is has-MMX */ + | ((SDL_HasMMX()) ? 1 : 0) + /* Feature 2 is has-AltiVec */ + | ((SDL_HasAltiVec()) ? 2 : 0) + /* Feature 4 is dont-use-prefetch */ + /* !!!! FIXME: Check for G5 or later, not the cache size! Always prefetch on a G4. */ + | ((GetL3CacheSize() == 0) ? 4 : 0) + ); + } + } + return features; +} +#if __MWERKS__ +#pragma altivec_model off +#endif +#else +/* Feature 1 is has-MMX */ +#define GetBlitFeatures() ((Uint32)(SDL_HasMMX() ? 1 : 0)) +#endif + +/* This is now endian dependent */ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define HI 1 +#define LO 0 +#else /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ +#define HI 0 +#define LO 1 +#endif + +#if SDL_HERMES_BLITTERS + +/* Heheheh, we coerce Hermes into using SDL blit information */ +#define X86_ASSEMBLER +#define HermesConverterInterface SDL_BlitInfo +#define HermesClearInterface void +#define STACKCALL + +#include "../hermes/HeadMMX.h" +#include "../hermes/HeadX86.h" + +#else + +/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ +#define RGB888_RGB332(dst, src) { \ + dst = (Uint8)((((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6)); \ +} +static void Blit_RGB888_index8(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + + if ( map == NULL ) { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + RGB888_RGB332(*dst++, *src); + , width); +#else + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + RGB888_RGB332(*dst++, *src); + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(*dst++, *src); + ++src; + case 2: + RGB888_RGB332(*dst++, *src); + ++src; + case 1: + RGB888_RGB332(*dst++, *src); + ++src; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } else { + int Pixel; + + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); +#else + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 2: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 1: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } +} +/* Special optimized blit for RGB 8-8-8 --> RGB 5-5-5 */ +#define RGB888_RGB555(dst, src) { \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>9)| \ + (((*src)&0x0000F800)>>6)| \ + (((*src)&0x000000F8)>>3)); \ +} +#define RGB888_RGB555_TWO(dst, src) { \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>9)| \ + (((src[HI])&0x0000F800)>>6)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>9)| \ + (((src[LO])&0x0000F800)>>6)| \ + (((src[LO])&0x000000F8)>>3); \ +} +static void Blit_RGB888_RGB555(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + Uint16 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB555(dst, src); + ++src; + ++dst; + , width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + RGB888_RGB555(dst, src); + ++src; + ++dst; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB555(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB555(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB555(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB555_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB555(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} +/* Special optimized blit for RGB 8-8-8 --> RGB 5-6-5 */ +#define RGB888_RGB565(dst, src) { \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>8)| \ + (((*src)&0x0000FC00)>>5)| \ + (((*src)&0x000000F8)>>3)); \ +} +#define RGB888_RGB565_TWO(dst, src) { \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>8)| \ + (((src[HI])&0x0000FC00)>>5)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>8)| \ + (((src[LO])&0x0000FC00)>>5)| \ + (((src[LO])&0x000000F8)>>3); \ +} +static void Blit_RGB888_RGB565(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint32 *src; + Uint16 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = (Uint16 *)info->d_pixels; + dstskip = info->d_skip/2; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB565(dst, src); + ++src; + ++dst; + , width); + src += srcskip; + dst += dstskip; + } +#else + /* Memory align at 4-byte boundary, if necessary */ + if ( (long)dst & 0x03 ) { + /* Don't do anything if width is 0 */ + if ( width == 0 ) { + return; + } + --width; + + while ( height-- ) { + /* Perform copy alignment */ + RGB888_RGB565(dst, src); + ++src; + ++dst; + + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB565(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB565(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + RGB888_RGB565(dst, src); + ++src; + ++dst; + case 2: + RGB888_RGB565_TWO(dst, src); + src += 2; + dst += 2; + break; + case 1: + RGB888_RGB565(dst, src); + ++src; + ++dst; + break; + } + src += srcskip; + dst += dstskip; + } + } +#endif /* USE_DUFFS_LOOP */ +} + +#endif /* SDL_HERMES_BLITTERS */ + + +/* Special optimized blit for RGB 5-6-5 --> 32-bit RGB surfaces */ +#define RGB565_32(dst, src, map) (map[src[LO]*2] + map[src[HI]*2+1]) +static void Blit_RGB565_32(SDL_BlitInfo *info, const Uint32 *map) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + Uint32 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint8 *)info->s_pixels; + srcskip = info->s_skip; + dst = (Uint32 *)info->d_pixels; + dstskip = info->d_skip/4; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + { + *dst++ = RGB565_32(dst, src, map); + src += 2; + }, + width); + src += srcskip; + dst += dstskip; + } +#else + while ( height-- ) { + /* Copy in 4 pixel chunks */ + for ( c=width/4; c; --c ) { + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + *dst++ = RGB565_32(dst, src, map); + src += 2; + } + /* Get any leftovers */ + switch (width & 3) { + case 3: + *dst++ = RGB565_32(dst, src, map); + src += 2; + case 2: + *dst++ = RGB565_32(dst, src, map); + src += 2; + case 1: + *dst++ = RGB565_32(dst, src, map); + src += 2; + break; + } + src += srcskip; + dst += dstskip; + } +#endif /* USE_DUFFS_LOOP */ +} + +/* Special optimized blit for RGB 5-6-5 --> ARGB 8-8-8-8 */ +static const Uint32 RGB565_ARGB8888_LUT[512] = { + 0x00000000, 0xff000000, 0x00000008, 0xff002000, + 0x00000010, 0xff004000, 0x00000018, 0xff006100, + 0x00000020, 0xff008100, 0x00000029, 0xff00a100, + 0x00000031, 0xff00c200, 0x00000039, 0xff00e200, + 0x00000041, 0xff080000, 0x0000004a, 0xff082000, + 0x00000052, 0xff084000, 0x0000005a, 0xff086100, + 0x00000062, 0xff088100, 0x0000006a, 0xff08a100, + 0x00000073, 0xff08c200, 0x0000007b, 0xff08e200, + 0x00000083, 0xff100000, 0x0000008b, 0xff102000, + 0x00000094, 0xff104000, 0x0000009c, 0xff106100, + 0x000000a4, 0xff108100, 0x000000ac, 0xff10a100, + 0x000000b4, 0xff10c200, 0x000000bd, 0xff10e200, + 0x000000c5, 0xff180000, 0x000000cd, 0xff182000, + 0x000000d5, 0xff184000, 0x000000de, 0xff186100, + 0x000000e6, 0xff188100, 0x000000ee, 0xff18a100, + 0x000000f6, 0xff18c200, 0x000000ff, 0xff18e200, + 0x00000400, 0xff200000, 0x00000408, 0xff202000, + 0x00000410, 0xff204000, 0x00000418, 0xff206100, + 0x00000420, 0xff208100, 0x00000429, 0xff20a100, + 0x00000431, 0xff20c200, 0x00000439, 0xff20e200, + 0x00000441, 0xff290000, 0x0000044a, 0xff292000, + 0x00000452, 0xff294000, 0x0000045a, 0xff296100, + 0x00000462, 0xff298100, 0x0000046a, 0xff29a100, + 0x00000473, 0xff29c200, 0x0000047b, 0xff29e200, + 0x00000483, 0xff310000, 0x0000048b, 0xff312000, + 0x00000494, 0xff314000, 0x0000049c, 0xff316100, + 0x000004a4, 0xff318100, 0x000004ac, 0xff31a100, + 0x000004b4, 0xff31c200, 0x000004bd, 0xff31e200, + 0x000004c5, 0xff390000, 0x000004cd, 0xff392000, + 0x000004d5, 0xff394000, 0x000004de, 0xff396100, + 0x000004e6, 0xff398100, 0x000004ee, 0xff39a100, + 0x000004f6, 0xff39c200, 0x000004ff, 0xff39e200, + 0x00000800, 0xff410000, 0x00000808, 0xff412000, + 0x00000810, 0xff414000, 0x00000818, 0xff416100, + 0x00000820, 0xff418100, 0x00000829, 0xff41a100, + 0x00000831, 0xff41c200, 0x00000839, 0xff41e200, + 0x00000841, 0xff4a0000, 0x0000084a, 0xff4a2000, + 0x00000852, 0xff4a4000, 0x0000085a, 0xff4a6100, + 0x00000862, 0xff4a8100, 0x0000086a, 0xff4aa100, + 0x00000873, 0xff4ac200, 0x0000087b, 0xff4ae200, + 0x00000883, 0xff520000, 0x0000088b, 0xff522000, + 0x00000894, 0xff524000, 0x0000089c, 0xff526100, + 0x000008a4, 0xff528100, 0x000008ac, 0xff52a100, + 0x000008b4, 0xff52c200, 0x000008bd, 0xff52e200, + 0x000008c5, 0xff5a0000, 0x000008cd, 0xff5a2000, + 0x000008d5, 0xff5a4000, 0x000008de, 0xff5a6100, + 0x000008e6, 0xff5a8100, 0x000008ee, 0xff5aa100, + 0x000008f6, 0xff5ac200, 0x000008ff, 0xff5ae200, + 0x00000c00, 0xff620000, 0x00000c08, 0xff622000, + 0x00000c10, 0xff624000, 0x00000c18, 0xff626100, + 0x00000c20, 0xff628100, 0x00000c29, 0xff62a100, + 0x00000c31, 0xff62c200, 0x00000c39, 0xff62e200, + 0x00000c41, 0xff6a0000, 0x00000c4a, 0xff6a2000, + 0x00000c52, 0xff6a4000, 0x00000c5a, 0xff6a6100, + 0x00000c62, 0xff6a8100, 0x00000c6a, 0xff6aa100, + 0x00000c73, 0xff6ac200, 0x00000c7b, 0xff6ae200, + 0x00000c83, 0xff730000, 0x00000c8b, 0xff732000, + 0x00000c94, 0xff734000, 0x00000c9c, 0xff736100, + 0x00000ca4, 0xff738100, 0x00000cac, 0xff73a100, + 0x00000cb4, 0xff73c200, 0x00000cbd, 0xff73e200, + 0x00000cc5, 0xff7b0000, 0x00000ccd, 0xff7b2000, + 0x00000cd5, 0xff7b4000, 0x00000cde, 0xff7b6100, + 0x00000ce6, 0xff7b8100, 0x00000cee, 0xff7ba100, + 0x00000cf6, 0xff7bc200, 0x00000cff, 0xff7be200, + 0x00001000, 0xff830000, 0x00001008, 0xff832000, + 0x00001010, 0xff834000, 0x00001018, 0xff836100, + 0x00001020, 0xff838100, 0x00001029, 0xff83a100, + 0x00001031, 0xff83c200, 0x00001039, 0xff83e200, + 0x00001041, 0xff8b0000, 0x0000104a, 0xff8b2000, + 0x00001052, 0xff8b4000, 0x0000105a, 0xff8b6100, + 0x00001062, 0xff8b8100, 0x0000106a, 0xff8ba100, + 0x00001073, 0xff8bc200, 0x0000107b, 0xff8be200, + 0x00001083, 0xff940000, 0x0000108b, 0xff942000, + 0x00001094, 0xff944000, 0x0000109c, 0xff946100, + 0x000010a4, 0xff948100, 0x000010ac, 0xff94a100, + 0x000010b4, 0xff94c200, 0x000010bd, 0xff94e200, + 0x000010c5, 0xff9c0000, 0x000010cd, 0xff9c2000, + 0x000010d5, 0xff9c4000, 0x000010de, 0xff9c6100, + 0x000010e6, 0xff9c8100, 0x000010ee, 0xff9ca100, + 0x000010f6, 0xff9cc200, 0x000010ff, 0xff9ce200, + 0x00001400, 0xffa40000, 0x00001408, 0xffa42000, + 0x00001410, 0xffa44000, 0x00001418, 0xffa46100, + 0x00001420, 0xffa48100, 0x00001429, 0xffa4a100, + 0x00001431, 0xffa4c200, 0x00001439, 0xffa4e200, + 0x00001441, 0xffac0000, 0x0000144a, 0xffac2000, + 0x00001452, 0xffac4000, 0x0000145a, 0xffac6100, + 0x00001462, 0xffac8100, 0x0000146a, 0xffaca100, + 0x00001473, 0xffacc200, 0x0000147b, 0xfface200, + 0x00001483, 0xffb40000, 0x0000148b, 0xffb42000, + 0x00001494, 0xffb44000, 0x0000149c, 0xffb46100, + 0x000014a4, 0xffb48100, 0x000014ac, 0xffb4a100, + 0x000014b4, 0xffb4c200, 0x000014bd, 0xffb4e200, + 0x000014c5, 0xffbd0000, 0x000014cd, 0xffbd2000, + 0x000014d5, 0xffbd4000, 0x000014de, 0xffbd6100, + 0x000014e6, 0xffbd8100, 0x000014ee, 0xffbda100, + 0x000014f6, 0xffbdc200, 0x000014ff, 0xffbde200, + 0x00001800, 0xffc50000, 0x00001808, 0xffc52000, + 0x00001810, 0xffc54000, 0x00001818, 0xffc56100, + 0x00001820, 0xffc58100, 0x00001829, 0xffc5a100, + 0x00001831, 0xffc5c200, 0x00001839, 0xffc5e200, + 0x00001841, 0xffcd0000, 0x0000184a, 0xffcd2000, + 0x00001852, 0xffcd4000, 0x0000185a, 0xffcd6100, + 0x00001862, 0xffcd8100, 0x0000186a, 0xffcda100, + 0x00001873, 0xffcdc200, 0x0000187b, 0xffcde200, + 0x00001883, 0xffd50000, 0x0000188b, 0xffd52000, + 0x00001894, 0xffd54000, 0x0000189c, 0xffd56100, + 0x000018a4, 0xffd58100, 0x000018ac, 0xffd5a100, + 0x000018b4, 0xffd5c200, 0x000018bd, 0xffd5e200, + 0x000018c5, 0xffde0000, 0x000018cd, 0xffde2000, + 0x000018d5, 0xffde4000, 0x000018de, 0xffde6100, + 0x000018e6, 0xffde8100, 0x000018ee, 0xffdea100, + 0x000018f6, 0xffdec200, 0x000018ff, 0xffdee200, + 0x00001c00, 0xffe60000, 0x00001c08, 0xffe62000, + 0x00001c10, 0xffe64000, 0x00001c18, 0xffe66100, + 0x00001c20, 0xffe68100, 0x00001c29, 0xffe6a100, + 0x00001c31, 0xffe6c200, 0x00001c39, 0xffe6e200, + 0x00001c41, 0xffee0000, 0x00001c4a, 0xffee2000, + 0x00001c52, 0xffee4000, 0x00001c5a, 0xffee6100, + 0x00001c62, 0xffee8100, 0x00001c6a, 0xffeea100, + 0x00001c73, 0xffeec200, 0x00001c7b, 0xffeee200, + 0x00001c83, 0xfff60000, 0x00001c8b, 0xfff62000, + 0x00001c94, 0xfff64000, 0x00001c9c, 0xfff66100, + 0x00001ca4, 0xfff68100, 0x00001cac, 0xfff6a100, + 0x00001cb4, 0xfff6c200, 0x00001cbd, 0xfff6e200, + 0x00001cc5, 0xffff0000, 0x00001ccd, 0xffff2000, + 0x00001cd5, 0xffff4000, 0x00001cde, 0xffff6100, + 0x00001ce6, 0xffff8100, 0x00001cee, 0xffffa100, + 0x00001cf6, 0xffffc200, 0x00001cff, 0xffffe200 +}; +static void Blit_RGB565_ARGB8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_ARGB8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> ABGR 8-8-8-8 */ +static const Uint32 RGB565_ABGR8888_LUT[512] = { + 0xff000000, 0x00000000, 0xff080000, 0x00002000, + 0xff100000, 0x00004000, 0xff180000, 0x00006100, + 0xff200000, 0x00008100, 0xff290000, 0x0000a100, + 0xff310000, 0x0000c200, 0xff390000, 0x0000e200, + 0xff410000, 0x00000008, 0xff4a0000, 0x00002008, + 0xff520000, 0x00004008, 0xff5a0000, 0x00006108, + 0xff620000, 0x00008108, 0xff6a0000, 0x0000a108, + 0xff730000, 0x0000c208, 0xff7b0000, 0x0000e208, + 0xff830000, 0x00000010, 0xff8b0000, 0x00002010, + 0xff940000, 0x00004010, 0xff9c0000, 0x00006110, + 0xffa40000, 0x00008110, 0xffac0000, 0x0000a110, + 0xffb40000, 0x0000c210, 0xffbd0000, 0x0000e210, + 0xffc50000, 0x00000018, 0xffcd0000, 0x00002018, + 0xffd50000, 0x00004018, 0xffde0000, 0x00006118, + 0xffe60000, 0x00008118, 0xffee0000, 0x0000a118, + 0xfff60000, 0x0000c218, 0xffff0000, 0x0000e218, + 0xff000400, 0x00000020, 0xff080400, 0x00002020, + 0xff100400, 0x00004020, 0xff180400, 0x00006120, + 0xff200400, 0x00008120, 0xff290400, 0x0000a120, + 0xff310400, 0x0000c220, 0xff390400, 0x0000e220, + 0xff410400, 0x00000029, 0xff4a0400, 0x00002029, + 0xff520400, 0x00004029, 0xff5a0400, 0x00006129, + 0xff620400, 0x00008129, 0xff6a0400, 0x0000a129, + 0xff730400, 0x0000c229, 0xff7b0400, 0x0000e229, + 0xff830400, 0x00000031, 0xff8b0400, 0x00002031, + 0xff940400, 0x00004031, 0xff9c0400, 0x00006131, + 0xffa40400, 0x00008131, 0xffac0400, 0x0000a131, + 0xffb40400, 0x0000c231, 0xffbd0400, 0x0000e231, + 0xffc50400, 0x00000039, 0xffcd0400, 0x00002039, + 0xffd50400, 0x00004039, 0xffde0400, 0x00006139, + 0xffe60400, 0x00008139, 0xffee0400, 0x0000a139, + 0xfff60400, 0x0000c239, 0xffff0400, 0x0000e239, + 0xff000800, 0x00000041, 0xff080800, 0x00002041, + 0xff100800, 0x00004041, 0xff180800, 0x00006141, + 0xff200800, 0x00008141, 0xff290800, 0x0000a141, + 0xff310800, 0x0000c241, 0xff390800, 0x0000e241, + 0xff410800, 0x0000004a, 0xff4a0800, 0x0000204a, + 0xff520800, 0x0000404a, 0xff5a0800, 0x0000614a, + 0xff620800, 0x0000814a, 0xff6a0800, 0x0000a14a, + 0xff730800, 0x0000c24a, 0xff7b0800, 0x0000e24a, + 0xff830800, 0x00000052, 0xff8b0800, 0x00002052, + 0xff940800, 0x00004052, 0xff9c0800, 0x00006152, + 0xffa40800, 0x00008152, 0xffac0800, 0x0000a152, + 0xffb40800, 0x0000c252, 0xffbd0800, 0x0000e252, + 0xffc50800, 0x0000005a, 0xffcd0800, 0x0000205a, + 0xffd50800, 0x0000405a, 0xffde0800, 0x0000615a, + 0xffe60800, 0x0000815a, 0xffee0800, 0x0000a15a, + 0xfff60800, 0x0000c25a, 0xffff0800, 0x0000e25a, + 0xff000c00, 0x00000062, 0xff080c00, 0x00002062, + 0xff100c00, 0x00004062, 0xff180c00, 0x00006162, + 0xff200c00, 0x00008162, 0xff290c00, 0x0000a162, + 0xff310c00, 0x0000c262, 0xff390c00, 0x0000e262, + 0xff410c00, 0x0000006a, 0xff4a0c00, 0x0000206a, + 0xff520c00, 0x0000406a, 0xff5a0c00, 0x0000616a, + 0xff620c00, 0x0000816a, 0xff6a0c00, 0x0000a16a, + 0xff730c00, 0x0000c26a, 0xff7b0c00, 0x0000e26a, + 0xff830c00, 0x00000073, 0xff8b0c00, 0x00002073, + 0xff940c00, 0x00004073, 0xff9c0c00, 0x00006173, + 0xffa40c00, 0x00008173, 0xffac0c00, 0x0000a173, + 0xffb40c00, 0x0000c273, 0xffbd0c00, 0x0000e273, + 0xffc50c00, 0x0000007b, 0xffcd0c00, 0x0000207b, + 0xffd50c00, 0x0000407b, 0xffde0c00, 0x0000617b, + 0xffe60c00, 0x0000817b, 0xffee0c00, 0x0000a17b, + 0xfff60c00, 0x0000c27b, 0xffff0c00, 0x0000e27b, + 0xff001000, 0x00000083, 0xff081000, 0x00002083, + 0xff101000, 0x00004083, 0xff181000, 0x00006183, + 0xff201000, 0x00008183, 0xff291000, 0x0000a183, + 0xff311000, 0x0000c283, 0xff391000, 0x0000e283, + 0xff411000, 0x0000008b, 0xff4a1000, 0x0000208b, + 0xff521000, 0x0000408b, 0xff5a1000, 0x0000618b, + 0xff621000, 0x0000818b, 0xff6a1000, 0x0000a18b, + 0xff731000, 0x0000c28b, 0xff7b1000, 0x0000e28b, + 0xff831000, 0x00000094, 0xff8b1000, 0x00002094, + 0xff941000, 0x00004094, 0xff9c1000, 0x00006194, + 0xffa41000, 0x00008194, 0xffac1000, 0x0000a194, + 0xffb41000, 0x0000c294, 0xffbd1000, 0x0000e294, + 0xffc51000, 0x0000009c, 0xffcd1000, 0x0000209c, + 0xffd51000, 0x0000409c, 0xffde1000, 0x0000619c, + 0xffe61000, 0x0000819c, 0xffee1000, 0x0000a19c, + 0xfff61000, 0x0000c29c, 0xffff1000, 0x0000e29c, + 0xff001400, 0x000000a4, 0xff081400, 0x000020a4, + 0xff101400, 0x000040a4, 0xff181400, 0x000061a4, + 0xff201400, 0x000081a4, 0xff291400, 0x0000a1a4, + 0xff311400, 0x0000c2a4, 0xff391400, 0x0000e2a4, + 0xff411400, 0x000000ac, 0xff4a1400, 0x000020ac, + 0xff521400, 0x000040ac, 0xff5a1400, 0x000061ac, + 0xff621400, 0x000081ac, 0xff6a1400, 0x0000a1ac, + 0xff731400, 0x0000c2ac, 0xff7b1400, 0x0000e2ac, + 0xff831400, 0x000000b4, 0xff8b1400, 0x000020b4, + 0xff941400, 0x000040b4, 0xff9c1400, 0x000061b4, + 0xffa41400, 0x000081b4, 0xffac1400, 0x0000a1b4, + 0xffb41400, 0x0000c2b4, 0xffbd1400, 0x0000e2b4, + 0xffc51400, 0x000000bd, 0xffcd1400, 0x000020bd, + 0xffd51400, 0x000040bd, 0xffde1400, 0x000061bd, + 0xffe61400, 0x000081bd, 0xffee1400, 0x0000a1bd, + 0xfff61400, 0x0000c2bd, 0xffff1400, 0x0000e2bd, + 0xff001800, 0x000000c5, 0xff081800, 0x000020c5, + 0xff101800, 0x000040c5, 0xff181800, 0x000061c5, + 0xff201800, 0x000081c5, 0xff291800, 0x0000a1c5, + 0xff311800, 0x0000c2c5, 0xff391800, 0x0000e2c5, + 0xff411800, 0x000000cd, 0xff4a1800, 0x000020cd, + 0xff521800, 0x000040cd, 0xff5a1800, 0x000061cd, + 0xff621800, 0x000081cd, 0xff6a1800, 0x0000a1cd, + 0xff731800, 0x0000c2cd, 0xff7b1800, 0x0000e2cd, + 0xff831800, 0x000000d5, 0xff8b1800, 0x000020d5, + 0xff941800, 0x000040d5, 0xff9c1800, 0x000061d5, + 0xffa41800, 0x000081d5, 0xffac1800, 0x0000a1d5, + 0xffb41800, 0x0000c2d5, 0xffbd1800, 0x0000e2d5, + 0xffc51800, 0x000000de, 0xffcd1800, 0x000020de, + 0xffd51800, 0x000040de, 0xffde1800, 0x000061de, + 0xffe61800, 0x000081de, 0xffee1800, 0x0000a1de, + 0xfff61800, 0x0000c2de, 0xffff1800, 0x0000e2de, + 0xff001c00, 0x000000e6, 0xff081c00, 0x000020e6, + 0xff101c00, 0x000040e6, 0xff181c00, 0x000061e6, + 0xff201c00, 0x000081e6, 0xff291c00, 0x0000a1e6, + 0xff311c00, 0x0000c2e6, 0xff391c00, 0x0000e2e6, + 0xff411c00, 0x000000ee, 0xff4a1c00, 0x000020ee, + 0xff521c00, 0x000040ee, 0xff5a1c00, 0x000061ee, + 0xff621c00, 0x000081ee, 0xff6a1c00, 0x0000a1ee, + 0xff731c00, 0x0000c2ee, 0xff7b1c00, 0x0000e2ee, + 0xff831c00, 0x000000f6, 0xff8b1c00, 0x000020f6, + 0xff941c00, 0x000040f6, 0xff9c1c00, 0x000061f6, + 0xffa41c00, 0x000081f6, 0xffac1c00, 0x0000a1f6, + 0xffb41c00, 0x0000c2f6, 0xffbd1c00, 0x0000e2f6, + 0xffc51c00, 0x000000ff, 0xffcd1c00, 0x000020ff, + 0xffd51c00, 0x000040ff, 0xffde1c00, 0x000061ff, + 0xffe61c00, 0x000081ff, 0xffee1c00, 0x0000a1ff, + 0xfff61c00, 0x0000c2ff, 0xffff1c00, 0x0000e2ff +}; +static void Blit_RGB565_ABGR8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_ABGR8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> RGBA 8-8-8-8 */ +static const Uint32 RGB565_RGBA8888_LUT[512] = { + 0x000000ff, 0x00000000, 0x000008ff, 0x00200000, + 0x000010ff, 0x00400000, 0x000018ff, 0x00610000, + 0x000020ff, 0x00810000, 0x000029ff, 0x00a10000, + 0x000031ff, 0x00c20000, 0x000039ff, 0x00e20000, + 0x000041ff, 0x08000000, 0x00004aff, 0x08200000, + 0x000052ff, 0x08400000, 0x00005aff, 0x08610000, + 0x000062ff, 0x08810000, 0x00006aff, 0x08a10000, + 0x000073ff, 0x08c20000, 0x00007bff, 0x08e20000, + 0x000083ff, 0x10000000, 0x00008bff, 0x10200000, + 0x000094ff, 0x10400000, 0x00009cff, 0x10610000, + 0x0000a4ff, 0x10810000, 0x0000acff, 0x10a10000, + 0x0000b4ff, 0x10c20000, 0x0000bdff, 0x10e20000, + 0x0000c5ff, 0x18000000, 0x0000cdff, 0x18200000, + 0x0000d5ff, 0x18400000, 0x0000deff, 0x18610000, + 0x0000e6ff, 0x18810000, 0x0000eeff, 0x18a10000, + 0x0000f6ff, 0x18c20000, 0x0000ffff, 0x18e20000, + 0x000400ff, 0x20000000, 0x000408ff, 0x20200000, + 0x000410ff, 0x20400000, 0x000418ff, 0x20610000, + 0x000420ff, 0x20810000, 0x000429ff, 0x20a10000, + 0x000431ff, 0x20c20000, 0x000439ff, 0x20e20000, + 0x000441ff, 0x29000000, 0x00044aff, 0x29200000, + 0x000452ff, 0x29400000, 0x00045aff, 0x29610000, + 0x000462ff, 0x29810000, 0x00046aff, 0x29a10000, + 0x000473ff, 0x29c20000, 0x00047bff, 0x29e20000, + 0x000483ff, 0x31000000, 0x00048bff, 0x31200000, + 0x000494ff, 0x31400000, 0x00049cff, 0x31610000, + 0x0004a4ff, 0x31810000, 0x0004acff, 0x31a10000, + 0x0004b4ff, 0x31c20000, 0x0004bdff, 0x31e20000, + 0x0004c5ff, 0x39000000, 0x0004cdff, 0x39200000, + 0x0004d5ff, 0x39400000, 0x0004deff, 0x39610000, + 0x0004e6ff, 0x39810000, 0x0004eeff, 0x39a10000, + 0x0004f6ff, 0x39c20000, 0x0004ffff, 0x39e20000, + 0x000800ff, 0x41000000, 0x000808ff, 0x41200000, + 0x000810ff, 0x41400000, 0x000818ff, 0x41610000, + 0x000820ff, 0x41810000, 0x000829ff, 0x41a10000, + 0x000831ff, 0x41c20000, 0x000839ff, 0x41e20000, + 0x000841ff, 0x4a000000, 0x00084aff, 0x4a200000, + 0x000852ff, 0x4a400000, 0x00085aff, 0x4a610000, + 0x000862ff, 0x4a810000, 0x00086aff, 0x4aa10000, + 0x000873ff, 0x4ac20000, 0x00087bff, 0x4ae20000, + 0x000883ff, 0x52000000, 0x00088bff, 0x52200000, + 0x000894ff, 0x52400000, 0x00089cff, 0x52610000, + 0x0008a4ff, 0x52810000, 0x0008acff, 0x52a10000, + 0x0008b4ff, 0x52c20000, 0x0008bdff, 0x52e20000, + 0x0008c5ff, 0x5a000000, 0x0008cdff, 0x5a200000, + 0x0008d5ff, 0x5a400000, 0x0008deff, 0x5a610000, + 0x0008e6ff, 0x5a810000, 0x0008eeff, 0x5aa10000, + 0x0008f6ff, 0x5ac20000, 0x0008ffff, 0x5ae20000, + 0x000c00ff, 0x62000000, 0x000c08ff, 0x62200000, + 0x000c10ff, 0x62400000, 0x000c18ff, 0x62610000, + 0x000c20ff, 0x62810000, 0x000c29ff, 0x62a10000, + 0x000c31ff, 0x62c20000, 0x000c39ff, 0x62e20000, + 0x000c41ff, 0x6a000000, 0x000c4aff, 0x6a200000, + 0x000c52ff, 0x6a400000, 0x000c5aff, 0x6a610000, + 0x000c62ff, 0x6a810000, 0x000c6aff, 0x6aa10000, + 0x000c73ff, 0x6ac20000, 0x000c7bff, 0x6ae20000, + 0x000c83ff, 0x73000000, 0x000c8bff, 0x73200000, + 0x000c94ff, 0x73400000, 0x000c9cff, 0x73610000, + 0x000ca4ff, 0x73810000, 0x000cacff, 0x73a10000, + 0x000cb4ff, 0x73c20000, 0x000cbdff, 0x73e20000, + 0x000cc5ff, 0x7b000000, 0x000ccdff, 0x7b200000, + 0x000cd5ff, 0x7b400000, 0x000cdeff, 0x7b610000, + 0x000ce6ff, 0x7b810000, 0x000ceeff, 0x7ba10000, + 0x000cf6ff, 0x7bc20000, 0x000cffff, 0x7be20000, + 0x001000ff, 0x83000000, 0x001008ff, 0x83200000, + 0x001010ff, 0x83400000, 0x001018ff, 0x83610000, + 0x001020ff, 0x83810000, 0x001029ff, 0x83a10000, + 0x001031ff, 0x83c20000, 0x001039ff, 0x83e20000, + 0x001041ff, 0x8b000000, 0x00104aff, 0x8b200000, + 0x001052ff, 0x8b400000, 0x00105aff, 0x8b610000, + 0x001062ff, 0x8b810000, 0x00106aff, 0x8ba10000, + 0x001073ff, 0x8bc20000, 0x00107bff, 0x8be20000, + 0x001083ff, 0x94000000, 0x00108bff, 0x94200000, + 0x001094ff, 0x94400000, 0x00109cff, 0x94610000, + 0x0010a4ff, 0x94810000, 0x0010acff, 0x94a10000, + 0x0010b4ff, 0x94c20000, 0x0010bdff, 0x94e20000, + 0x0010c5ff, 0x9c000000, 0x0010cdff, 0x9c200000, + 0x0010d5ff, 0x9c400000, 0x0010deff, 0x9c610000, + 0x0010e6ff, 0x9c810000, 0x0010eeff, 0x9ca10000, + 0x0010f6ff, 0x9cc20000, 0x0010ffff, 0x9ce20000, + 0x001400ff, 0xa4000000, 0x001408ff, 0xa4200000, + 0x001410ff, 0xa4400000, 0x001418ff, 0xa4610000, + 0x001420ff, 0xa4810000, 0x001429ff, 0xa4a10000, + 0x001431ff, 0xa4c20000, 0x001439ff, 0xa4e20000, + 0x001441ff, 0xac000000, 0x00144aff, 0xac200000, + 0x001452ff, 0xac400000, 0x00145aff, 0xac610000, + 0x001462ff, 0xac810000, 0x00146aff, 0xaca10000, + 0x001473ff, 0xacc20000, 0x00147bff, 0xace20000, + 0x001483ff, 0xb4000000, 0x00148bff, 0xb4200000, + 0x001494ff, 0xb4400000, 0x00149cff, 0xb4610000, + 0x0014a4ff, 0xb4810000, 0x0014acff, 0xb4a10000, + 0x0014b4ff, 0xb4c20000, 0x0014bdff, 0xb4e20000, + 0x0014c5ff, 0xbd000000, 0x0014cdff, 0xbd200000, + 0x0014d5ff, 0xbd400000, 0x0014deff, 0xbd610000, + 0x0014e6ff, 0xbd810000, 0x0014eeff, 0xbda10000, + 0x0014f6ff, 0xbdc20000, 0x0014ffff, 0xbde20000, + 0x001800ff, 0xc5000000, 0x001808ff, 0xc5200000, + 0x001810ff, 0xc5400000, 0x001818ff, 0xc5610000, + 0x001820ff, 0xc5810000, 0x001829ff, 0xc5a10000, + 0x001831ff, 0xc5c20000, 0x001839ff, 0xc5e20000, + 0x001841ff, 0xcd000000, 0x00184aff, 0xcd200000, + 0x001852ff, 0xcd400000, 0x00185aff, 0xcd610000, + 0x001862ff, 0xcd810000, 0x00186aff, 0xcda10000, + 0x001873ff, 0xcdc20000, 0x00187bff, 0xcde20000, + 0x001883ff, 0xd5000000, 0x00188bff, 0xd5200000, + 0x001894ff, 0xd5400000, 0x00189cff, 0xd5610000, + 0x0018a4ff, 0xd5810000, 0x0018acff, 0xd5a10000, + 0x0018b4ff, 0xd5c20000, 0x0018bdff, 0xd5e20000, + 0x0018c5ff, 0xde000000, 0x0018cdff, 0xde200000, + 0x0018d5ff, 0xde400000, 0x0018deff, 0xde610000, + 0x0018e6ff, 0xde810000, 0x0018eeff, 0xdea10000, + 0x0018f6ff, 0xdec20000, 0x0018ffff, 0xdee20000, + 0x001c00ff, 0xe6000000, 0x001c08ff, 0xe6200000, + 0x001c10ff, 0xe6400000, 0x001c18ff, 0xe6610000, + 0x001c20ff, 0xe6810000, 0x001c29ff, 0xe6a10000, + 0x001c31ff, 0xe6c20000, 0x001c39ff, 0xe6e20000, + 0x001c41ff, 0xee000000, 0x001c4aff, 0xee200000, + 0x001c52ff, 0xee400000, 0x001c5aff, 0xee610000, + 0x001c62ff, 0xee810000, 0x001c6aff, 0xeea10000, + 0x001c73ff, 0xeec20000, 0x001c7bff, 0xeee20000, + 0x001c83ff, 0xf6000000, 0x001c8bff, 0xf6200000, + 0x001c94ff, 0xf6400000, 0x001c9cff, 0xf6610000, + 0x001ca4ff, 0xf6810000, 0x001cacff, 0xf6a10000, + 0x001cb4ff, 0xf6c20000, 0x001cbdff, 0xf6e20000, + 0x001cc5ff, 0xff000000, 0x001ccdff, 0xff200000, + 0x001cd5ff, 0xff400000, 0x001cdeff, 0xff610000, + 0x001ce6ff, 0xff810000, 0x001ceeff, 0xffa10000, + 0x001cf6ff, 0xffc20000, 0x001cffff, 0xffe20000, +}; +static void Blit_RGB565_RGBA8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_RGBA8888_LUT); +} + +/* Special optimized blit for RGB 5-6-5 --> BGRA 8-8-8-8 */ +static const Uint32 RGB565_BGRA8888_LUT[512] = { + 0x00000000, 0x000000ff, 0x08000000, 0x002000ff, + 0x10000000, 0x004000ff, 0x18000000, 0x006100ff, + 0x20000000, 0x008100ff, 0x29000000, 0x00a100ff, + 0x31000000, 0x00c200ff, 0x39000000, 0x00e200ff, + 0x41000000, 0x000008ff, 0x4a000000, 0x002008ff, + 0x52000000, 0x004008ff, 0x5a000000, 0x006108ff, + 0x62000000, 0x008108ff, 0x6a000000, 0x00a108ff, + 0x73000000, 0x00c208ff, 0x7b000000, 0x00e208ff, + 0x83000000, 0x000010ff, 0x8b000000, 0x002010ff, + 0x94000000, 0x004010ff, 0x9c000000, 0x006110ff, + 0xa4000000, 0x008110ff, 0xac000000, 0x00a110ff, + 0xb4000000, 0x00c210ff, 0xbd000000, 0x00e210ff, + 0xc5000000, 0x000018ff, 0xcd000000, 0x002018ff, + 0xd5000000, 0x004018ff, 0xde000000, 0x006118ff, + 0xe6000000, 0x008118ff, 0xee000000, 0x00a118ff, + 0xf6000000, 0x00c218ff, 0xff000000, 0x00e218ff, + 0x00040000, 0x000020ff, 0x08040000, 0x002020ff, + 0x10040000, 0x004020ff, 0x18040000, 0x006120ff, + 0x20040000, 0x008120ff, 0x29040000, 0x00a120ff, + 0x31040000, 0x00c220ff, 0x39040000, 0x00e220ff, + 0x41040000, 0x000029ff, 0x4a040000, 0x002029ff, + 0x52040000, 0x004029ff, 0x5a040000, 0x006129ff, + 0x62040000, 0x008129ff, 0x6a040000, 0x00a129ff, + 0x73040000, 0x00c229ff, 0x7b040000, 0x00e229ff, + 0x83040000, 0x000031ff, 0x8b040000, 0x002031ff, + 0x94040000, 0x004031ff, 0x9c040000, 0x006131ff, + 0xa4040000, 0x008131ff, 0xac040000, 0x00a131ff, + 0xb4040000, 0x00c231ff, 0xbd040000, 0x00e231ff, + 0xc5040000, 0x000039ff, 0xcd040000, 0x002039ff, + 0xd5040000, 0x004039ff, 0xde040000, 0x006139ff, + 0xe6040000, 0x008139ff, 0xee040000, 0x00a139ff, + 0xf6040000, 0x00c239ff, 0xff040000, 0x00e239ff, + 0x00080000, 0x000041ff, 0x08080000, 0x002041ff, + 0x10080000, 0x004041ff, 0x18080000, 0x006141ff, + 0x20080000, 0x008141ff, 0x29080000, 0x00a141ff, + 0x31080000, 0x00c241ff, 0x39080000, 0x00e241ff, + 0x41080000, 0x00004aff, 0x4a080000, 0x00204aff, + 0x52080000, 0x00404aff, 0x5a080000, 0x00614aff, + 0x62080000, 0x00814aff, 0x6a080000, 0x00a14aff, + 0x73080000, 0x00c24aff, 0x7b080000, 0x00e24aff, + 0x83080000, 0x000052ff, 0x8b080000, 0x002052ff, + 0x94080000, 0x004052ff, 0x9c080000, 0x006152ff, + 0xa4080000, 0x008152ff, 0xac080000, 0x00a152ff, + 0xb4080000, 0x00c252ff, 0xbd080000, 0x00e252ff, + 0xc5080000, 0x00005aff, 0xcd080000, 0x00205aff, + 0xd5080000, 0x00405aff, 0xde080000, 0x00615aff, + 0xe6080000, 0x00815aff, 0xee080000, 0x00a15aff, + 0xf6080000, 0x00c25aff, 0xff080000, 0x00e25aff, + 0x000c0000, 0x000062ff, 0x080c0000, 0x002062ff, + 0x100c0000, 0x004062ff, 0x180c0000, 0x006162ff, + 0x200c0000, 0x008162ff, 0x290c0000, 0x00a162ff, + 0x310c0000, 0x00c262ff, 0x390c0000, 0x00e262ff, + 0x410c0000, 0x00006aff, 0x4a0c0000, 0x00206aff, + 0x520c0000, 0x00406aff, 0x5a0c0000, 0x00616aff, + 0x620c0000, 0x00816aff, 0x6a0c0000, 0x00a16aff, + 0x730c0000, 0x00c26aff, 0x7b0c0000, 0x00e26aff, + 0x830c0000, 0x000073ff, 0x8b0c0000, 0x002073ff, + 0x940c0000, 0x004073ff, 0x9c0c0000, 0x006173ff, + 0xa40c0000, 0x008173ff, 0xac0c0000, 0x00a173ff, + 0xb40c0000, 0x00c273ff, 0xbd0c0000, 0x00e273ff, + 0xc50c0000, 0x00007bff, 0xcd0c0000, 0x00207bff, + 0xd50c0000, 0x00407bff, 0xde0c0000, 0x00617bff, + 0xe60c0000, 0x00817bff, 0xee0c0000, 0x00a17bff, + 0xf60c0000, 0x00c27bff, 0xff0c0000, 0x00e27bff, + 0x00100000, 0x000083ff, 0x08100000, 0x002083ff, + 0x10100000, 0x004083ff, 0x18100000, 0x006183ff, + 0x20100000, 0x008183ff, 0x29100000, 0x00a183ff, + 0x31100000, 0x00c283ff, 0x39100000, 0x00e283ff, + 0x41100000, 0x00008bff, 0x4a100000, 0x00208bff, + 0x52100000, 0x00408bff, 0x5a100000, 0x00618bff, + 0x62100000, 0x00818bff, 0x6a100000, 0x00a18bff, + 0x73100000, 0x00c28bff, 0x7b100000, 0x00e28bff, + 0x83100000, 0x000094ff, 0x8b100000, 0x002094ff, + 0x94100000, 0x004094ff, 0x9c100000, 0x006194ff, + 0xa4100000, 0x008194ff, 0xac100000, 0x00a194ff, + 0xb4100000, 0x00c294ff, 0xbd100000, 0x00e294ff, + 0xc5100000, 0x00009cff, 0xcd100000, 0x00209cff, + 0xd5100000, 0x00409cff, 0xde100000, 0x00619cff, + 0xe6100000, 0x00819cff, 0xee100000, 0x00a19cff, + 0xf6100000, 0x00c29cff, 0xff100000, 0x00e29cff, + 0x00140000, 0x0000a4ff, 0x08140000, 0x0020a4ff, + 0x10140000, 0x0040a4ff, 0x18140000, 0x0061a4ff, + 0x20140000, 0x0081a4ff, 0x29140000, 0x00a1a4ff, + 0x31140000, 0x00c2a4ff, 0x39140000, 0x00e2a4ff, + 0x41140000, 0x0000acff, 0x4a140000, 0x0020acff, + 0x52140000, 0x0040acff, 0x5a140000, 0x0061acff, + 0x62140000, 0x0081acff, 0x6a140000, 0x00a1acff, + 0x73140000, 0x00c2acff, 0x7b140000, 0x00e2acff, + 0x83140000, 0x0000b4ff, 0x8b140000, 0x0020b4ff, + 0x94140000, 0x0040b4ff, 0x9c140000, 0x0061b4ff, + 0xa4140000, 0x0081b4ff, 0xac140000, 0x00a1b4ff, + 0xb4140000, 0x00c2b4ff, 0xbd140000, 0x00e2b4ff, + 0xc5140000, 0x0000bdff, 0xcd140000, 0x0020bdff, + 0xd5140000, 0x0040bdff, 0xde140000, 0x0061bdff, + 0xe6140000, 0x0081bdff, 0xee140000, 0x00a1bdff, + 0xf6140000, 0x00c2bdff, 0xff140000, 0x00e2bdff, + 0x00180000, 0x0000c5ff, 0x08180000, 0x0020c5ff, + 0x10180000, 0x0040c5ff, 0x18180000, 0x0061c5ff, + 0x20180000, 0x0081c5ff, 0x29180000, 0x00a1c5ff, + 0x31180000, 0x00c2c5ff, 0x39180000, 0x00e2c5ff, + 0x41180000, 0x0000cdff, 0x4a180000, 0x0020cdff, + 0x52180000, 0x0040cdff, 0x5a180000, 0x0061cdff, + 0x62180000, 0x0081cdff, 0x6a180000, 0x00a1cdff, + 0x73180000, 0x00c2cdff, 0x7b180000, 0x00e2cdff, + 0x83180000, 0x0000d5ff, 0x8b180000, 0x0020d5ff, + 0x94180000, 0x0040d5ff, 0x9c180000, 0x0061d5ff, + 0xa4180000, 0x0081d5ff, 0xac180000, 0x00a1d5ff, + 0xb4180000, 0x00c2d5ff, 0xbd180000, 0x00e2d5ff, + 0xc5180000, 0x0000deff, 0xcd180000, 0x0020deff, + 0xd5180000, 0x0040deff, 0xde180000, 0x0061deff, + 0xe6180000, 0x0081deff, 0xee180000, 0x00a1deff, + 0xf6180000, 0x00c2deff, 0xff180000, 0x00e2deff, + 0x001c0000, 0x0000e6ff, 0x081c0000, 0x0020e6ff, + 0x101c0000, 0x0040e6ff, 0x181c0000, 0x0061e6ff, + 0x201c0000, 0x0081e6ff, 0x291c0000, 0x00a1e6ff, + 0x311c0000, 0x00c2e6ff, 0x391c0000, 0x00e2e6ff, + 0x411c0000, 0x0000eeff, 0x4a1c0000, 0x0020eeff, + 0x521c0000, 0x0040eeff, 0x5a1c0000, 0x0061eeff, + 0x621c0000, 0x0081eeff, 0x6a1c0000, 0x00a1eeff, + 0x731c0000, 0x00c2eeff, 0x7b1c0000, 0x00e2eeff, + 0x831c0000, 0x0000f6ff, 0x8b1c0000, 0x0020f6ff, + 0x941c0000, 0x0040f6ff, 0x9c1c0000, 0x0061f6ff, + 0xa41c0000, 0x0081f6ff, 0xac1c0000, 0x00a1f6ff, + 0xb41c0000, 0x00c2f6ff, 0xbd1c0000, 0x00e2f6ff, + 0xc51c0000, 0x0000ffff, 0xcd1c0000, 0x0020ffff, + 0xd51c0000, 0x0040ffff, 0xde1c0000, 0x0061ffff, + 0xe61c0000, 0x0081ffff, 0xee1c0000, 0x00a1ffff, + 0xf61c0000, 0x00c2ffff, 0xff1c0000, 0x00e2ffff +}; +static void Blit_RGB565_BGRA8888(SDL_BlitInfo *info) +{ + Blit_RGB565_32(info, RGB565_BGRA8888_LUT); +} + +/* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ +#ifndef RGB888_RGB332 +#define RGB888_RGB332(dst, src) { \ + dst = (((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6); \ +} +#endif +static void Blit_RGB888_index8_map(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int Pixel; + int width, height; + Uint32 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = (Uint32 *)info->s_pixels; + srcskip = info->s_skip/4; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + +#ifdef USE_DUFFS_LOOP + while ( height-- ) { + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); + src += srcskip; + dst += dstskip; + } +#else + while ( height-- ) { + for ( c=width/4; c; --c ) { + /* Pack RGB into 8bit pixel */ + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + switch ( width & 3 ) { + case 3: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 2: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + case 1: + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + } + src += srcskip; + dst += dstskip; + } +#endif /* USE_DUFFS_LOOP */ +} +static void BlitNto1(SDL_BlitInfo *info) +{ +#ifndef USE_DUFFS_LOOP + int c; +#endif + int width, height; + Uint8 *src; + const Uint8 *map; + Uint8 *dst; + int srcskip, dstskip; + int srcbpp; + Uint32 Pixel; + int sR, sG, sB; + SDL_PixelFormat *srcfmt; + + /* Set up some basic variables */ + width = info->d_width; + height = info->d_height; + src = info->s_pixels; + srcskip = info->s_skip; + dst = info->d_pixels; + dstskip = info->d_skip; + map = info->table; + srcfmt = info->src; + srcbpp = srcfmt->BytesPerPixel; + + if ( map == NULL ) { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = ((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ; + } + dst++; + src += srcbpp; + , width); +#else + for ( c=width; c; --c ) { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = ((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ; + } + dst++; + src += srcbpp; + } +#endif + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { +#ifdef USE_DUFFS_LOOP + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = map[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + , width); +#else + for ( c=width; c; --c ) { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = map[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + } +#endif /* USE_DUFFS_LOOP */ + src += srcskip; + dst += dstskip; + } + } +} + +/* blits 32 bit RGB<->RGBA with both surfaces having the same R,G,B fields */ +static void Blit4to4MaskAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint32 *src = (Uint32 *)info->s_pixels; + int srcskip = info->s_skip; + Uint32 *dst = (Uint32 *)info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + + if (dstfmt->Amask) { + /* RGB->RGBA, SET_ALPHA */ + Uint32 mask = (srcfmt->alpha >> dstfmt->Aloss) << dstfmt->Ashift; + + while ( height-- ) { + DUFFS_LOOP( + { + *dst = *src | mask; + ++dst; + ++src; + }, + width); + src = (Uint32*)((Uint8*)src + srcskip); + dst = (Uint32*)((Uint8*)dst + dstskip); + } + } else { + /* RGBA->RGB, NO_ALPHA */ + Uint32 mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; + + while ( height-- ) { + DUFFS_LOOP( + { + *dst = *src & mask; + ++dst; + ++src; + }, + width); + src = (Uint32*)((Uint8*)src + srcskip); + dst = (Uint32*)((Uint8*)dst + dstskip); + } + } +} + +static void BlitNtoN(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void BlitNtoNCopyAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + int srcbpp = srcfmt->BytesPerPixel; + SDL_PixelFormat *dstfmt = info->dst; + int dstbpp = dstfmt->BytesPerPixel; + int c; + + /* FIXME: should map alpha to [0..255] correctly! */ + while ( height-- ) { + for ( c=width; c; --c ) { + Uint32 Pixel; + unsigned sR, sG, sB, sA; + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, + sR, sG, sB, sA); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, sA); + dst += dstbpp; + src += srcbpp; + } + src += srcskip; + dst += dstskip; + } +} + +static void BlitNto1Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + SDL_PixelFormat *srcfmt = info->src; + const Uint8 *palmap = info->table; + Uint32 ckey = srcfmt->colorkey; + Uint32 rgbmask = ~srcfmt->Amask; + int srcbpp; + Uint32 Pixel; + unsigned sR, sG, sB; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + ckey &= rgbmask; + + if ( palmap == NULL ) { + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)(((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0))); + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } else { + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)palmap[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } + } +} + +static void Blit2to2Key(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint16 *srcp = (Uint16 *)info->s_pixels; + int srcskip = info->s_skip; + Uint16 *dstp = (Uint16 *)info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + Uint32 rgbmask = ~info->src->Amask; + + /* Set up some basic variables */ + srcskip /= 2; + dstskip /= 2; + ckey &= rgbmask; + + while ( height-- ) { + DUFFS_LOOP( + { + if ( (*srcp & rgbmask) != ckey ) { + *dstp = *srcp; + } + dstp++; + srcp++; + }, + width); + srcp += srcskip; + dstp += dstskip; + } +} + +static void BlitNtoNKey(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + int srcbpp = srcfmt->BytesPerPixel; + int dstbpp = dstfmt->BytesPerPixel; + unsigned alpha = dstfmt->Amask ? srcfmt->alpha : 0; + Uint32 rgbmask = ~srcfmt->Amask; + + /* Set up some basic variables */ + ckey &= rgbmask; + + while ( height-- ) { + DUFFS_LOOP( + { + Uint32 Pixel; + unsigned sR; + unsigned sG; + unsigned sB; + RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); + if ( (Pixel & rgbmask) != ckey ) { + RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, alpha); + } + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info) +{ + int width = info->d_width; + int height = info->d_height; + Uint8 *src = info->s_pixels; + int srcskip = info->s_skip; + Uint8 *dst = info->d_pixels; + int dstskip = info->d_skip; + Uint32 ckey = info->src->colorkey; + SDL_PixelFormat *srcfmt = info->src; + SDL_PixelFormat *dstfmt = info->dst; + Uint32 rgbmask = ~srcfmt->Amask; + + Uint8 srcbpp; + Uint8 dstbpp; + Uint32 Pixel; + unsigned sR, sG, sB, sA; + + /* Set up some basic variables */ + srcbpp = srcfmt->BytesPerPixel; + dstbpp = dstfmt->BytesPerPixel; + ckey &= rgbmask; + + /* FIXME: should map alpha to [0..255] correctly! */ + while ( height-- ) { + DUFFS_LOOP( + { + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, + sR, sG, sB, sA); + if ( (Pixel & rgbmask) != ckey ) { + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, + sR, sG, sB, sA); + } + dst += dstbpp; + src += srcbpp; + }, + width); + src += srcskip; + dst += dstskip; + } +} + +/* Normal N to N optimized blitters */ +struct blit_table { + Uint32 srcR, srcG, srcB; + int dstbpp; + Uint32 dstR, dstG, dstB; + Uint32 blit_features; + void *aux_data; + SDL_loblit blitfunc; + enum { NO_ALPHA=1, SET_ALPHA=2, COPY_ALPHA=4 } alpha; +}; +static const struct blit_table normal_blit_1[] = { + /* Default for 8-bit RGB source, an invalid combination */ + { 0,0,0, 0, 0,0,0, 0, NULL, NULL }, +}; +static const struct blit_table normal_blit_2[] = { +#if SDL_HERMES_BLITTERS + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000007E0,0x0000F800, + 0, ConvertX86p16_16BGR565, ConvertX86, NO_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, ConvertX86p16_16RGB555, ConvertX86, NO_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 2, 0x0000001F,0x000003E0,0x00007C00, + 0, ConvertX86p16_16BGR555, ConvertX86, NO_ALPHA }, +#elif SDL_ALTIVEC_BLITTERS + /* has-altivec */ + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, Blit_RGB565_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x00007C00,0x000003E0,0x0000001F, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, Blit_RGB555_32Altivec, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, +#endif + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x00FF0000,0x0000FF00,0x000000FF, + 0, NULL, Blit_RGB565_ARGB8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x000000FF,0x0000FF00,0x00FF0000, + 0, NULL, Blit_RGB565_ABGR8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0xFF000000,0x00FF0000,0x0000FF00, + 0, NULL, Blit_RGB565_RGBA8888, SET_ALPHA }, + { 0x0000F800,0x000007E0,0x0000001F, 4, 0x0000FF00,0x00FF0000,0xFF000000, + 0, NULL, Blit_RGB565_BGRA8888, SET_ALPHA }, + + /* Default for 16-bit RGB source, used if no other blitter matches */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table normal_blit_3[] = { + /* Default for 24-bit RGB source, never optimized */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table normal_blit_4[] = { +#if SDL_HERMES_BLITTERS + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 1, ConvertMMXpII32_16RGB565, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 0, ConvertX86p32_16RGB565, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, + 1, ConvertMMXpII32_16BGR565, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, + 0, ConvertX86p32_16BGR565, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 1, ConvertMMXpII32_16RGB555, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, ConvertX86p32_16RGB555, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, + 1, ConvertMMXpII32_16BGR555, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, + 0, ConvertX86p32_16BGR555, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF, + 1, ConvertMMXpII32_24RGB888, ConvertMMX, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF, + 0, ConvertX86p32_24RGB888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x000000FF,0x0000FF00,0x00FF0000, + 0, ConvertX86p32_24BGR888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x000000FF,0x0000FF00,0x00FF0000, + 0, ConvertX86p32_32BGR888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0xFF000000,0x00FF0000,0x0000FF00, + 0, ConvertX86p32_32RGBA888, ConvertX86, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 4, 0x0000FF00,0x00FF0000,0xFF000000, + 0, ConvertX86p32_32BGRA888, ConvertX86, NO_ALPHA }, +#else +#if SDL_ALTIVEC_BLITTERS + /* has-altivec | dont-use-prefetch */ + { 0x00000000,0x00000000,0x00000000, 4, 0x00000000,0x00000000,0x00000000, + 6, NULL, ConvertAltivec32to32_noprefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + /* has-altivec */ + { 0x00000000,0x00000000,0x00000000, 4, 0x00000000,0x00000000,0x00000000, + 2, NULL, ConvertAltivec32to32_prefetch, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + /* has-altivec */ + { 0x00000000,0x00000000,0x00000000, 2, 0x0000F800,0x000007E0,0x0000001F, + 2, NULL, Blit_RGB888_RGB565Altivec, NO_ALPHA }, +#endif + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, + 0, NULL, Blit_RGB888_RGB565, NO_ALPHA }, + { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, + 0, NULL, Blit_RGB888_RGB555, NO_ALPHA }, +#endif + /* Default for 32-bit RGB source, used if no other blitter matches */ + { 0,0,0, 0, 0,0,0, 0, NULL, BlitNtoN, 0 } +}; +static const struct blit_table *normal_blit[] = { + normal_blit_1, normal_blit_2, normal_blit_3, normal_blit_4 +}; + +/* Mask matches table, or table entry is zero */ +#define MASKOK(x, y) (((x) == (y)) || ((y) == 0x00000000)) + +SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int blit_index) +{ + struct private_swaccel *sdata; + SDL_PixelFormat *srcfmt; + SDL_PixelFormat *dstfmt; + const struct blit_table *table; + int which; + SDL_loblit blitfun; + + /* Set up data for choosing the blit */ + sdata = surface->map->sw_data; + srcfmt = surface->format; + dstfmt = surface->map->dst->format; + + if ( blit_index & 2 ) { + /* alpha or alpha+colorkey */ + return SDL_CalculateAlphaBlit(surface, blit_index); + } + + /* We don't support destinations less than 8-bits */ + if ( dstfmt->BitsPerPixel < 8 ) { + return(NULL); + } + + if(blit_index == 1) { + /* colorkey blit: Here we don't have too many options, mostly + because RLE is the preferred fast way to deal with this. + If a particular case turns out to be useful we'll add it. */ + + if(srcfmt->BytesPerPixel == 2 + && surface->map->identity) + return Blit2to2Key; + else if(dstfmt->BytesPerPixel == 1) + return BlitNto1Key; + else { +#if SDL_ALTIVEC_BLITTERS + if((srcfmt->BytesPerPixel == 4) && (dstfmt->BytesPerPixel == 4) && SDL_HasAltiVec()) { + return Blit32to32KeyAltivec; + } else +#endif + + if(srcfmt->Amask && dstfmt->Amask) + return BlitNtoNKeyCopyAlpha; + else + return BlitNtoNKey; + } + } + + blitfun = NULL; + if ( dstfmt->BitsPerPixel == 8 ) { + /* We assume 8-bit destinations are palettized */ + if ( (srcfmt->BytesPerPixel == 4) && + (srcfmt->Rmask == 0x00FF0000) && + (srcfmt->Gmask == 0x0000FF00) && + (srcfmt->Bmask == 0x000000FF) ) { + if ( surface->map->table ) { + blitfun = Blit_RGB888_index8_map; + } else { +#if SDL_HERMES_BLITTERS + sdata->aux_data = ConvertX86p32_8RGB332; + blitfun = ConvertX86; +#else + blitfun = Blit_RGB888_index8; +#endif + } + } else { + blitfun = BlitNto1; + } + } else { + /* Now the meat, choose the blitter we want */ + int a_need = NO_ALPHA; + if(dstfmt->Amask) + a_need = srcfmt->Amask ? COPY_ALPHA : SET_ALPHA; + table = normal_blit[srcfmt->BytesPerPixel-1]; + for ( which=0; table[which].dstbpp; ++which ) { + if ( MASKOK(srcfmt->Rmask, table[which].srcR) && + MASKOK(srcfmt->Gmask, table[which].srcG) && + MASKOK(srcfmt->Bmask, table[which].srcB) && + MASKOK(dstfmt->Rmask, table[which].dstR) && + MASKOK(dstfmt->Gmask, table[which].dstG) && + MASKOK(dstfmt->Bmask, table[which].dstB) && + dstfmt->BytesPerPixel == table[which].dstbpp && + (a_need & table[which].alpha) == a_need && + ((table[which].blit_features & GetBlitFeatures()) == table[which].blit_features) ) + break; + } + sdata->aux_data = table[which].aux_data; + blitfun = table[which].blitfunc; + + if(blitfun == BlitNtoN) { /* default C fallback catch-all. Slow! */ + /* Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB */ + if ( srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4 && + srcfmt->Rmask == dstfmt->Rmask && + srcfmt->Gmask == dstfmt->Gmask && + srcfmt->Bmask == dstfmt->Bmask ) { + blitfun = Blit4to4MaskAlpha; + } else if ( a_need == COPY_ALPHA ) { + blitfun = BlitNtoNCopyAlpha; + } + } + } + +#ifdef DEBUG_ASM +#if SDL_HERMES_BLITTERS + if ( blitfun == ConvertMMX ) + fprintf(stderr, "Using mmx blit\n"); + else + if ( blitfun == ConvertX86 ) + fprintf(stderr, "Using asm blit\n"); + else +#endif + if ( (blitfun == BlitNtoN) || (blitfun == BlitNto1) ) + fprintf(stderr, "Using C blit\n"); + else + fprintf(stderr, "Using optimized C blit\n"); +#endif /* DEBUG_ASM */ + + return(blitfun); +} diff --git a/3rdparty/SDL/src/video/SDL_bmp.c b/3rdparty/SDL/src/video/SDL_bmp.c new file mode 100644 index 0000000..d56cfd8 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_bmp.c @@ -0,0 +1,549 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Code to load and save surfaces in Windows BMP format. + + Why support BMP format? Well, it's a native format for Windows, and + most image processing programs can read and write it. It would be nice + to be able to have at least one image format that we can natively load + and save, and since PNG is so complex that it would bloat the library, + BMP is a good alternative. + + This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp. +*/ + +#include "SDL_video.h" +#include "SDL_endian.h" + +/* Compression encodings for BMP files */ +#ifndef BI_RGB +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#define BI_BITFIELDS 3 +#endif + + +SDL_Surface * SDL_LoadBMP_RW (SDL_RWops *src, int freesrc) +{ + SDL_bool was_error; + long fp_offset = 0; + int bmpPitch; + int i, pad; + SDL_Surface *surface; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + SDL_Palette *palette; + Uint8 *bits; + Uint8 *top, *end; + SDL_bool topDown; + int ExpandBMP; + + /* The Win32 BMP file header (14 bytes) */ + char magic[2]; + Uint32 bfSize; + Uint16 bfReserved1; + Uint16 bfReserved2; + Uint32 bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we are passed a valid data source */ + surface = NULL; + was_error = SDL_FALSE; + if ( src == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Read in the BMP file header */ + fp_offset = SDL_RWtell(src); + SDL_ClearError(); + if ( SDL_RWread(src, magic, 1, 2) != 2 ) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } + if ( SDL_strncmp(magic, "BM", 2) != 0 ) { + SDL_SetError("File is not a Windows BMP file"); + was_error = SDL_TRUE; + goto done; + } + bfSize = SDL_ReadLE32(src); + bfReserved1 = SDL_ReadLE16(src); + bfReserved2 = SDL_ReadLE16(src); + bfOffBits = SDL_ReadLE32(src); + + /* Read the Win32 BITMAPINFOHEADER */ + biSize = SDL_ReadLE32(src); + if ( biSize == 12 ) { + biWidth = (Uint32)SDL_ReadLE16(src); + biHeight = (Uint32)SDL_ReadLE16(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = BI_RGB; + biSizeImage = 0; + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + biClrUsed = 0; + biClrImportant = 0; + } else { + biWidth = SDL_ReadLE32(src); + biHeight = SDL_ReadLE32(src); + biPlanes = SDL_ReadLE16(src); + biBitCount = SDL_ReadLE16(src); + biCompression = SDL_ReadLE32(src); + biSizeImage = SDL_ReadLE32(src); + biXPelsPerMeter = SDL_ReadLE32(src); + biYPelsPerMeter = SDL_ReadLE32(src); + biClrUsed = SDL_ReadLE32(src); + biClrImportant = SDL_ReadLE32(src); + } + + /* stop some compiler warnings. */ + (void) bfSize; + (void) bfReserved1; + (void) bfReserved2; + (void) biPlanes; + (void) biSizeImage; + (void) biXPelsPerMeter; + (void) biYPelsPerMeter; + (void) biClrImportant; + + if (biHeight < 0) { + topDown = SDL_TRUE; + biHeight = -biHeight; + } else { + topDown = SDL_FALSE; + } + + /* Check for read error */ + if ( SDL_strcmp(SDL_GetError(), "") != 0 ) { + was_error = SDL_TRUE; + goto done; + } + + /* Expand 1 and 4 bit bitmaps to 8 bits per pixel */ + switch (biBitCount) { + case 1: + case 4: + ExpandBMP = biBitCount; + biBitCount = 8; + break; + default: + ExpandBMP = 0; + break; + } + + /* We don't support any BMP compression right now */ + Rmask = Gmask = Bmask = 0; + switch (biCompression) { + case BI_RGB: + /* If there are no masks, use the defaults */ + if ( bfOffBits == (14+biSize) ) { + /* Default values for the BMP format */ + switch (biBitCount) { + case 15: + case 16: + Rmask = 0x7C00; + Gmask = 0x03E0; + Bmask = 0x001F; + break; + case 24: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + Rmask = 0x000000FF; + Gmask = 0x0000FF00; + Bmask = 0x00FF0000; + break; +#endif + case 32: + Rmask = 0x00FF0000; + Gmask = 0x0000FF00; + Bmask = 0x000000FF; + break; + default: + break; + } + break; + } + /* Fall through -- read the RGB masks */ + + case BI_BITFIELDS: + switch (biBitCount) { + case 15: + case 16: + case 32: + Rmask = SDL_ReadLE32(src); + Gmask = SDL_ReadLE32(src); + Bmask = SDL_ReadLE32(src); + break; + default: + break; + } + break; + default: + SDL_SetError("Compressed BMP files not supported"); + was_error = SDL_TRUE; + goto done; + } + + /* Create a compatible surface, note that the colors are RGB ordered */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, 0); + if ( surface == NULL ) { + was_error = SDL_TRUE; + goto done; + } + + /* Load the palette, if any */ + palette = (surface->format)->palette; + if ( palette ) { + if ( biClrUsed == 0 ) { + biClrUsed = 1 << biBitCount; + } + if ( biSize == 12 ) { + for ( i = 0; i < (int)biClrUsed; ++i ) { + SDL_RWread(src, &palette->colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + palette->colors[i].unused = 0; + } + } else { + for ( i = 0; i < (int)biClrUsed; ++i ) { + SDL_RWread(src, &palette->colors[i].b, 1, 1); + SDL_RWread(src, &palette->colors[i].g, 1, 1); + SDL_RWread(src, &palette->colors[i].r, 1, 1); + SDL_RWread(src, &palette->colors[i].unused, 1, 1); + } + } + palette->ncolors = biClrUsed; + } + + /* Read the surface pixels. Note that the bmp image is upside down */ + if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + was_error = SDL_TRUE; + goto done; + } + top = (Uint8 *)surface->pixels; + end = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + switch (ExpandBMP) { + case 1: + bmpPitch = (biWidth + 7) >> 3; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + case 4: + bmpPitch = (biWidth + 1) >> 1; + pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0); + break; + default: + pad = ((surface->pitch%4) ? + (4-(surface->pitch%4)) : 0); + break; + } + if ( topDown ) { + bits = top; + } else { + bits = end - surface->pitch; + } + while ( bits >= top && bits < end ) { + switch (ExpandBMP) { + case 1: + case 4: { + Uint8 pixel = 0; + int shift = (8-ExpandBMP); + for ( i=0; i<surface->w; ++i ) { + if ( i%(8/ExpandBMP) == 0 ) { + if ( !SDL_RWread(src, &pixel, 1, 1) ) { + SDL_SetError( + "Error reading from BMP"); + was_error = SDL_TRUE; + goto done; + } + } + *(bits+i) = (pixel>>shift); + pixel <<= ExpandBMP; + } } + break; + + default: + if ( SDL_RWread(src, bits, 1, surface->pitch) + != surface->pitch ) { + SDL_Error(SDL_EFREAD); + was_error = SDL_TRUE; + goto done; + } +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + /* Byte-swap the pixels if needed. Note that the 24bpp + case has already been taken care of above. */ + switch(biBitCount) { + case 15: + case 16: { + Uint16 *pix = (Uint16 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap16(pix[i]); + break; + } + + case 32: { + Uint32 *pix = (Uint32 *)bits; + for(i = 0; i < surface->w; i++) + pix[i] = SDL_Swap32(pix[i]); + break; + } + } +#endif + break; + } + /* Skip padding bytes, ugh */ + if ( pad ) { + Uint8 padbyte; + for ( i=0; i<pad; ++i ) { + SDL_RWread(src, &padbyte, 1, 1); + } + } + if ( topDown ) { + bits += surface->pitch; + } else { + bits -= surface->pitch; + } + } +done: + if ( was_error ) { + if ( src ) { + SDL_RWseek(src, fp_offset, RW_SEEK_SET); + } + if ( surface ) { + SDL_FreeSurface(surface); + } + surface = NULL; + } + if ( freesrc && src ) { + SDL_RWclose(src); + } + return(surface); +} + +int SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst) +{ + long fp_offset; + int i, pad; + SDL_Surface *surface; + Uint8 *bits; + + /* The Win32 BMP file header (14 bytes) */ + char magic[2] = { 'B', 'M' }; + Uint32 bfSize; + Uint16 bfReserved1; + Uint16 bfReserved2; + Uint32 bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + + /* Make sure we have somewhere to save */ + surface = NULL; + if ( dst ) { + if ( saveme->format->palette ) { + if ( saveme->format->BitsPerPixel == 8 ) { + surface = saveme; + } else { + SDL_SetError("%d bpp BMP files not supported", + saveme->format->BitsPerPixel); + } + } + else if ( (saveme->format->BitsPerPixel == 24) && +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + (saveme->format->Rmask == 0x00FF0000) && + (saveme->format->Gmask == 0x0000FF00) && + (saveme->format->Bmask == 0x000000FF) +#else + (saveme->format->Rmask == 0x000000FF) && + (saveme->format->Gmask == 0x0000FF00) && + (saveme->format->Bmask == 0x00FF0000) +#endif + ) { + surface = saveme; + } else { + SDL_Rect bounds; + + /* Convert to 24 bits per pixel */ + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + saveme->w, saveme->h, 24, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x00FF0000, 0x0000FF00, 0x000000FF, +#else + 0x000000FF, 0x0000FF00, 0x00FF0000, +#endif + 0); + if ( surface != NULL ) { + bounds.x = 0; + bounds.y = 0; + bounds.w = saveme->w; + bounds.h = saveme->h; + if ( SDL_LowerBlit(saveme, &bounds, surface, + &bounds) < 0 ) { + SDL_FreeSurface(surface); + SDL_SetError( + "Couldn't convert image to 24 bpp"); + surface = NULL; + } + } + } + } + + if ( surface && (SDL_LockSurface(surface) == 0) ) { + const int bw = surface->w*surface->format->BytesPerPixel; + + /* Set the BMP file header values */ + bfSize = 0; /* We'll write this when we're done */ + bfReserved1 = 0; + bfReserved2 = 0; + bfOffBits = 0; /* We'll write this when we're done */ + + /* Write the BMP file header values */ + fp_offset = SDL_RWtell(dst); + SDL_ClearError(); + SDL_RWwrite(dst, magic, 2, 1); + SDL_WriteLE32(dst, bfSize); + SDL_WriteLE16(dst, bfReserved1); + SDL_WriteLE16(dst, bfReserved2); + SDL_WriteLE32(dst, bfOffBits); + + /* Set the BMP info values */ + biSize = 40; + biWidth = surface->w; + biHeight = surface->h; + biPlanes = 1; + biBitCount = surface->format->BitsPerPixel; + biCompression = BI_RGB; + biSizeImage = surface->h*surface->pitch; + biXPelsPerMeter = 0; + biYPelsPerMeter = 0; + if ( surface->format->palette ) { + biClrUsed = surface->format->palette->ncolors; + } else { + biClrUsed = 0; + } + biClrImportant = 0; + + /* Write the BMP info values */ + SDL_WriteLE32(dst, biSize); + SDL_WriteLE32(dst, biWidth); + SDL_WriteLE32(dst, biHeight); + SDL_WriteLE16(dst, biPlanes); + SDL_WriteLE16(dst, biBitCount); + SDL_WriteLE32(dst, biCompression); + SDL_WriteLE32(dst, biSizeImage); + SDL_WriteLE32(dst, biXPelsPerMeter); + SDL_WriteLE32(dst, biYPelsPerMeter); + SDL_WriteLE32(dst, biClrUsed); + SDL_WriteLE32(dst, biClrImportant); + + /* Write the palette (in BGR color order) */ + if ( surface->format->palette ) { + SDL_Color *colors; + int ncolors; + + colors = surface->format->palette->colors; + ncolors = surface->format->palette->ncolors; + for ( i=0; i<ncolors; ++i ) { + SDL_RWwrite(dst, &colors[i].b, 1, 1); + SDL_RWwrite(dst, &colors[i].g, 1, 1); + SDL_RWwrite(dst, &colors[i].r, 1, 1); + SDL_RWwrite(dst, &colors[i].unused, 1, 1); + } + } + + /* Write the bitmap offset */ + bfOffBits = SDL_RWtell(dst)-fp_offset; + if ( SDL_RWseek(dst, fp_offset+10, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + SDL_WriteLE32(dst, bfOffBits); + if ( SDL_RWseek(dst, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + + /* Write the bitmap image upside down */ + bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); + pad = ((bw%4) ? (4-(bw%4)) : 0); + while ( bits > (Uint8 *)surface->pixels ) { + bits -= surface->pitch; + if ( SDL_RWwrite(dst, bits, 1, bw) != bw) { + SDL_Error(SDL_EFWRITE); + break; + } + if ( pad ) { + const Uint8 padbyte = 0; + for ( i=0; i<pad; ++i ) { + SDL_RWwrite(dst, &padbyte, 1, 1); + } + } + } + + /* Write the BMP file size */ + bfSize = SDL_RWtell(dst)-fp_offset; + if ( SDL_RWseek(dst, fp_offset+2, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + SDL_WriteLE32(dst, bfSize); + if ( SDL_RWseek(dst, fp_offset+bfSize, RW_SEEK_SET) < 0 ) { + SDL_Error(SDL_EFSEEK); + } + + /* Close it up.. */ + SDL_UnlockSurface(surface); + if ( surface != saveme ) { + SDL_FreeSurface(surface); + } + } + + if ( freedst && dst ) { + SDL_RWclose(dst); + } + return((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); +} diff --git a/3rdparty/SDL/src/video/SDL_cursor.c b/3rdparty/SDL/src/video/SDL_cursor.c new file mode 100644 index 0000000..5d747d3 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_cursor.c @@ -0,0 +1,758 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General cursor handling code for SDL */ + +#include "SDL_mutex.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "SDL_blit.h" +#include "SDL_sysvideo.h" +#include "SDL_cursor_c.h" +#include "SDL_pixels_c.h" +#include "default_cursor.h" +#include "../events/SDL_sysevents.h" +#include "../events/SDL_events_c.h" + +/* These are static for our cursor handling code */ +volatile int SDL_cursorstate = CURSOR_VISIBLE; +SDL_Cursor *SDL_cursor = NULL; +static SDL_Cursor *SDL_defcursor = NULL; +SDL_mutex *SDL_cursorlock = NULL; + +/* Public functions */ +void SDL_CursorQuit(void) +{ + if ( SDL_cursor != NULL ) { + SDL_Cursor *cursor; + + SDL_cursorstate &= ~CURSOR_VISIBLE; + if ( SDL_cursor != SDL_defcursor ) { + SDL_FreeCursor(SDL_cursor); + } + SDL_cursor = NULL; + if ( SDL_defcursor != NULL ) { + cursor = SDL_defcursor; + SDL_defcursor = NULL; + SDL_FreeCursor(cursor); + } + } + if ( SDL_cursorlock != NULL ) { + SDL_DestroyMutex(SDL_cursorlock); + SDL_cursorlock = NULL; + } +} +int SDL_CursorInit(Uint32 multithreaded) +{ + /* We don't have mouse focus, and the cursor isn't drawn yet */ +#ifndef IPOD + SDL_cursorstate = CURSOR_VISIBLE; +#endif + + /* Create the default cursor */ + if ( SDL_defcursor == NULL ) { + SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask, + DEFAULT_CWIDTH, DEFAULT_CHEIGHT, + DEFAULT_CHOTX, DEFAULT_CHOTY); + SDL_SetCursor(SDL_defcursor); + } + + /* Create a lock if necessary */ + if ( multithreaded ) { + SDL_cursorlock = SDL_CreateMutex(); + } + + /* That's it! */ + return(0); +} + +/* Multi-thread support for cursors */ +#ifndef SDL_LockCursor +void SDL_LockCursor(void) +{ + if ( SDL_cursorlock ) { + SDL_mutexP(SDL_cursorlock); + } +} +#endif +#ifndef SDL_UnlockCursor +void SDL_UnlockCursor(void) +{ + if ( SDL_cursorlock ) { + SDL_mutexV(SDL_cursorlock); + } +} +#endif + +/* Software cursor drawing support */ +SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ + SDL_VideoDevice *video = current_video; + int savelen; + int i; + SDL_Cursor *cursor; + + /* Make sure the width is a multiple of 8 */ + w = ((w+7)&~7); + + /* Sanity check the hot spot */ + if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) { + SDL_SetError("Cursor hot spot doesn't lie within cursor"); + return(NULL); + } + + /* Allocate memory for the cursor */ + cursor = (SDL_Cursor *)SDL_malloc(sizeof *cursor); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + savelen = (w*4)*h; + cursor->area.x = 0; + cursor->area.y = 0; + cursor->area.w = w; + cursor->area.h = h; + cursor->hot_x = hot_x; + cursor->hot_y = hot_y; + cursor->data = (Uint8 *)SDL_malloc((w/8)*h*2); + cursor->mask = cursor->data+((w/8)*h); + cursor->save[0] = (Uint8 *)SDL_malloc(savelen*2); + cursor->save[1] = cursor->save[0] + savelen; + cursor->wm_cursor = NULL; + if ( ! cursor->data || ! cursor->save[0] ) { + SDL_FreeCursor(cursor); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=((w/8)*h)-1; i>=0; --i ) { + cursor->data[i] = data[i]; + cursor->mask[i] = mask[i] | data[i]; + } + SDL_memset(cursor->save[0], 0, savelen*2); + + /* If the window manager gives us a good cursor, we're done! */ + if ( video->CreateWMCursor ) { + cursor->wm_cursor = video->CreateWMCursor(video, data, mask, + w, h, hot_x, hot_y); + } else { + cursor->wm_cursor = NULL; + } + return(cursor); +} + +/* SDL_SetCursor(NULL) can be used to force the cursor redraw, + if this is desired for any reason. This is used when setting + the video mode and when the SDL window gains the mouse focus. + */ +void SDL_SetCursor (SDL_Cursor *cursor) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Make sure that the video subsystem has been initialized */ + if ( ! video ) { + return; + } + + /* Prevent the event thread from moving the mouse */ + SDL_LockCursor(); + + /* Set the new cursor */ + if ( cursor && (cursor != SDL_cursor) ) { + /* Erase the current mouse position */ + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_EraseCursor(SDL_VideoSurface); + } else if ( video->MoveWMCursor ) { + /* If the video driver is moving the cursor directly, + it needs to hide the old cursor before (possibly) + showing the new one. (But don't erase NULL cursor) + */ + if ( SDL_cursor && video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + } + SDL_cursor = cursor; + } + + /* Draw the new mouse cursor */ + if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) { + /* Use window manager cursor if possible */ + int show_wm_cursor = 0; + if ( SDL_cursor->wm_cursor && video->ShowWMCursor ) { + show_wm_cursor = video->ShowWMCursor(this, SDL_cursor->wm_cursor); + } + if ( show_wm_cursor ) { + SDL_cursorstate &= ~CURSOR_USINGSW; + } else { + SDL_cursorstate |= CURSOR_USINGSW; + if ( video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + { int x, y; + SDL_GetMouseState(&x, &y); + SDL_cursor->area.x = (x - SDL_cursor->hot_x); + SDL_cursor->area.y = (y - SDL_cursor->hot_y); + } + SDL_DrawCursor(SDL_VideoSurface); + } + } else { + /* Erase window manager mouse (cursor not visible) */ + if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) { + SDL_EraseCursor(SDL_VideoSurface); + } else { + if ( video ) { + if ( video->ShowWMCursor ) { + video->ShowWMCursor(this, NULL); + } + } + } + } + SDL_UnlockCursor(); +} + +SDL_Cursor * SDL_GetCursor (void) +{ + return(SDL_cursor); +} + +void SDL_FreeCursor (SDL_Cursor *cursor) +{ + if ( cursor ) { + if ( cursor == SDL_cursor ) { + SDL_SetCursor(SDL_defcursor); + } + if ( cursor != SDL_defcursor ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( cursor->data ) { + SDL_free(cursor->data); + } + if ( cursor->save[0] ) { + SDL_free(cursor->save[0]); + } + if ( video && cursor->wm_cursor ) { + if ( video->FreeWMCursor ) { + video->FreeWMCursor(this, cursor->wm_cursor); + } + } + SDL_free(cursor); + } + } +} + +int SDL_ShowCursor (int toggle) +{ + int showing; + + showing = (SDL_cursorstate & CURSOR_VISIBLE); + if ( toggle >= 0 ) { + SDL_LockCursor(); + if ( toggle ) { + SDL_cursorstate |= CURSOR_VISIBLE; + } else { + SDL_cursorstate &= ~CURSOR_VISIBLE; + } + SDL_UnlockCursor(); + if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + SDL_SetCursor(NULL); + if ( video && video->CheckMouseMode ) { + video->CheckMouseMode(this); + } + } + } else { + /* Query current state */ ; + } + return(showing ? 1 : 0); +} + +void SDL_WarpMouse (Uint16 x, Uint16 y) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( !video || !SDL_PublicSurface ) { + SDL_SetError("A video mode must be set before warping mouse"); + return; + } + + /* If we have an offset video mode, offset the mouse coordinates */ + if (this->screen->pitch == 0) { + x += this->screen->offset / this->screen->format->BytesPerPixel; + y += this->screen->offset; + } else { + x += (this->screen->offset % this->screen->pitch) / + this->screen->format->BytesPerPixel; + y += (this->screen->offset / this->screen->pitch); + } + + /* This generates a mouse motion event */ + if ( video->WarpWMCursor ) { + video->WarpWMCursor(this, x, y); + } else { + SDL_PrivateMouseMotion(0, 0, x, y); + } +} + +void SDL_MoveCursor(int x, int y) +{ + SDL_VideoDevice *video = current_video; + + /* Erase and update the current mouse position */ + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + /* Erase and redraw mouse cursor in new position */ + SDL_LockCursor(); + SDL_EraseCursor(SDL_VideoSurface); + SDL_cursor->area.x = (x - SDL_cursor->hot_x); + SDL_cursor->area.y = (y - SDL_cursor->hot_y); + SDL_DrawCursor(SDL_VideoSurface); + SDL_UnlockCursor(); + } else if ( video->MoveWMCursor ) { + video->MoveWMCursor(video, x, y); + } +} + +/* Keep track of the current cursor colors */ +static int palette_changed = 1; +static Uint8 pixels8[2]; + +void SDL_CursorPaletteChanged(void) +{ + palette_changed = 1; +} + +void SDL_MouseRect(SDL_Rect *area) +{ + int clip_diff; + + *area = SDL_cursor->area; + if ( area->x < 0 ) { + area->w += area->x; + area->x = 0; + } + if ( area->y < 0 ) { + area->h += area->y; + area->y = 0; + } + clip_diff = (area->x+area->w)-SDL_VideoSurface->w; + if ( clip_diff > 0 ) { + area->w = area->w < clip_diff ? 0 : area->w-clip_diff; + } + clip_diff = (area->y+area->h)-SDL_VideoSurface->h; + if ( clip_diff > 0 ) { + area->h = area->h < clip_diff ? 0 : area->h-clip_diff; + } +} + +static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) +{ + const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; + int i, w, h; + Uint8 *data, datab; + Uint8 *mask, maskb; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; + switch (screen->format->BytesPerPixel) { + + case 1: { + Uint8 *dst; + int dstskip; + + if ( palette_changed ) { + pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x; + dstskip = screen->pitch-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = pixels8[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 2: { + Uint16 *dst; + int dstskip; + + dst = (Uint16 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch/2 + + SDL_cursor->area.x; + dstskip = (screen->pitch/2)-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = (Uint16)pixels[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + + case 3: { + Uint8 *dst; + int dstskip; + + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x*3; + dstskip = screen->pitch-area->w*3; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + SDL_memset(dst,pixels[datab>>7],3); + } + maskb <<= 1; + datab <<= 1; + dst += 3; + } + } + dst += dstskip; + } + } + break; + + case 4: { + Uint32 *dst; + int dstskip; + + dst = (Uint32 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch/4 + + SDL_cursor->area.x; + dstskip = (screen->pitch/4)-area->w; + + for ( h=area->h; h; h-- ) { + for ( w=area->w/8; w; w-- ) { + maskb = *mask++; + datab = *data++; + for ( i=0; i<8; ++i ) { + if ( maskb & 0x80 ) { + *dst = pixels[datab>>7]; + } + maskb <<= 1; + datab <<= 1; + dst++; + } + } + dst += dstskip; + } + } + break; + } +} + +static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) +{ + const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; + int h; + int x, minx, maxx; + Uint8 *data, datab = 0; + Uint8 *mask, maskb = 0; + Uint8 *dst; + int dstbpp, dstskip; + + data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; + mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; + dstbpp = screen->format->BytesPerPixel; + dst = (Uint8 *)screen->pixels + + (SDL_cursor->area.y+area->y)*screen->pitch + + SDL_cursor->area.x*dstbpp; + dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; + + minx = area->x; + maxx = area->x+area->w; + if ( screen->format->BytesPerPixel == 1 ) { + if ( palette_changed ) { + pixels8[0] = (Uint8)SDL_MapRGB(screen->format, 255, 255, 255); + pixels8[1] = (Uint8)SDL_MapRGB(screen->format, 0, 0, 0); + palette_changed = 0; + } + for ( h=area->h; h; h-- ) { + for ( x=0; x<SDL_cursor->area.w; ++x ) { + if ( (x%8) == 0 ) { + maskb = *mask++; + datab = *data++; + } + if ( (x >= minx) && (x < maxx) ) { + if ( maskb & 0x80 ) { + SDL_memset(dst, pixels8[datab>>7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } else { + for ( h=area->h; h; h-- ) { + for ( x=0; x<SDL_cursor->area.w; ++x ) { + if ( (x%8) == 0 ) { + maskb = *mask++; + datab = *data++; + } + if ( (x >= minx) && (x < maxx) ) { + if ( maskb & 0x80 ) { + SDL_memset(dst, pixels[datab>>7], dstbpp); + } + } + maskb <<= 1; + datab <<= 1; + dst += dstbpp; + } + dst += dstskip; + } + } +} + +/* This handles the ugly work of converting the saved cursor background from + the pixel format of the shadow surface to that of the video surface. + This is only necessary when blitting from a shadow surface of a different + pixel format than the video surface, and using a software rendered cursor. +*/ +static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) +{ + SDL_BlitInfo info; + SDL_loblit RunBlit; + + /* Make sure we can steal the blit mapping */ + if ( screen->map->dst != SDL_VideoSurface ) { + return; + } + + /* Set up the blit information */ + info.s_pixels = SDL_cursor->save[1]; + info.s_width = w; + info.s_height = h; + info.s_skip = 0; + info.d_pixels = SDL_cursor->save[0]; + info.d_width = w; + info.d_height = h; + info.d_skip = 0; + info.aux_data = screen->map->sw_data->aux_data; + info.src = screen->format; + info.table = screen->map->table; + info.dst = SDL_VideoSurface->format; + RunBlit = screen->map->sw_data->blit; + + /* Run the actual software blit */ + RunBlit(&info); +} + +void SDL_DrawCursorNoLock(SDL_Surface *screen) +{ + SDL_Rect area; + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ( (area.w == 0) || (area.h == 0) ) { + return; + } + + /* Copy mouse background */ + { int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ( (screen == SDL_VideoSurface) || + FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { + dst = SDL_cursor->save[0]; + } else { + dst = SDL_cursor->save[1]; + } + src = (Uint8 *)screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w*screenbpp; + h = area.h; + while ( h-- ) { + SDL_memcpy(dst, src, w); + dst += w; + src += screen->pitch; + } + } + + /* Draw the mouse cursor */ + area.x -= SDL_cursor->area.x; + area.y -= SDL_cursor->area.y; + if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { + SDL_DrawCursorFast(screen, &area); + } else { + SDL_DrawCursorSlow(screen, &area); + } +} + +void SDL_DrawCursor(SDL_Surface *screen) +{ + /* Lock the screen if necessary */ + if ( screen == NULL ) { + return; + } + if ( SDL_MUSTLOCK(screen) ) { + if ( SDL_LockSurface(screen) < 0 ) { + return; + } + } + + SDL_DrawCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if ( SDL_MUSTLOCK(screen) ) { + SDL_UnlockSurface(screen); + } + if ( (screen == SDL_VideoSurface) && + ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect area; + + SDL_MouseRect(&area); + + /* This can be called before a video mode is set */ + if ( video->UpdateRects ) { + video->UpdateRects(this, 1, &area); + } + } +} + +void SDL_EraseCursorNoLock(SDL_Surface *screen) +{ + SDL_Rect area; + + /* Get the mouse rectangle, clipped to the screen */ + SDL_MouseRect(&area); + if ( (area.w == 0) || (area.h == 0) ) { + return; + } + + /* Copy mouse background */ + { int w, h, screenbpp; + Uint8 *src, *dst; + + /* Set up the copy pointers */ + screenbpp = screen->format->BytesPerPixel; + if ( (screen == SDL_VideoSurface) || + FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { + src = SDL_cursor->save[0]; + } else { + src = SDL_cursor->save[1]; + } + dst = (Uint8 *)screen->pixels + area.y * screen->pitch + + area.x * screenbpp; + + /* Perform the copy */ + w = area.w*screenbpp; + h = area.h; + while ( h-- ) { + SDL_memcpy(dst, src, w); + src += w; + dst += screen->pitch; + } + + /* Perform pixel conversion on cursor background */ + if ( src > SDL_cursor->save[1] ) { + SDL_ConvertCursorSave(screen, area.w, area.h); + } + } +} + +void SDL_EraseCursor(SDL_Surface *screen) +{ + /* Lock the screen if necessary */ + if ( screen == NULL ) { + return; + } + if ( SDL_MUSTLOCK(screen) ) { + if ( SDL_LockSurface(screen) < 0 ) { + return; + } + } + + SDL_EraseCursorNoLock(screen); + + /* Unlock the screen and update if necessary */ + if ( SDL_MUSTLOCK(screen) ) { + SDL_UnlockSurface(screen); + } + if ( (screen == SDL_VideoSurface) && + ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect area; + + SDL_MouseRect(&area); + if ( video->UpdateRects ) { + video->UpdateRects(this, 1, &area); + } + } +} + +/* Reset the cursor on video mode change + FIXME: Keep track of all cursors, and reset them all. + */ +void SDL_ResetCursor(void) +{ + int savelen; + + if ( SDL_cursor ) { + savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; + SDL_cursor->area.x = 0; + SDL_cursor->area.y = 0; + SDL_memset(SDL_cursor->save[0], 0, savelen); + } +} diff --git a/3rdparty/SDL/src/video/SDL_cursor_c.h b/3rdparty/SDL/src/video/SDL_cursor_c.h new file mode 100644 index 0000000..8be8df9 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_cursor_c.h @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful variables and functions from SDL_cursor.c */ +#include "SDL_mouse.h" + +extern int SDL_CursorInit(Uint32 flags); +extern void SDL_CursorPaletteChanged(void); +extern void SDL_DrawCursor(SDL_Surface *screen); +extern void SDL_DrawCursorNoLock(SDL_Surface *screen); +extern void SDL_EraseCursor(SDL_Surface *screen); +extern void SDL_EraseCursorNoLock(SDL_Surface *screen); +extern void SDL_UpdateCursor(SDL_Surface *screen); +extern void SDL_ResetCursor(void); +extern void SDL_MoveCursor(int x, int y); +extern void SDL_CursorQuit(void); + +#define INLINE_MOUSELOCK +#ifdef INLINE_MOUSELOCK +/* Inline (macro) versions of the mouse lock functions */ +#include "SDL_mutex.h" + +extern SDL_mutex *SDL_cursorlock; + +#define SDL_LockCursor() \ + do { \ + if ( SDL_cursorlock ) { \ + SDL_mutexP(SDL_cursorlock); \ + } \ + } while ( 0 ) +#define SDL_UnlockCursor() \ + do { \ + if ( SDL_cursorlock ) { \ + SDL_mutexV(SDL_cursorlock); \ + } \ + } while ( 0 ) +#else +extern void SDL_LockCursor(void); +extern void SDL_UnlockCursor(void); +#endif /* INLINE_MOUSELOCK */ + +/* Only for low-level mouse cursor drawing */ +extern SDL_Cursor *SDL_cursor; +extern void SDL_MouseRect(SDL_Rect *area); + +/* State definitions for the SDL cursor */ +#define CURSOR_VISIBLE 0x01 +#define CURSOR_USINGSW 0x10 +#define SHOULD_DRAWCURSOR(X) \ + (((X)&(CURSOR_VISIBLE|CURSOR_USINGSW)) == \ + (CURSOR_VISIBLE|CURSOR_USINGSW)) + +extern volatile int SDL_cursorstate; diff --git a/3rdparty/SDL/src/video/SDL_gamma.c b/3rdparty/SDL/src/video/SDL_gamma.c new file mode 100644 index 0000000..4fd0370 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_gamma.c @@ -0,0 +1,233 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Gamma correction support */ + +#ifdef HAVE_MATH_H +#include <math.h> /* Used for calculating gamma ramps */ +#else +/* Math routines from uClibc: http://www.uclibc.org */ +#include "math_private.h" +#include "e_sqrt.h" +#include "e_pow.h" +#include "e_log.h" +#define pow(x, y) __ieee754_pow(x, y) +#define log(x) __ieee754_log(x) +#endif + +#include "SDL_sysvideo.h" + + +static void CalculateGammaRamp(float gamma, Uint16 *ramp) +{ + int i; + + /* 0.0 gamma is all black */ + if ( gamma <= 0.0f ) { + for ( i=0; i<256; ++i ) { + ramp[i] = 0; + } + return; + } else + /* 1.0 gamma is identity */ + if ( gamma == 1.0f ) { + for ( i=0; i<256; ++i ) { + ramp[i] = (i << 8) | i; + } + return; + } else + /* Calculate a real gamma ramp */ + { int value; + gamma = 1.0f / gamma; + for ( i=0; i<256; ++i ) { + value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5); + if ( value > 65535 ) { + value = 65535; + } + ramp[i] = (Uint16)value; + } + } +} +static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp) +{ + /* The following is adapted from a post by Garrett Bass on OpenGL + Gamedev list, March 4, 2000. + */ + float sum = 0.0f; + int i, count = 0; + + *gamma = 1.0; + for ( i = 1; i < 256; ++i ) { + if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { + double B = (double)i / 256.0; + double A = ramp[i] / 65535.0; + sum += (float) ( log(A) / log(B) ); + count++; + } + } + if ( count && sum > 0.0f ) { + *gamma = 1.0f / (sum / count); + } +} + +int SDL_SetGamma(float red, float green, float blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + succeeded = -1; + /* Prefer using SetGammaRamp(), as it's more flexible */ + { + Uint16 ramp[3][256]; + + CalculateGammaRamp(red, ramp[0]); + CalculateGammaRamp(green, ramp[1]); + CalculateGammaRamp(blue, ramp[2]); + succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]); + } + if ( (succeeded < 0) && video->SetGamma ) { + SDL_ClearError(); + succeeded = video->SetGamma(this, red, green, blue); + } + return succeeded; +} + +/* Calculating the gamma by integrating the gamma ramps isn't exact, + so this function isn't officially supported. +*/ +int SDL_GetGamma(float *red, float *green, float *blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + succeeded = -1; + /* Prefer using GetGammaRamp(), as it's more flexible */ + { + Uint16 ramp[3][256]; + + succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]); + if ( succeeded >= 0 ) { + CalculateGammaFromRamp(red, ramp[0]); + CalculateGammaFromRamp(green, ramp[1]); + CalculateGammaFromRamp(blue, ramp[2]); + } + } + if ( (succeeded < 0) && video->GetGamma ) { + SDL_ClearError(); + succeeded = video->GetGamma(this, red, green, blue); + } + return succeeded; +} + +int SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue) +{ + int succeeded; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Surface *screen = SDL_PublicSurface; + + /* Verify the screen parameter */ + if ( !screen ) { + SDL_SetError("No video mode has been set"); + return -1; + } + + /* Lazily allocate the gamma tables */ + if ( ! video->gamma ) { + SDL_GetGammaRamp(0, 0, 0); + } + + /* Fill the gamma table with the new values */ + if ( red ) { + SDL_memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma)); + } + if ( green ) { + SDL_memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma)); + } + if ( blue ) { + SDL_memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma)); + } + + /* Gamma correction always possible on split palettes */ + if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { + SDL_Palette *pal = screen->format->palette; + + /* If physical palette has been set independently, use it */ + if(video->physpal) + pal = video->physpal; + + SDL_SetPalette(screen, SDL_PHYSPAL, + pal->colors, 0, pal->ncolors); + return 0; + } + + /* Try to set the gamma ramp in the driver */ + succeeded = -1; + if ( video->SetGammaRamp ) { + succeeded = video->SetGammaRamp(this, video->gamma); + } else { + SDL_SetError("Gamma ramp manipulation not supported"); + } + return succeeded; +} + +int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Lazily allocate the gamma table */ + if ( ! video->gamma ) { + video->gamma = SDL_malloc(3*256*sizeof(*video->gamma)); + if ( ! video->gamma ) { + SDL_OutOfMemory(); + return -1; + } + if ( video->GetGammaRamp ) { + /* Get the real hardware gamma */ + video->GetGammaRamp(this, video->gamma); + } else { + /* Assume an identity gamma */ + int i; + for ( i=0; i<256; ++i ) { + video->gamma[0*256+i] = (i << 8) | i; + video->gamma[1*256+i] = (i << 8) | i; + video->gamma[2*256+i] = (i << 8) | i; + } + } + } + + /* Just copy from our internal table */ + if ( red ) { + SDL_memcpy(red, &video->gamma[0*256], 256*sizeof(*red)); + } + if ( green ) { + SDL_memcpy(green, &video->gamma[1*256], 256*sizeof(*green)); + } + if ( blue ) { + SDL_memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue)); + } + return 0; +} diff --git a/3rdparty/SDL/src/video/SDL_glfuncs.h b/3rdparty/SDL/src/video/SDL_glfuncs.h new file mode 100644 index 0000000..fb2d964 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_glfuncs.h @@ -0,0 +1,341 @@ +/* list of OpenGL functions sorted alphabetically + If you need to use a GL function from the SDL video subsystem, + change it's entry from SDL_PROC_UNUSED to SDL_PROC and rebuild. +*/ +#define SDL_PROC_UNUSED(ret,func,params) +SDL_PROC_UNUSED(void,glAccum,(GLenum,GLfloat)) +SDL_PROC_UNUSED(void,glAlphaFunc,(GLenum,GLclampf)) +SDL_PROC_UNUSED(GLboolean,glAreTexturesResident,(GLsizei,const GLuint*,GLboolean*)) +SDL_PROC_UNUSED(void,glArrayElement,(GLint)) +SDL_PROC(void,glBegin,(GLenum)) +SDL_PROC(void,glBindTexture,(GLenum,GLuint)) +SDL_PROC_UNUSED(void,glBitmap,(GLsizei,GLsizei,GLfloat,GLfloat,GLfloat,GLfloat,const GLubyte*)) +SDL_PROC(void,glBlendFunc,(GLenum,GLenum)) +SDL_PROC_UNUSED(void,glCallList,(GLuint)) +SDL_PROC_UNUSED(void,glCallLists,(GLsizei,GLenum,const GLvoid*)) +SDL_PROC_UNUSED(void,glClear,(GLbitfield)) +SDL_PROC_UNUSED(void,glClearAccum,(GLfloat,GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glClearColor,(GLclampf,GLclampf,GLclampf,GLclampf)) +SDL_PROC_UNUSED(void,glClearDepth,(GLclampd)) +SDL_PROC_UNUSED(void,glClearIndex,(GLfloat)) +SDL_PROC_UNUSED(void,glClearStencil,(GLint)) +SDL_PROC_UNUSED(void,glClipPlane,(GLenum,const GLdouble*)) +SDL_PROC_UNUSED(void,glColor3b,(GLbyte,GLbyte,GLbyte)) +SDL_PROC_UNUSED(void,glColor3bv,(const GLbyte*)) +SDL_PROC_UNUSED(void,glColor3d,(GLdouble,GLdouble,GLdouble)) +SDL_PROC_UNUSED(void,glColor3dv,(const GLdouble*)) +SDL_PROC_UNUSED(void,glColor3f,(GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glColor3fv,(const GLfloat*)) +SDL_PROC_UNUSED(void,glColor3i,(GLint,GLint,GLint)) +SDL_PROC_UNUSED(void,glColor3iv,(const GLint*)) +SDL_PROC_UNUSED(void,glColor3s,(GLshort,GLshort,GLshort)) +SDL_PROC_UNUSED(void,glColor3sv,(const GLshort*)) +SDL_PROC_UNUSED(void,glColor3ub,(GLubyte,GLubyte,GLubyte)) +SDL_PROC_UNUSED(void,glColor3ubv,(const GLubyte*)) +SDL_PROC_UNUSED(void,glColor3ui,(GLuint,GLuint,GLuint)) +SDL_PROC_UNUSED(void,glColor3uiv,(const GLuint*)) +SDL_PROC_UNUSED(void,glColor3us,(GLushort,GLushort,GLushort)) +SDL_PROC_UNUSED(void,glColor3usv,(const GLushort*)) +SDL_PROC_UNUSED(void,glColor4b,(GLbyte,GLbyte,GLbyte,GLbyte)) +SDL_PROC_UNUSED(void,glColor4bv,(const GLbyte*)) +SDL_PROC_UNUSED(void,glColor4d,(GLdouble,GLdouble,GLdouble,GLdouble)) +SDL_PROC_UNUSED(void,glColor4dv,(const GLdouble*)) +SDL_PROC(void,glColor4f,(GLfloat,GLfloat,GLfloat,GLfloat)) +SDL_PROC_UNUSED(void,glColor4fv,(const GLfloat*)) +SDL_PROC_UNUSED(void,glColor4i,(GLint,GLint,GLint,GLint)) +SDL_PROC_UNUSED(void,glColor4iv,(const GLint*)) +SDL_PROC_UNUSED(void,glColor4s,(GLshort,GLshort,GLshort,GLshort)) +SDL_PROC_UNUSED(void,glColor4sv,(const GLshort*)) +SDL_PROC_UNUSED(void,glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)) +SDL_PROC_UNUSED(void,glColor4ubv,(const GLubyte *v)) +SDL_PROC_UNUSED(void,glColor4ui,(GLuint red, GLuint green, GLuint blue, GLuint alpha)) +SDL_PROC_UNUSED(void,glColor4uiv,(const GLuint *v)) +SDL_PROC_UNUSED(void,glColor4us,(GLushort red, GLushort green, GLushort blue, GLushort alpha)) +SDL_PROC_UNUSED(void,glColor4usv,(const GLushort *v)) +SDL_PROC_UNUSED(void,glColorMask,(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) +SDL_PROC_UNUSED(void,glColorMaterial,(GLenum face, GLenum mode)) +SDL_PROC_UNUSED(void,glColorPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)) +SDL_PROC_UNUSED(void,glCopyTexImage1D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border)) +SDL_PROC_UNUSED(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)) +SDL_PROC_UNUSED(void,glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)) +SDL_PROC_UNUSED(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC_UNUSED(void,glCullFace,(GLenum mode)) +SDL_PROC_UNUSED(void,glDeleteLists,(GLuint list, GLsizei range)) +SDL_PROC_UNUSED(void,glDeleteTextures,(GLsizei n, const GLuint *textures)) +SDL_PROC_UNUSED(void,glDepthFunc,(GLenum func)) +SDL_PROC_UNUSED(void,glDepthMask,(GLboolean flag)) +SDL_PROC_UNUSED(void,glDepthRange,(GLclampd zNear, GLclampd zFar)) +SDL_PROC(void,glDisable,(GLenum cap)) +SDL_PROC_UNUSED(void,glDisableClientState,(GLenum array)) +SDL_PROC_UNUSED(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count)) +SDL_PROC_UNUSED(void,glDrawBuffer,(GLenum mode)) +SDL_PROC_UNUSED(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)) +SDL_PROC_UNUSED(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glEdgeFlag,(GLboolean flag)) +SDL_PROC_UNUSED(void,glEdgeFlagPointer,(GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glEdgeFlagv,(const GLboolean *flag)) +SDL_PROC(void,glEnable,(GLenum cap)) +SDL_PROC_UNUSED(void,glEnableClientState,(GLenum array)) +SDL_PROC(void,glEnd,(void)) +SDL_PROC_UNUSED(void,glEndList,(void)) +SDL_PROC_UNUSED(void,glEvalCoord1d,(GLdouble u)) +SDL_PROC_UNUSED(void,glEvalCoord1dv,(const GLdouble *u)) +SDL_PROC_UNUSED(void,glEvalCoord1f,(GLfloat u)) +SDL_PROC_UNUSED(void,glEvalCoord1fv,(const GLfloat *u)) +SDL_PROC_UNUSED(void,glEvalCoord2d,(GLdouble u, GLdouble v)) +SDL_PROC_UNUSED(void,glEvalCoord2dv,(const GLdouble *u)) +SDL_PROC_UNUSED(void,glEvalCoord2f,(GLfloat u, GLfloat v)) +SDL_PROC_UNUSED(void,glEvalCoord2fv,(const GLfloat *u)) +SDL_PROC_UNUSED(void,glEvalMesh1,(GLenum mode, GLint i1, GLint i2)) +SDL_PROC_UNUSED(void,glEvalMesh2,(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)) +SDL_PROC_UNUSED(void,glEvalPoint1,(GLint i)) +SDL_PROC_UNUSED(void,glEvalPoint2,(GLint i, GLint j)) +SDL_PROC_UNUSED(void,glFeedbackBuffer,(GLsizei size, GLenum type, GLfloat *buffer)) +SDL_PROC_UNUSED(void,glFinish,(void)) +SDL_PROC(void,glFlush,(void)) +SDL_PROC_UNUSED(void,glFogf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glFogfv,(GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glFogi,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glFogiv,(GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glFrontFace,(GLenum mode)) +SDL_PROC_UNUSED(void,glFrustum,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +SDL_PROC_UNUSED(GLuint,glGenLists,(GLsizei range)) +SDL_PROC(void,glGenTextures,(GLsizei n, GLuint *textures)) +SDL_PROC_UNUSED(void,glGetBooleanv,(GLenum pname, GLboolean *params)) +SDL_PROC_UNUSED(void,glGetClipPlane,(GLenum plane, GLdouble *equation)) +SDL_PROC_UNUSED(void,glGetDoublev,(GLenum pname, GLdouble *params)) +SDL_PROC_UNUSED(GLenum,glGetError,(void)) +SDL_PROC_UNUSED(void,glGetFloatv,(GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetIntegerv,(GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetLightfv,(GLenum light, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetLightiv,(GLenum light, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetMapdv,(GLenum target, GLenum query, GLdouble *v)) +SDL_PROC_UNUSED(void,glGetMapfv,(GLenum target, GLenum query, GLfloat *v)) +SDL_PROC_UNUSED(void,glGetMapiv,(GLenum target, GLenum query, GLint *v)) +SDL_PROC_UNUSED(void,glGetMaterialfv,(GLenum face, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetMaterialiv,(GLenum face, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetPixelMapfv,(GLenum map, GLfloat *values)) +SDL_PROC_UNUSED(void,glGetPixelMapuiv,(GLenum map, GLuint *values)) +SDL_PROC_UNUSED(void,glGetPixelMapusv,(GLenum map, GLushort *values)) +SDL_PROC_UNUSED(void,glGetPointerv,(GLenum pname, GLvoid* *params)) +SDL_PROC_UNUSED(void,glGetPolygonStipple,(GLubyte *mask)) +SDL_PROC(const GLubyte *,glGetString,(GLenum name)) +SDL_PROC_UNUSED(void,glGetTexEnvfv,(GLenum target, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexEnviv,(GLenum target, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexGendv,(GLenum coord, GLenum pname, GLdouble *params)) +SDL_PROC_UNUSED(void,glGetTexGenfv,(GLenum coord, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexGeniv,(GLenum coord, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexImage,(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)) +SDL_PROC_UNUSED(void,glGetTexLevelParameterfv,(GLenum target, GLint level, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexLevelParameteriv,(GLenum target, GLint level, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glGetTexParameterfv,(GLenum target, GLenum pname, GLfloat *params)) +SDL_PROC_UNUSED(void,glGetTexParameteriv,(GLenum target, GLenum pname, GLint *params)) +SDL_PROC_UNUSED(void,glHint,(GLenum target, GLenum mode)) +SDL_PROC_UNUSED(void,glIndexMask,(GLuint mask)) +SDL_PROC_UNUSED(void,glIndexPointer,(GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(void,glIndexd,(GLdouble c)) +SDL_PROC_UNUSED(void,glIndexdv,(const GLdouble *c)) +SDL_PROC_UNUSED(void,glIndexf,(GLfloat c)) +SDL_PROC_UNUSED(void,glIndexfv,(const GLfloat *c)) +SDL_PROC_UNUSED(void,glIndexi,(GLint c)) +SDL_PROC_UNUSED(void,glIndexiv,(const GLint *c)) +SDL_PROC_UNUSED(void,glIndexs,(GLshort c)) +SDL_PROC_UNUSED(void,glIndexsv,(const GLshort *c)) +SDL_PROC_UNUSED(void,glIndexub,(GLubyte c)) +SDL_PROC_UNUSED(void,glIndexubv,(const GLubyte *c)) +SDL_PROC_UNUSED(void,glInitNames,(void)) +SDL_PROC_UNUSED(void,glInterleavedArrays,(GLenum format, GLsizei stride, const GLvoid *pointer)) +SDL_PROC_UNUSED(GLboolean,glIsEnabled,(GLenum cap)) +SDL_PROC_UNUSED(GLboolean,glIsList,(GLuint list)) +SDL_PROC_UNUSED(GLboolean,glIsTexture,(GLuint texture)) +SDL_PROC_UNUSED(void,glLightModelf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glLightModelfv,(GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glLightModeli,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glLightModeliv,(GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glLightf,(GLenum light, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glLightfv,(GLenum light, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glLighti,(GLenum light, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glLightiv,(GLenum light, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glLineStipple,(GLint factor, GLushort pattern)) +SDL_PROC_UNUSED(void,glLineWidth,(GLfloat width)) +SDL_PROC_UNUSED(void,glListBase,(GLuint base)) +SDL_PROC(void,glLoadIdentity,(void)) +SDL_PROC_UNUSED(void,glLoadMatrixd,(const GLdouble *m)) +SDL_PROC_UNUSED(void,glLoadMatrixf,(const GLfloat *m)) +SDL_PROC_UNUSED(void,glLoadName,(GLuint name)) +SDL_PROC_UNUSED(void,glLogicOp,(GLenum opcode)) +SDL_PROC_UNUSED(void,glMap1d,(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points)) +SDL_PROC_UNUSED(void,glMap1f,(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points)) +SDL_PROC_UNUSED(void,glMap2d,(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points)) +SDL_PROC_UNUSED(void,glMap2f,(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points)) +SDL_PROC_UNUSED(void,glMapGrid1d,(GLint un, GLdouble u1, GLdouble u2)) +SDL_PROC_UNUSED(void,glMapGrid1f,(GLint un, GLfloat u1, GLfloat u2)) +SDL_PROC_UNUSED(void,glMapGrid2d,(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)) +SDL_PROC_UNUSED(void,glMapGrid2f,(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)) +SDL_PROC_UNUSED(void,glMaterialf,(GLenum face, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glMaterialfv,(GLenum face, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glMateriali,(GLenum face, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glMaterialiv,(GLenum face, GLenum pname, const GLint *params)) +SDL_PROC(void,glMatrixMode,(GLenum mode)) +SDL_PROC_UNUSED(void,glMultMatrixd,(const GLdouble *m)) +SDL_PROC_UNUSED(void,glMultMatrixf,(const GLfloat *m)) +SDL_PROC_UNUSED(void,glNewList,(GLuint list, GLenum mode)) +SDL_PROC_UNUSED(void,glNormal3b,(GLbyte nx, GLbyte ny, GLbyte nz)) +SDL_PROC_UNUSED(void,glNormal3bv,(const GLbyte *v)) +SDL_PROC_UNUSED(void,glNormal3d,(GLdouble nx, GLdouble ny, GLdouble nz)) +SDL_PROC_UNUSED(void,glNormal3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glNormal3f,(GLfloat nx, GLfloat ny, GLfloat nz)) +SDL_PROC_UNUSED(void,glNormal3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glNormal3i,(GLint nx, GLint ny, GLint nz)) +SDL_PROC_UNUSED(void,glNormal3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glNormal3s,(GLshort nx, GLshort ny, GLshort nz)) +SDL_PROC_UNUSED(void,glNormal3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glNormalPointer,(GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +SDL_PROC_UNUSED(void,glPassThrough,(GLfloat token)) +SDL_PROC_UNUSED(void,glPixelMapfv,(GLenum map, GLsizei mapsize, const GLfloat *values)) +SDL_PROC_UNUSED(void,glPixelMapuiv,(GLenum map, GLsizei mapsize, const GLuint *values)) +SDL_PROC_UNUSED(void,glPixelMapusv,(GLenum map, GLsizei mapsize, const GLushort *values)) +SDL_PROC_UNUSED(void,glPixelStoref,(GLenum pname, GLfloat param)) +SDL_PROC(void,glPixelStorei,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glPixelTransferf,(GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glPixelTransferi,(GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glPixelZoom,(GLfloat xfactor, GLfloat yfactor)) +SDL_PROC_UNUSED(void,glPointSize,(GLfloat size)) +SDL_PROC_UNUSED(void,glPolygonMode,(GLenum face, GLenum mode)) +SDL_PROC_UNUSED(void,glPolygonOffset,(GLfloat factor, GLfloat units)) +SDL_PROC_UNUSED(void,glPolygonStipple,(const GLubyte *mask)) +SDL_PROC(void,glPopAttrib,(void)) +SDL_PROC(void,glPopClientAttrib,(void)) +SDL_PROC(void,glPopMatrix,(void)) +SDL_PROC_UNUSED(void,glPopName,(void)) +SDL_PROC_UNUSED(void,glPrioritizeTextures,(GLsizei n, const GLuint *textures, const GLclampf *priorities)) +SDL_PROC(void,glPushAttrib,(GLbitfield mask)) +SDL_PROC(void,glPushClientAttrib,(GLbitfield mask)) +SDL_PROC(void,glPushMatrix,(void)) +SDL_PROC_UNUSED(void,glPushName,(GLuint name)) +SDL_PROC_UNUSED(void,glRasterPos2d,(GLdouble x, GLdouble y)) +SDL_PROC_UNUSED(void,glRasterPos2dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos2f,(GLfloat x, GLfloat y)) +SDL_PROC_UNUSED(void,glRasterPos2fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos2i,(GLint x, GLint y)) +SDL_PROC_UNUSED(void,glRasterPos2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos2s,(GLshort x, GLshort y)) +SDL_PROC_UNUSED(void,glRasterPos2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glRasterPos3d,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glRasterPos3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos3f,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glRasterPos3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos3i,(GLint x, GLint y, GLint z)) +SDL_PROC_UNUSED(void,glRasterPos3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos3s,(GLshort x, GLshort y, GLshort z)) +SDL_PROC_UNUSED(void,glRasterPos3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glRasterPos4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +SDL_PROC_UNUSED(void,glRasterPos4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glRasterPos4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +SDL_PROC_UNUSED(void,glRasterPos4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glRasterPos4i,(GLint x, GLint y, GLint z, GLint w)) +SDL_PROC_UNUSED(void,glRasterPos4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glRasterPos4s,(GLshort x, GLshort y, GLshort z, GLshort w)) +SDL_PROC_UNUSED(void,glRasterPos4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glReadBuffer,(GLenum mode)) +SDL_PROC_UNUSED(void,glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) +SDL_PROC_UNUSED(void,glRectd,(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)) +SDL_PROC_UNUSED(void,glRectdv,(const GLdouble *v1, const GLdouble *v2)) +SDL_PROC_UNUSED(void,glRectf,(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)) +SDL_PROC_UNUSED(void,glRectfv,(const GLfloat *v1, const GLfloat *v2)) +SDL_PROC_UNUSED(void,glRecti,(GLint x1, GLint y1, GLint x2, GLint y2)) +SDL_PROC_UNUSED(void,glRectiv,(const GLint *v1, const GLint *v2)) +SDL_PROC_UNUSED(void,glRects,(GLshort x1, GLshort y1, GLshort x2, GLshort y2)) +SDL_PROC_UNUSED(void,glRectsv,(const GLshort *v1, const GLshort *v2)) +SDL_PROC_UNUSED(GLint,glRenderMode,(GLenum mode)) +SDL_PROC_UNUSED(void,glRotated,(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glRotatef,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glScaled,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glScalef,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glScissor,(GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC_UNUSED(void,glSelectBuffer,(GLsizei size, GLuint *buffer)) +SDL_PROC_UNUSED(void,glShadeModel,(GLenum mode)) +SDL_PROC_UNUSED(void,glStencilFunc,(GLenum func, GLint ref, GLuint mask)) +SDL_PROC_UNUSED(void,glStencilMask,(GLuint mask)) +SDL_PROC_UNUSED(void,glStencilOp,(GLenum fail, GLenum zfail, GLenum zpass)) +SDL_PROC_UNUSED(void,glTexCoord1d,(GLdouble s)) +SDL_PROC_UNUSED(void,glTexCoord1dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord1f,(GLfloat s)) +SDL_PROC_UNUSED(void,glTexCoord1fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord1i,(GLint s)) +SDL_PROC_UNUSED(void,glTexCoord1iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord1s,(GLshort s)) +SDL_PROC_UNUSED(void,glTexCoord1sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord2d,(GLdouble s, GLdouble t)) +SDL_PROC_UNUSED(void,glTexCoord2dv,(const GLdouble *v)) +SDL_PROC(void,glTexCoord2f,(GLfloat s, GLfloat t)) +SDL_PROC_UNUSED(void,glTexCoord2fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord2i,(GLint s, GLint t)) +SDL_PROC_UNUSED(void,glTexCoord2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord2s,(GLshort s, GLshort t)) +SDL_PROC_UNUSED(void,glTexCoord2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord3d,(GLdouble s, GLdouble t, GLdouble r)) +SDL_PROC_UNUSED(void,glTexCoord3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord3f,(GLfloat s, GLfloat t, GLfloat r)) +SDL_PROC_UNUSED(void,glTexCoord3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord3i,(GLint s, GLint t, GLint r)) +SDL_PROC_UNUSED(void,glTexCoord3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord3s,(GLshort s, GLshort t, GLshort r)) +SDL_PROC_UNUSED(void,glTexCoord3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoord4d,(GLdouble s, GLdouble t, GLdouble r, GLdouble q)) +SDL_PROC_UNUSED(void,glTexCoord4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glTexCoord4f,(GLfloat s, GLfloat t, GLfloat r, GLfloat q)) +SDL_PROC_UNUSED(void,glTexCoord4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glTexCoord4i,(GLint s, GLint t, GLint r, GLint q)) +SDL_PROC_UNUSED(void,glTexCoord4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glTexCoord4s,(GLshort s, GLshort t, GLshort r, GLshort q)) +SDL_PROC_UNUSED(void,glTexCoord4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glTexCoordPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glTexEnvf,(GLenum target, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexEnvfv,(GLenum target, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glTexEnvi,(GLenum target, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexEnviv,(GLenum target, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexGend,(GLenum coord, GLenum pname, GLdouble param)) +SDL_PROC_UNUSED(void,glTexGendv,(GLenum coord, GLenum pname, const GLdouble *params)) +SDL_PROC_UNUSED(void,glTexGenf,(GLenum coord, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexGenfv,(GLenum coord, GLenum pname, const GLfloat *params)) +SDL_PROC_UNUSED(void,glTexGeni,(GLenum coord, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexGeniv,(GLenum coord, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexImage1D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC(void,glTexImage2D,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glTexParameterf,(GLenum target, GLenum pname, GLfloat param)) +SDL_PROC_UNUSED(void,glTexParameterfv,(GLenum target, GLenum pname, const GLfloat *params)) +SDL_PROC(void,glTexParameteri,(GLenum target, GLenum pname, GLint param)) +SDL_PROC_UNUSED(void,glTexParameteriv,(GLenum target, GLenum pname, const GLint *params)) +SDL_PROC_UNUSED(void,glTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC(void,glTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +SDL_PROC_UNUSED(void,glTranslated,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glTranslatef,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glVertex2d,(GLdouble x, GLdouble y)) +SDL_PROC_UNUSED(void,glVertex2dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex2f,(GLfloat x, GLfloat y)) +SDL_PROC_UNUSED(void,glVertex2fv,(const GLfloat *v)) +SDL_PROC(void,glVertex2i,(GLint x, GLint y)) +SDL_PROC_UNUSED(void,glVertex2iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex2s,(GLshort x, GLshort y)) +SDL_PROC_UNUSED(void,glVertex2sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertex3d,(GLdouble x, GLdouble y, GLdouble z)) +SDL_PROC_UNUSED(void,glVertex3dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex3f,(GLfloat x, GLfloat y, GLfloat z)) +SDL_PROC_UNUSED(void,glVertex3fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glVertex3i,(GLint x, GLint y, GLint z)) +SDL_PROC_UNUSED(void,glVertex3iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex3s,(GLshort x, GLshort y, GLshort z)) +SDL_PROC_UNUSED(void,glVertex3sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertex4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w)) +SDL_PROC_UNUSED(void,glVertex4dv,(const GLdouble *v)) +SDL_PROC_UNUSED(void,glVertex4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w)) +SDL_PROC_UNUSED(void,glVertex4fv,(const GLfloat *v)) +SDL_PROC_UNUSED(void,glVertex4i,(GLint x, GLint y, GLint z, GLint w)) +SDL_PROC_UNUSED(void,glVertex4iv,(const GLint *v)) +SDL_PROC_UNUSED(void,glVertex4s,(GLshort x, GLshort y, GLshort z, GLshort w)) +SDL_PROC_UNUSED(void,glVertex4sv,(const GLshort *v)) +SDL_PROC_UNUSED(void,glVertexPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +SDL_PROC(void,glViewport,(GLint x, GLint y, GLsizei width, GLsizei height)) diff --git a/3rdparty/SDL/src/video/SDL_leaks.h b/3rdparty/SDL/src/video/SDL_leaks.h new file mode 100644 index 0000000..74495c6 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_leaks.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Define this if you want surface leak detection code enabled */ +/*#define CHECK_LEAKS*/ + +/* Global variables used to check leaks in code using SDL */ + +#ifdef CHECK_LEAKS +extern int surfaces_allocated; +#endif diff --git a/3rdparty/SDL/src/video/SDL_pixels.c b/3rdparty/SDL/src/video/SDL_pixels.c new file mode 100644 index 0000000..1a7fd51 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_pixels.c @@ -0,0 +1,626 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* General (mostly internal) pixel/color manipulation routines for SDL */ + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_pixels_c.h" +#include "SDL_RLEaccel_c.h" + +/* Helper functions */ +/* + * Allocate a pixel format structure and fill it according to the given info. + */ +SDL_PixelFormat *SDL_AllocFormat(int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_PixelFormat *format; + Uint32 mask; + + /* Allocate an empty pixel format structure */ + format = SDL_malloc(sizeof(*format)); + if ( format == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(format, 0, sizeof(*format)); + format->alpha = SDL_ALPHA_OPAQUE; + + /* Set up the format */ + format->BitsPerPixel = bpp; + format->BytesPerPixel = (bpp+7)/8; + if ( Rmask || Bmask || Gmask ) { /* Packed pixels with custom mask */ + format->palette = NULL; + format->Rshift = 0; + format->Rloss = 8; + if ( Rmask ) { + for ( mask = Rmask; !(mask&0x01); mask >>= 1 ) + ++format->Rshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Rloss; + } + format->Gshift = 0; + format->Gloss = 8; + if ( Gmask ) { + for ( mask = Gmask; !(mask&0x01); mask >>= 1 ) + ++format->Gshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Gloss; + } + format->Bshift = 0; + format->Bloss = 8; + if ( Bmask ) { + for ( mask = Bmask; !(mask&0x01); mask >>= 1 ) + ++format->Bshift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Bloss; + } + format->Ashift = 0; + format->Aloss = 8; + if ( Amask ) { + for ( mask = Amask; !(mask&0x01); mask >>= 1 ) + ++format->Ashift; + for ( ; (mask&0x01); mask >>= 1 ) + --format->Aloss; + } + format->Rmask = Rmask; + format->Gmask = Gmask; + format->Bmask = Bmask; + format->Amask = Amask; + } else if ( bpp > 8 ) { /* Packed pixels with standard mask */ + /* R-G-B */ + if ( bpp > 24 ) + bpp = 24; + format->Rloss = 8-(bpp/3); + format->Gloss = 8-(bpp/3)-(bpp%3); + format->Bloss = 8-(bpp/3); + format->Rshift = ((bpp/3)+(bpp%3))+(bpp/3); + format->Gshift = (bpp/3); + format->Bshift = 0; + format->Rmask = ((0xFF>>format->Rloss)<<format->Rshift); + format->Gmask = ((0xFF>>format->Gloss)<<format->Gshift); + format->Bmask = ((0xFF>>format->Bloss)<<format->Bshift); + } else { + /* Palettized formats have no mask info */ + format->Rloss = 8; + format->Gloss = 8; + format->Bloss = 8; + format->Aloss = 8; + format->Rshift = 0; + format->Gshift = 0; + format->Bshift = 0; + format->Ashift = 0; + format->Rmask = 0; + format->Gmask = 0; + format->Bmask = 0; + format->Amask = 0; + } + if ( bpp <= 8 ) { /* Palettized mode */ + int ncolors = 1<<bpp; +#ifdef DEBUG_PALETTE + fprintf(stderr,"bpp=%d ncolors=%d\n",bpp,ncolors); +#endif + format->palette = (SDL_Palette *)SDL_malloc(sizeof(SDL_Palette)); + if ( format->palette == NULL ) { + SDL_FreeFormat(format); + SDL_OutOfMemory(); + return(NULL); + } + (format->palette)->ncolors = ncolors; + (format->palette)->colors = (SDL_Color *)SDL_malloc( + (format->palette)->ncolors*sizeof(SDL_Color)); + if ( (format->palette)->colors == NULL ) { + SDL_FreeFormat(format); + SDL_OutOfMemory(); + return(NULL); + } + if ( Rmask || Bmask || Gmask ) { + /* create palette according to masks */ + int i; + int Rm=0,Gm=0,Bm=0; + int Rw=0,Gw=0,Bw=0; +#ifdef ENABLE_PALETTE_ALPHA + int Am=0,Aw=0; +#endif + if(Rmask) + { + Rw=8-format->Rloss; + for(i=format->Rloss;i>0;i-=Rw) + Rm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Rw=%d Rm=0x%02X\n",Rw,Rm); +#endif + if(Gmask) + { + Gw=8-format->Gloss; + for(i=format->Gloss;i>0;i-=Gw) + Gm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Gw=%d Gm=0x%02X\n",Gw,Gm); +#endif + if(Bmask) + { + Bw=8-format->Bloss; + for(i=format->Bloss;i>0;i-=Bw) + Bm|=1<<i; + } +#ifdef DEBUG_PALETTE + fprintf(stderr,"Bw=%d Bm=0x%02X\n",Bw,Bm); +#endif +#ifdef ENABLE_PALETTE_ALPHA + if(Amask) + { + Aw=8-format->Aloss; + for(i=format->Aloss;i>0;i-=Aw) + Am|=1<<i; + } +# ifdef DEBUG_PALETTE + fprintf(stderr,"Aw=%d Am=0x%02X\n",Aw,Am); +# endif +#endif + for(i=0; i < ncolors; ++i) { + int r,g,b; + r=(i&Rmask)>>format->Rshift; + r=(r<<format->Rloss)|((r*Rm)>>Rw); + format->palette->colors[i].r=r; + + g=(i&Gmask)>>format->Gshift; + g=(g<<format->Gloss)|((g*Gm)>>Gw); + format->palette->colors[i].g=g; + + b=(i&Bmask)>>format->Bshift; + b=(b<<format->Bloss)|((b*Bm)>>Bw); + format->palette->colors[i].b=b; + +#ifdef ENABLE_PALETTE_ALPHA + a=(i&Amask)>>format->Ashift; + a=(a<<format->Aloss)|((a*Am)>>Aw); + format->palette->colors[i].unused=a; +#else + format->palette->colors[i].unused=0; +#endif + } + } else if ( ncolors == 2 ) { + /* Create a black and white bitmap palette */ + format->palette->colors[0].r = 0xFF; + format->palette->colors[0].g = 0xFF; + format->palette->colors[0].b = 0xFF; + format->palette->colors[1].r = 0x00; + format->palette->colors[1].g = 0x00; + format->palette->colors[1].b = 0x00; + } else { + /* Create an empty palette */ + SDL_memset((format->palette)->colors, 0, + (format->palette)->ncolors*sizeof(SDL_Color)); + } + } + return(format); +} +SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + if ( surface->format ) { + SDL_FreeFormat(surface->format); + SDL_FormatChanged(surface); + } + surface->format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + return surface->format; +} + +/* + * Change any previous mappings from/to the new surface format + */ +void SDL_FormatChanged(SDL_Surface *surface) +{ + static int format_version = 0; + ++format_version; + if ( format_version < 0 ) { /* It wrapped... */ + format_version = 1; + } + surface->format_version = format_version; + SDL_InvalidateMap(surface->map); +} +/* + * Free a previously allocated format structure + */ +void SDL_FreeFormat(SDL_PixelFormat *format) +{ + if ( format ) { + if ( format->palette ) { + if ( format->palette->colors ) { + SDL_free(format->palette->colors); + } + SDL_free(format->palette); + } + SDL_free(format); + } +} +/* + * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors + */ +void SDL_DitherColors(SDL_Color *colors, int bpp) +{ + int i; + if(bpp != 8) + return; /* only 8bpp supported right now */ + + for(i = 0; i < 256; i++) { + int r, g, b; + /* map each bit field to the full [0, 255] interval, + so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */ + r = i & 0xe0; + r |= r >> 3 | r >> 6; + colors[i].r = r; + g = (i << 3) & 0xe0; + g |= g >> 3 | g >> 6; + colors[i].g = g; + b = i & 0x3; + b |= b << 2; + b |= b << 4; + colors[i].b = b; + } +} +/* + * Calculate the pad-aligned scanline width of a surface + */ +Uint16 SDL_CalculatePitch(SDL_Surface *surface) +{ + Uint16 pitch; + + /* Surface should be 4-byte aligned for speed */ + pitch = surface->w*surface->format->BytesPerPixel; + switch (surface->format->BitsPerPixel) { + case 1: + pitch = (pitch+7)/8; + break; + case 4: + pitch = (pitch+1)/2; + break; + default: + break; + } + pitch = (pitch + 3) & ~3; /* 4-byte aligning */ + return(pitch); +} +/* + * Match an RGB value to a particular palette index + */ +Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b) +{ + /* Do colorspace distance matching */ + unsigned int smallest; + unsigned int distance; + int rd, gd, bd; + int i; + Uint8 pixel=0; + + smallest = ~0; + for ( i=0; i<pal->ncolors; ++i ) { + rd = pal->colors[i].r - r; + gd = pal->colors[i].g - g; + bd = pal->colors[i].b - b; + distance = (rd*rd)+(gd*gd)+(bd*bd); + if ( distance < smallest ) { + pixel = i; + if ( distance == 0 ) { /* Perfect match! */ + break; + } + smallest = distance; + } + } + return(pixel); +} + +/* Find the opaque pixel value corresponding to an RGB triple */ +Uint32 SDL_MapRGB +(const SDL_PixelFormat * const format, + const Uint8 r, const Uint8 g, const Uint8 b) +{ + if ( format->palette == NULL ) { + return (r >> format->Rloss) << format->Rshift + | (g >> format->Gloss) << format->Gshift + | (b >> format->Bloss) << format->Bshift + | format->Amask; + } else { + return SDL_FindColor(format->palette, r, g, b); + } +} + +/* Find the pixel value corresponding to an RGBA quadruple */ +Uint32 SDL_MapRGBA +(const SDL_PixelFormat * const format, + const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) +{ + if ( format->palette == NULL ) { + return (r >> format->Rloss) << format->Rshift + | (g >> format->Gloss) << format->Gshift + | (b >> format->Bloss) << format->Bshift + | ((a >> format->Aloss) << format->Ashift & format->Amask); + } else { + return SDL_FindColor(format->palette, r, g, b); + } +} + +void SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * const fmt, + Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + if ( fmt->palette == NULL ) { + /* + * This makes sure that the result is mapped to the + * interval [0..255], and the maximum value for each + * component is 255. This is important to make sure + * that white is indeed reported as (255, 255, 255), + * and that opaque alpha is 255. + * This only works for RGB bit fields at least 4 bit + * wide, which is almost always the case. + */ + unsigned v; + v = (pixel & fmt->Rmask) >> fmt->Rshift; + *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); + v = (pixel & fmt->Gmask) >> fmt->Gshift; + *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); + v = (pixel & fmt->Bmask) >> fmt->Bshift; + *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); + if(fmt->Amask) { + v = (pixel & fmt->Amask) >> fmt->Ashift; + *a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + } else { + *a = SDL_ALPHA_OPAQUE; + } + } else { + *r = fmt->palette->colors[pixel].r; + *g = fmt->palette->colors[pixel].g; + *b = fmt->palette->colors[pixel].b; + *a = SDL_ALPHA_OPAQUE; + } +} + +void SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * const fmt, + Uint8 *r,Uint8 *g,Uint8 *b) +{ + if ( fmt->palette == NULL ) { + /* the note for SDL_GetRGBA above applies here too */ + unsigned v; + v = (pixel & fmt->Rmask) >> fmt->Rshift; + *r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1))); + v = (pixel & fmt->Gmask) >> fmt->Gshift; + *g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1))); + v = (pixel & fmt->Bmask) >> fmt->Bshift; + *b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1))); + } else { + *r = fmt->palette->colors[pixel].r; + *g = fmt->palette->colors[pixel].g; + *b = fmt->palette->colors[pixel].b; + } +} + +/* Apply gamma to a set of colors - this is easy. :) */ +void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, + int ncolors) +{ + int i; + + for ( i=0; i<ncolors; ++i ) { + output[i].r = gamma[0*256 + colors[i].r] >> 8; + output[i].g = gamma[1*256 + colors[i].g] >> 8; + output[i].b = gamma[2*256 + colors[i].b] >> 8; + } +} + +/* Map from Palette to Palette */ +static Uint8 *Map1to1(SDL_Palette *src, SDL_Palette *dst, int *identical) +{ + Uint8 *map; + int i; + + if ( identical ) { + if ( src->ncolors <= dst->ncolors ) { + /* If an identical palette, no need to map */ + if ( SDL_memcmp(src->colors, dst->colors, src->ncolors* + sizeof(SDL_Color)) == 0 ) { + *identical = 1; + return(NULL); + } + } + *identical = 0; + } + map = (Uint8 *)SDL_malloc(src->ncolors); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<src->ncolors; ++i ) { + map[i] = SDL_FindColor(dst, + src->colors[i].r, src->colors[i].g, src->colors[i].b); + } + return(map); +} +/* Map from Palette to BitField */ +static Uint8 *Map1toN(SDL_PixelFormat *src, SDL_PixelFormat *dst) +{ + Uint8 *map; + int i; + int bpp; + unsigned alpha; + SDL_Palette *pal = src->palette; + + bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel); + map = (Uint8 *)SDL_malloc(pal->ncolors*bpp); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + alpha = dst->Amask ? src->alpha : 0; + /* We memory copy to the pixel map so the endianness is preserved */ + for ( i=0; i<pal->ncolors; ++i ) { + ASSEMBLE_RGBA(&map[i*bpp], dst->BytesPerPixel, dst, + pal->colors[i].r, pal->colors[i].g, + pal->colors[i].b, alpha); + } + return(map); +} +/* Map from BitField to Dithered-Palette to Palette */ +static Uint8 *MapNto1(SDL_PixelFormat *src, SDL_PixelFormat *dst, int *identical) +{ + /* Generate a 256 color dither palette */ + SDL_Palette dithered; + SDL_Color colors[256]; + SDL_Palette *pal = dst->palette; + + /* SDL_DitherColors does not initialize the 'unused' component of colors, + but Map1to1 compares it against pal, so we should initialize it. */ + SDL_memset(colors, 0, sizeof(colors)); + + dithered.ncolors = 256; + SDL_DitherColors(colors, 8); + dithered.colors = colors; + return(Map1to1(&dithered, pal, identical)); +} + +SDL_BlitMap *SDL_AllocBlitMap(void) +{ + SDL_BlitMap *map; + + /* Allocate the empty map */ + map = (SDL_BlitMap *)SDL_malloc(sizeof(*map)); + if ( map == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(map, 0, sizeof(*map)); + + /* Allocate the software blit data */ + map->sw_data = (struct private_swaccel *)SDL_malloc(sizeof(*map->sw_data)); + if ( map->sw_data == NULL ) { + SDL_FreeBlitMap(map); + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(map->sw_data, 0, sizeof(*map->sw_data)); + + /* It's ready to go */ + return(map); +} +void SDL_InvalidateMap(SDL_BlitMap *map) +{ + if ( ! map ) { + return; + } + map->dst = NULL; + map->format_version = (unsigned int)-1; + if ( map->table ) { + SDL_free(map->table); + map->table = NULL; + } +} +int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst) +{ + SDL_PixelFormat *srcfmt; + SDL_PixelFormat *dstfmt; + SDL_BlitMap *map; + + /* Clear out any previous mapping */ + map = src->map; + if ( (src->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(src, 1); + } + SDL_InvalidateMap(map); + + /* Figure out what kind of mapping we're doing */ + map->identity = 0; + srcfmt = src->format; + dstfmt = dst->format; + switch (srcfmt->BytesPerPixel) { + case 1: + switch (dstfmt->BytesPerPixel) { + case 1: + /* Palette --> Palette */ + /* If both SDL_HWSURFACE, assume have same palette */ + if ( ((src->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && + ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) ) { + map->identity = 1; + } else { + map->table = Map1to1(srcfmt->palette, + dstfmt->palette, &map->identity); + } + if ( ! map->identity ) { + if ( map->table == NULL ) { + return(-1); + } + } + if (srcfmt->BitsPerPixel!=dstfmt->BitsPerPixel) + map->identity = 0; + break; + + default: + /* Palette --> BitField */ + map->table = Map1toN(srcfmt, dstfmt); + if ( map->table == NULL ) { + return(-1); + } + break; + } + break; + default: + switch (dstfmt->BytesPerPixel) { + case 1: + /* BitField --> Palette */ + map->table = MapNto1(srcfmt, dstfmt, &map->identity); + if ( ! map->identity ) { + if ( map->table == NULL ) { + return(-1); + } + } + map->identity = 0; /* Don't optimize to copy */ + break; + default: + /* BitField --> BitField */ + if ( FORMAT_EQUAL(srcfmt, dstfmt) ) + map->identity = 1; + break; + } + break; + } + + map->dst = dst; + map->format_version = dst->format_version; + + /* Choose your blitters wisely */ + return(SDL_CalculateBlit(src)); +} +void SDL_FreeBlitMap(SDL_BlitMap *map) +{ + if ( map ) { + SDL_InvalidateMap(map); + if ( map->sw_data != NULL ) { + SDL_free(map->sw_data); + } + SDL_free(map); + } +} diff --git a/3rdparty/SDL/src/video/SDL_pixels_c.h b/3rdparty/SDL/src/video/SDL_pixels_c.h new file mode 100644 index 0000000..76759e2 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_pixels_c.h @@ -0,0 +1,46 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Useful functions and variables from SDL_pixel.c */ + +#include "SDL_blit.h" + +/* Pixel format functions */ +extern SDL_PixelFormat *SDL_AllocFormat(int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern SDL_PixelFormat *SDL_ReallocFormat(SDL_Surface *surface, int bpp, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); +extern void SDL_FormatChanged(SDL_Surface *surface); +extern void SDL_FreeFormat(SDL_PixelFormat *format); + +/* Blit mapping functions */ +extern SDL_BlitMap *SDL_AllocBlitMap(void); +extern void SDL_InvalidateMap(SDL_BlitMap *map); +extern int SDL_MapSurface (SDL_Surface *src, SDL_Surface *dst); +extern void SDL_FreeBlitMap(SDL_BlitMap *map); + +/* Miscellaneous functions */ +extern Uint16 SDL_CalculatePitch(SDL_Surface *surface); +extern void SDL_DitherColors(SDL_Color *colors, int bpp); +extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b); +extern void SDL_ApplyGamma(Uint16 *gamma, SDL_Color *colors, SDL_Color *output, int ncolors); diff --git a/3rdparty/SDL/src/video/SDL_stretch.c b/3rdparty/SDL/src/video/SDL_stretch.c new file mode 100644 index 0000000..7ce401f --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_stretch.c @@ -0,0 +1,358 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This a stretch blit implementation based on ideas given to me by + Tomasz Cejner - thanks! :) + + April 27, 2000 - Sam Lantinga +*/ + +#include "SDL_video.h" +#include "SDL_blit.h" + +/* This isn't ready for general consumption yet - it should be folded + into the general blitting mechanism. +*/ + +#if ((defined(_MFC_VER) && defined(_M_IX86)/* && !defined(_WIN32_WCE) still needed? */) || \ + defined(__WATCOMC__) || \ + (defined(__GNUC__) && defined(__i386__))) && SDL_ASSEMBLY_ROUTINES +/* There's a bug with gcc 4.4.1 and -O2 where srcp doesn't get the correct + * value after the first scanline. FIXME? */ +/*#define USE_ASM_STRETCH*/ +#endif + +#ifdef USE_ASM_STRETCH + +#ifdef HAVE_MPROTECT +#include <sys/types.h> +#include <sys/mman.h> +#endif +#ifdef __GNUC__ +#define PAGE_ALIGNED __attribute__((__aligned__(4096))) +#else +#define PAGE_ALIGNED +#endif + +#if defined(_M_IX86) || defined(i386) +#define PREFIX16 0x66 +#define STORE_BYTE 0xAA +#define STORE_WORD 0xAB +#define LOAD_BYTE 0xAC +#define LOAD_WORD 0xAD +#define RETURN 0xC3 +#else +#error Need assembly opcodes for this architecture +#endif + +static unsigned char copy_row[4096] PAGE_ALIGNED; + +static int generate_rowbytes(int src_w, int dst_w, int bpp) +{ + static struct { + int bpp; + int src_w; + int dst_w; + int status; + } last; + + int i; + int pos, inc; + unsigned char *eip, *fence; + unsigned char load, store; + + /* See if we need to regenerate the copy buffer */ + if ( (src_w == last.src_w) && + (dst_w == last.dst_w) && (bpp == last.bpp) ) { + return(last.status); + } + last.bpp = bpp; + last.src_w = src_w; + last.dst_w = dst_w; + last.status = -1; + + switch (bpp) { + case 1: + load = LOAD_BYTE; + store = STORE_BYTE; + break; + case 2: + case 4: + load = LOAD_WORD; + store = STORE_WORD; + break; + default: + SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp); + return(-1); + } +#ifdef HAVE_MPROTECT + /* Make the code writeable */ + if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE) < 0 ) { + SDL_SetError("Couldn't make copy buffer writeable"); + return(-1); + } +#endif + pos = 0x10000; + inc = (src_w << 16) / dst_w; + eip = copy_row; + fence = copy_row+sizeof(copy_row)-2; + for ( i=0; i<dst_w && eip < end; ++i ) { + while ( pos >= 0x10000L ) { + if ( eip == fence ) { + return -1; + } + if ( bpp == 2 ) { + *eip++ = PREFIX16; + } + *eip++ = load; + pos -= 0x10000L; + } + if ( eip == fence ) { + return -1; + } + if ( bpp == 2 ) { + *eip++ = PREFIX16; + } + *eip++ = store; + pos += inc; + } + *eip++ = RETURN; + +#ifdef HAVE_MPROTECT + /* Make the code executable but not writeable */ + if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_EXEC) < 0 ) { + SDL_SetError("Couldn't make copy buffer executable"); + return(-1); + } +#endif + last.status = 0; + return(0); +} + +#endif /* USE_ASM_STRETCH */ + +#define DEFINE_COPY_ROW(name, type) \ +void name(type *src, int src_w, type *dst, int dst_w) \ +{ \ + int i; \ + int pos, inc; \ + type pixel = 0; \ + \ + pos = 0x10000; \ + inc = (src_w << 16) / dst_w; \ + for ( i=dst_w; i>0; --i ) { \ + while ( pos >= 0x10000L ) { \ + pixel = *src++; \ + pos -= 0x10000L; \ + } \ + *dst++ = pixel; \ + pos += inc; \ + } \ +} +DEFINE_COPY_ROW(copy_row1, Uint8) +DEFINE_COPY_ROW(copy_row2, Uint16) +DEFINE_COPY_ROW(copy_row4, Uint32) + +/* The ASM code doesn't handle 24-bpp stretch blits */ +void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w) +{ + int i; + int pos, inc; + Uint8 pixel[3] = { 0, 0, 0 }; + + pos = 0x10000; + inc = (src_w << 16) / dst_w; + for ( i=dst_w; i>0; --i ) { + while ( pos >= 0x10000L ) { + pixel[0] = *src++; + pixel[1] = *src++; + pixel[2] = *src++; + pos -= 0x10000L; + } + *dst++ = pixel[0]; + *dst++ = pixel[1]; + *dst++ = pixel[2]; + pos += inc; + } +} + +/* Perform a stretch blit between two surfaces of the same format. + NOTE: This function is not safe to call from multiple threads! +*/ +int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + int src_locked; + int dst_locked; + int pos, inc; + int dst_maxrow; + int src_row, dst_row; + Uint8 *srcp = NULL; + Uint8 *dstp; + SDL_Rect full_src; + SDL_Rect full_dst; +#ifdef USE_ASM_STRETCH + SDL_bool use_asm = SDL_TRUE; +#ifdef __GNUC__ + int u1, u2; +#endif +#endif /* USE_ASM_STRETCH */ + const int bpp = dst->format->BytesPerPixel; + + if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) { + SDL_SetError("Only works with same format surfaces"); + return(-1); + } + + /* Verify the blit rectangles */ + if ( srcrect ) { + if ( (srcrect->x < 0) || (srcrect->y < 0) || + ((srcrect->x+srcrect->w) > src->w) || + ((srcrect->y+srcrect->h) > src->h) ) { + SDL_SetError("Invalid source blit rectangle"); + return(-1); + } + } else { + full_src.x = 0; + full_src.y = 0; + full_src.w = src->w; + full_src.h = src->h; + srcrect = &full_src; + } + if ( dstrect ) { + if ( (dstrect->x < 0) || (dstrect->y < 0) || + ((dstrect->x+dstrect->w) > dst->w) || + ((dstrect->y+dstrect->h) > dst->h) ) { + SDL_SetError("Invalid destination blit rectangle"); + return(-1); + } + } else { + full_dst.x = 0; + full_dst.y = 0; + full_dst.w = dst->w; + full_dst.h = dst->h; + dstrect = &full_dst; + } + + /* Lock the destination if it's in hardware */ + dst_locked = 0; + if ( SDL_MUSTLOCK(dst) ) { + if ( SDL_LockSurface(dst) < 0 ) { + SDL_SetError("Unable to lock destination surface"); + return(-1); + } + dst_locked = 1; + } + /* Lock the source if it's in hardware */ + src_locked = 0; + if ( SDL_MUSTLOCK(src) ) { + if ( SDL_LockSurface(src) < 0 ) { + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + SDL_SetError("Unable to lock source surface"); + return(-1); + } + src_locked = 1; + } + + /* Set up the data... */ + pos = 0x10000; + inc = (srcrect->h << 16) / dstrect->h; + src_row = srcrect->y; + dst_row = dstrect->y; + +#ifdef USE_ASM_STRETCH + /* Write the opcodes for this stretch */ + if ( (bpp == 3) || + (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) { + use_asm = SDL_FALSE; + } +#endif + + /* Perform the stretch blit */ + for ( dst_maxrow = dst_row+dstrect->h; dst_row<dst_maxrow; ++dst_row ) { + dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch) + + (dstrect->x*bpp); + while ( pos >= 0x10000L ) { + srcp = (Uint8 *)src->pixels + (src_row*src->pitch) + + (srcrect->x*bpp); + ++src_row; + pos -= 0x10000L; + } +#ifdef USE_ASM_STRETCH + if (use_asm) { +#ifdef __GNUC__ + __asm__ __volatile__ ( + "call *%4" + : "=&D" (u1), "=&S" (u2) + : "0" (dstp), "1" (srcp), "r" (copy_row) + : "memory" ); +#elif defined(_MSC_VER) || defined(__WATCOMC__) + { void *code = copy_row; + __asm { + push edi + push esi + + mov edi, dstp + mov esi, srcp + call dword ptr code + + pop esi + pop edi + } + } +#else +#error Need inline assembly for this compiler +#endif + } else +#endif + switch (bpp) { + case 1: + copy_row1(srcp, srcrect->w, dstp, dstrect->w); + break; + case 2: + copy_row2((Uint16 *)srcp, srcrect->w, + (Uint16 *)dstp, dstrect->w); + break; + case 3: + copy_row3(srcp, srcrect->w, dstp, dstrect->w); + break; + case 4: + copy_row4((Uint32 *)srcp, srcrect->w, + (Uint32 *)dstp, dstrect->w); + break; + } + pos += inc; + } + + /* We need to unlock the surfaces if they're locked */ + if ( dst_locked ) { + SDL_UnlockSurface(dst); + } + if ( src_locked ) { + SDL_UnlockSurface(src); + } + return(0); +} + diff --git a/3rdparty/SDL/src/video/SDL_stretch_c.h b/3rdparty/SDL/src/video/SDL_stretch_c.h new file mode 100644 index 0000000..4cc6acb --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_stretch_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Perform a stretch blit between two surfaces of the same format. + NOTE: This function is not safe to call from multiple threads! +*/ +extern int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); + diff --git a/3rdparty/SDL/src/video/SDL_surface.c b/3rdparty/SDL/src/video/SDL_surface.c new file mode 100644 index 0000000..0f3ad12 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_surface.c @@ -0,0 +1,941 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_cursor_c.h" +#include "SDL_blit.h" +#include "SDL_RLEaccel_c.h" +#include "SDL_pixels_c.h" +#include "SDL_leaks.h" + + +/* Public routines */ +/* + * Create an empty RGB surface of the appropriate depth + */ +SDL_Surface * SDL_CreateRGBSurface (Uint32 flags, + int width, int height, int depth, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Surface *screen; + SDL_Surface *surface; + + /* Make sure the size requested doesn't overflow our datatypes */ + /* Next time I write a library like SDL, I'll use int for size. :) */ + if ( width >= 16384 || height >= 65536 ) { + SDL_SetError("Width or height is too large"); + return(NULL); + } + + /* Check to see if we desire the surface in video memory */ + if ( video ) { + screen = SDL_PublicSurface; + } else { + screen = NULL; + } + if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) { + if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) { + flags |= SDL_HWSURFACE; + } + if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! current_video->info.blit_hw_CC ) { + flags &= ~SDL_HWSURFACE; + } + } + if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! current_video->info.blit_hw_A ) { + flags &= ~SDL_HWSURFACE; + } + } + } else { + flags &= ~SDL_HWSURFACE; + } + + /* Allocate the surface */ + surface = (SDL_Surface *)SDL_malloc(sizeof(*surface)); + if ( surface == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + surface->flags = SDL_SWSURFACE; + if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + if ((Amask) && (video->displayformatalphapixel)) + { + depth = video->displayformatalphapixel->BitsPerPixel; + Rmask = video->displayformatalphapixel->Rmask; + Gmask = video->displayformatalphapixel->Gmask; + Bmask = video->displayformatalphapixel->Bmask; + Amask = video->displayformatalphapixel->Amask; + } + else + { + depth = screen->format->BitsPerPixel; + Rmask = screen->format->Rmask; + Gmask = screen->format->Gmask; + Bmask = screen->format->Bmask; + Amask = screen->format->Amask; + } + } + surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); + if ( surface->format == NULL ) { + SDL_free(surface); + return(NULL); + } + if ( Amask ) { + surface->flags |= SDL_SRCALPHA; + } + surface->w = width; + surface->h = height; + surface->pitch = SDL_CalculatePitch(surface); + surface->pixels = NULL; + surface->offset = 0; + surface->hwdata = NULL; + surface->locked = 0; + surface->map = NULL; + surface->unused1 = 0; + SDL_SetClipRect(surface, NULL); + SDL_FormatChanged(surface); + + /* Get the pixels */ + if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || + (video->AllocHWSurface(this, surface) < 0) ) { + if ( surface->w && surface->h ) { + surface->pixels = SDL_malloc(surface->h*surface->pitch); + if ( surface->pixels == NULL ) { + SDL_FreeSurface(surface); + SDL_OutOfMemory(); + return(NULL); + } + /* This is important for bitmaps */ + SDL_memset(surface->pixels, 0, surface->h*surface->pitch); + } + } + + /* Allocate an empty mapping */ + surface->map = SDL_AllocBlitMap(); + if ( surface->map == NULL ) { + SDL_FreeSurface(surface); + return(NULL); + } + + /* The surface is ready to go */ + surface->refcount = 1; +#ifdef CHECK_LEAKS + ++surfaces_allocated; +#endif + return(surface); +} +/* + * Create an RGB surface from an existing memory buffer + */ +SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels, + int width, int height, int depth, int pitch, + Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + SDL_Surface *surface; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth, + Rmask, Gmask, Bmask, Amask); + if ( surface != NULL ) { + surface->flags |= SDL_PREALLOC; + surface->pixels = pixels; + surface->w = width; + surface->h = height; + surface->pitch = pitch; + SDL_SetClipRect(surface, NULL); + } + return(surface); +} +/* + * Set the color key in a blittable surface + */ +int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key) +{ + /* Sanity check the flag as it gets passed in */ + if ( flag & SDL_SRCCOLORKEY ) { + if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { + flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK); + } else { + flag = SDL_SRCCOLORKEY; + } + } else { + flag = 0; + } + + /* Optimize away operations that don't change anything */ + if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) && + (key == surface->format->colorkey) ) { + return(0); + } + + /* UnRLE surfaces before we change the colorkey */ + if ( surface->flags & SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + } + + if ( flag ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + + surface->flags |= SDL_SRCCOLORKEY; + surface->format->colorkey = key; + if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( (video->SetHWColorKey == NULL) || + (video->SetHWColorKey(this, surface, key) < 0) ) { + surface->flags &= ~SDL_HWACCEL; + } + } + if ( flag & SDL_RLEACCELOK ) { + surface->flags |= SDL_RLEACCELOK; + } else { + surface->flags &= ~SDL_RLEACCELOK; + } + } else { + surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK); + surface->format->colorkey = 0; + } + SDL_InvalidateMap(surface->map); + return(0); +} +/* This function sets the alpha channel of a surface */ +int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value) +{ + Uint32 oldflags = surface->flags; + Uint32 oldalpha = surface->format->alpha; + + /* Sanity check the flag as it gets passed in */ + if ( flag & SDL_SRCALPHA ) { + if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) { + flag = (SDL_SRCALPHA | SDL_RLEACCELOK); + } else { + flag = SDL_SRCALPHA; + } + } else { + flag = 0; + } + + /* Optimize away operations that don't change anything */ + if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) && + (!flag || value == oldalpha) ) { + return(0); + } + + if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL)) + SDL_UnRLESurface(surface, 1); + + if ( flag ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + surface->flags |= SDL_SRCALPHA; + surface->format->alpha = value; + if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( (video->SetHWAlpha == NULL) || + (video->SetHWAlpha(this, surface, value) < 0) ) { + surface->flags &= ~SDL_HWACCEL; + } + } + if ( flag & SDL_RLEACCELOK ) { + surface->flags |= SDL_RLEACCELOK; + } else { + surface->flags &= ~SDL_RLEACCELOK; + } + } else { + surface->flags &= ~SDL_SRCALPHA; + surface->format->alpha = SDL_ALPHA_OPAQUE; + } + /* + * The representation for software surfaces is independent of + * per-surface alpha, so no need to invalidate the blit mapping + * if just the alpha value was changed. (If either is 255, we still + * need to invalidate.) + */ + if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL + || oldflags != surface->flags + || (((oldalpha + 1) ^ (value + 1)) & 0x100)) + SDL_InvalidateMap(surface->map); + return(0); +} +int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value) +{ + int row, col; + int offset; + Uint8 *buf; + + if ( (surface->format->Amask != 0xFF000000) && + (surface->format->Amask != 0x000000FF) ) { + SDL_SetError("Unsupported surface alpha mask format"); + return -1; + } + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + if ( surface->format->Amask == 0xFF000000 ) { + offset = 3; + } else { + offset = 0; + } +#else + if ( surface->format->Amask == 0xFF000000 ) { + offset = 0; + } else { + offset = 3; + } +#endif /* Byte ordering */ + + /* Quickly set the alpha channel of an RGBA or ARGB surface */ + if ( SDL_MUSTLOCK(surface) ) { + if ( SDL_LockSurface(surface) < 0 ) { + return -1; + } + } + row = surface->h; + while (row--) { + col = surface->w; + buf = (Uint8 *)surface->pixels + row * surface->pitch + offset; + while(col--) { + *buf = value; + buf += 4; + } + } + if ( SDL_MUSTLOCK(surface) ) { + SDL_UnlockSurface(surface); + } + return 0; +} + +/* + * A function to calculate the intersection of two rectangles: + * return true if the rectangles intersect, false otherwise + */ +static __inline__ +SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection) +{ + int Amin, Amax, Bmin, Bmax; + + /* Horizontal intersection */ + Amin = A->x; + Amax = Amin + A->w; + Bmin = B->x; + Bmax = Bmin + B->w; + if(Bmin > Amin) + Amin = Bmin; + intersection->x = Amin; + if(Bmax < Amax) + Amax = Bmax; + intersection->w = Amax - Amin > 0 ? Amax - Amin : 0; + + /* Vertical intersection */ + Amin = A->y; + Amax = Amin + A->h; + Bmin = B->y; + Bmax = Bmin + B->h; + if(Bmin > Amin) + Amin = Bmin; + intersection->y = Amin; + if(Bmax < Amax) + Amax = Bmax; + intersection->h = Amax - Amin > 0 ? Amax - Amin : 0; + + return (intersection->w && intersection->h); +} +/* + * Set the clipping rectangle for a blittable surface + */ +SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect) +{ + SDL_Rect full_rect; + + /* Don't do anything if there's no surface to act on */ + if ( ! surface ) { + return SDL_FALSE; + } + + /* Set up the full surface rectangle */ + full_rect.x = 0; + full_rect.y = 0; + full_rect.w = surface->w; + full_rect.h = surface->h; + + /* Set the clipping rectangle */ + if ( ! rect ) { + surface->clip_rect = full_rect; + return 1; + } + return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect); +} +void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect) +{ + if ( surface && rect ) { + *rect = surface->clip_rect; + } +} +/* + * Set up a blit between two surfaces -- split into three parts: + * The upper part, SDL_UpperBlit(), performs clipping and rectangle + * verification. The lower part is a pointer to a low level + * accelerated blitting function. + * + * These parts are separated out and each used internally by this + * library in the optimimum places. They are exported so that if + * you know exactly what you are doing, you can optimize your code + * by calling the one(s) you need. + */ +int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_blit do_blit; + SDL_Rect hw_srcrect; + SDL_Rect hw_dstrect; + + /* Check to make sure the blit mapping is valid */ + if ( (src->map->dst != dst) || + (src->map->dst->format_version != src->map->format_version) ) { + if ( SDL_MapSurface(src, dst) < 0 ) { + return(-1); + } + } + + /* Figure out which blitter to use */ + if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) { + if ( src == SDL_VideoSurface ) { + hw_srcrect = *srcrect; + hw_srcrect.x += current_video->offset_x; + hw_srcrect.y += current_video->offset_y; + srcrect = &hw_srcrect; + } + if ( dst == SDL_VideoSurface ) { + hw_dstrect = *dstrect; + hw_dstrect.x += current_video->offset_x; + hw_dstrect.y += current_video->offset_y; + dstrect = &hw_dstrect; + } + do_blit = src->map->hw_blit; + } else { + do_blit = src->map->sw_blit; + } + return(do_blit(src, srcrect, dst, dstrect)); +} + + +int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_Rect fulldst; + int srcx, srcy, w, h; + + /* Make sure the surfaces aren't locked */ + if ( ! src || ! dst ) { + SDL_SetError("SDL_UpperBlit: passed a NULL surface"); + return(-1); + } + if ( src->locked || dst->locked ) { + SDL_SetError("Surfaces must not be locked during blit"); + return(-1); + } + + /* If the destination rectangle is NULL, use the entire dest surface */ + if ( dstrect == NULL ) { + fulldst.x = fulldst.y = 0; + dstrect = &fulldst; + } + + /* clip the source rectangle to the source surface */ + if(srcrect) { + int maxw, maxh; + + srcx = srcrect->x; + w = srcrect->w; + if(srcx < 0) { + w += srcx; + dstrect->x -= srcx; + srcx = 0; + } + maxw = src->w - srcx; + if(maxw < w) + w = maxw; + + srcy = srcrect->y; + h = srcrect->h; + if(srcy < 0) { + h += srcy; + dstrect->y -= srcy; + srcy = 0; + } + maxh = src->h - srcy; + if(maxh < h) + h = maxh; + + } else { + srcx = srcy = 0; + w = src->w; + h = src->h; + } + + /* clip the destination rectangle against the clip rectangle */ + { + SDL_Rect *clip = &dst->clip_rect; + int dx, dy; + + dx = clip->x - dstrect->x; + if(dx > 0) { + w -= dx; + dstrect->x += dx; + srcx += dx; + } + dx = dstrect->x + w - clip->x - clip->w; + if(dx > 0) + w -= dx; + + dy = clip->y - dstrect->y; + if(dy > 0) { + h -= dy; + dstrect->y += dy; + srcy += dy; + } + dy = dstrect->y + h - clip->y - clip->h; + if(dy > 0) + h -= dy; + } + + if(w > 0 && h > 0) { + SDL_Rect sr; + sr.x = srcx; + sr.y = srcy; + sr.w = dstrect->w = w; + sr.h = dstrect->h = h; + return SDL_LowerBlit(src, &sr, dst, dstrect); + } + dstrect->w = dstrect->h = 0; + return 0; +} + +static int SDL_FillRect1(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + /* FIXME: We have to worry about packing order.. *sigh* */ + SDL_SetError("1-bpp rect fill not yet implemented"); + return -1; +} + +static int SDL_FillRect4(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + /* FIXME: We have to worry about packing order.. *sigh* */ + SDL_SetError("4-bpp rect fill not yet implemented"); + return -1; +} + +/* + * This function performs a fast fill of the given rectangle with 'color' + */ +int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int x, y; + Uint8 *row; + + /* This function doesn't work on surfaces < 8 bpp */ + if ( dst->format->BitsPerPixel < 8 ) { + switch(dst->format->BitsPerPixel) { + case 1: + return SDL_FillRect1(dst, dstrect, color); + break; + case 4: + return SDL_FillRect4(dst, dstrect, color); + break; + default: + SDL_SetError("Fill rect on unsupported surface format"); + return(-1); + break; + } + } + + /* If 'dstrect' == NULL, then fill the whole surface */ + if ( dstrect ) { + /* Perform clipping */ + if ( !SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect) ) { + return(0); + } + } else { + dstrect = &dst->clip_rect; + } + + /* Check for hardware acceleration */ + if ( ((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) && + video->info.blit_fill ) { + SDL_Rect hw_rect; + if ( dst == SDL_VideoSurface ) { + hw_rect = *dstrect; + hw_rect.x += current_video->offset_x; + hw_rect.y += current_video->offset_y; + dstrect = &hw_rect; + } + return(video->FillHWRect(this, dst, dstrect, color)); + } + + /* Perform software fill */ + if ( SDL_LockSurface(dst) != 0 ) { + return(-1); + } + row = (Uint8 *)dst->pixels+dstrect->y*dst->pitch+ + dstrect->x*dst->format->BytesPerPixel; + if ( dst->format->palette || (color == 0) ) { + x = dstrect->w*dst->format->BytesPerPixel; + if ( !color && !((uintptr_t)row&3) && !(x&3) && !(dst->pitch&3) ) { + int n = x >> 2; + for ( y=dstrect->h; y; --y ) { + SDL_memset4(row, 0, n); + row += dst->pitch; + } + } else { +#ifdef __powerpc__ + /* + * SDL_memset() on PPC (both glibc and codewarrior) uses + * the dcbz (Data Cache Block Zero) instruction, which + * causes an alignment exception if the destination is + * uncachable, so only use it on software surfaces + */ + if((dst->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { + if(dstrect->w >= 8) { + /* + * 64-bit stores are probably most + * efficient to uncached video memory + */ + double fill; + SDL_memset(&fill, color, (sizeof fill)); + for(y = dstrect->h; y; y--) { + Uint8 *d = row; + unsigned n = x; + unsigned nn; + Uint8 c = color; + double f = fill; + while((unsigned long)d + & (sizeof(double) - 1)) { + *d++ = c; + n--; + } + nn = n / (sizeof(double) * 4); + while(nn) { + ((double *)d)[0] = f; + ((double *)d)[1] = f; + ((double *)d)[2] = f; + ((double *)d)[3] = f; + d += 4*sizeof(double); + nn--; + } + n &= ~(sizeof(double) * 4 - 1); + nn = n / sizeof(double); + while(nn) { + *(double *)d = f; + d += sizeof(double); + nn--; + } + n &= ~(sizeof(double) - 1); + while(n) { + *d++ = c; + n--; + } + row += dst->pitch; + } + } else { + /* narrow boxes */ + for(y = dstrect->h; y; y--) { + Uint8 *d = row; + Uint8 c = color; + int n = x; + while(n) { + *d++ = c; + n--; + } + row += dst->pitch; + } + } + } else +#endif /* __powerpc__ */ + { + for(y = dstrect->h; y; y--) { + SDL_memset(row, color, x); + row += dst->pitch; + } + } + } + } else { + switch (dst->format->BytesPerPixel) { + case 2: + for ( y=dstrect->h; y; --y ) { + Uint16 *pixels = (Uint16 *)row; + Uint16 c = (Uint16)color; + Uint32 cc = (Uint32)c << 16 | c; + int n = dstrect->w; + if((uintptr_t)pixels & 3) { + *pixels++ = c; + n--; + } + if(n >> 1) + SDL_memset4(pixels, cc, n >> 1); + if(n & 1) + pixels[n - 1] = c; + row += dst->pitch; + } + break; + + case 3: + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + color <<= 8; + #endif + for ( y=dstrect->h; y; --y ) { + Uint8 *pixels = row; + for ( x=dstrect->w; x; --x ) { + SDL_memcpy(pixels, &color, 3); + pixels += 3; + } + row += dst->pitch; + } + break; + + case 4: + for(y = dstrect->h; y; --y) { + SDL_memset4(row, color, dstrect->w); + row += dst->pitch; + } + break; + } + } + SDL_UnlockSurface(dst); + + /* We're done! */ + return(0); +} + +/* + * Lock a surface to directly access the pixels + */ +int SDL_LockSurface (SDL_Surface *surface) +{ + if ( ! surface->locked ) { + /* Perform the lock */ + if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + if ( video->LockHWSurface(this, surface) < 0 ) { + return(-1); + } + } + if ( surface->flags & SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 1); + surface->flags |= SDL_RLEACCEL; /* save accel'd state */ + } + /* This needs to be done here in case pixels changes value */ + surface->pixels = (Uint8 *)surface->pixels + surface->offset; + } + + /* Increment the surface lock count, for recursive locks */ + ++surface->locked; + + /* Ready to go.. */ + return(0); +} +/* + * Unlock a previously locked surface + */ +void SDL_UnlockSurface (SDL_Surface *surface) +{ + /* Only perform an unlock if we are locked */ + if ( ! surface->locked || (--surface->locked > 0) ) { + return; + } + + /* Perform the unlock */ + surface->pixels = (Uint8 *)surface->pixels - surface->offset; + + /* Unlock hardware or accelerated surfaces */ + if ( surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->UnlockHWSurface(this, surface); + } else { + /* Update RLE encoded surface with new data */ + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + surface->flags &= ~SDL_RLEACCEL; /* stop lying */ + SDL_RLESurface(surface); + } + } +} + +/* + * Convert a surface into the specified pixel format. + */ +SDL_Surface * SDL_ConvertSurface (SDL_Surface *surface, + SDL_PixelFormat *format, Uint32 flags) +{ + SDL_Surface *convert; + Uint32 colorkey = 0; + Uint8 alpha = 0; + Uint32 surface_flags; + SDL_Rect bounds; + + /* Check for empty destination palette! (results in empty image) */ + if ( format->palette != NULL ) { + int i; + for ( i=0; i<format->palette->ncolors; ++i ) { + if ( (format->palette->colors[i].r != 0) || + (format->palette->colors[i].g != 0) || + (format->palette->colors[i].b != 0) ) + break; + } + if ( i == format->palette->ncolors ) { + SDL_SetError("Empty destination palette"); + return(NULL); + } + } + + /* Only create hw surfaces with alpha channel if hw alpha blits + are supported */ + if(format->Amask != 0 && (flags & SDL_HWSURFACE)) { + const SDL_VideoInfo *vi = SDL_GetVideoInfo(); + if(!vi || !vi->blit_hw_A) + flags &= ~SDL_HWSURFACE; + } + + /* Create a new surface with the desired format */ + convert = SDL_CreateRGBSurface(flags, + surface->w, surface->h, format->BitsPerPixel, + format->Rmask, format->Gmask, format->Bmask, format->Amask); + if ( convert == NULL ) { + return(NULL); + } + + /* Copy the palette if any */ + if ( format->palette && convert->format->palette ) { + SDL_memcpy(convert->format->palette->colors, + format->palette->colors, + format->palette->ncolors*sizeof(SDL_Color)); + convert->format->palette->ncolors = format->palette->ncolors; + } + + /* Save the original surface color key and alpha */ + surface_flags = surface->flags; + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + /* Convert colourkeyed surfaces to RGBA if requested */ + if((flags & SDL_SRCCOLORKEY) != SDL_SRCCOLORKEY + && format->Amask) { + surface_flags &= ~SDL_SRCCOLORKEY; + } else { + colorkey = surface->format->colorkey; + SDL_SetColorKey(surface, 0, 0); + } + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + /* Copy over the alpha channel to RGBA if requested */ + if ( format->Amask ) { + surface->flags &= ~SDL_SRCALPHA; + } else { + alpha = surface->format->alpha; + SDL_SetAlpha(surface, 0, 0); + } + } + + /* Copy over the image data */ + bounds.x = 0; + bounds.y = 0; + bounds.w = surface->w; + bounds.h = surface->h; + SDL_LowerBlit(surface, &bounds, convert, &bounds); + + /* Clean up the original surface, and update converted surface */ + if ( convert != NULL ) { + SDL_SetClipRect(convert, &surface->clip_rect); + } + if ( (surface_flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 cflags = surface_flags&(SDL_SRCCOLORKEY|SDL_RLEACCELOK); + if ( convert != NULL ) { + Uint8 keyR, keyG, keyB; + + SDL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); + SDL_SetColorKey(convert, cflags|(flags&SDL_RLEACCELOK), + SDL_MapRGB(convert->format, keyR, keyG, keyB)); + } + SDL_SetColorKey(surface, cflags, colorkey); + } + if ( (surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + Uint32 aflags = surface_flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + if ( convert != NULL ) { + SDL_SetAlpha(convert, aflags|(flags&SDL_RLEACCELOK), + alpha); + } + if ( format->Amask ) { + surface->flags |= SDL_SRCALPHA; + } else { + SDL_SetAlpha(surface, aflags, alpha); + } + } + + /* We're ready to go! */ + return(convert); +} + +/* + * Free a surface created by the above function. + */ +void SDL_FreeSurface (SDL_Surface *surface) +{ + /* Free anything that's not NULL, and not the screen surface */ + if ((surface == NULL) || + (current_video && + ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) { + return; + } + if ( --surface->refcount > 0 ) { + return; + } + while ( surface->locked > 0 ) { + SDL_UnlockSurface(surface); + } + if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { + SDL_UnRLESurface(surface, 0); + } + if ( surface->format ) { + SDL_FreeFormat(surface->format); + surface->format = NULL; + } + if ( surface->map != NULL ) { + SDL_FreeBlitMap(surface->map); + surface->map = NULL; + } + if ( surface->hwdata ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + video->FreeHWSurface(this, surface); + } + if ( surface->pixels && + ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC) ) { + SDL_free(surface->pixels); + } + SDL_free(surface); +#ifdef CHECK_LEAKS + --surfaces_allocated; +#endif +} diff --git a/3rdparty/SDL/src/video/SDL_sysvideo.h b/3rdparty/SDL/src/video/SDL_sysvideo.h new file mode 100644 index 0000000..436450e --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_sysvideo.h @@ -0,0 +1,424 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_sysvideo_h +#define _SDL_sysvideo_h + +#include "SDL_mouse.h" +#define SDL_PROTOTYPES_ONLY +#include "SDL_syswm.h" +#undef SDL_PROTOTYPES_ONLY + +/* This file prototypes the video driver implementation. + This is designed to be easily converted to C++ in the future. + */ + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif /* SDL_VIDEO_OPENGL */ + +/* The SDL video driver */ +typedef struct SDL_VideoDevice SDL_VideoDevice; + +/* Define the SDL video driver structure */ +#define _THIS SDL_VideoDevice *_this +#ifndef _STATUS +#define _STATUS SDL_status *status +#endif +struct SDL_VideoDevice { + /* * * */ + /* The name of this video driver */ + const char *name; + + /* * * */ + /* Initialization/Query functions */ + + /* Initialize the native video subsystem, filling 'vformat' with the + "best" display pixel format, returning 0 or -1 if there's an error. + */ + int (*VideoInit)(_THIS, SDL_PixelFormat *vformat); + + /* List the available video modes for the given pixel format, sorted + from largest to smallest. + */ + SDL_Rect **(*ListModes)(_THIS, SDL_PixelFormat *format, Uint32 flags); + + /* Set the requested video mode, returning a surface which will be + set to the SDL_VideoSurface. The width and height will already + be verified by ListModes(), and the video subsystem is free to + set the mode to a supported bit depth different from the one + specified -- the desired bpp will be emulated with a shadow + surface if necessary. If a new mode is returned, this function + should take care of cleaning up the current mode. + */ + SDL_Surface *(*SetVideoMode)(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags); + + /* Toggle the fullscreen mode */ + int (*ToggleFullScreen)(_THIS, int on); + + /* This is called after the video mode has been set, to get the + initial mouse state. It should queue events as necessary to + properly represent the current mouse focus and position. + */ + void (*UpdateMouse)(_THIS); + + /* Create a YUV video surface (possibly overlay) of the given + format. The hardware should be able to perform at least 2x + scaling on display. + */ + SDL_Overlay *(*CreateYUVOverlay)(_THIS, int width, int height, + Uint32 format, SDL_Surface *display); + + /* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) } + of the physical palette to those in 'colors'. If the device is + using a software palette (SDL_HWPALETTE not set), then the + changes are reflected in the logical palette of the screen + as well. + The return value is 1 if all entries could be set properly + or 0 otherwise. + */ + int (*SetColors)(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); + + /* This pointer should exist in the native video subsystem and should + point to an appropriate update function for the current video mode + */ + void (*UpdateRects)(_THIS, int numrects, SDL_Rect *rects); + + /* Reverse the effects VideoInit() -- called if VideoInit() fails + or if the application is shutting down the video subsystem. + */ + void (*VideoQuit)(_THIS); + + /* * * */ + /* Hardware acceleration functions */ + + /* Information about the video hardware */ + SDL_VideoInfo info; + + /* The pixel format used when SDL_CreateRGBSurface creates SDL_HWSURFACEs with alpha */ + SDL_PixelFormat* displayformatalphapixel; + + /* Allocates a surface in video memory */ + int (*AllocHWSurface)(_THIS, SDL_Surface *surface); + + /* Sets the hardware accelerated blit function, if any, based + on the current flags of the surface (colorkey, alpha, etc.) + */ + int (*CheckHWBlit)(_THIS, SDL_Surface *src, SDL_Surface *dst); + + /* Fills a surface rectangle with the given color */ + int (*FillHWRect)(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); + + /* Sets video mem colorkey and accelerated blit function */ + int (*SetHWColorKey)(_THIS, SDL_Surface *surface, Uint32 key); + + /* Sets per surface hardware alpha value */ + int (*SetHWAlpha)(_THIS, SDL_Surface *surface, Uint8 value); + + /* Returns a readable/writable surface */ + int (*LockHWSurface)(_THIS, SDL_Surface *surface); + void (*UnlockHWSurface)(_THIS, SDL_Surface *surface); + + /* Performs hardware flipping */ + int (*FlipHWSurface)(_THIS, SDL_Surface *surface); + + /* Frees a previously allocated video surface */ + void (*FreeHWSurface)(_THIS, SDL_Surface *surface); + + /* * * */ + /* Gamma support */ + + Uint16 *gamma; + + /* Set the gamma correction directly (emulated with gamma ramps) */ + int (*SetGamma)(_THIS, float red, float green, float blue); + + /* Get the gamma correction directly (emulated with gamma ramps) */ + int (*GetGamma)(_THIS, float *red, float *green, float *blue); + + /* Set the gamma ramp */ + int (*SetGammaRamp)(_THIS, Uint16 *ramp); + + /* Get the gamma ramp */ + int (*GetGammaRamp)(_THIS, Uint16 *ramp); + + /* * * */ + /* OpenGL support */ + + /* Sets the dll to use for OpenGL and loads it */ + int (*GL_LoadLibrary)(_THIS, const char *path); + + /* Retrieves the address of a function in the gl library */ + void* (*GL_GetProcAddress)(_THIS, const char *proc); + + /* Get attribute information from the windowing system. */ + int (*GL_GetAttribute)(_THIS, SDL_GLattr attrib, int* value); + + /* Make the context associated with this driver current */ + int (*GL_MakeCurrent)(_THIS); + + /* Swap the current buffers in double buffer mode. */ + void (*GL_SwapBuffers)(_THIS); + + /* OpenGL functions for SDL_OPENGLBLIT */ +#if SDL_VIDEO_OPENGL +#if !defined(__WIN32__) +#define WINAPI +#endif +#define SDL_PROC(ret,func,params) ret (WINAPI *func) params; +#include "SDL_glfuncs.h" +#undef SDL_PROC + + /* Texture id */ + GLuint texture; +#endif + int is_32bit; + + /* * * */ + /* Window manager functions */ + + /* Set the title and icon text */ + void (*SetCaption)(_THIS, const char *title, const char *icon); + + /* Set the window icon image */ + void (*SetIcon)(_THIS, SDL_Surface *icon, Uint8 *mask); + + /* Iconify the window. + This function returns 1 if there is a window manager and the + window was actually iconified, it returns 0 otherwise. + */ + int (*IconifyWindow)(_THIS); + + /* Grab or ungrab keyboard and mouse input */ + SDL_GrabMode (*GrabInput)(_THIS, SDL_GrabMode mode); + + /* Get some platform dependent window information */ + int (*GetWMInfo)(_THIS, SDL_SysWMinfo *info); + + /* * * */ + /* Cursor manager functions */ + + /* Free a window manager cursor + This function can be NULL if CreateWMCursor is also NULL. + */ + void (*FreeWMCursor)(_THIS, WMcursor *cursor); + + /* If not NULL, create a black/white window manager cursor */ + WMcursor *(*CreateWMCursor)(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); + + /* Show the specified cursor, or hide if cursor is NULL */ + int (*ShowWMCursor)(_THIS, WMcursor *cursor); + + /* Warp the window manager cursor to (x,y) + If NULL, a mouse motion event is posted internally. + */ + void (*WarpWMCursor)(_THIS, Uint16 x, Uint16 y); + + /* If not NULL, this is called when a mouse motion event occurs */ + void (*MoveWMCursor)(_THIS, int x, int y); + + /* Determine whether the mouse should be in relative mode or not. + This function is called when the input grab state or cursor + visibility state changes. + If the cursor is not visible, and the input is grabbed, the + driver can place the mouse in relative mode, which may result + in higher accuracy sampling of the pointer motion. + */ + void (*CheckMouseMode)(_THIS); + + /* * * */ + /* Event manager functions */ + + /* Initialize keyboard mapping for this driver */ + void (*InitOSKeymap)(_THIS); + + /* Handle any queued OS events */ + void (*PumpEvents)(_THIS); + + /* * * */ + /* Data common to all drivers */ + SDL_Surface *screen; + SDL_Surface *shadow; + SDL_Surface *visible; + SDL_Palette *physpal; /* physical palette, if != logical palette */ + SDL_Color *gammacols; /* gamma-corrected colours, or NULL */ + char *wm_title; + char *wm_icon; + int offset_x; + int offset_y; + SDL_GrabMode input_grab; + + /* Driver information flags */ + int handles_any_size; /* Driver handles any size video mode */ + + /* * * */ + /* Data used by the GL drivers */ + struct { + int red_size; + int green_size; + int blue_size; + int alpha_size; + int depth_size; + int buffer_size; + int stencil_size; + int double_buffer; + int accum_red_size; + int accum_green_size; + int accum_blue_size; + int accum_alpha_size; + int stereo; + int multisamplebuffers; + int multisamplesamples; + int accelerated; + int swap_control; + int driver_loaded; + char driver_path[256]; + void* dll_handle; + } gl_config; + + /* * * */ + /* Data private to this driver */ + struct SDL_PrivateVideoData *hidden; + struct SDL_PrivateGLData *gl_data; + + /* * * */ + /* The function used to dispose of this structure */ + void (*free)(_THIS); +}; +#undef _THIS + +typedef struct VideoBootStrap { + const char *name; + const char *desc; + int (*available)(void); + SDL_VideoDevice *(*create)(int devindex); +} VideoBootStrap; + +#if SDL_VIDEO_DRIVER_QUARTZ +extern VideoBootStrap QZ_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_X11 +extern VideoBootStrap X11_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DGA +extern VideoBootStrap DGA_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_NANOX +extern VideoBootStrap NX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_IPOD +extern VideoBootStrap iPod_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_QTOPIA +extern VideoBootStrap Qtopia_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_WSCONS +extern VideoBootStrap WSCONS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_FBCON +extern VideoBootStrap FBCON_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DIRECTFB +extern VideoBootStrap DirectFB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PS2GS +extern VideoBootStrap PS2GS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PS3 +extern VideoBootStrap PS3_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GGI +extern VideoBootStrap GGI_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_VGL +extern VideoBootStrap VGL_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_SVGALIB +extern VideoBootStrap SVGALIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GAPI +extern VideoBootStrap GAPI_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_WINDIB +extern VideoBootStrap WINDIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DDRAW +extern VideoBootStrap DIRECTX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_BWINDOW +extern VideoBootStrap BWINDOW_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_TOOLBOX +extern VideoBootStrap TOOLBOX_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DRAWSPROCKET +extern VideoBootStrap DSp_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PHOTON +extern VideoBootStrap ph_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_EPOC +extern VideoBootStrap EPOC_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_XBIOS +extern VideoBootStrap XBIOS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_GEM +extern VideoBootStrap GEM_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_PICOGUI +extern VideoBootStrap PG_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DC +extern VideoBootStrap DC_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_NDS +extern VideoBootStrap NDS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_RISCOS +extern VideoBootStrap RISCOS_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_OS2FS +extern VideoBootStrap OS2FSLib_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_AALIB +extern VideoBootStrap AALIB_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_CACA +extern VideoBootStrap CACA_bootstrap; +#endif +#if SDL_VIDEO_DRIVER_DUMMY +extern VideoBootStrap DUMMY_bootstrap; +#endif + +/* This is the current video device */ +extern SDL_VideoDevice *current_video; + +#define SDL_VideoSurface (current_video->screen) +#define SDL_ShadowSurface (current_video->shadow) +#define SDL_PublicSurface (current_video->visible) + +#endif /* _SDL_sysvideo_h */ diff --git a/3rdparty/SDL/src/video/SDL_video.c b/3rdparty/SDL/src/video/SDL_video.c new file mode 100644 index 0000000..46285c9 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_video.c @@ -0,0 +1,1978 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* The high-level video driver subsystem */ + +#include "SDL.h" +#include "SDL_sysvideo.h" +#include "SDL_blit.h" +#include "SDL_pixels_c.h" +#include "SDL_cursor_c.h" +#include "../events/SDL_sysevents.h" +#include "../events/SDL_events_c.h" + +/* Available video drivers */ +static VideoBootStrap *bootstrap[] = { +#if SDL_VIDEO_DRIVER_QUARTZ + &QZ_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_X11 + &X11_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DGA + &DGA_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_NANOX + &NX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_IPOD + &iPod_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_QTOPIA + &Qtopia_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_WSCONS + &WSCONS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_FBCON + &FBCON_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DIRECTFB + &DirectFB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PS2GS + &PS2GS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PS3 + &PS3_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GGI + &GGI_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_VGL + &VGL_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_SVGALIB + &SVGALIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GAPI + &GAPI_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_WINDIB + &WINDIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DDRAW + &DIRECTX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_BWINDOW + &BWINDOW_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_TOOLBOX + &TOOLBOX_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DRAWSPROCKET + &DSp_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PHOTON + &ph_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_EPOC + &EPOC_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_XBIOS + &XBIOS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_GEM + &GEM_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_PICOGUI + &PG_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DC + &DC_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_NDS + &NDS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_RISCOS + &RISCOS_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_OS2FS + &OS2FSLib_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_AALIB + &AALIB_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_CACA + &CACA_bootstrap, +#endif +#if SDL_VIDEO_DRIVER_DUMMY + &DUMMY_bootstrap, +#endif + NULL +}; + +SDL_VideoDevice *current_video = NULL; + +/* Various local functions */ +int SDL_VideoInit(const char *driver_name, Uint32 flags); +void SDL_VideoQuit(void); +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects); + +static SDL_GrabMode SDL_WM_GrabInputOff(void); +#if SDL_VIDEO_OPENGL +static int lock_count = 0; +#endif + + +/* + * Initialize the video and event subsystems -- determine native pixel format + */ +int SDL_VideoInit (const char *driver_name, Uint32 flags) +{ + SDL_VideoDevice *video; + int index; + int i; + SDL_PixelFormat vformat; + Uint32 video_flags; + + /* Toggle the event thread flags, based on OS requirements */ +#if defined(MUST_THREAD_EVENTS) + flags |= SDL_INIT_EVENTTHREAD; +#elif defined(CANT_THREAD_EVENTS) + if ( (flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) { + SDL_SetError("OS doesn't support threaded events"); + return(-1); + } +#endif + + /* Check to make sure we don't overwrite 'current_video' */ + if ( current_video != NULL ) { + SDL_VideoQuit(); + } + + /* Select the proper video driver */ + index = 0; + video = NULL; + if ( driver_name != NULL ) { +#if 0 /* This will be replaced with a better driver selection API */ + if ( SDL_strrchr(driver_name, ':') != NULL ) { + index = atoi(SDL_strrchr(driver_name, ':')+1); + } +#endif + for ( i=0; bootstrap[i]; ++i ) { + if ( SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) { + if ( bootstrap[i]->available() ) { + video = bootstrap[i]->create(index); + break; + } + } + } + } else { + for ( i=0; bootstrap[i]; ++i ) { + if ( bootstrap[i]->available() ) { + video = bootstrap[i]->create(index); + if ( video != NULL ) { + break; + } + } + } + } + if ( video == NULL ) { + SDL_SetError("No available video device"); + return(-1); + } + current_video = video; + current_video->name = bootstrap[i]->name; + + /* Do some basic variable initialization */ + video->screen = NULL; + video->shadow = NULL; + video->visible = NULL; + video->physpal = NULL; + video->gammacols = NULL; + video->gamma = NULL; + video->wm_title = NULL; + video->wm_icon = NULL; + video->offset_x = 0; + video->offset_y = 0; + SDL_memset(&video->info, 0, (sizeof video->info)); + + video->displayformatalphapixel = NULL; + + /* Set some very sane GL defaults */ + video->gl_config.driver_loaded = 0; + video->gl_config.dll_handle = NULL; + video->gl_config.red_size = 3; + video->gl_config.green_size = 3; + video->gl_config.blue_size = 2; + video->gl_config.alpha_size = 0; + video->gl_config.buffer_size = 0; + video->gl_config.depth_size = 16; + video->gl_config.stencil_size = 0; + video->gl_config.double_buffer = 1; + video->gl_config.accum_red_size = 0; + video->gl_config.accum_green_size = 0; + video->gl_config.accum_blue_size = 0; + video->gl_config.accum_alpha_size = 0; + video->gl_config.stereo = 0; + video->gl_config.multisamplebuffers = 0; + video->gl_config.multisamplesamples = 0; + video->gl_config.accelerated = -1; /* not known, don't set */ + video->gl_config.swap_control = -1; /* not known, don't set */ + + /* Initialize the video subsystem */ + SDL_memset(&vformat, 0, sizeof(vformat)); + if ( video->VideoInit(video, &vformat) < 0 ) { + SDL_VideoQuit(); + return(-1); + } + + /* Create a zero sized video surface of the appropriate format */ + video_flags = SDL_SWSURFACE; + SDL_VideoSurface = SDL_CreateRGBSurface(video_flags, 0, 0, + vformat.BitsPerPixel, + vformat.Rmask, vformat.Gmask, vformat.Bmask, 0); + if ( SDL_VideoSurface == NULL ) { + SDL_VideoQuit(); + return(-1); + } + SDL_PublicSurface = NULL; /* Until SDL_SetVideoMode() */ + +#if 0 /* Don't change the current palette - may be used by other programs. + * The application can't do anything with the display surface until + * a video mode has been set anyway. :) + */ + /* If we have a palettized surface, create a default palette */ + if ( SDL_VideoSurface->format->palette ) { + SDL_PixelFormat *vf = SDL_VideoSurface->format; + SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); + video->SetColors(video, + 0, vf->palette->ncolors, vf->palette->colors); + } +#endif + video->info.vfmt = SDL_VideoSurface->format; + + /* Start the event loop */ + if ( SDL_StartEventLoop(flags) < 0 ) { + SDL_VideoQuit(); + return(-1); + } + SDL_CursorInit(flags & SDL_INIT_EVENTTHREAD); + + /* We're ready to go! */ + return(0); +} + +char *SDL_VideoDriverName(char *namebuf, int maxlen) +{ + if ( current_video != NULL ) { + SDL_strlcpy(namebuf, current_video->name, maxlen); + return(namebuf); + } + return(NULL); +} + +/* + * Get the current display surface + */ +SDL_Surface *SDL_GetVideoSurface(void) +{ + SDL_Surface *visible; + + visible = NULL; + if ( current_video ) { + visible = current_video->visible; + } + return(visible); +} + +/* + * Get the current information about the video hardware + */ +const SDL_VideoInfo *SDL_GetVideoInfo(void) +{ + const SDL_VideoInfo *info; + + info = NULL; + if ( current_video ) { + info = ¤t_video->info; + } + return(info); +} + +/* + * Return a pointer to an array of available screen dimensions for the + * given format, sorted largest to smallest. Returns NULL if there are + * no dimensions available for a particular format, or (SDL_Rect **)-1 + * if any dimension is okay for the given format. If 'format' is NULL, + * the mode list will be for the format given by SDL_GetVideoInfo()->vfmt + */ +SDL_Rect ** SDL_ListModes (SDL_PixelFormat *format, Uint32 flags) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + SDL_Rect **modes; + + modes = NULL; + if ( SDL_VideoSurface ) { + if ( format == NULL ) { + format = SDL_VideoSurface->format; + } + modes = video->ListModes(this, format, flags); + } + return(modes); +} + +/* + * Check to see if a particular video mode is supported. + * It returns 0 if the requested mode is not supported under any bit depth, + * or returns the bits-per-pixel of the closest available mode with the + * given width and height. If this bits-per-pixel is different from the + * one used when setting the video mode, SDL_SetVideoMode() will succeed, + * but will emulate the requested bits-per-pixel with a shadow surface. + */ +static Uint8 SDL_closest_depths[4][8] = { + /* 8 bit closest depth ordering */ + { 0, 8, 16, 15, 32, 24, 0, 0 }, + /* 15,16 bit closest depth ordering */ + { 0, 16, 15, 32, 24, 8, 0, 0 }, + /* 24 bit closest depth ordering */ + { 0, 24, 32, 16, 15, 8, 0, 0 }, + /* 32 bit closest depth ordering */ + { 0, 32, 16, 15, 24, 8, 0, 0 } +}; + + +#ifdef __MACOS__ /* MPW optimization bug? */ +#define NEGATIVE_ONE 0xFFFFFFFF +#else +#define NEGATIVE_ONE -1 +#endif + +int SDL_VideoModeOK (int width, int height, int bpp, Uint32 flags) +{ + int table, b, i; + int supported; + SDL_PixelFormat format; + SDL_Rect **sizes; + + /* Currently 1 and 4 bpp are not supported */ + if ( bpp < 8 || bpp > 32 ) { + return(0); + } + if ( (width <= 0) || (height <= 0) ) { + return(0); + } + + /* Search through the list valid of modes */ + SDL_memset(&format, 0, sizeof(format)); + supported = 0; + table = ((bpp+7)/8)-1; + SDL_closest_depths[table][0] = bpp; + SDL_closest_depths[table][7] = 0; + for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { + format.BitsPerPixel = SDL_closest_depths[table][b]; + sizes = SDL_ListModes(&format, flags); + if ( sizes == (SDL_Rect **)0 ) { + /* No sizes supported at this bit-depth */ + continue; + } else + if (sizes == (SDL_Rect **)NEGATIVE_ONE) { + /* Any size supported at this bit-depth */ + supported = 1; + continue; + } else if (current_video->handles_any_size) { + /* Driver can center a smaller surface to simulate fullscreen */ + for ( i=0; sizes[i]; ++i ) { + if ((sizes[i]->w >= width) && (sizes[i]->h >= height)) { + supported = 1; /* this mode can fit the centered window. */ + break; + } + } + } else + for ( i=0; sizes[i]; ++i ) { + if ((sizes[i]->w == width) && (sizes[i]->h == height)) { + supported = 1; + break; + } + } + } + if ( supported ) { + --b; + return(SDL_closest_depths[table][b]); + } else { + return(0); + } +} + +/* + * Get the closest non-emulated video mode to the one requested + */ +static int SDL_GetVideoMode (int *w, int *h, int *BitsPerPixel, Uint32 flags) +{ + int table, b, i; + int supported; + int native_bpp; + SDL_PixelFormat format; + SDL_Rect **sizes; + + /* Check parameters */ + if ( *BitsPerPixel < 8 || *BitsPerPixel > 32 ) { + SDL_SetError("Invalid bits per pixel (range is {8...32})"); + return(0); + } + if ((*w <= 0) || (*h <= 0)) { + SDL_SetError("Invalid width or height"); + return(0); + } + + /* Try the original video mode, get the closest depth */ + native_bpp = SDL_VideoModeOK(*w, *h, *BitsPerPixel, flags); + if ( native_bpp == *BitsPerPixel ) { + return(1); + } + if ( native_bpp > 0 ) { + *BitsPerPixel = native_bpp; + return(1); + } + + /* No exact size match at any depth, look for closest match */ + SDL_memset(&format, 0, sizeof(format)); + supported = 0; + table = ((*BitsPerPixel+7)/8)-1; + SDL_closest_depths[table][0] = *BitsPerPixel; + SDL_closest_depths[table][7] = SDL_VideoSurface->format->BitsPerPixel; + for ( b = 0; !supported && SDL_closest_depths[table][b]; ++b ) { + int best; + + format.BitsPerPixel = SDL_closest_depths[table][b]; + sizes = SDL_ListModes(&format, flags); + if ( sizes == (SDL_Rect **)0 ) { + /* No sizes supported at this bit-depth */ + continue; + } + best=0; + for ( i=0; sizes[i]; ++i ) { + /* Mode with both dimensions bigger or equal than asked ? */ + if ((sizes[i]->w >= *w) && (sizes[i]->h >= *h)) { + /* Mode with any dimension smaller or equal than current best ? */ + if ((sizes[i]->w <= sizes[best]->w) || (sizes[i]->h <= sizes[best]->h)) { + /* Now choose the mode that has less pixels */ + if ((sizes[i]->w * sizes[i]->h) <= (sizes[best]->w * sizes[best]->h)) { + best=i; + supported = 1; + } + } + } + } + if (supported) { + *w=sizes[best]->w; + *h=sizes[best]->h; + *BitsPerPixel = SDL_closest_depths[table][b]; + } + } + if ( ! supported ) { + SDL_SetError("No video mode large enough for %dx%d", *w, *h); + } + return(supported); +} + +/* This should probably go somewhere else -- like SDL_surface.c */ +static void SDL_ClearSurface(SDL_Surface *surface) +{ + Uint32 black; + + black = SDL_MapRGB(surface->format, 0, 0, 0); + SDL_FillRect(surface, NULL, black); + if ((surface->flags&SDL_HWSURFACE) && (surface->flags&SDL_DOUBLEBUF)) { + SDL_Flip(surface); + SDL_FillRect(surface, NULL, black); + } + if (surface->flags&SDL_FULLSCREEN) { + SDL_Flip(surface); + } +} + +/* + * Create a shadow surface suitable for fooling the app. :-) + */ +static void SDL_CreateShadowSurface(int depth) +{ + Uint32 Rmask, Gmask, Bmask; + + /* Allocate the shadow surface */ + if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { + Rmask = (SDL_VideoSurface->format)->Rmask; + Gmask = (SDL_VideoSurface->format)->Gmask; + Bmask = (SDL_VideoSurface->format)->Bmask; + } else { + Rmask = Gmask = Bmask = 0; + } + SDL_ShadowSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, + SDL_VideoSurface->w, SDL_VideoSurface->h, + depth, Rmask, Gmask, Bmask, 0); + if ( SDL_ShadowSurface == NULL ) { + return; + } + + /* 8-bit shadow surfaces report that they have exclusive palette */ + if ( SDL_ShadowSurface->format->palette ) { + SDL_ShadowSurface->flags |= SDL_HWPALETTE; + if ( depth == (SDL_VideoSurface->format)->BitsPerPixel ) { + SDL_memcpy(SDL_ShadowSurface->format->palette->colors, + SDL_VideoSurface->format->palette->colors, + SDL_VideoSurface->format->palette->ncolors* + sizeof(SDL_Color)); + } else { + SDL_DitherColors( + SDL_ShadowSurface->format->palette->colors, depth); + } + } + + /* If the video surface is resizable, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_RESIZABLE) == SDL_RESIZABLE ) { + SDL_ShadowSurface->flags |= SDL_RESIZABLE; + } + /* If the video surface has no frame, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_NOFRAME) == SDL_NOFRAME ) { + SDL_ShadowSurface->flags |= SDL_NOFRAME; + } + /* If the video surface is fullscreen, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + SDL_ShadowSurface->flags |= SDL_FULLSCREEN; + } + /* If the video surface is flippable, the shadow should say so */ + if ( (SDL_VideoSurface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + SDL_ShadowSurface->flags |= SDL_DOUBLEBUF; + } + return; +} + +#ifdef __QNXNTO__ + #include <sys/neutrino.h> +#endif /* __QNXNTO__ */ + +#ifdef WIN32 + extern int sysevents_mouse_pressed; +#endif + +/* + * Set the requested video mode, allocating a shadow buffer if necessary. + */ +SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags) +{ + SDL_VideoDevice *video, *this; + SDL_Surface *prev_mode, *mode; + int video_w; + int video_h; + int video_bpp; + int is_opengl; + SDL_GrabMode saved_grab; + + #ifdef WIN32 + sysevents_mouse_pressed = 0; + #endif + + /* Start up the video driver, if necessary.. + WARNING: This is the only function protected this way! + */ + if ( ! current_video ) { + if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) { + return(NULL); + } + } + this = video = current_video; + + /* Default to the current width and height */ + if ( width == 0 ) { + width = video->info.current_w; + } + if ( height == 0 ) { + height = video->info.current_h; + } + /* Default to the current video bpp */ + if ( bpp == 0 ) { + flags |= SDL_ANYFORMAT; + bpp = SDL_VideoSurface->format->BitsPerPixel; + } + + /* Get a good video mode, the closest one possible */ + video_w = width; + video_h = height; + video_bpp = bpp; + if ( ! SDL_GetVideoMode(&video_w, &video_h, &video_bpp, flags) ) { + return(NULL); + } + + /* Check the requested flags */ + /* There's no palette in > 8 bits-per-pixel mode */ + if ( video_bpp > 8 ) { + flags &= ~SDL_HWPALETTE; + } +#if 0 + if ( (flags&SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* There's no windowed double-buffering */ + flags &= ~SDL_DOUBLEBUF; + } +#endif + if ( (flags&SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + /* Use hardware surfaces when double-buffering */ + flags |= SDL_HWSURFACE; + } + + is_opengl = ( ( flags & SDL_OPENGL ) == SDL_OPENGL ); + if ( is_opengl ) { + /* These flags are for 2D video modes only */ + flags &= ~(SDL_HWSURFACE|SDL_DOUBLEBUF); + } + + /* Reset the keyboard here so event callbacks can run */ + SDL_ResetKeyboard(); + SDL_ResetMouse(); + SDL_SetMouseRange(width, height); + SDL_cursorstate &= ~CURSOR_USINGSW; + + /* Clean up any previous video mode */ + if ( SDL_PublicSurface != NULL ) { + SDL_PublicSurface = NULL; + } + if ( SDL_ShadowSurface != NULL ) { + SDL_Surface *ready_to_go; + ready_to_go = SDL_ShadowSurface; + SDL_ShadowSurface = NULL; + SDL_FreeSurface(ready_to_go); + } + if ( video->physpal ) { + SDL_free(video->physpal->colors); + SDL_free(video->physpal); + video->physpal = NULL; + } + if( video->gammacols) { + SDL_free(video->gammacols); + video->gammacols = NULL; + } + + /* Save the previous grab state and turn off grab for mode switch */ + saved_grab = SDL_WM_GrabInputOff(); + + /* Try to set the video mode, along with offset and clipping */ + prev_mode = SDL_VideoSurface; + SDL_LockCursor(); + SDL_VideoSurface = NULL; /* In case it's freed by driver */ + mode = video->SetVideoMode(this, prev_mode,video_w,video_h,video_bpp,flags); + if ( mode ) { /* Prevent resize events from mode change */ + /* But not on OS/2 */ +#ifndef __OS2__ + SDL_PrivateResize(mode->w, mode->h); +#endif + + /* Sam - If we asked for OpenGL mode, and didn't get it, fail */ + if ( is_opengl && !(mode->flags & SDL_OPENGL) ) { + mode = NULL; + SDL_SetError("OpenGL not available"); + } + } + /* + * rcg11292000 + * If you try to set an SDL_OPENGL surface, and fail to find a + * matching visual, then the next call to SDL_SetVideoMode() + * will segfault, since we no longer point to a dummy surface, + * but rather NULL. + * Sam 11/29/00 + * WARNING, we need to make sure that the previous mode hasn't + * already been freed by the video driver. What do we do in + * that case? Should we call SDL_VideoInit() again? + */ + SDL_VideoSurface = (mode != NULL) ? mode : prev_mode; + + if ( (mode != NULL) && (!is_opengl) ) { + /* Sanity check */ + if ( (mode->w < width) || (mode->h < height) ) { + SDL_SetError("Video mode smaller than requested"); + return(NULL); + } + + /* If we have a palettized surface, create a default palette */ + if ( mode->format->palette ) { + SDL_PixelFormat *vf = mode->format; + SDL_DitherColors(vf->palette->colors, vf->BitsPerPixel); + video->SetColors(this, 0, vf->palette->ncolors, + vf->palette->colors); + } + + /* Clear the surface to black */ + video->offset_x = 0; + video->offset_y = 0; + mode->offset = 0; + SDL_SetClipRect(mode, NULL); + SDL_ClearSurface(mode); + + /* Now adjust the offsets to match the desired mode */ + video->offset_x = (mode->w-width)/2; + video->offset_y = (mode->h-height)/2; + mode->offset = video->offset_y*mode->pitch + + video->offset_x*mode->format->BytesPerPixel; +#ifdef DEBUG_VIDEO + fprintf(stderr, + "Requested mode: %dx%dx%d, obtained mode %dx%dx%d (offset %d)\n", + width, height, bpp, + mode->w, mode->h, mode->format->BitsPerPixel, mode->offset); +#endif + mode->w = width; + mode->h = height; + SDL_SetClipRect(mode, NULL); + } + SDL_ResetCursor(); + SDL_UnlockCursor(); + + /* If we failed setting a video mode, return NULL... (Uh Oh!) */ + if ( mode == NULL ) { + return(NULL); + } + + /* If there is no window manager, set the SDL_NOFRAME flag */ + if ( ! video->info.wm_available ) { + mode->flags |= SDL_NOFRAME; + } + + /* Reset the mouse cursor and grab for new video mode */ + SDL_SetCursor(NULL); + if ( video->UpdateMouse ) { + video->UpdateMouse(this); + } + SDL_WM_GrabInput(saved_grab); + SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */ + +#if SDL_VIDEO_OPENGL + /* Load GL symbols (before MakeCurrent, where we need glGetString). */ + if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) { + +#if defined(__QNXNTO__) && (_NTO_VERSION < 630) +#define __SDL_NOGETPROCADDR__ +#elif defined(__MINT__) +#define __SDL_NOGETPROCADDR__ +#endif +#ifdef __SDL_NOGETPROCADDR__ + #define SDL_PROC(ret,func,params) video->func=func; +#else + #define SDL_PROC(ret,func,params) \ + do { \ + video->func = SDL_GL_GetProcAddress(#func); \ + if ( ! video->func ) { \ + SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \ + return(NULL); \ + } \ + } while ( 0 ); + +#endif /* __SDL_NOGETPROCADDR__ */ + +#include "SDL_glfuncs.h" +#undef SDL_PROC + } +#endif /* SDL_VIDEO_OPENGL */ + + /* If we're running OpenGL, make the context current */ + if ( (video->screen->flags & SDL_OPENGL) && + video->GL_MakeCurrent ) { + if ( video->GL_MakeCurrent(this) < 0 ) { + return(NULL); + } + } + + /* Set up a fake SDL surface for OpenGL "blitting" */ + if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) { + /* Load GL functions for performing the texture updates */ +#if SDL_VIDEO_OPENGL + + /* Create a software surface for blitting */ +#ifdef GL_VERSION_1_2 + /* If the implementation either supports the packed pixels + extension, or implements the core OpenGL 1.2 API, it will + support the GL_UNSIGNED_SHORT_5_6_5 texture format. + */ + if ( (bpp == 16) && + (SDL_strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") || + (SDL_atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f)) + ) { + video->is_32bit = 0; + SDL_VideoSurface = SDL_CreateRGBSurface( + flags, + width, + height, + 16, + 31 << 11, + 63 << 5, + 31, + 0 + ); + } + else +#endif /* OpenGL 1.2 */ + { + video->is_32bit = 1; + SDL_VideoSurface = SDL_CreateRGBSurface( + flags, + width, + height, + 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + ); + } + if ( ! SDL_VideoSurface ) { + return(NULL); + } + SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT; + + /* Free the original video mode surface (is this safe?) */ + SDL_FreeSurface(mode); + + /* Set the surface completely opaque & white by default */ + SDL_memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch ); + video->glGenTextures( 1, &video->texture ); + video->glBindTexture( GL_TEXTURE_2D, video->texture ); + video->glTexImage2D( + GL_TEXTURE_2D, + 0, + video->is_32bit ? GL_RGBA : GL_RGB, + 256, + 256, + 0, + video->is_32bit ? GL_RGBA : GL_RGB, +#ifdef GL_VERSION_1_2 + video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, +#else + GL_UNSIGNED_BYTE, +#endif + NULL); + + video->UpdateRects = SDL_GL_UpdateRectsLock; +#else + SDL_SetError("Somebody forgot to #define SDL_VIDEO_OPENGL"); + return(NULL); +#endif + } + + /* Create a shadow surface if necessary */ + /* There are three conditions under which we create a shadow surface: + 1. We need a particular bits-per-pixel that we didn't get. + 2. We need a hardware palette and didn't get one. + 3. We need a software surface and got a hardware surface. + */ + if ( !(SDL_VideoSurface->flags & SDL_OPENGL) && + ( + ( !(flags&SDL_ANYFORMAT) && + (SDL_VideoSurface->format->BitsPerPixel != bpp)) || + ( (flags&SDL_HWPALETTE) && + !(SDL_VideoSurface->flags&SDL_HWPALETTE)) || + /* If the surface is in hardware, video writes are visible + as soon as they are performed, so we need to buffer them + */ + ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) && + (SDL_VideoSurface->flags&SDL_HWSURFACE)) || + ( (flags&SDL_DOUBLEBUF) && + (SDL_VideoSurface->flags&SDL_HWSURFACE) && + !(SDL_VideoSurface->flags&SDL_DOUBLEBUF)) + ) ) { + SDL_CreateShadowSurface(bpp); + if ( SDL_ShadowSurface == NULL ) { + SDL_SetError("Couldn't create shadow surface"); + return(NULL); + } + SDL_PublicSurface = SDL_ShadowSurface; + } else { + SDL_PublicSurface = SDL_VideoSurface; + } + video->info.vfmt = SDL_VideoSurface->format; + video->info.current_w = SDL_VideoSurface->w; + video->info.current_h = SDL_VideoSurface->h; + + /* We're done! */ + return(SDL_PublicSurface); +} + +/* + * Convert a surface into the video pixel format. + */ +SDL_Surface * SDL_DisplayFormat (SDL_Surface *surface) +{ + Uint32 flags; + + if ( ! SDL_PublicSurface ) { + SDL_SetError("No video mode has been set"); + return(NULL); + } + /* Set the flags appropriate for copying to display surface */ + if (((SDL_PublicSurface->flags&SDL_HWSURFACE) == SDL_HWSURFACE) && current_video->info.blit_hw) + flags = SDL_HWSURFACE; + else + flags = SDL_SWSURFACE; +#ifdef AUTORLE_DISPLAYFORMAT + flags |= (surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA)); + flags |= SDL_RLEACCELOK; +#else + flags |= surface->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA|SDL_RLEACCELOK); +#endif + return(SDL_ConvertSurface(surface, SDL_PublicSurface->format, flags)); +} + +/* + * Convert a surface into a format that's suitable for blitting to + * the screen, but including an alpha channel. + */ +SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface) +{ + SDL_PixelFormat *vf; + SDL_PixelFormat *format; + SDL_Surface *converted; + Uint32 flags; + /* default to ARGB8888 */ + Uint32 amask = 0xff000000; + Uint32 rmask = 0x00ff0000; + Uint32 gmask = 0x0000ff00; + Uint32 bmask = 0x000000ff; + + if ( ! SDL_PublicSurface ) { + SDL_SetError("No video mode has been set"); + return(NULL); + } + vf = SDL_PublicSurface->format; + + switch(vf->BytesPerPixel) { + case 2: + /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}. + For anything else (like ARGB4444) it doesn't matter + since we have no special code for it anyway */ + if ( (vf->Rmask == 0x1f) && + (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) { + rmask = 0xff; + bmask = 0xff0000; + } + break; + + case 3: + case 4: + /* Keep the video format, as long as the high 8 bits are + unused or alpha */ + if ( (vf->Rmask == 0xff) && (vf->Bmask == 0xff0000) ) { + rmask = 0xff; + bmask = 0xff0000; + } else if ( vf->Rmask == 0xFF00 && (vf->Bmask == 0xFF000000) ) { + amask = 0x000000FF; + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; + } + break; + + default: + /* We have no other optimised formats right now. When/if a new + optimised alpha format is written, add the converter here */ + break; + } + format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); + flags = SDL_PublicSurface->flags & SDL_HWSURFACE; + flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + converted = SDL_ConvertSurface(surface, format, flags); + SDL_FreeFormat(format); + return(converted); +} + +/* + * Update a specific portion of the physical screen + */ +void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) +{ + if ( screen ) { + SDL_Rect rect; + + /* Perform some checking */ + if ( w == 0 ) + w = screen->w; + if ( h == 0 ) + h = screen->h; + if ( (int)(x+w) > screen->w ) + return; + if ( (int)(y+h) > screen->h ) + return; + + /* Fill the rectangle */ + rect.x = (Sint16)x; + rect.y = (Sint16)y; + rect.w = (Uint16)w; + rect.h = (Uint16)h; + SDL_UpdateRects(screen, 1, &rect); + } +} +void SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects) +{ + int i; + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( (screen->flags & (SDL_OPENGL | SDL_OPENGLBLIT)) == SDL_OPENGL ) { + SDL_SetError("OpenGL active, use SDL_GL_SwapBuffers()"); + return; + } + if ( screen == SDL_ShadowSurface ) { + /* Blit the shadow surface using saved mapping */ + SDL_Palette *pal = screen->format->palette; + SDL_Color *saved_colors = NULL; + if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { + /* simulated 8bpp, use correct physical palette */ + saved_colors = pal->colors; + if ( video->gammacols ) { + /* gamma-corrected palette */ + pal->colors = video->gammacols; + } else if ( video->physpal ) { + /* physical palette different from logical */ + pal->colors = video->physpal->colors; + } + } + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_LockCursor(); + SDL_DrawCursor(SDL_ShadowSurface); + for ( i=0; i<numrects; ++i ) { + SDL_LowerBlit(SDL_ShadowSurface, &rects[i], + SDL_VideoSurface, &rects[i]); + } + SDL_EraseCursor(SDL_ShadowSurface); + SDL_UnlockCursor(); + } else { + for ( i=0; i<numrects; ++i ) { + SDL_LowerBlit(SDL_ShadowSurface, &rects[i], + SDL_VideoSurface, &rects[i]); + } + } + if ( saved_colors ) { + pal->colors = saved_colors; + } + + /* Fall through to video surface update */ + screen = SDL_VideoSurface; + } + if ( screen == SDL_VideoSurface ) { + /* Update the video surface */ + if ( screen->offset ) { + for ( i=0; i<numrects; ++i ) { + rects[i].x += video->offset_x; + rects[i].y += video->offset_y; + } + video->UpdateRects(this, numrects, rects); + for ( i=0; i<numrects; ++i ) { + rects[i].x -= video->offset_x; + rects[i].y -= video->offset_y; + } + } else { + video->UpdateRects(this, numrects, rects); + } + } +} + +/* + * Performs hardware double buffering, if possible, or a full update if not. + */ +int SDL_Flip(SDL_Surface *screen) +{ + SDL_VideoDevice *video = current_video; + /* Copy the shadow surface to the video surface */ + if ( screen == SDL_ShadowSurface ) { + SDL_Rect rect; + SDL_Palette *pal = screen->format->palette; + SDL_Color *saved_colors = NULL; + if ( pal && !(SDL_VideoSurface->flags & SDL_HWPALETTE) ) { + /* simulated 8bpp, use correct physical palette */ + saved_colors = pal->colors; + if ( video->gammacols ) { + /* gamma-corrected palette */ + pal->colors = video->gammacols; + } else if ( video->physpal ) { + /* physical palette different from logical */ + pal->colors = video->physpal->colors; + } + } + + rect.x = 0; + rect.y = 0; + rect.w = screen->w; + rect.h = screen->h; + if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { + SDL_LockCursor(); + SDL_DrawCursor(SDL_ShadowSurface); + SDL_LowerBlit(SDL_ShadowSurface, &rect, + SDL_VideoSurface, &rect); + SDL_EraseCursor(SDL_ShadowSurface); + SDL_UnlockCursor(); + } else { + SDL_LowerBlit(SDL_ShadowSurface, &rect, + SDL_VideoSurface, &rect); + } + if ( saved_colors ) { + pal->colors = saved_colors; + } + + /* Fall through to video surface update */ + screen = SDL_VideoSurface; + } + if ( (screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + SDL_VideoDevice *this = current_video; + return(video->FlipHWSurface(this, SDL_VideoSurface)); + } else { + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + return(0); +} + +static void SetPalette_logical(SDL_Surface *screen, SDL_Color *colors, + int firstcolor, int ncolors) +{ + SDL_Palette *pal = screen->format->palette; + SDL_Palette *vidpal; + + if ( colors != (pal->colors + firstcolor) ) { + SDL_memcpy(pal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + + if ( current_video && SDL_VideoSurface ) { + vidpal = SDL_VideoSurface->format->palette; + if ( (screen == SDL_ShadowSurface) && vidpal ) { + /* + * This is a shadow surface, and the physical + * framebuffer is also indexed. Propagate the + * changes to its logical palette so that + * updates are always identity blits + */ + SDL_memcpy(vidpal->colors + firstcolor, colors, + ncolors * sizeof(*colors)); + } + } + SDL_FormatChanged(screen); +} + +static int SetPalette_physical(SDL_Surface *screen, + SDL_Color *colors, int firstcolor, int ncolors) +{ + SDL_VideoDevice *video = current_video; + int gotall = 1; + + if ( video->physpal ) { + /* We need to copy the new colors, since we haven't + * already done the copy in the logical set above. + */ + SDL_memcpy(video->physpal->colors + firstcolor, + colors, ncolors * sizeof(*colors)); + } + if ( screen == SDL_ShadowSurface ) { + if ( SDL_VideoSurface->flags & SDL_HWPALETTE ) { + /* + * The real screen is also indexed - set its physical + * palette. The physical palette does not include the + * gamma modification, we apply it directly instead, + * but this only happens if we have hardware palette. + */ + screen = SDL_VideoSurface; + } else { + /* + * The video surface is not indexed - invalidate any + * active shadow-to-video blit mappings. + */ + if ( screen->map->dst == SDL_VideoSurface ) { + SDL_InvalidateMap(screen->map); + } + if ( video->gamma ) { + if( ! video->gammacols ) { + SDL_Palette *pp = video->physpal; + if(!pp) + pp = screen->format->palette; + video->gammacols = SDL_malloc(pp->ncolors + * sizeof(SDL_Color)); + SDL_ApplyGamma(video->gamma, + pp->colors, + video->gammacols, + pp->ncolors); + } else { + SDL_ApplyGamma(video->gamma, colors, + video->gammacols + + firstcolor, + ncolors); + } + } + SDL_UpdateRect(screen, 0, 0, 0, 0); + } + } + + if ( screen == SDL_VideoSurface ) { + SDL_Color gcolors[256]; + + if ( video->gamma ) { + SDL_ApplyGamma(video->gamma, colors, gcolors, ncolors); + colors = gcolors; + } + gotall = video->SetColors(video, firstcolor, ncolors, colors); + if ( ! gotall ) { + /* The video flags shouldn't have SDL_HWPALETTE, and + the video driver is responsible for copying back the + correct colors into the video surface palette. + */ + ; + } + SDL_CursorPaletteChanged(); + } + return gotall; +} + +/* + * Set the physical and/or logical colormap of a surface: + * Only the screen has a physical colormap. It determines what is actually + * sent to the display. + * The logical colormap is used to map blits to/from the surface. + * 'which' is one or both of SDL_LOGPAL, SDL_PHYSPAL + * + * Return nonzero if all colours were set as requested, or 0 otherwise. + */ +int SDL_SetPalette(SDL_Surface *screen, int which, + SDL_Color *colors, int firstcolor, int ncolors) +{ + SDL_Palette *pal; + int gotall; + int palsize; + + if ( !screen ) { + return 0; + } + if ( !current_video || screen != SDL_PublicSurface ) { + /* only screens have physical palettes */ + which &= ~SDL_PHYSPAL; + } else if ( (screen->flags & SDL_HWPALETTE) != SDL_HWPALETTE ) { + /* hardware palettes required for split colormaps */ + which |= SDL_PHYSPAL | SDL_LOGPAL; + } + + /* Verify the parameters */ + pal = screen->format->palette; + if( !pal ) { + return 0; /* not a palettized surface */ + } + gotall = 1; + palsize = 1 << screen->format->BitsPerPixel; + if ( ncolors > (palsize - firstcolor) ) { + ncolors = (palsize - firstcolor); + gotall = 0; + } + + if ( which & SDL_LOGPAL ) { + /* + * Logical palette change: The actual screen isn't affected, + * but the internal colormap is altered so that the + * interpretation of the pixel values (for blits etc) is + * changed. + */ + SetPalette_logical(screen, colors, firstcolor, ncolors); + } + if ( which & SDL_PHYSPAL ) { + SDL_VideoDevice *video = current_video; + /* + * Physical palette change: This doesn't affect the + * program's idea of what the screen looks like, but changes + * its actual appearance. + */ + if ( !video->physpal && !(which & SDL_LOGPAL) ) { + /* Lazy physical palette allocation */ + int size; + SDL_Palette *pp = SDL_malloc(sizeof(*pp)); + if ( !pp ) { + return 0; + } + video->physpal = pp; + pp->ncolors = pal->ncolors; + size = pp->ncolors * sizeof(SDL_Color); + pp->colors = SDL_malloc(size); + if ( !pp->colors ) { + return 0; + } + SDL_memcpy(pp->colors, pal->colors, size); + } + if ( ! SetPalette_physical(screen, + colors, firstcolor, ncolors) ) { + gotall = 0; + } + } + return gotall; +} + +int SDL_SetColors(SDL_Surface *screen, SDL_Color *colors, int firstcolor, + int ncolors) +{ + return SDL_SetPalette(screen, SDL_LOGPAL | SDL_PHYSPAL, + colors, firstcolor, ncolors); +} + +/* + * Clean up the video subsystem + */ +void SDL_VideoQuit (void) +{ + SDL_Surface *ready_to_go; + + if ( current_video ) { + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Halt event processing before doing anything else */ + SDL_StopEventLoop(); + + /* Clean up allocated window manager items */ + if ( SDL_PublicSurface ) { + SDL_PublicSurface = NULL; + } + SDL_CursorQuit(); + + /* Just in case... */ + SDL_WM_GrabInputOff(); + + /* Clean up the system video */ + video->VideoQuit(this); + + /* Free any lingering surfaces */ + ready_to_go = SDL_ShadowSurface; + SDL_ShadowSurface = NULL; + SDL_FreeSurface(ready_to_go); + if ( SDL_VideoSurface != NULL ) { + ready_to_go = SDL_VideoSurface; + SDL_VideoSurface = NULL; + SDL_FreeSurface(ready_to_go); + } + SDL_PublicSurface = NULL; + + /* Clean up miscellaneous memory */ + if ( video->physpal ) { + SDL_free(video->physpal->colors); + SDL_free(video->physpal); + video->physpal = NULL; + } + if ( video->gammacols ) { + SDL_free(video->gammacols); + video->gammacols = NULL; + } + if ( video->gamma ) { + SDL_free(video->gamma); + video->gamma = NULL; + } + if ( video->wm_title != NULL ) { + SDL_free(video->wm_title); + video->wm_title = NULL; + } + if ( video->wm_icon != NULL ) { + SDL_free(video->wm_icon); + video->wm_icon = NULL; + } + + /* Finish cleaning up video subsystem */ + video->free(this); + current_video = NULL; + } + return; +} + +/* Load the GL driver library */ +int SDL_GL_LoadLibrary(const char *path) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int retval; + + retval = -1; + if ( video == NULL ) { + SDL_SetError("Video subsystem has not been initialized"); + } else { + if ( video->GL_LoadLibrary ) { + retval = video->GL_LoadLibrary(this, path); + } else { + SDL_SetError("No dynamic GL support in video driver"); + } + } + return(retval); +} + +void *SDL_GL_GetProcAddress(const char* proc) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + void *func; + + func = NULL; + if ( video->GL_GetProcAddress ) { + if ( video->gl_config.driver_loaded ) { + func = video->GL_GetProcAddress(this, proc); + } else { + SDL_SetError("No GL driver has been loaded"); + } + } else { + SDL_SetError("No dynamic GL support in video driver"); + } + return func; +} + +/* Set the specified GL attribute for setting up a GL video mode */ +int SDL_GL_SetAttribute( SDL_GLattr attr, int value ) +{ + int retval; + SDL_VideoDevice *video = current_video; + + retval = 0; + switch (attr) { + case SDL_GL_RED_SIZE: + video->gl_config.red_size = value; + break; + case SDL_GL_GREEN_SIZE: + video->gl_config.green_size = value; + break; + case SDL_GL_BLUE_SIZE: + video->gl_config.blue_size = value; + break; + case SDL_GL_ALPHA_SIZE: + video->gl_config.alpha_size = value; + break; + case SDL_GL_DOUBLEBUFFER: + video->gl_config.double_buffer = value; + break; + case SDL_GL_BUFFER_SIZE: + video->gl_config.buffer_size = value; + break; + case SDL_GL_DEPTH_SIZE: + video->gl_config.depth_size = value; + break; + case SDL_GL_STENCIL_SIZE: + video->gl_config.stencil_size = value; + break; + case SDL_GL_ACCUM_RED_SIZE: + video->gl_config.accum_red_size = value; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + video->gl_config.accum_green_size = value; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + video->gl_config.accum_blue_size = value; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + video->gl_config.accum_alpha_size = value; + break; + case SDL_GL_STEREO: + video->gl_config.stereo = value; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + video->gl_config.multisamplebuffers = value; + break; + case SDL_GL_MULTISAMPLESAMPLES: + video->gl_config.multisamplesamples = value; + break; + case SDL_GL_ACCELERATED_VISUAL: + video->gl_config.accelerated = value; + break; + case SDL_GL_SWAP_CONTROL: + video->gl_config.swap_control = value; + break; + default: + SDL_SetError("Unknown OpenGL attribute"); + retval = -1; + break; + } + return(retval); +} + +/* Retrieve an attribute value from the windowing system. */ +int SDL_GL_GetAttribute(SDL_GLattr attr, int* value) +{ + int retval = -1; + SDL_VideoDevice* video = current_video; + SDL_VideoDevice* this = current_video; + + if ( video->GL_GetAttribute ) { + retval = this->GL_GetAttribute(this, attr, value); + } else { + *value = 0; + SDL_SetError("GL_GetAttribute not supported"); + } + return retval; +} + +/* Perform a GL buffer swap on the current GL context */ +void SDL_GL_SwapBuffers(void) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video->screen->flags & SDL_OPENGL ) { + video->GL_SwapBuffers(this); + } else { + SDL_SetError("OpenGL video mode has not been set"); + } +} + +/* Update rects with locking */ +void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects) +{ + SDL_GL_Lock(); + SDL_GL_UpdateRects(numrects, rects); + SDL_GL_Unlock(); +} + +/* Update rects without state setting and changing (the caller is responsible for it) */ +void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects) +{ +#if SDL_VIDEO_OPENGL + SDL_VideoDevice *this = current_video; + SDL_Rect update, tmp; + int x, y, i; + + for ( i = 0; i < numrects; i++ ) + { + tmp.y = rects[i].y; + tmp.h = rects[i].h; + for ( y = 0; y <= rects[i].h / 256; y++ ) + { + tmp.x = rects[i].x; + tmp.w = rects[i].w; + for ( x = 0; x <= rects[i].w / 256; x++ ) + { + update.x = tmp.x; + update.y = tmp.y; + update.w = tmp.w; + update.h = tmp.h; + + if ( update.w > 256 ) + update.w = 256; + + if ( update.h > 256 ) + update.h = 256; + + this->glFlush(); + this->glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + update.w, + update.h, + this->is_32bit? GL_RGBA : GL_RGB, +#ifdef GL_VERSION_1_2 + this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, +#else + GL_UNSIGNED_BYTE, +#endif + (Uint8 *)this->screen->pixels + + this->screen->format->BytesPerPixel * update.x + + update.y * this->screen->pitch ); + + this->glFlush(); + /* + * Note the parens around the function name: + * This is because some OpenGL implementations define glTexCoord etc + * as macros, and we don't want them expanded here. + */ + this->glBegin(GL_TRIANGLE_STRIP); + (this->glTexCoord2f)( 0.0, 0.0 ); + (this->glVertex2i)( update.x, update.y ); + (this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 ); + (this->glVertex2i)( update.x + update.w, update.y ); + (this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) ); + (this->glVertex2i)( update.x, update.y + update.h ); + (this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) ); + (this->glVertex2i)( update.x + update.w , update.y + update.h ); + this->glEnd(); + + tmp.x += 256; + tmp.w -= 256; + } + tmp.y += 256; + tmp.h -= 256; + } + } +#endif +} + +/* Lock == save current state */ +void SDL_GL_Lock() +{ +#if SDL_VIDEO_OPENGL + lock_count--; + if (lock_count==-1) + { + SDL_VideoDevice *this = current_video; + + this->glPushAttrib( GL_ALL_ATTRIB_BITS ); /* TODO: narrow range of what is saved */ +#ifdef GL_CLIENT_PIXEL_STORE_BIT + this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT ); +#endif + + this->glEnable(GL_TEXTURE_2D); + this->glEnable(GL_BLEND); + this->glDisable(GL_FOG); + this->glDisable(GL_ALPHA_TEST); + this->glDisable(GL_DEPTH_TEST); + this->glDisable(GL_SCISSOR_TEST); + this->glDisable(GL_STENCIL_TEST); + this->glDisable(GL_CULL_FACE); + + this->glBindTexture( GL_TEXTURE_2D, this->texture ); + this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + + this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel ); + this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + (this->glColor4f)(1.0, 1.0, 1.0, 1.0); /* Solaris workaround */ + + this->glViewport(0, 0, this->screen->w, this->screen->h); + this->glMatrixMode(GL_PROJECTION); + this->glPushMatrix(); + this->glLoadIdentity(); + + this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0); + + this->glMatrixMode(GL_MODELVIEW); + this->glPushMatrix(); + this->glLoadIdentity(); + } +#endif +} + +/* Unlock == restore saved state */ +void SDL_GL_Unlock() +{ +#if SDL_VIDEO_OPENGL + lock_count++; + if (lock_count==0) + { + SDL_VideoDevice *this = current_video; + + this->glPopMatrix(); + this->glMatrixMode(GL_PROJECTION); + this->glPopMatrix(); + + this->glPopClientAttrib(); + this->glPopAttrib(); + } +#endif +} + + +void SDL_Audio_SetCaption(const char *caption); + +/* + * Sets/Gets the title and icon text of the display window, if any. + */ +void SDL_WM_SetCaption (const char *title, const char *icon) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video ) { + if ( title ) { + if ( video->wm_title ) { + SDL_free(video->wm_title); + } + video->wm_title = SDL_strdup(title); + } + if ( icon ) { + if ( video->wm_icon ) { + SDL_free(video->wm_icon); + } + video->wm_icon = SDL_strdup(icon); + } + if ( (title || icon) && (video->SetCaption != NULL) ) { + video->SetCaption(this, video->wm_title,video->wm_icon); + } + } + + /* PulseAudio can make use of this information. */ + SDL_Audio_SetCaption(title); +} + +void SDL_WM_GetCaption (char **title, char **icon) +{ + SDL_VideoDevice *video = current_video; + + if ( video ) { + if ( title ) { + *title = video->wm_title; + } + if ( icon ) { + *icon = video->wm_icon; + } + } +} + +/* Utility function used by SDL_WM_SetIcon(); + * flags & 1 for color key, flags & 2 for alpha channel. */ +static void CreateMaskFromColorKeyOrAlpha(SDL_Surface *icon, Uint8 *mask, int flags) +{ + int x, y; + Uint32 colorkey; +#define SET_MASKBIT(icon, x, y, mask) \ + mask[(y*((icon->w+7)/8))+(x/8)] &= ~(0x01<<(7-(x%8))) + + colorkey = icon->format->colorkey; + switch (icon->format->BytesPerPixel) { + case 1: { Uint8 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint8 *)icon->pixels + y*icon->pitch; + for ( x=0; x<icon->w; ++x ) { + if ( *pixels++ == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } + } + } + } + break; + + case 2: { Uint16 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint16 *)icon->pixels + + y*icon->pitch/2; + for ( x=0; x<icon->w; ++x ) { + if ( (flags & 1) && *pixels == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { + SET_MASKBIT(icon, x, y, mask); + } + pixels++; + } + } + } + break; + + case 4: { Uint32 *pixels; + for ( y=0; y<icon->h; ++y ) { + pixels = (Uint32 *)icon->pixels + + y*icon->pitch/4; + for ( x=0; x<icon->w; ++x ) { + if ( (flags & 1) && *pixels == colorkey ) { + SET_MASKBIT(icon, x, y, mask); + } else if((flags & 2) && (*pixels & icon->format->Amask) == 0) { + SET_MASKBIT(icon, x, y, mask); + } + pixels++; + } + } + } + break; + } +} + +/* + * Sets the window manager icon for the display window. + */ +void SDL_WM_SetIcon (SDL_Surface *icon, Uint8 *mask) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( icon && video->SetIcon ) { + /* Generate a mask if necessary, and create the icon! */ + if ( mask == NULL ) { + int mask_len = icon->h*(icon->w+7)/8; + int flags = 0; + mask = (Uint8 *)SDL_malloc(mask_len); + if ( mask == NULL ) { + return; + } + SDL_memset(mask, ~0, mask_len); + if ( icon->flags & SDL_SRCCOLORKEY ) flags |= 1; + if ( icon->flags & SDL_SRCALPHA ) flags |= 2; + if( flags ) { + CreateMaskFromColorKeyOrAlpha(icon, mask, flags); + } + video->SetIcon(video, icon, mask); + SDL_free(mask); + } else { + video->SetIcon(this, icon, mask); + } + } +} + +/* + * Grab or ungrab the keyboard and mouse input. + * This function returns the final grab mode after calling the + * driver dependent function. + */ +static SDL_GrabMode SDL_WM_GrabInputRaw(SDL_GrabMode mode) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + /* Only do something if we have support for grabs */ + if ( video->GrabInput == NULL ) { + return(video->input_grab); + } + + /* If the final grab mode if off, only then do we actually grab */ +#ifdef DEBUG_GRAB + printf("SDL_WM_GrabInputRaw(%d) ... ", mode); +#endif + if ( mode == SDL_GRAB_OFF ) { + if ( video->input_grab != SDL_GRAB_OFF ) { + mode = video->GrabInput(this, mode); + } + } else { + if ( video->input_grab == SDL_GRAB_OFF ) { + mode = video->GrabInput(this, mode); + } + } + if ( mode != video->input_grab ) { + video->input_grab = mode; + if ( video->CheckMouseMode ) { + video->CheckMouseMode(this); + } + } +#ifdef DEBUG_GRAB + printf("Final mode %d\n", video->input_grab); +#endif + + /* Return the final grab state */ + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + return(mode); +} +SDL_GrabMode SDL_WM_GrabInput(SDL_GrabMode mode) +{ + SDL_VideoDevice *video = current_video; + + /* If the video isn't initialized yet, we can't do anything */ + if ( ! video ) { + return SDL_GRAB_OFF; + } + + /* Return the current mode on query */ + if ( mode == SDL_GRAB_QUERY ) { + mode = video->input_grab; + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + return(mode); + } + +#ifdef DEBUG_GRAB + printf("SDL_WM_GrabInput(%d) ... ", mode); +#endif + /* If the video surface is fullscreen, we always grab */ + if ( mode >= SDL_GRAB_FULLSCREEN ) { + mode -= SDL_GRAB_FULLSCREEN; + } + if ( SDL_VideoSurface && (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) { + mode += SDL_GRAB_FULLSCREEN; + } + return(SDL_WM_GrabInputRaw(mode)); +} +static SDL_GrabMode SDL_WM_GrabInputOff(void) +{ + SDL_GrabMode mode; + + /* First query the current grab state */ + mode = SDL_WM_GrabInput(SDL_GRAB_QUERY); + + /* Now explicitly turn off input grab */ + SDL_WM_GrabInputRaw(SDL_GRAB_OFF); + + /* Return the old state */ + return(mode); +} + +/* + * Iconify the window in window managed environments. + * A successful iconification will result in an SDL_APPACTIVE loss event. + */ +int SDL_WM_IconifyWindow(void) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int retval; + + retval = 0; + if ( video->IconifyWindow ) { + retval = video->IconifyWindow(this); + } + return(retval); +} + +/* + * Toggle fullscreen mode + */ +int SDL_WM_ToggleFullScreen(SDL_Surface *surface) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + int toggled; + + toggled = 0; + if ( SDL_PublicSurface && (surface == SDL_PublicSurface) && + video->ToggleFullScreen ) { + if ( surface->flags & SDL_FULLSCREEN ) { + toggled = video->ToggleFullScreen(this, 0); + if ( toggled ) { + SDL_VideoSurface->flags &= ~SDL_FULLSCREEN; + SDL_PublicSurface->flags &= ~SDL_FULLSCREEN; + } + } else { + toggled = video->ToggleFullScreen(this, 1); + if ( toggled ) { + SDL_VideoSurface->flags |= SDL_FULLSCREEN; + SDL_PublicSurface->flags |= SDL_FULLSCREEN; + } + } + /* Double-check the grab state inside SDL_WM_GrabInput() */ + if ( toggled ) { + SDL_WM_GrabInput(video->input_grab); + } + } + return(toggled); +} + +/* + * Get some platform dependent window manager information + */ +int SDL_GetWMInfo (SDL_SysWMinfo *info) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + + if ( video && video->GetWMInfo ) { + return(video->GetWMInfo(this, info)); + } else { + return(0); + } +} diff --git a/3rdparty/SDL/src/video/SDL_yuv.c b/3rdparty/SDL/src/video/SDL_yuv.c new file mode 100644 index 0000000..eea3347 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv.c @@ -0,0 +1,150 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the implementation of the YUV video surface support */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" +#include "SDL_yuvfuncs.h" +#include "SDL_yuv_sw_c.h" + + +SDL_Overlay *SDL_CreateYUVOverlay(int w, int h, Uint32 format, + SDL_Surface *display) +{ + SDL_VideoDevice *video = current_video; + SDL_VideoDevice *this = current_video; + const char *yuv_hwaccel; + SDL_Overlay *overlay; + + if ( (display->flags & SDL_OPENGL) == SDL_OPENGL ) { + SDL_SetError("YUV overlays are not supported in OpenGL mode"); + return NULL; + } + + /* Display directly on video surface, if possible */ + if ( SDL_getenv("SDL_VIDEO_YUV_DIRECT") ) { + if ( (display == SDL_PublicSurface) && + ((SDL_VideoSurface->format->BytesPerPixel == 2) || + (SDL_VideoSurface->format->BytesPerPixel == 4)) ) { + display = SDL_VideoSurface; + } + } + overlay = NULL; + yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL"); + if ( ((display == SDL_VideoSurface) && video->CreateYUVOverlay) && + (!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0)) ) { + overlay = video->CreateYUVOverlay(this, w, h, format, display); + } + /* If hardware YUV overlay failed ... */ + if ( overlay == NULL ) { + overlay = SDL_CreateYUV_SW(this, w, h, format, display); + } + return overlay; +} + +int SDL_LockYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + SDL_SetError("Passed NULL overlay"); + return -1; + } + return overlay->hwfuncs->Lock(current_video, overlay); +} + +void SDL_UnlockYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + return; + } + overlay->hwfuncs->Unlock(current_video, overlay); +} + +int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect) +{ + SDL_Rect src, dst; + int srcx, srcy, srcw, srch; + int dstx, dsty, dstw, dsth; + + if ( overlay == NULL || dstrect == NULL ) { + SDL_SetError("Passed NULL overlay or dstrect"); + return -1; + } + + /* Clip the rectangle to the screen area */ + srcx = 0; + srcy = 0; + srcw = overlay->w; + srch = overlay->h; + dstx = dstrect->x; + dsty = dstrect->y; + dstw = dstrect->w; + dsth = dstrect->h; + if ( dstx < 0 ) { + srcw += (dstx * overlay->w) / dstrect->w; + dstw += dstx; + srcx -= (dstx * overlay->w) / dstrect->w; + dstx = 0; + } + if ( (dstx+dstw) > current_video->screen->w ) { + int extra = (dstx+dstw - current_video->screen->w); + srcw -= (extra * overlay->w) / dstrect->w; + dstw -= extra; + } + if ( dsty < 0 ) { + srch += (dsty * overlay->h) / dstrect->h; + dsth += dsty; + srcy -= (dsty * overlay->h) / dstrect->h; + dsty = 0; + } + if ( (dsty+dsth) > current_video->screen->h ) { + int extra = (dsty+dsth - current_video->screen->h); + srch -= (extra * overlay->h) / dstrect->h; + dsth -= extra; + } + if ( srcw <= 0 || srch <= 0 || + srch <= 0 || dsth <= 0 ) { + return 0; + } + /* Ugh, I can't wait for SDL_Rect to be int values */ + src.x = srcx; + src.y = srcy; + src.w = srcw; + src.h = srch; + dst.x = dstx; + dst.y = dsty; + dst.w = dstw; + dst.h = dsth; + return overlay->hwfuncs->Display(current_video, overlay, &src, &dst); +} + +void SDL_FreeYUVOverlay(SDL_Overlay *overlay) +{ + if ( overlay == NULL ) { + return; + } + if ( overlay->hwfuncs ) { + overlay->hwfuncs->FreeHW(current_video, overlay); + } + SDL_free(overlay); +} diff --git a/3rdparty/SDL/src/video/SDL_yuv_mmx.c b/3rdparty/SDL/src/video/SDL_yuv_mmx.c new file mode 100644 index 0000000..f11c432 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_mmx.c @@ -0,0 +1,428 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + +#include "SDL_stdinc.h" + +#include "mmx.h" + +/* *INDENT-OFF* */ + +static mmx_t MMX_0080w = { .ud = {0x00800080, 0x00800080} }; +static mmx_t MMX_00FFw = { .ud = {0x00ff00ff, 0x00ff00ff} }; +static mmx_t MMX_FF00w = { .ud = {0xff00ff00, 0xff00ff00} }; + +static mmx_t MMX_Ycoeff = { .uw = {0x004a, 0x004a, 0x004a, 0x004a} }; + +static mmx_t MMX_UbluRGB = { .uw = {0x0072, 0x0072, 0x0072, 0x0072} }; +static mmx_t MMX_VredRGB = { .uw = {0x0059, 0x0059, 0x0059, 0x0059} }; +static mmx_t MMX_UgrnRGB = { .uw = {0xffea, 0xffea, 0xffea, 0xffea} }; +static mmx_t MMX_VgrnRGB = { .uw = {0xffd2, 0xffd2, 0xffd2, 0xffd2} }; + +static mmx_t MMX_Ublu5x5 = { .uw = {0x0081, 0x0081, 0x0081, 0x0081} }; +static mmx_t MMX_Vred5x5 = { .uw = {0x0066, 0x0066, 0x0066, 0x0066} }; +static mmx_t MMX_Ugrn565 = { .uw = {0xffe8, 0xffe8, 0xffe8, 0xffe8} }; +static mmx_t MMX_Vgrn565 = { .uw = {0xffcd, 0xffcd, 0xffcd, 0xffcd} }; + +static mmx_t MMX_red565 = { .uw = {0xf800, 0xf800, 0xf800, 0xf800} }; +static mmx_t MMX_grn565 = { .uw = {0x07e0, 0x07e0, 0x07e0, 0x07e0} }; + +/** + This MMX assembler is my first assembler/MMX program ever. + Thus it maybe buggy. + Send patches to: + mvogt@rhrk.uni-kl.de + + After it worked fine I have "obfuscated" the code a bit to have + more parallism in the MMX units. This means I moved + initilisation around and delayed other instruction. + Performance measurement did not show that this brought any advantage + but in theory it _should_ be faster this way. + + The overall performanve gain to the C based dither was 30%-40%. + The MMX routine calculates 256bit=8RGB values in each cycle + (4 for row1 & 4 for row2) + + The red/green/blue.. coefficents are taken from the mpeg_play + player. They look nice, but I dont know if you can have + better values, to avoid integer rounding errors. + + + IMPORTANT: + ========== + + It is a requirement that the cr/cb/lum are 8 byte aligned and + the out are 16byte aligned or you will/may get segfaults + +*/ + +void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + Uint32 *row1; + Uint32 *row2; + + unsigned char* y = lum +cols*rows; // Pointer to the end + int x = 0; + row1 = (Uint32 *)out; // 32 bit target + row2 = (Uint32 *)out+cols+mod; // start of second row + mod = (mod+cols+mod)*4; // increment for row1 in byte + + __asm__ __volatile__ ( + // tap dance to workaround the inability to use %%ebx at will... + // move one thing to the stack... + "pushl $0\n" // save a slot on the stack. + "pushl %%ebx\n" // save %%ebx. + "movl %0, %%ebx\n" // put the thing in ebx. + "movl %%ebx,4(%%esp)\n" // put the thing in the stack slot. + "popl %%ebx\n" // get back %%ebx (the PIC register). + + ".align 8\n" + "1:\n" + + // create Cr (result in mm1) + "pushl %%ebx\n" + "movl 4(%%esp),%%ebx\n" + "movd (%%ebx),%%mm1\n" // 0 0 0 0 v3 v2 v1 v0 + "popl %%ebx\n" + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "movd (%2), %%mm2\n" // 0 0 0 0 l3 l2 l1 l0 + "punpcklbw %%mm7,%%mm1\n" // 0 v3 0 v2 00 v1 00 v0 + "punpckldq %%mm1,%%mm1\n" // 00 v1 00 v0 00 v1 00 v0 + "psubw %9,%%mm1\n" // mm1-128:r1 r1 r0 r0 r1 r1 r0 r0 + + // create Cr_g (result in mm0) + "movq %%mm1,%%mm0\n" // r1 r1 r0 r0 r1 r1 r0 r0 + "pmullw %10,%%mm0\n" // red*-46dec=0.7136*64 + "pmullw %11,%%mm1\n" // red*89dec=1.4013*64 + "psraw $6, %%mm0\n" // red=red/64 + "psraw $6, %%mm1\n" // red=red/64 + + // create L1 L2 (result in mm2,mm4) + // L2=lum+cols + "movq (%2,%4),%%mm3\n" // 0 0 0 0 L3 L2 L1 L0 + "punpckldq %%mm3,%%mm2\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "movq %%mm2,%%mm4\n" // L3 L2 L1 L0 l3 l2 l1 l0 + "pand %12,%%mm2\n" // L3 0 L1 0 l3 0 l1 0 + "pand %13,%%mm4\n" // 0 L2 0 L0 0 l2 0 l0 + "psrlw $8,%%mm2\n" // 0 L3 0 L1 0 l3 0 l1 + + // create R (result in mm6) + "movq %%mm2,%%mm5\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm6\n" // 0 L2 0 L0 0 l2 0 l0 + "paddsw %%mm1, %%mm5\n" // lum1+red:x R3 x R1 x r3 x r1 + "paddsw %%mm1, %%mm6\n" // lum1+red:x R2 x R0 x r2 x r0 + "packuswb %%mm5,%%mm5\n" // R3 R1 r3 r1 R3 R1 r3 r1 + "packuswb %%mm6,%%mm6\n" // R2 R0 r2 r0 R2 R0 r2 r0 + "pxor %%mm7,%%mm7\n" // 00 00 00 00 00 00 00 00 + "punpcklbw %%mm5,%%mm6\n" // R3 R2 R1 R0 r3 r2 r1 r0 + + // create Cb (result in mm1) + "movd (%1), %%mm1\n" // 0 0 0 0 u3 u2 u1 u0 + "punpcklbw %%mm7,%%mm1\n" // 0 u3 0 u2 00 u1 00 u0 + "punpckldq %%mm1,%%mm1\n" // 00 u1 00 u0 00 u1 00 u0 + "psubw %9,%%mm1\n" // mm1-128:u1 u1 u0 u0 u1 u1 u0 u0 + // create Cb_g (result in mm5) + "movq %%mm1,%%mm5\n" // u1 u1 u0 u0 u1 u1 u0 u0 + "pmullw %14,%%mm5\n" // blue*-109dec=1.7129*64 + "pmullw %15,%%mm1\n" // blue*114dec=1.78125*64 + "psraw $6, %%mm5\n" // blue=red/64 + "psraw $6, %%mm1\n" // blue=blue/64 + + // create G (result in mm7) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm7\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm5, %%mm3\n" // lum1+Cb_g:x G3t x G1t x g3t x g1t + "paddsw %%mm5, %%mm7\n" // lum1+Cb_g:x G2t x G0t x g2t x g0t + "paddsw %%mm0, %%mm3\n" // lum1+Cr_g:x G3 x G1 x g3 x g1 + "paddsw %%mm0, %%mm7\n" // lum1+blue:x G2 x G0 x g2 x g0 + "packuswb %%mm3,%%mm3\n" // G3 G1 g3 g1 G3 G1 g3 g1 + "packuswb %%mm7,%%mm7\n" // G2 G0 g2 g0 G2 G0 g2 g0 + "punpcklbw %%mm3,%%mm7\n" // G3 G2 G1 G0 g3 g2 g1 g0 + + // create B (result in mm5) + "movq %%mm2,%%mm3\n" // 0 L3 0 L1 0 l3 0 l1 + "movq %%mm4,%%mm5\n" // 0 L2 0 L0 0 l2 0 l1 + "paddsw %%mm1, %%mm3\n" // lum1+blue:x B3 x B1 x b3 x b1 + "paddsw %%mm1, %%mm5\n" // lum1+blue:x B2 x B0 x b2 x b0 + "packuswb %%mm3,%%mm3\n" // B3 B1 b3 b1 B3 B1 b3 b1 + "packuswb %%mm5,%%mm5\n" // B2 B0 b2 b0 B2 B0 b2 b0 + "punpcklbw %%mm3,%%mm5\n" // B3 B2 B1 B0 b3 b2 b1 b0 + + // fill destination row1 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "pxor %%mm4,%%mm4\n" // 0 0 0 0 0 0 0 0 + "movq %%mm6,%%mm1\n" // R3 R2 R1 R0 r3 r2 r1 r0 + "movq %%mm5,%%mm3\n" // B3 B2 B1 B0 b3 b2 b1 b0 + // process lower lum + "punpcklbw %%mm4,%%mm1\n" // 0 r3 0 r2 0 r1 0 r0 + "punpcklbw %%mm4,%%mm3\n" // 0 b3 0 b2 0 b1 0 b0 + "movq %%mm1,%%mm2\n" // 0 r3 0 r2 0 r1 0 r0 + "movq %%mm3,%%mm0\n" // 0 b3 0 b2 0 b1 0 b0 + "punpcklwd %%mm1,%%mm3\n" // 0 r1 0 b1 0 r0 0 b0 + "punpckhwd %%mm2,%%mm0\n" // 0 r3 0 b3 0 r2 0 b2 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "movq %%mm7,%%mm1\n" // G3 G2 G1 G0 g3 g2 g1 g0 + "punpcklbw %%mm1,%%mm2\n" // g3 0 g2 0 g1 0 g0 0 + "punpcklwd %%mm4,%%mm2\n" // 0 0 g1 0 0 0 g0 0 + "por %%mm3, %%mm2\n" // 0 r1 g1 b1 0 r0 g0 b0 + "movq %%mm2,(%3)\n" // wrote out ! row1 + + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpcklbw %%mm1,%%mm4\n" // g3 0 g2 0 g1 0 g0 0 + "punpckhwd %%mm2,%%mm4\n" // 0 0 g3 0 0 0 g2 0 + "por %%mm0, %%mm4\n" // 0 r3 g3 b3 0 r2 g2 b2 + "movq %%mm4,8(%3)\n" // wrote out ! row1 + + // fill destination row2 (needed are mm6=Rr,mm7=Gg,mm5=Bb) + // this can be done "destructive" + "pxor %%mm2,%%mm2\n" // 0 0 0 0 0 0 0 0 + "punpckhbw %%mm2,%%mm6\n" // 0 R3 0 R2 0 R1 0 R0 + "punpckhbw %%mm1,%%mm5\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "movq %%mm5,%%mm1\n" // G3 B3 G2 B2 G1 B1 G0 B0 + "punpcklwd %%mm6,%%mm1\n" // 0 R1 G1 B1 0 R0 G0 B0 + "movq %%mm1,(%5)\n" // wrote out ! row2 + "punpckhwd %%mm6,%%mm5\n" // 0 R3 G3 B3 0 R2 G2 B2 + "movq %%mm5,8(%5)\n" // wrote out ! row2 + + "addl $4,%2\n" // lum+4 + "leal 16(%3),%3\n" // row1+16 + "leal 16(%5),%5\n" // row2+16 + "addl $2,(%%esp)\n" // cr+2 + "addl $2,%1\n" // cb+2 + + "addl $4,%6\n" // x+4 + "cmpl %4,%6\n" + + "jl 1b\n" + "addl %4,%2\n" // lum += cols + "addl %8,%3\n" // row1+= mod + "addl %8,%5\n" // row2+= mod + "movl $0,%6\n" // x=0 + "cmpl %7,%2\n" + "jl 1b\n" + + "addl $4,%%esp\n" // get rid of the stack slot we reserved. + "emms\n" // reset MMX registers. + : + : "m" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod), + "m"(MMX_0080w),"m"(MMX_VgrnRGB),"m"(MMX_VredRGB), + "m"(MMX_FF00w),"m"(MMX_00FFw),"m"(MMX_UgrnRGB), + "m"(MMX_UbluRGB) + ); +} + +void Color565DitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + Uint16 *row1; + Uint16 *row2; + + unsigned char* y = lum +cols*rows; /* Pointer to the end */ + int x = 0; + row1 = (Uint16 *)out; /* 16 bit target */ + row2 = (Uint16 *)out+cols+mod; /* start of second row */ + mod = (mod+cols+mod)*2; /* increment for row1 in byte */ + + __asm__ __volatile__( + // tap dance to workaround the inability to use %%ebx at will... + // move one thing to the stack... + "pushl $0\n" // save a slot on the stack. + "pushl %%ebx\n" // save %%ebx. + "movl %0, %%ebx\n" // put the thing in ebx. + "movl %%ebx, 4(%%esp)\n" // put the thing in the stack slot. + "popl %%ebx\n" // get back %%ebx (the PIC register). + + ".align 8\n" + "1:\n" + "movd (%1), %%mm0\n" // 4 Cb 0 0 0 0 u3 u2 u1 u0 + "pxor %%mm7, %%mm7\n" + "pushl %%ebx\n" + "movl 4(%%esp), %%ebx\n" + "movd (%%ebx), %%mm1\n" // 4 Cr 0 0 0 0 v3 v2 v1 v0 + "popl %%ebx\n" + + "punpcklbw %%mm7, %%mm0\n" // 4 W cb 0 u3 0 u2 0 u1 0 u0 + "punpcklbw %%mm7, %%mm1\n" // 4 W cr 0 v3 0 v2 0 v1 0 v0 + "psubw %9, %%mm0\n" + "psubw %9, %%mm1\n" + "movq %%mm0, %%mm2\n" // Cb 0 u3 0 u2 0 u1 0 u0 + "movq %%mm1, %%mm3\n" // Cr + "pmullw %10, %%mm2\n" // Cb2green 0 R3 0 R2 0 R1 0 R0 + "movq (%2), %%mm6\n" // L1 l7 L6 L5 L4 L3 L2 L1 L0 + "pmullw %11, %%mm0\n" // Cb2blue + "pand %12, %%mm6\n" // L1 00 L6 00 L4 00 L2 00 L0 + "pmullw %13, %%mm3\n" // Cr2green + "movq (%2), %%mm7\n" // L2 + "pmullw %14, %%mm1\n" // Cr2red + "psrlw $8, %%mm7\n" // L2 00 L7 00 L5 00 L3 00 L1 + "pmullw %15, %%mm6\n" // lum1 + "paddw %%mm3, %%mm2\n" // Cb2green + Cr2green == green + "pmullw %15, %%mm7\n" // lum2 + + "movq %%mm6, %%mm4\n" // lum1 + "paddw %%mm0, %%mm6\n" // lum1 +blue 00 B6 00 B4 00 B2 00 B0 + "movq %%mm4, %%mm5\n" // lum1 + "paddw %%mm1, %%mm4\n" // lum1 +red 00 R6 00 R4 00 R2 00 R0 + "paddw %%mm2, %%mm5\n" // lum1 +green 00 G6 00 G4 00 G2 00 G0 + "psraw $6, %%mm4\n" // R1 0 .. 64 + "movq %%mm7, %%mm3\n" // lum2 00 L7 00 L5 00 L3 00 L1 + "psraw $6, %%mm5\n" // G1 - .. + + "paddw %%mm0, %%mm7\n" // Lum2 +blue 00 B7 00 B5 00 B3 00 B1 + "psraw $6, %%mm6\n" // B1 0 .. 64 + "packuswb %%mm4, %%mm4\n" // R1 R1 + "packuswb %%mm5, %%mm5\n" // G1 G1 + "packuswb %%mm6, %%mm6\n" // B1 B1 + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + + "pand %16, %%mm4\n" + "psllw $3, %%mm5\n" // GREEN 1 + "punpcklbw %%mm6, %%mm6\n" + "pand %17, %%mm5\n" + "pand %16, %%mm6\n" + "por %%mm5, %%mm4\n" // + "psrlw $11, %%mm6\n" // BLUE 1 + "movq %%mm3, %%mm5\n" // lum2 + "paddw %%mm1, %%mm3\n" // lum2 +red 00 R7 00 R5 00 R3 00 R1 + "paddw %%mm2, %%mm5\n" // lum2 +green 00 G7 00 G5 00 G3 00 G1 + "psraw $6, %%mm3\n" // R2 + "por %%mm6, %%mm4\n" // MM4 + "psraw $6, %%mm5\n" // G2 + "movq (%2, %4), %%mm6\n" // L3 load lum2 + "psraw $6, %%mm7\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm5, %%mm5\n" + "packuswb %%mm7, %%mm7\n" + "pand %12, %%mm6\n" // L3 + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm5, %%mm5\n" + "pmullw %15, %%mm6\n" // lum3 + "punpcklbw %%mm7, %%mm7\n" + "psllw $3, %%mm5\n" // GREEN 2 + "pand %16, %%mm7\n" + "pand %16, %%mm3\n" + "psrlw $11, %%mm7\n" // BLUE 2 + "pand %17, %%mm5\n" + "por %%mm7, %%mm3\n" + "movq (%2,%4), %%mm7\n" // L4 load lum2 + "por %%mm5, %%mm3\n" // + "psrlw $8, %%mm7\n" // L4 + "movq %%mm4, %%mm5\n" + "punpcklwd %%mm3, %%mm4\n" + "pmullw %15, %%mm7\n" // lum4 + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%3)\n" // write row1 + "movq %%mm5, 8(%3)\n" // write row1 + + "movq %%mm6, %%mm4\n" // Lum3 + "paddw %%mm0, %%mm6\n" // Lum3 +blue + + "movq %%mm4, %%mm5\n" // Lum3 + "paddw %%mm1, %%mm4\n" // Lum3 +red + "paddw %%mm2, %%mm5\n" // Lum3 +green + "psraw $6, %%mm4\n" + "movq %%mm7, %%mm3\n" // Lum4 + "psraw $6, %%mm5\n" + "paddw %%mm0, %%mm7\n" // Lum4 +blue + "psraw $6, %%mm6\n" // Lum3 +blue + "movq %%mm3, %%mm0\n" // Lum4 + "packuswb %%mm4, %%mm4\n" + "paddw %%mm1, %%mm3\n" // Lum4 +red + "packuswb %%mm5, %%mm5\n" + "paddw %%mm2, %%mm0\n" // Lum4 +green + "packuswb %%mm6, %%mm6\n" + "punpcklbw %%mm4, %%mm4\n" + "punpcklbw %%mm5, %%mm5\n" + "punpcklbw %%mm6, %%mm6\n" + "psllw $3, %%mm5\n" // GREEN 3 + "pand %16, %%mm4\n" + "psraw $6, %%mm3\n" // psr 6 + "psraw $6, %%mm0\n" + "pand %16, %%mm6\n" // BLUE + "pand %17, %%mm5\n" + "psrlw $11, %%mm6\n" // BLUE 3 + "por %%mm5, %%mm4\n" + "psraw $6, %%mm7\n" + "por %%mm6, %%mm4\n" + "packuswb %%mm3, %%mm3\n" + "packuswb %%mm0, %%mm0\n" + "packuswb %%mm7, %%mm7\n" + "punpcklbw %%mm3, %%mm3\n" + "punpcklbw %%mm0, %%mm0\n" + "punpcklbw %%mm7, %%mm7\n" + "pand %16, %%mm3\n" + "pand %16, %%mm7\n" // BLUE + "psllw $3, %%mm0\n" // GREEN 4 + "psrlw $11, %%mm7\n" + "pand %17, %%mm0\n" + "por %%mm7, %%mm3\n" + "por %%mm0, %%mm3\n" + + "movq %%mm4, %%mm5\n" + + "punpcklwd %%mm3, %%mm4\n" + "punpckhwd %%mm3, %%mm5\n" + + "movq %%mm4, (%5)\n" + "movq %%mm5, 8(%5)\n" + + "addl $8, %6\n" + "addl $8, %2\n" + "addl $4, (%%esp)\n" + "addl $4, %1\n" + "cmpl %4, %6\n" + "leal 16(%3), %3\n" + "leal 16(%5),%5\n" // row2+16 + + "jl 1b\n" + "addl %4, %2\n" // lum += cols + "addl %8, %3\n" // row1+= mod + "addl %8, %5\n" // row2+= mod + "movl $0, %6\n" // x=0 + "cmpl %7, %2\n" + "jl 1b\n" + "addl $4, %%esp\n" // get rid of the stack slot we reserved. + "emms\n" + : + : "m" (cr), "r"(cb),"r"(lum), + "r"(row1),"r"(cols),"r"(row2),"m"(x),"m"(y),"m"(mod), + "m"(MMX_0080w),"m"(MMX_Ugrn565),"m"(MMX_Ublu5x5), + "m"(MMX_00FFw),"m"(MMX_Vgrn565),"m"(MMX_Vred5x5), + "m"(MMX_Ycoeff),"m"(MMX_red565),"m"(MMX_grn565) + ); +} + +/* *INDENT-ON* */ + +#endif /* GCC3 i386 inline assembly */ + diff --git a/3rdparty/SDL/src/video/SDL_yuv_sw.c b/3rdparty/SDL/src/video/SDL_yuv_sw.c new file mode 100644 index 0000000..c555ce0 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_sw.c @@ -0,0 +1,1299 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the software implementation of the YUV video overlay support */ + +/* This code was derived from code carrying the following copyright notices: + + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + * Copyright (c) 1995 Erik Corry + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" + * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, + * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + + * Portions of this software Copyright (c) 1995 Brown University. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement + * is hereby granted, provided that the above copyright notice and the + * following two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN + * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" + * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, + * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "SDL_video.h" +#include "SDL_cpuinfo.h" +#include "SDL_stretch_c.h" +#include "SDL_yuvfuncs.h" +#include "SDL_yuv_sw_c.h" + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs sw_yuvfuncs = { + SDL_LockYUV_SW, + SDL_UnlockYUV_SW, + SDL_DisplayYUV_SW, + SDL_FreeYUV_SW +}; + +/* RGB conversion lookup tables */ +struct private_yuvhwdata { + SDL_Surface *stretch; + SDL_Surface *display; + Uint8 *pixels; + int *colortab; + Uint32 *rgb_2_pix; + void (*Display1X)(int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); + void (*Display2X)(int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + + +/* The colorspace conversion functions */ + +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES +extern void Color565DitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); +extern void ColorRGBDitherYV12MMX1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ); +#endif + +static void Color16DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned short* row1; + unsigned short* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = (unsigned short*) out; + row2 = row1 + cols + mod; + lum2 = lum + cols; + + mod += cols + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum++; + *row1++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + /* Now, do second row. */ + + L = *lum2++; + *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum2++; + *row2++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color24DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row1; + unsigned char* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = out; + row2 = row1 + cols*3 + mod*3; + lum2 = lum + cols; + + mod += cols + mod; + mod *= 3; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row1++ = (value ) & 0xFF; + *row1++ = (value >> 8) & 0xFF; + *row1++ = (value >> 16) & 0xFF; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row1++ = (value ) & 0xFF; + *row1++ = (value >> 8) & 0xFF; + *row1++ = (value >> 16) & 0xFF; + + + /* Now, do second row. */ + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row2++ = (value ) & 0xFF; + *row2++ = (value >> 8) & 0xFF; + *row2++ = (value >> 16) & 0xFF; + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row2++ = (value ) & 0xFF; + *row2++ = (value >> 8) & 0xFF; + *row2++ = (value >> 16) & 0xFF; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color32DitherYV12Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1; + unsigned int* row2; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row1 = (unsigned int*) out; + row2 = row1 + cols + mod; + lum2 = lum + cols; + + mod += cols + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + *row1++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum++; + *row1++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + /* Now, do second row. */ + + L = *lum2++; + *row2++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum2++; + *row2++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +/* + * In this function I make use of a nasty trick. The tables have the lower + * 16 bits replicated in the upper 16. This means I can write ints and get + * the horisontal doubling for free (almost). + */ +static void Color16DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1 = (unsigned int*) out; + const int next_row = cols+(mod/2); + unsigned int* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = (next_row * 3) + (mod/2); + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1++; + + L = *lum++; + row1[0] = row1[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1++; + + + /* Now, do second row. */ + + L = *lum2++; + row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2++; + + L = *lum2++; + row2[0] = row2[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2++; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color24DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row1 = out; + const int next_row = (cols*2 + mod) * 3; + unsigned char* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = next_row*3 + mod*3; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = + (value ) & 0xFF; + row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = + (value >> 8) & 0xFF; + row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = + (value >> 16) & 0xFF; + row1 += 2*3; + + L = *lum++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1[0+0] = row1[3+0] = row1[next_row+0] = row1[next_row+3+0] = + (value ) & 0xFF; + row1[0+1] = row1[3+1] = row1[next_row+1] = row1[next_row+3+1] = + (value >> 8) & 0xFF; + row1[0+2] = row1[3+2] = row1[next_row+2] = row1[next_row+3+2] = + (value >> 16) & 0xFF; + row1 += 2*3; + + + /* Now, do second row. */ + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = + (value ) & 0xFF; + row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = + (value >> 8) & 0xFF; + row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = + (value >> 16) & 0xFF; + row2 += 2*3; + + L = *lum2++; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2[0+0] = row2[3+0] = row2[next_row+0] = row2[next_row+3+0] = + (value ) & 0xFF; + row2[0+1] = row2[3+1] = row2[next_row+1] = row2[next_row+3+1] = + (value >> 8) & 0xFF; + row2[0+2] = row2[3+2] = row2[next_row+2] = row2[next_row+3+2] = + (value >> 16) & 0xFF; + row2 += 2*3; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color32DitherYV12Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row1 = (unsigned int*) out; + const int next_row = cols*2+mod; + unsigned int* row2 = row1 + 2*next_row; + unsigned char* lum2; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + lum2 = lum + cols; + + mod = (next_row * 3) + mod; + + y = rows / 2; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + ++cr; ++cb; + + L = *lum++; + row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1 += 2; + + L = *lum++; + row1[0] = row1[1] = row1[next_row] = row1[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row1 += 2; + + + /* Now, do second row. */ + + L = *lum2++; + row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2 += 2; + + L = *lum2++; + row2[0] = row2[1] = row2[next_row] = row2[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row2 += 2; + } + + /* + * These values are at the start of the next line, (due + * to the ++'s above),but they need to be at the start + * of the line after that. + */ + lum += cols; + lum2 += cols; + row1 += mod; + row2 += mod; + } +} + +static void Color16DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned short* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned short*) out; + + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum; lum += 2; + *row++ = (unsigned short)(rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + } + + row += mod; + } +} + +static void Color24DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned char*) out; + mod *= 3; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row++ = (value ) & 0xFF; + *row++ = (value >> 8) & 0xFF; + *row++ = (value >> 16) & 0xFF; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + *row++ = (value ) & 0xFF; + *row++ = (value >> 8) & 0xFF; + *row++ = (value >> 16) & 0xFF; + + } + row += mod; + } +} + +static void Color32DitherYUY2Mod1X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + row = (unsigned int*) out; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + *row++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + L = *lum; lum += 2; + *row++ = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + + + } + row += mod; + } +} + +/* + * In this function I make use of a nasty trick. The tables have the lower + * 16 bits replicated in the upper 16. This means I can write ints and get + * the horisontal doubling for free (almost). + */ +static void Color16DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row = (unsigned int*) out; + const int next_row = cols+(mod/2); + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row++; + + L = *lum; lum += 2; + row[0] = row[next_row] = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row++; + + } + row += next_row; + } +} + +static void Color24DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int value; + unsigned char* row = out; + const int next_row = (cols*2 + mod) * 3; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = + (value ) & 0xFF; + row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = + (value >> 8) & 0xFF; + row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = + (value >> 16) & 0xFF; + row += 2*3; + + L = *lum; lum += 2; + value = (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row[0+0] = row[3+0] = row[next_row+0] = row[next_row+3+0] = + (value ) & 0xFF; + row[0+1] = row[3+1] = row[next_row+1] = row[next_row+3+1] = + (value >> 8) & 0xFF; + row[0+2] = row[3+2] = row[next_row+2] = row[next_row+3+2] = + (value >> 16) & 0xFF; + row += 2*3; + + } + row += next_row; + } +} + +static void Color32DitherYUY2Mod2X( int *colortab, Uint32 *rgb_2_pix, + unsigned char *lum, unsigned char *cr, + unsigned char *cb, unsigned char *out, + int rows, int cols, int mod ) +{ + unsigned int* row = (unsigned int*) out; + const int next_row = cols*2+mod; + int x, y; + int cr_r; + int crb_g; + int cb_b; + int cols_2 = cols / 2; + mod+=mod; + y = rows; + while( y-- ) + { + x = cols_2; + while( x-- ) + { + register int L; + + cr_r = 0*768+256 + colortab[ *cr + 0*256 ]; + crb_g = 1*768+256 + colortab[ *cr + 1*256 ] + + colortab[ *cb + 2*256 ]; + cb_b = 2*768+256 + colortab[ *cb + 3*256 ]; + cr += 4; cb += 4; + + L = *lum; lum += 2; + row[0] = row[1] = row[next_row] = row[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row += 2; + + L = *lum; lum += 2; + row[0] = row[1] = row[next_row] = row[next_row+1] = + (rgb_2_pix[ L + cr_r ] | + rgb_2_pix[ L + crb_g ] | + rgb_2_pix[ L + cb_b ]); + row += 2; + + + } + + row += next_row; + } +} + +/* + * How many 1 bits are there in the Uint32. + * Low performance, do not call often. + */ +static int number_of_bits_set( Uint32 a ) +{ + if(!a) return 0; + if(a & 1) return 1 + number_of_bits_set(a >> 1); + return(number_of_bits_set(a >> 1)); +} + +/* + * How many 0 bits are there at least significant end of Uint32. + * Low performance, do not call often. + */ +static int free_bits_at_bottom( Uint32 a ) +{ + /* assume char is 8 bits */ + if(!a) return sizeof(Uint32) * 8; + if(((Sint32)a) & 1l) return 0; + return 1 + free_bits_at_bottom ( a >> 1); +} + + +SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *swdata; + int *Cr_r_tab; + int *Cr_g_tab; + int *Cb_g_tab; + int *Cb_b_tab; + Uint32 *r_2_pix_alloc; + Uint32 *g_2_pix_alloc; + Uint32 *b_2_pix_alloc; + int i; + int CR, CB; + Uint32 Rmask, Gmask, Bmask; + + /* Only RGB packed pixel conversion supported */ + if ( (display->format->BytesPerPixel != 2) && + (display->format->BytesPerPixel != 3) && + (display->format->BytesPerPixel != 4) ) { + SDL_SetError("Can't use YUV data on non 16/24/32 bit surfaces"); + return(NULL); + } + + /* Verify that we support the format */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + break; + default: + SDL_SetError("Unsupported YUV format"); + return(NULL); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &sw_yuvfuncs; + + /* Create the pixel data and lookup tables */ + swdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *swdata); + overlay->hwdata = swdata; + if ( swdata == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + swdata->stretch = NULL; + swdata->display = display; + swdata->pixels = (Uint8 *) SDL_malloc(width*height*2); + swdata->colortab = (int *)SDL_malloc(4*256*sizeof(int)); + Cr_r_tab = &swdata->colortab[0*256]; + Cr_g_tab = &swdata->colortab[1*256]; + Cb_g_tab = &swdata->colortab[2*256]; + Cb_b_tab = &swdata->colortab[3*256]; + swdata->rgb_2_pix = (Uint32 *)SDL_malloc(3*768*sizeof(Uint32)); + r_2_pix_alloc = &swdata->rgb_2_pix[0*768]; + g_2_pix_alloc = &swdata->rgb_2_pix[1*768]; + b_2_pix_alloc = &swdata->rgb_2_pix[2*768]; + if ( ! swdata->pixels || ! swdata->colortab || ! swdata->rgb_2_pix ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + /* Generate the tables for the display surface */ + for (i=0; i<256; i++) { + /* Gamma correction (luminescence table) and chroma correction + would be done here. See the Berkeley mpeg_play sources. + */ + CB = CR = (i-128); + Cr_r_tab[i] = (int) ( (0.419/0.299) * CR); + Cr_g_tab[i] = (int) (-(0.299/0.419) * CR); + Cb_g_tab[i] = (int) (-(0.114/0.331) * CB); + Cb_b_tab[i] = (int) ( (0.587/0.331) * CB); + } + + /* + * Set up entries 0-255 in rgb-to-pixel value tables. + */ + Rmask = display->format->Rmask; + Gmask = display->format->Gmask; + Bmask = display->format->Bmask; + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Rmask)); + r_2_pix_alloc[i+256] <<= free_bits_at_bottom(Rmask); + g_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Gmask)); + g_2_pix_alloc[i+256] <<= free_bits_at_bottom(Gmask); + b_2_pix_alloc[i+256] = i >> (8 - number_of_bits_set(Bmask)); + b_2_pix_alloc[i+256] <<= free_bits_at_bottom(Bmask); + } + + /* + * If we have 16-bit output depth, then we double the value + * in the top word. This means that we can write out both + * pixels in the pixel doubling mode with one op. It is + * harmless in the normal case as storing a 32-bit value + * through a short pointer will lose the top bits anyway. + */ + if( display->format->BytesPerPixel == 2 ) { + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i+256] |= (r_2_pix_alloc[i+256]) << 16; + g_2_pix_alloc[i+256] |= (g_2_pix_alloc[i+256]) << 16; + b_2_pix_alloc[i+256] |= (b_2_pix_alloc[i+256]) << 16; + } + } + + /* + * Spread out the values we have to the rest of the array so that + * we do not need to check for overflow. + */ + for ( i=0; i<256; ++i ) { + r_2_pix_alloc[i] = r_2_pix_alloc[256]; + r_2_pix_alloc[i+512] = r_2_pix_alloc[511]; + g_2_pix_alloc[i] = g_2_pix_alloc[256]; + g_2_pix_alloc[i+512] = g_2_pix_alloc[511]; + b_2_pix_alloc[i] = b_2_pix_alloc[256]; + b_2_pix_alloc[i+512] = b_2_pix_alloc[511]; + } + + /* You have chosen wisely... */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + if ( display->format->BytesPerPixel == 2 ) { +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + /* inline assembly functions */ + if ( SDL_HasMMX() && (Rmask == 0xF800) && + (Gmask == 0x07E0) && + (Bmask == 0x001F) && + (width & 15) == 0) { +/*printf("Using MMX 16-bit 565 dither\n");*/ + swdata->Display1X = Color565DitherYV12MMX1X; + } else { +/*printf("Using C 16-bit dither\n");*/ + swdata->Display1X = Color16DitherYV12Mod1X; + } +#else + swdata->Display1X = Color16DitherYV12Mod1X; +#endif + swdata->Display2X = Color16DitherYV12Mod2X; + } + if ( display->format->BytesPerPixel == 3 ) { + swdata->Display1X = Color24DitherYV12Mod1X; + swdata->Display2X = Color24DitherYV12Mod2X; + } + if ( display->format->BytesPerPixel == 4 ) { +#if (__GNUC__ > 2) && defined(__i386__) && __OPTIMIZE__ && SDL_ASSEMBLY_ROUTINES + /* inline assembly functions */ + if ( SDL_HasMMX() && (Rmask == 0x00FF0000) && + (Gmask == 0x0000FF00) && + (Bmask == 0x000000FF) && + (width & 15) == 0) { +/*printf("Using MMX 32-bit dither\n");*/ + swdata->Display1X = ColorRGBDitherYV12MMX1X; + } else { +/*printf("Using C 32-bit dither\n");*/ + swdata->Display1X = Color32DitherYV12Mod1X; + } +#else + swdata->Display1X = Color32DitherYV12Mod1X; +#endif + swdata->Display2X = Color32DitherYV12Mod2X; + } + break; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + if ( display->format->BytesPerPixel == 2 ) { + swdata->Display1X = Color16DitherYUY2Mod1X; + swdata->Display2X = Color16DitherYUY2Mod2X; + } + if ( display->format->BytesPerPixel == 3 ) { + swdata->Display1X = Color24DitherYUY2Mod1X; + swdata->Display2X = Color24DitherYUY2Mod2X; + } + if ( display->format->BytesPerPixel == 4 ) { + swdata->Display1X = Color32DitherYUY2Mod1X; + swdata->Display2X = Color32DitherYUY2Mod2X; + } + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = swdata->pitches; + overlay->pixels = swdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = swdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + overlay->pitches[0] = overlay->w*2; + overlay->pixels[0] = swdata->pixels; + overlay->planes = 1; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* We're all done.. */ + return(overlay); +} + +int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *swdata; + int stretch; + int scale_2x; + SDL_Surface *display; + Uint8 *lum, *Cr, *Cb; + Uint8 *dstp; + int mod; + + swdata = overlay->hwdata; + stretch = 0; + scale_2x = 0; + if ( src->x || src->y || src->w < overlay->w || src->h < overlay->h ) { + /* The source rectangle has been clipped. + Using a scratch surface is easier than adding clipped + source support to all the blitters, plus that would + slow them down in the general unclipped case. + */ + stretch = 1; + } else if ( (src->w != dst->w) || (src->h != dst->h) ) { + if ( (dst->w == 2*src->w) && + (dst->h == 2*src->h) ) { + scale_2x = 1; + } else { + stretch = 1; + } + } + if ( stretch ) { + if ( ! swdata->stretch ) { + display = swdata->display; + swdata->stretch = SDL_CreateRGBSurface( + SDL_SWSURFACE, + overlay->w, overlay->h, + display->format->BitsPerPixel, + display->format->Rmask, + display->format->Gmask, + display->format->Bmask, 0); + if ( ! swdata->stretch ) { + return(-1); + } + } + display = swdata->stretch; + } else { + display = swdata->display; + } + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = overlay->pixels[0]; + Cr = overlay->pixels[1]; + Cb = overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = overlay->pixels[0]; + Cr = overlay->pixels[2]; + Cb = overlay->pixels[1]; + break; + case SDL_YUY2_OVERLAY: + lum = overlay->pixels[0]; + Cr = lum + 3; + Cb = lum + 1; + break; + case SDL_UYVY_OVERLAY: + lum = overlay->pixels[0]+1; + Cr = lum + 1; + Cb = lum - 1; + break; + case SDL_YVYU_OVERLAY: + lum = overlay->pixels[0]; + Cr = lum + 1; + Cb = lum + 3; + break; + default: + SDL_SetError("Unsupported YUV format in blit"); + return(-1); + } + if ( SDL_MUSTLOCK(display) ) { + if ( SDL_LockSurface(display) < 0 ) { + return(-1); + } + } + if ( stretch ) { + dstp = (Uint8 *)swdata->stretch->pixels; + } else { + dstp = (Uint8 *)display->pixels + + dst->x * display->format->BytesPerPixel + + dst->y * display->pitch; + } + mod = (display->pitch / display->format->BytesPerPixel); + + if ( scale_2x ) { + mod -= (overlay->w * 2); + swdata->Display2X(swdata->colortab, swdata->rgb_2_pix, + lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); + } else { + mod -= overlay->w; + swdata->Display1X(swdata->colortab, swdata->rgb_2_pix, + lum, Cr, Cb, dstp, overlay->h, overlay->w, mod); + } + if ( SDL_MUSTLOCK(display) ) { + SDL_UnlockSurface(display); + } + if ( stretch ) { + display = swdata->display; + SDL_SoftStretch(swdata->stretch, src, display, dst); + } + SDL_UpdateRects(display, 1, dst); + + return(0); +} + +void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *swdata; + + swdata = overlay->hwdata; + if ( swdata ) { + if ( swdata->stretch ) { + SDL_FreeSurface(swdata->stretch); + } + if ( swdata->pixels ) { + SDL_free(swdata->pixels); + } + if ( swdata->colortab ) { + SDL_free(swdata->colortab); + } + if ( swdata->rgb_2_pix ) { + SDL_free(swdata->rgb_2_pix); + } + SDL_free(swdata); + overlay->hwdata = NULL; + } +} diff --git a/3rdparty/SDL/src/video/SDL_yuv_sw_c.h b/3rdparty/SDL/src/video/SDL_yuv_sw_c.h new file mode 100644 index 0000000..5aea3a5 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuv_sw_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_sysvideo.h" + +/* This is the software implementation of the YUV video overlay support */ + +extern SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int SDL_LockYUV_SW(_THIS, SDL_Overlay *overlay); + +extern void SDL_UnlockYUV_SW(_THIS, SDL_Overlay *overlay); + +extern int SDL_DisplayYUV_SW(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void SDL_FreeYUV_SW(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/SDL_yuvfuncs.h b/3rdparty/SDL/src/video/SDL_yuvfuncs.h new file mode 100644 index 0000000..cb496b6 --- /dev/null +++ b/3rdparty/SDL/src/video/SDL_yuvfuncs.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the definition of the YUV video surface function structure */ + +#include "SDL_video.h" +#include "SDL_sysvideo.h" + +#ifndef _THIS +#define _THIS SDL_VideoDevice *_this +#endif +struct private_yuvhwfuncs { + int (*Lock)(_THIS, SDL_Overlay *overlay); + void (*Unlock)(_THIS, SDL_Overlay *overlay); + int (*Display)(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + void (*FreeHW)(_THIS, SDL_Overlay *overlay); +}; diff --git a/3rdparty/SDL/src/video/Xext/README b/3rdparty/SDL/src/video/Xext/README new file mode 100644 index 0000000..a16ea68 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/README @@ -0,0 +1,10 @@ + +The reason these libraries are built outside of the standard XFree86 +tree is so that they can be linked as shared object code directly into +SDL without causing any symbol collisions with code in the application. + +You can't link static library code into shared libraries on non-x86 +Linux platforms. Since these libraries haven't become standard yet, +we'll just include them directly. + +These sources are synchronized with XFree86 4.2.1 diff --git a/3rdparty/SDL/src/video/Xext/XME/xme.c b/3rdparty/SDL/src/video/Xext/XME/xme.c new file mode 100644 index 0000000..2cead35 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/XME/xme.c @@ -0,0 +1,410 @@ +/* + * Copyright 1993-2001 by Xi Graphics, Inc. + * All Rights Reserved. + * + * Please see the LICENSE file accompanying this distribution for licensing + * information. + * + * Please send any bug fixes and modifications to src@xig.com. + * + * $XiGId: xme.c,v 1.2 2001/11/30 21:56:59 jon Exp $ + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xthreads.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" + +/*****************************************************************************/ + + +#define XIGMISC_PROTOCOL_NAME "XiG-SUNDRY-NONSTANDARD" +#define XIGMISC_MAJOR_VERSION 2 +#define XIGMISC_MINOR_VERSION 0 + +#define XiGMiscNumberEvents 0 + +#define X_XiGMiscQueryVersion 0 +#define X_XiGMiscQueryViews 1 +#define X_XiGMiscQueryResolutions 2 +#define X_XiGMiscChangeResolution 3 +#define X_XiGMiscFullScreen 4 + +#define sz_xXiGMiscQueryVersionReq 8 +#define sz_xXiGMiscQueryViewsReq 8 +#define sz_xXiGMiscQueryResolutionsReq 8 +#define sz_xXiGMiscChangeResolutionReq 16 +#define sz_xXiGMiscFullScreenReq 16 + +#define sz_xXiGMiscQueryVersionReply 32 +#define sz_xXiGMiscQueryViewsReply 32 +#define sz_xXiGMiscQueryResolutionsReply 32 +#define sz_xXiGMiscQueryFullScreenReply 32 + +/*******************************************************************/ + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryVersion */ + CARD16 length; + CARD16 major; + CARD16 minor; +} xXiGMiscQueryVersionReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryViews */ + CARD16 length; + CARD8 screen; + CARD8 pad0; + CARD16 pad1; +} xXiGMiscQueryViewsReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscQueryResolutions */ + CARD16 length; + CARD8 screen; + CARD8 view; + CARD16 pad0; +} xXiGMiscQueryResolutionsReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscChangeResolution */ + CARD16 length; + CARD8 screen; + CARD8 view; + CARD16 pad0; + CARD16 width; + CARD16 height; + INT32 refresh; +} xXiGMiscChangeResolutionReq; + +typedef struct { + CARD8 reqType; /* always codes->major_opcode */ + CARD8 xigmiscReqType; /* always X_XiGMiscFullScreen */ + CARD16 length; + CARD8 screen; + CARD8 pad0; + CARD16 pad1; + CARD32 window; + CARD32 cmap; +} xXiGMiscFullScreenReq; + +/*******************************************************************/ + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD16 major; + CARD16 minor; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryVersionReply; + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD32 nviews; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryViewsReply; + +typedef struct { + BYTE type; /* X_Reply */ + CARD8 pad0; + CARD16 sequenceNumber; + CARD32 length; + CARD16 active; + CARD16 nresolutions; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; +} xXiGMiscQueryResolutionsReply; + +typedef struct { + BYTE type; /* X_Reply */ + BOOL success; + CARD16 sequenceNumber; + CARD32 length; + CARD32 pad1; + CARD32 pad2; + CARD32 pad3; + CARD32 pad4; + CARD32 pad5; + CARD32 pad6; +} xXiGMiscFullScreenReply; + +/*******************************************************************/ + +typedef struct { + INT16 x; + INT16 y; + CARD16 w; + CARD16 h; +} XiGMiscViewInfo; + +typedef struct { + CARD16 width; + CARD16 height; + INT32 refresh; +} XiGMiscResolutionInfo; + +/*****************************************************************************/ + +static XExtensionInfo *xigmisc_info = NULL; +static char *xigmisc_extension_name = XIGMISC_PROTOCOL_NAME; + +#define XiGMiscCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xigmisc_extension_name, val) +#define XiGMiscSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, xigmisc_extension_name) + +#if defined(__STDC__) && !defined(UNIXCPP) +#define XiGMiscGetReq(name,req,info) GetReq (name, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_##name; + +#define XiGMiscGetReqExtra(name,n,req,info) GetReqExtra (name, n, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmicReqType = X_##name; +#else +#define XiGMiscGetReq(name,req,info) GetReq (name, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_/**/name; +#define XiGMiscGetReqExtra(name,n,req,info) GetReqExtra (name, n, req); \ + req->reqType = info->codes->major_opcode; \ + req->xigmiscReqType = X_/**/name; +#endif + + + +/* + * find_display - locate the display info block + */ +static int XiGMiscCloseDisplay(); + +static XExtensionHooks xigmisc_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + XiGMiscCloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + + +static XEXT_GENERATE_CLOSE_DISPLAY (XiGMiscCloseDisplay, xigmisc_info) + +static XEXT_GENERATE_FIND_DISPLAY (XiGMiscFindDisplay, xigmisc_info, + xigmisc_extension_name, + &xigmisc_extension_hooks, XiGMiscNumberEvents, NULL) + + +/*****************************************************************************/ + +Bool XiGMiscQueryVersion(Display *dpy, int *major, int *minor) +{ + int opcode, event, error; + xXiGMiscQueryVersionReq *req; + xXiGMiscQueryVersionReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + if (!XQueryExtension(dpy, XIGMISC_PROTOCOL_NAME, &opcode, &event, &error)) + return xFalse; + + XiGMiscCheckExtension(dpy, info, xFalse); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryVersion, req, info); + + req->major = XIGMISC_MAJOR_VERSION; + req->minor = XIGMISC_MINOR_VERSION; + + if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return xFalse; + } + + *major = rep.major; + *minor = rep.minor; + UnlockDisplay(dpy); + SyncHandle(); + + return xTrue; +} + +int XiGMiscQueryViews(Display *dpy, int screen, XiGMiscViewInfo **pviews) +{ + int n, size; + XiGMiscViewInfo *views; + xXiGMiscQueryViewsReq *req; + xXiGMiscQueryViewsReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + XiGMiscCheckExtension(dpy, info, 0); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryViews, req, info); + req->screen = screen; + + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + n = rep.nviews; + + if (n > 0) { + size = sizeof(XiGMiscViewInfo) * n; + views = (XiGMiscViewInfo*)Xmalloc(size); + if (!views) { + _XEatData(dpy, (unsigned long)size); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + _XReadPad(dpy, (void*)views, size); + + *pviews = views; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return n; +} + +int XiGMiscQueryResolutions(Display *dpy, int screen, int view, int *pactive, XiGMiscResolutionInfo **presolutions) +{ + int n, size; + XiGMiscResolutionInfo *resolutions; + xXiGMiscQueryResolutionsReq *req; + xXiGMiscQueryResolutionsReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + XiGMiscCheckExtension(dpy, info, 0); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscQueryResolutions, req, info); + req->screen = screen; + req->view = view; + + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + n = rep.nresolutions; + + if (n > 0) { + size = sizeof(XiGMiscResolutionInfo) * n; + resolutions = (XiGMiscResolutionInfo*)Xmalloc(size); + if (!resolutions) { + _XEatData(dpy, (unsigned long)size); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + _XReadPad(dpy, (void*)resolutions, size); + + *presolutions = resolutions; + *pactive = rep.active; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return n; +} + +void XiGMiscChangeResolution(Display *dpy, int screen, int view, int width, int height, int refresh) +{ + xXiGMiscChangeResolutionReq *req; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + XiGMiscSimpleCheckExtension(dpy, info); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscChangeResolution, req, info); + req->screen = screen; + req->view = view; + req->width = width; + req->height = height; + req->refresh = refresh; + + UnlockDisplay(dpy); + SyncHandle(); +} + + +Bool XiGMiscFullScreen(Display *dpy, int screen, XID window, XID cmap) +{ + xXiGMiscFullScreenReq *req; + xXiGMiscFullScreenReply rep; + XExtDisplayInfo *info = XiGMiscFindDisplay(dpy); + + XiGMiscCheckExtension(dpy, info, xFalse); + + LockDisplay (dpy); + XiGMiscGetReq (XiGMiscFullScreen, req, info); + req->screen = screen; + req->pad0 = 0; + req->pad1 = 0; + req->window = window; + req->cmap = cmap; + + if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return xFalse; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return (rep.success ? xTrue : xFalse); +} + + +/* SDL addition from Ryan: free memory used by xme. */ +void XiGMiscDestroy(void) +{ + if (xigmisc_info) { + XextDestroyExtension(xigmisc_info); + xigmisc_info = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c b/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c new file mode 100644 index 0000000..4ff42eb --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xinerama/Xinerama.c @@ -0,0 +1,324 @@ +/* $Xorg: XPanoramiX.c,v 1.4 2000/08/17 19:45:51 cpqbld Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* $XFree86: xc/lib/Xinerama/Xinerama.c,v 1.2 2001/07/23 17:20:28 dawes Exp $ */ + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xutil.h> +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" /* in ../include */ +#include "../extensions/panoramiXext.h" +#include "../extensions/panoramiXproto.h" /* in ../include */ +#include "../extensions/Xinerama.h" + +static XExtensionInfo _panoramiX_ext_info_data; +static XExtensionInfo *panoramiX_ext_info = &_panoramiX_ext_info_data; +static /* const */ char *panoramiX_extension_name = PANORAMIX_PROTOCOL_NAME; + +#define PanoramiXCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, panoramiX_extension_name, val) +#define PanoramiXSimpleCheckExtension(dpy,i) \ + XextSimpleCheckExtension (dpy, i, panoramiX_extension_name) + +static int close_display(); +static /* const */ XExtensionHooks panoramiX_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, panoramiX_ext_info, + panoramiX_extension_name, + &panoramiX_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, panoramiX_ext_info) + + + +/**************************************************************************** + * * + * PanoramiX public interfaces * + * * + ****************************************************************************/ + +Bool SDL_NAME(XPanoramiXQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +) +{ + XExtDisplayInfo *info = find_display (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Status SDL_NAME(XPanoramiXQueryVersion)( + Display *dpy, + int *major_versionp, + int *minor_versionp +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXQueryVersionReply rep; + register xPanoramiXQueryVersionReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXQueryVersion; + req->clientMajor = PANORAMIX_MAJOR_VERSION; + req->clientMinor = PANORAMIX_MINOR_VERSION; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + *major_versionp = rep.majorVersion; + *minor_versionp = rep.minorVersion; + UnlockDisplay (dpy); + SyncHandle (); + return 1; +} + +SDL_NAME(XPanoramiXInfo) *SDL_NAME(XPanoramiXAllocInfo)(void) +{ + return (SDL_NAME(XPanoramiXInfo) *) Xmalloc (sizeof (SDL_NAME(XPanoramiXInfo))); +} + +Status SDL_NAME(XPanoramiXGetState) ( + Display *dpy, + Drawable drawable, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetStateReply rep; + register xPanoramiXGetStateReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetState, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetState; + req->window = drawable; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->State = rep.state; + return 1; +} + +Status SDL_NAME(XPanoramiXGetScreenCount) ( + Display *dpy, + Drawable drawable, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetScreenCountReply rep; + register xPanoramiXGetScreenCountReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetScreenCount, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetScreenCount; + req->window = drawable; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->ScreenCount = rep.ScreenCount; + return 1; +} + +Status SDL_NAME(XPanoramiXGetScreenSize) ( + Display *dpy, + Drawable drawable, + int screen_num, + SDL_NAME(XPanoramiXInfo) *panoramiX_info +) +{ + XExtDisplayInfo *info = find_display (dpy); + xPanoramiXGetScreenSizeReply rep; + register xPanoramiXGetScreenSizeReq *req; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (PanoramiXGetScreenSize, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_PanoramiXGetScreenSize; + req->window = drawable; + req->screen = screen_num; /* need to define */ + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return 0; + } + UnlockDisplay (dpy); + SyncHandle (); + panoramiX_info->window = rep.window; + panoramiX_info->screen = rep.screen; + panoramiX_info->width = rep.width; + panoramiX_info->height = rep.height; + return 1; +} + +/*******************************************************************\ + Alternate interface to make up for shortcomings in the original, + namely, the omission of the screen origin. The new interface is + in the "Xinerama" namespace instead of "PanoramiX". +\*******************************************************************/ + +Bool SDL_NAME(XineramaQueryExtension) ( + Display *dpy, + int *event_base, + int *error_base +) +{ + return SDL_NAME(XPanoramiXQueryExtension)(dpy, event_base, error_base); +} + +Status SDL_NAME(XineramaQueryVersion)( + Display *dpy, + int *major, + int *minor +) +{ + return SDL_NAME(XPanoramiXQueryVersion)(dpy, major, minor); +} + +Bool SDL_NAME(XineramaIsActive)(Display *dpy) +{ + xXineramaIsActiveReply rep; + xXineramaIsActiveReq *req; + XExtDisplayInfo *info = find_display (dpy); + + if(!XextHasExtension(info)) + return False; /* server doesn't even have the extension */ + + LockDisplay (dpy); + GetReq (XineramaIsActive, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_XineramaIsActive; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + UnlockDisplay (dpy); + SyncHandle (); + return rep.state; +} + +#include <stdio.h> + +SDL_NAME(XineramaScreenInfo) * +SDL_NAME(XineramaQueryScreens)( + Display *dpy, + int *number +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXineramaQueryScreensReply rep; + xXineramaQueryScreensReq *req; + SDL_NAME(XineramaScreenInfo) *scrnInfo = NULL; + + PanoramiXCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (XineramaQueryScreens, req); + req->reqType = info->codes->major_opcode; + req->panoramiXReqType = X_XineramaQueryScreens; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + return NULL; + } + + if(rep.number) { + if((scrnInfo = Xmalloc(sizeof(SDL_NAME(XineramaScreenInfo)) * rep.number))) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < rep.number; i++) { + _XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo); + scrnInfo[i].screen_number = i; + scrnInfo[i].x_org = scratch.x_org; + scrnInfo[i].y_org = scratch.y_org; + scrnInfo[i].width = scratch.width; + scrnInfo[i].height = scratch.height; + } + + *number = rep.number; + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay (dpy); + SyncHandle (); + return scrnInfo; +} + + + diff --git a/3rdparty/SDL/src/video/Xext/Xv/Xv.c b/3rdparty/SDL/src/video/Xext/Xv/Xv.c new file mode 100644 index 0000000..7147b9e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xv/Xv.c @@ -0,0 +1,1151 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/lib/Xv/Xv.c,v 1.15 2001/05/11 08:23:22 alanh Exp $ */ +/* +** File: +** +** Xv.c --- Xv library extension module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 26.06.91 Carver +** - changed XvFreeAdaptors to XvFreeAdaptorInfo +** - changed XvFreeEncodings to XvFreeEncodingInfo +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 240.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <stdio.h> +#include "Xvlibint.h" +#include "../extensions/Xext.h" +#include <X11/extensions/XShm.h> +#include "../extensions/extutil.h" + +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) + +static char *xv_error_string(); +static int xv_close_display(); +static Bool xv_wire_to_event(); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + + +int +SDL_NAME(XvQueryExtension)( + Display *dpy, + unsigned int *p_version, + unsigned int *p_revision, + unsigned int *p_requestBase, + unsigned int *p_eventBase, + unsigned int *p_errorBase +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryExtensionReq *req; + xvQueryExtensionReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryExtension, req); + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return XvBadExtension; + } + + *p_version = rep.version; + *p_revision = rep.revision; + *p_requestBase = info->codes->major_opcode; + *p_eventBase = info->codes->first_event; + *p_errorBase = info->codes->first_error; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvQueryAdaptors)( + Display *dpy, + Window window, + unsigned int *p_nAdaptors, + SDL_NAME(XvAdaptorInfo) **p_pAdaptors +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryAdaptorsReq *req; + xvQueryAdaptorsReply rep; + int size,ii,jj; + char *name; + SDL_NAME(XvAdaptorInfo) *pas, *pa; + SDL_NAME(XvFormat) *pfs, *pf; + char *buffer; + union + { + char *buffer; + char *string; + xvAdaptorInfo *pa; + xvFormat *pf; + } u; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryAdaptors, req); + req->window = window; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + size = rep.length << 2; + if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + _XRead (dpy, buffer, size); + + u.buffer = buffer; + + /* GET INPUT ADAPTORS */ + + if (rep.num_adaptors == 0) { + pas = NULL; + } else { + size = rep.num_adaptors*sizeof(SDL_NAME(XvAdaptorInfo)); + if ((pas=(SDL_NAME(XvAdaptorInfo) *)Xmalloc(size))==NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + } + + /* INIT ADAPTOR FIELDS */ + + pa = pas; + for (ii=0; ii<rep.num_adaptors; ii++) { + pa->num_adaptors = 0; + pa->name = (char *)NULL; + pa->formats = (SDL_NAME(XvFormat) *)NULL; + pa++; + } + + pa = pas; + for (ii=0; ii<rep.num_adaptors; ii++) { + pa->type = u.pa->type; + pa->base_id = u.pa->base_id; + pa->num_ports = u.pa->num_ports; + pa->num_formats = u.pa->num_formats; + pa->num_adaptors = rep.num_adaptors - ii; + + /* GET ADAPTOR NAME */ + + size = u.pa->name_size; + u.buffer += (sz_xvAdaptorInfo + 3) & ~3; + + if ( (name = (char *)Xmalloc(size+1)) == NULL) + { + SDL_NAME(XvFreeAdaptorInfo)(pas); + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + SDL_strlcpy(name, u.string, size); + pa->name = name; + + u.buffer += (size + 3) & ~3; + + /* GET FORMATS */ + + size = pa->num_formats*sizeof(SDL_NAME(XvFormat)); + if ((pfs=(SDL_NAME(XvFormat) *)Xmalloc(size))==NULL) { + SDL_NAME(XvFreeAdaptorInfo)(pas); + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + + pf = pfs; + for (jj=0; jj<pa->num_formats; jj++) { + pf->depth = u.pf->depth; + pf->visual_id = u.pf->visual; + pf++; + + u.buffer += (sz_xvFormat + 3) & ~3; + } + + pa->formats = pfs; + + pa++; + + } + + *p_nAdaptors = rep.num_adaptors; + *p_pAdaptors = pas; + + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + + +void +SDL_NAME(XvFreeAdaptorInfo)(SDL_NAME(XvAdaptorInfo) *pAdaptors) +{ + + SDL_NAME(XvAdaptorInfo) *pa; + int ii; + + if (!pAdaptors) return; + + pa = pAdaptors; + + for (ii=0; ii<pAdaptors->num_adaptors; ii++, pa++) + { + if (pa->name) + { + Xfree(pa->name); + } + if (pa->formats) + { + Xfree(pa->formats); + } + } + + Xfree(pAdaptors); +} + +int +SDL_NAME(XvQueryEncodings)( + Display *dpy, + XvPortID port, + unsigned int *p_nEncodings, + SDL_NAME(XvEncodingInfo) **p_pEncodings +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryEncodingsReq *req; + xvQueryEncodingsReply rep; + int size, jj; + char *name; + SDL_NAME(XvEncodingInfo) *pes, *pe; + char *buffer; + union + { + char *buffer; + char *string; + xvEncodingInfo *pe; + } u; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryEncodings, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + size = rep.length << 2; + if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + _XRead (dpy, buffer, size); + + u.buffer = buffer; + + /* GET ENCODINGS */ + + size = rep.num_encodings*sizeof(SDL_NAME(XvEncodingInfo)); + if ( (pes = (SDL_NAME(XvEncodingInfo) *)Xmalloc(size)) == NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + + /* INITIALIZE THE ENCODING POINTER */ + + pe = pes; + for (jj=0; jj<rep.num_encodings; jj++) { + pe->name = (char *)NULL; + pe->num_encodings = 0; + pe++; + } + + pe = pes; + for (jj=0; jj<rep.num_encodings; jj++) { + pe->encoding_id = u.pe->encoding; + pe->width = u.pe->width; + pe->height = u.pe->height; + pe->rate.numerator = u.pe->rate.numerator; + pe->rate.denominator = u.pe->rate.denominator; + pe->num_encodings = rep.num_encodings - jj; + + size = u.pe->name_size; + u.buffer += (sz_xvEncodingInfo + 3) & ~3; + + if ( (name = (char *)Xmalloc(size+1)) == NULL) { + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadAlloc); + } + SDL_strlcpy(name, u.string, size); + pe->name = name; + pe++; + + u.buffer += (size + 3) & ~3; + } + + *p_nEncodings = rep.num_encodings; + *p_pEncodings = pes; + + Xfree(buffer); + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +void +SDL_NAME(XvFreeEncodingInfo)(SDL_NAME(XvEncodingInfo) *pEncodings) +{ + + SDL_NAME(XvEncodingInfo) *pe; + int ii; + + if (!pEncodings) return; + + pe = pEncodings; + + for (ii=0; ii<pEncodings->num_encodings; ii++, pe++) { + if (pe->name) Xfree(pe->name); + } + + Xfree(pEncodings); +} + +int +SDL_NAME(XvPutVideo)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutVideo, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvPutStill)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutStillReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutStill, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGetVideo)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(GetVideo, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGetStill)( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + int vx, int vy, + unsigned int vw, unsigned int vh, + int dx, int dy, + unsigned int dw, unsigned int dh +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetStillReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(GetStill, req); + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->vid_x = vx; + req->vid_y = vy; + req->vid_w = vw; + req->vid_h = vh; + req->drw_x = dx; + req->drw_y = dy; + req->drw_w = dw; + req->drw_h = dh; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvStopVideo)( + Display *dpy, + XvPortID port, + Drawable draw +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvStopVideoReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(StopVideo, req); + req->port = port; + req->drawable = draw; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvGrabPort)( + Display *dpy, + XvPortID port, + Time time +){ + XExtDisplayInfo *info = xv_find_display(dpy); + int result; + xvGrabPortReply rep; + xvGrabPortReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(GrabPort, req); + req->port = port; + req->time = time; + + if (_XReply (dpy, (xReply *) &rep, 0, xTrue) == 0) + rep.result = GrabSuccess; + + result = rep.result; + + UnlockDisplay(dpy); + SyncHandle(); + + return result; +} + +int +SDL_NAME(XvUngrabPort)( + Display *dpy, + XvPortID port, + Time time +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvUngrabPortReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(UngrabPort, req); + req->port = port; + req->time = time; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSelectVideoNotify)( + Display *dpy, + Drawable drawable, + Bool onoff +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSelectVideoNotifyReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SelectVideoNotify, req); + req->drawable = drawable; + req->onoff = onoff; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSelectPortNotify)( + Display *dpy, + XvPortID port, + Bool onoff +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSelectPortNotifyReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SelectPortNotify, req); + req->port = port; + req->onoff = onoff; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int +SDL_NAME(XvSetPortAttribute) ( + Display *dpy, + XvPortID port, + Atom attribute, + int value +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvSetPortAttributeReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(SetPortAttribute, req); + req->port = port; + req->attribute = attribute; + req->value = value; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +int +SDL_NAME(XvGetPortAttribute) ( + Display *dpy, + XvPortID port, + Atom attribute, + int *p_value +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvGetPortAttributeReq *req; + xvGetPortAttributeReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(GetPortAttribute, req); + req->port = port; + req->attribute = attribute; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + *p_value = rep.value; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + +int +SDL_NAME(XvQueryBestSize)( + Display *dpy, + XvPortID port, + Bool motion, + unsigned int vid_w, + unsigned int vid_h, + unsigned int drw_w, + unsigned int drw_h, + unsigned int *p_actual_width, + unsigned int *p_actual_height +) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryBestSizeReq *req; + xvQueryBestSizeReply rep; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + XvGetReq(QueryBestSize, req); + req->port = port; + req->motion = motion; + req->vid_w = vid_w; + req->vid_h = vid_h; + req->drw_w = drw_w; + req->drw_h = drw_h; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return(XvBadReply); + } + + *p_actual_width = rep.actual_width; + *p_actual_height = rep.actual_height; + + UnlockDisplay(dpy); + SyncHandle(); + + return (Success); +} + + +SDL_NAME(XvAttribute)* +SDL_NAME(XvQueryPortAttributes)(Display *dpy, XvPortID port, int *num) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryPortAttributesReq *req; + xvQueryPortAttributesReply rep; + SDL_NAME(XvAttribute) *ret = NULL; + + *num = 0; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(QueryPortAttributes, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return ret; + } + + if(rep.num_attributes) { + int size = (rep.num_attributes * sizeof(SDL_NAME(XvAttribute))) + rep.text_size; + + if((ret = Xmalloc(size))) { + char* marker = (char*)(&ret[rep.num_attributes]); + xvAttributeInfo Info; + int i; + + for(i = 0; i < rep.num_attributes; i++) { + _XRead(dpy, (char*)(&Info), sz_xvAttributeInfo); + ret[i].flags = (int)Info.flags; + ret[i].min_value = Info.min; + ret[i].max_value = Info.max; + ret[i].name = marker; + _XRead(dpy, marker, Info.size); + marker += Info.size; + (*num)++; + } + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay(dpy); + SyncHandle(); + + return ret; +} + +SDL_NAME(XvImageFormatValues) * SDL_NAME(XvListImageFormats) ( + Display *dpy, + XvPortID port, + int *num +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvListImageFormatsReq *req; + xvListImageFormatsReply rep; + SDL_NAME(XvImageFormatValues) *ret = NULL; + + *num = 0; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(ListImageFormats, req); + req->port = port; + + /* READ THE REPLY */ + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + if(rep.num_formats) { + int size = (rep.num_formats * sizeof(SDL_NAME(XvImageFormatValues))); + + if((ret = Xmalloc(size))) { + xvImageFormatInfo Info; + int i; + + for(i = 0; i < rep.num_formats; i++) { + _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo); + ret[i].id = Info.id; + ret[i].type = Info.type; + ret[i].byte_order = Info.byte_order; + memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16); + ret[i].bits_per_pixel = Info.bpp; + ret[i].format = Info.format; + ret[i].num_planes = Info.num_planes; + ret[i].depth = Info.depth; + ret[i].red_mask = Info.red_mask; + ret[i].green_mask = Info.green_mask; + ret[i].blue_mask = Info.blue_mask; + ret[i].y_sample_bits = Info.y_sample_bits; + ret[i].u_sample_bits = Info.u_sample_bits; + ret[i].v_sample_bits = Info.v_sample_bits; + ret[i].horz_y_period = Info.horz_y_period; + ret[i].horz_u_period = Info.horz_u_period; + ret[i].horz_v_period = Info.horz_v_period; + ret[i].vert_y_period = Info.vert_y_period; + ret[i].vert_u_period = Info.vert_u_period; + ret[i].vert_v_period = Info.vert_v_period; + memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32); + ret[i].scanline_order = Info.scanline_order; + (*num)++; + } + } else + _XEatData(dpy, rep.length << 2); + } + + UnlockDisplay(dpy); + SyncHandle(); + + return ret; +} + +SDL_NAME(XvImage) * SDL_NAME(XvCreateImage) ( + Display *dpy, + XvPortID port, + int id, + char *data, + int width, + int height +) { + XExtDisplayInfo *info = xv_find_display(dpy); + xvQueryImageAttributesReq *req; + xvQueryImageAttributesReply rep; + SDL_NAME(XvImage) *ret = NULL; + + XvCheckExtension(dpy, info, NULL); + + LockDisplay(dpy); + + XvGetReq(QueryImageAttributes, req); + req->id = id; + req->port = port; + req->width = width; + req->height = height; + + /* READ THE REPLY */ + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + if((ret = (SDL_NAME(XvImage)*)Xmalloc(sizeof(SDL_NAME(XvImage)) + (rep.num_planes << 3)))) { + ret->id = id; + ret->width = rep.width; + ret->height = rep.height; + ret->data_size = rep.data_size; + ret->num_planes = rep.num_planes; + ret->pitches = (int*)(&ret[1]); + ret->offsets = ret->pitches + rep.num_planes; + ret->data = data; + ret->obdata = NULL; + _XRead(dpy, (char*)(ret->pitches), rep.num_planes << 2); + _XRead(dpy, (char*)(ret->offsets), rep.num_planes << 2); + } else + _XEatData(dpy, rep.length << 2); + + UnlockDisplay(dpy); + SyncHandle(); + return ret; +} + +SDL_NAME(XvImage) * SDL_NAME(XvShmCreateImage) ( + Display *dpy, + XvPortID port, + int id, + char *data, + int width, + int height, + XShmSegmentInfo *shminfo +){ + SDL_NAME(XvImage) *ret; + + ret = SDL_NAME(XvCreateImage)(dpy, port, id, data, width, height); + + if(ret) ret->obdata = (XPointer)shminfo; + + return ret; +} + +int SDL_NAME(XvPutImage) ( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h +){ + XExtDisplayInfo *info = xv_find_display(dpy); + xvPutImageReq *req; + int len; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(PutImage, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->id = image->id; + req->src_x = src_x; + req->src_y = src_y; + req->src_w = src_w; + req->src_h = src_h; + req->drw_x = dest_x; + req->drw_y = dest_y; + req->drw_w = dest_w; + req->drw_h = dest_h; + req->width = image->width; + req->height = image->height; + + len = (image->data_size + 3) >> 2; + SetReqLen(req, len, len); + + /* Yes it's kindof lame that we are sending the whole thing, + but for video all of it may be needed even if displaying + only a subsection, and I don't want to go through the + trouble of creating subregions to send */ + Data(dpy, (char *)image->data, image->data_size); + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int SDL_NAME(XvShmPutImage) ( + Display *dpy, + XvPortID port, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h, + Bool send_event +){ + XExtDisplayInfo *info = xv_find_display(dpy); + XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata; + xvShmPutImageReq *req; + + XvCheckExtension(dpy, info, XvBadExtension); + + LockDisplay(dpy); + + FlushGC(dpy, gc); + + XvGetReq(ShmPutImage, req); + + req->port = port; + req->drawable = d; + req->gc = gc->gid; + req->shmseg = shminfo->shmseg; + req->id = image->id; + req->src_x = src_x; + req->src_y = src_y; + req->src_w = src_w; + req->src_h = src_h; + req->drw_x = dest_x; + req->drw_y = dest_y; + req->drw_w = dest_w; + req->drw_h = dest_h; + req->offset = image->data - shminfo->shmaddr; + req->width = image->width; + req->height = image->height; + req->send_event = send_event; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + + +static Bool +xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) +{ + XExtDisplayInfo *info = xv_find_display(dpy); + SDL_NAME(XvEvent) *re = (SDL_NAME(XvEvent) *)host; + xvEvent *event = (xvEvent *)wire; + + XvCheckExtension(dpy, info, False); + + switch((event->u.u.type & 0x7F) - info->codes->first_event) + { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return (True); +} + + diff --git a/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h b/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h new file mode 100644 index 0000000..20df706 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xv/Xvlibint.h @@ -0,0 +1,81 @@ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/lib/Xv/Xvlibint.h,v 1.5 2001/07/25 15:04:53 dawes Exp $ */ + +#ifndef XVLIBINT_H +#define XVLIBINT_H +/* +** File: +** +** Xvlibint.h --- Xv library internal header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/Xvproto.h" +#include "../extensions/Xvlib.h" + +#if !defined(UNIXCPP) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv/**/name/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_/**/name;\ + req->length = (SIZEOF(xv/**/name/**/Req))>>2;\ + dpy->bufptr += SIZEOF(xv/**/name/**/Req);\ + dpy->request++ +#endif + + +#endif /* XVLIBINT_H */ diff --git a/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c new file mode 100644 index 0000000..fc729f1 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA.c @@ -0,0 +1,721 @@ +/* $XFree86: xc/lib/Xxf86dga/XF86DGA.c,v 3.19 2001/08/18 02:41:30 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995,1996 The XFree86 Project, Inc + +*/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#ifdef __EMX__ /* needed here to override certain constants in X headers */ +#define INCL_DOS +#define INCL_DOSIOCTL +#include <os2.h> +#endif + +#if defined(linux) +#define HAS_MMAP_ANON +#include <sys/types.h> +#include <sys/mman.h> +/*#include <asm/page.h>*/ /* PAGE_SIZE */ +#define HAS_SC_PAGESIZE /* _SC_PAGESIZE may be an enum for Linux */ +#define HAS_GETPAGESIZE +#endif /* linux */ + +#if defined(CSRG_BASED) +#define HAS_MMAP_ANON +#define HAS_GETPAGESIZE +#include <sys/types.h> +#include <sys/mman.h> +#endif /* CSRG_BASED */ + +#if defined(DGUX) +#define HAS_GETPAGESIZE +#define MMAP_DEV_ZERO +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#endif /* DGUX */ + +#if defined(SVR4) && !defined(DGUX) +#define MMAP_DEV_ZERO +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> +#endif /* SVR4 && !DGUX */ + +#if defined(sun) && !defined(SVR4) /* SunOS */ +#define MMAP_DEV_ZERO /* doesn't SunOS have MAP_ANON ?? */ +#define HAS_GETPAGESIZE +#include <sys/types.h> +#include <sys/mman.h> +#endif /* sun && !SVR4 */ + +#ifdef XNO_SYSCONF +#undef _SC_PAGESIZE +#endif + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/xf86dga.h" +#include "../extensions/xf86dgastr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" + +extern XExtDisplayInfo* SDL_NAME(xdga_find_display)(Display*); +extern char *SDL_NAME(xdga_extension_name); + +#define XF86DGACheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val) + +/***************************************************************************** + * * + * public XFree86-DGA Extension routines * + * * + *****************************************************************************/ + +Bool SDL_NAME(XF86DGAQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +){ + return SDL_NAME(XDGAQueryExtension)(dpy, event_basep, error_basep); +} + +Bool SDL_NAME(XF86DGAQueryVersion)( + Display* dpy, + int* majorVersion, + int* minorVersion +){ + return SDL_NAME(XDGAQueryVersion)(dpy, majorVersion, minorVersion); +} + +Bool SDL_NAME(XF86DGAGetVideoLL)( + Display* dpy, + int screen, + int *offset, + int *width, + int *bank_size, + int *ram_size +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetVideoLLReply rep; + xXF86DGAGetVideoLLReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetVideoLL, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetVideoLL; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *offset = /*(char *)*/rep.offset; + *width = rep.width; + *bank_size = rep.bank_size; + *ram_size = rep.ram_size; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGADirectVideoLL)( + Display* dpy, + int screen, + int enable +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGADirectVideoReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGADirectVideo, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGADirectVideo; + req->screen = screen; + req->enable = enable; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAGetViewPortSize)( + Display* dpy, + int screen, + int *width, + int *height +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetViewPortSizeReply rep; + xXF86DGAGetViewPortSizeReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetViewPortSize, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetViewPortSize; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *width = rep.width; + *height = rep.height; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGASetViewPort)( + Display* dpy, + int screen, + int x, + int y +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGASetViewPortReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGASetViewPort, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGASetViewPort; + req->screen = screen; + req->x = x; + req->y = y; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + + +Bool SDL_NAME(XF86DGAGetVidPage)( + Display* dpy, + int screen, + int *vpage +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAGetVidPageReply rep; + xXF86DGAGetVidPageReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAGetVidPage, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAGetVidPage; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *vpage = rep.vpage; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool SDL_NAME(XF86DGASetVidPage)( + Display* dpy, + int screen, + int vpage +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGASetVidPageReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGASetVidPage, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGASetVidPage; + req->screen = screen; + req->vpage = vpage; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAInstallColormap)( + Display* dpy, + int screen, + Colormap cmap +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAInstallColormapReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAInstallColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAInstallColormap; + req->screen = screen; + req->id = cmap; + UnlockDisplay(dpy); + SyncHandle(); + XSync(dpy,False); + return True; +} + +Bool SDL_NAME(XF86DGAQueryDirectVideo)( + Display *dpy, + int screen, + int *flags +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAQueryDirectVideoReply rep; + xXF86DGAQueryDirectVideoReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAQueryDirectVideo, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAQueryDirectVideo; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *flags = rep.flags; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XF86DGAViewPortChanged)( + Display *dpy, + int screen, + int n +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXF86DGAViewPortChangedReply rep; + xXF86DGAViewPortChangedReq *req; + + XF86DGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86DGAViewPortChanged, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XF86DGAViewPortChanged; + req->screen = screen; + req->n = n; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.result; +} + + + +/* Helper functions */ + +#include <X11/Xmd.h> +#include "../extensions/xf86dga.h" +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#if defined(ISC) +# define HAS_SVR3_MMAP +# include <sys/types.h> +# include <errno.h> + +# include <sys/at_ansi.h> +# include <sys/kd.h> + +# include <sys/sysmacros.h> +# include <sys/immu.h> +# include <sys/region.h> + +# include <sys/mmap.h> +#else +# if !defined(Lynx) +# if !defined(__EMX__) +# include <sys/mman.h> +# endif +# else +# include <sys/types.h> +# include <errno.h> +# include <smem.h> +# endif +#endif +#include <sys/wait.h> +#include <signal.h> +#include <unistd.h> + +#if defined(SVR4) && !defined(sun) && !defined(SCO325) +#define DEV_MEM "/dev/pmem" +#elif defined(SVR4) && defined(sun) +#define DEV_MEM "/dev/xsvc" +#else +#define DEV_MEM "/dev/mem" +#endif + +typedef struct { + unsigned long physaddr; /* actual requested physical address */ + unsigned long size; /* actual requested map size */ + unsigned long delta; /* delta to account for page alignment */ + void * vaddr; /* mapped address, without the delta */ + int refcount; /* reference count */ +} MapRec, *MapPtr; + +typedef struct { + Display * display; + int screen; + MapPtr map; +} ScrRec, *ScrPtr; + +static int mapFd = -1; +static int numMaps = 0; +static int numScrs = 0; +static MapPtr *mapList = NULL; +static ScrPtr *scrList = NULL; + +static MapPtr +AddMap(void) +{ + MapPtr *old; + + old = mapList; + mapList = realloc(mapList, sizeof(MapPtr) * (numMaps + 1)); + if (!mapList) { + mapList = old; + return NULL; + } + mapList[numMaps] = malloc(sizeof(MapRec)); + if (!mapList[numMaps]) + return NULL; + return mapList[numMaps++]; +} + +static ScrPtr +AddScr(void) +{ + ScrPtr *old; + + old = scrList; + scrList = realloc(scrList, sizeof(ScrPtr) * (numScrs + 1)); + if (!scrList) { + scrList = old; + return NULL; + } + scrList[numScrs] = malloc(sizeof(ScrRec)); + if (!scrList[numScrs]) + return NULL; + return scrList[numScrs++]; +} + +static MapPtr +FindMap(unsigned long address, unsigned long size) +{ + int i; + + for (i = 0; i < numMaps; i++) { + if (mapList[i]->physaddr == address && + mapList[i]->size == size) + return mapList[i]; + } + return NULL; +} + +static ScrPtr +FindScr(Display *display, int screen) +{ + int i; + + for (i = 0; i < numScrs; i++) { + if (scrList[i]->display == display && + scrList[i]->screen == screen) + return scrList[i]; + } + return NULL; +} + +static void * +MapPhysAddress(unsigned long address, unsigned long size) +{ + unsigned long offset, delta; + int pagesize = -1; + void *vaddr; + MapPtr mp; +#if defined(ISC) && defined(HAS_SVR3_MMAP) + struct kd_memloc mloc; +#elif defined(__EMX__) + APIRET rc; + ULONG action; + HFILE hfd; +#endif + + if ((mp = FindMap(address, size))) { + mp->refcount++; + return (void *)((unsigned long)mp->vaddr + mp->delta); + } + +#if defined(_SC_PAGESIZE) && defined(HAS_SC_PAGESIZE) + pagesize = sysconf(_SC_PAGESIZE); +#endif +#ifdef _SC_PAGE_SIZE + if (pagesize == -1) + pagesize = sysconf(_SC_PAGE_SIZE); +#endif +#ifdef HAS_GETPAGESIZE + if (pagesize == -1) + pagesize = getpagesize(); +#endif +#ifdef PAGE_SIZE + if (pagesize == -1) + pagesize = PAGE_SIZE; +#endif + if (pagesize == -1) + pagesize = 4096; + + delta = address % pagesize; + offset = address - delta; + +#if defined(ISC) && defined(HAS_SVR3_MMAP) + if (mapFd < 0) { + if ((mapFd = open("/dev/mmap", O_RDWR)) < 0) + return NULL; + } + mloc.vaddr = (char *)0; + mloc.physaddr = (char *)offset; + mloc.length = size + delta; + mloc.ioflg=1; + + if ((vaddr = (void *)ioctl(mapFd, MAP, &mloc)) == (void *)-1) + return NULL; +#elif defined (__EMX__) + /* + * Dragon warning here! /dev/pmap$ is never closed, except on progam exit. + * Consecutive calling of this routine will make PMAP$ driver run out + * of memory handles. Some umap/close mechanism should be provided + */ + + rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL); + if (rc != 0) + return NULL; + { + struct map_ioctl { + union { + ULONG phys; + void* user; + } a; + ULONG size; + } pmap,dmap; + ULONG plen,dlen; +#define XFREE86_PMAP 0x76 +#define PMAP_MAP 0x44 + + pmap.a.phys = offset; + pmap.size = size + delta; + rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP, + (PULONG)&pmap, sizeof(pmap), &plen, + (PULONG)&dmap, sizeof(dmap), &dlen); + if (rc == 0) { + vaddr = dmap.a.user; + } + } + if (rc != 0) + return NULL; +#elif defined (Lynx) + vaddr = (void *)smem_create("XF86DGA", (char *)offset, + size + delta, SM_READ|SM_WRITE); +#else +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + if (mapFd < 0) { + if ((mapFd = open(DEV_MEM, O_RDWR)) < 0) + return NULL; + } + vaddr = (void *)mmap(NULL, size + delta, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, mapFd, (off_t)offset); + if (vaddr == (void *)-1) + return NULL; +#endif + + if (!vaddr) { + if (!(mp = AddMap())) + return NULL; + mp->physaddr = address; + mp->size = size; + mp->delta = delta; + mp->vaddr = vaddr; + mp->refcount = 1; + } + return (void *)((unsigned long)vaddr + delta); +} + +/* + * Still need to find a clean way of detecting the death of a DGA app + * and returning things to normal - Jon + * This is here to help debugging without rebooting... Also C-A-BS + * should restore text mode. + */ + +int +SDL_NAME(XF86DGAForkApp)(int screen) +{ + pid_t pid; + int status; + int i; + + /* fork the app, parent hangs around to clean up */ + if ((pid = fork()) > 0) { + ScrPtr sp; + + waitpid(pid, &status, 0); + for (i = 0; i < numScrs; i++) { + sp = scrList[i]; + SDL_NAME(XF86DGADirectVideoLL)(sp->display, sp->screen, 0); + XSync(sp->display, False); + } + if (WIFEXITED(status)) + _exit(0); + else + _exit(-1); + } + return pid; +} + + +Bool +SDL_NAME(XF86DGADirectVideo)( + Display *dis, + int screen, + int enable +){ + ScrPtr sp; + MapPtr mp = NULL; + + if ((sp = FindScr(dis, screen))) + mp = sp->map; + + if (enable & XF86DGADirectGraphics) { +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + if (mp && mp->vaddr) + mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ | PROT_WRITE); +#endif + } else { +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + if (mp && mp->vaddr) + mprotect(mp->vaddr, mp->size + mp->delta, PROT_READ); +#elif defined(Lynx) + /* XXX this doesn't allow enable after disable */ + smem_create(NULL, mp->vaddr, mp->size + mp->delta, SM_DETACH); + smem_remove("XF86DGA"); +#endif + } + + SDL_NAME(XF86DGADirectVideoLL)(dis, screen, enable); + return 1; +} + + +static void +XF86cleanup(int sig) +{ + ScrPtr sp; + int i; + static char beenhere = 0; + + if (beenhere) + _exit(3); + beenhere = 1; + + for (i = 0; i < numScrs; i++) { + sp = scrList[i]; + SDL_NAME(XF86DGADirectVideo)(sp->display, sp->screen, 0); + XSync(sp->display, False); + } + _exit(3); +} + +Bool +SDL_NAME(XF86DGAGetVideo)( + Display *dis, + int screen, + char **addr, + int *width, + int *bank, + int *ram +){ + /*unsigned long*/ int offset; + static int beenHere = 0; + ScrPtr sp; + MapPtr mp; + + if (!(sp = FindScr(dis, screen))) { + if (!(sp = AddScr())) { + fprintf(stderr, "XF86DGAGetVideo: malloc failure\n"); + exit(-2); + } + sp->display = dis; + sp->screen = screen; + sp->map = NULL; + } + + SDL_NAME(XF86DGAGetVideoLL)(dis, screen , &offset, width, bank, ram); + + *addr = MapPhysAddress(offset, *bank); + if (*addr == NULL) { + fprintf(stderr, "XF86DGAGetVideo: failed to map video memory (%s)\n", + strerror(errno)); + exit(-2); + } + + if ((mp = FindMap(offset, *bank))) + sp->map = mp; + + if (!beenHere) { + beenHere = 1; + atexit((void(*)(void))XF86cleanup); + /* one shot XF86cleanup attempts */ + signal(SIGSEGV, XF86cleanup); +#ifdef SIGBUS + signal(SIGBUS, XF86cleanup); +#endif + signal(SIGHUP, XF86cleanup); + signal(SIGFPE, XF86cleanup); + } + + return 1; +} + diff --git a/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c new file mode 100644 index 0000000..11d4fdd --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86dga/XF86DGA2.c @@ -0,0 +1,993 @@ +/* $XFree86: xc/lib/Xxf86dga/XF86DGA2.c,v 1.18 2001/08/17 13:27:51 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995,1996 The XFree86 Project, Inc + +*/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#ifdef __EMX__ /* needed here to override certain constants in X headers */ +#define INCL_DOS +#define INCL_DOSIOCTL +#include <os2.h> +#endif + +#define NEED_EVENTS +#define NEED_REPLIES + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include "../extensions/xf86dga.h" +#include "../extensions/xf86dgastr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" +#include <stdio.h> + +#if defined(ENABLE_FBCON) /* Needed for framebuffer console support */ +#include <sys/ioctl.h> +#include <linux/fb.h> +#endif + +/* If you change this, change the Bases[] array below as well */ +#define MAX_HEADS 16 + +char *SDL_NAME(xdga_extension_name) = XF86DGANAME; + +static XExtensionInfo _xdga_info_data; +static XExtensionInfo *xdga_info = &_xdga_info_data; + + +Bool SDL_NAME(XDGAMapFramebuffer)(int, char *, unsigned char*, CARD32, CARD32, CARD32); +void SDL_NAME(XDGAUnmapFramebuffer)(int); +unsigned char* SDL_NAME(XDGAGetMappedMemory)(int); + +#define XDGACheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, SDL_NAME(xdga_extension_name), val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static int xdga_close_display(Display *dpy, XExtCodes *codes); +static Bool xdga_wire_to_event(Display *dpy, XEvent *event, xEvent *wire_ev); +static Status xdga_event_to_wire(Display *dpy, XEvent *event, xEvent *wire_ev); + +static XExtensionHooks xdga_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xdga_close_display, /* close_display */ + xdga_wire_to_event, /* wire_to_event */ + xdga_event_to_wire, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_CLOSE_DISPLAY (xdga_close_display, xdga_info) + + +XEXT_GENERATE_FIND_DISPLAY (SDL_NAME(xdga_find_display), xdga_info, + "XFree86-DGA", + &xdga_extension_hooks, + 0, NULL) + + +static Status +xdga_event_to_wire( + Display *dpy, + XEvent *event, + xEvent *wire_ev +){ + return True; +} + +static Bool +xdga_wire_to_event( + Display *dpy, + XEvent *event, + xEvent *wire_ev +){ + dgaEvent *wire = (dgaEvent *) wire_ev; + SDL_NAME(XDGAButtonEvent) *bevent; + SDL_NAME(XDGAKeyEvent) *kevent; + SDL_NAME(XDGAMotionEvent) *mevent; + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + + XDGACheckExtension (dpy, info, False); + + switch((wire->u.u.type & 0x7f) - info->codes->first_event) { + case MotionNotify: + mevent = (SDL_NAME(XDGAMotionEvent)*)event; + mevent->type = wire->u.u.type & 0x7F; + mevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + mevent->display = dpy; + mevent->screen = wire->u.event.screen; + mevent->time = wire->u.event.time; + mevent->state = wire->u.event.state; + mevent->dx = wire->u.event.dx; + mevent->dy = wire->u.event.dy; + return True; + case ButtonPress: + case ButtonRelease: + bevent = (SDL_NAME(XDGAButtonEvent)*)event; + bevent->type = wire->u.u.type & 0x7F; + bevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + bevent->display = dpy; + bevent->screen = wire->u.event.screen; + bevent->time = wire->u.event.time; + bevent->state = wire->u.event.state; + bevent->button = wire->u.u.detail; + return True; + case KeyPress: + case KeyRelease: + kevent = (SDL_NAME(XDGAKeyEvent)*)event; + kevent->type = wire->u.u.type & 0x7F; + kevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *)wire); + kevent->display = dpy; + kevent->screen = wire->u.event.screen; + kevent->time = wire->u.event.time; + kevent->state = wire->u.event.state; + kevent->keycode = wire->u.u.detail; + return True; + } + + return False; +} + + +Bool SDL_NAME(XDGAQueryExtension) ( + Display *dpy, + int *event_basep, + int *error_basep +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + + +Bool SDL_NAME(XDGAQueryVersion)( + Display *dpy, + int *majorVersion, + int *minorVersion +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAQueryVersionReply rep; + xXDGAQueryVersionReq *req; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGAQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + if (*majorVersion >= 2) + { + int i, j; + + for (i = 0, j = info->codes->first_event; + i < XF86DGANumberEvents; + i++, j++) + { + XESetWireToEvent(dpy, j, xdga_wire_to_event); + XESetEventToWire(dpy, j, xdga_event_to_wire); + } + SDL_NAME(XDGASetClientVersion)(dpy); + } + return True; +} + +Bool SDL_NAME(XDGASetClientVersion)( + Display *dpy +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASetClientVersionReq *req; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGASetClientVersion, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASetClientVersion; + req->major = XDGA_MAJOR_VERSION; + req->minor = XDGA_MINOR_VERSION; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XDGAOpenFramebuffer)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAOpenFramebufferReply rep; + xXDGAOpenFramebufferReq *req; + char *deviceName = NULL; + Bool ret; + + XDGACheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XDGAOpenFramebuffer, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAOpenFramebuffer; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if(rep.length) { + deviceName = Xmalloc(rep.length << 2); + _XRead(dpy, deviceName, rep.length << 2); + } + + ret = SDL_NAME(XDGAMapFramebuffer)(screen, deviceName, + (unsigned char*)(long)rep.mem1, + rep.size, rep.offset, rep.extra); + + if(deviceName) + Xfree(deviceName); + + UnlockDisplay(dpy); + SyncHandle(); + return ret; +} + +void SDL_NAME(XDGACloseFramebuffer)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACloseFramebufferReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + SDL_NAME(XDGAUnmapFramebuffer)(screen); + + LockDisplay(dpy); + GetReq(XDGACloseFramebuffer, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACloseFramebuffer; + req->screen = screen; + UnlockDisplay(dpy); + SyncHandle(); +} + + + +SDL_NAME(XDGAMode)* SDL_NAME(XDGAQueryModes)( + Display *dpy, + int screen, + int *num +){ + XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy); + xXDGAQueryModesReply rep; + xXDGAQueryModesReq *req; + SDL_NAME(XDGAMode) *modes = NULL; + + *num = 0; + + XDGACheckExtension (dpy, dinfo, NULL); + + LockDisplay(dpy); + GetReq(XDGAQueryModes, req); + req->reqType = dinfo->codes->major_opcode; + req->dgaReqType = X_XDGAQueryModes; + req->screen = screen; + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + if(rep.length) { + xXDGAModeInfo info; + int i, size; + char *offset; + + size = rep.length << 2; + size -= rep.number * sz_xXDGAModeInfo; /* find text size */ + modes = (SDL_NAME(XDGAMode)*)Xmalloc((rep.number * sizeof(SDL_NAME(XDGAMode))) + size); + offset = (char*)(&modes[rep.number]); /* start of text */ + + + if(modes) { + for(i = 0; i < rep.number; i++) { + _XRead(dpy, (char*)(&info), sz_xXDGAModeInfo); + + modes[i].num = info.num; + modes[i].verticalRefresh = + (float)info.vsync_num / (float)info.vsync_den; + modes[i].flags = info.flags; + modes[i].imageWidth = info.image_width; + modes[i].imageHeight = info.image_height; + modes[i].pixmapWidth = info.pixmap_width; + modes[i].pixmapHeight = info.pixmap_height; + modes[i].bytesPerScanline = info.bytes_per_scanline; + modes[i].byteOrder = info.byte_order; + modes[i].depth = info.depth; + modes[i].bitsPerPixel = info.bpp; + modes[i].redMask = info.red_mask; + modes[i].greenMask = info.green_mask; + modes[i].blueMask = info.blue_mask; + modes[i].visualClass = info.visual_class; + modes[i].viewportWidth = info.viewport_width; + modes[i].viewportHeight = info.viewport_height; + modes[i].xViewportStep = info.viewport_xstep; + modes[i].yViewportStep = info.viewport_ystep; + modes[i].maxViewportX = info.viewport_xmax; + modes[i].maxViewportY = info.viewport_ymax; + modes[i].viewportFlags = info.viewport_flags; + modes[i].reserved1 = info.reserved1; + modes[i].reserved2 = info.reserved2; + + _XRead(dpy, offset, info.name_size); + modes[i].name = offset; + offset += info.name_size; + } + *num = rep.number; + } else + _XEatData(dpy, rep.length << 2); + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + return modes; +} + + +SDL_NAME(XDGADevice) * +SDL_NAME(XDGASetMode)( + Display *dpy, + int screen, + int mode +){ + XExtDisplayInfo *dinfo = SDL_NAME(xdga_find_display) (dpy); + xXDGASetModeReply rep; + xXDGASetModeReq *req; + SDL_NAME(XDGADevice) *dev = NULL; + Pixmap pid; + + XDGACheckExtension (dpy, dinfo, NULL); + + LockDisplay(dpy); + GetReq(XDGASetMode, req); + req->reqType = dinfo->codes->major_opcode; + req->dgaReqType = X_XDGASetMode; + req->screen = screen; + req->mode = mode; + req->pid = pid = XAllocID(dpy); + + if (_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + if(rep.length) { + xXDGAModeInfo info; + int size; + + size = rep.length << 2; + size -= sz_xXDGAModeInfo; /* get text size */ + + dev = (SDL_NAME(XDGADevice)*)Xmalloc(sizeof(SDL_NAME(XDGADevice)) + size); + + if(dev) { + _XRead(dpy, (char*)(&info), sz_xXDGAModeInfo); + + dev->mode.num = info.num; + dev->mode.verticalRefresh = + (float)info.vsync_num / (float)info.vsync_den; + dev->mode.flags = info.flags; + dev->mode.imageWidth = info.image_width; + dev->mode.imageHeight = info.image_height; + dev->mode.pixmapWidth = info.pixmap_width; + dev->mode.pixmapHeight = info.pixmap_height; + dev->mode.bytesPerScanline = info.bytes_per_scanline; + dev->mode.byteOrder = info.byte_order; + dev->mode.depth = info.depth; + dev->mode.bitsPerPixel = info.bpp; + dev->mode.redMask = info.red_mask; + dev->mode.greenMask = info.green_mask; + dev->mode.blueMask = info.blue_mask; + dev->mode.visualClass = info.visual_class; + dev->mode.viewportWidth = info.viewport_width; + dev->mode.viewportHeight = info.viewport_height; + dev->mode.xViewportStep = info.viewport_xstep; + dev->mode.yViewportStep = info.viewport_ystep; + dev->mode.maxViewportX = info.viewport_xmax; + dev->mode.maxViewportY = info.viewport_ymax; + dev->mode.viewportFlags = info.viewport_flags; + dev->mode.reserved1 = info.reserved1; + dev->mode.reserved2 = info.reserved2; + + dev->mode.name = (char*)(&dev[1]); + _XRead(dpy, dev->mode.name, info.name_size); + + dev->pixmap = (rep.flags & XDGAPixmap) ? pid : 0; + dev->data = SDL_NAME(XDGAGetMappedMemory)(screen); + + if(dev->data) + dev->data += rep.offset; + } + /* not sure what to do if the allocation fails */ + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + return dev; +} + + +void SDL_NAME(XDGASetViewport)( + Display *dpy, + int screen, + int x, + int y, + int flags +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASetViewportReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASetViewport, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASetViewport; + req->screen = screen; + req->x = x; + req->y = y; + req->flags = flags; + UnlockDisplay(dpy); + SyncHandle(); +} + + +void SDL_NAME(XDGAInstallColormap)( + Display *dpy, + int screen, + Colormap cmap +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAInstallColormapReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAInstallColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAInstallColormap; + req->screen = screen; + req->cmap = cmap; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGASelectInput)( + Display *dpy, + int screen, + long mask +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASelectInputReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASelectInput, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASelectInput; + req->screen = screen; + req->mask = mask; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGAFillRectangle)( + Display *dpy, + int screen, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long color +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAFillRectangleReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAFillRectangle, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAFillRectangle; + req->screen = screen; + req->x = x; + req->y = y; + req->width = width; + req->height = height; + req->color = color; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGACopyArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACopyAreaReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGACopyArea, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACopyArea; + req->screen = screen; + req->srcx = srcx; + req->srcy = srcy; + req->width = width; + req->height = height; + req->dstx = dstx; + req->dsty = dsty; + UnlockDisplay(dpy); + SyncHandle(); +} + +void SDL_NAME(XDGACopyTransparentArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty, + unsigned long key +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACopyTransparentAreaReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGACopyTransparentArea, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACopyTransparentArea; + req->screen = screen; + req->srcx = srcx; + req->srcy = srcy; + req->width = width; + req->height = height; + req->dstx = dstx; + req->dsty = dsty; + req->key = key; + UnlockDisplay(dpy); + SyncHandle(); +} + + +int SDL_NAME(XDGAGetViewportStatus)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAGetViewportStatusReply rep; + xXDGAGetViewportStatusReq *req; + int status = 0; + + XDGACheckExtension (dpy, info, 0); + + LockDisplay(dpy); + GetReq(XDGAGetViewportStatus, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAGetViewportStatus; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) + status = rep.status; + UnlockDisplay(dpy); + SyncHandle(); + return status; +} + +void SDL_NAME(XDGASync)( + Display *dpy, + int screen +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGASyncReply rep; + xXDGASyncReq *req; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGASync, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGASync; + req->screen = screen; + _XReply(dpy, (xReply *)&rep, 0, xFalse); + UnlockDisplay(dpy); + SyncHandle(); +} + + +void SDL_NAME(XDGAChangePixmapMode)( + Display *dpy, + int screen, + int *x, + int *y, + int mode +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGAChangePixmapModeReq *req; + xXDGAChangePixmapModeReply rep; + + XextSimpleCheckExtension (dpy, info, SDL_NAME(xdga_extension_name)); + + LockDisplay(dpy); + GetReq(XDGAChangePixmapMode, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGAChangePixmapMode; + req->screen = screen; + req->x = *x; + req->y = *y; + req->flags = mode; + _XReply(dpy, (xReply *)&rep, 0, xFalse); + *x = rep.x; + *y = rep.y; + UnlockDisplay(dpy); + SyncHandle(); +} + +Colormap SDL_NAME(XDGACreateColormap)( + Display *dpy, + int screen, + SDL_NAME(XDGADevice) *dev, + int alloc +){ + XExtDisplayInfo *info = SDL_NAME(xdga_find_display) (dpy); + xXDGACreateColormapReq *req; + Colormap cid; + + XDGACheckExtension (dpy, info, -1); + + LockDisplay(dpy); + GetReq(XDGACreateColormap, req); + req->reqType = info->codes->major_opcode; + req->dgaReqType = X_XDGACreateColormap; + req->screen = screen; + req->mode = dev->mode.num; + req->alloc = alloc; + cid = req->id = XAllocID(dpy); + UnlockDisplay(dpy); + SyncHandle(); + + return cid; +} + + +void SDL_NAME(XDGAKeyEventToXKeyEvent)( + SDL_NAME(XDGAKeyEvent)* dk, + XKeyEvent* xk +){ + xk->type = dk->type; + xk->serial = dk->serial; + xk->send_event = False; + xk->display = dk->display; + xk->window = RootWindow(dk->display, dk->screen); + xk->root = xk->window; + xk->subwindow = None; + xk->time = dk->time; + xk->x = xk->y = xk->x_root = xk->y_root = 0; + xk->state = dk->state; + xk->keycode = dk->keycode; + xk->same_screen = True; +} + +#include <X11/Xmd.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#if defined(ISC) +# define HAS_SVR3_MMAP +# include <sys/types.h> +# include <errno.h> + +# include <sys/at_ansi.h> +# include <sys/kd.h> + +# include <sys/sysmacros.h> +# include <sys/immu.h> +# include <sys/region.h> + +# include <sys/mmap.h> +#else +# if !defined(Lynx) +# if !defined(__EMX__) +# include <sys/mman.h> +# endif +# else +# include <sys/types.h> +# include <errno.h> +# include <smem.h> +# endif +#endif +#include <sys/wait.h> +#include <signal.h> +#include <unistd.h> + +#if defined(SVR4) && !defined(sun) && !defined(SCO325) +#define DEV_MEM "/dev/pmem" +#elif defined(SVR4) && defined(sun) +#define DEV_MEM "/dev/xsvc" +#else +#define DEV_MEM "/dev/mem" +#endif + + + +typedef struct _DGAMapRec{ + unsigned char *physical; + unsigned char *virtual; + CARD32 size; + int fd; + int screen; + struct _DGAMapRec *next; +} DGAMapRec, *DGAMapPtr; + +static Bool +DGAMapPhysical(int, char*, unsigned char*, CARD32, CARD32, CARD32, DGAMapPtr); +static void DGAUnmapPhysical(DGAMapPtr); + +static DGAMapPtr _Maps = NULL; + + +unsigned char* +SDL_NAME(XDGAGetMappedMemory)(int screen) +{ + DGAMapPtr pMap = _Maps; + unsigned char *pntr = NULL; + + while(pMap != NULL) { + if(pMap->screen == screen) { + pntr = pMap->virtual; + break; + } + pMap = pMap->next; + } + + return pntr; +} + +Bool +SDL_NAME(XDGAMapFramebuffer)( + int screen, + char *name, /* optional device name */ + unsigned char* base, /* physical memory */ + CARD32 size, /* size */ + CARD32 offset, /* optional offset */ + CARD32 extra /* optional extra data */ +){ + DGAMapPtr pMap = _Maps; + Bool result; + + /* is it already mapped ? */ + while(pMap != NULL) { + if(pMap->screen == screen) + return True; + pMap = pMap->next; + } + + if(extra & XDGANeedRoot) { + /* we should probably check if we have root permissions and + return False here */ + + } + + pMap = (DGAMapPtr)Xmalloc(sizeof(DGAMapRec)); + + result = DGAMapPhysical(screen, name, base, size, offset, extra, pMap); + + if(result) { + pMap->next = _Maps; + _Maps = pMap; + } else + Xfree(pMap); + + return result; +} + +void +SDL_NAME(XDGAUnmapFramebuffer)(int screen) +{ + DGAMapPtr pMap = _Maps; + DGAMapPtr pPrev = NULL; + + /* is it already mapped */ + while(pMap != NULL) { + if(pMap->screen == screen) + break; + pPrev = pMap; + pMap = pMap->next; + } + + if(!pMap) + return; + + DGAUnmapPhysical(pMap); + + if(!pPrev) + _Maps = pMap->next; + else + pPrev->next = pMap->next; + + Xfree(pMap); +} + + +static Bool +DGAMapPhysical( + int screen, + char *name, /* optional device name */ + unsigned char* base, /* physical memory */ + CARD32 size, /* size */ + CARD32 offset, /* optional offset */ + CARD32 extra, /* optional extra data */ + DGAMapPtr pMap +) { +#if defined(ISC) && defined(HAS_SVR3_MMAP) + struct kd_memloc mloc; +#elif defined(__EMX__) + APIRET rc; + ULONG action; + HFILE hfd; +#endif + + base += offset; + + pMap->screen = screen; + pMap->physical = base; + pMap->size = size; + +#if defined(ISC) && defined(HAS_SVR3_MMAP) + if ((pMap->fd = open("/dev/mmap", O_RDWR)) < 0) + return False; + mloc.vaddr = (char *)0; + mloc.physaddr = (char *)base; + mloc.length = size; + mloc.ioflg=1; + + if ((pMap->virtual = (void *)ioctl(pMap->fd, MAP, &mloc)) == (void *)-1) + return False; +#elif defined (__EMX__) + /* + * Dragon warning here! /dev/pmap$ is never closed, except on progam exit. + * Consecutive calling of this routine will make PMAP$ driver run out + * of memory handles. Some umap/close mechanism should be provided + */ + + rc = DosOpen("/dev/pmap$", &hfd, &action, 0, FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE, (PEAOP2)NULL); + if (rc != 0) + return False; + { + struct map_ioctl { + union { + ULONG phys; + void* user; + } a; + ULONG size; + } pmap,dmap; + ULONG plen,dlen; +#define XFREE86_PMAP 0x76 +#define PMAP_MAP 0x44 + + pmap.a.phys = base; + pmap.size = size; + rc = DosDevIOCtl(hfd, XFREE86_PMAP, PMAP_MAP, + (PULONG)&pmap, sizeof(pmap), &plen, + (PULONG)&dmap, sizeof(dmap), &dlen); + if (rc == 0) { + pMap->virtual = dmap.a.user; + } + } + if (rc != 0) + return False; +#elif defined (Lynx) + pMap->virtual = smem_create("XF86DGA", (char*)base, size, SM_READ|SM_WRITE); +#else +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + if (!name) + name = DEV_MEM; + if ((pMap->fd = open(name, O_RDWR)) < 0) +#if defined(ENABLE_FBCON) + { /* /dev/fb0 fallback added by Sam Lantinga <hercules@lokigames.com> */ + /* Try to fall back to /dev/fb on Linux - FIXME: verify the device */ + struct fb_fix_screeninfo finfo; + + if ((pMap->fd = open("/dev/fb0", O_RDWR)) < 0) { + return False; + } + /* The useable framebuffer console memory may not be the whole + framebuffer that X has access to. :-( + */ + if ( ioctl(pMap->fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + close(pMap->fd); + return False; + } + /* Warning: On PPC, the size and virtual need to be offset by: + (((long)finfo.smem_start) - + (((long)finfo.smem_start)&~(PAGE_SIZE-1))) + */ + base = 0; + size = pMap->size = finfo.smem_len; + } +#else + return False; +#endif + pMap->virtual = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, pMap->fd, (off_t)((size_t)base)); + if (pMap->virtual == (void *)-1) + return False; +#endif + +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + mprotect(pMap->virtual, size, PROT_READ | PROT_WRITE); +#endif + + return True; +} + + + +static void +DGAUnmapPhysical(DGAMapPtr pMap) +{ +#if !defined(ISC) && !defined(HAS_SVR3_MMAP) && !defined(Lynx) \ + && !defined(__EMX__) + mprotect(pMap->virtual,pMap->size, PROT_READ); +#elif defined(Lynx) + /* XXX this doesn't allow enable after disable */ + smem_create(NULL, pMap->virtual, pMap->size, SM_DETACH); + smem_remove("XF86DGA"); +#endif + + + /* We need to unmap and close too !!!!!!!!!!*/ +} diff --git a/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c b/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c new file mode 100644 index 0000000..5cb2190 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/Xxf86vm/XF86VMode.c @@ -0,0 +1,1226 @@ +/* $XConsortium: XF86VMode.c /main/2 1995/11/14 18:17:58 kaleb $ */ +/* $XFree86: xc/lib/Xxf86vm/XF86VMode.c,v 3.32 2001/07/25 15:04:54 dawes Exp $ */ +/* + +Copyright (c) 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY. + +*/ +/* $XConsortium: XF86VMode.c /main/4 1996/01/16 07:52:25 kaleb CHECKEDOUT $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD */ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifndef XBUILD_IN_CLIENT +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif +#include "../extensions/xf86vmstr.h" +#include "../extensions/Xext.h" +#include "../extensions/extutil.h" +#else +#include "include/extensions/xf86vmstr.h" +#include "include/extensions/Xext.h" +#include "include/extensions/extutil.h" +#endif + +#ifdef DEBUG +#include <stdio.h> +#endif + +#ifndef MODE_BAD +#define MODE_BAD 255 +#endif + +static XExtensionInfo _xf86vidmode_info_data; +static XExtensionInfo *xf86vidmode_info = &_xf86vidmode_info_data; +static char *xf86vidmode_extension_name = XF86VIDMODENAME; + +#define XF86VidModeCheckExtension(dpy,i,val) \ + XextCheckExtension (dpy, i, xf86vidmode_extension_name, val) + +/***************************************************************************** + * * + * private utility routines * + * * + *****************************************************************************/ + +static XEXT_CLOSE_DISPLAY_PROTO(close_display); +static /* const */ XExtensionHooks xf86vidmode_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + close_display, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (find_display, xf86vidmode_info, + xf86vidmode_extension_name, + &xf86vidmode_extension_hooks, + 0, NULL) + +static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xf86vidmode_info) + + +/***************************************************************************** + * * + * public XFree86-VidMode Extension routines * + * * + *****************************************************************************/ + +Bool +SDL_NAME(XF86VidModeQueryExtension) (dpy, event_basep, error_basep) + Display *dpy; + int *event_basep, *error_basep; +{ + XExtDisplayInfo *info = find_display (dpy); + + if (XextHasExtension(info)) { + *event_basep = info->codes->first_event; + *error_basep = info->codes->first_error; + return True; + } else { + return False; + } +} + +Bool +SDL_NAME(XF86VidModeQueryVersion)(dpy, majorVersion, minorVersion) + Display* dpy; + int* majorVersion; + int* minorVersion; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeQueryVersionReply rep; + xXF86VidModeQueryVersionReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeQueryVersion, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeQueryVersion; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *majorVersion = rep.majorVersion; + *minorVersion = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + if (*majorVersion >= 2) + SDL_NAME(XF86VidModeSetClientVersion)(dpy); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetClientVersion)(Display *dpy) +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86VidModeSetClientVersionReq *req; + + XF86VidModeCheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetClientVersion, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetClientVersion; + req->major = XF86VIDMODE_MAJOR_VERSION; + req->minor = XF86VIDMODE_MINOR_VERSION; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetGamma)(Display *dpy, int screen, SDL_NAME(XF86VidModeGamma) *Gamma) +{ + XExtDisplayInfo *info = find_display(dpy); + xXF86VidModeSetGammaReq *req; + + XF86VidModeCheckExtension(dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetGamma, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetGamma; + req->screen = screen; + req->red = (CARD32)(Gamma->red * 10000.); + req->green = (CARD32)(Gamma->green * 10000.); + req->blue = (CARD32)(Gamma->blue * 10000.); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetGamma)(Display *dpy, int screen, SDL_NAME(XF86VidModeGamma) *Gamma) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaReply rep; + xXF86VidModeGetGammaReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGamma, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGamma; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + Gamma->red = ((float)rep.red) / 10000.; + Gamma->green = ((float)rep.green) / 10000.; + Gamma->blue = ((float)rep.blue) / 10000.; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetModeLine)(dpy, screen, dotclock, modeline) + Display* dpy; + int screen; + int* dotclock; + SDL_NAME(XF86VidModeModeLine)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetModeLineReply rep; + xXF86OldVidModeGetModeLineReply oldrep; + xXF86VidModeGetModeLineReq *req; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, False); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + GetReq(XF86VidModeGetModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetModeLine; + req->screen = screen; + + if (majorVersion < 2) { + if (!_XReply(dpy, (xReply *)&oldrep, + (SIZEOF(xXF86OldVidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *dotclock = oldrep.dotclock; + modeline->hdisplay = oldrep.hdisplay; + modeline->hsyncstart = oldrep.hsyncstart; + modeline->hsyncend = oldrep.hsyncend; + modeline->htotal = oldrep.htotal; + modeline->hskew = 0; + modeline->vdisplay = oldrep.vdisplay; + modeline->vsyncstart = oldrep.vsyncstart; + modeline->vsyncend = oldrep.vsyncend; + modeline->vtotal = oldrep.vtotal; + modeline->flags = oldrep.flags; + modeline->privsize = oldrep.privsize; + } else { + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetModeLineReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *dotclock = rep.dotclock; + modeline->hdisplay = rep.hdisplay; + modeline->hsyncstart = rep.hsyncstart; + modeline->hsyncend = rep.hsyncend; + modeline->htotal = rep.htotal; + modeline->hskew = rep.hskew; + modeline->vdisplay = rep.vdisplay; + modeline->vsyncstart = rep.vsyncstart; + modeline->vsyncend = rep.vsyncend; + modeline->vtotal = rep.vtotal; + modeline->flags = rep.flags; + modeline->privsize = rep.privsize; + } + + if (modeline->privsize > 0) { + if (!(modeline->private = Xcalloc(modeline->privsize, sizeof(INT32)))) { + _XEatData(dpy, (modeline->privsize) * sizeof(INT32)); + Xfree(modeline->private); + return False; + } + _XRead(dpy, (char*)modeline->private, modeline->privsize * sizeof(INT32)); + } else { + modeline->private = NULL; + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetAllModeLines)(dpy, screen, modecount, modelinesPtr) + Display* dpy; + int screen; + int* modecount; + SDL_NAME(XF86VidModeModeInfo) ***modelinesPtr; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetAllModeLinesReply rep; + xXF86VidModeGetAllModeLinesReq *req; + SDL_NAME(XF86VidModeModeInfo) *mdinfptr, **modelines; + xXF86VidModeModeInfo xmdline; + xXF86OldVidModeModeInfo oldxmdline; + int i; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (the .private field wasn't being passed over the wire). + * Check the server's version, and accept the old format if appropriate. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeGetAllModeLines: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + + LockDisplay(dpy); + GetReq(XF86VidModeGetAllModeLines, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetAllModeLines; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetAllModeLinesReply) - SIZEOF(xReply)) >> 2, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *modecount = rep.modecount; + + if (!(modelines = (SDL_NAME(XF86VidModeModeInfo) **) Xcalloc(rep.modecount, + sizeof(SDL_NAME(XF86VidModeModeInfo) *) + +sizeof(SDL_NAME(XF86VidModeModeInfo))))) { + if (majorVersion < 2) + _XEatData(dpy, (rep.modecount) * sizeof(xXF86OldVidModeModeInfo)); + else + _XEatData(dpy, (rep.modecount) * sizeof(xXF86VidModeModeInfo)); + Xfree(modelines); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + mdinfptr = (SDL_NAME(XF86VidModeModeInfo) *) ( + (char *) modelines + + rep.modecount*sizeof(SDL_NAME(XF86VidModeModeInfo) *) + ); + + for (i = 0; i < rep.modecount; i++) { + modelines[i] = mdinfptr++; + if (majorVersion < 2) { + _XRead(dpy, (char*)&oldxmdline, sizeof(xXF86OldVidModeModeInfo)); + modelines[i]->dotclock = oldxmdline.dotclock; + modelines[i]->hdisplay = oldxmdline.hdisplay; + modelines[i]->hsyncstart = oldxmdline.hsyncstart; + modelines[i]->hsyncend = oldxmdline.hsyncend; + modelines[i]->htotal = oldxmdline.htotal; + modelines[i]->hskew = 0; + modelines[i]->vdisplay = oldxmdline.vdisplay; + modelines[i]->vsyncstart = oldxmdline.vsyncstart; + modelines[i]->vsyncend = oldxmdline.vsyncend; + modelines[i]->vtotal = oldxmdline.vtotal; + modelines[i]->flags = oldxmdline.flags; + if (protocolBug) { + modelines[i]->privsize = 0; + modelines[i]->private = NULL; + } else { + modelines[i]->privsize = oldxmdline.privsize; + if (oldxmdline.privsize > 0) { + if (!(modelines[i]->private = + Xcalloc(oldxmdline.privsize, sizeof(INT32)))) { + _XEatData(dpy, (oldxmdline.privsize) * sizeof(INT32)); + Xfree(modelines[i]->private); + } else { + _XRead(dpy, (char*)modelines[i]->private, + oldxmdline.privsize * sizeof(INT32)); + } + } else { + modelines[i]->private = NULL; + } + } + } else { + _XRead(dpy, (char*)&xmdline, sizeof(xXF86VidModeModeInfo)); + modelines[i]->dotclock = xmdline.dotclock; + modelines[i]->hdisplay = xmdline.hdisplay; + modelines[i]->hsyncstart = xmdline.hsyncstart; + modelines[i]->hsyncend = xmdline.hsyncend; + modelines[i]->htotal = xmdline.htotal; + modelines[i]->hskew = xmdline.hskew; + modelines[i]->vdisplay = xmdline.vdisplay; + modelines[i]->vsyncstart = xmdline.vsyncstart; + modelines[i]->vsyncend = xmdline.vsyncend; + modelines[i]->vtotal = xmdline.vtotal; + modelines[i]->flags = xmdline.flags; + if (protocolBug) { + modelines[i]->privsize = 0; + modelines[i]->private = NULL; + } else { + modelines[i]->privsize = xmdline.privsize; + if (xmdline.privsize > 0) { + if (!(modelines[i]->private = + Xcalloc(xmdline.privsize, sizeof(INT32)))) { + _XEatData(dpy, (xmdline.privsize) * sizeof(INT32)); + Xfree(modelines[i]->private); + } else { + _XRead(dpy, (char*)modelines[i]->private, + xmdline.privsize * sizeof(INT32)); + } + } else { + modelines[i]->private = NULL; + } + } + } + } + *modelinesPtr = modelines; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +/* + * GetReq replacement for use with VidMode protocols earlier than 2.0 + */ +#if !defined(UNIXCPP) || defined(ANSICPP) +#define GetOldReq(name, oldname, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x##oldname##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x##oldname##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = X_##name;\ + req->length = (SIZEOF(x##oldname##Req))>>2;\ + dpy->bufptr += SIZEOF(x##oldname##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define GetOldReq(name, oldname, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x/**/oldname/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x/**/oldname/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = X_/**/name;\ + req->length = (SIZEOF(x/**/oldname/**/Req))>>2;\ + dpy->bufptr += SIZEOF(x/**/oldname/**/Req);\ + dpy->request++ +#endif + +Bool +SDL_NAME(XF86VidModeAddModeLine) (dpy, screen, newmodeline, aftermodeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* newmodeline; + SDL_NAME(XF86VidModeModeInfo)* aftermodeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeAddModeLineReq *req; + xXF86OldVidModeAddModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, False); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeAddModeLine, XF86OldVidModeAddModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeAddModeLine; + oldreq->screen = screen; + oldreq->dotclock = newmodeline->dotclock; + oldreq->hdisplay = newmodeline->hdisplay; + oldreq->hsyncstart = newmodeline->hsyncstart; + oldreq->hsyncend = newmodeline->hsyncend; + oldreq->htotal = newmodeline->htotal; + oldreq->vdisplay = newmodeline->vdisplay; + oldreq->vsyncstart = newmodeline->vsyncstart; + oldreq->vsyncend = newmodeline->vsyncend; + oldreq->vtotal = newmodeline->vtotal; + oldreq->flags = newmodeline->flags; + oldreq->privsize = newmodeline->privsize; + if (aftermodeline != NULL) { + oldreq->after_dotclock = aftermodeline->dotclock; + oldreq->after_hdisplay = aftermodeline->hdisplay; + oldreq->after_hsyncstart = aftermodeline->hsyncstart; + oldreq->after_hsyncend = aftermodeline->hsyncend; + oldreq->after_htotal = aftermodeline->htotal; + oldreq->after_vdisplay = aftermodeline->vdisplay; + oldreq->after_vsyncstart = aftermodeline->vsyncstart; + oldreq->after_vsyncend = aftermodeline->vsyncend; + oldreq->after_vtotal = aftermodeline->vtotal; + oldreq->after_flags = aftermodeline->flags; + } else { + oldreq->after_dotclock = 0; + oldreq->after_hdisplay = 0; + oldreq->after_hsyncstart = 0; + oldreq->after_hsyncend = 0; + oldreq->after_htotal = 0; + oldreq->after_vdisplay = 0; + oldreq->after_vsyncstart = 0; + oldreq->after_vsyncend = 0; + oldreq->after_vtotal = 0; + oldreq->after_flags = 0; + } + if (newmodeline->privsize) { + oldreq->length += newmodeline->privsize; + Data32(dpy, (long *) newmodeline->private, + newmodeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeAddModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeAddModeLine; + req->screen = screen; + req->dotclock = newmodeline->dotclock; + req->hdisplay = newmodeline->hdisplay; + req->hsyncstart = newmodeline->hsyncstart; + req->hsyncend = newmodeline->hsyncend; + req->htotal = newmodeline->htotal; + req->hskew = newmodeline->hskew; + req->vdisplay = newmodeline->vdisplay; + req->vsyncstart = newmodeline->vsyncstart; + req->vsyncend = newmodeline->vsyncend; + req->vtotal = newmodeline->vtotal; + req->flags = newmodeline->flags; + req->privsize = newmodeline->privsize; + if (aftermodeline != NULL) { + req->after_dotclock = aftermodeline->dotclock; + req->after_hdisplay = aftermodeline->hdisplay; + req->after_hsyncstart = aftermodeline->hsyncstart; + req->after_hsyncend = aftermodeline->hsyncend; + req->after_htotal = aftermodeline->htotal; + req->after_hskew = aftermodeline->hskew; + req->after_vdisplay = aftermodeline->vdisplay; + req->after_vsyncstart = aftermodeline->vsyncstart; + req->after_vsyncend = aftermodeline->vsyncend; + req->after_vtotal = aftermodeline->vtotal; + req->after_flags = aftermodeline->flags; + } else { + req->after_dotclock = 0; + req->after_hdisplay = 0; + req->after_hsyncstart = 0; + req->after_hsyncend = 0; + req->after_htotal = 0; + req->after_hskew = 0; + req->after_vdisplay = 0; + req->after_vsyncstart = 0; + req->after_vsyncend = 0; + req->after_vtotal = 0; + req->after_flags = 0; + } + if (newmodeline->privsize) { + req->length += newmodeline->privsize; + Data32(dpy, (long *) newmodeline->private, + newmodeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeDeleteModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeDeleteModeLineReq *req; + xXF86OldVidModeDeleteModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeDeleteModeLine, XF86OldVidModeDeleteModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeDeleteModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeDeleteModeLine; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeModModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeLine)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeModModeLineReq *req; + xXF86OldVidModeModModeLineReq *oldreq; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeModModeLine, XF86OldVidModeModModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeModModeLine; + oldreq->screen = screen; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeModModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeModModeLine; + req->screen = screen; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Status +SDL_NAME(XF86VidModeValidateModeLine) (dpy, screen, modeline) + Display *dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeValidateModeLineReq *req; + xXF86OldVidModeValidateModeLineReq *oldreq; + xXF86VidModeValidateModeLineReply rep; + int majorVersion, minorVersion; + + XF86VidModeCheckExtension (dpy, info, 0); + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + + LockDisplay(dpy); + + if (majorVersion < 2) { + GetOldReq(XF86VidModeValidateModeLine, XF86OldVidModeValidateModeLine, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeValidateModeLine; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } else { + GetReq(XF86VidModeValidateModeLine, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeValidateModeLine; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return MODE_BAD; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.status; +} + +Bool +SDL_NAME(XF86VidModeSwitchMode)(dpy, screen, zoom) + Display* dpy; + int screen; + int zoom; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSwitchModeReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSwitchMode, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSwitchMode; + req->screen = screen; + req->zoom = zoom; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSwitchToMode)(dpy, screen, modeline) + Display* dpy; + int screen; + SDL_NAME(XF86VidModeModeInfo)* modeline; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSwitchToModeReq *req; + xXF86OldVidModeSwitchToModeReq *oldreq; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (the .private field wasn't expected to be sent over + * the wire). Check the server's version, and accept the old format + * if appropriate. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeSwitchToMode: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + + LockDisplay(dpy); + if (majorVersion < 2) { + GetOldReq(XF86VidModeSwitchToMode, XF86OldVidModeSwitchToMode, oldreq); + oldreq->reqType = info->codes->major_opcode; + oldreq->xf86vidmodeReqType = X_XF86VidModeSwitchToMode; + oldreq->screen = screen; + oldreq->dotclock = modeline->dotclock; + oldreq->hdisplay = modeline->hdisplay; + oldreq->hsyncstart = modeline->hsyncstart; + oldreq->hsyncend = modeline->hsyncend; + oldreq->htotal = modeline->htotal; + oldreq->vdisplay = modeline->vdisplay; + oldreq->vsyncstart = modeline->vsyncstart; + oldreq->vsyncend = modeline->vsyncend; + oldreq->vtotal = modeline->vtotal; + oldreq->flags = modeline->flags; + if (protocolBug) { + oldreq->privsize = 0; + } else { + oldreq->privsize = modeline->privsize; + if (modeline->privsize) { + oldreq->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + } else { + GetReq(XF86VidModeSwitchToMode, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSwitchToMode; + req->screen = screen; + req->dotclock = modeline->dotclock; + req->hdisplay = modeline->hdisplay; + req->hsyncstart = modeline->hsyncstart; + req->hsyncend = modeline->hsyncend; + req->htotal = modeline->htotal; + req->hskew = modeline->hskew; + req->vdisplay = modeline->vdisplay; + req->vsyncstart = modeline->vsyncstart; + req->vsyncend = modeline->vsyncend; + req->vtotal = modeline->vtotal; + req->flags = modeline->flags; + if (protocolBug) { + req->privsize = 0; + } else { + req->privsize = modeline->privsize; + if (modeline->privsize) { + req->length += modeline->privsize; + Data32(dpy, (long *) modeline->private, + modeline->privsize * sizeof(INT32)); + } + } + } + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeLockModeSwitch)(dpy, screen, lock) + Display* dpy; + int screen; + int lock; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeLockModeSwitchReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeLockModeSwitch, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeLockModeSwitch; + req->screen = screen; + req->lock = lock; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetMonitor)(dpy, screen, monitor) + Display* dpy; + int screen; + SDL_NAME(XF86VidModeMonitor)* monitor; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetMonitorReply rep; + xXF86VidModeGetMonitorReq *req; + CARD32 syncrange; + int i; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetMonitor, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetMonitor; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + monitor->nhsync = rep.nhsync; + monitor->nvsync = rep.nvsync; +#if 0 + monitor->bandwidth = (float)rep.bandwidth / 1e6; +#endif + if (rep.vendorLength) { + if (!(monitor->vendor = (char *)Xcalloc(rep.vendorLength + 1, 1))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + } else { + monitor->vendor = NULL; + } + if (rep.modelLength) { + if (!(monitor->model = Xcalloc(rep.modelLength + 1, 1))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + if (monitor->vendor) + Xfree(monitor->vendor); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + } else { + monitor->model = NULL; + } + if (!(monitor->hsync = Xcalloc(rep.nhsync, sizeof(SDL_NAME(XF86VidModeSyncRange))))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + + if (monitor->vendor) + Xfree(monitor->vendor); + if (monitor->model) + Xfree(monitor->model); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (!(monitor->vsync = Xcalloc(rep.nvsync, sizeof(SDL_NAME(XF86VidModeSyncRange))))) { + _XEatData(dpy, (rep.nhsync + rep.nvsync) * 4 + + ((rep.vendorLength+3) & ~3) + ((rep.modelLength+3) & ~3)); + if (monitor->vendor) + Xfree(monitor->vendor); + if (monitor->model) + Xfree(monitor->model); + Xfree(monitor->hsync); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + for (i = 0; i < rep.nhsync; i++) { + _XRead(dpy, (char *)&syncrange, 4); + monitor->hsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0; + monitor->hsync[i].hi = (float)(syncrange >> 16) / 100.0; + } + for (i = 0; i < rep.nvsync; i++) { + _XRead(dpy, (char *)&syncrange, 4); + monitor->vsync[i].lo = (float)(syncrange & 0xFFFF) / 100.0; + monitor->vsync[i].hi = (float)(syncrange >> 16) / 100.0; + } + if (rep.vendorLength) + _XReadPad(dpy, monitor->vendor, rep.vendorLength); + else + monitor->vendor = ""; + if (rep.modelLength) + _XReadPad(dpy, monitor->model, rep.modelLength); + else + monitor->model = ""; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetViewPort)(dpy, screen, x, y) + Display* dpy; + int screen; + int *x, *y; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetViewPortReply rep; + xXF86VidModeGetViewPortReq *req; + int majorVersion, minorVersion; + Bool protocolBug = False; + + XF86VidModeCheckExtension (dpy, info, False); + + /* + * Note: There was a bug in the protocol implementation in versions + * 0.x with x < 8 (no reply was sent, so the client would hang) + * Check the server's version, and don't wait for a reply with older + * versions. + */ + + SDL_NAME(XF86VidModeQueryVersion)(dpy, &majorVersion, &minorVersion); + if (majorVersion == 0 && minorVersion < 8) { + protocolBug = True; +#ifdef DEBUG + fprintf(stderr, "XF86VidModeGetViewPort: Warning: Xserver is" + "running an old version (%d.%d)\n", majorVersion, + minorVersion); +#endif + } + LockDisplay(dpy); + GetReq(XF86VidModeGetViewPort, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetViewPort; + req->screen = screen; + if (protocolBug) { + *x = 0; + *y = 0; + } else { + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *x = rep.x; + *y = rep.y; + } + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetViewPort)(dpy, screen, x, y) + Display* dpy; + int screen; + int x, y; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSetViewPortReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeSetViewPort, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetViewPort; + req->screen = screen; + req->x = x; + req->y = y; + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeGetDotClocks)(dpy, screen, + flagsPtr, numclocksPtr, maxclocksPtr, clocksPtr) + Display* dpy; + int screen; + int *flagsPtr, *numclocksPtr, *maxclocksPtr, *clocksPtr[]; +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetDotClocksReply rep; + xXF86VidModeGetDotClocksReq *req; + int i, *dotclocks; + CARD32 dotclk; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetDotClocks, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetDotClocks; + req->screen = screen; + if (!_XReply(dpy, (xReply *)&rep, + (SIZEOF(xXF86VidModeGetDotClocksReply) - SIZEOF(xReply)) >> 2, xFalse)) + { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *numclocksPtr = rep.clocks; + *maxclocksPtr = rep.maxclocks; + *flagsPtr = rep.flags; + + if (!(dotclocks = (int*) Xcalloc(rep.clocks, sizeof(int)))) { + _XEatData(dpy, (rep.clocks) * 4); + Xfree(dotclocks); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + for (i = 0; i < rep.clocks; i++) { + _XRead(dpy, (char*)&dotclk, 4); + dotclocks[i] = dotclk; + } + *clocksPtr = dotclocks; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool +SDL_NAME(XF86VidModeSetGammaRamp) ( + Display *dpy, + int screen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +) +{ + int length = (size + 1) & ~1; + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeSetGammaRampReq *req; + + XF86VidModeCheckExtension (dpy, info, False); + LockDisplay(dpy); + GetReq(XF86VidModeSetGammaRamp, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeSetGammaRamp; + req->screen = screen; + req->length += (length >> 1) * 3; + req->size = size; + _XSend(dpy, (char*)red, size * 2); + _XSend(dpy, (char*)green, size * 2); + _XSend(dpy, (char*)blue, size * 2); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +Bool +SDL_NAME(XF86VidModeGetGammaRamp) ( + Display *dpy, + int screen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaRampReq *req; + xXF86VidModeGetGammaRampReply rep; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGammaRamp, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGammaRamp; + req->screen = screen; + req->size = size; + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + if(rep.size) { + _XRead(dpy, (char*)red, rep.size << 1); + _XRead(dpy, (char*)green, rep.size << 1); + _XRead(dpy, (char*)blue, rep.size << 1); + } + + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool SDL_NAME(XF86VidModeGetGammaRampSize)( + Display *dpy, + int screen, + int *size +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXF86VidModeGetGammaRampSizeReq *req; + xXF86VidModeGetGammaRampSizeReply rep; + + *size = 0; + + XF86VidModeCheckExtension (dpy, info, False); + + LockDisplay(dpy); + GetReq(XF86VidModeGetGammaRampSize, req); + req->reqType = info->codes->major_opcode; + req->xf86vidmodeReqType = X_XF86VidModeGetGammaRampSize; + req->screen = screen; + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay (dpy); + SyncHandle (); + return False; + } + *size = rep.size; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xext.h b/3rdparty/SDL/src/video/Xext/extensions/Xext.h new file mode 100644 index 0000000..9edf319 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xext.h @@ -0,0 +1,50 @@ +/* +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + */ +/* $XFree86: xc/include/extensions/Xext.h,v 1.7 2005/01/27 03:03:09 dawes Exp $ */ + +#ifndef _XEXT_H_ +#define _XEXT_H_ + +#include <X11/Xfuncproto.h> + +_XFUNCPROTOBEGIN + +typedef int (*XExtensionErrorHandler)(Display *, _Xconst char *, + _Xconst char *); + +extern XExtensionErrorHandler XSetExtensionErrorHandler( + XExtensionErrorHandler handler +); + +extern int XMissingExtension( + Display* /* dpy */, + _Xconst char* /* ext_name */ +); + +_XFUNCPROTOEND + +#define X_EXTENSION_UNKNOWN "unknown" +#define X_EXTENSION_MISSING "missing" + +#endif /* _XEXT_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h b/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h new file mode 100644 index 0000000..54f2fe1 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xinerama.h @@ -0,0 +1,46 @@ +/* $XFree86: xc/include/extensions/Xinerama.h,v 3.2 2000/03/01 01:04:20 dawes Exp $ */ + +#ifndef _Xinerama_h +#define _Xinerama_h + +#include "SDL_name.h" + +typedef struct { + int screen_number; + short x_org; + short y_org; + short width; + short height; +} SDL_NAME(XineramaScreenInfo); + +Bool SDL_NAME(XineramaQueryExtension) ( + Display *dpy, + int *event_base, + int *error_base +); + +Status SDL_NAME(XineramaQueryVersion)( + Display *dpy, + int *major, + int *minor +); + +Bool SDL_NAME(XineramaIsActive)(Display *dpy); + + +/* + Returns the number of heads and a pointer to an array of + structures describing the position and size of the individual + heads. Returns NULL and number = 0 if Xinerama is not active. + + Returned array should be freed with XFree(). +*/ + +SDL_NAME(XineramaScreenInfo) * +SDL_NAME(XineramaQueryScreens)( + Display *dpy, + int *number +); + +#endif /* _Xinerama_h */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xv.h b/3rdparty/SDL/src/video/Xext/extensions/Xv.h new file mode 100644 index 0000000..a6a0271 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xv.h @@ -0,0 +1,129 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xv.h,v 1.5 1999/12/11 19:28:48 mvojkovi Exp $ */ + +#ifndef XV_H +#define XV_H +/* +** File: +** +** Xv.h --- Xv shared library and server header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 05.15.91 Carver +** - version 2.0 upgrade +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/X.h> + +#define XvName "XVideo" +#define XvVersion 2 +#define XvRevision 2 + +/* Symbols */ + +typedef XID XvPortID; +typedef XID XvEncodingID; + +#define XvNone 0 + +#define XvInput 0 +#define XvOutput 1 + +#define XvInputMask (1L<<XvInput) +#define XvOutputMask (1L<<XvOutput) +#define XvVideoMask 0x00000004 +#define XvStillMask 0x00000008 +#define XvImageMask 0x00000010 + +/* These two are not client viewable */ +#define XvPixmapMask 0x00010000 +#define XvWindowMask 0x00020000 + + +#define XvGettable 0x01 +#define XvSettable 0x02 + +#define XvRGB 0 +#define XvYUV 1 + +#define XvPacked 0 +#define XvPlanar 1 + +#define XvTopToBottom 0 +#define XvBottomToTop 1 + + +/* Events */ + +#define XvVideoNotify 0 +#define XvPortNotify 1 +#define XvNumEvents 2 + +/* Video Notify Reasons */ + +#define XvStarted 0 +#define XvStopped 1 +#define XvBusy 2 +#define XvPreempted 3 +#define XvHardError 4 +#define XvLastReason 4 + +#define XvNumReasons (XvLastReason + 1) + +#define XvStartedMask (1L<<XvStarted) +#define XvStoppedMask (1L<<XvStopped) +#define XvBusyMask (1L<<XvBusy) +#define XvPreemptedMask (1L<<XvPreempted) +#define XvHardErrorMask (1L<<XvHardError) + +#define XvAnyReasonMask ((1L<<XvNumReasons) - 1) +#define XvNoReasonMask 0 + +/* Errors */ + +#define XvBadPort 0 +#define XvBadEncoding 1 +#define XvBadControl 2 +#define XvNumErrors 3 + +/* Status */ + +#define XvBadExtension 1 +#define XvAlreadyGrabbed 2 +#define XvInvalidTime 3 +#define XvBadReply 4 +#define XvBadAlloc 5 + +#endif /* XV_H */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h b/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h new file mode 100644 index 0000000..0d0a55d --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xvlib.h @@ -0,0 +1,433 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xvlib.h,v 1.3 1999/12/11 19:28:48 mvojkovi Exp $ */ + +#ifndef XVLIB_H +#define XVLIB_H +/* +** File: +** +** Xvlib.h --- Xv library public header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 26.06.91 Carver +** - changed XvFreeAdaptors to XvFreeAdaptorInfo +** - changed XvFreeEncodings to XvFreeEncodingInfo +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 05.15.91 Carver +** - version 2.0 upgrade +** +** 01.24.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/Xfuncproto.h> +#include "Xv.h" +#include "SDL_name.h" + +typedef struct { + int numerator; + int denominator; +} SDL_NAME(XvRational); + +typedef struct { + int flags; /* XvGettable, XvSettable */ + int min_value; + int max_value; + char *name; +} SDL_NAME(XvAttribute); + +typedef struct { + XvEncodingID encoding_id; + char *name; + unsigned long width; + unsigned long height; + SDL_NAME(XvRational) rate; + unsigned long num_encodings; +} SDL_NAME(XvEncodingInfo); + +typedef struct { + char depth; + unsigned long visual_id; +} SDL_NAME(XvFormat); + +typedef struct { + XvPortID base_id; + unsigned long num_ports; + char type; + char *name; + unsigned long num_formats; + SDL_NAME(XvFormat) *formats; + unsigned long num_adaptors; +} SDL_NAME(XvAdaptorInfo); + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + Drawable drawable; /* drawable */ + unsigned long reason; /* what generated this event */ + XvPortID port_id; /* what port */ + Time time; /* milliseconds */ +} SDL_NAME(XvVideoNotifyEvent); + +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + XvPortID port_id; /* what port */ + Time time; /* milliseconds */ + Atom attribute; /* atom that identifies attribute */ + long value; /* value of attribute */ +} SDL_NAME(XvPortNotifyEvent); + +typedef union { + int type; + SDL_NAME(XvVideoNotifyEvent) xvvideo; + SDL_NAME(XvPortNotifyEvent) xvport; + long pad[24]; +} SDL_NAME(XvEvent); + +typedef struct { + int id; /* Unique descriptor for the format */ + int type; /* XvRGB, XvYUV */ + int byte_order; /* LSBFirst, MSBFirst */ + char guid[16]; /* Globally Unique IDentifier */ + int bits_per_pixel; + int format; /* XvPacked, XvPlanar */ + int num_planes; + + /* for RGB formats only */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats only */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; /* eg. UYVY */ + int scanline_order; /* XvTopToBottom, XvBottomToTop */ +} SDL_NAME(XvImageFormatValues); + +typedef struct { + int id; + int width, height; + int data_size; /* bytes */ + int num_planes; + int *pitches; /* bytes */ + int *offsets; /* bytes */ + char *data; + XPointer obdata; +} SDL_NAME(XvImage); + +_XFUNCPROTOBEGIN + +extern int SDL_NAME(XvQueryExtension)( +#if NeedFunctionPrototypes + Display* /* display */, + unsigned int* /* p_version */, + unsigned int* /* p_revision */, + unsigned int* /* p_requestBase */, + unsigned int* /* p_eventBase */, + unsigned int* /* p_errorBase */ +#endif +); + +extern int SDL_NAME(XvQueryAdaptors)( +#if NeedFunctionPrototypes + Display* /* display */, + Window /* window */, + unsigned int* /* p_nAdaptors */, + SDL_NAME(XvAdaptorInfo)** /* p_pAdaptors */ +#endif +); + +extern int SDL_NAME(XvQueryEncodings)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + unsigned int* /* p_nEncoding */, + SDL_NAME(XvEncodingInfo)** /* p_pEncoding */ +#endif +); + +extern int SDL_NAME(XvPutVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvPutStill)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvGetVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvGetStill)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* d */, + GC /* gc */, + int /* vx */, + int /* vy */, + unsigned int /* vw */, + unsigned int /* vh */, + int /* dx */, + int /* dy */, + unsigned int /* dw */, + unsigned int /* dh */ +#endif +); + +extern int SDL_NAME(XvStopVideo)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Drawable /* drawable */ +#endif +); + +extern int SDL_NAME(XvGrabPort)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Time /* time */ +#endif +); + +extern int SDL_NAME(XvUngrabPort)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Time /* time */ +#endif +); + +extern int SDL_NAME(XvSelectVideoNotify)( +#if NeedFunctionPrototypes + Display* /* display */, + Drawable /* drawable */, + Bool /* onoff */ +#endif +); + +extern int SDL_NAME(XvSelectPortNotify)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Bool /* onoff */ +#endif +); + +extern int SDL_NAME(XvSetPortAttribute)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Atom /* attribute */, + int /* value */ +#endif +); + +extern int SDL_NAME(XvGetPortAttribute)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Atom /* attribute */, + int* /* p_value */ +#endif +); + +extern int SDL_NAME(XvQueryBestSize)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + Bool /* motion */, + unsigned int /* vid_w */, + unsigned int /* vid_h */, + unsigned int /* drw_w */, + unsigned int /* drw_h */, + unsigned int* /* p_actual_width */, + unsigned int* /* p_actual_width */ +#endif +); + +extern SDL_NAME(XvAttribute)* SDL_NAME(XvQueryPortAttributes)( +#if NeedFunctionPrototypes + Display* /* display */, + XvPortID /* port */, + int* /* number */ +#endif +); + + +extern void SDL_NAME(XvFreeAdaptorInfo)( +#if NeedFunctionPrototypes + SDL_NAME(XvAdaptorInfo)* /* adaptors */ +#endif +); + +extern void SDL_NAME(XvFreeEncodingInfo)( +#if NeedFunctionPrototypes + SDL_NAME(XvEncodingInfo)* /* encodings */ +#endif +); + + +extern SDL_NAME(XvImageFormatValues) * SDL_NAME(XvListImageFormats) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port_id, + int *count_return +#endif +); + +extern SDL_NAME(XvImage) * SDL_NAME(XvCreateImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port, + int id, + char *data, + int width, + int height +#endif +); + +extern int SDL_NAME(XvPutImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID id, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h +#endif +); + +extern int SDL_NAME(XvShmPutImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID id, + Drawable d, + GC gc, + SDL_NAME(XvImage) *image, + int src_x, + int src_y, + unsigned int src_w, + unsigned int src_h, + int dest_x, + int dest_y, + unsigned int dest_w, + unsigned int dest_h, + Bool send_event +#endif +); + +#ifdef _XSHM_H_ + +extern SDL_NAME(XvImage) * SDL_NAME(XvShmCreateImage) ( +#if NeedFunctionPrototypes + Display *display, + XvPortID port, + int id, + char* data, + int width, + int height, + XShmSegmentInfo *shminfo +#endif +); + +#endif + + +_XFUNCPROTOEND + +#endif /* XVLIB_H */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h b/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h new file mode 100644 index 0000000..b4d8f22 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/Xvproto.h @@ -0,0 +1,604 @@ +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/include/extensions/Xvproto.h,v 1.6 2001/05/07 21:37:12 tsi Exp $ */ + +#ifndef XVPROTO_H +#define XVPROTO_H +/* +** File: +** +** Xvproto.h --- Xv protocol header file +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +*/ + +#include <X11/Xmd.h> + +/* Symbols: These are undefined at the end of this file to restore the + values they have in Xv.h */ + +#define XvPortID CARD32 +#define XvEncodingID CARD32 +#define ShmSeg CARD32 +#define VisualID CARD32 +#define Drawable CARD32 +#define GContext CARD32 +#define Time CARD32 +#define Atom CARD32 + +/* Structures */ + +typedef struct { + INT32 numerator B32; + INT32 denominator B32; +} xvRational; +#define sz_xvRational 8 + +typedef struct { + XvPortID base_id B32; + CARD16 name_size B16; + CARD16 num_ports B16; + CARD16 num_formats B16; + CARD8 type; + CARD8 pad; +} xvAdaptorInfo; +#define sz_xvAdaptorInfo 12 + +typedef struct { + XvEncodingID encoding B32; + CARD16 name_size B16; + CARD16 width B16, height B16; + xvRational rate; + CARD16 pad B16; +} xvEncodingInfo; +#define sz_xvEncodingInfo (12 + sz_xvRational) + +typedef struct { + VisualID visual B32; + CARD8 depth; + CARD8 pad1; + CARD16 pad2 B16; +} xvFormat; +#define sz_xvFormat 8 + +typedef struct { + CARD32 flags B32; + INT32 min B32; + INT32 max B32; + CARD32 size B32; +} xvAttributeInfo; +#define sz_xvAttributeInfo 16 + +typedef struct { + CARD32 id B32; + CARD8 type; + CARD8 byte_order; + CARD16 pad1 B16; + CARD8 guid[16]; + CARD8 bpp; + CARD8 num_planes; + CARD16 pad2 B16; + CARD8 depth; + CARD8 pad3; + CARD16 pad4 B16; + CARD32 red_mask B32; + CARD32 green_mask B32; + CARD32 blue_mask B32; + CARD8 format; + CARD8 pad5; + CARD16 pad6 B16; + CARD32 y_sample_bits B32; + CARD32 u_sample_bits B32; + CARD32 v_sample_bits B32; + CARD32 horz_y_period B32; + CARD32 horz_u_period B32; + CARD32 horz_v_period B32; + CARD32 vert_y_period B32; + CARD32 vert_u_period B32; + CARD32 vert_v_period B32; + CARD8 comp_order[32]; + CARD8 scanline_order; + CARD8 pad7; + CARD16 pad8 B16; + CARD32 pad9 B32; + CARD32 pad10 B32; +} xvImageFormatInfo; +#define sz_xvImageFormatInfo 128 + + +/* Requests */ + +#define xv_QueryExtension 0 +#define xv_QueryAdaptors 1 +#define xv_QueryEncodings 2 +#define xv_GrabPort 3 +#define xv_UngrabPort 4 +#define xv_PutVideo 5 +#define xv_PutStill 6 +#define xv_GetVideo 7 +#define xv_GetStill 8 +#define xv_StopVideo 9 +#define xv_SelectVideoNotify 10 +#define xv_SelectPortNotify 11 +#define xv_QueryBestSize 12 +#define xv_SetPortAttribute 13 +#define xv_GetPortAttribute 14 +#define xv_QueryPortAttributes 15 +#define xv_ListImageFormats 16 +#define xv_QueryImageAttributes 17 +#define xv_PutImage 18 +#define xv_ShmPutImage 19 +#define xv_LastRequest xv_ShmPutImage + +#define xvNumRequests (xv_LastRequest + 1) + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; +} xvQueryExtensionReq; +#define sz_xvQueryExtensionReq 4 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 window B32; +} xvQueryAdaptorsReq; +#define sz_xvQueryAdaptorsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 port B32; +} xvQueryEncodingsReq; +#define sz_xvQueryEncodingsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvPutVideoReq; +#define sz_xvPutVideoReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvPutStillReq; +#define sz_xvPutStillReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvGetVideoReq; +#define sz_xvGetVideoReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + INT16 vid_x B16; + INT16 vid_y B16; + CARD16 vid_w B16; + CARD16 vid_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; +} xvGetStillReq; +#define sz_xvGetStillReq 32 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Time time B32; +} xvGrabPortReq; +#define sz_xvGrabPortReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Time time B32; +} xvUngrabPortReq; +#define sz_xvUngrabPortReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + Drawable drawable B32; + BOOL onoff; + CARD8 pad1; + CARD16 pad2; +} xvSelectVideoNotifyReq; +#define sz_xvSelectVideoNotifyReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + BOOL onoff; + CARD8 pad1; + CARD16 pad2; +} xvSelectPortNotifyReq; +#define sz_xvSelectPortNotifyReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; +} xvStopVideoReq; +#define sz_xvStopVideoReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Atom attribute B32; + INT32 value B32; +} xvSetPortAttributeReq; +#define sz_xvSetPortAttributeReq 16 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Atom attribute B32; +} xvGetPortAttributeReq; +#define sz_xvGetPortAttributeReq 12 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + CARD16 vid_w B16; + CARD16 vid_h B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD8 motion; + CARD8 pad1; + CARD16 pad2 B16; +} xvQueryBestSizeReq; +#define sz_xvQueryBestSizeReq 20 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; +} xvQueryPortAttributesReq; +#define sz_xvQueryPortAttributesReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + CARD32 id B32; + INT16 src_x B16; + INT16 src_y B16; + CARD16 src_w B16; + CARD16 src_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD16 width B16; + CARD16 height B16; +} xvPutImageReq; +#define sz_xvPutImageReq 40 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; + Drawable drawable B32; + GContext gc B32; + ShmSeg shmseg B32; + CARD32 id B32; + CARD32 offset B32; + INT16 src_x B16; + INT16 src_y B16; + CARD16 src_w B16; + CARD16 src_h B16; + INT16 drw_x B16; + INT16 drw_y B16; + CARD16 drw_w B16; + CARD16 drw_h B16; + CARD16 width B16; + CARD16 height B16; + CARD8 send_event; + CARD8 pad1; + CARD16 pad2 B16; +} xvShmPutImageReq; +#define sz_xvShmPutImageReq 52 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + XvPortID port B32; +} xvListImageFormatsReq; +#define sz_xvListImageFormatsReq 8 + +typedef struct { + CARD8 reqType; + CARD8 xvReqType; + CARD16 length B16; + CARD32 port B32; + CARD32 id B32; + CARD16 width B16; + CARD16 height B16; +} xvQueryImageAttributesReq; +#define sz_xvQueryImageAttributesReq 16 + + +/* Replies */ + +typedef struct _QueryExtensionReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 version B16; + CARD16 revision B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryExtensionReply; +#define sz_xvQueryExtensionReply 32 + +typedef struct _QueryAdaptorsReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 num_adaptors B16; + CARD16 pads3 B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryAdaptorsReply; +#define sz_xvQueryAdaptorsReply 32 + +typedef struct _QueryEncodingsReply { + BYTE type; /* X_Reply */ + CARD8 padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 num_encodings B16; + CARD32 padl3 B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryEncodingsReply; +#define sz_xvQueryEncodingsReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE result; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD32 padl3 B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvGrabPortReply; +#define sz_xvGrabPortReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + INT32 value B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvGetPortAttributeReply; +#define sz_xvGetPortAttributeReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD16 actual_width B16; + CARD16 actual_height B16; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryBestSizeReply; +#define sz_xvQueryBestSizeReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* 0 */ + CARD32 num_attributes B32; + CARD32 text_size B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryPortAttributesReply; +#define sz_xvQueryPortAttributesReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 num_formats B32; + CARD32 padl4 B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvListImageFormatsReply; +#define sz_xvListImageFormatsReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE padb1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 num_planes B32; + CARD32 data_size B32; + CARD16 width B16; + CARD16 height B16; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; +} xvQueryImageAttributesReply; +#define sz_xvQueryImageAttributesReply 32 + +/* DEFINE EVENT STRUCTURE */ + +typedef struct { + union { + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + } u; + struct { + BYTE type; + BYTE reason; + CARD16 sequenceNumber B16; + Time time B32; + Drawable drawable B32; + XvPortID port B32; + CARD32 padl5 B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; + } videoNotify; + struct { + BYTE type; + BYTE padb1; + CARD16 sequenceNumber B16; + Time time B32; + XvPortID port B32; + Atom attribute B32; + INT32 value B32; + CARD32 padl6 B32; + CARD32 padl7 B32; + CARD32 padl8 B32; + } portNotify; + } u; +} xvEvent; + +#undef XvPortID +#undef XvEncodingID +#undef ShmSeg +#undef VisualID +#undef Drawable +#undef GContext +#undef Time +#undef Atom + +#endif /* XVPROTO_H */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/extutil.h b/3rdparty/SDL/src/video/Xext/extensions/extutil.h new file mode 100644 index 0000000..f3a741e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/extutil.h @@ -0,0 +1,226 @@ +/* + * $Xorg: extutil.h,v 1.4 2001/02/09 02:03:24 xorgcvs Exp $ + * +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Jim Fulton, MIT The Open Group + * + * Xlib Extension-Writing Utilities + * + * This package contains utilities for writing the client API for various + * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND + * ARE SUBJECT TO CHANGE! + */ +/* $XFree86: xc/include/extensions/extutil.h,v 1.9 2001/12/14 19:53:28 dawes Exp $ */ + +#ifndef _EXTUTIL_H_ +#define _EXTUTIL_H_ + +#include "SDL_stdinc.h" /* For portable string functions */ + +#include "./Xext.h" + +/* + * We need to keep a list of open displays since the Xlib display list isn't + * public. We also have to per-display info in a separate block since it isn't + * stored directly in the Display structure. + */ +typedef struct _XExtDisplayInfo { + struct _XExtDisplayInfo *next; /* keep a linked list */ + Display *display; /* which display this is */ + XExtCodes *codes; /* the extension protocol codes */ + XPointer data; /* extra data for extension to use */ +} XExtDisplayInfo; + +typedef struct _XExtensionInfo { + XExtDisplayInfo *head; /* start of list */ + XExtDisplayInfo *cur; /* most recently used */ + int ndisplays; /* number of displays */ +} XExtensionInfo; + +typedef struct _XExtensionHooks { + int (*create_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*copy_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*flush_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*free_gc)( +#if NeedNestedPrototypes + Display* /* display */, + GC /* gc */, + XExtCodes* /* codes */ +#endif +); + int (*create_font)( +#if NeedNestedPrototypes + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +#endif +); + int (*free_font)( +#if NeedNestedPrototypes + Display* /* display */, + XFontStruct* /* fs */, + XExtCodes* /* codes */ +#endif +); + int (*close_display)( +#if NeedNestedPrototypes + Display* /* display */, + XExtCodes* /* codes */ +#endif +); + Bool (*wire_to_event)( +#if NeedNestedPrototypes + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +#endif +); + Status (*event_to_wire)( +#if NeedNestedPrototypes + Display* /* display */, + XEvent* /* re */, + xEvent* /* event */ +#endif +); + int (*error)( +#if NeedNestedPrototypes + Display* /* display */, + xError* /* err */, + XExtCodes* /* codes */, + int* /* ret_code */ +#endif +); + char *(*error_string)( +#if NeedNestedPrototypes + Display* /* display */, + int /* code */, + XExtCodes* /* codes */, + char* /* buffer */, + int /* nbytes */ +#endif +); +} XExtensionHooks; + +extern XExtensionInfo *XextCreateExtension( +#if NeedFunctionPrototypes + void +#endif +); +extern void XextDestroyExtension( +#if NeedFunctionPrototypes + XExtensionInfo* /* info */ +#endif +); +extern XExtDisplayInfo *XextAddDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */, + char* /* ext_name */, + XExtensionHooks* /* hooks */, + int /* nevents */, + XPointer /* data */ +#endif +); +extern int XextRemoveDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */ +#endif +); +extern XExtDisplayInfo *XextFindDisplay( +#if NeedFunctionPrototypes + XExtensionInfo* /* extinfo */, + Display* /* dpy */ +#endif +); + +#define XextHasExtension(i) ((i) && ((i)->codes)) +#define XextCheckExtension(dpy,i,name,val) \ + if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; } +#define XextSimpleCheckExtension(dpy,i,name) \ + if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; } + + +/* + * helper macros to generate code that is common to all extensions; caller + * should prefix it with static if extension source is in one file; this + * could be a utility function, but have to stack 6 unused arguments for + * something that is called many, many times would be bad. + */ +#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \ +XExtDisplayInfo *proc (Display *dpy) \ +{ \ + XExtDisplayInfo *dpyinfo; \ + if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \ + if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \ + dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \ + return dpyinfo; \ +} + +#define XEXT_FIND_DISPLAY_PROTO(proc) \ + XExtDisplayInfo *proc(Display *dpy) + +#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \ +int proc (Display *dpy, XExtCodes *codes) \ +{ \ + return XextRemoveDisplay (extinfo, dpy); \ +} + +#define XEXT_CLOSE_DISPLAY_PROTO(proc) \ + int proc(Display *dpy, XExtCodes *codes) + +#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \ +char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \ +{ \ + code -= codes->first_error; \ + if (code >= 0 && code < nerr) { \ + char tmp[256]; \ + SDL_snprintf (tmp, SDL_arraysize(tmp), "%s.%d", extname, code); \ + XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \ + return buf; \ + } \ + return (char *)0; \ +} + +#define XEXT_ERROR_STRING_PROTO(proc) \ + char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n) +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h b/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h new file mode 100644 index 0000000..e89d891 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/panoramiXext.h @@ -0,0 +1,52 @@ +/* $Xorg: panoramiXext.h,v 1.4 2000/08/18 04:05:45 coskrey Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* + * PanoramiX definitions + */ +/* $XFree86: xc/include/extensions/panoramiXext.h,v 3.6 2001/01/17 17:53:22 dawes Exp $ */ + +#include "SDL_name.h" + +/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */ + +#define PANORAMIX_MAJOR_VERSION 1 /* current version number */ +#define PANORAMIX_MINOR_VERSION 1 + +typedef struct { + Window window; /* PanoramiX window - may not exist */ + int screen; + int State; /* PanroamiXOff, PanoramiXOn */ + int width; /* width of this screen */ + int height; /* height of this screen */ + int ScreenCount; /* real physical number of screens */ + XID eventMask; /* selected events for this client */ +} SDL_NAME(XPanoramiXInfo); + +extern SDL_NAME(XPanoramiXInfo) *SDL_NAME(XPanoramiXAllocInfo) ( +#if NeedFunctionPrototypes + void +#endif +); diff --git a/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h b/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h new file mode 100644 index 0000000..fe3826e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/panoramiXproto.h @@ -0,0 +1,192 @@ +/* $Xorg: panoramiXproto.h,v 1.4 2000/08/18 04:05:45 coskrey Exp $ */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ +/* $XFree86: xc/include/extensions/panoramiXproto.h,v 3.6 2001/01/17 17:53:22 dawes Exp $ */ + +/* THIS IS NOT AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _PANORAMIXPROTO_H_ +#define _PANORAMIXPROTO_H_ + +#define PANORAMIX_PROTOCOL_NAME "XINERAMA" + +#define X_PanoramiXQueryVersion 0 +#define X_PanoramiXGetState 1 +#define X_PanoramiXGetScreenCount 2 +#define X_PanoramiXGetScreenSize 3 + +#define X_XineramaIsActive 4 +#define X_XineramaQueryScreens 5 + +typedef struct _PanoramiXQueryVersion { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXQueryVersion */ + CARD16 length B16; + CARD8 clientMajor; + CARD8 clientMinor; + CARD16 unused B16; +} xPanoramiXQueryVersionReq; + +#define sz_xPanoramiXQueryVersionReq 8 + +typedef struct { + CARD8 type; /* must be X_Reply */ + CARD8 pad1; /* unused */ + CARD16 sequenceNumber B16; /* last sequence number */ + CARD32 length B32; /* 0 */ + CARD16 majorVersion B16; + CARD16 minorVersion B16; + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ + CARD32 pad6 B32; /* unused */ +} xPanoramiXQueryVersionReply; + +#define sz_xPanoramiXQueryVersionReply 32 + + +typedef struct _PanoramiXGetState { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetState */ + CARD16 length B16; + CARD32 window B32; +} xPanoramiXGetStateReq; +#define sz_xPanoramiXGetStateReq 8 + +typedef struct { + BYTE type; + BYTE state; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 window B32; + CARD32 pad1 B32; /* unused */ + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ +} xPanoramiXGetStateReply; + +#define sz_panoramiXGetStateReply 32 + +typedef struct _PanoramiXGetScreenCount { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetScreenCount */ + CARD16 length B16; + CARD32 window B32; +} xPanoramiXGetScreenCountReq; +#define sz_xPanoramiXGetScreenCountReq 8 + +typedef struct { + BYTE type; + BYTE ScreenCount; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 window B32; + CARD32 pad1 B32; /* unused */ + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ + CARD32 pad4 B32; /* unused */ + CARD32 pad5 B32; /* unused */ +} xPanoramiXGetScreenCountReply; +#define sz_panoramiXGetScreenCountReply 32 + +typedef struct _PanoramiXGetScreenSize { + CARD8 reqType; /* always PanoramiXReqCode */ + CARD8 panoramiXReqType; /* always X_PanoramiXGetState */ + CARD16 length B16; + CARD32 window B32; + CARD32 screen B32; +} xPanoramiXGetScreenSizeReq; +#define sz_xPanoramiXGetScreenSizeReq 12 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 width B32; + CARD32 height B32; + CARD32 window B32; + CARD32 screen B32; + CARD32 pad2 B32; /* unused */ + CARD32 pad3 B32; /* unused */ +} xPanoramiXGetScreenSizeReply; +#define sz_panoramiXGetScreenSizeReply 32 + +/************ Alternate protocol ******************/ + +typedef struct { + CARD8 reqType; + CARD8 panoramiXReqType; + CARD16 length B16; +} xXineramaIsActiveReq; +#define sz_xXineramaIsActiveReq 4 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 state B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXineramaIsActiveReply; +#define sz_XineramaIsActiveReply 32 + + +typedef struct { + CARD8 reqType; + CARD8 panoramiXReqType; + CARD16 length B16; +} xXineramaQueryScreensReq; +#define sz_xXineramaQueryScreensReq 4 + +typedef struct { + BYTE type; + CARD8 pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 number B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXineramaQueryScreensReply; +#define sz_XineramaQueryScreensReply 32 + +typedef struct { + INT16 x_org B16; + INT16 y_org B16; + CARD16 width B16; + CARD16 height B16; +} xXineramaScreenInfo; +#define sz_XineramaScreenInfo 8 + +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h new file mode 100644 index 0000000..c71ef4b --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga.h @@ -0,0 +1,265 @@ +/* + Copyright (c) 1999 XFree86 Inc +*/ +/* $XFree86: xc/include/extensions/xf86dga.h,v 3.21 2001/08/01 00:44:36 tsi Exp $ */ + +#ifndef _XF86DGA_H_ +#define _XF86DGA_H_ + +#include <X11/Xfuncproto.h> +#include "xf86dga1.h" +#include "SDL_name.h" + +#define X_XDGAQueryVersion 0 + +/* 1 through 9 are in xf86dga1.h */ + +/* 10 and 11 are reserved to avoid conflicts with rogue DGA extensions */ + +#define X_XDGAQueryModes 12 +#define X_XDGASetMode 13 +#define X_XDGASetViewport 14 +#define X_XDGAInstallColormap 15 +#define X_XDGASelectInput 16 +#define X_XDGAFillRectangle 17 +#define X_XDGACopyArea 18 +#define X_XDGACopyTransparentArea 19 +#define X_XDGAGetViewportStatus 20 +#define X_XDGASync 21 +#define X_XDGAOpenFramebuffer 22 +#define X_XDGACloseFramebuffer 23 +#define X_XDGASetClientVersion 24 +#define X_XDGAChangePixmapMode 25 +#define X_XDGACreateColormap 26 + + +#define XDGAConcurrentAccess 0x00000001 +#define XDGASolidFillRect 0x00000002 +#define XDGABlitRect 0x00000004 +#define XDGABlitTransRect 0x00000008 +#define XDGAPixmap 0x00000010 + +#define XDGAInterlaced 0x00010000 +#define XDGADoublescan 0x00020000 + +#define XDGAFlipImmediate 0x00000001 +#define XDGAFlipRetrace 0x00000002 + +#define XDGANeedRoot 0x00000001 + +#define XF86DGANumberEvents 7 + +#define XDGAPixmapModeLarge 0 +#define XDGAPixmapModeSmall 1 + +#define XF86DGAClientNotLocal 0 +#define XF86DGANoDirectVideoMode 1 +#define XF86DGAScreenNotActive 2 +#define XF86DGADirectNotActivated 3 +#define XF86DGAOperationNotSupported 4 +#define XF86DGANumberErrors (XF86DGAOperationNotSupported + 1) + + +typedef struct { + int num; /* A unique identifier for the mode (num > 0) */ + char *name; /* name of mode given in the XF86Config */ + float verticalRefresh; + int flags; /* DGA_CONCURRENT_ACCESS, etc... */ + int imageWidth; /* linear accessible portion (pixels) */ + int imageHeight; + int pixmapWidth; /* Xlib accessible portion (pixels) */ + int pixmapHeight; /* both fields ignored if no concurrent access */ + int bytesPerScanline; + int byteOrder; /* MSBFirst, LSBFirst */ + int depth; + int bitsPerPixel; + unsigned long redMask; + unsigned long greenMask; + unsigned long blueMask; + short visualClass; + int viewportWidth; + int viewportHeight; + int xViewportStep; /* viewport position granularity */ + int yViewportStep; + int maxViewportX; /* max viewport origin */ + int maxViewportY; + int viewportFlags; /* types of page flipping possible */ + int reserved1; + int reserved2; +} SDL_NAME(XDGAMode); + + +typedef struct { + SDL_NAME(XDGAMode) mode; + unsigned char *data; + Pixmap pixmap; +} SDL_NAME(XDGADevice); + + +#ifndef _XF86DGA_SERVER_ +_XFUNCPROTOBEGIN + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + unsigned int button; +} SDL_NAME(XDGAButtonEvent); + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + unsigned int keycode; +} SDL_NAME(XDGAKeyEvent); + +typedef struct { + int type; + unsigned long serial; + Display *display; + int screen; + Time time; + unsigned int state; + int dx; + int dy; +} SDL_NAME(XDGAMotionEvent); + +typedef union { + int type; + SDL_NAME(XDGAButtonEvent) xbutton; + SDL_NAME(XDGAKeyEvent) xkey; + SDL_NAME(XDGAMotionEvent) xmotion; + long pad[24]; +} SDL_NAME(XDGAEvent); + +Bool SDL_NAME(XDGAQueryExtension)( + Display *dpy, + int *eventBase, + int *erroBase +); + +Bool SDL_NAME(XDGAQueryVersion)( + Display *dpy, + int *majorVersion, + int *minorVersion +); + +SDL_NAME(XDGAMode)* SDL_NAME(XDGAQueryModes)( + Display *dpy, + int screen, + int *num +); + +SDL_NAME(XDGADevice)* SDL_NAME(XDGASetMode)( + Display *dpy, + int screen, + int mode +); + +Bool SDL_NAME(XDGAOpenFramebuffer)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGACloseFramebuffer)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGASetViewport)( + Display *dpy, + int screen, + int x, + int y, + int flags +); + +void SDL_NAME(XDGAInstallColormap)( + Display *dpy, + int screen, + Colormap cmap +); + +Colormap SDL_NAME(XDGACreateColormap)( + Display *dpy, + int screen, + SDL_NAME(XDGADevice) *device, + int alloc +); + +void SDL_NAME(XDGASelectInput)( + Display *dpy, + int screen, + long event_mask +); + +void SDL_NAME(XDGAFillRectangle)( + Display *dpy, + int screen, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long color +); + + +void SDL_NAME(XDGACopyArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty +); + + +void SDL_NAME(XDGACopyTransparentArea)( + Display *dpy, + int screen, + int srcx, + int srcy, + unsigned int width, + unsigned int height, + int dstx, + int dsty, + unsigned long key +); + +int SDL_NAME(XDGAGetViewportStatus)( + Display *dpy, + int screen +); + +void SDL_NAME(XDGASync)( + Display *dpy, + int screen +); + +Bool SDL_NAME(XDGASetClientVersion)( + Display *dpy +); + +void SDL_NAME(XDGAChangePixmapMode)( + Display *dpy, + int screen, + int *x, + int *y, + int mode +); + + +void SDL_NAME(XDGAKeyEventToXKeyEvent)(SDL_NAME(XDGAKeyEvent)* dk, XKeyEvent* xk); + + +_XFUNCPROTOEND +#endif /* _XF86DGA_SERVER_ */ +#endif /* _XF86DGA_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h new file mode 100644 index 0000000..4a49e9f --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1.h @@ -0,0 +1,169 @@ +/* $XFree86: xc/include/extensions/xf86dga1.h,v 1.2 1999/04/17 07:05:41 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc + +*/ + +/************************************************************************ + + THIS IS THE OLD DGA API AND IS OBSOLETE. PLEASE DO NOT USE IT ANYMORE + +************************************************************************/ + +#ifndef _XF86DGA1_H_ +#define _XF86DGA1_H_ + +#include <X11/Xfuncproto.h> +#include "SDL_name.h" + +#define X_XF86DGAQueryVersion 0 +#define X_XF86DGAGetVideoLL 1 +#define X_XF86DGADirectVideo 2 +#define X_XF86DGAGetViewPortSize 3 +#define X_XF86DGASetViewPort 4 +#define X_XF86DGAGetVidPage 5 +#define X_XF86DGASetVidPage 6 +#define X_XF86DGAInstallColormap 7 +#define X_XF86DGAQueryDirectVideo 8 +#define X_XF86DGAViewPortChanged 9 + +#define XF86DGADirectPresent 0x0001 +#define XF86DGADirectGraphics 0x0002 +#define XF86DGADirectMouse 0x0004 +#define XF86DGADirectKeyb 0x0008 +#define XF86DGAHasColormap 0x0100 +#define XF86DGADirectColormap 0x0200 + + + + +#ifndef _XF86DGA_SERVER_ + +_XFUNCPROTOBEGIN + +Bool SDL_NAME(XF86DGAQueryVersion)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int* /* majorVersion */, + int* /* minorVersion */ +#endif +); + +Bool SDL_NAME(XF86DGAQueryExtension)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int* /* event_base */, + int* /* error_base */ +#endif +); + +Status SDL_NAME(XF86DGAGetVideoLL)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* base addr */, + int * /* width */, + int * /* bank_size */, + int * /* ram_size */ +#endif +); + +Status SDL_NAME(XF86DGAGetVideo)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + char ** /* base addr */, + int * /* width */, + int * /* bank_size */, + int * /* ram_size */ +#endif +); + +Status SDL_NAME(XF86DGADirectVideo)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* enable */ +#endif +); + +Status SDL_NAME(XF86DGADirectVideoLL)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* enable */ +#endif +); + +Status SDL_NAME(XF86DGAGetViewPortSize)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* width */, + int * /* height */ +#endif +); + +Status SDL_NAME(XF86DGASetViewPort)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int x /* X */, + int y /* Y */ +#endif +); + +Status SDL_NAME(XF86DGAGetVidPage)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int * /* vid page */ +#endif +); + +Status SDL_NAME(XF86DGASetVidPage)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + int /* vid page */ +#endif +); + +Status SDL_NAME(XF86DGAInstallColormap)( +#if NeedFunctionPrototypes + Display* /* dpy */, + int /* screen */, + Colormap /*Colormap */ +#endif +); + +int SDL_NAME(XF86DGAForkApp)( +#if NeedFunctionPrototypes + int screen +#endif +); + +Status SDL_NAME(XF86DGAQueryDirectVideo)( +#if NeedFunctionPrototypes + Display * /* dpy */, + int /* screen */, + int * /* flags */ +#endif +); + +Bool SDL_NAME(XF86DGAViewPortChanged)( +#if NeedFunctionPrototypes + Display * /* dpy */, + int /* screen */, + int /* n */ +#endif +); + + +_XFUNCPROTOEND + +#endif /* _XF86DGA_SERVER_ */ + +#endif /* _XF86DGA1_H_ */ diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h new file mode 100644 index 0000000..5695fbd --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dga1str.h @@ -0,0 +1,194 @@ +/* $XFree86: xc/include/extensions/xf86dga1str.h,v 1.2 1999/05/03 12:15:37 dawes Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc. + +*/ + +#ifndef _XF86DGASTR1_H_ +#define _XF86DGASTR1_H_ + +typedef struct _XF86DGAQueryVersion { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; +} xXF86DGAQueryVersionReq; +#define sz_xXF86DGAQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DGA protocol */ + CARD16 minorVersion B16; /* minor version of DGA protocol */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86DGAQueryVersionReply; +#define sz_xXF86DGAQueryVersionReply 32 + +typedef struct _XF86DGAGetVideoLL { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetVideoLL */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetVideoLLReq; +#define sz_xXF86DGAGetVideoLLReq 8 + +typedef struct _XF86DGAInstallColormap{ + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad2; + CARD32 id B32; /* colormap. */ +} xXF86DGAInstallColormapReq; +#define sz_xXF86DGAInstallColormapReq 12 + + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 offset B32; + CARD32 width B32; + CARD32 bank_size B32; + CARD32 ram_size B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetVideoLLReply; +#define sz_xXF86DGAGetVideoLLReply 32 + +typedef struct _XF86DGADirectVideo { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGADirectVideo */ + CARD16 length B16; + CARD16 screen B16; + CARD16 enable B16; +} xXF86DGADirectVideoReq; +#define sz_xXF86DGADirectVideoReq 8 + + +typedef struct _XF86DGAGetViewPortSize { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetViewPortSizeReq; +#define sz_xXF86DGAGetViewPortSizeReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 width B32; + CARD32 height B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetViewPortSizeReply; +#define sz_xXF86DGAGetViewPortSizeReply 32 + +typedef struct _XF86DGASetViewPort { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGASetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 x B32; + CARD32 y B32; +} xXF86DGASetViewPortReq; +#define sz_xXF86DGASetViewPortReq 16 + +typedef struct _XF86DGAGetVidPage { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGAGetVidPage */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAGetVidPageReq; +#define sz_xXF86DGAGetVidPageReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 vpage B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAGetVidPageReply; +#define sz_xXF86DGAGetVidPageReply 32 + + +typedef struct _XF86DGASetVidPage { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_XF86DGASetVidPage */ + CARD16 length B16; + CARD16 screen B16; + CARD16 vpage B16; +} xXF86DGASetVidPageReq; +#define sz_xXF86DGASetVidPageReq 8 + + +typedef struct _XF86DGAQueryDirectVideo { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86DGAQueryDirectVideoReq; +#define sz_xXF86DGAQueryDirectVideoReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAQueryDirectVideoReply; +#define sz_xXF86DGAQueryDirectVideoReply 32 + + +typedef struct _XF86DGAViewPortChanged { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; + CARD16 screen B16; + CARD16 n B16; +} xXF86DGAViewPortChangedReq; +#define sz_xXF86DGAViewPortChangedReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 result B32; + CARD32 pad B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86DGAViewPortChangedReply; +#define sz_xXF86DGAViewPortChangedReply 32 + +#endif /* _XF86DGASTR1_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h b/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h new file mode 100644 index 0000000..b249feb --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86dgastr.h @@ -0,0 +1,344 @@ +/* $XFree86: xc/include/extensions/xf86dgastr.h,v 3.14 2001/08/01 00:44:36 tsi Exp $ */ +/* + +Copyright (c) 1995 Jon Tombs +Copyright (c) 1995 XFree86 Inc. + +*/ + +#ifndef _XF86DGASTR_H_ +#define _XF86DGASTR_H_ + +#include "xf86dga1str.h" + +#define XF86DGANAME "XFree86-DGA" + +#define XDGA_MAJOR_VERSION 2 /* current version numbers */ +#define XDGA_MINOR_VERSION 0 + + +typedef struct _XDGAQueryVersion { + CARD8 reqType; /* always DGAReqCode */ + CARD8 dgaReqType; /* always X_DGAQueryVersion */ + CARD16 length B16; +} xXDGAQueryVersionReq; +#define sz_xXDGAQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DGA protocol */ + CARD16 minorVersion B16; /* minor version of DGA protocol */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAQueryVersionReply; +#define sz_xXDGAQueryVersionReply 32 + +typedef struct _XDGAQueryModes { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAQueryModesReq; +#define sz_xXDGAQueryModesReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 number B32; /* number of modes available */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAQueryModesReply; +#define sz_xXDGAQueryModesReply 32 + + +typedef struct _XDGASetMode { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 mode B32; /* mode number to init */ + CARD32 pid B32; /* Pixmap descriptor */ +} xXDGASetModeReq; +#define sz_xXDGASetModeReq 16 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 offset B32; /* offset into framebuffer map */ + CARD32 flags B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXDGASetModeReply; +#define sz_xXDGASetModeReply 32 + +typedef struct { + CARD8 byte_order; + CARD8 depth; + CARD16 num B16; + CARD16 bpp B16; + CARD16 name_size B16; + CARD32 vsync_num B32; + CARD32 vsync_den B32; + CARD32 flags B32; + CARD16 image_width B16; + CARD16 image_height B16; + CARD16 pixmap_width B16; + CARD16 pixmap_height B16; + CARD32 bytes_per_scanline B32; + CARD32 red_mask B32; + CARD32 green_mask B32; + CARD32 blue_mask B32; + CARD16 visual_class B16; + CARD16 pad1 B16; + CARD16 viewport_width B16; + CARD16 viewport_height B16; + CARD16 viewport_xstep B16; + CARD16 viewport_ystep B16; + CARD16 viewport_xmax B16; + CARD16 viewport_ymax B16; + CARD32 viewport_flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; +} xXDGAModeInfo; +#define sz_xXDGAModeInfo 72 + +typedef struct _XDGAOpenFramebuffer { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAOpenFramebufferReq; +#define sz_xXDGAOpenFramebufferReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; /* device name size if there is one */ + CARD32 mem1 B32; /* physical memory */ + CARD32 mem2 B32; /* spillover for _alpha_ */ + CARD32 size B32; /* size of map in bytes */ + CARD32 offset B32; /* optional offset into device */ + CARD32 extra B32; /* extra info associated with the map */ + CARD32 pad2 B32; +} xXDGAOpenFramebufferReply; +#define sz_xXDGAOpenFramebufferReply 32 + + +typedef struct _XDGACloseFramebuffer { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGACloseFramebufferReq; +#define sz_xXDGACloseFramebufferReq 8 + + +typedef struct _XDGASetViewport { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD32 flags B32; +} xXDGASetViewportReq; +#define sz_xXDGASetViewportReq 16 + + +typedef struct _XDGAInstallColormap { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 cmap B32; +} xXDGAInstallColormapReq; +#define sz_xXDGAInstallColormapReq 12 + +typedef struct _XDGASelectInput { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 mask B32; +} xXDGASelectInputReq; +#define sz_xXDGASelectInputReq 12 + +typedef struct _XDGAFillRectangle { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD16 width B16; + CARD16 height B16; + CARD32 color B32; +} xXDGAFillRectangleReq; +#define sz_xXDGAFillRectangleReq 20 + + +typedef struct _XDGACopyArea { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 srcx B16; + CARD16 srcy B16; + CARD16 width B16; + CARD16 height B16; + CARD16 dstx B16; + CARD16 dsty B16; +} xXDGACopyAreaReq; +#define sz_xXDGACopyAreaReq 20 + +typedef struct _XDGACopyTransparentArea { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 srcx B16; + CARD16 srcy B16; + CARD16 width B16; + CARD16 height B16; + CARD16 dstx B16; + CARD16 dsty B16; + CARD32 key B32; +} xXDGACopyTransparentAreaReq; +#define sz_xXDGACopyTransparentAreaReq 24 + + +typedef struct _XDGAGetViewportStatus { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGAGetViewportStatusReq; +#define sz_xXDGAGetViewportStatusReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 status B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXDGAGetViewportStatusReply; +#define sz_xXDGAGetViewportStatusReply 32 + +typedef struct _XDGASync { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; +} xXDGASyncReq; +#define sz_xXDGASyncReq 8 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xXDGASyncReply; +#define sz_xXDGASyncReply 32 + +typedef struct _XDGASetClientVersion { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD16 major B16; + CARD16 minor B16; +} xXDGASetClientVersionReq; +#define sz_xXDGASetClientVersionReq 8 + + +typedef struct { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD16 x B16; + CARD16 y B16; + CARD32 flags B32; +} xXDGAChangePixmapModeReq; +#define sz_xXDGAChangePixmapModeReq 16 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 x B16; + CARD16 y B16; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xXDGAChangePixmapModeReply; +#define sz_xXDGAChangePixmapModeReply 32 + +typedef struct _XDGACreateColormap { + CARD8 reqType; + CARD8 dgaReqType; + CARD16 length B16; + CARD32 screen B32; + CARD32 id B32; + CARD32 mode B32; + CARD8 alloc; + CARD8 pad1; + CARD16 pad2; +} xXDGACreateColormapReq; +#define sz_xXDGACreateColormapReq 20 + + +typedef struct { + union { + struct { + BYTE type; + BYTE detail; + CARD16 sequenceNumber B16; + } u; + struct { + CARD32 pad0 B32; + CARD32 time B32; + INT16 dx B16; + INT16 dy B16; + INT16 screen B16; + CARD16 state B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + } event; + } u; +} dgaEvent; + + +#endif /* _XF86DGASTR_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h b/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h new file mode 100644 index 0000000..eb56c0e --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86vmode.h @@ -0,0 +1,314 @@ +/* $XFree86: xc/include/extensions/xf86vmode.h,v 3.30 2001/05/07 20:09:50 mvojkovi Exp $ */ +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $Xorg: xf86vmode.h,v 1.3 2000/08/18 04:05:46 coskrey Exp $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _XF86VIDMODE_H_ +#define _XF86VIDMODE_H_ + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include "SDL_name.h" + +#define X_XF86VidModeQueryVersion 0 +#define X_XF86VidModeGetModeLine 1 +#define X_XF86VidModeModModeLine 2 +#define X_XF86VidModeSwitchMode 3 +#define X_XF86VidModeGetMonitor 4 +#define X_XF86VidModeLockModeSwitch 5 +#define X_XF86VidModeGetAllModeLines 6 +#define X_XF86VidModeAddModeLine 7 +#define X_XF86VidModeDeleteModeLine 8 +#define X_XF86VidModeValidateModeLine 9 +#define X_XF86VidModeSwitchToMode 10 +#define X_XF86VidModeGetViewPort 11 +#define X_XF86VidModeSetViewPort 12 +/* new for version 2.x of this extension */ +#define X_XF86VidModeGetDotClocks 13 +#define X_XF86VidModeSetClientVersion 14 +#define X_XF86VidModeSetGamma 15 +#define X_XF86VidModeGetGamma 16 +#define X_XF86VidModeGetGammaRamp 17 +#define X_XF86VidModeSetGammaRamp 18 +#define X_XF86VidModeGetGammaRampSize 19 + +#define CLKFLAG_PROGRAMABLE 1 + +#ifdef XF86VIDMODE_EVENTS +#define XF86VidModeNotify 0 +#define XF86VidModeNumberEvents (XF86VidModeNotify + 1) + +#define XF86VidModeNotifyMask 0x00000001 + +#define XF86VidModeNonEvent 0 +#define XF86VidModeModeChange 1 +#else +#define XF86VidModeNumberEvents 0 +#endif + +#define XF86VidModeBadClock 0 +#define XF86VidModeBadHTimings 1 +#define XF86VidModeBadVTimings 2 +#define XF86VidModeModeUnsuitable 3 +#define XF86VidModeExtensionDisabled 4 +#define XF86VidModeClientNotLocal 5 +#define XF86VidModeZoomLocked 6 +#define XF86VidModeNumberErrors (XF86VidModeZoomLocked + 1) + +#ifndef _XF86VIDMODE_SERVER_ + +typedef struct { + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} SDL_NAME(XF86VidModeModeLine); + +typedef struct { + unsigned int dotclock; + unsigned short hdisplay; + unsigned short hsyncstart; + unsigned short hsyncend; + unsigned short htotal; + unsigned short hskew; + unsigned short vdisplay; + unsigned short vsyncstart; + unsigned short vsyncend; + unsigned short vtotal; + unsigned int flags; + int privsize; +#if defined(__cplusplus) || defined(c_plusplus) + /* private is a C++ reserved word */ + INT32 *c_private; +#else + INT32 *private; +#endif +} SDL_NAME(XF86VidModeModeInfo); + +typedef struct { + float hi; + float lo; +} SDL_NAME(XF86VidModeSyncRange); + +typedef struct { + char* vendor; + char* model; + float EMPTY; + unsigned char nhsync; + SDL_NAME(XF86VidModeSyncRange)* hsync; + unsigned char nvsync; + SDL_NAME(XF86VidModeSyncRange)* vsync; +} SDL_NAME(XF86VidModeMonitor); + +typedef struct { + int type; /* of event */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent req */ + Display *display; /* Display the event was read from */ + Window root; /* root window of event screen */ + int state; /* What happened */ + int kind; /* What happened */ + Bool forced; /* extents of new region */ + Time time; /* event timestamp */ +} SDL_NAME(XF86VidModeNotifyEvent); + +typedef struct { + float red; /* Red Gamma value */ + float green; /* Green Gamma value */ + float blue; /* Blue Gamma value */ +} SDL_NAME(XF86VidModeGamma); + + +#define SDL_XF86VidModeSelectNextMode(disp, scr) \ + SDL_NAME(XF86VidModeSwitchMode)(disp, scr, 1) +#define SDL_XF86VidModeSelectPrevMode(disp, scr) \ + SDL_NAME(XF86VidModeSwitchMode)(disp, scr, -1) + +_XFUNCPROTOBEGIN + +Bool SDL_NAME(XF86VidModeQueryVersion)( + Display* /* dpy */, + int* /* majorVersion */, + int* /* minorVersion */ +); + +Bool SDL_NAME(XF86VidModeQueryExtension)( + Display* /* dpy */, + int* /* event_base */, + int* /* error_base */ +); + +Bool SDL_NAME(XF86VidModeSetClientVersion)( + Display* /* dpy */ +); + +Bool SDL_NAME(XF86VidModeGetModeLine)( + Display* /* dpy */, + int /* screen */, + int* /* dotclock */, + SDL_NAME(XF86VidModeModeLine)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeGetAllModeLines)( + Display* /* dpy */, + int /* screen */, + int* /* modecount */, + SDL_NAME(XF86VidModeModeInfo)*** /* modelinesPtr */ +); + +Bool SDL_NAME(XF86VidModeAddModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* new modeline */, + SDL_NAME(XF86VidModeModeInfo)* /* after modeline */ +); + +Bool SDL_NAME(XF86VidModeDeleteModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeModModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeLine)* /* modeline */ +); + +Status SDL_NAME(XF86VidModeValidateModeLine)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeSwitchMode)( + Display* /* dpy */, + int /* screen */, + int /* zoom */ +); + +Bool SDL_NAME(XF86VidModeSwitchToMode)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeModeInfo)* /* modeline */ +); + +Bool SDL_NAME(XF86VidModeLockModeSwitch)( + Display* /* dpy */, + int /* screen */, + int /* lock */ +); + +Bool SDL_NAME(XF86VidModeGetMonitor)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeMonitor)* /* monitor */ +); + +Bool SDL_NAME(XF86VidModeGetViewPort)( + Display* /* dpy */, + int /* screen */, + int* /* x return */, + int* /* y return */ +); + +Bool SDL_NAME(XF86VidModeSetViewPort)( + Display* /* dpy */, + int /* screen */, + int /* x */, + int /* y */ +); + +Bool SDL_NAME(XF86VidModeGetDotClocks)( + Display* /* dpy */, + int /* screen */, + int* /* flags return */, + int* /* number of clocks return */, + int* /* max dot clock return */, + int** /* clocks return */ +); + +Bool SDL_NAME(XF86VidModeGetGamma)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeGamma)* /* Gamma */ +); + +Bool SDL_NAME(XF86VidModeSetGamma)( + Display* /* dpy */, + int /* screen */, + SDL_NAME(XF86VidModeGamma)* /* Gamma */ +); + +Bool SDL_NAME(XF86VidModeSetGammaRamp)( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool SDL_NAME(XF86VidModeGetGammaRamp)( + Display* /* dpy */, + int /* screen */, + int /* size */, + unsigned short* /* red array */, + unsigned short* /* green array */, + unsigned short* /* blue array */ +); + +Bool SDL_NAME(XF86VidModeGetGammaRampSize)( + Display* /* dpy */, + int /* screen */, + int* /* size */ +); + + +_XFUNCPROTOEND + +#endif + +#endif diff --git a/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h b/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h new file mode 100644 index 0000000..0c3078d --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xf86vmstr.h @@ -0,0 +1,546 @@ +/* $XFree86: xc/include/extensions/xf86vmstr.h,v 3.27 2001/08/01 00:44:36 tsi Exp $ */ +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* $Xorg: xf86vmstr.h,v 1.3 2000/08/18 04:05:46 coskrey Exp $ */ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifndef _XF86VIDMODESTR_H_ +#define _XF86VIDMODESTR_H_ + +#include "xf86vmode.h" + +#define XF86VIDMODENAME "XFree86-VidModeExtension" + +#define XF86VIDMODE_MAJOR_VERSION 2 /* current version numbers */ +#define XF86VIDMODE_MINOR_VERSION 1 +/* + * major version 0 == uses parameter-to-wire functions in XFree86 libXxf86vm. + * major version 1 == uses parameter-to-wire functions hard-coded in xvidtune + * client. + * major version 2 == uses new protocol version in XFree86 4.0. + */ + +typedef struct _XF86VidModeQueryVersion { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeQueryVersion */ + CARD16 length B16; +} xXF86VidModeQueryVersionReq; +#define sz_xXF86VidModeQueryVersionReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of XF86VidMode */ + CARD16 minorVersion B16; /* minor version of XF86VidMode */ + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeQueryVersionReply; +#define sz_xXF86VidModeQueryVersionReply 32 + +typedef struct _XF86VidModeGetModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86VidModeGetModeLineReq, + xXF86VidModeGetAllModeLinesReq, + xXF86VidModeGetMonitorReq, + xXF86VidModeGetViewPortReq, + xXF86VidModeGetDotClocksReq; +#define sz_xXF86VidModeGetModeLineReq 8 +#define sz_xXF86VidModeGetAllModeLinesReq 8 +#define sz_xXF86VidModeGetMonitorReq 8 +#define sz_xXF86VidModeGetViewPortReq 8 +#define sz_xXF86VidModeGetDotClocksReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad2 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeGetModeLineReply; +#define sz_xXF86VidModeGetModeLineReply 52 + +/* 0.x version */ +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeGetModeLineReply; +#define sz_xXF86OldVidModeGetModeLineReply 36 + +typedef struct { + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD32 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeModeInfo; + +/* 0.x version */ +typedef struct { + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeModeInfo; + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 modecount B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetAllModeLinesReply; +#define sz_xXF86VidModeGetAllModeLinesReply 32 + +typedef struct _XF86VidModeAddModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeAddMode */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; + CARD32 after_dotclock B32; + CARD16 after_hdisplay B16; + CARD16 after_hsyncstart B16; + CARD16 after_hsyncend B16; + CARD16 after_htotal B16; + CARD16 after_hskew B16; + CARD16 after_vdisplay B16; + CARD16 after_vsyncstart B16; + CARD16 after_vsyncend B16; + CARD16 after_vtotal B16; + CARD16 pad2 B16; + CARD32 after_flags B32; + CARD32 reserved4 B32; + CARD32 reserved5 B32; + CARD32 reserved6 B32; +} xXF86VidModeAddModeLineReq; +#define sz_xXF86VidModeAddModeLineReq 92 + +/* 0.x version */ +typedef struct _XF86OldVidModeAddModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeAddMode */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; + CARD32 after_dotclock B32; + CARD16 after_hdisplay B16; + CARD16 after_hsyncstart B16; + CARD16 after_hsyncend B16; + CARD16 after_htotal B16; + CARD16 after_vdisplay B16; + CARD16 after_vsyncstart B16; + CARD16 after_vsyncend B16; + CARD16 after_vtotal B16; + CARD32 after_flags B32; +} xXF86OldVidModeAddModeLineReq; +#define sz_xXF86OldVidModeAddModeLineReq 60 + +typedef struct _XF86VidModeModModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeModModeLine */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeModModeLineReq; +#define sz_xXF86VidModeModModeLineReq 48 + +/* 0.x version */ +typedef struct _XF86OldVidModeModModeLine { + CARD8 reqType; /* always XF86OldVidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86OldVidModeModModeLine */ + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeModModeLineReq; +#define sz_xXF86OldVidModeModModeLineReq 32 + +typedef struct _XF86VidModeValidateModeLine { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 hskew B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD16 pad1 B16; + CARD32 flags B32; + CARD32 reserved1 B32; + CARD32 reserved2 B32; + CARD32 reserved3 B32; + CARD32 privsize B32; +} xXF86VidModeDeleteModeLineReq, + xXF86VidModeValidateModeLineReq, + xXF86VidModeSwitchToModeReq; +#define sz_xXF86VidModeDeleteModeLineReq 52 +#define sz_xXF86VidModeValidateModeLineReq 52 +#define sz_xXF86VidModeSwitchToModeReq 52 + +/* 0.x version */ +typedef struct _XF86OldVidModeValidateModeLine { + CARD8 reqType; /* always XF86OldVidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD32 screen B32; /* could be CARD16 but need the pad */ + CARD32 dotclock B32; + CARD16 hdisplay B16; + CARD16 hsyncstart B16; + CARD16 hsyncend B16; + CARD16 htotal B16; + CARD16 vdisplay B16; + CARD16 vsyncstart B16; + CARD16 vsyncend B16; + CARD16 vtotal B16; + CARD32 flags B32; + CARD32 privsize B32; +} xXF86OldVidModeDeleteModeLineReq, + xXF86OldVidModeValidateModeLineReq, + xXF86OldVidModeSwitchToModeReq; +#define sz_xXF86OldVidModeDeleteModeLineReq 36 +#define sz_xXF86OldVidModeValidateModeLineReq 36 +#define sz_xXF86OldVidModeSwitchToModeReq 36 + +typedef struct _XF86VidModeSwitchMode { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeSwitchMode */ + CARD16 length B16; + CARD16 screen B16; + CARD16 zoom B16; +} xXF86VidModeSwitchModeReq; +#define sz_xXF86VidModeSwitchModeReq 8 + +typedef struct _XF86VidModeLockModeSwitch { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeLockModeSwitch */ + CARD16 length B16; + CARD16 screen B16; + CARD16 lock B16; +} xXF86VidModeLockModeSwitchReq; +#define sz_xXF86VidModeLockModeSwitchReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 status B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeValidateModeLineReply; +#define sz_xXF86VidModeValidateModeLineReply 32 + +typedef struct { + BYTE type; /* X_Reply */ + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD8 vendorLength; + CARD8 modelLength; + CARD8 nhsync; + CARD8 nvsync; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetMonitorReply; +#define sz_xXF86VidModeGetMonitorReply 32 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 x B32; + CARD32 y B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetViewPortReply; +#define sz_xXF86VidModeGetViewPortReply 32 + +typedef struct _XF86VidModeSetViewPort { + CARD8 reqType; /* always VidModeReqCode */ + CARD8 xf86vidmodeReqType; /* always X_XF86VidModeSetViewPort */ + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 x B32; + CARD32 y B32; +} xXF86VidModeSetViewPortReq; +#define sz_xXF86VidModeSetViewPortReq 16 + +typedef struct { + BYTE type; + BOOL pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 flags B32; + CARD32 clocks B32; + CARD32 maxclocks B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; +} xXF86VidModeGetDotClocksReply; +#define sz_xXF86VidModeGetDotClocksReply 32 + +typedef struct _XF86VidModeSetClientVersion { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 major B16; + CARD16 minor B16; +} xXF86VidModeSetClientVersionReq; +#define sz_xXF86VidModeSetClientVersionReq 8 + +typedef struct _XF86VidModeGetGamma { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xXF86VidModeGetGammaReq; +#define sz_xXF86VidModeGetGammaReq 32 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 red B32; + CARD32 green B32; + CARD32 blue B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xXF86VidModeGetGammaReply; +#define sz_xXF86VidModeGetGammaReply 32 + +typedef struct _XF86VidModeSetGamma { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; + CARD32 red B32; + CARD32 green B32; + CARD32 blue B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; +} xXF86VidModeSetGammaReq; +#define sz_xXF86VidModeSetGammaReq 32 + + +typedef struct _XF86VidModeSetGammaRamp { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 size B16; +} xXF86VidModeSetGammaRampReq; +#define sz_xXF86VidModeSetGammaRampReq 8 + +typedef struct _XF86VidModeGetGammaRamp { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 size B16; +} xXF86VidModeGetGammaRampReq; +#define sz_xXF86VidModeGetGammaRampReq 8 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 size B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetGammaRampReply; +#define sz_xXF86VidModeGetGammaRampReply 32 + +typedef struct _XF86VidModeGetGammaRampSize { + CARD8 reqType; /* always XF86VidModeReqCode */ + CARD8 xf86vidmodeReqType; + CARD16 length B16; + CARD16 screen B16; + CARD16 pad B16; +} xXF86VidModeGetGammaRampSizeReq; +#define sz_xXF86VidModeGetGammaRampSizeReq 8 + +typedef struct { + BYTE type; + BOOL pad; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 size B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xXF86VidModeGetGammaRampSizeReply; +#define sz_xXF86VidModeGetGammaRampSizeReply 32 + + +#endif /* _XF86VIDMODESTR_H_ */ + diff --git a/3rdparty/SDL/src/video/Xext/extensions/xme.h b/3rdparty/SDL/src/video/Xext/extensions/xme.h new file mode 100644 index 0000000..f550623 --- /dev/null +++ b/3rdparty/SDL/src/video/Xext/extensions/xme.h @@ -0,0 +1,45 @@ +/* + * Copyright 1993-2001 by Xi Graphics, Inc. + * All Rights Reserved. + * + * Please see the LICENSE file accompanying this distribution for licensing + * information. + * + * Please send any bug fixes and modifications to src@xig.com. + * + * $XiGId: xme.h,v 1.1.1.1 2001/11/19 19:01:10 jon Exp $ + * + */ + + +#ifndef _XME_H_INCLUDED +#define _XME_H_INCLUDED + +typedef struct { + short x; + short y; + unsigned short w; + unsigned short h; +} XiGMiscViewInfo; + +typedef struct { + unsigned short width; + unsigned short height; + int refresh; +} XiGMiscResolutionInfo; + +extern Bool XiGMiscQueryVersion(Display *dpy, int *major, int *minor); +extern int XiGMiscQueryViews(Display *dpy, int screen, + XiGMiscViewInfo **pviews); +extern int XiGMiscQueryResolutions(Display *dpy, int screen, int view, + int *pactive, + XiGMiscResolutionInfo **presolutions); +extern void XiGMiscChangeResolution(Display *dpy, int screen, int view, + int width, int height, int refresh); + +/* SDL addition from Ryan: free memory used by xme. */ +extern void XiGMiscDestroy(void); + +#endif /* _XME_H_INCLUDED */ + + diff --git a/3rdparty/SDL/src/video/aalib/SDL_aaevents.c b/3rdparty/SDL/src/video/aalib/SDL_aaevents.c new file mode 100644 index 0000000..a26ab2d --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aaevents.c @@ -0,0 +1,202 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting AA events into SDL events */ + +#include <stdio.h> + +#include <aalib.h> + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_aavideo.h" +#include "SDL_aaevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[401]; + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + + +void AA_PumpEvents(_THIS) +{ + int posted = 0; + int mouse_button, mouse_x, mouse_y; + int evt; + SDL_keysym keysym; + + static int prev_button = -1, prev_x = -1, prev_y = -1; + + if( ! this->screen ) /* Wait till we got the screen initialized */ + return; + + do { + posted = 0; + /* Gather events */ + + /* Get mouse status */ + SDL_mutexP(AA_mutex); + aa_getmouse (AA_context, &mouse_x, &mouse_y, &mouse_button); + SDL_mutexV(AA_mutex); + mouse_x = mouse_x * this->screen->w / aa_scrwidth (AA_context); + mouse_y = mouse_y * this->screen->h / aa_scrheight (AA_context); + + /* Compare against previous state and generate events */ + if( prev_button != mouse_button ) { + if( mouse_button & AA_BUTTON1 ) { + if ( ! (prev_button & AA_BUTTON1) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 1, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON1 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 1, 0, 0); + } + } + if( mouse_button & AA_BUTTON2 ) { + if ( ! (prev_button & AA_BUTTON2) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 2, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON2 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 2, 0, 0); + } + } + if( mouse_button & AA_BUTTON3 ) { + if ( ! (prev_button & AA_BUTTON3) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 3, 0, 0); + } + } else { + if ( prev_button & AA_BUTTON3 ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 3, 0, 0); + } + } + } + if ( prev_x != mouse_x || prev_y != mouse_y ) { + posted += SDL_PrivateMouseMotion(0, 0, mouse_x, mouse_y); + } + + prev_button = mouse_button; + prev_x = mouse_x; prev_y = mouse_y; + + /* Get keyboard event */ + SDL_mutexP(AA_mutex); + evt = aa_getevent(AA_context, 0); + SDL_mutexV(AA_mutex); + if ( (evt > AA_NONE) && (evt < AA_RELEASE) && (evt != AA_MOUSE) && (evt != AA_RESIZE) ) { + /* Key pressed */ +/* printf("Key pressed: %d (%c)\n", evt, evt); */ + posted += SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(evt, &keysym)); + } else if ( evt >= AA_RELEASE ) { + /* Key released */ + evt &= ~AA_RELEASE; +/* printf("Key released: %d (%c)\n", evt, evt); */ + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(evt, &keysym)); + } + } while ( posted ); +} + +void AA_InitOSKeymap(_THIS) +{ + int i; + static const char *std_keys = " 01234567890&#'()_-|$*+-=/\\:;.,!?<>{}[]@~%^\x9"; + const char *std; + + /* Initialize the AAlib key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + /* Alphabet keys */ + for ( i = 0; i<26; ++i ){ + keymap['a' + i] = SDLK_a+i; + keymap['A' + i] = SDLK_a+i; + } + /* Function keys */ + for ( i = 0; i<12; ++i ){ + keymap[334 + i] = SDLK_F1+i; + } + /* Keys that have the same symbols and don't have to be translated */ + for( std = std_keys; *std; std ++ ) { + keymap[*std] = *std; + } + + keymap[13] = SDLK_RETURN; + keymap[AA_BACKSPACE] = SDLK_BACKSPACE; + + keymap[369] = SDLK_LSHIFT; + keymap[370] = SDLK_RSHIFT; + keymap[371] = SDLK_LCTRL; + keymap[372] = SDLK_RCTRL; + keymap[377] = SDLK_LALT; + keymap[270] = SDLK_RALT; + keymap[271] = SDLK_NUMLOCK; + keymap[373] = SDLK_CAPSLOCK; + keymap[164] = SDLK_SCROLLOCK; + + keymap[243] = SDLK_INSERT; + keymap[304] = SDLK_DELETE; + keymap[224] = SDLK_HOME; + keymap[231] = SDLK_END; + keymap[229] = SDLK_PAGEUP; + keymap[230] = SDLK_PAGEDOWN; + + keymap[241] = SDLK_PRINT; + keymap[163] = SDLK_BREAK; + + keymap[302] = SDLK_KP0; + keymap[300] = SDLK_KP1; + keymap[297] = SDLK_KP2; + keymap[299] = SDLK_KP3; + keymap[294] = SDLK_KP4; + keymap[301] = SDLK_KP5; + keymap[296] = SDLK_KP6; + keymap[293] = SDLK_KP7; + keymap[295] = SDLK_KP8; + keymap[298] = SDLK_KP9; + + keymap[AA_ESC] = SDLK_ESCAPE; + keymap[AA_UP] = SDLK_UP; + keymap[AA_DOWN] = SDLK_DOWN; + keymap[AA_LEFT] = SDLK_LEFT; + keymap[AA_RIGHT] = SDLK_RIGHT; +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Sanity check */ + if ( scancode >= SDL_arraysize(keymap) ) + scancode = AA_UNKNOWN; + + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h b/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h new file mode 100644 index 0000000..6dbc9f6 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_aavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void AA_initkeymaps(int fd); +extern void AA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4); +extern void AA_keyboardcallback(int scancode, int pressed); + +extern void AA_InitOSKeymap(_THIS); +extern void AA_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/aalib/SDL_aamouse.c b/3rdparty/SDL/src/video/aalib/SDL_aamouse.c new file mode 100644 index 0000000..dc784a5 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aamouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_aamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h b/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h new file mode 100644 index 0000000..6ce3d98 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_aavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/aalib/SDL_aavideo.c b/3rdparty/SDL/src/video/aalib/SDL_aavideo.c new file mode 100644 index 0000000..e6d5d3e --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aavideo.c @@ -0,0 +1,388 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* AAlib based SDL video driver implementation. +*/ + +#include <unistd.h> +#include <sys/stat.h> + + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_aavideo.h" +#include "SDL_aaevents_c.h" +#include "SDL_aamouse_c.h" + +#include <aalib.h> + +/* Initialization/Query functions */ +static int AA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void AA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int AA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int AA_LockHWSurface(_THIS, SDL_Surface *surface); +static int AA_FlipHWSurface(_THIS, SDL_Surface *surface); +static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void AA_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Cache the VideoDevice struct */ +static struct SDL_VideoDevice *local_this; + +/* AAlib driver bootstrap functions */ + +static int AA_Available(void) +{ + return 1; /* Always available ! */ +} + +static void AA_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *AA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = AA_VideoInit; + device->ListModes = AA_ListModes; + device->SetVideoMode = AA_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = AA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = AA_VideoQuit; + device->AllocHWSurface = AA_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = AA_LockHWSurface; + device->UnlockHWSurface = AA_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = AA_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = AA_InitOSKeymap; + device->PumpEvents = AA_PumpEvents; + + device->free = AA_DeleteDevice; + + return device; +} + +VideoBootStrap AALIB_bootstrap = { + "aalib", "ASCII Art Library", + AA_Available, AA_CreateDevice +}; + +static void AA_ResizeHandler(aa_context *); + +int AA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int keyboard; + int i; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + SDL_modelist[i] = SDL_malloc(sizeof(SDL_Rect)); + SDL_modelist[i]->x = SDL_modelist[i]->y = 0; + } + /* Modes sorted largest to smallest */ + SDL_modelist[0]->w = 1024; SDL_modelist[0]->h = 768; + SDL_modelist[1]->w = 800; SDL_modelist[1]->h = 600; + SDL_modelist[2]->w = 640; SDL_modelist[2]->h = 480; + SDL_modelist[3]->w = 320; SDL_modelist[3]->h = 400; + SDL_modelist[4]->w = 320; SDL_modelist[4]->h = 240; + SDL_modelist[5]->w = 320; SDL_modelist[5]->h = 200; + SDL_modelist[6] = NULL; + + /* Initialize the library */ + + AA_mutex = SDL_CreateMutex(); + + aa_parseoptions (NULL, NULL, NULL, NULL); + + AA_context = aa_autoinit(&aa_defparams); + if ( ! AA_context ) { + SDL_SetError("Unable to initialize AAlib"); + return(-1); + } + + /* Enable mouse and keyboard support */ + + if ( ! aa_autoinitkbd (AA_context, AA_SENDRELEASE) ) { + SDL_SetError("Unable to initialize AAlib keyboard"); + return(-1); + } + if ( ! aa_autoinitmouse (AA_context, AA_SENDRELEASE) ) { + fprintf(stderr,"Warning: Unable to initialize AAlib mouse"); + } + AA_rparams = aa_getrenderparams(); + + local_this = this; + + aa_resizehandler(AA_context, AA_ResizeHandler); + + fprintf(stderr,"Using AAlib driver: %s (%s)\n", AA_context->driver->name, AA_context->driver->shortname); + + AA_in_x11 = (SDL_strcmp(AA_context->driver->shortname,"X11") == 0); + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **AA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if(format->BitsPerPixel != 8) + return NULL; + + if ( flags & SDL_FULLSCREEN ) { + return SDL_modelist; + } else { + return (SDL_Rect **) -1; + } +} + +/* From aavga.c + AAlib does not give us the choice of the actual resolution, thus we have to simulate additional + resolution by scaling down manually each frame +*/ +static void fastscale (register char *b1, register char *b2, int x1, int x2, int y1, int y2) +{ + register int ex, spx = 0, ddx, ddx1; + int ddy1, ddy, spy = 0, ey; + int x; + char *bb1 = b1; + if (!x1 || !x2 || !y1 || !y2) + return; + ddx = x1 + x1; + ddx1 = x2 + x2; + if (ddx1 < ddx) + spx = ddx / ddx1, ddx %= ddx1; + ddy = y1 + y1; + ddy1 = y2 + y2; + if (ddy1 < ddy) + spy = (ddy / ddy1) * x1, ddy %= ddy1; + ey = -ddy1; + for (; y2; y2--) { + ex = -ddx1; + for (x = x2; x; x--) { + *b2 = *b1; + b2++; + b1 += spx; + ex += ddx; + if (ex > 0) { + b1++; + ex -= ddx1; + } + } + bb1 += spy; + ey += ddy; + if (ey > 0) { + bb1 += x1; + ey -= ddy1; + } + b1 = bb1; + } +} + +/* Various screen update functions available */ +static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *AA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode; + + if ( AA_buffer ) { + SDL_free( AA_buffer ); + } + + AA_buffer = SDL_malloc(width * height); + if ( ! AA_buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + SDL_memset(aa_image(AA_context), 0, aa_imgwidth(AA_context) * aa_imgheight(AA_context)); + SDL_memset(AA_buffer, 0, width * height); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, 8, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + AA_w = current->w = width; + AA_h = current->h = height; + current->pitch = current->w; + current->pixels = AA_buffer; + + AA_x_ratio = ((double)aa_imgwidth(AA_context)) / ((double)width); + AA_y_ratio = ((double)aa_imgheight(AA_context)) / ((double)height); + + /* Set the blit function */ + this->UpdateRects = AA_DirectUpdate; + + /* We're done */ + return(current); +} + +static void AA_ResizeHandler(aa_context *context) +{ + aa_resize(context); + local_this->hidden->x_ratio = ((double)aa_imgwidth(context)) / ((double)local_this->screen->w); + local_this->hidden->y_ratio = ((double)aa_imgheight(context)) / ((double)local_this->screen->h); + + fastscale (local_this->hidden->buffer, aa_image(context), local_this->hidden->w, aa_imgwidth (context), local_this->hidden->h, aa_imgheight (context)); + aa_renderpalette(context, local_this->hidden->palette, local_this->hidden->rparams, 0, 0, aa_scrwidth(context), aa_scrheight(context)); + aa_flush(context); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int AA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void AA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int AA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* TODO ? */ + return(0); +} +static void AA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* FIXME: How is this done with AAlib? */ +static int AA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + SDL_mutexP(AA_mutex); + aa_flush(AA_context); + SDL_mutexV(AA_mutex); + return(0); +} + +static void AA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + SDL_Rect *rect; + + fastscale (AA_buffer, aa_image(AA_context), AA_w, aa_imgwidth (AA_context), AA_h, aa_imgheight (AA_context)); +#if 1 + aa_renderpalette(AA_context, AA_palette, AA_rparams, 0, 0, aa_scrwidth(AA_context), aa_scrheight(AA_context)); +#else + /* Render only the rectangles in the list */ + printf("Update rects : "); + for ( i=0; i < numrects; ++i ) { + rect = &rects[i]; + printf("(%d,%d-%d,%d)", rect->x, rect->y, rect->w, rect->h); + aa_renderpalette(AA_context, AA_palette, AA_rparams, rect->x * AA_x_ratio, rect->y * AA_y_ratio, rect->w * AA_x_ratio, rect->h * AA_y_ratio); + } + printf("\n"); +#endif + SDL_mutexP(AA_mutex); + aa_flush(AA_context); + SDL_mutexV(AA_mutex); + return; +} + +int AA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for ( i=0; i < ncolors; i++ ) { + aa_setpalette(AA_palette, firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void AA_VideoQuit(_THIS) +{ + int i; + + aa_uninitkbd(AA_context); + aa_uninitmouse(AA_context); + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( SDL_modelist[i] != NULL ) { + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + aa_close(AA_context); + + SDL_DestroyMutex(AA_mutex); + + this->screen->pixels = NULL; +} diff --git a/3rdparty/SDL/src/video/aalib/SDL_aavideo.h b/3rdparty/SDL/src/video/aalib/SDL_aavideo.h new file mode 100644 index 0000000..987edc9 --- /dev/null +++ b/3rdparty/SDL/src/video/aalib/SDL_aavideo.h @@ -0,0 +1,66 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_aavideo_h +#define _SDL_aavideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +#include <aalib.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define SDL_NUMMODES 6 + +/* Private display data */ +struct SDL_PrivateVideoData { + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; + aa_context *context; + aa_palette palette; + aa_renderparams *rparams; + double x_ratio, y_ratio; + int w, h; + SDL_mutex *mutex; + int in_x11; + void *buffer; +}; + +/* Old variable names */ +#define SDL_modelist (this->hidden->SDL_modelist) +#define AA_context (this->hidden->context) +#define AA_palette (this->hidden->palette) +#define AA_rparams (this->hidden->rparams) +#define AA_buffer (this->hidden->buffer) + +#define AA_x_ratio (this->hidden->x_ratio) +#define AA_y_ratio (this->hidden->y_ratio) + +#define AA_mutex (this->hidden->mutex) +#define AA_in_x11 (this->hidden->in_x11) +#define AA_w (this->hidden->w) +#define AA_h (this->hidden->h) + +#endif /* _SDL_aavideo_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S new file mode 100644 index 0000000..3cd1961 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p.S @@ -0,0 +1,452 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + Chunky to planar conversion routine + 1 byte/pixel -> 4 or 8 bit planes + + Patrice Mandin + Xavier Joubert + Mikael Kalms +*/ + + .globl _SDL_Atari_C2pConvert + .globl _SDL_Atari_C2pConvert8 + .globl _SDL_Atari_C2pConvert4 + .globl _SDL_Atari_C2pConvert4_pal + +/* ------------ Conversion C2P, 8 bits ------------ */ + + .text +_SDL_Atari_C2pConvert8: +#if !defined(__mcoldfire__) + movel sp@(4),c2p_source + movel sp@(8),c2p_dest + movel sp@(12),c2p_width + movel sp@(16),c2p_height + movel sp@(20),c2p_dblligne + movel sp@(24),c2p_srcpitch + movel sp@(28),c2p_dstpitch + + moveml d2-d7/a2-a6,sp@- + + movel c2p_source,c2p_cursrc + movel c2p_dest,c2p_curdst + movel #0x0f0f0f0f,d4 + movel #0x00ff00ff,d5 + movel #0x55555555,d6 + movew c2p_height+2,c2p_row + movew c2p_width+2,d0 + andw #-8,d0 + movew d0,c2p_rowlen + +SDL_Atari_C2p8_rowloop: + + movel c2p_cursrc,a0 + movel c2p_curdst,a1 + + movel a0,a2 + addw c2p_rowlen,a2 + + movel a0@+,d0 + movel a0@+,d1 + movel a0@+,d2 + movel a0@+,d3 +/* + d0 = a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0 + d1 = e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0 + d2 = i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0 + d3 = m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0 +*/ + movel d1,d7 + lsrl #4,d7 + eorl d0,d7 + andl d4,d7 + eorl d7,d0 + lsll #4,d7 + eorl d7,d1 + + movel d3,d7 + lsrl #4,d7 + eorl d2,d7 + andl d4,d7 + eorl d7,d2 + lsll #4,d7 + eorl d7,d3 + + movel d2,d7 + lsrl #8,d7 + eorl d0,d7 + andl d5,d7 + eorl d7,d0 + lsll #8,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #8,d7 + eorl d1,d7 + andl d5,d7 + eorl d7,d1 + lsll #8,d7 + eorl d7,d3 +/* + d0 = a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4 + d1 = a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0 + d2 = b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4 + d3 = b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0 +*/ + bras SDL_Atari_C2p8_start + +SDL_Atari_C2p8_pix16: + + movel a0@+,d0 + movel a0@+,d1 + movel a0@+,d2 + movel a0@+,d3 +/* + d0 = a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0 + d1 = e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0 + d2 = i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0 k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0 + d3 = m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0 o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0 +*/ + movel d1,d7 + lsrl #4,d7 + movel a3,a1@+ + eorl d0,d7 + andl d4,d7 + eorl d7,d0 + lsll #4,d7 + eorl d7,d1 + + movel d3,d7 + lsrl #4,d7 + eorl d2,d7 + andl d4,d7 + eorl d7,d2 + movel a4,a1@+ + lsll #4,d7 + eorl d7,d3 + + movel d2,d7 + lsrl #8,d7 + eorl d0,d7 + andl d5,d7 + eorl d7,d0 + movel a5,a1@+ + lsll #8,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #8,d7 + eorl d1,d7 + andl d5,d7 + eorl d7,d1 + movel a6,a1@+ + lsll #8,d7 + eorl d7,d3 +/* + d0 = a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4 c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4 + d1 = a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0 c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0 + d2 = b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4 d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4 + d3 = b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0 d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0 +*/ + +SDL_Atari_C2p8_start: + + movel d2,d7 + lsrl #1,d7 + eorl d0,d7 + andl d6,d7 + eorl d7,d0 + addl d7,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #1,d7 + eorl d1,d7 + andl d6,d7 + eorl d7,d1 + addl d7,d7 + eorl d7,d3 +/* + d0 = a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 + d1 = a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 + d2 = a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4 + d3 = a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0 +*/ + movew d2,d7 + movew d0,d2 + swap d2 + movew d2,d0 + movew d7,d2 + + movew d3,d7 + movew d1,d3 + swap d3 + movew d3,d1 + movew d7,d3 +/* + d0 = a7b7a5b5e7f7e5f5 i7j7i5j5m7n7m5n5 a6b6a4b4e6f6e4f4 i6j6i4j4m6n6m4n4 + d1 = a3b3a1b1e3f3e1f1 i3j3i1j1m3n3m1n1 a2b2a0b0e2f2e0f0 i2j2i0j0m2n2m0n0 + d2 = c7d7c5d5g7h7g5h5 k7l7k5l5o7p7o5p5 c6d6c4d4g6h6g4h4 k6l6k4l4o6p6o4p4 + d3 = c3d3c1d1g3h3g1h1 k3l3k1l1o3p3o1p1 c2d2c0d0g2h2g0h0 k2l2k0l0o2p2o0p0 +*/ + movel d2,d7 + lsrl #2,d7 + eorl d0,d7 + andl #0x33333333,d7 + eorl d7,d0 + lsll #2,d7 + eorl d7,d2 + + movel d3,d7 + lsrl #2,d7 + eorl d1,d7 + andl #0x33333333,d7 + eorl d7,d1 + lsll #2,d7 + eorl d7,d3 +/* + d0 = a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7 a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6 + d1 = a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3 a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2 + d2 = a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5 a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4 + d3 = a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1 a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0 +*/ + swap d0 + swap d1 + swap d2 + swap d3 + + movel d0,a6 + movel d2,a5 + movel d1,a4 + movel d3,a3 + + cmpl a0,a2 + bgt SDL_Atari_C2p8_pix16 + + movel a3,a1@+ + movel a4,a1@+ + movel a5,a1@+ + movel a6,a1@+ + + /* Double the line ? */ + + movel c2p_srcpitch,d0 + movel c2p_dstpitch,d1 + + tstl c2p_dblligne + beqs SDL_Atari_C2p8_nodblline + + movel c2p_curdst,a0 + movel a0,a1 + addl d1,a1 + + movew c2p_width+2,d7 + lsrw #4,d7 + subql #1,d7 +SDL_Atari_C2p8_dblloop: + movel a0@+,a1@+ + movel a0@+,a1@+ + movel a0@+,a1@+ + movel a0@+,a1@+ + dbra d7,SDL_Atari_C2p8_dblloop + + addl d1,c2p_curdst + +SDL_Atari_C2p8_nodblline: + + /* Next line */ + + addl d0,c2p_cursrc + addl d1,c2p_curdst + + subqw #1,c2p_row + bne SDL_Atari_C2p8_rowloop + + moveml sp@+,d2-d7/a2-a6 +#endif + rts + +/* ------------ Conversion C2P, 4 bits ------------ */ + +_SDL_Atari_C2pConvert4: +#if !defined(__mcoldfire__) + movel sp@(4),c2p_source + movel sp@(8),c2p_dest + movel sp@(12),c2p_width + movel sp@(16),c2p_height + movel sp@(20),c2p_dblligne + movel sp@(24),c2p_srcpitch + movel sp@(28),c2p_dstpitch + + moveml d2-d7/a2-a6,sp@- + + movel c2p_source,a0 + movel c2p_dest,a1 + lea _SDL_Atari_table_c2p,a2 + movel #0x00070001,d3 +#if defined(__mc68020__) + moveq #0,d0 +#endif + + movel c2p_height,d7 + subql #1,d7 +c2p4_bcly: + movel a0,a4 | Save start address of source + movel a1,a5 | Save start address of dest + + | Conversion + + movel c2p_width,d6 + lsrw #4,d6 + subql #1,d6 +c2p4_bclx: + | Octets 0-7 + + moveq #0,d1 + moveq #7,d5 +c2p4_bcl07: +#if defined(__mc68020__) + moveb a0@+,d0 + lea a2@(0,d0:w:4),a3 +#else + moveq #0,d0 + moveb a0@+,d0 + lslw #2,d0 + lea a2@(0,d0:w),a3 +#endif + lsll #1,d1 + orl a3@,d1 + dbra d5,c2p4_bcl07 + + movepl d1,a1@(0) + addw d3,a1 + swap d3 + + | Octets 8-15 + + moveq #0,d1 + moveq #7,d5 +c2p4_bcl815: +#if defined(__mc68020__) + moveb a0@+,d0 + lea a2@(0,d0:w:4),a3 +#else + moveq #0,d0 + moveb a0@+,d0 + lslw #2,d0 + lea a2@(0,d0:w),a3 +#endif + lsll #1,d1 + orl a3@,d1 + dbra d5,c2p4_bcl815 + + movepl d1,a1@(0) + addw d3,a1 + swap d3 + + dbra d6,c2p4_bclx + + | Double line ? + + tstl c2p_dblligne + beqs c2p4_nodblligne + + movel a5,a6 | src line + movel a5,a1 | dest line + addl c2p_dstpitch,a1 + + movel c2p_width,d6 + lsrw #3,d6 + subql #1,d6 +c2p4_copydbl: + movel a6@+,a1@+ + dbra d6,c2p4_copydbl + + addl c2p_dstpitch,a5 +c2p4_nodblligne: + + | Next line + + movel a4,a0 + addl c2p_srcpitch,a0 + movel a5,a1 + addl c2p_dstpitch,a1 + + dbra d7,c2p4_bcly + + moveml sp@+,d2-d7/a2-a6 +#endif + rts + +/* ------------ Conversion of a light palette in 4 bits ------------ */ + +_SDL_Atari_C2pConvert4_pal: +#if !defined(__mcoldfire__) + /* a0 is a 256-word light palette */ + movel sp@(4),a0 + + moveml d2-d3,sp@- + + lea _SDL_Atari_table_c2p,a1 + movew #255,d3 +c2p_pal_initbcl: + movew a0@+,d0 + lsrw #4,d0 + andw #15,d0 + + moveq #3,d1 +c2p_pal_initbyte: + btst d1,d0 + sne d2 + negw d2 + moveb d2,a1@(0,d1:w) + + dbra d1,c2p_pal_initbyte + + addql #4,a1 + dbra d3,c2p_pal_initbcl + + moveml sp@+,d2-d3 +#endif + rts + +/* ------------ Buffers ------------ */ + + .bss + + .even + .comm _SDL_Atari_C2pConvert,4 + .comm _SDL_Atari_table_c2p,1024 + + .comm c2p_source,4 /* Source framebuffer */ + .comm c2p_dest,4 /* Destination framebuffer */ + .comm c2p_width,4 /* Width of zone to convert */ + .comm c2p_height,4 /* Height of zone to convert */ + .comm c2p_dblligne,4 /* Double the lines while converting ? */ + .comm c2p_srcpitch,4 /* Source pitch */ + .comm c2p_dstpitch,4 /* Destination pitch */ + .comm c2p_cursrc,4 /* Current source line */ + .comm c2p_curdst,4 /* Current destination line */ + .comm c2p_rowlen,2 /* Line length in bytes */ + .comm c2p_row,2 /* Current line number */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h new file mode 100644 index 0000000..48bdae7 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataric2p_s.h @@ -0,0 +1,75 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ATARI_C2P_h +#define _ATARI_C2P_h + +#include "SDL_stdinc.h" + +/*--- Functions pointers ---*/ + +/* Convert a chunky screen to bitplane screen */ + +extern void (*SDL_Atari_C2pConvert)( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (4/8 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/*--- 8 bits functions ---*/ + +/* Convert a chunky screen to bitplane screen */ + +void SDL_Atari_C2pConvert8( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (8 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/*--- 4 bits functions ---*/ + +/* Convert a chunky screen to bitplane screen */ + +void SDL_Atari_C2pConvert4( + Uint8 *src, /* Source screen (one byte=one pixel) */ + Uint8 *dest, /* Destination (4 bits planes) */ + Uint32 width, /* Dimensions of screen to convert */ + Uint32 height, + Uint32 dblligne, /* Double the lines when converting ? */ + Uint32 srcpitch, /* Length of one source line in bytes */ + Uint32 dstpitch /* Length of one destination line in bytes */ +); + +/* Conversion palette */ + +void SDL_Atari_C2pConvert4_pal(Uint16 *lightpalette); + +#endif /* _ATARI_C2P_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c new file mode 100644 index 0000000..0527380 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse.c @@ -0,0 +1,159 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT /dev/mouse driver + + Patrice Mandin +*/ + +#include <fcntl.h> +#include <unistd.h> + +#include "../../events/SDL_events_c.h" +#include "SDL_ataridevmouse_c.h" + +/* Defines */ + +#define DEVICE_NAME "/dev/mouse" + +/* Local variables */ + +static int handle = -1; +static int mouseb, prev_mouseb; + +/* Functions */ + +int SDL_AtariDevMouse_Open(void) +{ + int r; + const char *mousedev; + + /* + TODO: Fix the MiNT device driver, that locks mouse for other + applications, so this is disabled till fixed + */ + return 0; + + /* First, try SDL_MOUSEDEV device */ + mousedev = SDL_getenv("SDL_MOUSEDEV"); + if (!mousedev) { + handle = open(mousedev, 0); + } + + /* Failed, try default device */ + if (handle<0) { + handle = open(DEVICE_NAME, 0); + } + + if (handle<0) { + handle = -1; + return 0; + } + + /* Set non blocking mode */ + r = fcntl(handle, F_GETFL, 0); + if (r<0) { + close(handle); + handle = -1; + return 0; + } + + r |= O_NDELAY; + + r = fcntl(handle, F_SETFL, r); + if (r<0) { + close(handle); + handle = -1; + return 0; + } + + prev_mouseb = 7; + return 1; +} + +void SDL_AtariDevMouse_Close(void) +{ + if (handle>0) { + close(handle); + handle = -1; + } +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + case 1: + return SDL_BUTTON_MIDDLE; + default: + break; + } + + return SDL_BUTTON_LEFT; +} + +void SDL_AtariDevMouse_PostMouseEvents(_THIS, SDL_bool buttonEvents) +{ + unsigned char buffer[3]; + int mousex, mousey; + + if (handle<0) { + return; + } + + mousex = mousey = 0; + while (read(handle, buffer, sizeof(buffer))==sizeof(buffer)) { + mouseb = buffer[0] & 7; + mousex += (char) buffer[1]; + mousey += (char) buffer[2]; + + /* Mouse button events */ + if (buttonEvents && (mouseb != prev_mouseb)) { + int i; + + for (i=0;i<3;i++) { + int curbutton, prevbutton; + + curbutton = mouseb & (1<<i); + prevbutton = prev_mouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + } + + prev_mouseb = mouseb; + } + } + + /* Mouse motion event */ + if (mousex || mousey) { + SDL_PrivateMouseMotion(0, 1, mousex, -mousey); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h new file mode 100644 index 0000000..7cae022 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ataridevmouse_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + MiNT /dev/mouse driver + + Patrice Mandin +*/ + +#ifndef _SDL_ATARI_DEVMOUSE_H_ +#define _SDL_ATARI_DEVMOUSE_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern int SDL_AtariDevMouse_Open(void); +extern void SDL_AtariDevMouse_Close(void); +extern void SDL_AtariDevMouse_PostMouseEvents(_THIS, SDL_bool buttonEvents); + +#endif /* _SDL_ATARI_DEVMOUSE_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S new file mode 100644 index 0000000..d8cbf48 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi.S @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * Read EdDI version + * + * Patrice Mandin + */ + + .text + + .globl _Atari_get_EdDI_version + +/*--- Vector installer ---*/ + +_Atari_get_EdDI_version: + movel sp@(4),a0 /* Value of EdDI cookie */ + + /* Call EdDI function #0 */ + clrw d0 + jsr (a0) + + rts diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h new file mode 100644 index 0000000..cd3e524 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarieddi_s.h @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_Atari_eddi_s_h +#define _SDL_Atari_eddi_s_h + +/*--- Defines ---*/ + +/* EdDI versions */ + +#define EDDI_10 (0x0100) +#define EDDI_11 (0x0110) + +/* Screen format */ + +enum { + VDI_FORMAT_UNKNOWN=-1, + VDI_FORMAT_INTER=0, /* Interleaved bitplanes */ + VDI_FORMAT_VDI=1, /* VDI independent */ + VDI_FORMAT_PACK=2 /* Packed pixels */ +}; + +/* CLUT types */ +enum { + VDI_CLUT_NONE=0, /* Monochrome mode */ + VDI_CLUT_HARDWARE, /* <256 colours mode */ + VDI_CLUT_SOFTWARE /* True colour mode */ +}; + +/*--- Functions ---*/ + +unsigned long Atari_get_EdDI_version(void *function_pointer); + +#endif /* _SDL_Atari_eddi_s_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c new file mode 100644 index 0000000..8831275 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents.c @@ -0,0 +1,234 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager + * + * Patrice Mandin + * + * This routines choose what the final event manager will be + */ + +#include <mint/cookie.h> +#include <mint/osbind.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_biosevents_c.h" +#include "SDL_gemdosevents_c.h" +#include "SDL_ikbdevents_c.h" + +enum { + MCH_ST=0, + MCH_STE, + MCH_TT, + MCH_F30, + MCH_CLONE, + MCH_ARANYM +}; + +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[ATARIBIOS_MAXKEYS]; +static char *keytab_normal; + +void (*Atari_ShutdownEvents)(void); + +static void Atari_InitializeEvents(_THIS) +{ + const char *envr; + long cookie_mch; + + /* Test if we are on an Atari machine or not */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = 0; + } + cookie_mch >>= 16; + + /* Default is Ikbd, the faster except for clones */ + switch(cookie_mch) { + case MCH_ST: + case MCH_STE: + case MCH_TT: + case MCH_F30: + case MCH_ARANYM: + this->InitOSKeymap=AtariIkbd_InitOSKeymap; + this->PumpEvents=AtariIkbd_PumpEvents; + Atari_ShutdownEvents=AtariIkbd_ShutdownEvents; + break; + default: + this->InitOSKeymap=AtariGemdos_InitOSKeymap; + this->PumpEvents=AtariGemdos_PumpEvents; + Atari_ShutdownEvents=AtariGemdos_ShutdownEvents; + break; + } + + envr = SDL_getenv("SDL_ATARI_EVENTSDRIVER"); + + if (!envr) { + return; + } + + if (SDL_strcmp(envr, "ikbd") == 0) { + this->InitOSKeymap=AtariIkbd_InitOSKeymap; + this->PumpEvents=AtariIkbd_PumpEvents; + Atari_ShutdownEvents=AtariIkbd_ShutdownEvents; + } + + if (SDL_strcmp(envr, "gemdos") == 0) { + this->InitOSKeymap=AtariGemdos_InitOSKeymap; + this->PumpEvents=AtariGemdos_PumpEvents; + Atari_ShutdownEvents=AtariGemdos_ShutdownEvents; + } + + if (SDL_strcmp(envr, "bios") == 0) { + this->InitOSKeymap=AtariBios_InitOSKeymap; + this->PumpEvents=AtariBios_PumpEvents; + Atari_ShutdownEvents=AtariBios_ShutdownEvents; + } +} + +void Atari_InitOSKeymap(_THIS) +{ + Atari_InitializeEvents(this); + + SDL_Atari_InitInternalKeymap(this); + + /* Call choosen routine */ + this->InitOSKeymap(this); +} + +void SDL_Atari_InitInternalKeymap(_THIS) +{ + int i; + _KEYTAB *key_tables; + + /* Read system tables for scancode -> ascii translation */ + key_tables = (_KEYTAB *) Keytbl(KT_NOCHANGE, KT_NOCHANGE, KT_NOCHANGE); + keytab_normal = key_tables->unshift; + + /* Initialize keymap */ + for ( i=0; i<ATARIBIOS_MAXKEYS; i++ ) + keymap[i] = SDLK_UNKNOWN; + + /* Functions keys */ + for ( i = 0; i<10; i++ ) + keymap[SCANCODE_F1 + i] = SDLK_F1+i; + + /* Cursor keypad */ + keymap[SCANCODE_HELP] = SDLK_HELP; + keymap[SCANCODE_UNDO] = SDLK_UNDO; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_CLRHOME] = SDLK_HOME; + keymap[SCANCODE_UP] = SDLK_UP; + keymap[SCANCODE_DOWN] = SDLK_DOWN; + keymap[SCANCODE_RIGHT] = SDLK_RIGHT; + keymap[SCANCODE_LEFT] = SDLK_LEFT; + + /* Special keys */ + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_DELETE] = SDLK_DELETE; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; +} + +void Atari_PumpEvents(_THIS) +{ + Atari_InitializeEvents(this); + + /* Call choosen routine */ + this->PumpEvents(this); +} + +/* Atari to Unicode charset translation table */ + +Uint16 SDL_AtariToUnicodeTable[256]={ + /* Standard ASCII characters from 0x00 to 0x7e */ + /* Unicode stuff from 0x7f to 0xff */ + + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x0394, + + 0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7, + 0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5, + 0x00C9,0x00E6,0x00C6,0x00F4,0x00F6,0x00F2,0x00FB,0x00F9, + 0x00FF,0x00D6,0x00DC,0x00A2,0x00A3,0x00A5,0x00DF,0x0192, + 0x00E1,0x00ED,0x00F3,0x00FA,0x00F1,0x00D1,0x00AA,0x00BA, + 0x00BF,0x2310,0x00AC,0x00BD,0x00BC,0x00A1,0x00AB,0x00BB, + 0x00C3,0x00F5,0x00D8,0x00F8,0x0153,0x0152,0x00C0,0x00C3, + 0x00D5,0x00A8,0x00B4,0x2020,0x00B6,0x00A9,0x00AE,0x2122, + + 0x0133,0x0132,0x05D0,0x05D1,0x05D2,0x05D3,0x05D4,0x05D5, + 0x05D6,0x05D7,0x05D8,0x05D9,0x05DB,0x05DC,0x05DE,0x05E0, + 0x05E1,0x05E2,0x05E4,0x05E6,0x05E7,0x05E8,0x05E9,0x05EA, + 0x05DF,0x05DA,0x05DD,0x05E3,0x05E5,0x00A7,0x2038,0x221E, + 0x03B1,0x03B2,0x0393,0x03C0,0x03A3,0x03C3,0x00B5,0x03C4, + 0x03A6,0x0398,0x03A9,0x03B4,0x222E,0x03C6,0x2208,0x2229, + 0x2261,0x00B1,0x2265,0x2264,0x2320,0x2321,0x00F7,0x2248, + 0x00B0,0x2022,0x00B7,0x221A,0x207F,0x00B2,0x00B3,0x00AF +}; + +SDL_keysym *SDL_Atari_TranslateKey(int scancode, SDL_keysym *keysym, + SDL_bool pressed) +{ + int asciicode = 0; + + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->mod = KMOD_NONE; + keysym->sym = keymap[scancode]; + keysym->unicode = 0; + + if (keysym->sym == SDLK_UNKNOWN) { + keysym->sym = asciicode = keytab_normal[scancode]; + } + + if (SDL_TranslateUNICODE && pressed) { + keysym->unicode = SDL_AtariToUnicodeTable[asciicode]; + } + + return(keysym); +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h new file mode 100644 index 0000000..a7dd882 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarievents_c.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_EVENTS_H_ +#define _SDL_ATARI_EVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define ATARIBIOS_MAXKEYS 128 + +extern void (*Atari_ShutdownEvents)(void); + +extern void Atari_InitOSKeymap(_THIS); +extern void Atari_PumpEvents(_THIS); + +extern void SDL_Atari_InitInternalKeymap(_THIS); + +/* Atari to Unicode charset translation table */ +extern Uint16 SDL_AtariToUnicodeTable[256]; +SDL_keysym *SDL_Atari_TranslateKey(int scancode, SDL_keysym *keysym, + SDL_bool pressed); + +#endif /* _SDL_ATARI_EVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c new file mode 100644 index 0000000..1cf2689 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl.c @@ -0,0 +1,1086 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Atari OSMesa.ldg implementation of SDL OpenGL support */ + +/*--- Includes ---*/ + +#if SDL_VIDEO_OPENGL +#include <GL/osmesa.h> +#endif + +#include <mint/osbind.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_atarigl_c.h" +#if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC +#include "SDL_loadso.h" +#endif + +/*--- Defines ---*/ + +#define PATH_OSMESA_LDG "osmesa.ldg" +#define PATH_MESAGL_LDG "mesa_gl.ldg" +#define PATH_TINYGL_LDG "tiny_gl.ldg" + +#define VDI_RGB 0xf + +/*--- Functions prototypes ---*/ + +#if SDL_VIDEO_OPENGL +static void SDL_AtariGL_UnloadLibrary(_THIS); + +static void CopyShadowNull(_THIS, SDL_Surface *surface); +static void CopyShadowDirect(_THIS, SDL_Surface *surface); +static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface); +static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface); +static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface); +static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface); +static void CopyShadow8888To555(_THIS, SDL_Surface *surface); +static void CopyShadow8888To565(_THIS, SDL_Surface *surface); + +static void ConvertNull(_THIS, SDL_Surface *surface); +static void Convert565To555be(_THIS, SDL_Surface *surface); +static void Convert565To555le(_THIS, SDL_Surface *surface); +static void Convert565le(_THIS, SDL_Surface *surface); +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface); + +static int InitNew(_THIS, SDL_Surface *current); +static int InitOld(_THIS, SDL_Surface *current); +#endif + +/*--- Public functions ---*/ + +int SDL_AtariGL_Init(_THIS, SDL_Surface *current) +{ +#if SDL_VIDEO_OPENGL + if (gl_oldmesa) { + gl_active = InitOld(this, current); + } else { + gl_active = InitNew(this, current); + } +#endif + + return (gl_active); +} + +void SDL_AtariGL_Quit(_THIS, SDL_bool unload) +{ +#if SDL_VIDEO_OPENGL + if (gl_oldmesa) { + /* Old mesa implementations */ + if (this->gl_data->OSMesaDestroyLDG) { + this->gl_data->OSMesaDestroyLDG(); + } + if (gl_shadow) { + Mfree(gl_shadow); + gl_shadow = NULL; + } + } else { + /* New mesa implementation */ + if (gl_ctx) { + if (this->gl_data->OSMesaDestroyContext) { + this->gl_data->OSMesaDestroyContext(gl_ctx); + } + gl_ctx = NULL; + } + } + + if (unload) { + SDL_AtariGL_UnloadLibrary(this); + } + +#endif /* SDL_VIDEO_OPENGL */ + gl_active = 0; +} + +int SDL_AtariGL_LoadLibrary(_THIS, const char *path) +{ +#if SDL_VIDEO_OPENGL + +#if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC + void *handle; + SDL_bool cancel_load; + + if (gl_active) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + /* Unload previous driver */ + SDL_AtariGL_UnloadLibrary(this); + + /* Load library given by path */ + handle = SDL_LoadObject(path); + if (handle == NULL) { + /* Try to load another one */ + path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); + if ( path != NULL ) { + handle = SDL_LoadObject(path); + } + + /* If it does not work, try some other */ + if (handle == NULL) { + path = PATH_OSMESA_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_MESAGL_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_TINYGL_LDG; + handle = SDL_LoadObject(path); + } + } + + if (handle == NULL) { + SDL_SetError("Could not load OpenGL library"); + return -1; + } + + this->gl_data->glGetIntegerv = SDL_LoadFunction(handle, "glGetIntegerv"); + this->gl_data->glFinish = SDL_LoadFunction(handle, "glFinish"); + this->gl_data->glFlush = SDL_LoadFunction(handle, "glFlush"); + + cancel_load = SDL_FALSE; + if (this->gl_data->glGetIntegerv == NULL) { + cancel_load = SDL_TRUE; + } else { + /* We need either glFinish (OSMesa) or glFlush (TinyGL) */ + if ((this->gl_data->glFinish == NULL) && + (this->gl_data->glFlush == NULL)) { + cancel_load = SDL_TRUE; + } + } + if (cancel_load) { + SDL_SetError("Could not retrieve OpenGL functions"); + SDL_UnloadObject(handle); + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + return -1; + } + + /* Load functions pointers (osmesa.ldg) */ + this->gl_data->OSMesaCreateContextExt = SDL_LoadFunction(handle, "OSMesaCreateContextExt"); + this->gl_data->OSMesaDestroyContext = SDL_LoadFunction(handle, "OSMesaDestroyContext"); + this->gl_data->OSMesaMakeCurrent = SDL_LoadFunction(handle, "OSMesaMakeCurrent"); + this->gl_data->OSMesaPixelStore = SDL_LoadFunction(handle, "OSMesaPixelStore"); + this->gl_data->OSMesaGetProcAddress = SDL_LoadFunction(handle, "OSMesaGetProcAddress"); + + /* Load old functions pointers (mesa_gl.ldg, tiny_gl.ldg) */ + this->gl_data->OSMesaCreateLDG = SDL_LoadFunction(handle, "OSMesaCreateLDG"); + this->gl_data->OSMesaDestroyLDG = SDL_LoadFunction(handle, "OSMesaDestroyLDG"); + + gl_oldmesa = 0; + + if ( (this->gl_data->OSMesaCreateContextExt == NULL) || + (this->gl_data->OSMesaDestroyContext == NULL) || + (this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL) || + (this->gl_data->OSMesaGetProcAddress == NULL)) { + /* Hum, maybe old library ? */ + if ( (this->gl_data->OSMesaCreateLDG == NULL) || + (this->gl_data->OSMesaDestroyLDG == NULL)) { + SDL_SetError("Could not retrieve OSMesa functions"); + SDL_UnloadObject(handle); + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + return -1; + } else { + gl_oldmesa = 1; + } + } + + this->gl_config.dll_handle = handle; + if ( path ) { + SDL_strlcpy(this->gl_config.driver_path, path, + SDL_arraysize(this->gl_config.driver_path)); + } else { + *this->gl_config.driver_path = '\0'; + } + +#endif + this->gl_config.driver_loaded = 1; + + return 0; +#else + return -1; +#endif +} + +void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc) +{ + void *func = NULL; +#if SDL_VIDEO_OPENGL + + if (this->gl_config.dll_handle) { + func = SDL_LoadFunction(this->gl_config.dll_handle, (void *)proc); + } else if (this->gl_data->OSMesaGetProcAddress) { + func = this->gl_data->OSMesaGetProcAddress(proc); + } + +#endif + return func; +} + +int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ +#if SDL_VIDEO_OPENGL + GLenum mesa_attrib; + SDL_Surface *surface; + + if (!gl_active) { + return -1; + } + + switch(attrib) { + case SDL_GL_RED_SIZE: + mesa_attrib = GL_RED_BITS; + break; + case SDL_GL_GREEN_SIZE: + mesa_attrib = GL_GREEN_BITS; + break; + case SDL_GL_BLUE_SIZE: + mesa_attrib = GL_BLUE_BITS; + break; + case SDL_GL_ALPHA_SIZE: + mesa_attrib = GL_ALPHA_BITS; + break; + case SDL_GL_DOUBLEBUFFER: + surface = this->screen; + *value = ((surface->flags & SDL_DOUBLEBUF)==SDL_DOUBLEBUF); + return 0; + case SDL_GL_DEPTH_SIZE: + mesa_attrib = GL_DEPTH_BITS; + break; + case SDL_GL_STENCIL_SIZE: + mesa_attrib = GL_STENCIL_BITS; + break; + case SDL_GL_ACCUM_RED_SIZE: + mesa_attrib = GL_ACCUM_RED_BITS; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + mesa_attrib = GL_ACCUM_GREEN_BITS; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + mesa_attrib = GL_ACCUM_BLUE_BITS; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + mesa_attrib = GL_ACCUM_ALPHA_BITS; + break; + default : + return -1; + } + + this->gl_data->glGetIntegerv(mesa_attrib, value); + return 0; +#else + return -1; +#endif +} + +int SDL_AtariGL_MakeCurrent(_THIS) +{ +#if SDL_VIDEO_OPENGL + SDL_Surface *surface; + GLenum type; + + if (gl_oldmesa && gl_active) { + return 0; + } + + if (this->gl_config.dll_handle) { + if ((this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL)) { + return -1; + } + } + + if (!gl_active) { + SDL_SetError("Invalid OpenGL context"); + return -1; + } + + surface = this->screen; + + if ((surface->format->BitsPerPixel == 15) || (surface->format->BitsPerPixel == 16)) { + type = GL_UNSIGNED_SHORT_5_6_5; + } else { + type = GL_UNSIGNED_BYTE; + } + + if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h))) { + SDL_SetError("Can not make OpenGL context current"); + return -1; + } + + /* OSMesa draws upside down */ + this->gl_data->OSMesaPixelStore(OSMESA_Y_UP, 0); + + return 0; +#else + return -1; +#endif +} + +void SDL_AtariGL_SwapBuffers(_THIS) +{ +#if SDL_VIDEO_OPENGL + if (gl_active) { + if (this->gl_config.dll_handle) { + if (this->gl_data->glFinish) { + this->gl_data->glFinish(); + } else if (this->gl_data->glFlush) { + this->gl_data->glFlush(); + } + } else { + this->gl_data->glFinish(); + } + gl_copyshadow(this, this->screen); + gl_convert(this, this->screen); + } +#endif +} + +void SDL_AtariGL_InitPointers(_THIS) +{ +#if SDL_VIDEO_OPENGL + this->gl_data->OSMesaCreateContextExt = OSMesaCreateContextExt; + this->gl_data->OSMesaDestroyContext = OSMesaDestroyContext; + this->gl_data->OSMesaMakeCurrent = OSMesaMakeCurrent; + this->gl_data->OSMesaPixelStore = OSMesaPixelStore; + this->gl_data->OSMesaGetProcAddress = OSMesaGetProcAddress; + + this->gl_data->glGetIntegerv = glGetIntegerv; + this->gl_data->glFinish = glFinish; + this->gl_data->glFlush = glFlush; + + this->gl_data->OSMesaCreateLDG = NULL; + this->gl_data->OSMesaDestroyLDG = NULL; +#endif +} + +/*--- Private functions ---*/ + +#if SDL_VIDEO_OPENGL +static void SDL_AtariGL_UnloadLibrary(_THIS) +{ + if (this->gl_config.dll_handle) { + SDL_UnloadObject(this->gl_config.dll_handle); + this->gl_config.dll_handle = NULL; + + /* Restore pointers to static library */ + SDL_AtariGL_InitPointers(this); + } +} + +/*--- Creation of an OpenGL context using new/old functions ---*/ + +static int InitNew(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + int recreatecontext; + GLint newaccumsize; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateContextExt == NULL) { + return 0; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + gl_upsidedown = SDL_FALSE; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 1555, big and little endian, unsupported */ + gl_pixelsize = 2; + osmesa_format = OSMESA_RGB_565; + if (redmask == 31<<10) { + gl_convert = Convert565To555be; + } else { + gl_convert = Convert565To555le; + } + break; + case 16: + gl_pixelsize = 2; + if (redmask == 31<<11) { + osmesa_format = OSMESA_RGB_565; + } else { + /* 565, little endian, unsupported */ + osmesa_format = OSMESA_RGB_565; + gl_convert = Convert565le; + } + break; + case 24: + gl_pixelsize = 3; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + break; + case 32: + gl_pixelsize = 4; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + break; + default: + gl_pixelsize = 1; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + /* Try to keep current context if possible */ + newaccumsize = + this->gl_config.accum_red_size + + this->gl_config.accum_green_size + + this->gl_config.accum_blue_size + + this->gl_config.accum_alpha_size; + recreatecontext=1; + if (gl_ctx && + (gl_curformat == osmesa_format) && + (gl_curdepth == this->gl_config.depth_size) && + (gl_curstencil == this->gl_config.stencil_size) && + (gl_curaccum == newaccumsize)) { + recreatecontext = 0; + } + if (recreatecontext) { + SDL_AtariGL_Quit(this, SDL_FALSE); + + gl_ctx = this->gl_data->OSMesaCreateContextExt( + osmesa_format, this->gl_config.depth_size, + this->gl_config.stencil_size, newaccumsize, NULL ); + + if (gl_ctx) { + gl_curformat = osmesa_format; + gl_curdepth = this->gl_config.depth_size; + gl_curstencil = this->gl_config.stencil_size; + gl_curaccum = newaccumsize; + } else { + gl_curformat = 0; + gl_curdepth = 0; + gl_curstencil = 0; + gl_curaccum = 0; + } + } + + return (gl_ctx != NULL); +} + + +static int InitOld(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + int recreatecontext, tinygl_present; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateLDG == NULL) { + return 0; + } + } + + /* TinyGL only supports VDI_RGB (OSMESA_RGB) */ + tinygl_present=0; + if (this->gl_config.dll_handle) { + if (this->gl_data->glFinish == NULL) { + tinygl_present=1; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + gl_upsidedown = SDL_FALSE; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 15 bits unsupported */ + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + if (redmask == 31<<10) { + gl_copyshadow = CopyShadowRGBTo555; + } else { + gl_copyshadow = CopyShadowRGBTo565; + gl_convert = Convert565To555le; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + osmesa_format = OSMESA_ARGB; + if (redmask == 31<<10) { + gl_copyshadow = CopyShadow8888To555; + } else { + gl_copyshadow = CopyShadow8888To565; + gl_convert = Convert565To555le; + } + } + break; + case 16: + /* 16 bits unsupported */ + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowRGBTo565; + if (redmask != 31<<11) { + /* 565, little endian, unsupported */ + gl_convert = Convert565le; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + osmesa_format = OSMESA_ARGB; + gl_copyshadow = CopyShadow8888To565; + if (redmask != 31<<11) { + /* 565, little endian, unsupported */ + gl_convert = Convert565le; + } + } + break; + case 24: + gl_pixelsize = 3; + if (tinygl_present) { + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowDirect; + if (redmask != 255<<16) { + gl_copyshadow = CopyShadowRGBSwap; + } + } else { + gl_copyshadow = CopyShadowDirect; + gl_upsidedown = SDL_TRUE; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + } + break; + case 32: + if (tinygl_present) { + gl_pixelsize = 3; + osmesa_format = VDI_RGB; + gl_copyshadow = CopyShadowRGBToARGB; + if (redmask == 255) { + gl_convert = CopyShadowRGBToABGR; + } else if (redmask == 255<<8) { + gl_convert = CopyShadowRGBToBGRA; + } else if (redmask == 255<<24) { + gl_convert = CopyShadowRGBToRGBA; + } + } else { + gl_pixelsize = 4; + gl_upsidedown = SDL_TRUE; + gl_copyshadow = CopyShadowDirect; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + } + break; + default: + if (tinygl_present) { + SDL_AtariGL_Quit(this, SDL_FALSE); + return 0; + } + gl_pixelsize = 1; + gl_copyshadow = CopyShadowDirect; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + /* Try to keep current context if possible */ + recreatecontext=1; + if (gl_shadow && + (gl_curformat == osmesa_format) && + (gl_curwidth == current->w) && + (gl_curheight == current->h)) { + recreatecontext = 0; + } + if (recreatecontext) { + SDL_AtariGL_Quit(this, SDL_FALSE); + + gl_shadow = this->gl_data->OSMesaCreateLDG( + osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h + ); + + if (gl_shadow) { + gl_curformat = osmesa_format; + gl_curwidth = current->w; + gl_curheight = current->h; + } else { + gl_curformat = 0; + gl_curwidth = 0; + gl_curheight = 0; + } + } + + return (gl_shadow != NULL); +} + +/*--- Conversions routines from shadow buffer to the screen ---*/ + +static void CopyShadowNull(_THIS, SDL_Surface *surface) +{ +} + +static void CopyShadowDirect(_THIS, SDL_Surface *surface) +{ + int y, srcpitch, dstpitch; + Uint8 *srcline, *dstline; + + srcline = gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + SDL_memcpy(dstline, srcline, srcpitch); + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + for (x=0; x<surface->w; x++) { + Uint16 dstcolor; + + dstcolor = ((*srccol++)<<7) & (31<<10); + dstcolor |= ((*srccol++)<<2) & (31<<5); + dstcolor |= ((*srccol++)>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint16 dstcolor; + + dstcolor = ((*srccol++)<<8) & (31<<11); + dstcolor |= ((*srccol++)<<3) & (63<<5); + dstcolor |= ((*srccol++)>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint8 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + *dstcol++ = srccol[2]; + *dstcol++ = srccol[1]; + *dstcol++ = srccol[0]; + srccol += 3; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<16; + dstcolor |= (*srccol++)<<8; + dstcolor |= *srccol++; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = *srccol++; + dstcolor |= (*srccol++)<<8; + dstcolor |= (*srccol++)<<16; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<8; + dstcolor |= (*srccol++)<<16; + dstcolor |= (*srccol++)<<24; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint32 *dstline, *dstcol; + Uint8 *srcline, *srccol; + + srcline = (Uint8 *)gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch >>2; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 dstcolor; + + dstcolor = (*srccol++)<<24; + dstcolor |= (*srccol++)<<16; + dstcolor |= (*srccol++)<<8; + + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To555(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = (surface->w * gl_pixelsize) >>2; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>9) & (31<<10); + dstcolor |= (srccolor>>6) & (31<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To565(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = (surface->w * gl_pixelsize) >> 2; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + if (gl_upsidedown) { + srcline += (surface->h-1)*srcpitch; + srcpitch = -srcpitch; + } + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>8) & (31<<11); + dstcolor |= (srccolor>>5) & (63<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +/*--- Conversions routines in the screen ---*/ + +static void ConvertNull(_THIS, SDL_Surface *surface) +{ +} + +static void Convert565To555be(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >> 1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + *pixel++ = (color & 0x1f)|((color>>1) & 0xffe0); + } + + line += pitch; + } +} + +static void Convert565To555le(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + color = (color & 0x1f)|((color>>1) & 0xffe0); + *pixel++ = SDL_Swap16(color); + } + + line += pitch; + } +} + +static void Convert565le(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned short *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>1; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned short color = *pixel; + + *pixel++ = SDL_Swap16(color); + } + + line += pitch; + } +} + +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface) +{ + int x,y, pitch; + unsigned long *line, *pixel; + + line = surface->pixels; + pitch = surface->pitch >>2; + for (y=0; y<surface->h; y++) { + pixel = line; + for (x=0; x<surface->w; x++) { + unsigned long color = *pixel; + + *pixel++ = (color<<24)|(color>>8); + } + + line += pitch; + } +} + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h new file mode 100644 index 0000000..5adcf2a --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarigl_c.h @@ -0,0 +1,109 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Atari OSMesa.ldg implementation of SDL OpenGL support */ + +#ifndef _SDL_ATARIGL_H_ +#define _SDL_ATARIGL_H_ + +#if SDL_VIDEO_OPENGL +#include <GL/osmesa.h> +#endif + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +struct SDL_PrivateGLData { + + int gl_active; /* to stop switching drivers while we have a valid context */ + + int gl_oldmesa; /* Old OpenGL support ? */ + + int gl_pixelsize; /* for CopyShadow functions */ + + SDL_bool gl_upsidedown; /* Some implementations draw upside down */ + + Uint8 *gl_shadow; /* Shadow buffer for old implementations */ + + /* for unsupported OSMesa buffer formats */ + void (*ConvertSurface)(_THIS, SDL_Surface *surface); + + /* to convert the shadow buffer to the screen format */ + void (*CopyShadow)(_THIS, SDL_Surface *surface); + +#if SDL_VIDEO_OPENGL + OSMesaContext ctx; + + /* OpenGL functions */ + void (*glGetIntegerv)( GLenum pname, GLint *value ); + void (*glFinish)(void); + void (*glFlush)(void); + + /* osmesa.ldg */ + OSMesaContext (*OSMesaCreateContextExt)( GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, OSMesaContext sharelist); + void (*OSMesaDestroyContext)( OSMesaContext ctx ); + GLboolean (*OSMesaMakeCurrent)( OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height ); + void (*OSMesaPixelStore)( GLint pname, GLint value ); + void * (*OSMesaGetProcAddress)( const char *funcName ); + + /* mesa_gl.ldg, tiny_gl.ldg */ + void *(*OSMesaCreateLDG)( long format, long type, long width, long height ); + void (*OSMesaDestroyLDG)(void); + + /* Info needed to compare existing context with new asked one */ + int width, height; + GLenum format; + GLint depth,stencil,accum; +#endif +}; + +/* Variable names */ +#define gl_active (this->gl_data->gl_active) +#define gl_ctx (this->gl_data->ctx) +#define gl_oldmesa (this->gl_data->gl_oldmesa) +#define gl_pixelsize (this->gl_data->gl_pixelsize) +#define gl_upsidedown (this->gl_data->gl_upsidedown) +#define gl_shadow (this->gl_data->gl_shadow) +#define gl_convert (this->gl_data->ConvertSurface) +#define gl_copyshadow (this->gl_data->CopyShadow) +#define gl_curformat (this->gl_data->format) +#define gl_curdepth (this->gl_data->depth) +#define gl_curstencil (this->gl_data->stencil) +#define gl_curaccum (this->gl_data->accum) +#define gl_curwidth (this->gl_data->width) +#define gl_curheight (this->gl_data->height) + +/* OpenGL functions */ +extern int SDL_AtariGL_Init(_THIS, SDL_Surface *current); +extern void SDL_AtariGL_Quit(_THIS, SDL_bool unload); +extern void SDL_AtariGL_InitPointers(_THIS); + +extern int SDL_AtariGL_LoadLibrary(_THIS, const char *path); +extern void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc); +extern int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern int SDL_AtariGL_MakeCurrent(_THIS); +extern void SDL_AtariGL_SwapBuffers(_THIS); + +#endif /* _SDL_ATARIGL_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h new file mode 100644 index 0000000..a9f7cfd --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarikeys.h @@ -0,0 +1,140 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * Atari Scancode definitions + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARIKEYS_H_ +#define _SDL_ATARIKEYS_H_ + +/* --- Keyboard scancodes --- */ +/* taken from svgalib/vgakeyboard.h */ + +#define SCANCODE_ESCAPE 0x01 +#define SCANCODE_1 0x02 +#define SCANCODE_2 0x03 +#define SCANCODE_3 0x04 +#define SCANCODE_4 0x05 +#define SCANCODE_5 0x06 +#define SCANCODE_6 0x07 +#define SCANCODE_7 0x08 +#define SCANCODE_8 0x09 +#define SCANCODE_9 0x0a +#define SCANCODE_0 0x0b +#define SCANCODE_MINUS 0x0c +#define SCANCODE_EQUAL 0x0d +#define SCANCODE_BACKSPACE 0x0e + +#define SCANCODE_TAB 0x0f +#define SCANCODE_Q 0x10 +#define SCANCODE_W 0x11 +#define SCANCODE_E 0x12 +#define SCANCODE_R 0x13 +#define SCANCODE_T 0x14 +#define SCANCODE_Y 0x15 +#define SCANCODE_U 0x16 +#define SCANCODE_I 0x17 +#define SCANCODE_O 0x18 +#define SCANCODE_P 0x19 +#define SCANCODE_BRACKET_LEFT 0x1a +#define SCANCODE_BRACKET_RIGHT 0x1b +#define SCANCODE_ENTER 0x1c +#define SCANCODE_DELETE 0x53 + +#define SCANCODE_LEFTCONTROL 0x1d +#define SCANCODE_A 0x1e +#define SCANCODE_S 0x1f +#define SCANCODE_D 0x20 +#define SCANCODE_F 0x21 +#define SCANCODE_G 0x22 +#define SCANCODE_H 0x23 +#define SCANCODE_J 0x24 +#define SCANCODE_K 0x25 +#define SCANCODE_L 0x26 +#define SCANCODE_SEMICOLON 0x27 +#define SCANCODE_APOSTROPHE 0x28 +#define SCANCODE_GRAVE 0x29 + +#define SCANCODE_LEFTSHIFT 0x2a +#define SCANCODE_BACKSLASH 0x2b +#define SCANCODE_Z 0x2c +#define SCANCODE_X 0x2d +#define SCANCODE_C 0x2e +#define SCANCODE_V 0x2f +#define SCANCODE_B 0x30 +#define SCANCODE_N 0x31 +#define SCANCODE_M 0x32 +#define SCANCODE_COMMA 0x33 +#define SCANCODE_PERIOD 0x34 +#define SCANCODE_SLASH 0x35 +#define SCANCODE_RIGHTSHIFT 0x36 + +#define SCANCODE_LEFTALT 0x38 +#define SCANCODE_SPACE 0x39 +#define SCANCODE_CAPSLOCK 0x3a + +/* Functions keys */ +#define SCANCODE_F1 0x3b +#define SCANCODE_F2 0x3c +#define SCANCODE_F3 0x3d +#define SCANCODE_F4 0x3e +#define SCANCODE_F5 0x3f +#define SCANCODE_F6 0x40 +#define SCANCODE_F7 0x41 +#define SCANCODE_F8 0x42 +#define SCANCODE_F9 0x43 +#define SCANCODE_F10 0x44 + +/* Numeric keypad */ +#define SCANCODE_KP0 0x70 +#define SCANCODE_KP1 0x6d +#define SCANCODE_KP2 0x6e +#define SCANCODE_KP3 0x6f +#define SCANCODE_KP4 0x6a +#define SCANCODE_KP5 0x6b +#define SCANCODE_KP6 0x6c +#define SCANCODE_KP7 0x67 +#define SCANCODE_KP8 0x68 +#define SCANCODE_KP9 0x69 +#define SCANCODE_KP_PERIOD 0x71 +#define SCANCODE_KP_DIVIDE 0x65 +#define SCANCODE_KP_MULTIPLY 0x66 +#define SCANCODE_KP_MINUS 0x4a +#define SCANCODE_KP_PLUS 0x4e +#define SCANCODE_KP_ENTER 0x72 +#define SCANCODE_KP_LEFTPAREN 0x63 +#define SCANCODE_KP_RIGHTPAREN 0x64 + +/* Cursor keypad */ +#define SCANCODE_HELP 0x62 +#define SCANCODE_UNDO 0x61 +#define SCANCODE_INSERT 0x52 +#define SCANCODE_CLRHOME 0x47 +#define SCANCODE_UP 0x48 +#define SCANCODE_DOWN 0x50 +#define SCANCODE_RIGHT 0x4d +#define SCANCODE_LEFT 0x4b + +#endif /* _SDL_ATARIKEYS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c new file mode 100644 index 0000000..224baef --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc.c @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Memory allocation + * + * Patrice Mandin + */ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/*--- Variables ---*/ + +static int atari_mxalloc_avail=-1; + +/*--- Functions ---*/ + +void *Atari_SysMalloc(Uint32 size, Uint16 alloc_type) +{ + /* Test if Mxalloc() available */ + if (atari_mxalloc_avail<0) { + atari_mxalloc_avail = ((Sversion()&0xFF)>=0x01) | (Sversion()>=0x1900); + } + + if (atari_mxalloc_avail) { + return (void *) Mxalloc(size, alloc_type); + } else { + return (void *) Malloc(size); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h new file mode 100644 index 0000000..937408d --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarimxalloc_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Memory allocation + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_MXALLOC_H_ +#define _SDL_ATARI_MXALLOC_H_ + +/*--- Functions ---*/ + +extern void *Atari_SysMalloc(Uint32 size, Uint16 alloc_type); + +#endif /* _SDL_ATARI_MXALLOC_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h b/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h new file mode 100644 index 0000000..8f25c7e --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_atarisuper.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _ATARI_SUPER_h +#define _ATARI_SUPER_h + +#include "SDL_stdinc.h" + +#ifndef SuperToUser + +/* + * Safe binding to switch back from supervisor to user mode. + * On TOS or EmuTOS, if the stack pointer has changed between Super(0) + * and Super(oldssp), the resulting user stack pointer is wrong. + * This bug does not occur with FreeMiNT. + * So the safe way to return from supervisor to user mode is to backup + * the stack pointer then restore it after the trap. + * Sometimes, GCC optimizes the stack usage, so this matters. + */ +#define SuperToUser(ptr) \ +(void)__extension__ \ +({ \ + register long retvalue __asm__("d0"); \ + register long sp_backup; \ + \ + __asm__ volatile \ + ( \ + "movl sp,%1\n\t" \ + "movl %2,sp@-\n\t" \ + "movw #0x20,sp@-\n\t" \ + "trap #1\n\t" \ + "movl %1,sp\n\t" \ + : "=r"(retvalue), "=&r"(sp_backup) /* outputs */ \ + : "g"((long)(ptr)) /* inputs */ \ + : "d1", "d2", "a0", "a1", "a2" \ + ); \ +}) + +#endif /* SuperToUser */ + +#endif /* _ATARI_SUPER_h */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c new file mode 100644 index 0000000..3d36b2b --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents.c @@ -0,0 +1,131 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using BIOS + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_ataridevmouse_c.h" + +static unsigned char bios_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char bios_previouskeyboard[ATARIBIOS_MAXKEYS]; +static SDL_bool use_dev_mouse = SDL_FALSE; + +static void UpdateSpecialKeys(int special_keys_state); + +void AtariBios_InitOSKeymap(_THIS) +{ + int vectors_mask; +/* unsigned long dummy;*/ + + SDL_memset(bios_currentkeyboard, 0, sizeof(bios_currentkeyboard)); + SDL_memset(bios_previouskeyboard, 0, sizeof(bios_previouskeyboard)); + + use_dev_mouse = (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!use_dev_mouse) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + + SDL_AtariXbios_InstallVectors(vectors_mask); +} + +void AtariBios_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /* Update pressed keys */ + SDL_memset(bios_currentkeyboard, 0, ATARIBIOS_MAXKEYS); + + while (Bconstat(_CON)) { + unsigned long key_pressed; + key_pressed=Bconin(_CON); + bios_currentkeyboard[(key_pressed>>16)&(ATARIBIOS_MAXKEYS-1)]=0xFF; + } + + /* Read special keys */ + UpdateSpecialKeys(Kbshift(-1)); + + /* Now generate events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (bios_currentkeyboard[i] && !bios_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (bios_previouskeyboard[i] && !bios_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + if (use_dev_mouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_TRUE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_TRUE); + } + + /* Will be previous table */ + SDL_memcpy(bios_previouskeyboard, bios_currentkeyboard, sizeof(bios_previouskeyboard)); +} + +static void UpdateSpecialKeys(int special_keys_state) +{ +#define UPDATE_SPECIAL_KEYS(numbit,scancode) \ + { \ + if (special_keys_state & (1<<(numbit))) { \ + bios_currentkeyboard[scancode]=0xFF; \ + } \ + } + + UPDATE_SPECIAL_KEYS(K_RSHIFT, SCANCODE_RIGHTSHIFT); + UPDATE_SPECIAL_KEYS(K_LSHIFT, SCANCODE_LEFTSHIFT); + UPDATE_SPECIAL_KEYS(K_CTRL, SCANCODE_LEFTCONTROL); + UPDATE_SPECIAL_KEYS(K_ALT, SCANCODE_LEFTALT); + UPDATE_SPECIAL_KEYS(K_CAPSLOCK, SCANCODE_CAPSLOCK); +} + +void AtariBios_ShutdownEvents(void) +{ + SDL_AtariXbios_RestoreVectors(); + if (use_dev_mouse) { + SDL_AtariDevMouse_Close(); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h new file mode 100644 index 0000000..f016e6a --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_biosevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using BIOS + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_BIOSEVENTS_H_ +#define _SDL_ATARI_BIOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariBios_InitOSKeymap(_THIS); +extern void AtariBios_PumpEvents(_THIS); +extern void AtariBios_ShutdownEvents(void); + +#endif /* _SDL_ATARI_BIOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c new file mode 100644 index 0000000..e1ebaa6 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents.c @@ -0,0 +1,132 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using Gemdos + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_ataridevmouse_c.h" + +/* To save state of keyboard */ + +static unsigned char gemdos_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char gemdos_previouskeyboard[ATARIBIOS_MAXKEYS]; +static SDL_bool use_dev_mouse = SDL_FALSE; + +static void UpdateSpecialKeys(int special_keys_state); + +void AtariGemdos_InitOSKeymap(_THIS) +{ + int vectors_mask; +/* unsigned long dummy;*/ + + SDL_memset(gemdos_currentkeyboard, 0, sizeof(gemdos_currentkeyboard)); + SDL_memset(gemdos_previouskeyboard, 0, sizeof(gemdos_previouskeyboard)); + + use_dev_mouse = (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!use_dev_mouse) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + SDL_AtariXbios_InstallVectors(vectors_mask); +} + +void AtariGemdos_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /* Update pressed keys */ + SDL_memset(gemdos_currentkeyboard, 0, ATARIBIOS_MAXKEYS); + + while (Cconis()!=DEV_BUSY) { + unsigned long key_pressed; + key_pressed=Cnecin(); + gemdos_currentkeyboard[(key_pressed>>16)&(ATARIBIOS_MAXKEYS-1)]=0xFF; + } + + /* Read special keys */ + UpdateSpecialKeys(Kbshift(-1)); + + /* Now generate events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (gemdos_currentkeyboard[i] && !gemdos_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (gemdos_previouskeyboard[i] && !gemdos_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + if (use_dev_mouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_TRUE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_TRUE); + } + + /* Will be previous table */ + SDL_memcpy(gemdos_previouskeyboard, gemdos_currentkeyboard, sizeof(gemdos_previouskeyboard)); +} + +static void UpdateSpecialKeys(int special_keys_state) +{ +#define UPDATE_SPECIAL_KEYS(numbit,scancode) \ + { \ + if (special_keys_state & (1<<(numbit))) { \ + gemdos_currentkeyboard[scancode]=0xFF; \ + } \ + } + + UPDATE_SPECIAL_KEYS(K_RSHIFT, SCANCODE_RIGHTSHIFT); + UPDATE_SPECIAL_KEYS(K_LSHIFT, SCANCODE_LEFTSHIFT); + UPDATE_SPECIAL_KEYS(K_CTRL, SCANCODE_LEFTCONTROL); + UPDATE_SPECIAL_KEYS(K_ALT, SCANCODE_LEFTALT); + UPDATE_SPECIAL_KEYS(K_CAPSLOCK, SCANCODE_CAPSLOCK); +} + +void AtariGemdos_ShutdownEvents(void) +{ + SDL_AtariXbios_RestoreVectors(); + if (use_dev_mouse) { + SDL_AtariDevMouse_Close(); + } +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h new file mode 100644 index 0000000..b9924e6 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_gemdosevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using Gemdos + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_GEMDOSEVENTS_H_ +#define _SDL_ATARI_GEMDOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariGemdos_InitOSKeymap(_THIS); +extern void AtariGemdos_PumpEvents(_THIS); +extern void AtariGemdos_ShutdownEvents(void); + +#endif /* _SDL_ATARI_GEMDOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c new file mode 100644 index 0000000..35fc5cb --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents.c @@ -0,0 +1,124 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using hardware IKBD + * + * Patrice Mandin + */ + +/* Mint includes */ +#include <mint/osbind.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_atarikeys.h" +#include "SDL_atarievents_c.h" +#include "SDL_ikbdinterrupt_s.h" + +#define KEY_PRESSED 0xff +#define KEY_UNDEFINED 0x80 +#define KEY_RELEASED 0x00 + +static Uint16 atari_prevmouseb; /* save state of mouse buttons */ + +void AtariIkbd_InitOSKeymap(_THIS) +{ + SDL_memset((void *) SDL_AtariIkbd_keyboard, KEY_UNDEFINED, sizeof(SDL_AtariIkbd_keyboard)); + + /* Now install our handler */ + SDL_AtariIkbd_mouseb = SDL_AtariIkbd_mousex = SDL_AtariIkbd_mousey = 0; + atari_prevmouseb = 0; + + Supexec(SDL_AtariIkbdInstall); +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + break; + case 1: + default: + return SDL_BUTTON_LEFT; + break; + } +} + +void AtariIkbd_PumpEvents(_THIS) +{ + int i; + SDL_keysym keysym; + + /*--- Send keyboard events ---*/ + + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (SDL_AtariIkbd_keyboard[i]==KEY_PRESSED) { + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + SDL_AtariIkbd_keyboard[i]=KEY_UNDEFINED; + } + + /* Key released ? */ + if (SDL_AtariIkbd_keyboard[i]==KEY_RELEASED) { + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + SDL_AtariIkbd_keyboard[i]=KEY_UNDEFINED; + } + } + + /*--- Send mouse events ---*/ + + /* Mouse motion ? */ + if (SDL_AtariIkbd_mousex || SDL_AtariIkbd_mousey) { + SDL_PrivateMouseMotion(0, 1, SDL_AtariIkbd_mousex, SDL_AtariIkbd_mousey); + SDL_AtariIkbd_mousex = SDL_AtariIkbd_mousey = 0; + } + + /* Mouse button ? */ + if (SDL_AtariIkbd_mouseb != atari_prevmouseb) { + for (i=0;i<2;i++) { + int curbutton, prevbutton; + + curbutton = SDL_AtariIkbd_mouseb & (1<<i); + prevbutton = atari_prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + } + atari_prevmouseb = SDL_AtariIkbd_mouseb; + } +} + +void AtariIkbd_ShutdownEvents(void) +{ + Supexec(SDL_AtariIkbdUninstall); +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h new file mode 100644 index 0000000..753e777 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdevents_c.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Atari keyboard events manager, using hardware IKBD + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_IKBDEVENTS_H_ +#define _SDL_ATARI_IKBDEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +extern void AtariIkbd_InitOSKeymap(_THIS); +extern void AtariIkbd_PumpEvents(_THIS); +extern void AtariIkbd_ShutdownEvents(void); + +#endif /* _SDL_ATARI_IKBDEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S new file mode 100644 index 0000000..21facc8 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt.S @@ -0,0 +1,404 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * IKBD 6301 interrupt routine + * + * Patrice Mandin + */ + + .text + + .globl _SDL_AtariIkbdInstall + .globl _SDL_AtariIkbdUninstall + + .globl _SDL_AtariIkbd_keyboard + .globl _SDL_AtariIkbd_mouseb + .globl _SDL_AtariIkbd_mousex + .globl _SDL_AtariIkbd_mousey + .globl _SDL_AtariIkbd_joystick + + .globl _SDL_AtariIkbd_enabled + +/*--- Install our IKBD vector ---*/ + +_SDL_AtariIkbdInstall: +#if defined(__mcoldfire__) + lea sp@(-16),sp + moveml d0-d1/a0-a1,sp@ +#else + moveml d0-d1/a0-a1,sp@- +#endif + + | Disable interrupts + + movew #0x2700,sr + + | Save MFP registers used for keyboard + + lea 0xfffffa00:w,a0 + btst #6,a0@(0x09) +#if defined(__mcoldfire__) + sne d0 + move.b d0,ikbd_ierb +#else + sne ikbd_ierb +#endif + btst #6,a0@(0x15) +#if defined(__mcoldfire__) + sne d0 + move.b d0,ikbd_imrb +#else + sne ikbd_imrb +#endif + + | Set our routine + +#if defined(__mcoldfire__) + movel 0x118:w,d0 + movel d0,old_ikbd + lea ikbd,a0 + movel a0,0x118:w + moveql #6,d0 + bset d0,0xfffffa09:w | IERB + bset d0,0xfffffa15:w | IMRB +#else + movel 0x118:w,old_ikbd + movel #ikbd,0x118:w + bset #6,0xfffffa09:w | IERB + bset #6,0xfffffa15:w | IMRB +#endif + + | Set mouse relative mode + +#if defined(__mcoldfire__) + moveql #8,d0 + moveb d0,0xfffffc02:w +#else + moveb #8,0xfffffc02:w +#endif + + | Reenable interrupts + + movew #0x2300,sr + + | Interrupts done + +#if defined(__mcoldfire__) + movel #0xffff,d0 + movew d0,_SDL_AtariIkbd_enabled + + moveml sp@,d0-d1/a0-a1 + lea sp@(16),sp +#else + movew #0xffff,_SDL_AtariIkbd_enabled + + moveml sp@+,d0-d1/a0-a1 +#endif + rts + +/*--- Uninstall our IKBD vector ---*/ + +_SDL_AtariIkbdUninstall: + movel a0,sp@- + + | Disable interrupts + + movew #0x2700,sr + + | Restore previous MFP registers + + lea 0xfffffa00:w,a0 + + bclr #6,a0@(0x09) + tstb ikbd_ierb + beqs ikbd_restoreierb + bset #6,a0@(0x09) +ikbd_restoreierb: + + bclr #6,a0@(0x15) + tstb ikbd_imrb + beqs ikbd_restoreimrb + bset #6,a0@(0x15) +ikbd_restoreimrb: + +#if defined(__mcoldfire__) + movel old_ikbd,a0 + movel a0,0x118:w +#else + movel old_ikbd,0x118:w +#endif + + | Clear keyboard buffer + + lea 0xfffffc00:w,a0 +ikbd_videbuffer: + btst #0,a0@ + beqs ikbd_finbuffer + tstb a0@(0x02) + bras ikbd_videbuffer +ikbd_finbuffer: + + | Reenable interrupts + + movew #0x2300,sr + + movel sp@+,a0 + rts + + .bss + + .even + .comm ikbd_ierb,1 + .comm ikbd_imrb,1 + +/*--- Our custom IKBD vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm old_ikbd,4*1 +ikbd: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + + | Joystick packet ? + + cmpb #0xff,d0 + beqs ikbd_yes_joystick + + | Mouse packet ? + + cmpb #0xf8,d0 + bmis ikbd_no_mouse + cmpb #0xfc,d0 + bpls ikbd_no_mouse + + | Mouse packet, byte #1 + +ikbd_yes_mouse: +#if defined(__mcoldfire__) + andl #3,d0 +#else + andw #3,d0 +#endif + movew d0,_SDL_AtariIkbd_mouseb + +#if defined(__mcoldfire__) + movel #ikbd_mousex,d0 + movel d0,0x118:w +#else + movel #ikbd_mousex,0x118:w +#endif + bras ikbd_endit_stack + + | Joystick packet, byte #1 + +ikbd_yes_joystick: +#if defined(__mcoldfire__) + movel #ikbd_joystick,d0 + movel d0,0x118:w +#else + movel #ikbd_joystick,0x118:w +#endif + bras ikbd_endit_stack + + | Keyboard press/release + +ikbd_no_mouse: + moveb d0,d1 + lea _SDL_AtariIkbd_keyboard,a0 +#if defined(__mcoldfire__) + andl #0x7f,d1 + btst #7,d0 + spl d0 + moveb d0,a0@(0,d1:l) +#else + andw #0x7f,d1 + tas d0 + spl a0@(0,d1:w) +#endif + + | End of interrupt + +ikbd_endit_stack: +#if defined(__mcoldfire__) + moveql #6,d0 + bclr d0,0xfffffa11:w + + moveml sp@,d0-d1/a0 + lea sp@(12),sp +#else + moveml sp@+,d0-d1/a0 + + bclr #6,0xfffffa11:w +#endif + rte + + | Call old MIDI interrupt + +ikbd_oldmidi: +#if defined(__mcoldfire__) + moveml sp@,d0-d1/a0 + lea sp@(12),sp +#else + moveml sp@+,d0-d1/a0 +#endif + + movel old_ikbd,sp@- + rts + + | Mouse packet, byte #2 + +ikbd_mousex: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariIkbd_mousex,d1 + addl d1,d0 + movew d0,_SDL_AtariIkbd_mousex + + movel #ikbd_mousey,d0 + movel d0,0x118:w +#else + addw d0,_SDL_AtariIkbd_mousex + + movel #ikbd_mousey,0x118:w +#endif + bras ikbd_endit_stack + + | Mouse packet, byte #3 + +ikbd_mousey: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + + moveb 0xfffffc02:w,d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariIkbd_mousey,d1 + addl d1,d0 + movew d0,_SDL_AtariIkbd_mousey + + movel #ikbd,d0 + movel d0,0x118:w +#else + addw d0,_SDL_AtariIkbd_mousey + + movel #ikbd,0x118:w +#endif + bras ikbd_endit_stack + + | Joystick packet, byte #2 + +ikbd_joystick: +#if defined(__mcoldfire__) + lea sp@(-12),sp + moveml d0-d1/a0,sp@ +#else + moveml d0-d1/a0,sp@- +#endif + + | Check if source is IKBD or MIDI +#if defined(__mcoldfire__) + moveql #0,d0 + btst d0,0xfffffc00.w +#else + btst #0,0xfffffc00.w +#endif + beqs ikbd_oldmidi + +#if defined(__mcoldfire__) + moveb 0xfffffc02:w,d0 + moveb d0,_SDL_AtariIkbd_joystick+1 + + movel #ikbd,d0 + movel d0,0x118:w + + bra ikbd_endit_stack +#else + moveb 0xfffffc02:w,_SDL_AtariIkbd_joystick+1 + + movel #ikbd,0x118:w + + bras ikbd_endit_stack +#endif + + .data + + .even +_SDL_AtariIkbd_enabled: + .word 0 + + .bss + + .even + .comm _SDL_AtariIkbd_keyboard,128 + .comm _SDL_AtariIkbd_mousex,2 + .comm _SDL_AtariIkbd_mousey,2 + .comm _SDL_AtariIkbd_mouseb,2 + .comm _SDL_AtariIkbd_joystick,2 diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h new file mode 100644 index 0000000..ea544bc --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_ikbdinterrupt_s.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Mouse vector + * + * Patrice Mandin + */ + +#ifndef _SDL_IKBDINTERRUPT_S_H_ +#define _SDL_IKBDINTERRUPT_S_H_ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/* Const */ + +#define IKBD_JOY_UP (1<<0) +#define IKBD_JOY_DOWN (1<<1) +#define IKBD_JOY_LEFT (1<<2) +#define IKBD_JOY_RIGHT (1<<3) +#define IKBD_JOY_FIRE (1<<7) + +/* Variables */ + +extern volatile Uint8 SDL_AtariIkbd_keyboard[128]; /* Keyboard table */ +extern volatile Uint16 SDL_AtariIkbd_mouseb; /* Mouse on port 0, buttons */ +extern volatile Sint16 SDL_AtariIkbd_mousex; /* Mouse X relative motion */ +extern volatile Sint16 SDL_AtariIkbd_mousey; /* Mouse Y relative motion */ +extern volatile Uint16 SDL_AtariIkbd_joystick; /* Joystick on port 1 */ + +/* For joystick driver to know if this is usable */ +extern Uint16 SDL_AtariIkbd_enabled; + +/* Functions */ + +extern void SDL_AtariIkbdInstall(void); +extern void SDL_AtariIkbdUninstall(void); + +#endif /* _SDL_IKBDINTERRUPT_S_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c new file mode 100644 index 0000000..232500f --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents.c @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * XBIOS mouse & joystick vectors + * + * Patrice Mandin + */ + +#include <mint/osbind.h> + +#include "../../events/SDL_events_c.h" +#include "SDL_atarisuper.h" +#include "SDL_xbiosevents_c.h" +#include "SDL_xbiosinterrupt_s.h" + +/* Variables */ + +int SDL_AtariXbios_enabled=0; + +/* Local variables */ + +static _KBDVECS *kbdvecs; /* Pointer to access system vectors */ +static Uint16 atari_prevmouseb; /* buttons */ + +/* Functions */ + +void SDL_AtariXbios_InstallVectors(int vectors_mask) +{ + void *oldpile; + + /* Clear variables */ + SDL_AtariXbios_mouselock = + SDL_AtariXbios_mouseb = + SDL_AtariXbios_mousex = + SDL_AtariXbios_mousey = + SDL_AtariXbios_joystick = + atari_prevmouseb = 0; + + if (vectors_mask==0) { + SDL_AtariXbios_enabled=0; + return; + } + + /* Read IKBD vectors base */ + kbdvecs=Kbdvbase(); + + /* Go to supervisor mode */ + oldpile=(void *)Super(0); + + /* Install our vectors */ + SDL_AtariXbios_Install( + kbdvecs, + (vectors_mask & ATARI_XBIOS_MOUSEEVENTS) ? SDL_AtariXbios_MouseVector : NULL, + (vectors_mask & ATARI_XBIOS_JOYSTICKEVENTS) ? SDL_AtariXbios_JoystickVector : NULL + ); + + /* Back to user mode */ + SuperToUser(oldpile); + + SDL_AtariXbios_enabled=1; +} + +void SDL_AtariXbios_RestoreVectors(void) +{ + void *oldpile; + + if (SDL_AtariXbios_enabled==0) { + return; + } + + /* Read IKBD vectors base */ + kbdvecs=Kbdvbase(); + + /* Go to supervisor mode */ + oldpile=(void *)Super(NULL); + + /* Reinstall system vector */ + SDL_AtariXbios_Restore(kbdvecs); + + /* Back to user mode */ + SuperToUser(oldpile); +} + +static int atari_GetButton(int button) +{ + switch(button) + { + case 0: + return SDL_BUTTON_RIGHT; + break; + case 1: + default: + return SDL_BUTTON_LEFT; + break; + } +} + +void SDL_AtariXbios_PostMouseEvents(_THIS, SDL_bool buttonEvents) +{ + if (SDL_AtariXbios_enabled==0) { + return; + } + + /* Mouse motion ? */ + if (SDL_AtariXbios_mousex || SDL_AtariXbios_mousey) { + SDL_PrivateMouseMotion(0, 1, SDL_AtariXbios_mousex, SDL_AtariXbios_mousey); + SDL_AtariXbios_mousex = SDL_AtariXbios_mousey = 0; + } + + /* Mouse button ? */ + if (buttonEvents && (SDL_AtariXbios_mouseb != atari_prevmouseb)) { + int i; + + for (i=0;i<2;i++) { + int curbutton, prevbutton; + + curbutton = SDL_AtariXbios_mouseb & (1<<i); + prevbutton = atari_prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, atari_GetButton(i), 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, atari_GetButton(i), 0, 0); + } + } + atari_prevmouseb = SDL_AtariXbios_mouseb; + } +} + +void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition) +{ + SDL_AtariXbios_mouselock = lockPosition; +} diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h new file mode 100644 index 0000000..374b062 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosevents_c.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Xbios mouse & joystick vectors + * + * Patrice Mandin + */ + +#ifndef _SDL_ATARI_XBIOSEVENTS_H_ +#define _SDL_ATARI_XBIOSEVENTS_H_ + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define ATARI_XBIOS_MOUSEEVENTS (1<<0) +#define ATARI_XBIOS_JOYSTICKEVENTS (1<<1) + +extern int SDL_AtariXbios_enabled; + +extern void SDL_AtariXbios_InstallVectors(int vectors_mask); +extern void SDL_AtariXbios_RestoreVectors(void); +extern void SDL_AtariXbios_PostMouseEvents(_THIS, SDL_bool buttonEvents); +extern void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition); + +#endif /* _SDL_XBIOSEVENTS_H_ */ diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S new file mode 100644 index 0000000..3fc1a60 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt.S @@ -0,0 +1,212 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* + * XBIOS mouse & joystick vectors + * + * Patrice Mandin + */ + + .text + + .globl _SDL_AtariXbios_Install + .globl _SDL_AtariXbios_Restore + .globl _SDL_AtariXbios_MouseVector + .globl _SDL_AtariXbios_JoystickVector + + .globl _SDL_AtariXbios_mouselock + .globl _SDL_AtariXbios_mouseb + .globl _SDL_AtariXbios_mousex + .globl _SDL_AtariXbios_mousey + .globl _SDL_AtariXbios_joystick + +/*--- Vector installer ---*/ + +_SDL_AtariXbios_Install: + movel sp@(4),a0 + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Save old mouse vector, set our routine */ + + clrl oldmousevector + movel sp@(8),d0 + beqs no_new_mouse_vector +#if defined(__mcoldfire__) + movel a0@(16),d1 + movel d1,oldmousevector +#else + movel a0@(16),oldmousevector +#endif + movel d0,a0@(16) +no_new_mouse_vector: + + /* Save old joystick vector, set our routine */ + + clrl oldjoystickvector + movel sp@(12),d0 + beqs no_new_joystick_vector +#if defined(__mcoldfire__) + movel a0@(24),d1 + movel d1,oldjoystickvector +#else + movel a0@(24),oldjoystickvector +#endif + movel d0,a0@(24) +no_new_joystick_vector: + + /* Restart interrupts */ + + movew #0x2300,sr + + rts + +/*--- Vector restorer ---*/ + +_SDL_AtariXbios_Restore: + movel sp@(4),a0 + + /* Stop interrupts */ + + movew #0x2700,sr + + /* Restore mouse vector */ + + movel oldmousevector,d0 + beqs no_restore_mouse + movel d0,a0@(16) +no_restore_mouse: + + /* Restore joystick vector */ + + movel oldjoystickvector,d0 + beqs no_restore_joystick + movel d0,a0@(24) +no_restore_joystick: + + /* Restart interrupts */ + + movew #0x2300,sr + + rts + +/*--- Our mouse vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm oldmousevector,4*1 +_SDL_AtariXbios_MouseVector: +#if defined(__mcoldfire__) + lea sp@(-8),sp + moveml d0-d1,sp@ +#else + movel d0,sp@- +#endif + + /* Mouse buttons */ + moveb (a0),d0 +#if defined(__mcoldfire__) + andl #3,d0 +#else + andw #3,d0 +#endif + movew d0,_SDL_AtariXbios_mouseb + + /* X movement */ + moveb a0@(1),d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariXbios_mousex,d1 + addl d1,d0 + movew d0,_SDL_AtariXbios_mousex +#else + addw d0,_SDL_AtariXbios_mousex +#endif + + /* Y movement */ + moveb a0@(2),d0 + extw d0 +#if defined(__mcoldfire__) + movew _SDL_AtariXbios_mousey,d1 + addl d1,d0 + movew d0,_SDL_AtariXbios_mousey +#else + addw d0,_SDL_AtariXbios_mousey +#endif + + /* Lock mouse position ? */ + tstw _SDL_AtariXbios_mouselock + beq.s no_mouse_lock + clrb a0@(1) + clrb a0@(2) +no_mouse_lock: + + /* Jump through old vector */ +#if defined(__mcoldfire__) + moveml sp@,d0-d1 + lea sp@(8),sp +#else + movel sp@+,d0 +#endif + + movel oldmousevector,sp@- + rts + + .data + .even + .comm _SDL_AtariXbios_mouselock,2*1 + .comm _SDL_AtariXbios_mousex,2*1 + .comm _SDL_AtariXbios_mousey,2*1 + .comm _SDL_AtariXbios_mouseb,2*1 + +/*--- Our joystick vector ---*/ + + .text + .even + .ascii "XBRA" + .ascii "LSDL" + .comm oldjoystickvector,4*1 +_SDL_AtariXbios_JoystickVector: + movel d0,sp@- + + /* New joystick state */ + moveb a0@(2),d0 +#if defined(__mcoldfire__) + andl #0x8f,d0 +#else + andw #0x8f,d0 +#endif + movew d0,_SDL_AtariXbios_joystick + + /* Jump through old vector */ + movel sp@+,d0 + + movel oldjoystickvector,sp@- + rts + + .data + .even + .comm _SDL_AtariXbios_joystick,2*1 diff --git a/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h new file mode 100644 index 0000000..dfb31c2 --- /dev/null +++ b/3rdparty/SDL/src/video/ataricommon/SDL_xbiosinterrupt_s.h @@ -0,0 +1,52 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Mouse vector + * + * Patrice Mandin + */ + +#ifndef _SDL_XBIOSINTERRUPT_S_H_ +#define _SDL_XBIOSINTERRUPT_S_H_ + +#include <mint/osbind.h> + +#include "SDL_stdinc.h" + +/* Variables */ + +extern volatile Uint16 SDL_AtariXbios_mouselock; /* mouse lock position */ +extern volatile Uint16 SDL_AtariXbios_mouseb; /* buttons */ +extern volatile Sint16 SDL_AtariXbios_mousex; /* X relative motion */ +extern volatile Sint16 SDL_AtariXbios_mousey; /* Y relative motion */ +extern volatile Uint16 SDL_AtariXbios_joystick; /* Joystick */ + +/* Functions */ + +extern void SDL_AtariXbios_Install(_KBDVECS *kbdvecs,void *newmousevector,void *newjoystickvector); +extern void SDL_AtariXbios_Restore(_KBDVECS *kbdvecs); +extern void SDL_AtariXbios_MouseVector(void *buf); +extern void SDL_AtariXbios_JoystickVector(void *buf); + +#endif /* _SDL_XBIOSINTERRUPT_S_H_ */ diff --git a/3rdparty/SDL/src/video/blank_cursor.h b/3rdparty/SDL/src/video/blank_cursor.h new file mode 100644 index 0000000..db69601 --- /dev/null +++ b/3rdparty/SDL/src/video/blank_cursor.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * A default blank 8x8 cursor */ + +#define BLANK_CWIDTH 8 +#define BLANK_CHEIGHT 8 +#define BLANK_CHOTX 0 +#define BLANK_CHOTY 0 + +static unsigned char blank_cdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static unsigned char blank_cmask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + diff --git a/3rdparty/SDL/src/video/bwindow/SDL_BView.h b/3rdparty/SDL/src/video/bwindow/SDL_BView.h new file mode 100644 index 0000000..bfa2c89 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_BView.h @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_BView_h +#define _SDL_BView_h + +/* This is the event handling and graphics update portion of SDL_BWin */ + +extern "C" { +#include "../../events/SDL_events_c.h" +}; + +class SDL_BView : public BView +{ +public: + SDL_BView(BRect frame) : + BView(frame, "SDL View", B_FOLLOW_ALL_SIDES, + (B_WILL_DRAW|B_FRAME_EVENTS)) { + image = NULL; + xoff = yoff = 0; + SetViewColor(0,0,0,0); + SetHighColor(0,0,0,0); + } + virtual ~SDL_BView() { + SetBitmap(NULL); + } + /* Set drawing offsets for fullscreen mode */ + virtual void SetXYOffset(int x, int y) { + xoff = x; + yoff = y; + } + virtual void GetXYOffset(int &x, int &y) { + x = xoff; + y = yoff; + } + virtual void GetXYOffset(float &x, float &y) { + x = (float)xoff; + y = (float)yoff; + } + /* The view changed size. If it means we're in fullscreen, we + * draw a nice black box in the entire view to get black borders. + */ + virtual void FrameResized(float width, float height) { + BRect bounds; + bounds.top = bounds.left = 0; + bounds.right = width; + bounds.bottom = height; + /* Fill the entire view with black */ + FillRect(bounds, B_SOLID_HIGH); + /* And if there's an image, redraw it. */ + if( image ) { + bounds = image->Bounds(); + Draw(bounds); + } + } + + /* Drawing portion of this complete breakfast. :) */ + virtual void SetBitmap(BBitmap *bitmap) { + if ( image ) { + delete image; + } + image = bitmap; + } + virtual void Draw(BRect updateRect) { + if ( image ) { + if(xoff || yoff) { + BRect dest; + dest.top = updateRect.top + yoff; + dest.left = updateRect.left + xoff; + dest.bottom = updateRect.bottom + yoff; + dest.right = updateRect.right + xoff; + DrawBitmap(image, updateRect, dest); + } else { + DrawBitmap(image, updateRect, updateRect); + } + } + } + virtual void DrawAsync(BRect updateRect) { + if(xoff || yoff) { + BRect dest; + dest.top = updateRect.top + yoff; + dest.left = updateRect.left + xoff; + dest.bottom = updateRect.bottom + yoff; + dest.right = updateRect.right + xoff;; + DrawBitmapAsync(image, updateRect, dest); + } else { + DrawBitmapAsync(image, updateRect, updateRect); + } + } + +private: + BBitmap *image; + int xoff, yoff; +}; + +#endif /* _SDL_BView_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_BWin.h b/3rdparty/SDL/src/video/bwindow/SDL_BWin.h new file mode 100644 index 0000000..f2b19a2 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_BWin.h @@ -0,0 +1,290 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef _SDL_BWin_h +#define _SDL_BWin_h + +#include "SDL_config.h" + +#include <stdio.h> +#include <AppKit.h> +#include <InterfaceKit.h> +#include <be/game/DirectWindow.h> +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#include <be/opengl/GLView.h> +#endif +#include <support/UTF8.h> + +#include "../../main/beos/SDL_BeApp.h" +#include "SDL_events.h" +#include "SDL_BView.h" + +extern "C" { +#include "../../events/SDL_events_c.h" + +extern int mouse_relative; +}; + +class SDL_BWin : public BDirectWindow +{ +public: + SDL_BWin(BRect bounds) : + BDirectWindow(bounds, "Untitled", B_TITLED_WINDOW, 0) { + last_buttons = 0; + the_view = NULL; +#if SDL_VIDEO_OPENGL + SDL_GLView = NULL; +#endif + SDL_View = NULL; + Unlock(); + shown = false; + inhibit_resize = false; + } + + virtual ~SDL_BWin() { + Lock(); + if ( the_view ) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + SDL_GLView->UnlockGL(); + } +#endif + RemoveChild(the_view); + the_view = NULL; + } + Unlock(); +#if SDL_VIDEO_OPENGL + if ( SDL_GLView ) { + delete SDL_GLView; + } +#endif + if ( SDL_View ) { + delete SDL_View; + } + } + + + /* Override the Show() method so we can tell when we've been shown */ + virtual void Show(void) { + BWindow::Show(); + shown = true; + } + virtual bool Shown(void) { + return (shown); + } + /* If called, the next resize event will not be forwarded to SDL. */ + virtual void InhibitResize(void) { + inhibit_resize=true; + } + /* Handle resizing of the window */ + virtual void FrameResized(float width, float height) { + if(inhibit_resize) + inhibit_resize = false; + else + SDL_PrivateResize((int)width, (int)height); + } + virtual int CreateView(Uint32 flags, Uint32 gl_flags) { + int retval; + + retval = 0; + Lock(); + if ( flags & SDL_OPENGL ) { +#if SDL_VIDEO_OPENGL + if ( SDL_GLView == NULL ) { + SDL_GLView = new BGLView(Bounds(), "SDL GLView", + B_FOLLOW_ALL_SIDES, (B_WILL_DRAW|B_FRAME_EVENTS), + gl_flags|BGL_DOUBLE); + SDL_GLView->EnableDirectMode(true); + } + if ( the_view != SDL_GLView ) { + if ( the_view ) { + RemoveChild(the_view); + } + AddChild(SDL_GLView); + SDL_GLView->LockGL(); + the_view = SDL_GLView; + } +#else + SDL_SetError("OpenGL support not enabled"); + retval = -1; +#endif + } else { + if ( SDL_View == NULL ) { + SDL_View = new SDL_BView(Bounds()); + } + if ( the_view != SDL_View ) { + if ( the_view ) { + RemoveChild(the_view); + } + AddChild(SDL_View); + the_view = SDL_View; + } + } +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + SDL_GLView->UnlockGL(); + } +#endif + Unlock(); + return(retval); + } + virtual void SetBitmap(BBitmap *bitmap) { + SDL_View->SetBitmap(bitmap); + } + virtual void SetXYOffset(int x, int y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + return; + } +#endif + SDL_View->SetXYOffset(x, y); + } + virtual void GetXYOffset(int &x, int &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0; + y = 0; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } + virtual void GetXYOffset(float &x, float &y) { +#if SDL_VIDEO_OPENGL + if ( the_view == SDL_GLView ) { + x = 0.0f; + y = 0.0f; + return; + } +#endif + SDL_View->GetXYOffset(x, y); + } + virtual bool BeginDraw(void) { + return(Lock()); + } + virtual void DrawAsync(BRect updateRect) { + SDL_View->DrawAsync(updateRect); + } + virtual void EndDraw(void) { + SDL_View->Sync(); + Unlock(); + } +#if SDL_VIDEO_OPENGL + virtual void SwapBuffers(void) { + SDL_GLView->UnlockGL(); + SDL_GLView->SwapBuffers(); + SDL_GLView->LockGL(); + } +#endif + virtual BView *View(void) { + return(the_view); + } + + /* Hook functions -- overridden */ + virtual void Minimize(bool minimize) { + /* This is only called when mimimized, not when restored */ + //SDL_PrivateAppActive(minimize, SDL_APPACTIVE); + BWindow::Minimize(minimize); + } + virtual void WindowActivated(bool active) { + SDL_PrivateAppActive(active, SDL_APPINPUTFOCUS); + } + virtual bool QuitRequested(void) { + if ( SDL_BeAppActive > 0 ) { + SDL_PrivateQuit(); + /* We don't ever actually close the window here because + the application should respond to the quit request, + or ignore it as desired. + */ +#if SDL_VIDEO_OPENGL + if ( SDL_GLView != NULL ) { + SDL_GLView->EnableDirectMode(false); + } +#endif + return(false); + } + return(true); /* Close the app window */ + } + virtual void Quit() { + if (!IsLocked()) + Lock(); + BDirectWindow::Quit(); + } + + virtual int16 Translate2Unicode(const char *buf) { + int32 state, srclen, dstlen; + unsigned char destbuf[2]; + Uint16 unicode = 0; + + if ((uchar)buf[0] > 127) { + state = 0; + srclen = SDL_strlen(buf); + dstlen = sizeof(destbuf); + convert_from_utf8(B_UNICODE_CONVERSION, buf, &srclen, (char *)destbuf, &dstlen, &state); + unicode = destbuf[0]; + unicode <<= 8; + unicode |= destbuf[1]; + } else + unicode = buf[0]; + + /* For some reason function keys map to control characters */ +# define CTRL(X) ((X)-'@') + switch (unicode) { + case CTRL('A'): + case CTRL('B'): + case CTRL('C'): + case CTRL('D'): + case CTRL('E'): + case CTRL('K'): + case CTRL('L'): + case CTRL('P'): + if ( ! (SDL_GetModState() & KMOD_CTRL) ) + unicode = 0; + break; + /* Keyboard input maps newline to carriage return */ + case '\n': + unicode = '\r'; + break; + default: + break; + } + + return unicode; + } + + virtual void DispatchMessage(BMessage *msg, BHandler *target); + + virtual void DirectConnected(direct_buffer_info *info); + +private: +#if SDL_VIDEO_OPENGL + BGLView *SDL_GLView; +#endif + SDL_BView *SDL_View; + BView *the_view; + bool shown; + bool inhibit_resize; + int32 last_buttons; +}; + +#endif /* _SDL_BWin_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h b/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h new file mode 100644 index 0000000..0513b2d --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_lowvideo.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#include "SDL_BWin.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData { + /* The main window */ + SDL_BWin *SDL_Win; + + /* The fullscreen mode list */ + display_mode saved_mode; +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* A completely clear cursor */ + WMcursor *BlankCursor; + + SDL_Overlay *overlay; +}; +/* Old variable names */ +#define SDL_Win (_this->hidden->SDL_Win) +#define saved_mode (_this->hidden->saved_mode) +#define SDL_nummodes (_this->hidden->SDL_nummodes) +#define SDL_modelist (_this->hidden->SDL_modelist) +#define SDL_BlankCursor (_this->hidden->BlankCursor) +#define current_overlay (_this->hidden->overlay) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc new file mode 100644 index 0000000..9e12750 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysevents.cc @@ -0,0 +1,415 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <support/UTF8.h> +#include <stdio.h> +#include <string.h> +#include "SDL_error.h" +#include "SDL_events.h" +#include "SDL_BWin.h" +#include "SDL_lowvideo.h" + +static SDLKey keymap[128]; +int mouse_relative = 0; +extern "C" { + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "../SDL_cursor_c.h" + +void BE_PumpEvents(_THIS) +{ +} + +void BE_InitOSKeymap(_THIS) +{ + for ( uint i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[0x01] = SDLK_ESCAPE; + keymap[B_F1_KEY] = SDLK_F1; + keymap[B_F2_KEY] = SDLK_F2; + keymap[B_F3_KEY] = SDLK_F3; + keymap[B_F4_KEY] = SDLK_F4; + keymap[B_F5_KEY] = SDLK_F5; + keymap[B_F6_KEY] = SDLK_F6; + keymap[B_F7_KEY] = SDLK_F7; + keymap[B_F8_KEY] = SDLK_F8; + keymap[B_F9_KEY] = SDLK_F9; + keymap[B_F10_KEY] = SDLK_F10; + keymap[B_F11_KEY] = SDLK_F11; + keymap[B_F12_KEY] = SDLK_F12; + keymap[B_PRINT_KEY] = SDLK_PRINT; + keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK; + keymap[B_PAUSE_KEY] = SDLK_PAUSE; + keymap[0x11] = SDLK_BACKQUOTE; + keymap[0x12] = SDLK_1; + keymap[0x13] = SDLK_2; + keymap[0x14] = SDLK_3; + keymap[0x15] = SDLK_4; + keymap[0x16] = SDLK_5; + keymap[0x17] = SDLK_6; + keymap[0x18] = SDLK_7; + keymap[0x19] = SDLK_8; + keymap[0x1a] = SDLK_9; + keymap[0x1b] = SDLK_0; + keymap[0x1c] = SDLK_MINUS; + keymap[0x1d] = SDLK_EQUALS; + keymap[0x1e] = SDLK_BACKSPACE; + keymap[0x1f] = SDLK_INSERT; + keymap[0x20] = SDLK_HOME; + keymap[0x21] = SDLK_PAGEUP; + keymap[0x22] = SDLK_NUMLOCK; + keymap[0x23] = SDLK_KP_DIVIDE; + keymap[0x24] = SDLK_KP_MULTIPLY; + keymap[0x25] = SDLK_KP_MINUS; + keymap[0x26] = SDLK_TAB; + keymap[0x27] = SDLK_q; + keymap[0x28] = SDLK_w; + keymap[0x29] = SDLK_e; + keymap[0x2a] = SDLK_r; + keymap[0x2b] = SDLK_t; + keymap[0x2c] = SDLK_y; + keymap[0x2d] = SDLK_u; + keymap[0x2e] = SDLK_i; + keymap[0x2f] = SDLK_o; + keymap[0x30] = SDLK_p; + keymap[0x31] = SDLK_LEFTBRACKET; + keymap[0x32] = SDLK_RIGHTBRACKET; + keymap[0x33] = SDLK_BACKSLASH; + keymap[0x34] = SDLK_DELETE; + keymap[0x35] = SDLK_END; + keymap[0x36] = SDLK_PAGEDOWN; + keymap[0x37] = SDLK_KP7; + keymap[0x38] = SDLK_KP8; + keymap[0x39] = SDLK_KP9; + keymap[0x3a] = SDLK_KP_PLUS; + keymap[0x3b] = SDLK_CAPSLOCK; + keymap[0x3c] = SDLK_a; + keymap[0x3d] = SDLK_s; + keymap[0x3e] = SDLK_d; + keymap[0x3f] = SDLK_f; + keymap[0x40] = SDLK_g; + keymap[0x41] = SDLK_h; + keymap[0x42] = SDLK_j; + keymap[0x43] = SDLK_k; + keymap[0x44] = SDLK_l; + keymap[0x45] = SDLK_SEMICOLON; + keymap[0x46] = SDLK_QUOTE; + keymap[0x47] = SDLK_RETURN; + keymap[0x48] = SDLK_KP4; + keymap[0x49] = SDLK_KP5; + keymap[0x4a] = SDLK_KP6; + keymap[0x4b] = SDLK_LSHIFT; + keymap[0x4c] = SDLK_z; + keymap[0x4d] = SDLK_x; + keymap[0x4e] = SDLK_c; + keymap[0x4f] = SDLK_v; + keymap[0x50] = SDLK_b; + keymap[0x51] = SDLK_n; + keymap[0x52] = SDLK_m; + keymap[0x53] = SDLK_COMMA; + keymap[0x54] = SDLK_PERIOD; + keymap[0x55] = SDLK_SLASH; + keymap[0x56] = SDLK_RSHIFT; + keymap[0x57] = SDLK_UP; + keymap[0x58] = SDLK_KP1; + keymap[0x59] = SDLK_KP2; + keymap[0x5a] = SDLK_KP3; + keymap[0x5b] = SDLK_KP_ENTER; + keymap[0x5c] = SDLK_LCTRL; + keymap[0x5d] = SDLK_LALT; + keymap[0x5e] = SDLK_SPACE; + keymap[0x5f] = SDLK_RALT; + keymap[0x60] = SDLK_RCTRL; + keymap[0x61] = SDLK_LEFT; + keymap[0x62] = SDLK_DOWN; + keymap[0x63] = SDLK_RIGHT; + keymap[0x64] = SDLK_KP0; + keymap[0x65] = SDLK_KP_PERIOD; + keymap[0x66] = SDLK_LMETA; + keymap[0x67] = SDLK_RMETA; + keymap[0x68] = SDLK_MENU; + keymap[0x69] = SDLK_EURO; + keymap[0x6a] = SDLK_KP_EQUALS; + keymap[0x6b] = SDLK_POWER; +} + +}; /* Extern C */ + +void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target) +{ + switch (msg->what) { + case B_MOUSE_MOVED: + { + SDL_VideoDevice *view = current_video; + BPoint where; + int32 transit; + if (msg->FindPoint("where", &where) == B_OK && msg->FindInt32("be:transit", &transit) == B_OK) { + int x, y; + + GetXYOffset(x, y); + x = (int)where.x - x; + y = (int)where.y - y; + + //BeSman: I need another method for cursor catching !!! + if (view->input_grab != SDL_GRAB_OFF) + { + bool clipped = false; + if ( x < 0 ) { + x = 0; + clipped = true; + } else if ( x >= SDL_VideoSurface->w ) { + x = (SDL_VideoSurface->w-1); + clipped = true; + } + if ( y < 0 ) { + y = 0; + clipped = true; + } else if ( y >= SDL_VideoSurface->h ) { + y = (SDL_VideoSurface->h-1); + clipped = true; + } + if ( clipped ) { + BPoint edge; + GetXYOffset(edge.x, edge.y); + edge.x += x; + edge.y += y; + ConvertToScreen(&edge); + set_mouse_position((int)edge.x, (int)edge.y); + } + transit = B_INSIDE_VIEW; + } + if (transit == B_EXITED_VIEW) { + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); +#if SDL_VIDEO_OPENGL + // for some reason, SDL_EraseCursor fails for OpenGL + if (this->the_view != this->SDL_GLView) +#endif + SDL_EraseCursor(SDL_VideoSurface); + be_app->SetCursor(B_HAND_CURSOR); + } + } else { + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); +#if SDL_VIDEO_OPENGL + // for some reason, SDL_EraseCursor fails for OpenGL + if (this->the_view != this->SDL_GLView) +#endif + SDL_EraseCursor(SDL_VideoSurface); + SDL_SetCursor(NULL); + } + + if ( mouse_relative ) { + int half_w = (SDL_VideoSurface->w/2); + int half_h = (SDL_VideoSurface->h/2); + x -= half_w; + y -= half_h; + if ( x || y ) { + BPoint center; + GetXYOffset(center.x, center.y); + center.x += half_w; + center.y += half_h; + ConvertToScreen(¢er); + set_mouse_position((int)center.x, (int)center.y); + SDL_PrivateMouseMotion(0, 1, x, y); + } + } else { + SDL_PrivateMouseMotion(0, 0, x, y); + } + } + } + break; + } + + case B_MOUSE_DOWN: + { + /* it looks like mouse down is send only for first clicked + button, each next is not send while last one is holded */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if (buttons & B_PRIMARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_PRESSED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_UP: + { + /* mouse up doesn't give which button was released, + only state of buttons (after release, so it's always = 0), + which is not what we need ;] + So we need to store button in mouse down, and restore + in mouse up :( + mouse up is (similarly to mouse down) send only for + first button down (ie. it's no send if we click another button + without releasing previous one first) - but that's probably + because of how drivers are written?, not BeOS itself. */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if ((buttons ^ B_PRIMARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if ((buttons ^ B_SECONDARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if ((buttons ^ B_TERTIARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_RELEASED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_WHEEL_CHANGED: + { + float x, y; + x = y = 0; + if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) { + if (x < 0 || y < 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + } else if (x > 0 || y > 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + } + } + break; + } + + case B_KEY_DOWN: + case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + int32 key_repeat; + /* Workaround for SDL message queue being filled too fast because of BeOS own key-repeat mechanism */ + if (msg->FindInt32("be:key_repeat", &key_repeat) == B_OK && key_repeat > 0) + break; + + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + /* FIX THIS? + it seems SDL_PrivateKeyboard() changes mod value + anyway, and doesn't care about what we setup here */ + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + /* FIX THIS? + this cares only about first "letter", + so if someone maps some key to print + "BeOS rulez!" only "B" will be used. */ + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case B_KEY_UP: + case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + keysym.mod = KMOD_NONE; /* FIX THIS? */ + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + } + + default: + /* move it after switch{} so it's always handled + that way we keep BeOS feautures like: + - CTRL+Q to close window (and other shortcuts) + - PrintScreen to make screenshot into /boot/home + - etc.. */ + //BDirectWindow::DispatchMessage(msg, target); + break; + } + BDirectWindow::DispatchMessage(msg, target); +} + +void SDL_BWin::DirectConnected(direct_buffer_info *info) { + switch (info->buffer_state & B_DIRECT_MODE_MASK) { + case B_DIRECT_START: + case B_DIRECT_MODIFY: + { + int32 width = info->window_bounds.right - + info->window_bounds.left; + int32 height = info->window_bounds.bottom - + info->window_bounds.top; + SDL_PrivateResize(width, height); + break; + } + default: + break; + } +#if SDL_VIDEO_OPENGL + // If it is a BGLView, it is apparently required to + // call DirectConnected() on it as well + if (this->the_view == this->SDL_GLView) + this->SDL_GLView->DirectConnected(info); +#endif +} diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h b/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h new file mode 100644 index 0000000..70c5535 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysevents_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +extern void BE_InitOSKeymap(_THIS); +extern void BE_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc new file mode 100644 index 0000000..9a557d6 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse.cc @@ -0,0 +1,153 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <AppKit.h> +#include <GameKit.h> + +#include "SDL_BWin.h" + +extern "C" { +#include "../SDL_cursor_c.h" +#include "SDL_sysmouse_c.h" + +/* Convert bits to padded bytes */ +#define PADDED_BITS(bits) ((bits+7)/8) + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + char *bits; +}; + +/* Can this be done in the BeOS? */ +WMcursor *BE_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + int allowed_x; + int allowed_y; + int run, pad, i; + char *cptr; + + allowed_x = 16; /* BeOS limitation */ + allowed_y = 16; /* BeOS limitation */ + if ( (w > allowed_x) || (h > allowed_y) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + allowed_x, allowed_y); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + cursor->bits = (char *)SDL_malloc(4+2*((allowed_x/8)*allowed_y)); + if ( cursor->bits == NULL ) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + cursor->bits[0] = allowed_y; /* Size of the cursor */ + cursor->bits[1] = 1; /* Bit depth of cursor */ + cursor->bits[2] = hot_y; + cursor->bits[3] = hot_x; + cptr = &cursor->bits[4]; + + /* Pad out to the normal cursor size */ + run = PADDED_BITS(w); + pad = PADDED_BITS(allowed_x)-run; + for ( i=0; i<h; ++i ) { + SDL_memcpy(cptr, data, run); + SDL_memset(cptr+run, 0, pad); + data += run; + cptr += (run+pad); + } + for ( ; i<allowed_y; ++i ) { + SDL_memset(cptr, 0, run+pad); + cptr += (run+pad); + } + for ( i=0; i<h; ++i ) { + /* FIXME: The mask should be OR'd with the data to turn + inverted color pixels black, since inverted color pixels + aren't supported under BeOS. + */ + SDL_memcpy(cptr, mask, run); + SDL_memset(cptr+run, 0, pad); + mask += run; + cptr += (run+pad); + } + for ( ; i<allowed_y; ++i ) { + SDL_memset(cptr, 0, run+pad); + cptr += (run+pad); + } + return(cursor); +} + +int BE_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if ( be_app->Lock() ) { + if ( cursor == NULL ) { + if ( SDL_BlankCursor != NULL ) { + be_app->SetCursor(SDL_BlankCursor->bits); + } + } else { + be_app->SetCursor(cursor->bits); + } + be_app->Unlock(); + } + return(1); +} + +void BE_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor->bits); + SDL_free(cursor); +} + +/* Implementation by Christian Bauer <cbauer@student.physik.uni-mainz.de> */ +void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + BPoint pt; + SDL_Win->GetXYOffset(pt.x, pt.y); + pt.x += x; + pt.y += y; + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int32)pt.x, (int32)pt.y); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void BE_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (_this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h new file mode 100644 index 0000000..70b3b2a --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysmouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void BE_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *BE_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int BE_ShowWMCursor(_THIS, WMcursor *cursor); +extern void BE_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void BE_CheckMouseMode(_THIS); + diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc new file mode 100644 index 0000000..c32b661 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysvideo.cc @@ -0,0 +1,841 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* BWindow based framebuffer implementation */ + +#include <unistd.h> + +#include "SDL_BWin.h" +#include "SDL_timer.h" + +extern "C" { + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_syswm_c.h" +#include "SDL_lowvideo.h" +#include "../SDL_yuvfuncs.h" +#include "SDL_sysyuv.h" +#include "../blank_cursor.h" + +#define BEOS_HIDDEN_SIZE 32 /* starting hidden window size */ + +/* Initialization/Query functions */ +static int BE_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static void BE_UpdateMouse(_THIS); +static int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void BE_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int BE_AllocHWSurface(_THIS, SDL_Surface *surface); +static int BE_LockHWSurface(_THIS, SDL_Surface *surface); +static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void BE_FreeHWSurface(_THIS, SDL_Surface *surface); + +static int BE_ToggleFullScreen(_THIS, int fullscreen); + +/* OpenGL functions */ +#if SDL_VIDEO_OPENGL +static int BE_GL_LoadLibrary(_THIS, const char *path); +static void* BE_GL_GetProcAddress(_THIS, const char *proc); +static int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +static int BE_GL_MakeCurrent(_THIS); +static void BE_GL_SwapBuffers(_THIS); +#endif + +/* FB driver bootstrap functions */ + +static int BE_Available(void) +{ + return(1); +} + +static void BE_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *BE_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + /* Initialization/Query functions */ + device->VideoInit = BE_VideoInit; + device->ListModes = BE_ListModes; + device->SetVideoMode = BE_SetVideoMode; + device->ToggleFullScreen = BE_ToggleFullScreen; + device->UpdateMouse = BE_UpdateMouse; + device->CreateYUVOverlay = BE_CreateYUVOverlay; + device->SetColors = BE_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = BE_VideoQuit; + /* Hardware acceleration functions */ + device->AllocHWSurface = BE_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = BE_LockHWSurface; + device->UnlockHWSurface = BE_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = BE_FreeHWSurface; + /* Gamma support */ +#if SDL_VIDEO_OPENGL + /* OpenGL support */ + device->GL_LoadLibrary = BE_GL_LoadLibrary; + device->GL_GetProcAddress = BE_GL_GetProcAddress; + device->GL_GetAttribute = BE_GL_GetAttribute; + device->GL_MakeCurrent = BE_GL_MakeCurrent; + device->GL_SwapBuffers = BE_GL_SwapBuffers; +#endif + /* Window manager functions */ + device->SetCaption = BE_SetWMCaption; + device->SetIcon = NULL; + device->IconifyWindow = BE_IconifyWindow; + device->GrabInput = BE_GrabInput; + device->GetWMInfo = BE_GetWMInfo; + /* Cursor manager functions */ + device->FreeWMCursor = BE_FreeWMCursor; + device->CreateWMCursor = BE_CreateWMCursor; + device->ShowWMCursor = BE_ShowWMCursor; + device->WarpWMCursor = BE_WarpWMCursor; + device->MoveWMCursor = NULL; + device->CheckMouseMode = BE_CheckMouseMode; + /* Event manager functions */ + device->InitOSKeymap = BE_InitOSKeymap; + device->PumpEvents = BE_PumpEvents; + + device->free = BE_DeleteDevice; + + /* Set the driver flags */ + device->handles_any_size = 1; + + return device; +} + +VideoBootStrap BWINDOW_bootstrap = { + "bwindow", "BDirectWindow graphics", + BE_Available, BE_CreateDevice +}; + +static inline int ColorSpaceToBitsPerPixel(uint32 colorspace) +{ + int bitsperpixel; + + bitsperpixel = 0; + switch (colorspace) { + case B_CMAP8: + bitsperpixel = 8; + break; + case B_RGB15: + case B_RGBA15: + case B_RGB15_BIG: + case B_RGBA15_BIG: + bitsperpixel = 15; + break; + case B_RGB16: + case B_RGB16_BIG: + bitsperpixel = 16; + break; + case B_RGB32: + case B_RGBA32: + case B_RGB32_BIG: + case B_RGBA32_BIG: + bitsperpixel = 32; + break; + default: + break; + } + return(bitsperpixel); +} + +/* Function to sort the display_list in bscreen */ +static int CompareModes(const void *A, const void *B) +{ + const display_mode *a = (display_mode *)A; + const display_mode *b = (display_mode *)B; + + if ( a->space == b->space ) { + return((b->virtual_width*b->virtual_height)- + (a->virtual_width*a->virtual_height)); + } else { + return(ColorSpaceToBitsPerPixel(b->space)- + ColorSpaceToBitsPerPixel(a->space)); + } +} + +/* Yes, this isn't the fastest it could be, but it works nicely */ +static int BE_AddMode(_THIS, int index, unsigned int w, unsigned int h) +{ + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { +#ifdef BWINDOW_DEBUG + fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + return(0); + } + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef BWINDOW_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +int BE_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + display_mode *modes; + uint32 i, nmodes; + int bpp; + BRect bounds; + + /* Initialize the Be Application for appserver interaction */ + if ( SDL_InitBeApp() < 0 ) { + return(-1); + } + + /* It is important that this be created after SDL_InitBeApp() */ + BScreen bscreen; + + /* Save the current display mode */ + bscreen.GetMode(&saved_mode); + _this->info.current_w = saved_mode.virtual_width; + _this->info.current_h = saved_mode.virtual_height; + + /* Determine the screen depth */ + vformat->BitsPerPixel = ColorSpaceToBitsPerPixel(bscreen.ColorSpace()); + if ( vformat->BitsPerPixel == 0 ) { + SDL_SetError("Unknown BScreen colorspace: 0x%x", + bscreen.ColorSpace()); + return(-1); + } + + /* Get the video modes we can switch to in fullscreen mode */ + bscreen.GetModeList(&modes, &nmodes); + SDL_qsort(modes, nmodes, sizeof *modes, CompareModes); + for ( i=0; i<nmodes; ++i ) { + bpp = ColorSpaceToBitsPerPixel(modes[i].space); + //if ( bpp != 0 ) { // There are bugs in changing colorspace + if ( modes[i].space == saved_mode.space ) { + BE_AddMode(_this, ((bpp+7)/8)-1, + modes[i].virtual_width, + modes[i].virtual_height); + } + } + + /* Create the window and view */ + bounds.top = 0; bounds.left = 0; + bounds.right = BEOS_HIDDEN_SIZE; + bounds.bottom = BEOS_HIDDEN_SIZE; + SDL_Win = new SDL_BWin(bounds); + +#if SDL_VIDEO_OPENGL + /* testgl application doesn't load library, just tries to load symbols */ + /* is it correct? if so we have to load library here */ + BE_GL_LoadLibrary(_this, NULL); +#endif + + /* Create the clear cursor */ + SDL_BlankCursor = BE_CreateWMCursor(_this, blank_cdata, blank_cmask, + BLANK_CWIDTH, BLANK_CHEIGHT, BLANK_CHOTX, BLANK_CHOTY); + + /* Fill in some window manager capabilities */ + _this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +/* We support any dimension at our bit-depth */ +SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + SDL_Rect **modes; + + modes = ((SDL_Rect **)0); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; + } else { + if ( format->BitsPerPixel == + _this->screen->format->BitsPerPixel ) { + modes = ((SDL_Rect **)-1); + } + } + return(modes); +} + +/* Various screen update functions available */ +static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + + +/* Find the closest display mode for fullscreen */ +static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp, + display_mode *mode) +{ + BScreen bscreen; + uint32 i, nmodes; + SDL_Rect **modes; + display_mode *dmodes; + display_mode current; + float current_refresh; + bscreen.GetMode(¤t); + current_refresh = (1000 * current.timing.pixel_clock) / + (current.timing.h_total * current.timing.v_total); + + modes = SDL_modelist[((bpp+7)/8)-1]; + + // find end of list (lowest-resolution mode; modes are ordered + // highest-to-lowest). + i = 0; while(modes[i]) i++; + if (!i) return false; // what? no modes at all? + + // find first mode with resolution >= requested in both dimensions + for (--i; i >= 0; --i) + { + if (modes[i]->w >= width && modes[i]->h >= height) + break; + } + + // unable to find any mode with that high a resolution! + if (i < 0) + return false; + + width = modes[i]->w; + height = modes[i]->h; + + bscreen.GetModeList(&dmodes, &nmodes); + for ( i = 0; i < nmodes; ++i ) { + if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) && + (width == dmodes[i].virtual_width) && + (height == dmodes[i].virtual_height) ) { + break; + } + } + if ( i != nmodes ) { + *mode = dmodes[i]; + if ((mode->virtual_width <= current.virtual_width) && + (mode->virtual_height <= current.virtual_height)) { + float new_refresh = (1000 * mode->timing.pixel_clock) / + (mode->timing.h_total * mode->timing.v_total); + if (new_refresh < current_refresh) { + mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total) + * current_refresh / 1000); + } + } + return true; + } else { + return false; + } +} + +static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) +{ + // printf("SetFullScreen(%d)\n", fullscreen); + BScreen bscreen; + + // SetFullSscreen() does not work as expected if called in a window + // that was never shown. This is probably a bug in the Haiku Game Kit that needs + // to be investigated. + if (SDL_Win->Lock()) { + // Show our window. + SDL_Win->Show(); + } + + if (SDL_Win->IsLocked()) { + // Unlock the window if it was locked. This is needed as only the + // first call to Show() unlocks the looper. All other calls to it + // will not. + SDL_Win->Unlock(); + } + + int width = screen->w; + int height = screen->h; + + if (fullscreen) { + // Set resolution to the closest available one that matches the + // current SDL resolution. + display_mode mode; + bscreen.GetMode(&mode); + + int bpp = screen->format->BitsPerPixel; + if (bpp != ColorSpaceToBitsPerPixel(mode.space) || + width != mode.virtual_width || height != mode.virtual_height) { + if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { + bscreen.SetMode(&mode); + } else { + // printf("Could not set new mode.\n"); + return(0); + } + } + } else { + // Reset to the previous known resolution as we are now in window + // mode. + bscreen.SetMode(&saved_mode); + } + + // Effectivelly set/reset full screen mode. If we are already in + // full screen mode, we reset back to windowed mode first so the + // window can resize when going fullscreen. + // if (fullscreen) + // printf("Going fullscreen\n"); + // else + // printf("Going windowed\n"); + SDL_Win->SetFullScreen(fullscreen); + + // Calculate offsets for centering the window (in window mode) and for + // dentering the bitmap (in full screen mode). + BRect bounds = bscreen.Frame(); + bounds.PrintToStream(); + int32 cx = (bounds.IntegerWidth() - width)/2; + int32 cy = (bounds.IntegerHeight() - height)/2; + + // printf ("cx = %d, cy = %d\n", cx, cy); + if (!SDL_Win->IsFullScreen()) { + // printf("Doing not fullscreen stuff.\n"); + // We are not in full screen mode, so we want to change the window + // size to match the resolution in SDL. + SDL_Win->ResizeTo(width, height); + + // And also center the window and reset the drawing offset. + SDL_Win->MoveTo(cx, cy); + SDL_Win->SetXYOffset(0, 0); + } else { + // printf("Doing fullscreen stuff."); + // Center the bitmap whenever we are in full screen mode. + SDL_Win->SetXYOffset(cx, cy); + } + + // Set relevant internal SDL screen flags. + if (SDL_Win->IsFullScreen()) { + screen->flags |= SDL_FULLSCREEN; + } else { + screen->flags &= ~SDL_FULLSCREEN; + } + + return(1); +} + +static int BE_ToggleFullScreen(_THIS, int fullscreen) +{ + return BE_SetFullScreen(_this, _this->screen, fullscreen); +} + +/* FIXME: check return values and cleanup here */ +SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + BScreen bscreen; + BBitmap *bbitmap; + BRect bounds; + Uint32 gl_flags = 0; + + /* Only RGB works on r5 currently */ + gl_flags = BGL_RGB; + if (_this->gl_config.double_buffer) + gl_flags |= BGL_DOUBLE; + else + gl_flags |= BGL_SINGLE; + if (_this->gl_config.alpha_size > 0 || bpp == 32) + gl_flags |= BGL_ALPHA; + if (_this->gl_config.depth_size > 0) + gl_flags |= BGL_DEPTH; + if (_this->gl_config.stencil_size > 0) + gl_flags |= BGL_STENCIL; + if (_this->gl_config.accum_red_size > 0 + || _this->gl_config.accum_green_size > 0 + || _this->gl_config.accum_blue_size > 0 + || _this->gl_config.accum_alpha_size > 0) + gl_flags |= BGL_ACCUM; + + /* Create the view for this window, using found flags */ + if ( SDL_Win->CreateView(flags, gl_flags) < 0 ) { + return(NULL); + } + + current->flags = 0; /* Clear flags */ + current->w = width; + current->h = height; + SDL_Win->SetType(B_TITLED_WINDOW); + if ( flags & SDL_NOFRAME ) { + current->flags |= SDL_NOFRAME; + SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK); + } else { + if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) ) { + current->flags |= SDL_RESIZABLE; + /* We don't want opaque resizing (TM). :-) */ + SDL_Win->SetFlags(B_OUTLINE_RESIZE); + } else { + SDL_Win->SetFlags(B_NOT_RESIZABLE|B_NOT_ZOOMABLE); + } + } + + if ( flags & SDL_OPENGL ) { + current->flags |= SDL_OPENGL; + current->pitch = 0; + current->pixels = NULL; + _this->UpdateRects = NULL; + } else { + /* Create the BBitmap framebuffer */ + bounds.top = 0; bounds.left = 0; + bounds.right = width-1; + bounds.bottom = height-1; + bbitmap = new BBitmap(bounds, bscreen.ColorSpace()); + if ( ! bbitmap->IsValid() ) { + SDL_SetError("Couldn't create screen bitmap"); + delete bbitmap; + return(NULL); + } + current->pitch = bbitmap->BytesPerRow(); + current->pixels = (void *)bbitmap->Bits(); + SDL_Win->SetBitmap(bbitmap); + _this->UpdateRects = BE_NormalUpdate; + } + + /* Set the correct fullscreen mode */ + BE_SetFullScreen(_this, current, flags & SDL_FULLSCREEN ? 1 : 0); + + /* We're done */ + return(current); +} + +/* Update the current mouse state and position */ +void BE_UpdateMouse(_THIS) +{ + BPoint point; + uint32 buttons; + + if ( SDL_Win->Lock() ) { + /* Get new input state, if still active */ + if ( SDL_Win->IsActive() ) { + (SDL_Win->View())->GetMouse(&point, &buttons, true); + } else { + point.x = -1; + point.y = -1; + } + SDL_Win->Unlock(); + + if ( (point.x >= 0) && (point.x < SDL_VideoSurface->w) && + (point.y >= 0) && (point.y < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, + (Sint16)point.x, (Sint16)point.y); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int BE_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void BE_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int BE_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + if ( SDL_Win->BeginDraw() ) { + int i; + + for ( i=0; i<numrects; ++i ) { + BRect rect; + + rect.top = rects[i].y; + rect.left = rects[i].x; + rect.bottom = rect.top+rects[i].h-1; + rect.right = rect.left+rects[i].w-1; + SDL_Win->DrawAsync(rect); + } + SDL_Win->EndDraw(); + } +} + +#if SDL_VIDEO_OPENGL +/* Passing a NULL path means load pointers from the application */ +int BE_GL_LoadLibrary(_THIS, const char *path) +{ + if (path == NULL) { + if (_this->gl_config.dll_handle == NULL) { + image_info info; + int32 cookie = 0; + while (get_next_image_info(0,&cookie,&info) == B_OK) { + void *location = NULL; +#ifdef __HAIKU__ + if (get_image_symbol(info.id,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // This is how it actually works in Haiku +#else + if (get_image_symbol((image_id)cookie,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // I don't know if that *did* work in BeOS +#endif + _this->gl_config.dll_handle = (void*)info.id; + _this->gl_config.driver_loaded = 1; + SDL_strlcpy(_this->gl_config.driver_path, "libGL.so", SDL_arraysize(_this->gl_config.driver_path)); + } + } + } + } else { + /* + FIXME None of BeOS libGL.so implementations have exported functions + to load BGLView, which should be reloaded from new lib. + So for now just "load" linked libGL.so :( + */ + if (_this->gl_config.dll_handle == NULL) { + return BE_GL_LoadLibrary(_this, NULL); + } + + /* Unload old first */ + /*if (_this->gl_config.dll_handle != NULL) {*/ + /* Do not try to unload application itself (if LoadLibrary was called before with NULL ;) */ + /* image_info info; + if (get_image_info((image_id)_this->gl_config.dll_handle, &info) == B_OK) { + if (info.type != B_APP_IMAGE) { + unload_add_on((image_id)_this->gl_config.dll_handle); + } + } + + } + + if ((_this->gl_config.dll_handle = (void*)load_add_on(path)) != (void*)B_ERROR) { + _this->gl_config.driver_loaded = 1; + SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); + }*/ + } + + if (_this->gl_config.dll_handle != NULL) { + return 0; + } else { + _this->gl_config.dll_handle = NULL; + _this->gl_config.driver_loaded = 0; + *_this->gl_config.driver_path = '\0'; + return -1; + } +} + +void* BE_GL_GetProcAddress(_THIS, const char *proc) +{ + if (_this->gl_config.dll_handle != NULL) { + void *location = NULL; + status_t err; + if ((err = get_image_symbol((image_id)_this->gl_config.dll_handle, proc, B_SYMBOL_TYPE_ANY, &location)) == B_OK) { + return location; + } else { + SDL_SetError("Couldn't find OpenGL symbol"); + return NULL; + } + } else { + SDL_SetError("OpenGL library not loaded"); + return NULL; + } +} + +int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + /* + FIXME? Right now BE_GL_GetAttribute shouldn't be called between glBegin() and glEnd() - it doesn't use "cached" values + */ + switch (attrib) + { + case SDL_GL_RED_SIZE: + glGetIntegerv(GL_RED_BITS, (GLint*)value); + break; + case SDL_GL_GREEN_SIZE: + glGetIntegerv(GL_GREEN_BITS, (GLint*)value); + break; + case SDL_GL_BLUE_SIZE: + glGetIntegerv(GL_BLUE_BITS, (GLint*)value); + break; + case SDL_GL_ALPHA_SIZE: + glGetIntegerv(GL_ALPHA_BITS, (GLint*)value); + break; + case SDL_GL_DOUBLEBUFFER: + glGetBooleanv(GL_DOUBLEBUFFER, (GLboolean*)value); + break; + case SDL_GL_BUFFER_SIZE: + int v; + glGetIntegerv(GL_RED_BITS, (GLint*)&v); + *value = v; + glGetIntegerv(GL_GREEN_BITS, (GLint*)&v); + *value += v; + glGetIntegerv(GL_BLUE_BITS, (GLint*)&v); + *value += v; + glGetIntegerv(GL_ALPHA_BITS, (GLint*)&v); + *value += v; + break; + case SDL_GL_DEPTH_SIZE: + glGetIntegerv(GL_DEPTH_BITS, (GLint*)value); /* Mesa creates 16 only? r5 always 32 */ + break; + case SDL_GL_STENCIL_SIZE: + glGetIntegerv(GL_STENCIL_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_RED_SIZE: + glGetIntegerv(GL_ACCUM_RED_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_GREEN_SIZE: + glGetIntegerv(GL_ACCUM_GREEN_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_BLUE_SIZE: + glGetIntegerv(GL_ACCUM_BLUE_BITS, (GLint*)value); + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + glGetIntegerv(GL_ACCUM_ALPHA_BITS, (GLint*)value); + break; + case SDL_GL_STEREO: + case SDL_GL_MULTISAMPLEBUFFERS: + case SDL_GL_MULTISAMPLESAMPLES: + default: + *value=0; + return(-1); + } + return 0; +} + +int BE_GL_MakeCurrent(_THIS) +{ + /* FIXME: should we glview->unlock and then glview->lock()? */ + return 0; +} + +void BE_GL_SwapBuffers(_THIS) +{ + SDL_Win->SwapBuffers(); +} +#endif + +/* Is the system palette settable? */ +int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Palette *palette; + const color_map *cmap = BScreen().ColorMap(); + + /* Get the screen colormap */ + palette = _this->screen->format->palette; + for ( i=0; i<256; ++i ) { + palette->colors[i].r = cmap->color_list[i].red; + palette->colors[i].g = cmap->color_list[i].green; + palette->colors[i].b = cmap->color_list[i].blue; + } + return(0); +} + +void BE_VideoQuit(_THIS) +{ + int i, j; + + SDL_Win->Quit(); + SDL_Win = NULL; + + if ( SDL_BlankCursor != NULL ) { + BE_FreeWMCursor(_this, SDL_BlankCursor); + SDL_BlankCursor = NULL; + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + /* Restore the original video mode */ + if ( _this->screen ) { + if ( (_this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + BScreen bscreen; + bscreen.SetMode(&saved_mode); + } + _this->screen->pixels = NULL; + } + +#if SDL_VIDEO_OPENGL + if (_this->gl_config.dll_handle != NULL) + unload_add_on((image_id)_this->gl_config.dll_handle); +#endif + + SDL_QuitBeApp(); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc b/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc new file mode 100644 index 0000000..df80100 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_syswm.cc @@ -0,0 +1,92 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_BWin.h" + +extern "C" { +#include "SDL_syswm_c.h" +#include "SDL_error.h" +#include "../SDL_cursor_c.h" + +void BE_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_Win->SetTitle(title); +} + +int BE_IconifyWindow(_THIS) +{ + SDL_Win->Minimize(true); + return 1; +} + +SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode) +{ + if ( mode == SDL_GRAB_OFF ) { +// be_app->ShowCursor(); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* BeSman: Jan 2, 2006 + must be leaving relative mode, move mouse from + center of window to where it belongs ... */ + BPoint pt; + int x, y; + SDL_GetMouseState(&x,&y); + pt.x = x; + pt.y = y; + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int)pt.x, (int)pt.y); + } + } else { +// be_app->HideCursor(); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* BeSman: Jan 2, 2006 + must be entering relative mode, get ready by + moving mouse to center of window ... */ + BPoint pt; + pt.x = (SDL_VideoSurface->w/2); + pt.y = (SDL_VideoSurface->h/2); + SDL_Win->Lock(); + SDL_Win->ConvertToScreen(&pt); + SDL_Win->Unlock(); + set_mouse_position((int)pt.x, (int)pt.y); + } + } + return(mode); +} + +int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) + { + return 1; + } + else + { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return -1; + } +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h b/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h new file mode 100644 index 0000000..c1285c8 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_syswm_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "SDL_lowvideo.h" + + +/* Functions to be exported */ +extern void BE_SetWMCaption(_THIS, const char *title, const char *icon); +extern int BE_IconifyWindow(_THIS); +extern int BE_GetWMInfo(_THIS, SDL_SysWMinfo *info); +extern SDL_GrabMode BE_GrabInput(_THIS, SDL_GrabMode mode); diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc new file mode 100644 index 0000000..7c71b00 --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.cc @@ -0,0 +1,314 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the BeOS version of SDL YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_sysyuv.h" +#include "../SDL_yuvfuncs.h" + +extern "C" { + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs be_yuvfuncs = +{ + BE_LockYUVOverlay, + BE_UnlockYUVOverlay, + BE_DisplayYUVOverlay, + BE_FreeYUVOverlay +}; + +BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs) { + BBitmap *bbitmap; + bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs); + if (!bbitmap || bbitmap->InitCheck() != B_OK) { + delete bbitmap; + return 0; + } + overlay_restrictions r; + bbitmap->GetOverlayRestrictions(&r); + uint32 width = bounds.IntegerWidth() + 1; + uint32 height = bounds.IntegerHeight() + 1; + uint32 width_padding = 0; + uint32 height_padding = 0; + if ((r.source.horizontal_alignment != 0) || + (r.source.vertical_alignment != 0)) { + delete bbitmap; + return 0; + } + if (r.source.width_alignment != 0) { + uint32 aligned_width = r.source.width_alignment + 1; + if (width % aligned_width > 0) { + width_padding = aligned_width - width % aligned_width; + } + } + if (r.source.height_alignment != 0) { + uint32 aligned_height = r.source.height_alignment + 1; + if (height % aligned_height > 0) { + fprintf(stderr,"GetOverlayBitmap failed height alignment\n"); + fprintf(stderr,"- height = %lu, aligned_height = %lu\n",height,aligned_height); + delete bbitmap; + return 0; + } + } + if ((r.source.min_width > width) || + (r.source.min_height > height) || + (r.source.max_width < width) || + (r.source.max_height < height)) { + fprintf(stderr,"GetOverlayBitmap failed bounds tests\n"); + delete bbitmap; + return 0; + } + if ((width_padding != 0) || (height_padding != 0)) { + delete bbitmap; + bounds.Set(bounds.left,bounds.top,bounds.right+width_padding,bounds.bottom+height_padding); + bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs); + if (!bbitmap || bbitmap->InitCheck() != B_OK) { + fprintf(stderr,"GetOverlayBitmap failed late\n"); + delete bbitmap; + return 0; + } + } + return bbitmap; +} + +// See <GraphicsDefs.h> [btw: Cb=U, Cr=V] +// See also http://www.fourcc.org/indexyuv.htm +color_space convert_color_space(Uint32 format) { + switch (format) { + case SDL_YV12_OVERLAY: + return B_YUV9; + case SDL_IYUV_OVERLAY: + return B_YUV12; + case SDL_YUY2_OVERLAY: + return B_YCbCr422; + case SDL_UYVY_OVERLAY: + return B_YUV422; + case SDL_YVYU_OVERLAY: // not supported on beos? + return B_NO_COLOR_SPACE; + default: + return B_NO_COLOR_SPACE; + } +} + +// See SDL_video.h +int count_planes(Uint32 format) { + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + return 3; + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + return 1; + default: + return 0; + } +} + +SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) { + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + BBitmap *bbitmap; + int planes; + BRect bounds; + color_space cs; + + /* find the appropriate BeOS colorspace descriptor */ + cs = convert_color_space(format); + if (cs == B_NO_COLOR_SPACE) + { + return NULL; + } + + /* count planes */ + planes = count_planes(format); + if (planes == 0) + { + return NULL; + } + /* TODO: figure out planar modes, if anyone cares */ + if (planes == 3) + { + return NULL; + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay*)SDL_calloc(1, sizeof(SDL_Overlay)); + + if (overlay == NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &be_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata*)SDL_calloc(1, sizeof(struct private_yuvhwdata)); + + if (hwdata == NULL) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata = hwdata; + overlay->hwdata->display = display; + overlay->hwdata->bview = NULL; + overlay->hwdata->bbitmap = NULL; + overlay->hwdata->locked = 0; + + /* Create the BBitmap framebuffer */ + bounds.top = 0; bounds.left = 0; + bounds.right = width-1; + bounds.bottom = height-1; + + BView * bview = new BView(bounds,"overlay",B_FOLLOW_NONE,B_WILL_DRAW); + if (!bview) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata->bview = bview; + overlay->hwdata->first_display = true; + bview->Hide(); + + bbitmap = BE_GetOverlayBitmap(bounds,cs); + if (!bbitmap) { + overlay->hwdata->bbitmap = NULL; + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata->bbitmap = bbitmap; + + overlay->planes = planes; + overlay->pitches = (Uint16*)SDL_calloc(overlay->planes, sizeof(Uint16)); + overlay->pixels = (Uint8**)SDL_calloc(overlay->planes, sizeof(Uint8*)); + if (!overlay->pitches || !overlay->pixels) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + overlay->pitches[0] = bbitmap->BytesPerRow(); + overlay->pixels[0] = (Uint8 *)bbitmap->Bits(); + overlay->hw_overlay = 1; + + if (SDL_Win->LockWithTimeout(1000000) != B_OK) { + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + BView * view = SDL_Win->View(); + view->AddChild(bview); + rgb_color key; + bview->SetViewOverlay(bbitmap,bounds,bview->Bounds(),&key,B_FOLLOW_ALL, + B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL); + bview->SetViewColor(key); + bview->Flush(); + SDL_Win->Unlock(); + + current_overlay=overlay; + + return overlay; +} + +int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return 0; + } + + overlay->hwdata->locked = 1; + return 0; +} + +void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return; + } + + overlay->hwdata->locked = 0; +} + +int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect *dst) +{ + if ((overlay == NULL) || (overlay->hwdata==NULL) + || (overlay->hwdata->bview==NULL) || (SDL_Win->View() == NULL)) + { + return -1; + } + if (SDL_Win->LockWithTimeout(50000) != B_OK) { + return 0; + } + BView * bview = overlay->hwdata->bview; + if (SDL_Win->IsFullScreen()) { + int left,top; + SDL_Win->GetXYOffset(left,top); + bview->MoveTo(left+dst->x,top+dst->y); + } else { + bview->MoveTo(dst->x,dst->y); + } + bview->ResizeTo(dst->w,dst->h); + bview->Flush(); + if (overlay->hwdata->first_display) { + bview->Show(); + overlay->hwdata->first_display = false; + } + SDL_Win->Unlock(); + + return 0; +} + +void BE_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + if (overlay == NULL) + { + return; + } + + if (overlay->hwdata == NULL) + { + return; + } + + current_overlay=NULL; + + delete overlay->hwdata->bbitmap; + + SDL_free(overlay->hwdata); +} + +}; // extern "C" diff --git a/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h new file mode 100644 index 0000000..fb5961c --- /dev/null +++ b/3rdparty/SDL/src/video/bwindow/SDL_sysyuv.h @@ -0,0 +1,73 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + + +#ifndef __SDL_SYS_YUV_H__ +#define __SDL_SYS_YUV_H__ + +/* This is the BeOS implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_lowvideo.h" + +extern "C" { + +struct private_yuvhwdata +{ +/* FRAMEDATA* CurrentFrameData; + FRAMEDATA* FrameData0; + FRAMEDATA* FrameData1; + PgScalerProps_t props; + PgScalerCaps_t caps; + PgVideoChannel_t* channel; + PhArea_t CurrentViewPort; + PhPoint_t CurrentWindowPos; + long format; + int scaler_on; + int current; + long YStride; + long VStride; + long UStride; + int ischromakey; + long chromakey; + int forcedredraw; + unsigned long State; + long flags; +*/ + SDL_Surface *display; + BView *bview; + bool first_display; + BBitmap *bbitmap; + int locked; +}; + +extern BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs); +extern SDL_Overlay* BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display); +extern int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst); +extern void BE_FreeYUVOverlay(_THIS, SDL_Overlay* overlay); + +}; + +#endif /* __SDL_PH_YUV_H__ */ diff --git a/3rdparty/SDL/src/video/caca/SDL_cacaevents.c b/3rdparty/SDL/src/video/caca/SDL_cacaevents.c new file mode 100644 index 0000000..723b1dd --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacaevents.c @@ -0,0 +1,101 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#include <stdio.h> + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_cacavideo.h" +#include "SDL_cacaevents_c.h" + +void Caca_PumpEvents(_THIS) +{ + int posted = 0; + int event; + SDL_keysym keysym; + + if( ! this->screen ) /* Wait till we got the screen initialised */ + return; + + do { + posted = 0; + + /* Get libcaca event */ + SDL_mutexP(Caca_mutex); + event = caca_get_event(CACA_EVENT_ANY); + SDL_mutexV(Caca_mutex); + + if ( event & (CACA_EVENT_KEY_PRESS | CACA_EVENT_KEY_RELEASE)) { + int key; + switch ( event & 0xffffff ) + { + case CACA_KEY_LEFT: key = SDLK_LEFT; break; + case CACA_KEY_RIGHT: key = SDLK_RIGHT; break; + case CACA_KEY_UP: key = SDLK_UP; break; + case CACA_KEY_DOWN: key = SDLK_DOWN; break; + default: key = event & 0xff; break; + } + /* Key pressed */ +/* printf("Key pressed: %d (%c)\n", key, key); */ + keysym.scancode = key; + keysym.sym = key; + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if ( SDL_TranslateUNICODE ) { + keysym.unicode = key; + } + posted += SDL_PrivateKeyboard((event & CACA_EVENT_KEY_PRESS) ? SDL_PRESSED : SDL_RELEASED, &keysym); + } + else if ( event & (CACA_EVENT_MOUSE_PRESS | CACA_EVENT_MOUSE_RELEASE) ) { + /* FIXME: we currently ignore the button type! */ + int button = event & 0x00ffffff; + if ( button > 3 ) { + button = 1; + } + posted += SDL_PrivateMouseButton((event & CACA_EVENT_MOUSE_PRESS) ? SDL_PRESSED : SDL_RELEASED, button, 0, 0); + } + else if ( event & CACA_EVENT_MOUSE_MOTION ) { + int new_x = 0, new_y = 0; + new_x = ((event & 0x00fff000) >> 12) * Caca_w / caca_get_width(); + new_y = ((event & 0x00000fff) >> 0) * Caca_h / caca_get_height(); + posted += SDL_PrivateMouseMotion(0, 0, new_x, new_y); + } + } while ( posted ); +} + +void Caca_InitOSKeymap(_THIS) +{ + return; +} + + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h b/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h new file mode 100644 index 0000000..988c3b7 --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#include "SDL_cacavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts. + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void Caca_PumpEvents(_THIS); +extern void Caca_InitOSKeymap(_THIS); + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacavideo.c b/3rdparty/SDL/src/video/caca/SDL_cacavideo.c new file mode 100644 index 0000000..59a070c --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacavideo.c @@ -0,0 +1,304 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2003 Sam Hocevar + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Hocevar + sam@zoy.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +/* libcaca based SDL video driver implementation. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + + +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_cacavideo.h" +#include "SDL_cacaevents_c.h" + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +/* Initialization/Query functions */ +static int Caca_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **Caca_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *Caca_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static void Caca_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int Caca_AllocHWSurface(_THIS, SDL_Surface *surface); +static int Caca_LockHWSurface(_THIS, SDL_Surface *surface); +static int Caca_FlipHWSurface(_THIS, SDL_Surface *surface); +static void Caca_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void Caca_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Cache the VideoDevice struct */ +static struct SDL_VideoDevice *local_this; + +/* libcaca driver bootstrap functions */ + +static int Caca_Available(void) +{ + return 1; /* Always available ! */ +} + +static void Caca_DeleteDevice(SDL_VideoDevice *device) +{ + free(device->hidden); + free(device); +} +static SDL_VideoDevice *Caca_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = Caca_VideoInit; + device->ListModes = Caca_ListModes; + device->SetVideoMode = Caca_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = NULL; + device->UpdateRects = NULL; + device->VideoQuit = Caca_VideoQuit; + device->AllocHWSurface = Caca_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = Caca_LockHWSurface; + device->UnlockHWSurface = Caca_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = Caca_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = Caca_InitOSKeymap; + device->PumpEvents = Caca_PumpEvents; + + device->free = Caca_DeleteDevice; + + return device; +} + +VideoBootStrap CACA_bootstrap = { + "caca", "Color ASCII Art Library", + Caca_Available, Caca_CreateDevice +}; + +int Caca_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + SDL_modelist[i] = malloc(sizeof(SDL_Rect)); + SDL_modelist[i]->x = SDL_modelist[i]->y = 0; + } + /* Modes sorted largest to smallest */ + SDL_modelist[0]->w = 1024; SDL_modelist[0]->h = 768; + SDL_modelist[1]->w = 800; SDL_modelist[1]->h = 600; + SDL_modelist[2]->w = 640; SDL_modelist[2]->h = 480; + SDL_modelist[3]->w = 320; SDL_modelist[3]->h = 400; + SDL_modelist[4]->w = 320; SDL_modelist[4]->h = 240; + SDL_modelist[5]->w = 320; SDL_modelist[5]->h = 200; + SDL_modelist[6] = NULL; + + Caca_mutex = SDL_CreateMutex(); + + /* Initialize the library */ + if ( caca_init() != 0 ) { + SDL_SetError("Unable to initialize libcaca"); + return(-1); + } + + /* Initialize private variables */ + Caca_lastkey = 0; + Caca_bitmap = NULL; + Caca_buffer = NULL; + + local_this = this; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **Caca_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if(format->BitsPerPixel != 8) + return NULL; + + if ( flags & SDL_FULLSCREEN ) { + return SDL_modelist; + } else { + return (SDL_Rect **) -1; + } +} + +/* Various screen update functions available */ +static void Caca_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *Caca_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( Caca_buffer ) { + free( Caca_buffer ); + Caca_buffer = NULL; + } + + if ( Caca_bitmap ) { + caca_free_bitmap( Caca_bitmap ); + Caca_bitmap = NULL; + } + + Caca_buffer = malloc(2 * ((width + 15) & ~15) * height); + if ( ! Caca_buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + + memset(Caca_buffer, 0, 2 * ((width + 15) & ~15) * height); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, 16, 0xf800, 0x07e0, 0x001f, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + Caca_w = current->w = width; + Caca_h = current->h = height; + current->pitch = 2 * ((width + 15) & ~15); + current->pixels = Caca_buffer; + + /* Create the libcaca bitmap */ + Caca_bitmap = caca_create_bitmap( 16, width, height, current->pitch, 0xf800, 0x07e0, 0x001f, 0x0000 ); + if ( ! Caca_bitmap ) { + SDL_SetError("Couldn't allocate libcaca bitmap"); + return(NULL); + } + + /* Set the blit function */ + this->UpdateRects = Caca_DirectUpdate; + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int Caca_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void Caca_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int Caca_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* TODO ? */ + return(0); +} +static void Caca_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* FIXME: How is this done with libcaca? */ +static int Caca_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + SDL_mutexP(Caca_mutex); + caca_refresh(); + SDL_mutexV(Caca_mutex); + return(0); +} + +static void Caca_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_mutexP(Caca_mutex); + caca_draw_bitmap( 0, 0, caca_get_width() - 1, caca_get_height() - 1, + Caca_bitmap, Caca_buffer ); + caca_refresh(); + SDL_mutexV(Caca_mutex); + return; +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void Caca_VideoQuit(_THIS) +{ + int i; + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( SDL_modelist[i] != NULL ) { + free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + if ( Caca_bitmap ) { + caca_free_bitmap( Caca_bitmap ); + Caca_bitmap = NULL; + } + + caca_end(); + + SDL_DestroyMutex(Caca_mutex); +} + diff --git a/3rdparty/SDL/src/video/caca/SDL_cacavideo.h b/3rdparty/SDL/src/video/caca/SDL_cacavideo.h new file mode 100644 index 0000000..91fcc81 --- /dev/null +++ b/3rdparty/SDL/src/video/caca/SDL_cacavideo.h @@ -0,0 +1,76 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 2003 Sam Hocevar + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Hocevar + sam@zoy.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: libsdl-1.2.11-libcaca.patch,v 1.1 2006/09/18 16:06:06 mr_bones_ Exp $"; +#endif + +#ifndef _SDL_cacavideo_h +#define _SDL_cacavideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "SDL_mutex.h" + +#include <sys/time.h> +#include <time.h> + +#include <caca.h> +#ifdef CACA_API_VERSION_1 +#include <caca0.h> +#endif + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define SDL_NUMMODES 6 + +/* Private display data */ +struct SDL_PrivateVideoData { + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; + SDL_mutex *mutex; + + struct caca_bitmap *bitmap; + void *buffer; + int w, h; + + int lastkey; + struct timeval lasttime; +}; + +/* Old variable names */ +#define SDL_modelist (this->hidden->SDL_modelist) +#define Caca_palette (this->hidden->palette) +#define Caca_bitmap (this->hidden->bitmap) +#define Caca_buffer (this->hidden->buffer) + +#define Caca_w (this->hidden->w) +#define Caca_h (this->hidden->h) + +#define Caca_lastkey (this->hidden->lastkey) +#define Caca_lasttime (this->hidden->lasttime) + +#define Caca_mutex (this->hidden->mutex) + +#endif /* _SDL_cacavideo_h */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcevents.c b/3rdparty/SDL/src/video/dc/SDL_dcevents.c new file mode 100644 index 0000000..38dcca4 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcevents.c @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dcvideo.h" +#include "SDL_dcevents_c.h" + +#include <dc/maple.h> +#include <dc/maple/mouse.h> +#include <dc/maple/keyboard.h> + +const static unsigned short sdl_key[]= { + /*0*/ 0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + /*1e*/ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + /*28*/ SDLK_RETURN, SDLK_ESCAPE, SDLK_BACKSPACE, SDLK_TAB, SDLK_SPACE, SDLK_MINUS, SDLK_PLUS, SDLK_LEFTBRACKET, + SDLK_RIGHTBRACKET, SDLK_BACKSLASH , 0, SDLK_SEMICOLON, SDLK_QUOTE, + /*35*/ '~', SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_CAPSLOCK, + SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12, + /*46*/ SDLK_PRINT, SDLK_SCROLLOCK, SDLK_PAUSE, SDLK_INSERT, SDLK_HOME, SDLK_PAGEUP, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, SDLK_RIGHT, SDLK_LEFT, SDLK_DOWN, SDLK_UP, + /*53*/ SDLK_NUMLOCK, SDLK_KP_DIVIDE, SDLK_KP_MULTIPLY, SDLK_KP_MINUS, SDLK_KP_PLUS, SDLK_KP_ENTER, + SDLK_KP1, SDLK_KP2, SDLK_KP3, SDLK_KP4, SDLK_KP5, SDLK_KP6, + /*5f*/ SDLK_KP7, SDLK_KP8, SDLK_KP9, SDLK_KP0, SDLK_KP_PERIOD, 0 /* S3 */ +}; + +const static unsigned short sdl_shift[] = { + SDLK_LCTRL,SDLK_LSHIFT,SDLK_LALT,0 /* S1 */, + SDLK_RCTRL,SDLK_RSHIFT,SDLK_RALT,0 /* S2 */, +}; + +#define MOUSE_WHEELUP (1<<4) +#define MOUSE_WHEELDOWN (1<<5) + +static void mouse_update(void) +{ +const static char sdl_mousebtn[] = { + MOUSE_LEFTBUTTON, + MOUSE_RIGHTBUTTON, + MOUSE_SIDEBUTTON, + MOUSE_WHEELUP, + MOUSE_WHEELDOWN +}; + + uint8 addr; + mouse_cond_t cond; + + static int prev_buttons; + int buttons,changed; + int i; + + if ((addr = maple_first_mouse())==0 || mouse_get_cond(addr, &cond)<0) return; + + buttons = cond.buttons^0xff; + if (cond.dz<0) buttons|=MOUSE_WHEELUP; + if (cond.dz>0) buttons|=MOUSE_WHEELDOWN; + + if (cond.dx||cond.dy) SDL_PrivateMouseMotion(0,1,cond.dx,cond.dy); + + changed = buttons^prev_buttons; + for(i=0;i<sizeof(sdl_mousebtn);i++) { + if (changed & sdl_mousebtn[i]) { + SDL_PrivateMouseButton((buttons & sdl_mousebtn[i])?SDL_PRESSED:SDL_RELEASED,i,0,0); + } + } + prev_buttons = buttons; +} + +static void keyboard_update(void) +{ + static kbd_state_t old_state; + static uint8 old_addr; + + kbd_state_t *state; + uint8 addr; + int port,unit; + + int shiftkeys; + SDL_keysym keysym; + + int i; + + addr = maple_first_kb(); + + if (addr==0) return; + + if (addr!=old_addr) { + old_addr = addr; + SDL_memset(&old_state,0,sizeof(old_state)); + } + + maple_raddr(addr,&port,&unit); + + state = maple_dev_state(port,unit); + if (!state) return; + + shiftkeys = state->shift_keys ^ old_state.shift_keys; + for(i=0;i<sizeof(sdl_shift);i++) { + if ((shiftkeys>>i)&1) { + keysym.sym = sdl_shift[i]; + SDL_PrivateKeyboard(((state->shift_keys>>i)&1)?SDL_PRESSED:SDL_RELEASED,&keysym); + } + } + + for(i=0;i<sizeof(sdl_key);i++) { + if (state->matrix[i]!=old_state.matrix[i]) { + int key = sdl_key[i]; + if (key) { + keysym.sym = key; + SDL_PrivateKeyboard(state->matrix[i]?SDL_PRESSED:SDL_RELEASED,&keysym); + } + } + } + + old_state = *state; +} + +void DC_PumpEvents(_THIS) +{ + keyboard_update(); + mouse_update(); +} + +void DC_InitOSKeymap(_THIS) +{ + /* do nothing. */ +} + +/* end of SDL_dcevents.c ... */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h b/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h new file mode 100644 index 0000000..3196eae --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dcvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void DC_InitOSKeymap(_THIS); +extern void DC_PumpEvents(_THIS); + +/* end of SDL_dcevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/dc/SDL_dcmouse.c b/3rdparty/SDL/src/video/dc/SDL_dcmouse.c new file mode 100644 index 0000000..61a0ba0 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcmouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_dcmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h b/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h new file mode 100644 index 0000000..dc018bb --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dcvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dc/SDL_dcvideo.c b/3rdparty/SDL/src/video/dc/SDL_dcvideo.c new file mode 100644 index 0000000..5838a49 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcvideo.c @@ -0,0 +1,445 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_dcvideo.h" +#include "SDL_dcevents_c.h" +#include "SDL_dcmouse_c.h" + +#include <dc/video.h> +#include <dc/pvr.h> + + +/* Initialization/Query functions */ +static int DC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void DC_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DC_LockHWSurface(_THIS, SDL_Surface *surface); +static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DC_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DC_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* OpenGL */ +#if SDL_VIDEO_OPENGL +static void *DC_GL_GetProcAddress(_THIS, const char *proc); +static int DC_GL_LoadLibrary(_THIS, const char *path); +static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +static void DC_GL_SwapBuffers(_THIS); +#endif + +/* DC driver bootstrap functions */ + +static int DC_Available(void) +{ + return 1; +} + +static void DC_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DC_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DC_VideoInit; + device->ListModes = DC_ListModes; + device->SetVideoMode = DC_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = DC_SetColors; + device->UpdateRects = DC_UpdateRects; + device->VideoQuit = DC_VideoQuit; + device->AllocHWSurface = DC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DC_LockHWSurface; + device->UnlockHWSurface = DC_UnlockHWSurface; + device->FlipHWSurface = DC_FlipHWSurface; + device->FreeHWSurface = DC_FreeHWSurface; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = DC_GL_LoadLibrary; + device->GL_GetProcAddress = DC_GL_GetProcAddress; + device->GL_GetAttribute = DC_GL_GetAttribute; + device->GL_MakeCurrent = NULL; + device->GL_SwapBuffers = DC_GL_SwapBuffers; +#endif + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DC_InitOSKeymap; + device->PumpEvents = DC_PumpEvents; + + device->free = DC_DeleteDevice; + + return device; +} + +VideoBootStrap DC_bootstrap = { + "dcvideo", "Dreamcast Video", + DC_Available, DC_CreateDevice +}; + + +int DC_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* Determine the screen depth (use default 16-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + + /* We're done! */ + return(0); +} + +const static SDL_Rect + RECT_800x600 = {0,0,800,600}, + RECT_640x480 = {0,0,640,480}, + RECT_320x240 = {0,0,320,240}; +const static SDL_Rect *vid_modes[] = { + &RECT_800x600, + &RECT_640x480, + &RECT_320x240, + NULL +}; + +SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + switch(format->BitsPerPixel) { + case 15: + case 16: + return &vid_modes; + case 32: + if (!(flags & SDL_OPENGL)) + return &vid_modes; + default: + return NULL; + } +// return (SDL_Rect **) -1; +} + +pvr_init_params_t params = { + /* Enable opaque and translucent polygons with size 16 */ + { PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16 }, + + /* Vertex buffer size */ + 512*1024 +}; + +#if SDL_VIDEO_OPENGL +static int pvr_inited; +#endif + +SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int disp_mode,pixel_mode,pitch; + Uint32 Rmask, Gmask, Bmask; + + if (width==320 && height==240) disp_mode=DM_320x240; + else if (width==640 && height==480) disp_mode=DM_640x480; + else if (width==800 && height==600) disp_mode=DM_800x608; + else { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + + switch(bpp) { + case 15: pixel_mode = PM_RGB555; pitch = width*2; + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + break; + case 16: pixel_mode = PM_RGB565; pitch = width*2; + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + break; + case 24: bpp = 32; + case 32: pixel_mode = PM_RGB888; pitch = width*4; + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; +#if SDL_VIDEO_OPENGL + if (!(flags & SDL_OPENGL)) +#endif + break; + default: + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + +// if ( bpp != current->format->BitsPerPixel ) { + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + return(NULL); + } +// } + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); + current->w = width; + current->h = height; + current->pitch = pitch; + +#if SDL_VIDEO_OPENGL + if (pvr_inited) { + pvr_inited = 0; + pvr_shutdown(); + } +#endif + + vid_set_mode(disp_mode,pixel_mode); + + current->pixels = vram_s; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + this->gl_config.driver_loaded = 1; + current->flags = SDL_FULLSCREEN | SDL_OPENGL; + current->pixels = NULL; + pvr_inited = 1; + pvr_init(¶ms); + glKosInit(); + glKosBeginFrame(); + } else +#endif + if (flags | SDL_DOUBLEBUF) { + current->flags |= SDL_DOUBLEBUF; + current->pixels = (void*)((int)current->pixels | 0x400000); + } + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int DC_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DC_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int DC_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int DC_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->flags & SDL_DOUBLEBUF) { + vid_set_start((int)surface->pixels & 0xffffff); + surface->pixels = (void*)((int)surface->pixels ^ 0x400000); + } + return(0); +} + +static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + /* do nothing. */ +} + +static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void DC_VideoQuit(_THIS) +{ +#if SDL_VIDEO_OPENGL + if (pvr_inited) { + pvr_inited = 0; + pvr_shutdown(); + } +#endif +} + +#if SDL_VIDEO_OPENGL + +void dmyfunc(void) {} + +typedef void (*funcptr)(); +const static struct { + char *name; + funcptr addr; +} glfuncs[] = { +#define DEF(func) {#func,&func} + DEF(glBegin), + DEF(glBindTexture), + DEF(glBlendFunc), + DEF(glColor4f), +// DEF(glCopyImageID), + DEF(glDisable), + DEF(glEnable), + DEF(glEnd), + DEF(glFlush), + DEF(glGenTextures), + DEF(glGetString), + DEF(glLoadIdentity), + DEF(glMatrixMode), + DEF(glOrtho), + DEF(glPixelStorei), +// DEF(glPopAttrib), +// DEF(glPopClientAttrib), + {"glPopAttrib",&dmyfunc}, + {"glPopClientAttrib",&dmyfunc}, + DEF(glPopMatrix), +// DEF(glPushAttrib), +// DEF(glPushClientAttrib), + {"glPushAttrib",&dmyfunc}, + {"glPushClientAttrib",&dmyfunc}, + DEF(glPushMatrix), + DEF(glTexCoord2f), + DEF(glTexEnvf), + DEF(glTexImage2D), + DEF(glTexParameteri), + DEF(glTexSubImage2D), + DEF(glVertex2i), + DEF(glViewport), +#undef DEF +}; + +static void *DC_GL_GetProcAddress(_THIS, const char *proc) +{ + void *ret; + int i; + + ret = glKosGetProcAddress(proc); + if (ret) return ret; + + for(i=0;i<sizeof(glfuncs)/sizeof(glfuncs[0]);i++) { + if (SDL_strcmp(proc,glfuncs[i].name)==0) return glfuncs[i].addr; + } + + return NULL; +} + +static int DC_GL_LoadLibrary(_THIS, const char *path) +{ + this->gl_config.driver_loaded = 1; + + return 0; +} + +static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + GLenum mesa_attrib; + int val; + + switch(attrib) { + case SDL_GL_RED_SIZE: + val = 5; + break; + case SDL_GL_GREEN_SIZE: + val = 6; + break; + case SDL_GL_BLUE_SIZE: + val = 5; + break; + case SDL_GL_ALPHA_SIZE: + val = 0; + break; + case SDL_GL_DOUBLEBUFFER: + val = 1; + break; + case SDL_GL_DEPTH_SIZE: + val = 16; /* or 32? */ + break; + case SDL_GL_STENCIL_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_RED_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + val = 0; + case SDL_GL_ACCUM_BLUE_SIZE: + val = 0; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + val = 0; + break; + default : + return -1; + } + *value = val; + return 0; +} + +static void DC_GL_SwapBuffers(_THIS) +{ + glKosFinishFrame(); + glKosBeginFrame(); +} +#endif diff --git a/3rdparty/SDL/src/video/dc/SDL_dcvideo.h b/3rdparty/SDL/src/video/dc/SDL_dcvideo.h new file mode 100644 index 0000000..837f028 --- /dev/null +++ b/3rdparty/SDL/src/video/dc/SDL_dcvideo.h @@ -0,0 +1,42 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dcvideo_h +#define _SDL_dcvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; +}; + +#endif /* _SDL_dcvideo_h */ diff --git a/3rdparty/SDL/src/video/default_cursor.h b/3rdparty/SDL/src/video/default_cursor.h new file mode 100644 index 0000000..d637223 --- /dev/null +++ b/3rdparty/SDL/src/video/default_cursor.h @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Default cursor - it happens to be the Mac cursor, but could be anything */ + +#define DEFAULT_CWIDTH 16 +#define DEFAULT_CHEIGHT 16 +#define DEFAULT_CHOTX 0 +#define DEFAULT_CHOTY 0 + +/* Added a real MacOS cursor, at the request of Luc-Olivier de Charrire */ +#define USE_MACOS_CURSOR + +#ifdef USE_MACOS_CURSOR + +static unsigned char default_cdata[] = +{ + 0x00,0x00, + 0x40,0x00, + 0x60,0x00, + 0x70,0x00, + 0x78,0x00, + 0x7C,0x00, + 0x7E,0x00, + 0x7F,0x00, + 0x7F,0x80, + 0x7C,0x00, + 0x6C,0x00, + 0x46,0x00, + 0x06,0x00, + 0x03,0x00, + 0x03,0x00, + 0x00,0x00 +}; +static unsigned char default_cmask[] = +{ + 0xC0,0x00, + 0xE0,0x00, + 0xF0,0x00, + 0xF8,0x00, + 0xFC,0x00, + 0xFE,0x00, + 0xFF,0x00, + 0xFF,0x80, + 0xFF,0xC0, + 0xFF,0xE0, + 0xFE,0x00, + 0xEF,0x00, + 0xCF,0x00, + 0x87,0x80, + 0x07,0x80, + 0x03,0x00 +}; + +#else + +static unsigned char default_cdata[] = +{ + 0x00,0x00, + 0x40,0x00, + 0x60,0x00, + 0x70,0x00, + 0x78,0x00, + 0x7C,0x00, + 0x7E,0x00, + 0x7F,0x00, + 0x7F,0x80, + 0x7C,0x00, + 0x6C,0x00, + 0x46,0x00, + 0x06,0x00, + 0x03,0x00, + 0x03,0x00, + 0x00,0x00 +}; +static unsigned char default_cmask[] = +{ + 0x40,0x00, + 0xE0,0x00, + 0xF0,0x00, + 0xF8,0x00, + 0xFC,0x00, + 0xFE,0x00, + 0xFF,0x00, + 0xFF,0x80, + 0xFF,0xC0, + 0xFF,0x80, + 0xFE,0x00, + 0xEF,0x00, + 0x4F,0x00, + 0x07,0x80, + 0x07,0x80, + 0x03,0x00 +}; + +#endif /* TRUE_MACINTOSH_CURSOR */ diff --git a/3rdparty/SDL/src/video/dga/SDL_dgaevents.c b/3rdparty/SDL/src/video/dga/SDL_dgaevents.c new file mode 100644 index 0000000..4e6d5f0 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgaevents.c @@ -0,0 +1,163 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting DGA events into SDL events */ + +#include <stdio.h> +#include <X11/Xlib.h> +#include "../Xext/extensions/xf86dga.h" + +#include "SDL_timer.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgaevents_c.h" + +/* get function pointers... */ +#include "../x11/SDL_x11dyn.h" + +/* Heheh we're using X11 event code */ +extern int X11_Pending(Display *display); +extern void X11_InitKeymap(void); +extern SDLKey X11_TranslateKeycode(Display *display, KeyCode kc); + +static int DGA_DispatchEvent(_THIS) +{ + int posted; + SDL_NAME(XDGAEvent) xevent; + + XNextEvent(DGA_Display, (XEvent *)&xevent); + + posted = 0; + xevent.type -= DGA_event_base; + switch (xevent.type) { + + /* Mouse motion? */ + case MotionNotify: { + if ( SDL_VideoSurface ) { + posted = SDL_PrivateMouseMotion(0, 1, + xevent.xmotion.dx, xevent.xmotion.dy); + } + } + break; + + /* Mouse button press? */ + case ButtonPress: { + posted = SDL_PrivateMouseButton(SDL_PRESSED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Mouse button release? */ + case ButtonRelease: { + posted = SDL_PrivateMouseButton(SDL_RELEASED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Key press? */ + case KeyPress: { + SDL_keysym keysym; + KeyCode keycode; + XKeyEvent xkey; + + SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey); + keycode = xkey.keycode; +#ifdef DEBUG_XEVENTS +printf("KeyPress (X11 keycode = 0x%X)\n", xkey.keycode); +#endif + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(DGA_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + /* Look up the translated value for the key event */ + if ( SDL_TranslateUNICODE ) { + static XComposeStatus state; + char keybuf[32]; + + if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, &state) ) { + /* + * FIXME: XLookupString() may yield more than one + * character, so we need a mechanism to allow for + * this (perhaps null keypress events with a + * unicode value) + */ + keysym.unicode = (Uint8)keybuf[0]; + } + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + + /* Key release? */ + case KeyRelease: { + SDL_keysym keysym; + KeyCode keycode; + XKeyEvent xkey; + + SDL_NAME(XDGAKeyEventToXKeyEvent)(&xevent.xkey, &xkey); + keycode = xkey.keycode; +#ifdef DEBUG_XEVENTS +printf("KeyRelease (X11 keycode = 0x%X)\n", xkey.keycode); +#endif + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(DGA_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + } + return(posted); +} + +void DGA_PumpEvents(_THIS) +{ + /* Keep processing pending events */ + LOCK_DISPLAY(); + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) { + XResetScreenSaver(DGA_Display); + screensaverTicks = nowTicks; + } + } + + while ( X11_Pending(DGA_Display) ) { + DGA_DispatchEvent(this); + } + + UNLOCK_DISPLAY(); +} + +void DGA_InitOSKeymap(_THIS) +{ + X11_InitKeymap(); +} + diff --git a/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h b/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h new file mode 100644 index 0000000..45f8cc5 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgaevents_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dgavideo.h" + +/* Functions to be exported */ +extern void DGA_PumpEvents(_THIS); +extern void DGA_InitOSKeymap(_THIS); diff --git a/3rdparty/SDL/src/video/dga/SDL_dgamouse.c b/3rdparty/SDL/src/video/dga/SDL_dgamouse.c new file mode 100644 index 0000000..43bc5d6 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgamouse.c @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h b/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h new file mode 100644 index 0000000..4ea8b21 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_dgavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dga/SDL_dgavideo.c b/3rdparty/SDL/src/video/dga/SDL_dgavideo.c new file mode 100644 index 0000000..267d5cc --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgavideo.c @@ -0,0 +1,1101 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* DGA 2.0 based SDL video driver implementation. +*/ + +#include <stdio.h> + +#include <X11/Xlib.h> +#include "../Xext/extensions/xf86dga.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_dgavideo.h" +#include "SDL_dgamouse_c.h" +#include "SDL_dgaevents_c.h" + +/* get function pointers... */ +#include "../x11/SDL_x11dyn.h" + +/*#define DGA_DEBUG*/ + +/* Initialization/Query functions */ +static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DGA_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DGA_SetGammaRamp(_THIS, Uint16 *ramp); +static void DGA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size); +static void DGA_FreeHWSurfaces(_THIS); +static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); +static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DGA_LockHWSurface(_THIS, SDL_Surface *surface); +static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* DGA driver bootstrap functions */ + +static int DGA_Available(void) +{ + const char *display = NULL; + Display *dpy = NULL; + int available = 0; + + /* The driver is available is available if the display is local + and the DGA 2.0+ extension is available, and we can map mem. + */ + if ( SDL_X11_LoadSymbols() ) { + if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) || + (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) { + dpy = XOpenDisplay(display); + if ( dpy ) { + int events, errors, major, minor; + + if ( SDL_NAME(XDGAQueryExtension)(dpy, &events, &errors) && + SDL_NAME(XDGAQueryVersion)(dpy, &major, &minor) ) { + int screen; + + screen = DefaultScreen(dpy); + if ( (major >= 2) && + SDL_NAME(XDGAOpenFramebuffer)(dpy, screen) ) { + available = 1; + SDL_NAME(XDGACloseFramebuffer)(dpy, screen); + } + } + XCloseDisplay(dpy); + } + } + SDL_X11_UnloadSymbols(); + } + return(available); +} + +static void DGA_DeleteDevice(SDL_VideoDevice *device) +{ + if (device != NULL) { + SDL_free(device->hidden); + SDL_free(device); + SDL_X11_UnloadSymbols(); + } +} + +static SDL_VideoDevice *DGA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device = NULL; + + /* Initialize all variables that we clean on shutdown */ + if (SDL_X11_LoadSymbols()) { + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + SDL_X11_UnloadSymbols(); + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DGA_VideoInit; + device->ListModes = DGA_ListModes; + device->SetVideoMode = DGA_SetVideoMode; + device->SetColors = DGA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DGA_VideoQuit; + device->AllocHWSurface = DGA_AllocHWSurface; + device->CheckHWBlit = DGA_CheckHWBlit; + device->FillHWRect = DGA_FillHWRect; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DGA_LockHWSurface; + device->UnlockHWSurface = DGA_UnlockHWSurface; + device->FlipHWSurface = DGA_FlipHWSurface; + device->FreeHWSurface = DGA_FreeHWSurface; + device->SetGammaRamp = DGA_SetGammaRamp; + device->GetGammaRamp = NULL; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DGA_InitOSKeymap; + device->PumpEvents = DGA_PumpEvents; + + device->free = DGA_DeleteDevice; + } + + return device; +} + +VideoBootStrap DGA_bootstrap = { + "dga", "XFree86 DGA 2.0", + DGA_Available, DGA_CreateDevice +}; + +static int DGA_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + if ( SDL_nummodes[index] > 0 ) { + mode = SDL_modelist[index][SDL_nummodes[index]-1]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +/* This whole function is a hack. :) */ +static Uint32 get_video_size(_THIS) +{ + /* This is a non-exported function from libXxf86dga.a */ + extern unsigned char *SDL_NAME(XDGAGetMappedMemory)(int screen); + FILE *proc; + unsigned long mem; + unsigned start, stop; + char line[BUFSIZ]; + Uint32 size; + + mem = (unsigned long)SDL_NAME(XDGAGetMappedMemory)(DGA_Screen); + size = 0; + proc = fopen("/proc/self/maps", "r"); + if ( proc ) { + while ( fgets(line, sizeof(line)-1, proc) ) { + SDL_sscanf(line, "%x-%x", &start, &stop); + if ( start == mem ) { + size = (Uint32)((stop-start)/1024); + break; + } + } + fclose(proc); + } + return(size); +} + +#ifdef DGA_DEBUG +static void PrintMode(SDL_NAME(XDGAMode) *mode) +{ + printf("Mode: %s (%dx%d) at %d bpp (%f refresh, %d pitch) num: %d\n", + mode->name, + mode->viewportWidth, mode->viewportHeight, + mode->depth == 24 ? mode->bitsPerPixel : mode->depth, + mode->verticalRefresh, mode->bytesPerScanline, mode->num); + printf("\tRGB: 0x%8.8x 0x%8.8x 0x%8.8x (%d - %s)\n", + mode->redMask, mode->greenMask, mode->blueMask, + mode->visualClass, + mode->visualClass == TrueColor ? "truecolor" : + mode->visualClass == DirectColor ? "directcolor" : + mode->visualClass == PseudoColor ? "pseudocolor" : "unknown"); + printf("\tFlags: "); + if ( mode->flags & XDGAConcurrentAccess ) + printf(" XDGAConcurrentAccess"); + if ( mode->flags & XDGASolidFillRect ) + printf(" XDGASolidFillRect"); + if ( mode->flags & XDGABlitRect ) + printf(" XDGABlitRect"); + if ( mode->flags & XDGABlitTransRect ) + printf(" XDGABlitTransRect"); + if ( mode->flags & XDGAPixmap ) + printf(" XDGAPixmap"); + if ( mode->flags & XDGAInterlaced ) + printf(" XDGAInterlaced"); + if ( mode->flags & XDGADoublescan ) + printf(" XDGADoublescan"); + if ( mode->viewportFlags & XDGAFlipRetrace ) + printf(" XDGAFlipRetrace"); + if ( mode->viewportFlags & XDGAFlipImmediate ) + printf(" XDGAFlipImmediate"); + printf("\n"); +} +#endif /* DGA_DEBUG */ + +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_NAME(XDGAMode) *a = (const SDL_NAME(XDGAMode) *)va; + const SDL_NAME(XDGAMode) *b = (const SDL_NAME(XDGAMode) *)vb; + + if ( (a->viewportWidth == b->viewportWidth) && + (b->viewportHeight == a->viewportHeight) ) { + /* Prefer 32 bpp over 24 bpp, 16 bpp over 15 bpp */ + int a_bpp = a->depth == 24 ? a->bitsPerPixel : a->depth; + int b_bpp = b->depth == 24 ? b->bitsPerPixel : b->depth; + if ( a_bpp != b_bpp ) { + return b_bpp - a_bpp; + } + /* Prefer DirectColor visuals, for gamma support */ + if ( a->visualClass == DirectColor && b->visualClass != DirectColor ) + return -1; + if ( b->visualClass == DirectColor && a->visualClass != DirectColor ) + return 1; + /* Maintain server refresh rate sorting */ + return a->num - b->num; + } else if ( a->viewportWidth == b->viewportWidth ) { + return b->viewportHeight - a->viewportHeight; + } else { + return b->viewportWidth - a->viewportWidth; + } +} +static void UpdateHWInfo(_THIS, SDL_NAME(XDGAMode) *mode) +{ + this->info.wm_available = 0; + this->info.hw_available = 1; + if ( mode->flags & XDGABlitRect ) { + this->info.blit_hw = 1; + } else { + this->info.blit_hw = 0; + } + if ( mode->flags & XDGABlitTransRect ) { + this->info.blit_hw_CC = 1; + } else { + this->info.blit_hw_CC = 0; + } + if ( mode->flags & XDGASolidFillRect ) { + this->info.blit_fill = 1; + } else { + this->info.blit_fill = 0; + } + this->info.video_mem = get_video_size(this); +} + +static int DGA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env; + const char *display; + int event_base, error_base; + int major_version, minor_version; + Visual *visual; + SDL_NAME(XDGAMode) *modes; + int i, num_modes; + + /* Open the X11 display */ + display = NULL; /* Get it from DISPLAY environment variable */ + + DGA_Display = XOpenDisplay(display); + if ( DGA_Display == NULL ) { + SDL_SetError("Couldn't open X11 display"); + return(-1); + } + + /* Check for the DGA extension */ + if ( ! SDL_NAME(XDGAQueryExtension)(DGA_Display, &event_base, &error_base) || + ! SDL_NAME(XDGAQueryVersion)(DGA_Display, &major_version, &minor_version) ) { + SDL_SetError("DGA extension not available"); + XCloseDisplay(DGA_Display); + return(-1); + } + if ( major_version < 2 ) { + SDL_SetError("DGA driver requires DGA 2.0 or newer"); + XCloseDisplay(DGA_Display); + return(-1); + } + DGA_event_base = event_base; + + /* Determine the current screen size */ + this->info.current_w = DisplayWidth(DGA_Display, DGA_Screen); + this->info.current_h = DisplayHeight(DGA_Display, DGA_Screen); + + /* Determine the current screen depth */ + visual = DefaultVisual(DGA_Display, DGA_Screen); + { + XPixmapFormatValues *pix_format; + int i, num_formats; + + vformat->BitsPerPixel = DefaultDepth(DGA_Display, DGA_Screen); + pix_format = XListPixmapFormats(DGA_Display, &num_formats); + if ( pix_format == NULL ) { + SDL_SetError("Couldn't determine screen formats"); + XCloseDisplay(DGA_Display); + return(-1); + } + for ( i=0; i<num_formats; ++i ) { + if ( vformat->BitsPerPixel == pix_format[i].depth ) + break; + } + if ( i != num_formats ) + vformat->BitsPerPixel = pix_format[i].bits_per_pixel; + XFree((char *)pix_format); + } + if ( vformat->BitsPerPixel > 8 ) { + vformat->Rmask = visual->red_mask; + vformat->Gmask = visual->green_mask; + vformat->Bmask = visual->blue_mask; + } + + /* Open access to the framebuffer */ + if ( ! SDL_NAME(XDGAOpenFramebuffer)(DGA_Display, DGA_Screen) ) { + SDL_SetError("Unable to map the video memory"); + XCloseDisplay(DGA_Display); + return(-1); + } + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* Query for the list of available video modes */ + modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes); + SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes); + for ( i=0; i<num_modes; ++i ) { + if ( ((modes[i].visualClass == PseudoColor) || + (modes[i].visualClass == DirectColor) || + (modes[i].visualClass == TrueColor)) && + !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) { +#ifdef DGA_DEBUG + PrintMode(&modes[i]); +#endif + DGA_AddMode(this, modes[i].bitsPerPixel, + modes[i].viewportWidth, + modes[i].viewportHeight); + } + } + UpdateHWInfo(this, modes); + XFree(modes); + + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if ( hw_lock == NULL ) { + SDL_SetError("Unable to create lock mutex"); + DGA_VideoQuit(this); + return(-1); + } + +#ifdef LOCK_DGA_DISPLAY + /* Create the event lock so we're thread-safe.. :-/ */ + event_lock = SDL_CreateMutex(); +#endif /* LOCK_DGA_DISPLAY */ + + /* We're done! */ + return(0); +} + +SDL_Rect **DGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *DGA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_NAME(XDGAMode) *modes; + int i, num_modes; + SDL_NAME(XDGADevice) *mode; + int screen_len; + Uint8 *surfaces_mem; + int surfaces_len; + + /* Free any previous colormap */ + if ( DGA_colormap ) { + XFreeColormap(DGA_Display, DGA_colormap); + DGA_colormap = 0; + } + + /* Search for a matching video mode */ + modes = SDL_NAME(XDGAQueryModes)(DGA_Display, DGA_Screen, &num_modes); + SDL_qsort(modes, num_modes, sizeof *modes, cmpmodes); + for ( i=0; i<num_modes; ++i ) { + int depth; + + depth = modes[i].depth; + if ( depth == 24 ) { /* Distinguish between 24 and 32 bpp */ + depth = modes[i].bitsPerPixel; + } + if ( (depth == bpp) && + (modes[i].viewportWidth == width) && + (modes[i].viewportHeight == height) && + ((modes[i].visualClass == PseudoColor) || + (modes[i].visualClass == DirectColor) || + (modes[i].visualClass == TrueColor)) && + !(modes[i].flags & (XDGAInterlaced|XDGADoublescan)) ) { + break; + } + } + if ( i == num_modes ) { + SDL_SetError("No matching video mode found"); + return(NULL); + } +#ifdef DGA_DEBUG + PrintMode(&modes[i]); +#endif + + /* Set the video mode */ + mode = SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, modes[i].num); + XFree(modes); + if ( mode == NULL ) { + SDL_SetError("Unable to switch to requested mode"); + return(NULL); + } + DGA_visualClass = mode->mode.visualClass; + memory_base = (Uint8 *)mode->data; + memory_pitch = mode->mode.bytesPerScanline; + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); + current->w = mode->mode.viewportWidth; + current->h = mode->mode.viewportHeight; + current->pitch = memory_pitch; + current->pixels = memory_base; + if ( ! SDL_ReallocFormat(current, mode->mode.bitsPerPixel, + mode->mode.redMask, + mode->mode.greenMask, + mode->mode.blueMask, 0) ) { + return(NULL); + } + screen_len = current->h*current->pitch; + + /* Create a colormap if necessary */ + if ( (DGA_visualClass == PseudoColor) || + (DGA_visualClass == DirectColor) ) { + DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen, + mode, AllocAll); + if ( DGA_visualClass == PseudoColor ) { + current->flags |= SDL_HWPALETTE; + } else { + /* Initialize the colormap to the identity mapping */ + SDL_GetGammaRamp(0, 0, 0); + this->screen = current; + DGA_SetGammaRamp(this, this->gamma); + this->screen = NULL; + } + } else { + DGA_colormap = SDL_NAME(XDGACreateColormap)(DGA_Display, DGA_Screen, + mode, AllocNone); + } + SDL_NAME(XDGAInstallColormap)(DGA_Display, DGA_Screen, DGA_colormap); + + /* Update the hardware capabilities */ + UpdateHWInfo(this, &mode->mode); + + /* Set up the information for hardware surfaces */ + surfaces_mem = (Uint8 *)current->pixels + screen_len; + surfaces_len = (mode->mode.imageHeight*current->pitch - screen_len); + + /* Update for double-buffering, if we can */ + SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen, 0, 0, XDGAFlipRetrace); + if ( flags & SDL_DOUBLEBUF ) { + if ( mode->mode.imageHeight >= (current->h*2) ) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_yoffset[0] = 0; + flip_yoffset[1] = current->h; + flip_address[0] = memory_base; + flip_address[1] = memory_base+screen_len; + surfaces_mem += screen_len; + surfaces_len -= screen_len; + } + } + + /* Allocate memory tracking for hardware surfaces */ + DGA_FreeHWSurfaces(this); + if ( surfaces_len < 0 ) { + surfaces_len = 0; + } + DGA_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); + + /* Expose the back buffer as surface memory */ + if ( current->flags & SDL_DOUBLEBUF ) { + this->screen = current; + DGA_FlipHWSurface(this, current); + this->screen = NULL; + } + + /* Set the update rectangle function */ + this->UpdateRects = DGA_DirectUpdate; + + /* Enable mouse and keyboard support */ + { long input_mask; + input_mask = (KeyPressMask | KeyReleaseMask); + input_mask |= (ButtonPressMask | ButtonReleaseMask); + input_mask |= PointerMotionMask; + SDL_NAME(XDGASelectInput)(DGA_Display, DGA_Screen, input_mask); + } + + /* We're done */ + return(current); +} + +#ifdef DGA_DEBUG +static void DGA_DumpHWSurfaces(_THIS) +{ + vidmem_bucket *bucket; + + printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); + printf("\n"); + printf(" Base Size\n"); + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); + if ( bucket->prev ) { + if ( bucket->base != bucket->prev->base+bucket->prev->size ) { + printf("Warning, corrupt bucket list! (prev)\n"); + } + } else { + if ( bucket != &surfaces ) { + printf("Warning, corrupt bucket list! (!prev)\n"); + } + } + if ( bucket->next ) { + if ( bucket->next->base != bucket->base+bucket->size ) { + printf("Warning, corrupt bucket list! (next)\n"); + } + } + } + printf("\n"); +} +#endif + +static int DGA_InitHWSurfaces(_THIS, SDL_Surface *screen, Uint8 *base, int size) +{ + vidmem_bucket *bucket; + + surfaces_memtotal = size; + surfaces_memleft = size; + + if ( surfaces_memleft > 0 ) { + bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket)); + if ( bucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + bucket->prev = &surfaces; + bucket->used = 0; + bucket->dirty = 0; + bucket->base = base; + bucket->size = size; + bucket->next = NULL; + } else { + bucket = NULL; + } + + surfaces.prev = NULL; + surfaces.used = 1; + surfaces.dirty = 0; + surfaces.base = screen->pixels; + surfaces.size = (unsigned int)((long)base - (long)surfaces.base); + surfaces.next = bucket; + screen->hwdata = (struct private_hwdata *)((char*)&surfaces); + return(0); +} +static void DGA_FreeHWSurfaces(_THIS) +{ + vidmem_bucket *bucket, *freeable; + + bucket = surfaces.next; + while ( bucket ) { + freeable = bucket; + bucket = bucket->next; + SDL_free(freeable); + } + surfaces.next = NULL; +} + +static __inline__ void DGA_AddBusySurface(SDL_Surface *surface) +{ + ((vidmem_bucket *)surface->hwdata)->dirty = 1; +} + +static __inline__ int DGA_IsSurfaceBusy(SDL_Surface *surface) +{ + return ((vidmem_bucket *)surface->hwdata)->dirty; +} + +static __inline__ void DGA_WaitBusySurfaces(_THIS) +{ + vidmem_bucket *bucket; + + /* Wait for graphic operations to complete */ + SDL_NAME(XDGASync)(DGA_Display, DGA_Screen); + + /* Clear all surface dirty bits */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + bucket->dirty = 0; + } +} + +static int DGA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket; + int size; + int extra; + int retval = 0; + +/* Temporarily, we only allow surfaces the same width as display. + Some blitters require the pitch between two hardware surfaces + to be the same. Others have interesting alignment restrictions. +*/ +if ( surface->pitch > SDL_VideoSurface->pitch ) { + SDL_SetError("Surface requested wider than screen"); + return(-1); +} +surface->pitch = SDL_VideoSurface->pitch; + size = surface->h * surface->pitch; +#ifdef DGA_DEBUG + fprintf(stderr, "Allocating bucket of %d bytes\n", size); +#endif + LOCK_DISPLAY(); + + /* Quick check for available mem */ + if ( size > surfaces_memleft ) { + SDL_SetError("Not enough video memory"); + retval = -1; + goto done; + } + + /* Search for an empty bucket big enough */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( ! bucket->used && (size <= bucket->size) ) { + break; + } + } + if ( bucket == NULL ) { + SDL_SetError("Video memory too fragmented"); + retval = -1; + goto done; + } + + /* Create a new bucket for left-over memory */ + extra = (bucket->size - size); + if ( extra ) { + vidmem_bucket *newbucket; + +#ifdef DGA_DEBUG + fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); +#endif + newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket)); + if ( newbucket == NULL ) { + SDL_OutOfMemory(); + retval = -1; + goto done; + } + newbucket->prev = bucket; + newbucket->used = 0; + newbucket->base = bucket->base+size; + newbucket->size = extra; + newbucket->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = newbucket; + } + bucket->next = newbucket; + } + + /* Set the current bucket values and return it! */ + bucket->used = 1; + bucket->size = size; + bucket->dirty = 0; +#ifdef DGA_DEBUG + fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); +#endif + surfaces_memleft -= size; + surface->flags |= SDL_HWSURFACE; + surface->pixels = bucket->base; + surface->hwdata = (struct private_hwdata *)bucket; +done: + UNLOCK_DISPLAY(); + return(retval); +} +static void DGA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket, *freeable; + + /* Wait for any pending operations involving this surface */ + if ( DGA_IsSurfaceBusy(surface) ) { + LOCK_DISPLAY(); + DGA_WaitBusySurfaces(this); + UNLOCK_DISPLAY(); + } + + /* Look for the bucket in the current list */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( bucket == (vidmem_bucket *)surface->hwdata ) { + break; + } + } + if ( bucket && bucket->used ) { + /* Add the memory back to the total */ +#ifdef DGA_DEBUG + printf("Freeing bucket of %d bytes\n", bucket->size); +#endif + surfaces_memleft += bucket->size; + + /* Can we merge the space with surrounding buckets? */ + bucket->used = 0; + if ( bucket->next && ! bucket->next->used ) { +#ifdef DGA_DEBUG + printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); +#endif + freeable = bucket->next; + bucket->size += bucket->next->size; + bucket->next = bucket->next->next; + if ( bucket->next ) { + bucket->next->prev = bucket; + } + SDL_free(freeable); + } + if ( bucket->prev && ! bucket->prev->used ) { +#ifdef DGA_DEBUG + printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); +#endif + freeable = bucket; + bucket->prev->size += bucket->size; + bucket->prev->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = bucket->prev; + } + SDL_free(freeable); + } + } + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static __inline__ void DGA_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y) +{ + *x = (long)((Uint8 *)dst->pixels - memory_base)%memory_pitch; + *y = (long)((Uint8 *)dst->pixels - memory_base)/memory_pitch; +} + +static int DGA_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int x, y; + unsigned int w, h; + + /* Don't fill the visible part of the screen, wait until flipped */ + LOCK_DISPLAY(); + if ( was_flipped && (dst == this->screen) ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } + DGA_dst_to_xy(this, dst, &x, &y); + x += rect->x; + y += rect->y; + w = rect->w; + h = rect->h; +#if 0 + printf("Hardware accelerated rectangle fill: %dx%d at %d,%d\n", w, h, x, y); +#endif + SDL_NAME(XDGAFillRectangle)(DGA_Display, DGA_Screen, x, y, w, h, color); + if ( !(this->screen->flags & SDL_DOUBLEBUF) ) { + XFlush(DGA_Display); + } + DGA_AddBusySurface(dst); + UNLOCK_DISPLAY(); + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this; + int srcx, srcy; + int dstx, dsty; + unsigned int w, h; + + this = current_video; + /* Don't blit to the visible part of the screen, wait until flipped */ + LOCK_DISPLAY(); + if ( was_flipped && (dst == this->screen) ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } + DGA_dst_to_xy(this, src, &srcx, &srcy); + srcx += srcrect->x; + srcy += srcrect->y; + DGA_dst_to_xy(this, dst, &dstx, &dsty); + dstx += dstrect->x; + dsty += dstrect->y; + w = srcrect->w; + h = srcrect->h; +#if 0 + printf("Blitting %dx%d from %d,%d to %d,%d\n", w, h, srcx, srcy, dstx, dsty); +#endif + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + SDL_NAME(XDGACopyTransparentArea)(DGA_Display, DGA_Screen, + srcx, srcy, w, h, dstx, dsty, src->format->colorkey); + } else { + SDL_NAME(XDGACopyArea)(DGA_Display, DGA_Screen, + srcx, srcy, w, h, dstx, dsty); + } + if ( !(this->screen->flags & SDL_DOUBLEBUF) ) { + XFlush(DGA_Display); + } + DGA_AddBusySurface(src); + DGA_AddBusySurface(dst); + UNLOCK_DISPLAY(); + return(0); +} + +static int DGA_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +static __inline__ void DGA_WaitFlip(_THIS) +{ + if ( was_flipped ) { + while ( SDL_NAME(XDGAGetViewportStatus)(DGA_Display, DGA_Screen) ) + /* Keep waiting for the hardware ... */ ; + was_flipped = 0; + } +} + +static int DGA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexP(hw_lock); + LOCK_DISPLAY(); + if ( DGA_IsSurfaceBusy(surface) ) { + DGA_WaitBusySurfaces(this); + } + DGA_WaitFlip(this); + UNLOCK_DISPLAY(); + } else { + if ( DGA_IsSurfaceBusy(surface) ) { + LOCK_DISPLAY(); + DGA_WaitBusySurfaces(this); + UNLOCK_DISPLAY(); + } + } + return(0); +} +static void DGA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexV(hw_lock); + } +} + +static int DGA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + /* Wait for vertical retrace and then flip display */ + LOCK_DISPLAY(); + if ( DGA_IsSurfaceBusy(this->screen) ) { + DGA_WaitBusySurfaces(this); + } + DGA_WaitFlip(this); + SDL_NAME(XDGASetViewport)(DGA_Display, DGA_Screen, + 0, flip_yoffset[flip_page], XDGAFlipRetrace); + XFlush(DGA_Display); + UNLOCK_DISPLAY(); + was_flipped = 1; + flip_page = !flip_page; + + surface->pixels = flip_address[flip_page]; + return(0); +} + +static void DGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* The application is already updating the visible video memory */ + return; +} + +static int DGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + XColor *xcmap; + + /* This happens on initialization */ + if ( ! DGA_colormap ) { + return(0); + } + xcmap = SDL_stack_alloc(XColor, ncolors); + for ( i=0; i<ncolors; ++i ) { + xcmap[i].pixel = firstcolor + i; + xcmap[i].red = (colors[i].r<<8)|colors[i].r; + xcmap[i].green = (colors[i].g<<8)|colors[i].g; + xcmap[i].blue = (colors[i].b<<8)|colors[i].b; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + LOCK_DISPLAY(); + XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors); + XSync(DGA_Display, False); + UNLOCK_DISPLAY(); + SDL_stack_free(xcmap); + + /* That was easy. :) */ + return(1); +} + +int DGA_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i, ncolors; + XColor xcmap[256]; + + /* See if actually setting the gamma is supported */ + if ( DGA_visualClass != DirectColor ) { + SDL_SetError("Gamma correction not supported on this visual"); + return(-1); + } + + /* Calculate the appropriate palette for the given gamma ramp */ + if ( this->screen->format->BitsPerPixel <= 16 ) { + ncolors = 64; /* Is this right? */ + } else { + ncolors = 256; + } + for ( i=0; i<ncolors; ++i ) { + Uint8 c = (256 * i / ncolors); + xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); + xcmap[i].red = ramp[0*256+c]; + xcmap[i].green = ramp[1*256+c]; + xcmap[i].blue = ramp[2*256+c]; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + LOCK_DISPLAY(); + XStoreColors(DGA_Display, DGA_colormap, xcmap, ncolors); + XSync(DGA_Display, False); + UNLOCK_DISPLAY(); + return(0); +} + +void DGA_VideoQuit(_THIS) +{ + int i, j; + + if ( DGA_Display ) { + /* Free colormap, if necessary */ + if ( DGA_colormap ) { + XFreeColormap(DGA_Display, DGA_colormap); + DGA_colormap = 0; + } + + /* Unmap memory and reset video mode */ + SDL_NAME(XDGACloseFramebuffer)(DGA_Display, DGA_Screen); + if ( this->screen ) { + /* Tell SDL not to free the pixels */ + DGA_FreeHWSurface(this, this->screen); + } + SDL_NAME(XDGASetMode)(DGA_Display, DGA_Screen, 0); + + /* Clear the lock mutex */ + if ( hw_lock != NULL ) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } +#ifdef LOCK_DGA_DISPLAY + if ( event_lock != NULL ) { + SDL_DestroyMutex(event_lock); + event_lock = NULL; + } +#endif /* LOCK_DGA_DISPLAY */ + + /* Clean up defined video modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Clean up the memory bucket list */ + DGA_FreeHWSurfaces(this); + + /* Close up the display */ + XCloseDisplay(DGA_Display); + } +} diff --git a/3rdparty/SDL/src/video/dga/SDL_dgavideo.h b/3rdparty/SDL/src/video/dga/SDL_dgavideo.h new file mode 100644 index 0000000..bd2ecb8 --- /dev/null +++ b/3rdparty/SDL/src/video/dga/SDL_dgavideo.h @@ -0,0 +1,124 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dgavideo_h +#define _SDL_dgavideo_h + +#include <X11/Xlib.h> + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xproto.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Define this if you need the DGA driver to be thread-safe */ +#define LOCK_DGA_DISPLAY +#ifdef LOCK_DGA_DISPLAY +#define LOCK_DISPLAY() SDL_mutexP(event_lock) +#define UNLOCK_DISPLAY() SDL_mutexV(event_lock) +#else +#define LOCK_DISPLAY() +#define UNLOCK_DISPLAY() +#endif + + +/* This is the structure we use to keep track of video memory */ +typedef struct vidmem_bucket { + struct vidmem_bucket *prev; + int used; + int dirty; + Uint8 *base; + unsigned int size; + struct vidmem_bucket *next; +} vidmem_bucket; + +/* Private display data */ +struct SDL_PrivateVideoData { + Display *DGA_Display; + Colormap DGA_colormap; + int visualClass; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* Information for the video surface */ + Uint8 *memory_base; + int memory_pitch; + SDL_mutex *hw_lock; + int sync_needed; + int was_flipped; + + /* Information for hardware surfaces */ + vidmem_bucket surfaces; + int surfaces_memtotal; + int surfaces_memleft; + + /* Information for double-buffering */ + int flip_page; + int flip_yoffset[2]; + Uint8 *flip_address[2]; + + /* Used to handle DGA events */ + int event_base; +#ifdef LOCK_DGA_DISPLAY + SDL_mutex *event_lock; +#endif + + /* Screensaver settings */ + int allow_screensaver; +}; + +/* Old variable names */ +#define DGA_Display (this->hidden->DGA_Display) +#define DGA_Screen DefaultScreen(DGA_Display) +#define DGA_colormap (this->hidden->DGA_colormap) +#define DGA_visualClass (this->hidden->visualClass) +#define memory_base (this->hidden->memory_base) +#define memory_pitch (this->hidden->memory_pitch) +#define flip_page (this->hidden->flip_page) +#define flip_yoffset (this->hidden->flip_yoffset) +#define flip_address (this->hidden->flip_address) +#define sync_needed (this->hidden->sync_needed) +#define was_flipped (this->hidden->was_flipped) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define surfaces (this->hidden->surfaces) +#define surfaces_memtotal (this->hidden->surfaces_memtotal) +#define surfaces_memleft (this->hidden->surfaces_memleft) +#define hw_lock (this->hidden->hw_lock) +#define DGA_event_base (this->hidden->event_base) +#define event_lock (this->hidden->event_lock) +#define allow_screensaver (this->hidden->allow_screensaver) + +#endif /* _SDL_dgavideo_h */ diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c new file mode 100644 index 0000000..246b75b --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.c @@ -0,0 +1,219 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting DirectFB input events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#include <directfb.h> + +#include "SDL.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_events.h" + +/* The translation tables from a DirectFB keycode to a SDL keysym */ +static SDLKey keymap[256]; +static SDL_keysym *DirectFB_TranslateKey (DFBInputEvent *ev, SDL_keysym *keysym); +static int DirectFB_TranslateButton (DFBInputEvent *ev); + +static int posted = 0; + + +void DirectFB_PumpEvents (_THIS) +{ + DFBInputEvent evt; + + while (HIDDEN->eventbuffer->GetEvent (HIDDEN->eventbuffer, + DFB_EVENT (&evt)) == DFB_OK) + { + SDL_keysym keysym; + + switch (evt.type) + { + case DIET_BUTTONPRESS: + posted += SDL_PrivateMouseButton(SDL_PRESSED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_BUTTONRELEASE: + posted += SDL_PrivateMouseButton(SDL_RELEASED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_KEYPRESS: + posted += SDL_PrivateKeyboard(SDL_PRESSED, DirectFB_TranslateKey(&evt, &keysym)); + break; + case DIET_KEYRELEASE: + posted += SDL_PrivateKeyboard(SDL_RELEASED, DirectFB_TranslateKey(&evt, &keysym)); + break; + case DIET_AXISMOTION: + if (evt.flags & DIEF_AXISREL) + { + if (evt.axis == DIAI_X) + posted += SDL_PrivateMouseMotion(0, 1, evt.axisrel, 0); + else if (evt.axis == DIAI_Y) + posted += SDL_PrivateMouseMotion(0, 1, 0, evt.axisrel); + } + else if (evt.flags & DIEF_AXISABS) + { + static int last_x, last_y; + if (evt.axis == DIAI_X) + last_x = evt.axisabs; + else if (evt.axis == DIAI_Y) + last_y = evt.axisabs; + posted += SDL_PrivateMouseMotion(0, 0, last_x, last_y); + } + break; + default: + ; + } + } +} + +void DirectFB_InitOSKeymap (_THIS) +{ + int i; + + /* Initialize the DirectFB key translation table */ + for (i=0; i<SDL_arraysize(keymap); ++i) + keymap[i] = SDLK_UNKNOWN; + + keymap[DIKI_A - DIKI_UNKNOWN] = SDLK_a; + keymap[DIKI_B - DIKI_UNKNOWN] = SDLK_b; + keymap[DIKI_C - DIKI_UNKNOWN] = SDLK_c; + keymap[DIKI_D - DIKI_UNKNOWN] = SDLK_d; + keymap[DIKI_E - DIKI_UNKNOWN] = SDLK_e; + keymap[DIKI_F - DIKI_UNKNOWN] = SDLK_f; + keymap[DIKI_G - DIKI_UNKNOWN] = SDLK_g; + keymap[DIKI_H - DIKI_UNKNOWN] = SDLK_h; + keymap[DIKI_I - DIKI_UNKNOWN] = SDLK_i; + keymap[DIKI_J - DIKI_UNKNOWN] = SDLK_j; + keymap[DIKI_K - DIKI_UNKNOWN] = SDLK_k; + keymap[DIKI_L - DIKI_UNKNOWN] = SDLK_l; + keymap[DIKI_M - DIKI_UNKNOWN] = SDLK_m; + keymap[DIKI_N - DIKI_UNKNOWN] = SDLK_n; + keymap[DIKI_O - DIKI_UNKNOWN] = SDLK_o; + keymap[DIKI_P - DIKI_UNKNOWN] = SDLK_p; + keymap[DIKI_Q - DIKI_UNKNOWN] = SDLK_q; + keymap[DIKI_R - DIKI_UNKNOWN] = SDLK_r; + keymap[DIKI_S - DIKI_UNKNOWN] = SDLK_s; + keymap[DIKI_T - DIKI_UNKNOWN] = SDLK_t; + keymap[DIKI_U - DIKI_UNKNOWN] = SDLK_u; + keymap[DIKI_V - DIKI_UNKNOWN] = SDLK_v; + keymap[DIKI_W - DIKI_UNKNOWN] = SDLK_w; + keymap[DIKI_X - DIKI_UNKNOWN] = SDLK_x; + keymap[DIKI_Y - DIKI_UNKNOWN] = SDLK_y; + keymap[DIKI_Z - DIKI_UNKNOWN] = SDLK_z; + + keymap[DIKI_0 - DIKI_UNKNOWN] = SDLK_0; + keymap[DIKI_1 - DIKI_UNKNOWN] = SDLK_1; + keymap[DIKI_2 - DIKI_UNKNOWN] = SDLK_2; + keymap[DIKI_3 - DIKI_UNKNOWN] = SDLK_3; + keymap[DIKI_4 - DIKI_UNKNOWN] = SDLK_4; + keymap[DIKI_5 - DIKI_UNKNOWN] = SDLK_5; + keymap[DIKI_6 - DIKI_UNKNOWN] = SDLK_6; + keymap[DIKI_7 - DIKI_UNKNOWN] = SDLK_7; + keymap[DIKI_8 - DIKI_UNKNOWN] = SDLK_8; + keymap[DIKI_9 - DIKI_UNKNOWN] = SDLK_9; + + keymap[DIKI_F1 - DIKI_UNKNOWN] = SDLK_F1; + keymap[DIKI_F2 - DIKI_UNKNOWN] = SDLK_F2; + keymap[DIKI_F3 - DIKI_UNKNOWN] = SDLK_F3; + keymap[DIKI_F4 - DIKI_UNKNOWN] = SDLK_F4; + keymap[DIKI_F5 - DIKI_UNKNOWN] = SDLK_F5; + keymap[DIKI_F6 - DIKI_UNKNOWN] = SDLK_F6; + keymap[DIKI_F7 - DIKI_UNKNOWN] = SDLK_F7; + keymap[DIKI_F8 - DIKI_UNKNOWN] = SDLK_F8; + keymap[DIKI_F9 - DIKI_UNKNOWN] = SDLK_F9; + keymap[DIKI_F10 - DIKI_UNKNOWN] = SDLK_F10; + keymap[DIKI_F11 - DIKI_UNKNOWN] = SDLK_F11; + keymap[DIKI_F12 - DIKI_UNKNOWN] = SDLK_F12; + + keymap[DIKI_ESCAPE - DIKI_UNKNOWN] = SDLK_ESCAPE; + keymap[DIKI_LEFT - DIKI_UNKNOWN] = SDLK_LEFT; + keymap[DIKI_RIGHT - DIKI_UNKNOWN] = SDLK_RIGHT; + keymap[DIKI_UP - DIKI_UNKNOWN] = SDLK_UP; + keymap[DIKI_DOWN - DIKI_UNKNOWN] = SDLK_DOWN; + keymap[DIKI_CONTROL_L - DIKI_UNKNOWN] = SDLK_LCTRL; + keymap[DIKI_CONTROL_R - DIKI_UNKNOWN] = SDLK_RCTRL; + keymap[DIKI_SHIFT_L - DIKI_UNKNOWN] = SDLK_LSHIFT; + keymap[DIKI_SHIFT_R - DIKI_UNKNOWN] = SDLK_RSHIFT; + keymap[DIKI_ALT_L - DIKI_UNKNOWN] = SDLK_LALT; + keymap[DIKI_ALT_R - DIKI_UNKNOWN] = SDLK_RALT; + keymap[DIKI_TAB - DIKI_UNKNOWN] = SDLK_TAB; + keymap[DIKI_ENTER - DIKI_UNKNOWN] = SDLK_RETURN; + keymap[DIKI_SPACE - DIKI_UNKNOWN] = SDLK_SPACE; + keymap[DIKI_BACKSPACE - DIKI_UNKNOWN] = SDLK_BACKSPACE; + keymap[DIKI_INSERT - DIKI_UNKNOWN] = SDLK_INSERT; + keymap[DIKI_DELETE - DIKI_UNKNOWN] = SDLK_DELETE; + keymap[DIKI_HOME - DIKI_UNKNOWN] = SDLK_HOME; + keymap[DIKI_END - DIKI_UNKNOWN] = SDLK_END; + keymap[DIKI_PAGE_UP - DIKI_UNKNOWN] = SDLK_PAGEUP; + keymap[DIKI_PAGE_DOWN - DIKI_UNKNOWN] = SDLK_PAGEDOWN; + keymap[DIKI_CAPS_LOCK - DIKI_UNKNOWN] = SDLK_CAPSLOCK; + keymap[DIKI_NUM_LOCK - DIKI_UNKNOWN] = SDLK_NUMLOCK; + keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = SDLK_SCROLLOCK; + keymap[DIKI_PRINT - DIKI_UNKNOWN] = SDLK_PRINT; + keymap[DIKI_PAUSE - DIKI_UNKNOWN] = SDLK_PAUSE; + keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = SDLK_KP_DIVIDE; + keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = SDLK_KP_MULTIPLY; + keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = SDLK_KP_MINUS; + keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = SDLK_KP_PLUS; + keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = SDLK_KP_ENTER; +} + + +static SDL_keysym *DirectFB_TranslateKey (DFBInputEvent *ev, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = ev->key_id; + keysym->mod = KMOD_NONE; /* FIXME */ + keysym->unicode = (DFB_KEY_TYPE (ev->key_symbol) == DIKT_UNICODE) ? ev->key_symbol : 0; + + if (ev->key_symbol > 0 && ev->key_symbol < 128) + keysym->sym = ev->key_symbol; + else + keysym->sym = keymap[ev->key_id - DIKI_UNKNOWN]; + + return keysym; +} + +static int DirectFB_TranslateButton (DFBInputEvent *ev) +{ + switch (ev->button) + { + case DIBI_LEFT: + return 1; + case DIBI_MIDDLE: + return 2; + case DIBI_RIGHT: + return 3; + default: + return 0; + } +} diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h new file mode 100644 index 0000000..20f3967 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_events.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_DirectFB_video.h" + +/* Functions to be exported */ +extern void DirectFB_InitOSKeymap(_THIS); +extern void DirectFB_PumpEvents(_THIS); + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h new file mode 100644 index 0000000..2868ee6 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_keys.h @@ -0,0 +1,135 @@ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 90 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 92 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 94 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c new file mode 100644 index 0000000..f665ec6 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.c @@ -0,0 +1,1171 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com + CRTC2 support is inspired by mplayer's dfbmga driver + written by Ville Syrj��<syrjala@sci.fi> +*/ +#include "SDL_config.h" + +/* DirectFB video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <directfb.h> +#include <directfb_version.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_events.h" +#include "SDL_DirectFB_yuv.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + + +/* Initialization/Query functions */ +static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void DirectFB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); +static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface); +static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); +static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface); +static int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor); + +/* Various screen update functions available */ +static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects); + +/* This is the rect EnumModes2 uses */ +struct DirectFBEnumRect { + SDL_Rect r; + struct DirectFBEnumRect* next; +}; + +static struct DirectFBEnumRect *enumlist = NULL; + + +/* DirectFB driver bootstrap functions */ + +static int DirectFB_Available(void) +{ + return 1; +} + +static void DirectFB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DirectFB_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset (device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden)); + } + if (device == NULL || device->hidden == NULL) + { + SDL_OutOfMemory(); + if (device) + { + free (device); + } + return(0); + } + SDL_memset (device->hidden, 0, sizeof (*device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DirectFB_VideoInit; + device->ListModes = DirectFB_ListModes; + device->SetVideoMode = DirectFB_SetVideoMode; + device->SetColors = DirectFB_SetColors; + device->UpdateRects = NULL; + device->CreateYUVOverlay = DirectFB_CreateYUVOverlay; + device->VideoQuit = DirectFB_VideoQuit; + device->AllocHWSurface = DirectFB_AllocHWSurface; + device->CheckHWBlit = DirectFB_CheckHWBlit; + device->FillHWRect = DirectFB_FillHWRect; + device->SetHWColorKey = DirectFB_SetHWColorKey; + device->SetHWAlpha = DirectFB_SetHWAlpha; + device->LockHWSurface = DirectFB_LockHWSurface; + device->UnlockHWSurface = DirectFB_UnlockHWSurface; + device->FlipHWSurface = DirectFB_FlipHWSurface; + device->FreeHWSurface = DirectFB_FreeHWSurface; + device->ShowWMCursor = DirectFB_ShowWMCursor; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DirectFB_InitOSKeymap; + device->PumpEvents = DirectFB_PumpEvents; + + device->free = DirectFB_DeleteDevice; + + return device; +} + +VideoBootStrap DirectFB_bootstrap = { + "directfb", "DirectFB", + DirectFB_Available, DirectFB_CreateDevice +}; + +static DFBSurfacePixelFormat GetFormatForBpp (int bpp, IDirectFBDisplayLayer *layer) +{ + DFBDisplayLayerConfig dlc; + int bytes = (bpp + 7) / 8; + + layer->GetConfiguration (layer, &dlc); + + if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1) + return dlc.pixelformat; + + switch (bytes) + { + case 1: + return DSPF_LUT8; + case 2: + return DSPF_RGB16; + case 3: + return DSPF_RGB24; + case 4: + return DSPF_RGB32; + } + + return DSPF_UNKNOWN; +} + +static DFBEnumerationResult EnumModesCallback (int width, + int height, + int bpp, + void *data) +{ + SDL_VideoDevice *this = (SDL_VideoDevice *)data; + struct DirectFBEnumRect *enumrect; + + HIDDEN->nummodes++; + + if (enumlist && enumlist->r.w == width && enumlist->r.h == height) + return DFENUM_OK; + + enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect)); + if (!enumrect) + { + SDL_OutOfMemory(); + return DFENUM_CANCEL; + } + + enumrect->r.w = (Uint16)width; + enumrect->r.h = (Uint16)height; + enumrect->next = enumlist; + + enumlist = enumrect; + + return DFENUM_OK; +} + +struct private_hwdata { + IDirectFBSurface *surface; + IDirectFBPalette *palette; +}; + +void SetDirectFBerror (const char *function, DFBResult code) +{ + const char *error = DirectFBErrorString (code); + + if (error) + SDL_SetError("%s: %s", function, error); + else + SDL_SetError("Unknown error code from %s", function); +} + +static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format) +{ + if (format->Rmask && format->Gmask && format->Bmask) + { + switch (format->BitsPerPixel) + { + case 8: + return DSPF_LUT8; + + case 16: + if (format->Rmask == 0xF800 && + format->Gmask == 0x07E0 && + format->Bmask == 0x001F) + return DSPF_RGB16; + /* fall through */ + + case 15: + if (format->Rmask == 0x7C00 && + format->Gmask == 0x03E0 && + format->Bmask == 0x001F) + return DSPF_ARGB1555; + break; + + case 24: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + return DSPF_RGB24; + break; + + case 32: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + { + if (format->Amask == 0xFF000000) + return DSPF_ARGB; + else + return DSPF_RGB32; + } + break; + } + } + else + { + switch (format->BitsPerPixel) + { + case 8: + return DSPF_LUT8; + case 15: + return DSPF_ARGB1555; + case 16: + return DSPF_RGB16; + case 24: + return DSPF_RGB24; + case 32: + return DSPF_RGB32; + } + } + + return DSPF_UNKNOWN; +} + +static SDL_Palette *AllocatePalette(int size) +{ + SDL_Palette *palette; + SDL_Color *colors; + + palette = SDL_calloc (1, sizeof(SDL_Palette)); + if (!palette) + { + SDL_OutOfMemory(); + return NULL; + } + + colors = SDL_calloc (size, sizeof(SDL_Color)); + if (!colors) + { + SDL_OutOfMemory(); + return NULL; + } + + palette->ncolors = size; + palette->colors = colors; + + return palette; +} + +static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format) +{ + format->Amask = format->Rmask = format->Gmask = format->Bmask = 0; + format->BitsPerPixel = format->BytesPerPixel = 0; + + switch (pixelformat) + { + case DSPF_A8: + format->Amask = 0x000000FF; + break; + + case DSPF_ARGB1555: + format->Rmask = 0x00007C00; + format->Gmask = 0x000003E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_RGB16: + format->Rmask = 0x0000F800; + format->Gmask = 0x000007E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_ARGB: + format->Amask = 0; /* apps don't seem to like that: 0xFF000000; */ + /* fall through */ + case DSPF_RGB24: + case DSPF_RGB32: + format->Rmask = 0x00FF0000; + format->Gmask = 0x0000FF00; + format->Bmask = 0x000000FF; + break; + + case DSPF_LUT8: + format->Rmask = 0x000000FF; + format->Gmask = 0x000000FF; + format->Bmask = 0x000000FF; + + if (!format->palette) + format->palette = AllocatePalette(256); + break; + + default: + fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat); + return -1; + } + + format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8; + format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat); + + return 0; +} + + +int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + DFBResult ret; +#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) + DFBCardCapabilities caps; +#else + DFBGraphicsDeviceDescription caps; +#endif + DFBDisplayLayerConfig dlc; + struct DirectFBEnumRect *rect; + IDirectFB *dfb = NULL; + IDirectFBDisplayLayer *layer = NULL; + IDirectFBEventBuffer *events = NULL; + + HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL; + HIDDEN->enable_mga_crtc2 = 0; + HIDDEN->mga_crtc2_stretch_overscan = 1; + + ret = DirectFBInit (NULL, NULL); + if (ret) + { + SetDirectFBerror ("DirectFBInit", ret); + goto error; + } + + ret = DirectFBCreate (&dfb); + if (ret) + { + SetDirectFBerror ("DirectFBCreate", ret); + goto error; + } + + ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer", ret); + goto error; + } + + ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events); + if (ret) + { + SetDirectFBerror ("dfb->CreateEventBuffer", ret); + goto error; + } + + layer->EnableCursor (layer, 1); + + /* Query layer configuration to determine the current mode and pixelformat */ + layer->GetConfiguration (layer, &dlc); + + /* If current format is not supported use LUT8 as the default */ + if (DFBToSDLPixelFormat (dlc.pixelformat, vformat)) + DFBToSDLPixelFormat (DSPF_LUT8, vformat); + + /* Enumerate the available fullscreen modes */ + ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this); + if (ret) + { + SetDirectFBerror ("dfb->EnumVideoModes", ret); + goto error; + } + + HIDDEN->modelist = SDL_calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *)); + if (!HIDDEN->modelist) + { + SDL_OutOfMemory(); + goto error; + } + + for (i = 0, rect = enumlist; rect; ++i, rect = rect->next ) + { + HIDDEN->modelist[i] = &rect->r; + } + + HIDDEN->modelist[i] = NULL; + + + /* Query card capabilities to get the video memory size */ +#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) + dfb->GetCardCapabilities (dfb, &caps); +#else + dfb->GetDeviceDescription (dfb, &caps); +#endif + + this->info.wm_available = 1; + this->info.hw_available = 1; + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + this->info.blit_hw_A = 1; + this->info.blit_fill = 1; + this->info.video_mem = caps.video_memory / 1024; + this->info.current_w = dlc.width; + this->info.current_h = dlc.height; + + HIDDEN->initialized = 1; + HIDDEN->dfb = dfb; + HIDDEN->layer = layer; + HIDDEN->eventbuffer = events; + + if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL) + HIDDEN->enable_mga_crtc2 = 1; + + if (HIDDEN->enable_mga_crtc2) + { + DFBDisplayLayerConfig dlc; + DFBDisplayLayerConfigFlags failed; + + ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret); + goto error; + } + + ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE); + if (ret) + { + SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); + goto error; + } + + ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE); + if (ret) + { + SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); + goto error; + } + + HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0); + + /* Init the surface here as it got a fixed size */ + dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + dlc.buffermode = DLBM_BACKVIDEO; + dlc.pixelformat = DSPF_RGB32; + + ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed ); + if (ret) + { + SetDirectFBerror ("c2layer->TestConfiguration", ret); + goto error; + } + + ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc ); + if (ret) + { + SetDirectFBerror ("c2layer->SetConfiguration", ret); + goto error; + } + + ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame ); + if (ret) + { + SetDirectFBerror ("c2layer->GetSurface", ret); + goto error; + } + + HIDDEN->c2framesize.x = 0; + HIDDEN->c2framesize.y = 0; + HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h); + + HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX ); + HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff ); + + /* Clear CRTC2 */ + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); + HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); + + HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF ); + + /* Check if overscan is possibly set */ + if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL) + { + float overscan = 0; + if (SDL_sscanf(SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1) + if (overscan > 0 && overscan < 2) + HIDDEN->mga_crtc2_stretch_overscan = overscan; + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan); + #endif + } + + return 0; + + error: + if (events) + events->Release (events); + + if (HIDDEN->c2frame) + HIDDEN->c2frame->Release (HIDDEN->c2frame); + + if (HIDDEN->c2layer) + HIDDEN->c2layer->Release (HIDDEN->c2layer); + + if (layer) + layer->Release (layer); + + if (dfb) + dfb->Release (dfb); + + return -1; +} + +static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + return HIDDEN->modelist; + else + if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN) + return (SDL_Rect**) -1; + + return NULL; +} + +static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + DFBSurfacePixelFormat pixelformat; + IDirectFBSurface *surface; + + fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n", + width, height, bpp, flags); + + flags |= SDL_FULLSCREEN; + + /* Release previous primary surface */ + if (current->hwdata && current->hwdata->surface) + { + current->hwdata->surface->Release (current->hwdata->surface); + current->hwdata->surface = NULL; + + /* And its palette if present */ + if (current->hwdata->palette) + { + current->hwdata->palette->Release (current->hwdata->palette); + current->hwdata->palette = NULL; + } + } + else if (!current->hwdata) + { + /* Allocate the hardware acceleration data */ + current->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*current->hwdata)); + if (!current->hwdata) + { + SDL_OutOfMemory(); + return NULL; + } + } + + /* Set cooperative level depending on flag SDL_FULLSCREEN */ + if (flags & SDL_FULLSCREEN) + { + ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN); + if (ret && !HIDDEN->enable_mga_crtc2) + { + DirectFBError ("dfb->SetCooperativeLevel", ret); + flags &= ~SDL_FULLSCREEN; + } + } + else + HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); + + /* Set video mode */ + ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); + if (ret) + { + if (flags & SDL_FULLSCREEN) + { + flags &= ~SDL_FULLSCREEN; + HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); + ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); + } + + if (ret) + { + SetDirectFBerror ("dfb->SetVideoMode", ret); + return NULL; + } + } + + /* Create primary surface */ + dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0); + dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer); + + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); + if (ret && (flags & SDL_DOUBLEBUF)) + { + /* Try without double buffering */ + dsc.caps &= ~DSCAPS_FLIPPING; + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); + } + if (ret) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + return NULL; + } + + current->w = width; + current->h = height; + current->flags = SDL_HWSURFACE | SDL_PREALLOC; + + if (flags & SDL_FULLSCREEN) + { + current->flags |= SDL_FULLSCREEN; + this->UpdateRects = DirectFB_DirectUpdate; + } + else + this->UpdateRects = DirectFB_WindowedUpdate; + + if (dsc.caps & DSCAPS_FLIPPING) + current->flags |= SDL_DOUBLEBUF; + + surface->GetPixelFormat (surface, &pixelformat); + + DFBToSDLPixelFormat (pixelformat, current->format); + + /* Get the surface palette (if supported) */ + if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat )) + { + surface->GetPalette (surface, ¤t->hwdata->palette); + + current->flags |= SDL_HWPALETTE; + } + + current->hwdata->surface = surface; + + /* MGA CRTC2 stuff */ + if (HIDDEN->enable_mga_crtc2) + { + /* no stretching if c2ssize == c2framesize */ + HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0; + HIDDEN->c2ssize.w = width; + HIDDEN->c2ssize.h = height; + + HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0; + HIDDEN->c2dsize.w = width; + HIDDEN->c2dsize.h = height; + + HIDDEN->mga_crtc2_stretch = 0; + + if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL) + { + /* Normally assume a picture aspect ratio of 4:3 */ + int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j; + + for (i = 1; i < 20; i++) + { + for (j = 1; j < 10; j++) + { + if ((float)width/(float)i*(float)j == height) + { + zoom_aspect_x = i; + zoom_aspect_y = j; + + /* break the loop */ + i = 21; + break; + } + } + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y); + printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h); + #endif + + /* don't stretch only slightly smaller/larger images */ + if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w < (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && (float)HIDDEN->c2dsize.h < (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) + { + HIDDEN->c2dsize.w+=zoom_aspect_x; + HIDDEN->c2dsize.h+=zoom_aspect_y; + } + + /* one step down */ + HIDDEN->c2dsize.w-=zoom_aspect_x; + HIDDEN->c2dsize.h-=zoom_aspect_y; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); + #endif + + HIDDEN->mga_crtc2_stretch = 1; + } + else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w > (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || (float)HIDDEN->c2dsize.h > (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) + { + HIDDEN->c2dsize.w-=zoom_aspect_x; + HIDDEN->c2dsize.h-=zoom_aspect_y; + } + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); + #endif + + HIDDEN->mga_crtc2_stretch = 1; + } else { + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Not stretching image\n"); + #endif + } + + /* Panning */ + if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w) + HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2; + else + HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2; + + if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h) + HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2; + else + HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + #endif + } + } + + return current; +} + +static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + + /* fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n", + surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/ + + if (surface->w < 8 || surface->h < 8) + return -1; + + /* fill surface description */ + dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; + dsc.width = surface->w; + dsc.height = surface->h; + dsc.caps = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0; + + /* find the right pixelformat */ + dsc.pixelformat = SDLToDFBPixelFormat (surface->format); + if (dsc.pixelformat == DSPF_UNKNOWN) + return -1; + + /* Allocate the hardware acceleration data */ + surface->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*surface->hwdata)); + if (surface->hwdata == NULL) + { + SDL_OutOfMemory(); + return -1; + } + + /* Create the surface */ + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface); + if (ret) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + free (surface->hwdata); + surface->hwdata = NULL; + return -1; + } + + surface->flags |= SDL_HWSURFACE | SDL_PREALLOC; + + return 0; +} + +static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->hwdata && HIDDEN->initialized) + { + surface->hwdata->surface->Release (surface->hwdata->surface); + free (surface->hwdata); + surface->hwdata = NULL; + } +} + +static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + /* fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n", + src->hwdata, dst->hwdata);*/ + + if (!src->hwdata || !dst->hwdata) + return 0; + + src->flags |= SDL_HWACCEL; + src->map->hw_blit = DirectFB_HWAccelBlit; + + return 1; +} + +static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; + + DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h }; + DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h }; + + IDirectFBSurface *surface = dst->hwdata->surface; + + if (src->flags & SDL_SRCCOLORKEY) + { + flags |= DSBLIT_SRC_COLORKEY; + DirectFB_SetHWColorKey (NULL, src, src->format->colorkey); + } + + if (src->flags & SDL_SRCALPHA) + { + flags |= DSBLIT_BLEND_COLORALPHA; + surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha); + } + + surface->SetBlittingFlags (surface, flags); + + if (sr.w == dr.w && sr.h == dr.h) + surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y); + else + surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr); + + return 0; +} + +static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_PixelFormat *fmt = dst->format; + IDirectFBSurface *surface = dst->hwdata->surface; + + /* ugly */ + surface->SetColor (surface, + (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), + (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), + (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF); + surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h); + + return 0; +} + +static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key) +{ + SDL_PixelFormat *fmt = src->format; + IDirectFBSurface *surface = src->hwdata->surface; + + if (fmt->BitsPerPixel == 8) + surface->SetSrcColorKeyIndex (surface, key); + else + /* ugly */ + surface->SetSrcColorKey (surface, + (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), + (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), + (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift)); + + return 0; +} + +static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + return 0; +} + +static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (HIDDEN->enable_mga_crtc2) + { + int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0); + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + return rtn; + } + else + return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC); +} + +static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + void *data; + int pitch; + + ret = surface->hwdata->surface->Lock (surface->hwdata->surface, + DSLF_WRITE, &data, &pitch); + if (ret) + { + SetDirectFBerror ("surface->Lock", ret); + return -1; + } + + surface->pixels = data; + surface->pitch = pitch; + + return 0; +} + +static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + surface->hwdata->surface->Unlock (surface->hwdata->surface); + surface->pixels = NULL; +} + +static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + } +} + +static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + DFBRegion region; + int i; + int region_valid = 0; + IDirectFBSurface *surface = this->screen->hwdata->surface; + + for (i=0; i<numrects; ++i) + { + int x2, y2; + + if ( ! rects[i].w ) /* Clipped? */ + continue; + + x2 = rects[i].x + rects[i].w - 1; + y2 = rects[i].y + rects[i].h - 1; + + if (region_valid) + { + if (rects[i].x < region.x1) + region.x1 = rects[i].x; + + if (rects[i].y < region.y1) + region.y1 = rects[i].y; + + if (x2 > region.x2) + region.x2 = x2; + + if (y2 > region.y2) + region.y2 = y2; + } + else + { + region.x1 = rects[i].x; + region.y1 = rects[i].y; + region.x2 = x2; + region.y2 = y2; + + region_valid = 1; + } + } + + if (region_valid) + { + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + } + else + surface->Flip (surface, ®ion, DSFLIP_WAITFORSYNC); + } +} + +int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (!palette) + return 0; + + if (firstcolor > 255) + return 0; + + if (firstcolor + ncolors > 256) + ncolors = 256 - firstcolor; + + if (ncolors > 0) + { + int i; + DFBColor entries[ncolors]; + + for (i=0; i<ncolors; i++) + { + entries[i].a = 0xff; + entries[i].r = colors[i].r; + entries[i].g = colors[i].g; + entries[i].b = colors[i].b; + } + + palette->SetEntries (palette, entries, ncolors, firstcolor); + } + + return 1; +} + +void DirectFB_VideoQuit(_THIS) +{ + struct DirectFBEnumRect *rect = enumlist; + + if (this->screen && this->screen->hwdata) + { + IDirectFBSurface *surface = this->screen->hwdata->surface; + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (palette) + palette->Release (palette); + + if (surface) + surface->Release (surface); + + this->screen->hwdata->surface = NULL; + this->screen->hwdata->palette = NULL; + } + + if (HIDDEN->c2frame) + { + HIDDEN->c2frame->Release (HIDDEN->c2frame); + HIDDEN->c2frame = NULL; + } + + if (HIDDEN->eventbuffer) + { + HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer); + HIDDEN->eventbuffer = NULL; + } + + if (HIDDEN->c2layer) + { + HIDDEN->c2layer->Release (HIDDEN->c2layer); + HIDDEN->c2layer = NULL; + } + + if (HIDDEN->layer) + { + HIDDEN->layer->Release (HIDDEN->layer); + HIDDEN->layer = NULL; + } + + if (HIDDEN->dfb) + { + HIDDEN->dfb->Release (HIDDEN->dfb); + HIDDEN->dfb = NULL; + } + + /* Free video mode list */ + if (HIDDEN->modelist) + { + free (HIDDEN->modelist); + HIDDEN->modelist = NULL; + } + + /* Free mode enumeration list */ + while (rect) + { + struct DirectFBEnumRect *next = rect->next; + free (rect); + rect = next; + } + enumlist = NULL; + + HIDDEN->initialized = 0; +} + + +int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor) +{ + /* We can only hide or show the default cursor */ + if ( cursor == NULL ) + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00); + } + else + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF); + } + return 1; +} + +void DirectFB_FinalQuit(void) +{ +} diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h new file mode 100644 index 0000000..e1fa12c --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_video.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_DirectFB_video_h +#define _SDL_DirectFB_video_h + +#include <directfb.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#define _THIS SDL_VideoDevice *this + +/* Private display data */ + +struct SDL_PrivateVideoData +{ + int initialized; + + IDirectFB *dfb; + IDirectFBDisplayLayer *layer; + IDirectFBEventBuffer *eventbuffer; + + int nummodes; + SDL_Rect **modelist; + + /* MGA CRTC2 support */ + int enable_mga_crtc2; + int mga_crtc2_stretch; + float mga_crtc2_stretch_overscan; + IDirectFBDisplayLayer *c2layer; + IDirectFBSurface *c2frame; + DFBRectangle c2ssize; /* Real screen size */ + DFBRectangle c2dsize; /* Stretched screen size */ + DFBRectangle c2framesize; /* CRTC2 screen size */ +}; + +#define HIDDEN (this->hidden) + +void SetDirectFBerror (const char *function, DFBResult code); + +#endif /* _SDL_DirectFB_video_h */ diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c new file mode 100644 index 0000000..fd0cef1 --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.c @@ -0,0 +1,290 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectFB implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_DirectFB_yuv.h" +#include "../SDL_yuvfuncs.h" + + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs directfb_yuvfuncs = { + DirectFB_LockYUVOverlay, + DirectFB_UnlockYUVOverlay, + DirectFB_DisplayYUVOverlay, + DirectFB_FreeYUVOverlay +}; + +struct private_yuvhwdata { + DFBDisplayLayerID layer_id; + + IDirectFBDisplayLayer *layer; + IDirectFBSurface *surface; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + +static DFBEnumerationResult +enum_layers_callback( DFBDisplayLayerID id, + DFBDisplayLayerDescription desc, + void *data ) +{ + struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data; + + /* we don't want the primary */ + if (id == DLID_PRIMARY) + return DFENUM_OK; + + /* take the one with a surface for video */ + if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) + { + hwdata->layer_id = id; + + return DFENUM_CANCEL; + } + + return DFENUM_OK; +} + + +static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata, + int width, int height, Uint32 format) +{ + DFBResult ret; + IDirectFB *dfb = HIDDEN->dfb; + IDirectFBDisplayLayer *layer; + DFBDisplayLayerConfig conf; + + ret = dfb->EnumDisplayLayers (dfb, enum_layers_callback, hwdata); + if (ret) + { + SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret); + return ret; + } + + if (!hwdata->layer_id) + return DFB_UNSUPPORTED; + + ret = dfb->GetDisplayLayer (dfb, hwdata->layer_id, &layer); + if (ret) + { + SetDirectFBerror("IDirectFB::GetDisplayLayer", ret); + return ret; + } + + conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; + conf.width = width; + conf.height = height; + + switch (format) + { + case SDL_YV12_OVERLAY: + conf.pixelformat = DSPF_YV12; + break; + case SDL_IYUV_OVERLAY: + conf.pixelformat = DSPF_I420; + break; + case SDL_YUY2_OVERLAY: + conf.pixelformat = DSPF_YUY2; + break; + case SDL_UYVY_OVERLAY: + conf.pixelformat = DSPF_UYVY; + break; + default: + fprintf (stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format); + break; + } + + /* Need to set coop level or newer DirectFB versions will fail here. */ + ret = layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetCooperativeLevel() failed", ret); + layer->Release (layer); + return ret; + } + + ret = layer->SetConfiguration (layer, &conf); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret); + layer->Release (layer); + return ret; + } + + ret = layer->GetSurface (layer, &hwdata->surface); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret); + layer->Release (layer); + return ret; + } + + hwdata->layer = layer; + + return DFB_OK; +} + +SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + + /* Create the overlay structure */ + overlay = SDL_calloc (1, sizeof(SDL_Overlay)); + if (!overlay) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &directfb_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); + overlay->hwdata = hwdata; + if (!hwdata) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay (overlay); + return NULL; + } + + if (CreateYUVSurface (this, hwdata, width, height, format)) + { + SDL_FreeYUVOverlay (overlay); + return NULL; + } + + overlay->hw_overlay = 1; + + /* Set up the plane pointers */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->planes = 3; + break; + default: + overlay->planes = 1; + break; + } + + /* We're all done.. */ + return overlay; +} + +int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + DFBResult ret; + void *data; + int pitch; + IDirectFBSurface *surface = overlay->hwdata->surface; + + ret = surface->Lock (surface, DSLF_READ | DSLF_WRITE, &data, &pitch); + if (ret) + { + SetDirectFBerror("IDirectFBSurface::Lock", ret); + return -1; + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches[0] = (Uint16) pitch; + overlay->pixels[0] = (Uint8*) data; + + switch (overlay->format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Add the two extra planes */ + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; + break; + default: + /* Only one plane, no worries */ + break; + } + + return 0; +} + +void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + IDirectFBSurface *surface = overlay->hwdata->surface; + + overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL; + + surface->Unlock (surface); +} + +int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + DFBResult ret; + DFBDisplayLayerConfig conf; + IDirectFBDisplayLayer *primary = HIDDEN->layer; + IDirectFBDisplayLayer *layer = overlay->hwdata->layer; + + primary->GetConfiguration (primary, &conf); + + ret = layer->SetScreenLocation (layer, + dst->x / (float) conf.width, dst->y / (float) conf.height, + dst->w / (float) conf.width, dst->h / (float) conf.height ); + if (ret) + { + SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret); + return -1; + } + + return 0; +} + +void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if (hwdata) + { + if (hwdata->surface) + hwdata->surface->Release (hwdata->surface); + + if (hwdata->layer) + hwdata->layer->Release (hwdata->layer); + + free (hwdata); + } +} + diff --git a/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h new file mode 100644 index 0000000..64bc86f --- /dev/null +++ b/3rdparty/SDL/src/video/directfb/SDL_DirectFB_yuv.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectFB implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_DirectFB_video.h" + +extern SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullevents.c b/3rdparty/SDL/src/video/dummy/SDL_nullevents.c new file mode 100644 index 0000000..177fc3f --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullevents.c @@ -0,0 +1,45 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Being a null driver, there's no event stream. We just define stubs for + most of the API. */ + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullvideo.h" +#include "SDL_nullevents_c.h" + +void DUMMY_PumpEvents(_THIS) +{ + /* do nothing. */ +} + +void DUMMY_InitOSKeymap(_THIS) +{ + /* do nothing. */ +} + +/* end of SDL_nullevents.c ... */ + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h b/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h new file mode 100644 index 0000000..3b65794 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nullvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void DUMMY_InitOSKeymap(_THIS); +extern void DUMMY_PumpEvents(_THIS); + +/* end of SDL_nullevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c b/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c new file mode 100644 index 0000000..47daea8 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h b/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h new file mode 100644 index 0000000..479eb0e --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nullvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c new file mode 100644 index 0000000..7e096e2 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.c @@ -0,0 +1,239 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Dummy SDL video driver implementation; this is just enough to make an + * SDL-based application THINK it's got a working video driver, for + * applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it, + * and also for use as a collection of stubs when porting SDL to a new + * platform for which you haven't yet written a valid video driver. + * + * This is also a great way to determine bottlenecks: if you think that SDL + * is a performance problem for a given platform, enable this driver, and + * then see if your application runs faster without video overhead. + * + * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion + * of this was cut-and-pasted from Stephane Peter's work in the AAlib + * SDL video driver. Renamed to "DUMMY" by Sam Lantinga. + */ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nullvideo.h" +#include "SDL_nullevents_c.h" +#include "SDL_nullmouse_c.h" + +#define DUMMYVID_DRIVER_NAME "dummy" + +/* Initialization/Query functions */ +static int DUMMY_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DUMMY_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DUMMY_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DUMMY_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void DUMMY_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DUMMY_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DUMMY_LockHWSurface(_THIS, SDL_Surface *surface); +static void DUMMY_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DUMMY_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void DUMMY_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* DUMMY driver bootstrap functions */ + +static int DUMMY_Available(void) +{ + const char *envr = SDL_getenv("SDL_VIDEODRIVER"); + if ((envr) && (SDL_strcmp(envr, DUMMYVID_DRIVER_NAME) == 0)) { + return(1); + } + + return(0); +} + +static void DUMMY_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DUMMY_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = DUMMY_VideoInit; + device->ListModes = DUMMY_ListModes; + device->SetVideoMode = DUMMY_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = DUMMY_SetColors; + device->UpdateRects = DUMMY_UpdateRects; + device->VideoQuit = DUMMY_VideoQuit; + device->AllocHWSurface = DUMMY_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DUMMY_LockHWSurface; + device->UnlockHWSurface = DUMMY_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = DUMMY_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DUMMY_InitOSKeymap; + device->PumpEvents = DUMMY_PumpEvents; + + device->free = DUMMY_DeleteDevice; + + return device; +} + +VideoBootStrap DUMMY_bootstrap = { + DUMMYVID_DRIVER_NAME, "SDL dummy video driver", + DUMMY_Available, DUMMY_CreateDevice +}; + + +int DUMMY_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* + fprintf(stderr, "WARNING: You are using the SDL dummy video driver!\n"); + */ + + /* Determine the screen depth (use default 8-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 8; + vformat->BytesPerPixel = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **DUMMY_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *DUMMY_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( this->hidden->buffer ) { + SDL_free( this->hidden->buffer ); + } + + this->hidden->buffer = SDL_malloc(width * height * (bpp / 8)); + if ( ! this->hidden->buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + SDL_memset(this->hidden->buffer, 0, width * height * (bpp / 8)); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + SDL_free(this->hidden->buffer); + this->hidden->buffer = NULL; + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = flags & SDL_FULLSCREEN; + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pitch = current->w * (bpp / 8); + current->pixels = this->hidden->buffer; + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int DUMMY_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DUMMY_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int DUMMY_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void DUMMY_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void DUMMY_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + /* do nothing. */ +} + +int DUMMY_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void DUMMY_VideoQuit(_THIS) +{ + if (this->screen->pixels != NULL) + { + SDL_free(this->screen->pixels); + this->screen->pixels = NULL; + } +} diff --git a/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h new file mode 100644 index 0000000..05c19e3 --- /dev/null +++ b/3rdparty/SDL/src/video/dummy/SDL_nullvideo.h @@ -0,0 +1,40 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_nullvideo_h +#define _SDL_nullvideo_h + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; +}; + +#endif /* _SDL_nullvideo_h */ diff --git a/3rdparty/SDL/src/video/e_log.h b/3rdparty/SDL/src/video/e_log.h new file mode 100644 index 0000000..7f8bf71 --- /dev/null +++ b/3rdparty/SDL/src/video/e_log.h @@ -0,0 +1,140 @@ +/* @(#)e_log.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $"; +#endif + +/* __ieee754_log(x) + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +#ifdef __STDC__ + double __ieee754_log(double x) +#else + double __ieee754_log(x) + double x; +#endif +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/zero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) {if(k==0) return zero; else {dk=(double)k; + return dk*ln2_hi+dk*ln2_lo;} + } + R = f*f*(0.5-0.33333333333333333*f); + if(k==0) return f-R; else {dk=(double)k; + return dk*ln2_hi-((R-dk*ln2_lo)-f);} + } + s = f/(2.0+f); + dk = (double)k; + z = s*s; + i = hx-0x6147a; + w = z*z; + j = 0x6b851-hx; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + i |= j; + R = t2+t1; + if(i>0) { + hfsq=0.5*f*f; + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); + } else { + if(k==0) return f-s*(f-R); else + return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); + } +} diff --git a/3rdparty/SDL/src/video/e_pow.h b/3rdparty/SDL/src/video/e_pow.h new file mode 100644 index 0000000..0aa372a --- /dev/null +++ b/3rdparty/SDL/src/video/e_pow.h @@ -0,0 +1,302 @@ +/* @(#)e_pow.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $"; +#endif + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. (anything) ** 0 is 1 + * 2. (anything) ** 1 is itself + * 3. (anything) ** NAN is NAN + * 4. NAN ** (anything except 0) is NAN + * 5. +-(|x| > 1) ** +INF is +INF + * 6. +-(|x| > 1) ** -INF is +0 + * 7. +-(|x| < 1) ** +INF is +0 + * 8. +-(|x| < 1) ** -INF is +INF + * 9. +-1 ** +-INF is NAN + * 10. +0 ** (+anything except 0, NAN) is +0 + * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 12. +0 ** (-anything except 0, NAN) is +INF + * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 14. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 15. +INF ** (+anything except 0,NAN) is +INF + * 16. +INF ** (-anything except 0,NAN) is +0 + * 17. -INF ** (anything) = -0 ** (-anything) + * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 19. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +#ifdef __STDC__ + double __ieee754_pow(double x, double y) +#else + double __ieee754_pow(x,y) + double x, y; +#endif +{ + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int32_t i,j,k,yisint,n; + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|ly)==0) return one; + + /* +-NaN return x+y */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return x+y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = ly>>(52-k); + if((u_int32_t)(j<<(52-k))==ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if(((ix-0x3ff00000)|lx)==0) + return y - y; /* inf**+-1 is NaN */ + else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */ + return (hy>=0)? y: zero; + else /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0)?-y: zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return __ieee754_sqrt(x); + } + } + + ax = x < 0 ? -x : x; /*fabs(x);*/ + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x); + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x-1; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + SET_LOW_WORD(t1,0); + t2 = v-(t1-u); + } else { + double s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */ + else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */ + else {k=0;n+=1;ix -= 0x00100000;} + SET_HIGH_WORD(ax,ix); + + /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ + u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ + v = one/(ax+bp[k]); + s = u*v; + s_h = s; + SET_LOW_WORD(s_h,0); + /* t_h=ax+bp[k] High */ + t_h = zero; + SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = s*s; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+s); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-3.0)-s2); + /* u+v = s*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*s; + /* 2/(3log2)*(s+...) */ + p_h = u+v; + SET_LOW_WORD(p_h,0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + SET_LOW_WORD(t1,0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0) + s = -one;/* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1,0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + EXTRACT_WORDS(j,i,z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t,n&~(0x000fffff>>k)); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + SET_LOW_WORD(t,0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + GET_HIGH_WORD(j,z); + j += (n<<20); + if((j>>20)<=0) z = SDL_NAME(scalbn)(z,n); /* subnormal output */ + else SET_HIGH_WORD(z,j); + return s*z; +} diff --git a/3rdparty/SDL/src/video/e_sqrt.h b/3rdparty/SDL/src/video/e_sqrt.h new file mode 100644 index 0000000..657380e --- /dev/null +++ b/3rdparty/SDL/src/video/e_sqrt.h @@ -0,0 +1,493 @@ +/* @(#)e_sqrt.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $"; +#endif + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +/*#include "math.h"*/ +#include "math_private.h" + +#ifdef __STDC__ + double SDL_NAME(copysign)(double x, double y) +#else + double SDL_NAME(copysign)(x,y) + double x,y; +#endif +{ + u_int32_t hx,hy; + GET_HIGH_WORD(hx,x); + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000)); + return x; +} + +#ifdef __STDC__ + double SDL_NAME(scalbn) (double x, int n) +#else + double SDL_NAME(scalbn) (x,n) + double x; int n; +#endif +{ + int32_t k,hx,lx; + EXTRACT_WORDS(hx,lx,x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx,x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return huge*SDL_NAME(copysign)(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge*SDL_NAME(copysign)(huge,x); /*overflow*/ + else return tiny*SDL_NAME(copysign)(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} + +#ifdef __STDC__ + double __ieee754_sqrt(double x) +#else + double __ieee754_sqrt(x) + double x; +#endif +{ + double z; + int32_t sign = (int)0x80000000; + int32_t ix0,s0,q,m,t,i; + u_int32_t r,t1,s1,ix1,q1; + + EXTRACT_WORDS(ix0,ix1,x); + + /* take care of Inf and NaN */ + if((ix0&0x7ff00000)==0x7ff00000) { + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if(ix0<=0) { + if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ + else if(ix0<0) + return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0>>20); + if(m==0) { /* subnormal x */ + while(ix0==0) { + m -= 21; + ix0 |= (ix1>>11); ix1 <<= 21; + } + for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; + m -= i-1; + ix0 |= (ix1>>(32-i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0&0x000fffff)|0x00100000; + if(m&1){ /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while(r!=0) { + t = s0+r; + if(t<=ix0) { + s0 = t+r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + r = sign; + while(r!=0) { + t1 = s1+r; + t = s0; + if((t<ix0)||((t==ix0)&&(t1<=ix1))) { + s1 = t1+r; + if(((int32_t)(t1&sign)==sign)&&(s1&sign)==0) s0 += 1; + ix0 -= t; + if (ix1 < t1) ix0 -= 1; + ix1 -= t1; + q1 += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if((ix0|ix1)!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(u_int32_t)0xfffffffe) q+=1; + q1+=2; + } else + q1 += (q1&1); + } + } + ix0 = (q>>1)+0x3fe00000; + ix1 = q1>>1; + if ((q&1)==1) ix1 |= sign; + ix0 += (m <<20); + INSERT_WORDS(z,ix0,ix1); + return z; +} + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifs and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x<z*z ... rounded up) z = z - ulp; else + if(x>=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */ + diff --git a/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h b/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h new file mode 100644 index 0000000..b641454 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/3dfx_mmio.h @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx register definitions */ + +#include "3dfx_regs.h" + +/* 3Dfx control macros */ + +#define tdfx_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define tdfx_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define tdfx_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define tdfx_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define tdfx_wait(space) \ +{ \ + while ( (tdfx_in8(TDFX_STATUS) & 0x1F) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define tdfx_waitidle() \ +{ \ + int i = 0; \ + \ + tdfx_wait(1); \ + tdfx_out32(COMMAND_3D, COMMAND_3D_NOP); \ + do { \ + i = (tdfx_in32(TDFX_STATUS) & STATUS_BUSY) ? 0 : i + 1; \ + } while ( i != 3 ); \ +} + diff --git a/3rdparty/SDL/src/video/fbcon/3dfx_regs.h b/3rdparty/SDL/src/video/fbcon/3dfx_regs.h new file mode 100644 index 0000000..e86f727 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/3dfx_regs.h @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _3DFX_REGS_H +#define _3DFX_REGS_H + +/* This information comes from the public 3Dfx specs for the Voodoo 3000 */ + +/* mapped_io register offsets */ +#define TDFX_STATUS 0x00 + +#define INTCTRL (0x00100000 + 0x04) +#define CLIP0MIN (0x00100000 + 0x08) +#define CLIP0MAX (0x00100000 + 0x0c) +#define DSTBASE (0x00100000 + 0x10) +#define DSTFORMAT (0x00100000 + 0x14) +#define SRCCOLORKEYMIN (0x00100000 + 0x18) +#define SRCCOLORKEYMAX (0x00100000 + 0x1c) +#define DSTCOLORKEYMIN (0x00100000 + 0x20) +#define DSTCOLORKEYMAX (0x00100000 + 0x24) +#define BRESERROR0 (0x00100000 + 0x28) +#define BRESERROR1 (0x00100000 + 0x2c) +#define ROP_2D (0x00100000 + 0x30) +#define SRCBASE (0x00100000 + 0x34) +#define COMMANDEXTRA_2D (0x00100000 + 0x38) +#define PATTERN0 (0x00100000 + 0x44) +#define PATTERN1 (0x00100000 + 0x48) +#define CLIP1MIN (0x00100000 + 0x4c) +#define CLIP1MAX (0x00100000 + 0x50) +#define SRCFORMAT (0x00100000 + 0x54) +#define SRCSIZE (0x00100000 + 0x58) +#define SRCXY (0x00100000 + 0x5c) +#define COLORBACK (0x00100000 + 0x60) +#define COLORFORE (0x00100000 + 0x64) +#define DSTSIZE (0x00100000 + 0x68) +#define DSTXY (0x00100000 + 0x6c) +#define COMMAND_2D (0x00100000 + 0x70) +#define LAUNCH_2D (0x00100000 + 0x80) +#define PATTERNBASE (0x00100000 + 0x100) + +#define COMMAND_3D (0x00200000 + 0x120) + +/* register bitfields (not all, only as needed) */ + +#define BIT(x) (1UL << (x)) + +#define COMMAND_2D_BITBLT 0x01 +#define COMMAND_2D_FILLRECT 0x05 +#define COMMAND_2D_LINE 0x06 +#define COMMAND_2D_POLYGON_FILL 0x08 +#define COMMAND_2D_INITIATE BIT(8) +#define COMMAND_2D_REVERSELINE BIT(9) +#define COMMAND_2D_STIPPLELINE BIT(12) +#define COMMAND_2D_MONOCHROME_PATT BIT(13) +#define COMMAND_2D_MONOCHROME_TRANSP BIT(16) + +#define COMMAND_3D_NOP 0x00 + +#define STATUS_RETRACE BIT(6) +#define STATUS_BUSY BIT(9) + +#endif /* _3DFX_REGS_H */ + diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c new file mode 100644 index 0000000..eb083b8 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fb3dfx.h" +#include "3dfx_mmio.h" + + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + /* find start of retrace */ + tdfx_waitidle(); + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == STATUS_RETRACE ) + ; + /* wait until we're past the start */ + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == 0 ) + ; +} +static void WaitIdle(_THIS) +{ + tdfx_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int bpp; + Uint32 dst_base; + Uint32 format; + int dstX, dstY; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the destination pixel format */ + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + format = dst->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + + /* Calculate source and destination base coordinates */ + dstX = rect->x; + dstY = rect->y; + + /* Execute the fill command */ + tdfx_wait(6); + tdfx_out32(DSTBASE, dst_base); + tdfx_out32(DSTFORMAT, format); + tdfx_out32(COLORFORE, color); + tdfx_out32(COMMAND_2D, COMMAND_2D_FILLRECT); + tdfx_out32(DSTSIZE, rect->w | (rect->h << 16)); + tdfx_out32(LAUNCH_2D, dstX | (dstY << 16)); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int bpp; + Uint32 src_format; + Uint32 src_base; + Uint32 dst_base; + int srcX, srcY; + int dstX, dstY; + Uint32 blitop; + Uint32 use_colorkey; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the source and destination pixel format */ + src_base = ((char *)src->pixels - mapped_mem); + bpp = src->format->BitsPerPixel; + src_format = src->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + + srcX = srcrect->x; + srcY = srcrect->y; + dstX = dstrect->x; + dstY = dstrect->y; + + /* Assemble the blit operation */ + blitop = COMMAND_2D_BITBLT | (0xCC << 24); + if ( srcX <= dstX ) { + blitop |= BIT(14); + srcX += (dstrect->w - 1); + dstX += (dstrect->w - 1); + } + if ( srcY <= dstY ) { + blitop |= BIT(15); + srcY += (dstrect->h - 1); + dstY += (dstrect->h - 1); + } + + /* Perform the blit! */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + tdfx_wait(3); + tdfx_out32(SRCCOLORKEYMIN, src->format->colorkey); + tdfx_out32(SRCCOLORKEYMAX, src->format->colorkey); + tdfx_out32(ROP_2D, 0xAA00); + use_colorkey = 1; + } else { + use_colorkey = 0; + } + tdfx_wait(9); + tdfx_out32(SRCBASE, (Uint32)src_base); + tdfx_out32(SRCFORMAT, src_format); + tdfx_out32(DSTBASE, (Uint32)dst_base); + tdfx_out32(DSTFORMAT, src_format); + tdfx_out32(COMMAND_2D, blitop); + tdfx_out32(COMMANDEXTRA_2D, use_colorkey); + tdfx_out32(DSTSIZE, dstrect->w | (dstrect->h << 16)); + tdfx_out32(DSTXY, dstX | (dstY << 16)); + tdfx_out32(LAUNCH_2D, srcX | (srcY << 16)); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_3DfxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* Reset the 3Dfx controller */ + tdfx_out32(BRESERROR0, 0); + tdfx_out32(BRESERROR1, 0); + + /* The 3Dfx has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The 3Dfx has accelerated normal and colorkey blits */ + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h new file mode 100644 index 0000000..4a59de9 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fb3dfx.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for 3Dfx acceleration */ +extern void FB_3DfxAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c new file mode 100644 index 0000000..63dff87 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.c @@ -0,0 +1,442 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <unistd.h> +#include <sys/time.h> +#include <ctype.h> + +#include "SDL_stdinc.h" +#include "SDL_fbvideo.h" +#include "SDL_fbelo.h" + +/* + calibration default values + values are read from the following environment variables: + + SDL_ELO_MIN_X + SDL_ELO_MAX_X + SDL_ELO_MIN_Y + SDL_ELO_MAX_Y +*/ + +static int ELO_MIN_X = 400; +static int ELO_MAX_X = 3670; +static int ELO_MIN_Y = 500; +static int ELO_MAX_Y = 3540; + +#define ELO_SNAP_SIZE 6 +#define ELO_TOUCH_BYTE 'T' +#define ELO_ID 'I' +#define ELO_MODE 'M' +#define ELO_PARAMETER 'P' +#define ELO_REPORT 'B' +#define ELO_ACK 'A' + +#define ELO_INIT_CHECKSUM 0xAA + +#define ELO_BTN_PRESS 0x01 +#define ELO_STREAM 0x02 +#define ELO_BTN_RELEASE 0x04 + +#define ELO_TOUCH_MODE 0x01 +#define ELO_STREAM_MODE 0x02 +#define ELO_UNTOUCH_MODE 0x04 +#define ELO_RANGE_CHECK_MODE 0x40 +#define ELO_TRIM_MODE 0x02 +#define ELO_CALIB_MODE 0x04 +#define ELO_SCALING_MODE 0x08 +#define ELO_TRACKING_MODE 0x40 + +#define ELO_SERIAL_MASK 0xF8 + +#define ELO_SERIAL_IO '0' + +#define ELO_MAX_TRIALS 3 +#define ELO_MAX_WAIT 100000 +#define ELO_UNTOUCH_DELAY 5 +#define ELO_REPORT_DELAY 1 + +/* eloParsePacket +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) { + static int elo_button = 0; + static int last_x = 0; + static int last_y = 0; + int x,y; + + /* Check if we have a touch packet */ + if (mousebuf[1] != ELO_TOUCH_BYTE) { + return 0; + } + + x = ((mousebuf[4] << 8) | mousebuf[3]); + y = ((mousebuf[6] << 8) | mousebuf[5]); + + if((SDL_abs(x - last_x) > ELO_SNAP_SIZE) || (SDL_abs(y - last_y) > ELO_SNAP_SIZE)) { + *dx = ((mousebuf[4] << 8) | mousebuf[3]); + *dy = ((mousebuf[6] << 8) | mousebuf[5]); + } + else { + *dx = last_x; + *dy = last_y; + } + + last_x = *dx; + last_y = *dy; + + if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) { + elo_button = 1; + } + if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) { + elo_button = 0; + } + + *button_state = elo_button; + return 1; +} + +/* Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy) { + int input_x = *dx; + int input_y = *dy; + int width = ELO_MAX_X - ELO_MIN_X; + int height = ELO_MAX_Y - ELO_MIN_Y; + + *dx = ((int)cache_vinfo.xres - ((int)cache_vinfo.xres * (input_x - ELO_MIN_X)) / width); + *dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height; +} + + +/* eloGetPacket +*/ +int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) { + int num_bytes; + int ok; + + if(fd == 0) { + num_bytes = ELO_PACKET_SIZE; + } + else { + num_bytes = read(fd, + (char *) (buffer + *buffer_p), + ELO_PACKET_SIZE - *buffer_p); + } + + if (num_bytes < 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "System error while reading from Elographics touchscreen.\n"); +#endif + return 0; + } + + while (num_bytes) { + if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) { + SDL_memcpy(&buffer[0], &buffer[1], num_bytes-1); + } + else { + if (*buffer_p < ELO_PACKET_SIZE-1) { + *checksum = *checksum + buffer[*buffer_p]; + *checksum = *checksum % 256; + } + (*buffer_p)++; + } + num_bytes--; + } + + if (*buffer_p == ELO_PACKET_SIZE) { + ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); + *checksum = ELO_INIT_CHECKSUM; + *buffer_p = 0; + + if (!ok) { + return 0; + } + + return 1; + } + else { + return 0; + } +} + +/* eloSendPacket +*/ + +int eloSendPacket(unsigned char* packet, int fd) +{ + int i, result; + int sum = ELO_INIT_CHECKSUM; + + packet[0] = ELO_START_BYTE; + for (i = 0; i < ELO_PACKET_SIZE-1; i++) { + sum += packet[i]; + sum &= 0xFF; + } + packet[ELO_PACKET_SIZE-1] = sum; + + result = write(fd, packet, ELO_PACKET_SIZE); + + if (result != ELO_PACKET_SIZE) { +#ifdef DEBUG_MOUSE + printf("System error while sending to Elographics touchscreen.\n"); +#endif + return 0; + } + else { + return 1; + } +} + + +/* eloWaitForInput + */ +int eloWaitForInput(int fd, int timeout) +{ + fd_set readfds; + struct timeval to; + int r; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + to.tv_sec = 0; + to.tv_usec = timeout; + + r = select(FD_SETSIZE, &readfds, NULL, NULL, &to); + return r; +} + +/* eloWaitReply + */ +int eloWaitReply(unsigned char type, unsigned char *reply, int fd) { + int ok; + int i, result; + int reply_p = 0; + int sum = ELO_INIT_CHECKSUM; + + i = ELO_MAX_TRIALS; + do { + ok = 0; + + result = eloWaitForInput(fd, ELO_MAX_WAIT); + + if (result > 0) { + ok = eloGetPacket(reply, &reply_p, &sum, fd); + + if (ok && reply[1] != type && type != ELO_PARAMETER) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Wrong reply received\n"); +#endif + ok = 0; + } + } + else { +#ifdef DEBUG_MOUSE + fprintf(stderr, "No input!\n"); +#endif + } + + if (result == 0) { + i--; + } + } while(!ok && (i>0)); + + return ok; +} + + +/* eloWaitAck + */ + +int eloWaitAck(int fd) { + unsigned char packet[ELO_PACKET_SIZE]; + int i, nb_errors; + + if (eloWaitReply(ELO_ACK, packet, fd)) { + for (i = 0, nb_errors = 0; i < 4; i++) { + if (packet[2 + i] != '0') { + nb_errors++; + } + } + + if (nb_errors != 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors); +#endif + } + return 1; + } + else { + return 0; + } +} + + +/* eloSendQuery -- +*/ +int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) { + int ok; + + if (eloSendPacket(request, fd)) { + ok = eloWaitReply(toupper(request[1]), reply, fd); + if (ok) { + ok = eloWaitAck(fd); + } + return ok; + } + else { + return 0; + } +} + + +/* eloSendControl +*/ +int eloSendControl(unsigned char* control, int fd) { + if (eloSendPacket(control, fd)) { + return eloWaitAck(fd); + } + else { + return 0; + } +} + +/* eloInitController +*/ +int eloInitController(int fd) { + unsigned char req[ELO_PACKET_SIZE]; + unsigned char reply[ELO_PACKET_SIZE]; + const char *buffer = NULL; + int result = 0; + + struct termios mouse_termios; + + /* try to read the calibration values */ + buffer = SDL_getenv("SDL_ELO_MIN_X"); + if(buffer) { + ELO_MIN_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_X"); + if(buffer) { + ELO_MAX_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MIN_Y"); + if(buffer) { + ELO_MIN_Y = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_Y"); + if(buffer) { + ELO_MAX_Y = SDL_atoi(buffer); + } + +#ifdef DEBUG_MOUSE + fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n", + ELO_MIN_X, + ELO_MAX_X, + ELO_MIN_Y, + ELO_MAX_Y); +#endif + + /* set comm params */ + SDL_memset(&mouse_termios, 0, sizeof(mouse_termios)); + mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; + mouse_termios.c_cc[VMIN] = 1; + result = tcsetattr(fd, TCSANOW, &mouse_termios); + + if (result < 0) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to configure Elographics touchscreen port\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_PARAMETER); + if (!eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Not at the specified rate or model 2310, will continue\n"); +#endif + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_ID); + if (eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Ok, controller configured!\n"); +#endif + } + else { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to ask Elographics touchscreen identification\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_MODE; + req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; + req[4] = ELO_TRACKING_MODE; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_REPORT; + req[2] = ELO_UNTOUCH_DELAY; + req[3] = ELO_REPORT_DELAY; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n"); +#endif + return 0; + } + + return 1; +} + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy) { + unsigned char buffer[ELO_PACKET_SIZE]; + int pointer = 0; + int checksum = ELO_INIT_CHECKSUM; + + while(pointer < ELO_PACKET_SIZE) { + if(eloGetPacket(buffer, &pointer, &checksum, fd)) { + break; + } + } + + if(!eloParsePacket(buffer, realx, realy, button_state)) { + return 0; + } + + *x = *realx; + *y = *realy; + + eloConvertXY(this, x, y); + + return 1; +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h new file mode 100644 index 0000000..e7fde4f --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbelo.h @@ -0,0 +1,55 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_fbelo_h +#define SDL_fbelo_h + +#include "SDL_fbvideo.h" + +/* ELO */ +#define ELO_PACKET_SIZE 10 +#define ELO_START_BYTE 'U' + +/* eloConvertXY + Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy); + +/* eloInitController(int fd) + Initialize the ELO serial touchscreen controller +*/ +int eloInitController(int fd); + +/* eloParsePacket + extract position and button state from a packet +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state); + +/* eloReadPosition + read a packet and get the cursor position +*/ + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy); + +#endif /* SDL_fbelo_h */ diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c b/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c new file mode 100644 index 0000000..5e369a4 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbevents.c @@ -0,0 +1,1254 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting console events into SDL events */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +/* For parsing /proc */ +#include <dirent.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "SDL_timer.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbevents_c.h" +#include "SDL_fbkeys.h" + +#include "SDL_fbelo.h" + +#ifndef GPM_NODE_FIFO +#define GPM_NODE_FIFO "/dev/gpmdata" +#endif + +/*#define DEBUG_KEYBOARD*/ +/*#define DEBUG_MOUSE*/ + +/* The translation tables from a console scancode to a SDL keysym */ +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +static SDLKey keymap[128]; +static Uint16 keymap_temp[128]; /* only used at startup */ +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +static void FB_vgainitkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Don't do anything if we are passed a closed keyboard */ + if ( fd < 0 ) { + return; + } + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* fill keytemp. This replaces SDL_fbkeys.h */ + if ( (map == 0) && (i<128) ) { + keymap_temp[i] = entry.kb_value; + } + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } +} + +int FB_InGraphicsMode(_THIS) +{ + return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); +} + +int FB_EnterGraphicsMode(_THIS) +{ + struct termios keyboard_termios; + + /* Set medium-raw keyboard mode */ + if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) { + + /* Switch to the correct virtual terminal */ + if ( current_vt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + saved_vt = vtstate.v_active; + } + if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); + } + } + + /* Set the terminal input mode */ + if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { + SDL_SetError("Unable to get terminal attributes"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { + SDL_SetError("Unable to get current keyboard mode"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + keyboard_termios = saved_kbd_termios; + keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + keyboard_termios.c_cc[VMIN] = 0; + keyboard_termios.c_cc[VTIME] = 0; + if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set terminal attributes"); + return(-1); + } + /* This will fail if we aren't root or this isn't our tty */ + if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in raw mode"); + return(-1); + } + if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in graphics mode"); + return(-1); + } + /* Prevent switching the virtual terminal */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + } + return(keyboard_fd); +} + +void FB_LeaveGraphicsMode(_THIS) +{ + if ( FB_InGraphicsMode(this) ) { + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); + tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); + saved_kbd_mode = -1; + + /* Head back over to the original virtual terminal */ + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); + if ( saved_vt > 0 ) { + ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); + } + } +} + +void FB_CloseKeyboard(_THIS) +{ + if ( keyboard_fd >= 0 ) { + FB_LeaveGraphicsMode(this); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + } + keyboard_fd = -1; +} + +int FB_OpenKeyboard(_THIS) +{ + /* Open only if not already opened */ + if ( keyboard_fd < 0 ) { + static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + int i, tty0_fd; + + /* Try to query for a free virtual terminal */ + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); + close(tty0_fd); + if ( (geteuid() == 0) && (current_vt > 0) ) { + for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt); + keyboard_fd = open(vtpath, O_RDWR, 0); +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "vtpath = %s, fd = %d\n", + vtpath, keyboard_fd); +#endif /* DEBUG_KEYBOARD */ + + /* This needs to be our controlling tty + so that the kernel ioctl() calls work + */ + if ( keyboard_fd >= 0 ) { + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + } + } + } + if ( keyboard_fd < 0 ) { + /* Last resort, maybe our tty is a usable VT */ + struct vt_stat vtstate; + + keyboard_fd = open("/dev/tty", O_RDWR); + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + current_vt = vtstate.v_active; + } else { + current_vt = 0; + } + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "Current VT: %d\n", current_vt); +#endif + saved_kbd_mode = -1; + + /* Make sure that our input is a console terminal */ + { int dummy; + if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { + close(keyboard_fd); + keyboard_fd = -1; + SDL_SetError("Unable to open a console terminal"); + } + } + + /* Set up keymap */ + FB_vgainitkeymaps(keyboard_fd); + } + return(keyboard_fd); +} + +static enum { + MOUSE_NONE = -1, + MOUSE_MSC, /* Note: GPM uses the MSC protocol */ + MOUSE_PS2, + MOUSE_IMPS2, + MOUSE_MS, + MOUSE_BM, + MOUSE_ELO, + MOUSE_TSLIB, + NUM_MOUSE_DRVS +} mouse_drv = MOUSE_NONE; + +void FB_CloseMouse(_THIS) +{ +#if SDL_INPUT_TSLIB + if (ts_dev != NULL) { + ts_close(ts_dev); + ts_dev = NULL; + mouse_fd = -1; + } +#endif /* SDL_INPUT_TSLIB */ + if ( mouse_fd > 0 ) { + close(mouse_fd); + } + mouse_fd = -1; +} + +/* Returns processes listed in /proc with the desired name */ +static int find_pid(DIR *proc, const char *wanted_name) +{ + struct dirent *entry; + int pid; + + /* First scan proc for the gpm process */ + pid = 0; + while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { + if ( isdigit(entry->d_name[0]) ) { + FILE *status; + char path[PATH_MAX]; + char name[PATH_MAX]; + + SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name); + status=fopen(path, "r"); + if ( status ) { + int matches = 0; + name[0] = '\0'; + matches = fscanf(status, "Name: %s", name); + if ( (matches == 1) && (SDL_strcmp(name, wanted_name) == 0) ) { + pid = SDL_atoi(entry->d_name); + } + fclose(status); + } + } + } + return pid; +} + +/* Returns true if /dev/gpmdata is being written to by gpm */ +static int gpm_available(char *proto, size_t protolen) +{ + int available; + DIR *proc; + int pid; + int cmdline, len, arglen; + char path[PATH_MAX]; + char args[PATH_MAX], *arg; + + /* Don't bother looking if the fifo isn't there */ +#ifdef DEBUG_MOUSE + fprintf(stderr,"testing gpm\n"); +#endif + if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { + return(0); + } + + available = 0; + proc = opendir("/proc"); + if ( proc ) { + char raw_proto[10] = { '\0' }; + char repeat_proto[10] = { '\0' }; + while ( !available && (pid=find_pid(proc, "gpm")) > 0 ) { + SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); + cmdline = open(path, O_RDONLY, 0); + if ( cmdline >= 0 ) { + len = read(cmdline, args, sizeof(args)); + arg = args; + while ( len > 0 ) { + arglen = SDL_strlen(arg)+1; +#ifdef DEBUG_MOUSE + fprintf(stderr,"gpm arg %s len %d\n",arg,arglen); +#endif + if ( SDL_strcmp(arg, "-t") == 0) { + /* protocol string, keep it for later */ + char *t, *s; + t = arg + arglen; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto)); + if (s) *s = ' '; + } + if ( SDL_strncmp(arg, "-R", 2) == 0 ) { + char *t, *s; + available = 1; + t = arg + 2; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(repeat_proto, t, SDL_arraysize(repeat_proto)); + if (s) *s = ' '; + } + len -= arglen; + arg += arglen; + } + close(cmdline); + } + } + closedir(proc); + + if ( available ) { + if ( SDL_strcmp(repeat_proto, "raw") == 0 ) { + SDL_strlcpy(proto, raw_proto, protolen); + } else if ( *repeat_proto ) { + SDL_strlcpy(proto, repeat_proto, protolen); + } else { + SDL_strlcpy(proto, "msc", protolen); + } + } + } + return available; +} + + +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives + * us access to the mousewheel, etc. Returns zero if + * writes to device failed, but you still need to query the + * device to see which mode it's actually in. + */ +static int set_imps2_mode(int fd) +{ + /* If you wanted to control the mouse mode (and we do :) ) ... + Set IMPS/2 protocol: + {0xf3,200,0xf3,100,0xf3,80} + Reset mouse device: + {0xFF} + */ + Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; + /*Uint8 reset = 0xff;*/ + fd_set fdset; + struct timeval tv; + int retval = 0; + + if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { + /* Don't reset it, that'll clear IMPS/2 mode on some mice + if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) { + retval = 1; + } + */ + } + + /* Get rid of any chatter from the above */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + return retval; +} + + +/* Returns true if the mouse uses the IMPS/2 protocol */ +static int detect_imps2(int fd) +{ + int imps2; + + imps2 = 0; + + if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) { + imps2 = 1; + } + if ( ! imps2 ) { + Uint8 query_ps2 = 0xF2; + fd_set fdset; + struct timeval tv; + + /* Get rid of any mouse motion noise */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + /* Query for the type of mouse protocol */ + if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) { + Uint8 ch = 0; + + /* Get the mouse protocol response */ + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 1; + tv.tv_usec = 0; + if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { + break; + } + } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) && + ((ch == 0xFA) || (ch == 0xAA)) ); + + /* Experimental values (Logitech wheelmouse) */ +#ifdef DEBUG_MOUSE +fprintf(stderr, "Last mouse mode: 0x%x\n", ch); +#endif + if ( (ch == 3) || (ch == 4) ) { + imps2 = 1; + } + } + } + return imps2; +} + +int FB_OpenMouse(_THIS) +{ + int i; + const char *mousedev; + const char *mousedrv; + + mousedrv = SDL_getenv("SDL_MOUSEDRV"); + mousedev = SDL_getenv("SDL_MOUSEDEV"); + mouse_fd = -1; + +#if SDL_INPUT_TSLIB + if ( mousedrv && (SDL_strcmp(mousedrv, "TSLIB") == 0) ) { + if (mousedev == NULL) mousedev = SDL_getenv("TSLIB_TSDEVICE"); + if (mousedev != NULL) { + ts_dev = ts_open(mousedev, 1); + if ((ts_dev != NULL) && (ts_config(ts_dev) >= 0)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Using tslib touchscreen\n"); +#endif + mouse_drv = MOUSE_TSLIB; + mouse_fd = ts_fd(ts_dev); + return mouse_fd; + } + } + mouse_drv = MOUSE_NONE; + return mouse_fd; + } +#endif /* SDL_INPUT_TSLIB */ + + /* ELO TOUCHSCREEN SUPPORT */ + + if ( mousedrv && (SDL_strcmp(mousedrv, "ELO") == 0) ) { + mouse_fd = open(mousedev, O_RDWR); + if ( mouse_fd >= 0 ) { + if(eloInitController(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ELO touchscreen\n"); +#endif + mouse_drv = MOUSE_ELO; + } + + } + else if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + + return(mouse_fd); + } + + /* STD MICE */ + + if ( mousedev == NULL ) { + /* FIXME someday... allow multiple mice in this driver */ + static const char *ps2mice[] = { + "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL + }; + /* First try to use GPM in repeater mode */ + if ( mouse_fd < 0 ) { + char proto[10]; + if ( gpm_available(proto, SDL_arraysize(proto)) ) { + mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + if ( SDL_strcmp(proto, "msc") == 0 ) { + mouse_drv = MOUSE_MSC; + } else if ( SDL_strcmp(proto, "ps2") == 0 ) { + mouse_drv = MOUSE_PS2; + } else if ( SDL_strcmp(proto, "imps2") == 0 ) { + mouse_drv = MOUSE_IMPS2; + } else if ( SDL_strcmp(proto, "ms") == 0 || + SDL_strcmp(proto, "bare") == 0 ) { + mouse_drv = MOUSE_MS; + } else if ( SDL_strcmp(proto, "bm") == 0 ) { + mouse_drv = MOUSE_BM; + } else { + /* Unknown protocol... */ +#ifdef DEBUG_MOUSE + fprintf(stderr, "GPM mouse using unknown protocol = %s\n", proto); +#endif + close(mouse_fd); + mouse_fd = -1; + } + } +#ifdef DEBUG_MOUSE + if ( mouse_fd >= 0 ) { + fprintf(stderr, "Using GPM mouse, protocol = %s\n", proto); + } +#endif /* DEBUG_MOUSE */ + } + } + /* Now try to use a modern PS/2 mouse */ + for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { + mouse_fd = open(ps2mice[i], O_RDWR, 0); + if (mouse_fd < 0) { + mouse_fd = open(ps2mice[i], O_RDONLY, 0); + } + if (mouse_fd >= 0) { + /* rcg06112001 Attempt to set IMPS/2 mode */ + set_imps2_mode(mouse_fd); + if (detect_imps2(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using IMPS2 mouse\n"); +#endif + mouse_drv = MOUSE_IMPS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using PS2 mouse\n"); +#endif + mouse_drv = MOUSE_PS2; + } + } + } + /* Next try to use a PPC ADB port mouse */ + if ( mouse_fd < 0 ) { + mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ADB mouse\n"); +#endif + mouse_drv = MOUSE_BM; + } + } + } + /* Default to a serial Microsoft mouse */ + if ( mouse_fd < 0 ) { + if ( mousedev == NULL ) { + mousedev = "/dev/mouse"; + } + mouse_fd = open(mousedev, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + struct termios mouse_termios; + + /* Set the sampling speed to 1200 baud */ + tcgetattr(mouse_fd, &mouse_termios); + mouse_termios.c_iflag = IGNBRK | IGNPAR; + mouse_termios.c_oflag = 0; + mouse_termios.c_lflag = 0; + mouse_termios.c_line = 0; + mouse_termios.c_cc[VTIME] = 0; + mouse_termios.c_cc[VMIN] = 1; + mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; + mouse_termios.c_cflag |= CS8; + mouse_termios.c_cflag |= B1200; + tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); + if ( mousedrv && (SDL_strcmp(mousedrv, "PS2") == 0) ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (user specified) PS2 mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_PS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (default) MS mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_MS; + } + } + } + if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + return(mouse_fd); +} + +static int posted = 0; + +void FB_vgamousecallback(int button, int relative, int dx, int dy) +{ + int button_1, button_3; + int button_state; + int state_changed; + int i; + Uint8 state; + + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, relative, dx, dy); + } + + /* Swap button 1 and 3 */ + button_1 = (button & 0x04) >> 2; + button_3 = (button & 0x01) << 2; + button &= ~0x05; + button |= (button_1|button_3); + + /* See what changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ button; + for ( i=0; i<8; ++i ) { + if ( state_changed & (1<<i) ) { + if ( button & (1<<i) ) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i+1, 0, 0); + } + } +} + +/* Handle input from tslib */ +#if SDL_INPUT_TSLIB +static void handle_tslib(_THIS) +{ + struct ts_sample sample; + int button; + + while (ts_read(ts_dev, &sample, 1) > 0) { + button = (sample.pressure > 0) ? 1 : 0; + button <<= 2; /* must report it as button 3 */ + FB_vgamousecallback(button, 0, sample.x, sample.y); + } + return; +} +#endif /* SDL_INPUT_TSLIB */ + +/* For now, use MSC, PS/2, and MS protocols + Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) + */ +static void handle_mouse(_THIS) +{ + static int start = 0; + static unsigned char mousebuf[BUFSIZ]; + static int relative = 1; + + int i, nread; + int button = 0; + int dx = 0, dy = 0; + int packetsize = 0; + int realx, realy; + + /* Figure out the mouse packet size */ + switch (mouse_drv) { + case MOUSE_NONE: + break; /* carry on to read from device and discard it. */ + case MOUSE_MSC: + packetsize = 5; + break; + case MOUSE_IMPS2: + packetsize = 4; + break; + case MOUSE_PS2: + case MOUSE_MS: + case MOUSE_BM: + packetsize = 3; + break; + case MOUSE_ELO: + /* try to read the next packet */ + if(eloReadPosition(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) { + button = (button & 0x01) << 2; + FB_vgamousecallback(button, 0, dx, dy); + } + return; /* nothing left to do */ + case MOUSE_TSLIB: +#if SDL_INPUT_TSLIB + handle_tslib(this); +#endif + return; /* nothing left to do */ + default: + /* Uh oh.. */ + packetsize = 0; + break; + } + + /* Special handling for the quite sensitive ELO controller */ + if (mouse_drv == MOUSE_ELO) { + + } + + /* Read as many packets as possible */ + nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); + if ( nread < 0 ) { + return; + } + + if (mouse_drv == MOUSE_NONE) { + return; /* we're done; just draining the input queue. */ + } + + nread += start; +#ifdef DEBUG_MOUSE + fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); +#endif + + for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { + switch (mouse_drv) { + case MOUSE_NONE: /* shouldn't actually hit this. */ + break; /* just throw everything away. */ + case MOUSE_MSC: + /* MSC protocol has 0x80 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)(mousebuf[i+1]) + + (signed char)(mousebuf[i+3]); + dy = -((signed char)(mousebuf[i+2]) + + (signed char)(mousebuf[i+4])); + break; + case MOUSE_PS2: + /* PS/2 protocol has nothing in high byte */ + if ( (mousebuf[i] & 0xC0) != 0 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2; /*Left*/ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + break; + case MOUSE_IMPS2: + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2 | /*Left*/ + (mousebuf[i] & 0x40) >> 3 | /* 4 */ + (mousebuf[i] & 0x80) >> 3; /* 5 */ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + switch (mousebuf[i+3]&0x0F) { + case 0x0E: /* DX = +1 */ + case 0x02: /* DX = -1 */ + break; + case 0x0F: /* DY = +1 (map button 4) */ + FB_vgamousecallback(button | (1<<3), + 1, 0, 0); + break; + case 0x01: /* DY = -1 (map button 5) */ + FB_vgamousecallback(button | (1<<4), + 1, 0, 0); + break; + } + break; + case MOUSE_MS: + /* Microsoft protocol has 0x40 in high byte */ + if ( (mousebuf[i] & 0x40) != 0x40 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = ((mousebuf[i] & 0x20) >> 3) | + ((mousebuf[i] & 0x10) >> 4); + dx = (signed char)(((mousebuf[i] & 0x03) << 6) | + (mousebuf[i + 1] & 0x3F)); + dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | + (mousebuf[i + 2] & 0x3F)); + break; + case MOUSE_BM: + /* BusMouse protocol has 0xF8 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)mousebuf[i+1]; + dy = -(signed char)mousebuf[i+2]; + break; + default: + /* Uh oh.. */ + dx = 0; + dy = 0; + break; + } + FB_vgamousecallback(button, relative, dx, dy); + } + if ( i < nread ) { + SDL_memcpy(mousebuf, &mousebuf[i], (nread-i)); + start = (nread-i); + } else { + start = 0; + } + return; +} + +/* Handle switching to another VC, returns when our VC is back */ +static void switch_vt_prep(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); + + /* Save the contents of the screen, and go to text mode */ + wait_idle(this); + screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch); + screen_contents = (Uint8 *)SDL_malloc(screen_arealen); + if ( screen_contents ) { + SDL_memcpy(screen_contents, screen->pixels, screen_arealen); + } + FB_SavePaletteTo(this, 256, screen_palette); + ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo); + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); +} +static void switch_vt_done(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + /* Restore graphics mode and the contents of the screen */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo); + FB_RestorePaletteFrom(this, 256, screen_palette); + if ( screen_contents ) { + SDL_memcpy(screen->pixels, screen_contents, screen_arealen); + SDL_free(screen_contents); + screen_contents = NULL; + } + + /* Get updates to the shadow surface while switched away */ + if ( SDL_ShadowSurface ) { + SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0); + } + + SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); +} +static void switch_vt(_THIS, unsigned short which) +{ + struct vt_stat vtstate; + + /* Figure out whether or not we're switching to a new console */ + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || + (which == vtstate.v_active) ) { + return; + } + + /* New console, switch to it */ + SDL_mutexP(hw_lock); + switch_vt_prep(this); + if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, which); + switched_away = 1; + } else { + switch_vt_done(this); + } + SDL_mutexV(hw_lock); +} + +static void handle_keyboard(_THIS) +{ + unsigned char keybuf[BUFSIZ]; + int i, nread; + int pressed; + int scancode; + SDL_keysym keysym; + + nread = read(keyboard_fd, keybuf, BUFSIZ); + for ( i=0; i<nread; ++i ) { + scancode = keybuf[i] & 0x7F; + if ( keybuf[i] & 0x80 ) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + TranslateKey(scancode, &keysym); + /* Handle Ctrl-Alt-FN for vt switch */ + switch (keysym.sym) { + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + case SDLK_F11: + case SDLK_F12: + if ( (SDL_GetModState() & KMOD_CTRL) && + (SDL_GetModState() & KMOD_ALT) ) { + if ( pressed ) { + switch_vt(this, (keysym.sym-SDLK_F1)+1); + } + break; + } + /* Fall through to normal processing */ + default: + posted += SDL_PrivateKeyboard(pressed, &keysym); + break; + } + } +} + +void FB_PumpEvents(_THIS) +{ + fd_set fdset; + int max_fd; + static struct timeval zero; + + do { + if ( switched_away ) { + struct vt_stat vtstate; + + SDL_mutexP(hw_lock); + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) && + vtstate.v_active == current_vt ) { + switched_away = 0; + switch_vt_done(this); + } + SDL_mutexV(hw_lock); + } + + posted = 0; + + FD_ZERO(&fdset); + max_fd = 0; + if ( keyboard_fd >= 0 ) { + FD_SET(keyboard_fd, &fdset); + if ( max_fd < keyboard_fd ) { + max_fd = keyboard_fd; + } + } + if ( mouse_fd >= 0 ) { + FD_SET(mouse_fd, &fdset); + if ( max_fd < mouse_fd ) { + max_fd = mouse_fd; + } + } + if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { + if ( keyboard_fd >= 0 ) { + if ( FD_ISSET(keyboard_fd, &fdset) ) { + handle_keyboard(this); + } + } + if ( mouse_fd >= 0 ) { + if ( FD_ISSET(mouse_fd, &fdset) ) { + handle_mouse(this); + } + } + } + } while ( posted ); +} + +void FB_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the Linux key translation table */ + + /* First get the ascii keys and others not well handled */ + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(i) { + /* These aren't handled by the x86 kernel keymapping (?) */ + case SCANCODE_PRINTSCREEN: + keymap[i] = SDLK_PRINT; + break; + case SCANCODE_BREAK: + keymap[i] = SDLK_BREAK; + break; + case SCANCODE_BREAK_ALTERNATIVE: + keymap[i] = SDLK_PAUSE; + break; + case SCANCODE_LEFTSHIFT: + keymap[i] = SDLK_LSHIFT; + break; + case SCANCODE_RIGHTSHIFT: + keymap[i] = SDLK_RSHIFT; + break; + case SCANCODE_LEFTCONTROL: + keymap[i] = SDLK_LCTRL; + break; + case SCANCODE_RIGHTCONTROL: + keymap[i] = SDLK_RCTRL; + break; + case SCANCODE_RIGHTWIN: + keymap[i] = SDLK_RSUPER; + break; + case SCANCODE_LEFTWIN: + keymap[i] = SDLK_LSUPER; + break; + case SCANCODE_LEFTALT: + keymap[i] = SDLK_LALT; + break; + case SCANCODE_RIGHTALT: + keymap[i] = SDLK_RALT; + break; + case 127: + keymap[i] = SDLK_MENU; + break; + /* this should take care of all standard ascii keys */ + default: + keymap[i] = KVAL(vga_keymap[0][i]); + break; + } + } + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(keymap_temp[i]) { + case K_F1: keymap[i] = SDLK_F1; break; + case K_F2: keymap[i] = SDLK_F2; break; + case K_F3: keymap[i] = SDLK_F3; break; + case K_F4: keymap[i] = SDLK_F4; break; + case K_F5: keymap[i] = SDLK_F5; break; + case K_F6: keymap[i] = SDLK_F6; break; + case K_F7: keymap[i] = SDLK_F7; break; + case K_F8: keymap[i] = SDLK_F8; break; + case K_F9: keymap[i] = SDLK_F9; break; + case K_F10: keymap[i] = SDLK_F10; break; + case K_F11: keymap[i] = SDLK_F11; break; + case K_F12: keymap[i] = SDLK_F12; break; + + case K_DOWN: keymap[i] = SDLK_DOWN; break; + case K_LEFT: keymap[i] = SDLK_LEFT; break; + case K_RIGHT: keymap[i] = SDLK_RIGHT; break; + case K_UP: keymap[i] = SDLK_UP; break; + + case K_P0: keymap[i] = SDLK_KP0; break; + case K_P1: keymap[i] = SDLK_KP1; break; + case K_P2: keymap[i] = SDLK_KP2; break; + case K_P3: keymap[i] = SDLK_KP3; break; + case K_P4: keymap[i] = SDLK_KP4; break; + case K_P5: keymap[i] = SDLK_KP5; break; + case K_P6: keymap[i] = SDLK_KP6; break; + case K_P7: keymap[i] = SDLK_KP7; break; + case K_P8: keymap[i] = SDLK_KP8; break; + case K_P9: keymap[i] = SDLK_KP9; break; + case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; + case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; + case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; + case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; + case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; + case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; + + case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) + keymap[i] = SDLK_LSHIFT; + break; + case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; + case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; + case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) + keymap[i] = SDLK_LCTRL; + break; + case K_CTRLL: keymap[i] = SDLK_LCTRL; break; + case K_CTRLR: keymap[i] = SDLK_RCTRL; break; + case K_ALT: keymap[i] = SDLK_LALT; break; + case K_ALTGR: keymap[i] = SDLK_RALT; break; + + case K_INSERT: keymap[i] = SDLK_INSERT; break; + case K_REMOVE: keymap[i] = SDLK_DELETE; break; + case K_PGUP: keymap[i] = SDLK_PAGEUP; break; + case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; + case K_FIND: keymap[i] = SDLK_HOME; break; + case K_SELECT: keymap[i] = SDLK_END; break; + + case K_NUM: keymap[i] = SDLK_NUMLOCK; break; + case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; + + case K_F13: keymap[i] = SDLK_PRINT; break; + case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; + case K_PAUSE: keymap[i] = SDLK_PAUSE; break; + + case 127: keymap[i] = SDLK_BACKSPACE; break; + + default: break; + } + } +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_LALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_RALT ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h b/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h new file mode 100644 index 0000000..fe8b09c --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbevents_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int FB_OpenKeyboard(_THIS); +extern void FB_CloseKeyboard(_THIS); +extern int FB_OpenMouse(_THIS); +extern void FB_CloseMouse(_THIS); +extern int FB_EnterGraphicsMode(_THIS); +extern int FB_InGraphicsMode(_THIS); +extern void FB_LeaveGraphicsMode(_THIS); + +extern void FB_InitOSKeymap(_THIS); +extern void FB_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h b/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h new file mode 100644 index 0000000..2b01b6b --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbkeys.h @@ -0,0 +1,139 @@ + +/* Scancodes for the Linux framebuffer console + - Taken with thanks from SVGAlib 1.4.0 +*/ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c new file mode 100644 index 0000000..04b90b0 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.c @@ -0,0 +1,280 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbmatrox.h" +#include "matrox_mmio.h" + + +/* Wait for vertical retrace - taken from the XFree86 Matrox driver */ +static void WaitVBL(_THIS) +{ + int count; + + /* find start of retrace */ + mga_waitidle(); + while ( (mga_in8(0x1FDA) & 0x08) ) + ; + while ( !(mga_in8(0x1FDA) & 0x08) ) + ; + /* wait until we're past the start */ + count = mga_in32(0x1E20) + 2; + while ( mga_in32(0x1E20) < count ) + ; +} +static void WaitIdle(_THIS) +{ + mga_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +#if 0 +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + Uint32 fxbndry; + Uint32 ydstlen; + Uint32 fillop; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + switch (dst->format->BytesPerPixel) { + case 1: + color |= (color<<8); + case 2: + color |= (color<<16); + break; + } + + /* Set up the X/Y base coordinates */ + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + /* Set up the X boundaries */ + fxbndry = (dstX | ((dstX+rect->w) << 16)); + + /* Set up the Y boundaries */ + ydstlen = (rect->h | (dstY << 16)); + + /* Set up for color fill operation */ + fillop = MGADWG_TRAP | MGADWG_SOLID | + MGADWG_ARZERO | MGADWG_SGNZERO | MGADWG_SHIFTZERO; + + /* Execute the operations! */ + mga_wait(5); + mga_out32(MGAREG_DWGCTL, fillop | MGADWG_REPLACE); + mga_out32(MGAREG_FCOL, color); + mga_out32(MGAREG_FXBNDRY, fxbndry); + mga_out32(MGAREG_YDSTLEN + MGAREG_EXEC, ydstlen); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int pitch, w, h; + int srcX, srcY; + int dstX, dstY; + Uint32 sign; + Uint32 start, stop; + int skip; + Uint32 blitop; + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + w = dstrect->w; + h = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + pitch = dst->pitch/dst->format->BytesPerPixel; + + /* Set up the blit direction (sign) flags */ + sign = 0; + if ( srcX < dstX ) { + sign |= 1; + } + if ( srcY < dstY ) { + sign |= 4; + srcY += (h - 1); + dstY += (h - 1); + } + + /* Set up the blit source row start, end, and skip (in pixels) */ + stop = start = (srcY * pitch) + srcX; + if ( srcX < dstX ) { + start += (w - 1); + } else { + stop += (w - 1); + } + if ( srcY < dstY ) { + skip = -pitch; + } else { + skip = pitch; + } + + /* Set up the blit operation */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 colorkey; + + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16) | + MGADWG_TRANSC; + + colorkey = src->format->colorkey; + switch (dst->format->BytesPerPixel) { + case 1: + colorkey |= (colorkey<<8); + case 2: + colorkey |= (colorkey<<16); + break; + } + mga_wait(2); + mga_out32(MGAREG_FCOL, colorkey); + mga_out32(MGAREG_BCOL, 0xFFFFFFFF); + } else { + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16); + } + mga_wait(7); + mga_out32(MGAREG_SGN, sign); + mga_out32(MGAREG_AR3, start); + mga_out32(MGAREG_AR0, stop); + mga_out32(MGAREG_AR5, skip); + mga_out32(MGAREG_FXBNDRY, (dstX | ((dstX + w-1) << 16))); + mga_out32(MGAREG_YDSTLEN, (dstY << 16) | h); + mga_out32(MGAREG_DWGCTL + MGAREG_EXEC, blitop); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_MatroxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* The Matrox has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Matrox has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; + /* The Millenium I appears to do the colorkey test a word + at a time, and the transparency is intverted. (?) + */ + if ( card != FB_ACCEL_MATROX_MGA2064W ) { + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; + } + +#if 0 /* Not yet implemented? */ + /* The Matrox G200/G400 has an accelerated alpha blit */ + if ( (card == FB_ACCEL_MATROX_MGAG200) + || (card == FB_ACCEL_MATROX_MGAG400) + ) { + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; + } +#endif +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h new file mode 100644 index 0000000..f7d41b0 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmatrox.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Matrox hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for Matrox acceleration */ +extern void FB_MatroxAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c new file mode 100644 index 0000000..d65f27e --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h new file mode 100644 index 0000000..fbb031d --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c new file mode 100644 index 0000000..eb4b71f --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.c @@ -0,0 +1,222 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbriva.h" +#include "riva_mmio.h" +#include "riva_regs.h" + + +static int FifoEmptyCount = 0; +static int FifoFreeCount = 0; + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + volatile Uint8 *port = (Uint8 *)(mapped_io + PCIO_OFFSET + 0x3DA); + + while ( (*port & 0x08) ) + ; + while ( !(*port & 0x08) ) + ; +} +static void NV3WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x000006B0) & 0x01) ) + ; +} +static void NV4WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x00000700) & 0x01) ) + ; +} + +#if 0 /* Not yet implemented? */ +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif /* Not yet implemented */ + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + int dstW, dstH; + RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET); + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set up the X/Y base coordinates */ + dstW = rect->w; + dstH = rect->h; + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + RIVA_FIFO_FREE(Bitmap, 1); + Bitmap->Color1A = color; + + RIVA_FIFO_FREE(Bitmap, 2); + Bitmap->UnclippedRectangle[0].TopLeft = (dstX << 16) | dstY; + Bitmap->UnclippedRectangle[0].WidthHeight = (dstW << 16) | dstH; + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int srcX, srcY; + int dstX, dstY; + int dstW, dstH; + RivaScreenBlt *Blt = (RivaScreenBlt *)(mapped_io + BLT_OFFSET); + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + dstW = dstrect->w; + dstH = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + + RIVA_FIFO_FREE(Blt, 3); + Blt->TopLeftSrc = (srcY << 16) | srcX; + Blt->TopLeftDst = (dstY << 16) | dstX; + Blt->WidthHeight = (dstH << 16) | dstW; + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_RivaAccel(_THIS, __u32 card) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + switch (card) { + case FB_ACCEL_NV3: + wait_idle = NV3WaitIdle; + break; + case FB_ACCEL_NV4: + wait_idle = NV4WaitIdle; + break; + default: + /* Hmm... FIXME */ + break; + } + FifoEmptyCount = Rop->FifoFree; + + /* The Riva has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Riva has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; +#if 0 /* Not yet implemented? */ + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +#endif + +#if 0 /* Not yet implemented? */ + /* The Riva has an accelerated alpha blit */ + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; +#endif +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h new file mode 100644 index 0000000..c78682e --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbriva.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Riva hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +#ifndef FB_ACCEL_NV3 +#define FB_ACCEL_NV3 27 +#endif +#ifndef FB_ACCEL_NV4 +#define FB_ACCEL_NV4 28 +#endif + +/* Set up the driver for Riva acceleration */ +extern void FB_RivaAccel(_THIS, __u32 card); diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c new file mode 100644 index 0000000..5e58809 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.c @@ -0,0 +1,1982 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Framebuffer console based SDL video driver implementation. +*/ + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#ifndef HAVE_GETPAGESIZE +#include <asm/page.h> /* For definition of PAGE_SIZE */ +#endif + +#include <linux/vt.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" +#include "SDL_fbevents_c.h" +#include "SDL_fb3dfx.h" +#include "SDL_fbmatrox.h" +#include "SDL_fbriva.h" + +/*#define FBCON_DEBUG*/ + +#if defined(i386) && defined(FB_TYPE_VGA_PLANES) +#define VGA16_FBCON_SUPPORT +#include <sys/io.h> /* For ioperm() */ +#ifndef FB_AUX_VGA_PLANES_VGA4 +#define FB_AUX_VGA_PLANES_VGA4 0 +#endif +/* +static inline void outb (unsigned char value, unsigned short port) +{ + __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port)); +} +*/ +#endif /* FB_TYPE_VGA_PLANES */ + +/* A list of video resolutions that we query for (sorted largest to smallest) */ +static const SDL_Rect checkres[] = { + { 0, 0, 1600, 1200 }, /* 16 bpp: 0x11E, or 286 */ + { 0, 0, 1408, 1056 }, /* 16 bpp: 0x19A, or 410 */ + { 0, 0, 1280, 1024 }, /* 16 bpp: 0x11A, or 282 */ + { 0, 0, 1152, 864 }, /* 16 bpp: 0x192, or 402 */ + { 0, 0, 1024, 768 }, /* 16 bpp: 0x117, or 279 */ + { 0, 0, 960, 720 }, /* 16 bpp: 0x18A, or 394 */ + { 0, 0, 800, 600 }, /* 16 bpp: 0x114, or 276 */ + { 0, 0, 768, 576 }, /* 16 bpp: 0x182, or 386 */ + { 0, 0, 720, 576 }, /* PAL */ + { 0, 0, 720, 480 }, /* NTSC */ + { 0, 0, 640, 480 }, /* 16 bpp: 0x111, or 273 */ + { 0, 0, 640, 400 }, /* 8 bpp: 0x100, or 256 */ + { 0, 0, 512, 384 }, + { 0, 0, 320, 240 }, + { 0, 0, 320, 200 } +}; +static const struct { + int xres; + int yres; + int pixclock; + int left; + int right; + int upper; + int lower; + int hslen; + int vslen; + int sync; + int vmode; +} vesa_timings[] = { +#ifdef USE_VESA_TIMINGS /* Only tested on Matrox Millenium I */ + { 640, 400, 39771, 48, 16, 39, 8, 96, 2, 2, 0 }, /* 70 Hz */ + { 640, 480, 39683, 48, 16, 33, 10, 96, 2, 0, 0 }, /* 60 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 24038, 144, 24, 28, 8, 112, 6, 0, 0 }, /* 60 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 15386, 160, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#else + /* You can generate these timings from your XF86Config file using + the 'modeline2fb' perl script included with the fbset package. + These timings were generated for Matrox Millenium I, 15" monitor. + */ + { 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, 2 }, /* 70 Hz */ + { 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, 2 }, /* 72 Hz */ + { 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, 0 }, /* 78 Hz */ + { 640, 400, 31746, 96, 32, 41, 1, 64, 3, 2, 0 }, /* 85 Hz */ + { 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0 }, /* 75 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 20000, 64, 56, 23, 37, 120, 6, 3, 0 }, /* 72 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, 0 }, /* 70 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#endif +}; +enum { + FBCON_ROTATE_NONE = 0, + FBCON_ROTATE_CCW = 90, + FBCON_ROTATE_UD = 180, + FBCON_ROTATE_CW = 270 +}; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* Initialization/Query functions */ +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#endif +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void FB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size); +static void FB_FreeHWSurfaces(_THIS); +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int FB_LockHWSurface(_THIS, SDL_Surface *surface); +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface); +static void FB_WaitVBL(_THIS); +static void FB_WaitIdle(_THIS); +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* Internal palette functions */ +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo); +static void FB_RestorePalette(_THIS); + +/* Shadow buffer functions */ +static FB_bitBlit FB_blit16; +static FB_bitBlit FB_blit16blocked; + +static int SDL_getpagesize(void) +{ +#ifdef HAVE_GETPAGESIZE + return getpagesize(); +#elif defined(PAGE_SIZE) + return PAGE_SIZE; +#else +#error Can not determine system page size. + return 4096; /* this is what it USED to be in Linux... */ +#endif +} + + +/* Small wrapper for mmap() so we can play nicely with no-mmu hosts + * (non-mmu hosts disallow the MAP_SHARED flag) */ + +static void *do_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + void *ret; + ret = mmap(start, length, prot, flags, fd, offset); + if ( ret == (char *)-1 && (flags & MAP_SHARED) ) { + ret = mmap(start, length, prot, + (flags & ~MAP_SHARED) | MAP_PRIVATE, fd, offset); + } + return ret; +} + +/* FB driver bootstrap functions */ + +static int FB_Available(void) +{ + int console = -1; + /* Added check for /fb/0 (devfs) */ + /* but - use environment variable first... if it fails, still check defaults */ + int idx = 0; + const char *SDL_fbdevs[4] = { NULL, "/dev/fb0", "/dev/fb/0", NULL }; + + SDL_fbdevs[0] = SDL_getenv("SDL_FBDEV"); + if( !SDL_fbdevs[0] ) + idx++; + for( ; SDL_fbdevs[idx]; idx++ ) + { + console = open(SDL_fbdevs[idx], O_RDWR, 0); + if ( console >= 0 ) { + close(console); + break; + } + } + return(console >= 0); +} + +static void FB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *FB_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + wait_vbl = FB_WaitVBL; + wait_idle = FB_WaitIdle; + mouse_fd = -1; + keyboard_fd = -1; + + /* Set the function pointers */ + this->VideoInit = FB_VideoInit; + this->ListModes = FB_ListModes; + this->SetVideoMode = FB_SetVideoMode; + this->SetColors = FB_SetColors; + this->UpdateRects = NULL; + this->VideoQuit = FB_VideoQuit; + this->AllocHWSurface = FB_AllocHWSurface; + this->CheckHWBlit = NULL; + this->FillHWRect = NULL; + this->SetHWColorKey = NULL; + this->SetHWAlpha = NULL; + this->LockHWSurface = FB_LockHWSurface; + this->UnlockHWSurface = FB_UnlockHWSurface; + this->FlipHWSurface = FB_FlipHWSurface; + this->FreeHWSurface = FB_FreeHWSurface; + this->SetCaption = NULL; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + this->GrabInput = NULL; + this->GetWMInfo = NULL; + this->InitOSKeymap = FB_InitOSKeymap; + this->PumpEvents = FB_PumpEvents; + + this->free = FB_DeleteDevice; + + return this; +} + +VideoBootStrap FBCON_bootstrap = { + "fbcon", "Linux Framebuffer Console", + FB_Available, FB_CreateDevice +}; + +#define FB_MODES_DB "/etc/fb.modes" + +static int read_fbmodes_line(FILE*f, char* line, int length) +{ + int blank; + char* c; + int i; + + blank=0; + /* find a relevant line */ + do + { + if (!fgets(line,length,f)) + return 0; + c=line; + while(((*c=='\t')||(*c==' '))&&(*c!=0)) + c++; + + if ((*c=='\n')||(*c=='#')||(*c==0)) + blank=1; + else + blank=0; + } + while(blank); + /* remove whitespace at the begining of the string */ + i=0; + do + { + line[i]=c[i]; + i++; + } + while(c[i]!=0); + return 1; +} + +static int read_fbmodes_mode(FILE *f, struct fb_var_screeninfo *vinfo) +{ + char line[1024]; + char option[256]; + + /* Find a "geometry" */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + if (SDL_strncmp(line,"geometry",8)==0) + break; + } + while(1); + + SDL_sscanf(line, "geometry %d %d %d %d %d", &vinfo->xres, &vinfo->yres, + &vinfo->xres_virtual, &vinfo->yres_virtual, &vinfo->bits_per_pixel); + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + SDL_sscanf(line, "timings %d %d %d %d %d %d %d", &vinfo->pixclock, + &vinfo->left_margin, &vinfo->right_margin, &vinfo->upper_margin, + &vinfo->lower_margin, &vinfo->hsync_len, &vinfo->vsync_len); + + vinfo->sync=0; + vinfo->vmode=FB_VMODE_NONINTERLACED; + + /* Parse misc options */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + if (SDL_strncmp(line,"hsync",5)==0) { + SDL_sscanf(line,"hsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_HOR_HIGH_ACT; + } + else if (SDL_strncmp(line,"vsync",5)==0) { + SDL_sscanf(line,"vsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_VERT_HIGH_ACT; + } + else if (SDL_strncmp(line,"csync",5)==0) { + SDL_sscanf(line,"csync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_COMP_HIGH_ACT; + } + else if (SDL_strncmp(line,"extsync",5)==0) { + SDL_sscanf(line,"extsync %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->sync |= FB_SYNC_EXT; + } + else if (SDL_strncmp(line,"laced",5)==0) { + SDL_sscanf(line,"laced %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_INTERLACED; + } + else if (SDL_strncmp(line,"double",6)==0) { + SDL_sscanf(line,"double %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_DOUBLE; + } + } + while(SDL_strncmp(line,"endmode",7)!=0); + + return 1; +} + +static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, + int index, unsigned int *w, unsigned int *h) +{ + int mode_okay; + + mode_okay = 0; + vinfo->bits_per_pixel = (index+1)*8; + vinfo->xres = *w; + vinfo->xres_virtual = *w; + vinfo->yres = *h; + vinfo->yres_virtual = *h; + vinfo->activate = FB_ACTIVATE_TEST; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0 ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n", *w, *h, (index+1)*8, vinfo->xres, vinfo->yres, vinfo->bits_per_pixel); +#endif + if ( (((vinfo->bits_per_pixel+7)/8)-1) == index ) { + *w = vinfo->xres; + *h = vinfo->yres; + mode_okay = 1; + } + } + return mode_okay; +} + +static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h, int check_timings) +{ + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + mode = SDL_modelist[index][SDL_nummodes[index]-1]; + if ( (mode->w == w) && (mode->h == h) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + return(0); + } + } + + /* Only allow a mode if we have a valid timing for it */ + if ( check_timings ) { + int found_timing = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (w == vesa_timings[i].xres) && + (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { + found_timing = 1; + break; + } + } + if ( !found_timing ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); +#endif + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect**)va; + const SDL_Rect *b = *(const SDL_Rect**)vb; + if ( a->h == b->h ) + return b->w - a->w; + else + return b->h - a->h; +} + +static void FB_SortModes(_THIS) +{ + int i; + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } +} + +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const int pagesize = SDL_getpagesize(); + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i, j; + int current_index; + unsigned int current_w; + unsigned int current_h; + const char *SDL_fbdev; + const char *rotation; + FILE *modesdb; + + /* Initialize the library */ + SDL_fbdev = SDL_getenv("SDL_FBDEV"); + if ( SDL_fbdev == NULL ) { + SDL_fbdev = "/dev/fb0"; + } + console_fd = open(SDL_fbdev, O_RDWR, 0); + if ( console_fd < 0 ) { + SDL_SetError("Unable to open %s", SDL_fbdev); + return(-1); + } + +#if !SDL_THREADS_DISABLED + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if ( hw_lock == NULL ) { + SDL_SetError("Unable to create lock mutex"); + FB_VideoQuit(this); + return(-1); + } +#endif + + /* Get the type of video hardware */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.type) { + case FB_TYPE_PACKED_PIXELS: + /* Supported, no worries.. */ + break; +#ifdef VGA16_FBCON_SUPPORT + case FB_TYPE_VGA_PLANES: + /* VGA16 is supported, but that's it */ + if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) { + if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) { + SDL_SetError("No I/O port permissions"); + FB_VideoQuit(this); + return(-1); + } + this->SetVideoMode = FB_SetVGA16Mode; + break; + } + /* Fall through to unsupported case */ +#endif /* VGA16_FBCON_SUPPORT */ + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.visual) { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + case FB_VISUAL_STATIC_PSEUDOCOLOR: + case FB_VISUAL_DIRECTCOLOR: + break; + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + + /* Check if the user wants to disable hardware acceleration */ + { const char *fb_accel; + fb_accel = SDL_getenv("SDL_FBACCEL"); + if ( fb_accel ) { + finfo.accel = SDL_atoi(fb_accel); + } + } + + /* Memory map the device, compensating for buggy PPC mmap() */ + mapped_offset = (((long)finfo.smem_start) - + (((long)finfo.smem_start)&~(pagesize-1))); + mapped_memlen = finfo.smem_len+mapped_offset; + mapped_mem = do_mmap(NULL, mapped_memlen, + PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0); + if ( mapped_mem == (char *)-1 ) { + SDL_SetError("Unable to memory map the video hardware"); + mapped_mem = NULL; + FB_VideoQuit(this); + return(-1); + } + + /* Determine the current screen depth */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console pixel format"); + FB_VideoQuit(this); + return(-1); + } + vformat->BitsPerPixel = vinfo.bits_per_pixel; + if ( vformat->BitsPerPixel < 8 ) { + /* Assuming VGA16, we handle this via a shadow framebuffer */ + vformat->BitsPerPixel = 8; + } + for ( i=0; i<vinfo.red.length; ++i ) { + vformat->Rmask <<= 1; + vformat->Rmask |= (0x00000001<<vinfo.red.offset); + } + for ( i=0; i<vinfo.green.length; ++i ) { + vformat->Gmask <<= 1; + vformat->Gmask |= (0x00000001<<vinfo.green.offset); + } + for ( i=0; i<vinfo.blue.length; ++i ) { + vformat->Bmask <<= 1; + vformat->Bmask |= (0x00000001<<vinfo.blue.offset); + } + saved_vinfo = vinfo; + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* If the I/O registers are available, memory map them so we + can take advantage of any supported hardware acceleration. + */ + vinfo.accel_flags = 0; /* Temporarily reserve registers */ + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo); + if ( finfo.accel && finfo.mmio_len ) { + mapped_iolen = finfo.mmio_len; + mapped_io = do_mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE, + MAP_SHARED, console_fd, mapped_memlen); + if ( mapped_io == (char *)-1 ) { + /* Hmm, failed to memory map I/O registers */ + mapped_io = NULL; + } + } + + rotate = FBCON_ROTATE_NONE; + rotation = SDL_getenv("SDL_VIDEO_FBCON_ROTATION"); + if (rotation != NULL) { + if (SDL_strlen(rotation) == 0) { + shadow_fb = 0; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, no shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "NONE")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, but still using shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "CW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CW; +#ifdef FBCON_DEBUG + printf("Rotating screen clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "CCW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CCW; +#ifdef FBCON_DEBUG + printf("Rotating screen counter clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "UD")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_UD; +#ifdef FBCON_DEBUG + printf("Rotating screen upside down\n"); +#endif + } else { + SDL_SetError("\"%s\" is not a valid value for " + "SDL_VIDEO_FBCON_ROTATION", rotation); + return(-1); + } + } + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + current_w = vinfo.yres; + current_h = vinfo.xres; + } else { + current_w = vinfo.xres; + current_h = vinfo.yres; + } + + /* Query for the list of available video modes */ + current_index = ((vinfo.bits_per_pixel+7)/8)-1; + modesdb = fopen(FB_MODES_DB, "r"); + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + } + if ( SDL_getenv("SDL_FB_BROKEN_MODES") != NULL ) { + FB_AddMode(this, current_index, current_w, current_h, 0); + } else if(modesdb) { + while ( read_fbmodes_mode(modesdb, &vinfo) ) { + for ( i=0; i<NUM_MODELISTS; ++i ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = vinfo.yres; + h = vinfo.xres; + } else { + w = vinfo.xres; + h = vinfo.yres; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 0); + } + } + } + fclose(modesdb); + FB_SortModes(this); + } else { + for ( i=0; i<NUM_MODELISTS; ++i ) { + for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = checkres[j].h; + h = checkres[j].w; + } else { + w = checkres[j].w; + h = checkres[j].h; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 1); + } + } + } + } + + this->info.current_w = current_w; + this->info.current_h = current_h; + this->info.wm_available = 0; + this->info.hw_available = !shadow_fb; + this->info.video_mem = shadow_fb ? 0 : finfo.smem_len/1024; + /* Fill in our hardware acceleration capabilities */ + if ( mapped_io ) { + switch (finfo.accel) { + case FB_ACCEL_MATROX_MGA2064W: + case FB_ACCEL_MATROX_MGA1064SG: + case FB_ACCEL_MATROX_MGA2164W: + case FB_ACCEL_MATROX_MGA2164W_AGP: + case FB_ACCEL_MATROX_MGAG100: + /*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */ + case FB_ACCEL_MATROX_MGAG400: +#ifdef FBACCEL_DEBUG + printf("Matrox hardware accelerator!\n"); +#endif + FB_MatroxAccel(this, finfo.accel); + break; + case FB_ACCEL_3DFX_BANSHEE: +#ifdef FBACCEL_DEBUG + printf("3DFX hardware accelerator!\n"); +#endif + FB_3DfxAccel(this, finfo.accel); + break; + case FB_ACCEL_NV3: + case FB_ACCEL_NV4: +#ifdef FBACCEL_DEBUG + printf("NVidia hardware accelerator!\n"); +#endif + FB_RivaAccel(this, finfo.accel); + break; + default: +#ifdef FBACCEL_DEBUG + printf("Unknown hardware accelerator.\n"); +#endif + break; + } + } + + if (shadow_fb) { + shadow_mem = (char *)SDL_malloc(mapped_memlen); + if (shadow_mem == NULL) { + SDL_SetError("No memory for shadow"); + return (-1); + } + } + + /* Enable mouse and keyboard support */ + if ( FB_OpenKeyboard(this) < 0 ) { + FB_VideoQuit(this); + return(-1); + } + if ( FB_OpenMouse(this) < 0 ) { + const char *sdl_nomouse; + + sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); + if ( ! sdl_nomouse ) { + SDL_SetError("Unable to open mouse"); + FB_VideoQuit(this); + return(-1); + } + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +#ifdef VGA16_FBCON_SUPPORT +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects); +#endif + +#ifdef FBCON_DEBUG +static void print_vinfo(struct fb_var_screeninfo *vinfo) +{ + fprintf(stderr, "Printing vinfo:\n"); + fprintf(stderr, "\txres: %d\n", vinfo->xres); + fprintf(stderr, "\tyres: %d\n", vinfo->yres); + fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual); + fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual); + fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset); + fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset); + fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel); + fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale); + fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd); + fprintf(stderr, "\tactivate: %d\n", vinfo->activate); + fprintf(stderr, "\theight: %d\n", vinfo->height); + fprintf(stderr, "\twidth: %d\n", vinfo->width); + fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags); + fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock); + fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin); + fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin); + fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin); + fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin); + fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len); + fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len); + fprintf(stderr, "\tsync: %d\n", vinfo->sync); + fprintf(stderr, "\tvmode: %d\n", vinfo->vmode); + fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset); + fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset); + fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset); + fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset); +} +static void print_finfo(struct fb_fix_screeninfo *finfo) +{ + fprintf(stderr, "Printing finfo:\n"); + fprintf(stderr, "\tsmem_start = %p\n", (char *)finfo->smem_start); + fprintf(stderr, "\tsmem_len = %d\n", finfo->smem_len); + fprintf(stderr, "\ttype = %d\n", finfo->type); + fprintf(stderr, "\ttype_aux = %d\n", finfo->type_aux); + fprintf(stderr, "\tvisual = %d\n", finfo->visual); + fprintf(stderr, "\txpanstep = %d\n", finfo->xpanstep); + fprintf(stderr, "\typanstep = %d\n", finfo->ypanstep); + fprintf(stderr, "\tywrapstep = %d\n", finfo->ywrapstep); + fprintf(stderr, "\tline_length = %d\n", finfo->line_length); + fprintf(stderr, "\tmmio_start = %p\n", (char *)finfo->mmio_start); + fprintf(stderr, "\tmmio_len = %d\n", finfo->mmio_len); + fprintf(stderr, "\taccel = %d\n", finfo->accel); +} +#endif + +static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + FILE *modesdb; + struct fb_var_screeninfo cinfo; + + matched = 0; + modesdb = fopen(FB_MODES_DB, "r"); + if ( modesdb ) { + /* Parse the mode definition file */ + while ( read_fbmodes_mode(modesdb, &cinfo) ) { + if ( (vinfo->xres == cinfo.xres && vinfo->yres == cinfo.yres) && + (!matched || (vinfo->bits_per_pixel == cinfo.bits_per_pixel)) ) { + vinfo->pixclock = cinfo.pixclock; + vinfo->left_margin = cinfo.left_margin; + vinfo->right_margin = cinfo.right_margin; + vinfo->upper_margin = cinfo.upper_margin; + vinfo->lower_margin = cinfo.lower_margin; + vinfo->hsync_len = cinfo.hsync_len; + vinfo->vsync_len = cinfo.vsync_len; + if ( matched ) { + break; + } + matched = 1; + } + } + fclose(modesdb); + } + return(matched); +} + +static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + int i; + + /* Check for VESA timings */ + matched = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (vinfo->xres == vesa_timings[i].xres) && + (vinfo->yres == vesa_timings[i].yres) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Using VESA timings for %dx%d\n", + vinfo->xres, vinfo->yres); +#endif + if ( vesa_timings[i].pixclock ) { + vinfo->pixclock = vesa_timings[i].pixclock; + } + vinfo->left_margin = vesa_timings[i].left; + vinfo->right_margin = vesa_timings[i].right; + vinfo->upper_margin = vesa_timings[i].upper; + vinfo->lower_margin = vesa_timings[i].lower; + vinfo->hsync_len = vesa_timings[i].hslen; + vinfo->vsync_len = vesa_timings[i].vslen; + vinfo->sync = vesa_timings[i].sync; + vinfo->vmode = vesa_timings[i].vmode; + matched = 1; + break; + } + } + return(matched); +} + +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + current->format->palette->ncolors = 16; + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual finfo:\n"); + print_finfo(&finfo); +#endif + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + current->w = vinfo.xres; + current->h = vinfo.yres; + current->pitch = current->w; + current->pixels = SDL_malloc(current->h*current->pitch); + + /* Set the update rectangle function */ + this->UpdateRects = FB_VGA16Update; + + /* We're done */ + return(current); +} +#endif /* VGA16_FBCON_SUPPORT */ + +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + char *surfaces_mem; + int surfaces_len; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing original vinfo:\n"); + print_vinfo(&vinfo); +#endif + /* Do not use double buffering with shadow buffer */ + if (shadow_fb) { + flags &= ~SDL_DOUBLEBUF; + } + + if ( (vinfo.xres != width) || (vinfo.yres != height) || + (vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF) ) { + vinfo.activate = FB_ACTIVATE_NOW; + vinfo.accel_flags = 0; + vinfo.bits_per_pixel = bpp; + vinfo.xres = width; + vinfo.xres_virtual = width; + vinfo.yres = height; + if ( flags & SDL_DOUBLEBUF ) { + vinfo.yres_virtual = height*2; + } else { + vinfo.yres_virtual = height; + } + vinfo.xoffset = 0; + vinfo.yoffset = 0; + vinfo.red.length = vinfo.red.offset = 0; + vinfo.green.length = vinfo.green.offset = 0; + vinfo.blue.length = vinfo.blue.offset = 0; + vinfo.transp.length = vinfo.transp.offset = 0; + if ( ! choose_fbmodes_mode(&vinfo) ) { + choose_vesa_mode(&vinfo); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing wanted vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( !shadow_fb && + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + vinfo.yres_virtual = height; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't set console screen info"); + return(NULL); + } + } + } else { + int maxheight; + + /* Figure out how much video memory is available */ + if ( flags & SDL_DOUBLEBUF ) { + maxheight = height*2; + } else { + maxheight = height; + } + if ( vinfo.yres_virtual > maxheight ) { + vinfo.yres_virtual = maxheight; + } + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + Rmask = 0; + for ( i=0; i<vinfo.red.length; ++i ) { + Rmask <<= 1; + Rmask |= (0x00000001<<vinfo.red.offset); + } + Gmask = 0; + for ( i=0; i<vinfo.green.length; ++i ) { + Gmask <<= 1; + Gmask |= (0x00000001<<vinfo.green.offset); + } + Bmask = 0; + for ( i=0; i<vinfo.blue.length; ++i ) { + Bmask <<= 1; + Bmask |= (0x00000001<<vinfo.blue.offset); + } + if ( ! SDL_ReallocFormat(current, vinfo.bits_per_pixel, + Rmask, Gmask, Bmask, 0) ) { + return(NULL); + } + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + if (shadow_fb) { + if (vinfo.bits_per_pixel == 16) { + blitFunc = (rotate == FBCON_ROTATE_NONE || + rotate == FBCON_ROTATE_UD) ? + FB_blit16 : FB_blit16blocked; + } else { +#ifdef FBCON_DEBUG + fprintf(stderr, "Init vinfo:\n"); + print_vinfo(&vinfo); +#endif + SDL_SetError("Using software buffer, but no blitter " + "function is available for %d bpp.", + vinfo.bits_per_pixel); + return(NULL); + } + } + + /* Set up the new mode framebuffer */ + current->flags &= SDL_FULLSCREEN; + if (shadow_fb) { + current->flags |= SDL_SWSURFACE; + } else { + current->flags |= SDL_HWSURFACE; + } + current->w = vinfo.xres; + current->h = vinfo.yres; + if (shadow_fb) { + current->pitch = current->w * ((vinfo.bits_per_pixel + 7) / 8); + current->pixels = shadow_mem; + physlinebytes = finfo.line_length; + } else { + current->pitch = finfo.line_length; + current->pixels = mapped_mem+mapped_offset; + } + + /* Set up the information for hardware surfaces */ + surfaces_mem = (char *)current->pixels + + vinfo.yres_virtual*current->pitch; + surfaces_len = (shadow_fb) ? + 0 : (mapped_memlen-(surfaces_mem-mapped_mem)); + + FB_FreeHWSurfaces(this); + FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); + + /* Let the application know we have a hardware palette */ + switch (finfo.visual) { + case FB_VISUAL_PSEUDOCOLOR: + current->flags |= SDL_HWPALETTE; + break; + default: + break; + } + + /* Update for double-buffering, if we can */ + if ( flags & SDL_DOUBLEBUF ) { + if ( vinfo.yres_virtual == (height*2) ) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_address[0] = (char *)current->pixels; + flip_address[1] = (char *)current->pixels+ + current->h*current->pitch; + this->screen = current; + FB_FlipHWSurface(this, current); + this->screen = NULL; + } + } + + /* Set the update rectangle function */ + this->UpdateRects = FB_DirectUpdate; + + /* We're done */ + return(current); +} + +#ifdef FBCON_DEBUG +void FB_DumpHWSurfaces(_THIS) +{ + vidmem_bucket *bucket; + + printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); + printf("\n"); + printf(" Base Size\n"); + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); + if ( bucket->prev ) { + if ( bucket->base != bucket->prev->base+bucket->prev->size ) { + printf("Warning, corrupt bucket list! (prev)\n"); + } + } else { + if ( bucket != &surfaces ) { + printf("Warning, corrupt bucket list! (!prev)\n"); + } + } + if ( bucket->next ) { + if ( bucket->next->base != bucket->base+bucket->size ) { + printf("Warning, corrupt bucket list! (next)\n"); + } + } + } + printf("\n"); +} +#endif + +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size) +{ + vidmem_bucket *bucket; + + surfaces_memtotal = size; + surfaces_memleft = size; + + if ( surfaces_memleft > 0 ) { + bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket)); + if ( bucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + bucket->prev = &surfaces; + bucket->used = 0; + bucket->dirty = 0; + bucket->base = base; + bucket->size = size; + bucket->next = NULL; + } else { + bucket = NULL; + } + + surfaces.prev = NULL; + surfaces.used = 1; + surfaces.dirty = 0; + surfaces.base = screen->pixels; + surfaces.size = (unsigned int)((long)base - (long)surfaces.base); + surfaces.next = bucket; + screen->hwdata = (struct private_hwdata *)&surfaces; + return(0); +} +static void FB_FreeHWSurfaces(_THIS) +{ + vidmem_bucket *bucket, *freeable; + + bucket = surfaces.next; + while ( bucket ) { + freeable = bucket; + bucket = bucket->next; + SDL_free(freeable); + } + surfaces.next = NULL; +} + +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket; + int size; + int extra; + +/* Temporarily, we only allow surfaces the same width as display. + Some blitters require the pitch between two hardware surfaces + to be the same. Others have interesting alignment restrictions. + Until someone who knows these details looks at the code... +*/ +if ( surface->pitch > SDL_VideoSurface->pitch ) { + SDL_SetError("Surface requested wider than screen"); + return(-1); +} +surface->pitch = SDL_VideoSurface->pitch; + size = surface->h * surface->pitch; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocating bucket of %d bytes\n", size); +#endif + + /* Quick check for available mem */ + if ( size > surfaces_memleft ) { + SDL_SetError("Not enough video memory"); + return(-1); + } + + /* Search for an empty bucket big enough */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( ! bucket->used && (size <= bucket->size) ) { + break; + } + } + if ( bucket == NULL ) { + SDL_SetError("Video memory too fragmented"); + return(-1); + } + + /* Create a new bucket for left-over memory */ + extra = (bucket->size - size); + if ( extra ) { + vidmem_bucket *newbucket; + +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); +#endif + newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket)); + if ( newbucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + newbucket->prev = bucket; + newbucket->used = 0; + newbucket->base = bucket->base+size; + newbucket->size = extra; + newbucket->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = newbucket; + } + bucket->next = newbucket; + } + + /* Set the current bucket values and return it! */ + bucket->used = 1; + bucket->size = size; + bucket->dirty = 0; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); +#endif + surfaces_memleft -= size; + surface->flags |= SDL_HWSURFACE; + surface->pixels = bucket->base; + surface->hwdata = (struct private_hwdata *)bucket; + return(0); +} +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket, *freeable; + + /* Look for the bucket in the current list */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( bucket == (vidmem_bucket *)surface->hwdata ) { + break; + } + } + if ( bucket && bucket->used ) { + /* Add the memory back to the total */ +#ifdef DGA_DEBUG + printf("Freeing bucket of %d bytes\n", bucket->size); +#endif + surfaces_memleft += bucket->size; + + /* Can we merge the space with surrounding buckets? */ + bucket->used = 0; + if ( bucket->next && ! bucket->next->used ) { +#ifdef DGA_DEBUG + printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); +#endif + freeable = bucket->next; + bucket->size += bucket->next->size; + bucket->next = bucket->next->next; + if ( bucket->next ) { + bucket->next->prev = bucket; + } + SDL_free(freeable); + } + if ( bucket->prev && ! bucket->prev->used ) { +#ifdef DGA_DEBUG + printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); +#endif + freeable = bucket; + bucket->prev->size += bucket->size; + bucket->prev->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = bucket->prev; + } + SDL_free(freeable); + } + } + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static int FB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( surface == this->screen ) { + SDL_mutexP(hw_lock); + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } else { + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } + return(0); +} +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexV(hw_lock); + } +} + +static void FB_WaitVBL(_THIS) +{ +#ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */ + ioctl(console_fd, FBIOWAITRETRACE, 0); +#endif + return; +} + +static void FB_WaitIdle(_THIS) +{ + return; +} + +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + + /* Wait for vertical retrace and then flip display */ + cache_vinfo.yoffset = flip_page*surface->h; + if ( FB_IsSurfaceBusy(this->screen) ) { + FB_WaitBusySurfaces(this); + } + wait_vbl(this); + if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) { + SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed"); + return(-1); + } + flip_page = !flip_page; + + surface->pixels = flip_address[flip_page]; + return(0); +} + +static void FB_blit16(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w != 0; w--) { + *dst = *src; + src += src_right_delta; + dst++; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes); + src_pos += src_down_delta; + height--; + } +} + +#define BLOCKSIZE_W 32 +#define BLOCKSIZE_H 32 + +static void FB_blit16blocked(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height > 0) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w > 0; w -= BLOCKSIZE_W) { + FB_blit16((Uint8 *)src, + src_right_delta, + src_down_delta, + (Uint8 *)dst, + dst_linebytes, + min(w, BLOCKSIZE_W), + min(height, BLOCKSIZE_H)); + src += src_right_delta * BLOCKSIZE_W; + dst += BLOCKSIZE_W; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H); + src_pos += src_down_delta * BLOCKSIZE_H; + height -= BLOCKSIZE_H; + } +} + +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int width = cache_vinfo.xres; + int height = cache_vinfo.yres; + int bytes_per_pixel = (cache_vinfo.bits_per_pixel + 7) / 8; + int i; + + if (!shadow_fb) { + /* The application is already updating the visible video memory */ + return; + } + + if (cache_vinfo.bits_per_pixel != 16) { + SDL_SetError("Shadow copy only implemented for 16 bpp"); + return; + } + + for (i = 0; i < numrects; i++) { + int x1, y1, x2, y2; + int scr_x1, scr_y1, scr_x2, scr_y2; + int sha_x1, sha_y1; + int shadow_right_delta; /* Address change when moving right in dest */ + int shadow_down_delta; /* Address change when moving down in dest */ + char *src_start; + char *dst_start; + + x1 = rects[i].x; + y1 = rects[i].y; + x2 = x1 + rects[i].w; + y2 = y1 + rects[i].h; + + if (x1 < 0) { + x1 = 0; + } else if (x1 > width) { + x1 = width; + } + if (x2 < 0) { + x2 = 0; + } else if (x2 > width) { + x2 = width; + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > height) { + y1 = height; + } + if (y2 < 0) { + y2 = 0; + } else if (y2 > height) { + y2 = height; + } + if (x2 <= x1 || y2 <= y1) { + continue; + } + + switch (rotate) { + case FBCON_ROTATE_NONE: + sha_x1 = scr_x1 = x1; + sha_y1 = scr_y1 = y1; + scr_x2 = x2; + scr_y2 = y2; + shadow_right_delta = 1; + shadow_down_delta = width; + break; + case FBCON_ROTATE_CCW: + scr_x1 = y1; + scr_y1 = width - x2; + scr_x2 = y2; + scr_y2 = width - x1; + sha_x1 = x2 - 1; + sha_y1 = y1; + shadow_right_delta = width; + shadow_down_delta = -1; + break; + case FBCON_ROTATE_UD: + scr_x1 = width - x2; + scr_y1 = height - y2; + scr_x2 = width - x1; + scr_y2 = height - y1; + sha_x1 = x2 - 1; + sha_y1 = y2 - 1; + shadow_right_delta = -1; + shadow_down_delta = -width; + break; + case FBCON_ROTATE_CW: + scr_x1 = height - y2; + scr_y1 = x1; + scr_x2 = height - y1; + scr_y2 = x2; + sha_x1 = x1; + sha_y1 = y2 - 1; + shadow_right_delta = -width; + shadow_down_delta = 1; + break; + default: + SDL_SetError("Unknown rotation"); + return; + } + + src_start = shadow_mem + + (sha_y1 * width + sha_x1) * bytes_per_pixel; + dst_start = mapped_mem + mapped_offset + scr_y1 * physlinebytes + + scr_x1 * bytes_per_pixel; + + blitFunc((Uint8 *) src_start, + shadow_right_delta, + shadow_down_delta, + (Uint8 *) dst_start, + physlinebytes, + scr_x2 - scr_x1, + scr_y2 - scr_y1); + } +} + +#ifdef VGA16_FBCON_SUPPORT +/* Code adapted with thanks from the XFree86 VGA16 driver! :) */ +#define writeGr(index, value) \ +outb(index, 0x3CE); \ +outb(value, 0x3CF); +#define writeSeq(index, value) \ +outb(index, 0x3C4); \ +outb(value, 0x3C5); + +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *screen; + int width, height, FBPitch, left, i, j, SRCPitch, phase; + register Uint32 m; + Uint8 s1, s2, s3, s4; + Uint32 *src, *srcPtr; + Uint8 *dst, *dstPtr; + + if ( switched_away ) { + return; /* no hardware access */ + } + + screen = this->screen; + FBPitch = screen->w >> 3; + SRCPitch = screen->pitch >> 2; + + writeGr(0x03, 0x00); + writeGr(0x05, 0x00); + writeGr(0x01, 0x00); + writeGr(0x08, 0xFF); + + while(numrects--) { + left = rects->x & ~7; + width = (rects->w + 7) >> 3; + height = rects->h; + src = (Uint32*)screen->pixels + (rects->y * SRCPitch) + (left >> 2); + dst = (Uint8*)mapped_mem + (rects->y * FBPitch) + (left >> 3); + + if((phase = (long)dst & 3L)) { + phase = 4 - phase; + if(phase > width) phase = width; + width -= phase; + } + + while(height--) { + writeSeq(0x02, 1 << 0); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101) << 4); + s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101) << 4); + s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101) << 4); + s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 1); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202) << 4); + s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202) << 4); + s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202) << 4); + s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 2); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404) << 4); + s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404) << 4); + s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404) << 4); + s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 3); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + s1 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808) << 4); + s2 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808) << 4); + s3 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808) << 4); + s4 = (m >> 27) | (m >> 18) | (m >> 9) | m; + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + + dst += FBPitch; + src += SRCPitch; + } + rects++; + } +} +#endif /* VGA16_FBCON_SUPPORT */ + +void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOGETCMAP, &cmap); +} + +void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOPUTCMAP, &cmap); +} + +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo) +{ + int i; + + /* Save hardware palette, if needed */ + if ( finfo->visual == FB_VISUAL_PSEUDOCOLOR ) { + saved_cmaplen = 1<<vinfo->bits_per_pixel; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + } + + /* Added support for FB_VISUAL_DIRECTCOLOR. + With this mode pixel information is passed through the palette... + Neat fading and gamma correction effects can be had by simply + fooling around with the palette instead of changing the pixel + values themselves... Very neat! + + Adam Meyerowitz 1/19/2000 + ameyerow@optonline.com + */ + if ( finfo->visual == FB_VISUAL_DIRECTCOLOR ) { + __u16 new_entries[3*256]; + + /* Save the colormap */ + saved_cmaplen = 256; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + + /* Allocate new identity colormap */ + for ( i=0; i<256; ++i ) { + new_entries[(0*256)+i] = + new_entries[(1*256)+i] = + new_entries[(2*256)+i] = (i<<8)|i; + } + FB_RestorePaletteFrom(this, 256, new_entries); + } +} + +static void FB_RestorePalette(_THIS) +{ + /* Restore the original palette */ + if ( saved_cmap ) { + FB_RestorePaletteFrom(this, saved_cmaplen, saved_cmap); + SDL_free(saved_cmap); + saved_cmap = NULL; + } +} + +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + __u16 r[256]; + __u16 g[256]; + __u16 b[256]; + struct fb_cmap cmap; + + /* Set up the colormap */ + for (i = 0; i < ncolors; i++) { + r[i] = colors[i].r << 8; + g[i] = colors[i].g << 8; + b[i] = colors[i].b << 8; + } + cmap.start = firstcolor; + cmap.len = ncolors; + cmap.red = r; + cmap.green = g; + cmap.blue = b; + cmap.transp = NULL; + + if( (ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) || + !(this->screen->flags & SDL_HWPALETTE) ) { + colors = this->screen->format->palette->colors; + ncolors = this->screen->format->palette->ncolors; + cmap.start = 0; + cmap.len = ncolors; + SDL_memset(r, 0, sizeof(r)); + SDL_memset(g, 0, sizeof(g)); + SDL_memset(b, 0, sizeof(b)); + if ( ioctl(console_fd, FBIOGETCMAP, &cmap) == 0 ) { + for ( i=ncolors-1; i>=0; --i ) { + colors[i].r = (r[i]>>8); + colors[i].g = (g[i]>>8); + colors[i].b = (b[i]>>8); + } + } + return(0); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void FB_VideoQuit(_THIS) +{ + int i, j; + + if ( this->screen ) { + /* Clear screen and tell SDL not to free the pixels */ + + const char *dontClearPixels = SDL_getenv("SDL_FBCON_DONT_CLEAR"); + + /* If the framebuffer is not to be cleared, make sure that we won't + * display the previous frame when disabling double buffering. */ + if ( dontClearPixels && flip_page == 0 ) { + SDL_memcpy(flip_address[0], flip_address[1], this->screen->pitch * this->screen->h); + } + + if ( !dontClearPixels && this->screen->pixels && FB_InGraphicsMode(this) ) { +#if defined(__powerpc__) || defined(__ia64__) /* SIGBUS when using SDL_memset() ?? */ + Uint8 *rowp = (Uint8 *)this->screen->pixels; + int left = this->screen->pitch*this->screen->h; + while ( left-- ) { *rowp++ = 0; } +#else + SDL_memset(this->screen->pixels,0,this->screen->h*this->screen->pitch); +#endif + } + /* This test fails when using the VGA16 shadow memory */ + if ( ((char *)this->screen->pixels >= mapped_mem) && + ((char *)this->screen->pixels < (mapped_mem+mapped_memlen)) ) { + this->screen->pixels = NULL; + } + } + + /* Clear the lock mutex */ + if ( hw_lock ) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } + + /* Clean up defined video modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Clean up the memory bucket list */ + FB_FreeHWSurfaces(this); + + /* Close console and input file descriptors */ + if ( console_fd > 0 ) { + /* Unmap the video framebuffer and I/O registers */ + if ( mapped_mem ) { + munmap(mapped_mem, mapped_memlen); + mapped_mem = NULL; + } + if ( mapped_io ) { + munmap(mapped_io, mapped_iolen); + mapped_io = NULL; + } + + /* Restore the original video mode and palette */ + if ( FB_InGraphicsMode(this) ) { + FB_RestorePalette(this); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo); + } + + /* We're all done with the framebuffer */ + close(console_fd); + console_fd = -1; + } + FB_CloseMouse(this); + FB_CloseKeyboard(this); +} diff --git a/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h new file mode 100644 index 0000000..1443d2b --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/SDL_fbvideo.h @@ -0,0 +1,200 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_fbvideo_h +#define _SDL_fbvideo_h + +#include <sys/types.h> +#include <termios.h> +#include <linux/fb.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#if SDL_INPUT_TSLIB +#include "tslib.h" +#endif + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +typedef void FB_bitBlit( + Uint8 *src_pos, + int src_right_delta, /* pixels, not bytes */ + int src_down_delta, /* pixels, not bytes */ + Uint8 *dst_pos, + int dst_linebytes, + int width, + int height); + +/* This is the structure we use to keep track of video memory */ +typedef struct vidmem_bucket { + struct vidmem_bucket *prev; + int used; + int dirty; + char *base; + unsigned int size; + struct vidmem_bucket *next; +} vidmem_bucket; + +/* Private display data */ +struct SDL_PrivateVideoData { + int console_fd; + struct fb_var_screeninfo cache_vinfo; + struct fb_var_screeninfo saved_vinfo; + int saved_cmaplen; + __u16 *saved_cmap; + + int current_vt; + int saved_vt; + int keyboard_fd; + int saved_kbd_mode; + struct termios saved_kbd_termios; + + int mouse_fd; +#if SDL_INPUT_TSLIB + struct tsdev *ts_dev; +#endif + + char *mapped_mem; + char *shadow_mem; + int mapped_memlen; + int mapped_offset; + char *mapped_io; + long mapped_iolen; + int flip_page; + char *flip_address[2]; + int rotate; + int shadow_fb; /* Tells whether a shadow is being used. */ + FB_bitBlit *blitFunc; + int physlinebytes; /* Length of a line in bytes in physical fb */ + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + vidmem_bucket surfaces; + int surfaces_memtotal; + int surfaces_memleft; + + SDL_mutex *hw_lock; + int switched_away; + struct fb_var_screeninfo screen_vinfo; + Uint32 screen_arealen; + Uint8 *screen_contents; + __u16 screen_palette[3*256]; + + void (*wait_vbl)(_THIS); + void (*wait_idle)(_THIS); +}; +/* Old variable names */ +#define console_fd (this->hidden->console_fd) +#define current_vt (this->hidden->current_vt) +#define saved_vt (this->hidden->saved_vt) +#define keyboard_fd (this->hidden->keyboard_fd) +#define saved_kbd_mode (this->hidden->saved_kbd_mode) +#define saved_kbd_termios (this->hidden->saved_kbd_termios) +#define mouse_fd (this->hidden->mouse_fd) +#if SDL_INPUT_TSLIB +#define ts_dev (this->hidden->ts_dev) +#endif +#define cache_vinfo (this->hidden->cache_vinfo) +#define saved_vinfo (this->hidden->saved_vinfo) +#define saved_cmaplen (this->hidden->saved_cmaplen) +#define saved_cmap (this->hidden->saved_cmap) +#define mapped_mem (this->hidden->mapped_mem) +#define shadow_mem (this->hidden->shadow_mem) +#define mapped_memlen (this->hidden->mapped_memlen) +#define mapped_offset (this->hidden->mapped_offset) +#define mapped_io (this->hidden->mapped_io) +#define mapped_iolen (this->hidden->mapped_iolen) +#define flip_page (this->hidden->flip_page) +#define flip_address (this->hidden->flip_address) +#define rotate (this->hidden->rotate) +#define shadow_fb (this->hidden->shadow_fb) +#define blitFunc (this->hidden->blitFunc) +#define physlinebytes (this->hidden->physlinebytes) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define surfaces (this->hidden->surfaces) +#define surfaces_memtotal (this->hidden->surfaces_memtotal) +#define surfaces_memleft (this->hidden->surfaces_memleft) +#define hw_lock (this->hidden->hw_lock) +#define switched_away (this->hidden->switched_away) +#define screen_vinfo (this->hidden->screen_vinfo) +#define screen_arealen (this->hidden->screen_arealen) +#define screen_contents (this->hidden->screen_contents) +#define screen_palette (this->hidden->screen_palette) +#define wait_vbl (this->hidden->wait_vbl) +#define wait_idle (this->hidden->wait_idle) + +/* Accelerator types that are supported by the driver, but are not + necessarily in the kernel headers on the system we compile on. +*/ +#ifndef FB_ACCEL_MATROX_MGAG400 +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#endif +#ifndef FB_ACCEL_3DFX_BANSHEE +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#endif + +/* These functions are defined in SDL_fbvideo.c */ +extern void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area); +extern void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area); + +/* These are utility functions for working with video surfaces */ + +static __inline__ void FB_AddBusySurface(SDL_Surface *surface) +{ + ((vidmem_bucket *)surface->hwdata)->dirty = 1; +} + +static __inline__ int FB_IsSurfaceBusy(SDL_Surface *surface) +{ + return ((vidmem_bucket *)surface->hwdata)->dirty; +} + +static __inline__ void FB_WaitBusySurfaces(_THIS) +{ + vidmem_bucket *bucket; + + /* Wait for graphic operations to complete */ + wait_idle(this); + + /* Clear all surface dirty bits */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + bucket->dirty = 0; + } +} + +static __inline__ void FB_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y) +{ + *x = (long)((char *)dst->pixels - mapped_mem)%this->screen->pitch; + *y = (long)((char *)dst->pixels - mapped_mem)/this->screen->pitch; + if ( dst == this->screen ) { + *x += this->offset_x; + *y += this->offset_y; + } +} + +#endif /* _SDL_fbvideo_h */ diff --git a/3rdparty/SDL/src/video/fbcon/matrox_mmio.h b/3rdparty/SDL/src/video/fbcon/matrox_mmio.h new file mode 100644 index 0000000..a1cf203 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/matrox_mmio.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* MGA register definitions */ + +#include "matrox_regs.h" + +/* MGA control macros */ + +#define mga_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define mga_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define mga_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define mga_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define mga_wait(space) \ +{ \ + while ( mga_in8(MGAREG_FIFOSTATUS) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define mga_waitidle() \ +{ \ + while ( mga_in32(MGAREG_STATUS) & 0x10000 ) \ + ; \ +} + diff --git a/3rdparty/SDL/src/video/fbcon/matrox_regs.h b/3rdparty/SDL/src/video/fbcon/matrox_regs.h new file mode 100644 index 0000000..d570b0c --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/matrox_regs.h @@ -0,0 +1,376 @@ + +/* + * MGA Millennium (MGA2064W) functions + * MGA Mystique (MGA1064SG) functions + * + * Copyright 1996 The XFree86 Project, Inc. + * + * Authors + * Dirk Hohndel + * hohndel@XFree86.Org + * David Dawes + * dawes@XFree86.Org + * Contributors: + * Guy DESBIEF, Aix-en-provence, France + * g.desbief@aix.pacwan.net + * MGA1064SG Mystique register file + */ + + +#ifndef _MGA_REG_H_ +#define _MGA_REG_H_ + +#define MGAREG_DWGCTL 0x1c00 +#define MGAREG_MACCESS 0x1c04 +/* the following is a mystique only register */ +#define MGAREG_MCTLWTST 0x1c08 +#define MGAREG_ZORG 0x1c0c + +#define MGAREG_PAT0 0x1c10 +#define MGAREG_PAT1 0x1c14 +#define MGAREG_PLNWT 0x1c1c + +#define MGAREG_BCOL 0x1c20 +#define MGAREG_FCOL 0x1c24 + +#define MGAREG_SRC0 0x1c30 +#define MGAREG_SRC1 0x1c34 +#define MGAREG_SRC2 0x1c38 +#define MGAREG_SRC3 0x1c3c + +#define MGAREG_XYSTRT 0x1c40 +#define MGAREG_XYEND 0x1c44 + +#define MGAREG_SHIFT 0x1c50 +/* the following is a mystique only register */ +#define MGAREG_DMAPAD 0x1c54 +#define MGAREG_SGN 0x1c58 +#define MGAREG_LEN 0x1c5c + +#define MGAREG_AR0 0x1c60 +#define MGAREG_AR1 0x1c64 +#define MGAREG_AR2 0x1c68 +#define MGAREG_AR3 0x1c6c +#define MGAREG_AR4 0x1c70 +#define MGAREG_AR5 0x1c74 +#define MGAREG_AR6 0x1c78 + +#define MGAREG_CXBNDRY 0x1c80 +#define MGAREG_FXBNDRY 0x1c84 +#define MGAREG_YDSTLEN 0x1c88 +#define MGAREG_PITCH 0x1c8c + +#define MGAREG_YDST 0x1c90 +#define MGAREG_YDSTORG 0x1c94 +#define MGAREG_YTOP 0x1c98 +#define MGAREG_YBOT 0x1c9c + +#define MGAREG_CXLEFT 0x1ca0 +#define MGAREG_CXRIGHT 0x1ca4 +#define MGAREG_FXLEFT 0x1ca8 +#define MGAREG_FXRIGHT 0x1cac + +#define MGAREG_XDST 0x1cb0 + +#define MGAREG_DR0 0x1cc0 +#define MGAREG_DR1 0x1cc4 +#define MGAREG_DR2 0x1cc8 +#define MGAREG_DR3 0x1ccc + +#define MGAREG_DR4 0x1cd0 +#define MGAREG_DR5 0x1cd4 +#define MGAREG_DR6 0x1cd8 +#define MGAREG_DR7 0x1cdc + +#define MGAREG_DR8 0x1ce0 +#define MGAREG_DR9 0x1ce4 +#define MGAREG_DR10 0x1ce8 +#define MGAREG_DR11 0x1cec + +#define MGAREG_DR12 0x1cf0 +#define MGAREG_DR13 0x1cf4 +#define MGAREG_DR14 0x1cf8 +#define MGAREG_DR15 0x1cfc + +#define MGAREG_SRCORG 0x2cb4 +#define MGAREG_DSTORG 0x2cb8 + +/* add or or this to one of the previous "power registers" to start + the drawing engine */ + +#define MGAREG_EXEC 0x0100 + +#define MGAREG_FIFOSTATUS 0x1e10 +#define MGAREG_STATUS 0x1e14 +#define MGAREG_ICLEAR 0x1e18 +#define MGAREG_IEN 0x1e1c + +#define MGAREG_VCOUNT 0x1e20 + +#define MGAREG_Reset 0x1e40 + +#define MGAREG_OPMODE 0x1e54 + +/* OPMODE register additives */ + +#define MGAOPM_DMA_GENERAL (0x00 << 2) +#define MGAOPM_DMA_BLIT (0x01 << 2) +#define MGAOPM_DMA_VECTOR (0x10 << 2) + +/* DWGCTL register additives */ + +/* Lines */ + +#define MGADWG_LINE_OPEN 0x00 +#define MGADWG_AUTOLINE_OPEN 0x01 +#define MGADWG_LINE_CLOSE 0x02 +#define MGADWG_AUTOLINE_CLOSE 0x03 + +/* Trapezoids */ +#define MGADWG_TRAP 0x04 +#define MGADWG_TEXTURE_TRAP 0x05 + +/* BitBlts */ + +#define MGADWG_BITBLT 0x08 +#define MGADWG_FBITBLT 0x0c +#define MGADWG_ILOAD 0x09 +#define MGADWG_ILOAD_SCALE 0x0d +#define MGADWG_ILOAD_FILTER 0x0f +#define MGADWG_IDUMP 0x0a + +/* atype access to WRAM */ + +#define MGADWG_RPL ( 0x00 << 4 ) +#define MGADWG_RSTR ( 0x01 << 4 ) +#define MGADWG_ZI ( 0x03 << 4 ) +#define MGADWG_BLK ( 0x04 << 4 ) +#define MGADWG_I ( 0x07 << 4 ) + +/* specifies whether bit blits are linear or xy */ +#define MGADWG_LINEAR ( 0x01 << 7 ) + +/* z drawing mode. use MGADWG_NOZCMP for always */ + +#define MGADWG_NOZCMP ( 0x00 << 8 ) +#define MGADWG_ZE ( 0x02 << 8 ) +#define MGADWG_ZNE ( 0x03 << 8 ) +#define MGADWG_ZLT ( 0x04 << 8 ) +#define MGADWG_ZLTE ( 0x05 << 8 ) +#define MGADWG_GT ( 0x06 << 8 ) +#define MGADWG_GTE ( 0x07 << 8 ) + +/* use this to force colour expansion circuitry to do its stuff */ + +#define MGADWG_SOLID ( 0x01 << 11 ) + +/* ar register at zero */ + +#define MGADWG_ARZERO ( 0x01 << 12 ) + +#define MGADWG_SGNZERO ( 0x01 << 13 ) + +#define MGADWG_SHIFTZERO ( 0x01 << 14 ) + +/* See table on 4-43 for bop ALU operations */ + +/* See table on 4-44 for translucidity masks */ + +#define MGADWG_BMONOLEF ( 0x00 << 25 ) +#define MGADWG_BMONOWF ( 0x04 << 25 ) +#define MGADWG_BPLAN ( 0x01 << 25 ) + +/* note that if bfcol is specified and you're doing a bitblt, it causes + a fbitblt to be performed, so check that you obey the fbitblt rules */ + +#define MGADWG_BFCOL ( 0x02 << 25 ) +#define MGADWG_BUYUV ( 0x0e << 25 ) +#define MGADWG_BU32BGR ( 0x03 << 25 ) +#define MGADWG_BU32RGB ( 0x07 << 25 ) +#define MGADWG_BU24BGR ( 0x0b << 25 ) +#define MGADWG_BU24RGB ( 0x0f << 25 ) + +#define MGADWG_REPLACE 0x000C0000 /* From Linux kernel sources */ +#define MGADWG_PATTERN ( 0x01 << 29 ) +#define MGADWG_TRANSC ( 0x01 << 30 ) +#define MGADWG_NOCLIP ( 0x01 << 31 ) +#define MGAREG_MISC_WRITE 0x3c2 +#define MGAREG_MISC_READ 0x3cc +#define MGAREG_MISC_IOADSEL (0x1 << 0) +#define MGAREG_MISC_RAMMAPEN (0x1 << 1) +#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2) +#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2) +#define MGAREG_MISC_VIDEO_DIS (0x1 << 4) +#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5) + +/* MMIO VGA registers */ +#define MGAREG_CRTC_INDEX 0x1fd4 +#define MGAREG_CRTC_DATA 0x1fd5 +#define MGAREG_CRTCEXT_INDEX 0x1fde +#define MGAREG_CRTCEXT_DATA 0x1fdf + + +/* MGA bits for registers PCI_OPTION_REG */ +#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 ) +#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 ) +#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 ) +#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 ) + +#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 ) +#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 ) + +#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 ) +#define MGA1064_OPT_VGA_ION ( 0x01 << 8 ) + +/* MGA registers in PCI config space */ +#define PCI_MGA_INDEX 0x44 +#define PCI_MGA_DATA 0x48 +#define PCI_MGA_OPTION2 0x50 +#define PCI_MGA_OPTION3 0x54 + +#define RAMDAC_OFFSET 0x3c00 + +/* TVP3026 direct registers */ + +#define TVP3026_INDEX 0x00 +#define TVP3026_WADR_PAL 0x00 +#define TVP3026_COL_PAL 0x01 +#define TVP3026_PIX_RD_MSK 0x02 +#define TVP3026_RADR_PAL 0x03 +#define TVP3026_CUR_COL_ADDR 0x04 +#define TVP3026_CUR_COL_DATA 0x05 +#define TVP3026_DATA 0x0a +#define TVP3026_CUR_RAM 0x0b +#define TVP3026_CUR_XLOW 0x0c +#define TVP3026_CUR_XHI 0x0d +#define TVP3026_CUR_YLOW 0x0e +#define TVP3026_CUR_YHI 0x0f + +/* TVP3026 indirect registers */ + +#define TVP3026_SILICON_REV 0x01 +#define TVP3026_CURSOR_CTL 0x06 +#define TVP3026_LATCH_CTL 0x0f +#define TVP3026_TRUE_COLOR_CTL 0x18 +#define TVP3026_MUX_CTL 0x19 +#define TVP3026_CLK_SEL 0x1a +#define TVP3026_PAL_PAGE 0x1c +#define TVP3026_GEN_CTL 0x1d +#define TVP3026_MISC_CTL 0x1e +#define TVP3026_GEN_IO_CTL 0x2a +#define TVP3026_GEN_IO_DATA 0x2b +#define TVP3026_PLL_ADDR 0x2c +#define TVP3026_PIX_CLK_DATA 0x2d +#define TVP3026_MEM_CLK_DATA 0x2e +#define TVP3026_LOAD_CLK_DATA 0x2f +#define TVP3026_KEY_RED_LOW 0x32 +#define TVP3026_KEY_RED_HI 0x33 +#define TVP3026_KEY_GREEN_LOW 0x34 +#define TVP3026_KEY_GREEN_HI 0x35 +#define TVP3026_KEY_BLUE_LOW 0x36 +#define TVP3026_KEY_BLUE_HI 0x37 +#define TVP3026_KEY_CTL 0x38 +#define TVP3026_MCLK_CTL 0x39 +#define TVP3026_SENSE_TEST 0x3a +#define TVP3026_TEST_DATA 0x3b +#define TVP3026_CRC_LSB 0x3c +#define TVP3026_CRC_MSB 0x3d +#define TVP3026_CRC_CTL 0x3e +#define TVP3026_ID 0x3f +#define TVP3026_RESET 0xff + + +/* MGA1064 DAC Register file */ +/* MGA1064 direct registers */ + +#define MGA1064_INDEX 0x00 +#define MGA1064_WADR_PAL 0x00 +#define MGA1064_COL_PAL 0x01 +#define MGA1064_PIX_RD_MSK 0x02 +#define MGA1064_RADR_PAL 0x03 +#define MGA1064_DATA 0x0a + +#define MGA1064_CUR_XLOW 0x0c +#define MGA1064_CUR_XHI 0x0d +#define MGA1064_CUR_YLOW 0x0e +#define MGA1064_CUR_YHI 0x0f + +/* MGA1064 indirect registers */ +#define MGA1064_CURSOR_BASE_ADR_LOW 0x04 +#define MGA1064_CURSOR_BASE_ADR_HI 0x05 +#define MGA1064_CURSOR_CTL 0x06 +#define MGA1064_CURSOR_COL0_RED 0x08 +#define MGA1064_CURSOR_COL0_GREEN 0x09 +#define MGA1064_CURSOR_COL0_BLUE 0x0a + +#define MGA1064_CURSOR_COL1_RED 0x0c +#define MGA1064_CURSOR_COL1_GREEN 0x0d +#define MGA1064_CURSOR_COL1_BLUE 0x0e + +#define MGA1064_CURSOR_COL2_RED 0x010 +#define MGA1064_CURSOR_COL2_GREEN 0x011 +#define MGA1064_CURSOR_COL2_BLUE 0x012 + +#define MGA1064_VREF_CTL 0x018 + +#define MGA1064_MUL_CTL 0x19 +#define MGA1064_MUL_CTL_8bits 0x0 +#define MGA1064_MUL_CTL_15bits 0x01 +#define MGA1064_MUL_CTL_16bits 0x02 +#define MGA1064_MUL_CTL_24bits 0x03 +#define MGA1064_MUL_CTL_32bits 0x04 +#define MGA1064_MUL_CTL_2G8V16bits 0x05 +#define MGA1064_MUL_CTL_G16V16bits 0x06 +#define MGA1064_MUL_CTL_32_24bits 0x07 + +#define MGAGDAC_XVREFCTRL 0x18 +#define MGA1064_PIX_CLK_CTL 0x1a +#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 ) +#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 ) + +#define MGA1064_GEN_CTL 0x1d +#define MGA1064_MISC_CTL 0x1e +#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 ) +#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 ) +#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 ) +#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 ) +#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 ) +#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 ) + +#define MGA1064_GEN_IO_CTL 0x2a +#define MGA1064_GEN_IO_DATA 0x2b +#define MGA1064_SYS_PLL_M 0x2c +#define MGA1064_SYS_PLL_N 0x2d +#define MGA1064_SYS_PLL_P 0x2e +#define MGA1064_SYS_PLL_STAT 0x2f +#define MGA1064_ZOOM_CTL 0x38 +#define MGA1064_SENSE_TST 0x3a + +#define MGA1064_CRC_LSB 0x3c +#define MGA1064_CRC_MSB 0x3d +#define MGA1064_CRC_CTL 0x3e +#define MGA1064_COL_KEY_MSK_LSB 0x40 +#define MGA1064_COL_KEY_MSK_MSB 0x41 +#define MGA1064_COL_KEY_LSB 0x42 +#define MGA1064_COL_KEY_MSB 0x43 +#define MGA1064_PIX_PLLA_M 0x44 +#define MGA1064_PIX_PLLA_N 0x45 +#define MGA1064_PIX_PLLA_P 0x46 +#define MGA1064_PIX_PLLB_M 0x48 +#define MGA1064_PIX_PLLB_N 0x49 +#define MGA1064_PIX_PLLB_P 0x4a +#define MGA1064_PIX_PLLC_M 0x4c +#define MGA1064_PIX_PLLC_N 0x4d +#define MGA1064_PIX_PLLC_P 0x4e + +#define MGA1064_PIX_PLL_STAT 0x4f + +#endif + diff --git a/3rdparty/SDL/src/video/fbcon/riva_mmio.h b/3rdparty/SDL/src/video/fbcon/riva_mmio.h new file mode 100644 index 0000000..e926167 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/riva_mmio.h @@ -0,0 +1,449 @@ +/***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| +\***************************************************************************/ + +#ifndef __RIVA_HW_H__ +#define __RIVA_HW_H__ +#define RIVA_SW_VERSION 0x00010003 + +/* + * Typedefs to force certain sized values. + */ +typedef Uint8 U008; +typedef Uint16 U016; +typedef Uint32 U032; + +/* + * HW access macros. + */ +#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d)) +#define NV_RD08(p,i) (((U008 *)(p))[i]) +#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d)) +#define NV_RD16(p,i) (((U016 *)(p))[(i)/2]) +#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d)) +#define NV_RD32(p,i) (((U032 *)(p))[(i)/4]) +#define VGA_WR08(p,i,d) NV_WR08(p,i,d) +#define VGA_RD08(p,i) NV_RD08(p,i) + +/* + * Define supported architectures. + */ +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +/***************************************************************************\ +* * +* FIFO registers. * +* * +\***************************************************************************/ + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 Rop3; +} RivaRop; +/* + * 8X8 Monochrome pattern. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Shape; + U032 reserved03[0x001]; + U032 Color0; + U032 Color1; + U032 Monochrome[2]; +} RivaPattern; +/* + * Scissor clip rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeft; + U032 WidthHeight; +} RivaClip; +/* + * 2D filled rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; + U032 reserved03[0x03E]; + U032 TopLeft; + U032 WidthHeight; +} RivaRectangle; +/* + * 2D screen-screen BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeftSrc; + U032 TopLeftDst; + U032 WidthHeight; +} RivaScreenBlt; +/* + * 2D pixel BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 TopLeft; + U032 WidthHeight; + U032 WidthHeightIn; + U032 reserved02[0x03C]; + U032 Pixels; +} RivaPixmap; +/* + * Filled rectangle combined with monochrome expand. Useful for glyphs. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 reserved03[(0x040)-1]; + U032 Color1A; + struct + { + U032 TopLeft; + U032 WidthHeight; + } UnclippedRectangle[64]; + U032 reserved04[(0x080)-3]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipB; + U032 Color1B; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClippedRectangle[64]; + U032 reserved05[(0x080)-5]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipC; + U032 Color1C; + U032 WidthHeightC; + U032 PointC; + U032 MonochromeData1C; + U032 reserved06[(0x080)+121]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipD; + U032 Color1D; + U032 WidthHeightInD; + U032 WidthHeightOutD; + U032 PointD; + U032 MonochromeData1D; + U032 reserved07[(0x080)+120]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipE; + U032 Color0E; + U032 Color1E; + U032 WidthHeightInE; + U032 WidthHeightOutE; + U032 PointE; + U032 MonochromeData01E; +} RivaBitmap; +/* + * 3D textured, Z buffered triangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BC]; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 FogColor; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 AlphaTest; + U032 reserved02[0x339]; + U032 FogAndIndex; + U032 Color; + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + float TextureS; + float TextureT; +} RivaTexturedTriangle03; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 ColorKey; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 Blend; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 FogColor; + U032 reserved02[0x39]; + struct + { + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + U032 Color; + U032 Specular; + float TextureS; + float TextureT; + } Vertex[16]; + U032 DrawTriangle3D; +} RivaTexturedTriangle05; +/* + * 2D line. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; /* source color 0304-0307*/ + U032 Reserved02[0x03e]; + struct { /* start aliased methods in array 0400- */ + U032 point0; /* y_x S16_S16 in pixels 0- 3*/ + U032 point1; /* y_x S16_S16 in pixels 4- 7*/ + } Lin[16]; /* end of aliased methods in array -047f*/ + struct { /* start aliased methods in array 0480- */ + U032 point0X; /* in pixels, 0 at left 0- 3*/ + U032 point0Y; /* in pixels, 0 at top 4- 7*/ + U032 point1X; /* in pixels, 0 at left 8- b*/ + U032 point1Y; /* in pixels, 0 at top c- f*/ + } Lin32[8]; /* end of aliased methods in array -04ff*/ + U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/ + struct { /* start aliased methods in array 0580- */ + U032 x; /* in pixels, 0 at left 0- 3*/ + U032 y; /* in pixels, 0 at top 4- 7*/ + } PolyLin32[16]; /* end of aliased methods in array -05ff*/ + struct { /* start aliased methods in array 0600- */ + U032 color; /* source color 0- 3*/ + U032 point; /* y_x S16_S16 in pixels 4- 7*/ + } ColorPolyLin[16]; /* end of aliased methods in array -067f*/ +} RivaLine; +/* + * 2D/3D surfaces + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BE]; + U032 Offset; +} RivaSurface; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Pitch; + U032 RenderBufferOffset; + U032 ZBufferOffset; +} RivaSurface3D; + +/***************************************************************************\ +* * +* Virtualized RIVA H/W interface. * +* * +\***************************************************************************/ + +struct _riva_hw_inst; +struct _riva_hw_state; +/* + * Virtialized chip interface. Makes RIVA 128 and TNT look alike. + */ +typedef struct _riva_hw_inst +{ + /* + * Chip specific settings. + */ + U032 Architecture; + U032 Version; + U032 CrystalFreqKHz; + U032 RamAmountKBytes; + U032 MaxVClockFreqKHz; + U032 RamBandwidthKBytesPerSec; + U032 EnableIRQ; + U032 IO; + U032 VBlankBit; + U032 FifoFreeCount; + U032 FifoEmptyCount; + /* + * Non-FIFO registers. + */ + volatile U032 *PCRTC; + volatile U032 *PRAMDAC; + volatile U032 *PFB; + volatile U032 *PFIFO; + volatile U032 *PGRAPH; + volatile U032 *PEXTDEV; + volatile U032 *PTIMER; + volatile U032 *PMC; + volatile U032 *PRAMIN; + volatile U032 *FIFO; + volatile U032 *CURSOR; + volatile U032 *CURSORPOS; + volatile U032 *VBLANKENABLE; + volatile U032 *VBLANK; + volatile U008 *PCIO; + volatile U008 *PVIO; + volatile U008 *PDIO; + /* + * Common chip functions. + */ + int (*Busy)(struct _riva_hw_inst *); + void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int); + void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*SetStartAddress)(struct _riva_hw_inst *,U032); + void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032); + void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032); + int (*ShowHideCursor)(struct _riva_hw_inst *,int); + void (*LockUnlock)(struct _riva_hw_inst *, int); + /* + * Current extended mode settings. + */ + struct _riva_hw_state *CurrentState; + /* + * FIFO registers. + */ + RivaRop *Rop; + RivaPattern *Patt; + RivaClip *Clip; + RivaPixmap *Pixmap; + RivaScreenBlt *Blt; + RivaBitmap *Bitmap; + RivaLine *Line; + RivaTexturedTriangle03 *Tri03; + RivaTexturedTriangle05 *Tri05; +} RIVA_HW_INST; +/* + * Extended mode state information. + */ +typedef struct _riva_hw_state +{ + U032 bpp; + U032 width; + U032 height; + U032 repaint0; + U032 repaint1; + U032 screen; + U032 pixel; + U032 horiz; + U032 arbitration0; + U032 arbitration1; + U032 vpll; + U032 pllsel; + U032 general; + U032 config; + U032 cursor0; + U032 cursor1; + U032 cursor2; + U032 offset0; + U032 offset1; + U032 offset2; + U032 offset3; + U032 pitch0; + U032 pitch1; + U032 pitch2; + U032 pitch3; +} RIVA_HW_STATE; + +/* + * FIFO Free Count. Should attempt to yield processor if RIVA is busy. + */ + +#define RIVA_FIFO_FREE(hwptr,cnt) \ +{ \ + while (FifoFreeCount < (cnt)) \ + FifoFreeCount = hwptr->FifoFree >> 2; \ + FifoFreeCount -= (cnt); \ +} +#endif /* __RIVA_HW_H__ */ + diff --git a/3rdparty/SDL/src/video/fbcon/riva_regs.h b/3rdparty/SDL/src/video/fbcon/riva_regs.h new file mode 100644 index 0000000..5324562 --- /dev/null +++ b/3rdparty/SDL/src/video/fbcon/riva_regs.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _RIVA_REGS_H +#define _RIVA_REGS_H + +/* This information comes from the XFree86 NVidia hardware driver */ + +/* mapped_io register offsets */ +#define PGRAPH_OFFSET 0x00400000 +#define FIFO_OFFSET 0x00800000 +#define ROP_OFFSET FIFO_OFFSET+0x00000000 +#define CLIP_OFFSET FIFO_OFFSET+0x00002000 +#define PATT_OFFSET FIFO_OFFSET+0x00004000 +#define PIXMAP_OFFSET FIFO_OFFSET+0x00006000 +#define BLT_OFFSET FIFO_OFFSET+0x00008000 +#define BITMAP_OFFSET FIFO_OFFSET+0x0000A000 +#define LINE_OFFSET FIFO_OFFSET+0x0000C000 +#define TRI03_OFFSET FIFO_OFFSET+0x0000E000 +#define PCIO_OFFSET 0x00601000 + +#endif /* _RIVA_REGS_H */ + diff --git a/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c new file mode 100644 index 0000000..86deadc --- /dev/null +++ b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.c @@ -0,0 +1,1287 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Pocket PC GAPI SDL video driver implementation; +Implemented by Dmitry Yakimov - support@activekitten.com +Inspired by http://arisme.free.fr/ports/SDL.php +*/ + +// TODO: copy surface on window when lost focus +// TODO: test buttons rotation +// TODO: test on be300 and HPC ( check WinDib fullscreen keys catching ) +// TODO: test on smartphones +// TODO: windib on SH3 PPC2000 landscape test +// TODO: optimize 8bpp landscape mode + +// there is some problems in runnings apps from a device landscape mode +// due to WinCE bugs. Some works and some - does not. +// TODO: finish Axim Dell X30 and user landscape mode, device landscape mode +// TODO: finish Axim Dell X30 user portrait, device landscape stylus conversion +// TODO: fix running GAPI apps from landscape mode - +// wince goes to portrait mode, but does not update video memory + + +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "../windib/SDL_dibevents_c.h" + +#include "../windib/SDL_gapidibvideo.h" +#include "SDL_gapivideo.h" + +#define gapi this->hidden->gapiInfo + +#define GAPIVID_DRIVER_NAME "gapi" + +#if defined(DEBUG) || defined (_DEBUG) || defined(NDEBUG) +#define REPORT_VIDEO_INFO 1 +#else +#define REPORT_VIDEO_INFO 0 +#endif + +// for testing with GapiEmu +#define USE_GAPI_EMU 0 +#define EMULATE_AXIM_X30 0 +#define WITHOUT_GAPI 0 + +#if USE_GAPI_EMU && !REPORT_VIDEO_INFO +#pragma message("Warning: Using GapiEmu in release build. I assume you'd like to set USE_GAPI_EMU to zero.") +#endif + +#ifndef _T +#define _T(x) L##x +#endif + +#ifndef ASSERT +#define ASSERT(x) +#endif + +// defined and used in SDL_sysevents.c +extern HINSTANCE aygshell; +extern void SDL_UnregisterApp(); +extern int DIB_AddMode(_THIS, int bpp, int w, int h); + +/* Initialization/Query functions */ +static int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GAPI_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface); +static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Windows message handling functions, will not be processed */ +static void GAPI_Activate(_THIS, BOOL active, BOOL minimized); +static void GAPI_RealizePalette(_THIS); +static void GAPI_PaletteChanged(_THIS, HWND window); +static void GAPI_WinPAINT(_THIS, HDC hdc); + +/* etc. */ +static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +static HMODULE g_hGapiLib = 0; +#define LINK(type,name,import) \ + if( g_hGapiLib ) \ + name = (PFN##type)GetProcAddress( g_hGapiLib, _T(import) ); + +static char g_bRawBufferAvailable = 0; + +/* GAPI driver bootstrap functions */ + +/* hi res definitions */ +typedef struct _RawFrameBufferInfo +{ + WORD wFormat; + WORD wBPP; + VOID *pFramePointer; + int cxStride; + int cyStride; + int cxPixels; + int cyPixels; +} RawFrameBufferInfo; + +static struct _RawFrameBufferInfo g_RawFrameBufferInfo = {0}; + +#define GETRAWFRAMEBUFFER 0x00020001 + +#define FORMAT_565 1 +#define FORMAT_555 2 +#define FORMAT_OTHER 3 + +/* Dell Axim x30 hangs when we use GAPI from landscape, + so lets avoid using GxOpenDisplay there via GETGXINFO trick + It seems that GAPI subsystem use the same ExtEscape code. +*/ +#define GETGXINFO 0x00020000 + +typedef struct GXDeviceInfo +{ +long Version; //00 (should filled with 100 before calling ExtEscape) +void * pvFrameBuffer; //04 +unsigned long cbStride; //08 +unsigned long cxWidth; //0c +unsigned long cyHeight; //10 +unsigned long cBPP; //14 +unsigned long ffFormat; //18 +char Unused[0x84-7*4]; +} GXDeviceInfo; + +static int GAPI_Available(void) +{ + // try to use VGA display, even on emulator + HDC hdc = GetDC(NULL); + int result = ExtEscape(hdc, GETRAWFRAMEBUFFER, 0, NULL, sizeof(RawFrameBufferInfo), (char *)&g_RawFrameBufferInfo); + ReleaseDC(NULL, hdc); + g_bRawBufferAvailable = result > 0; + + //My Asus MyPAL 696 reports the RAWFRAMEBUFFER as available, but with a size of 0 x 0 + if(g_RawFrameBufferInfo.cxPixels <= 0 || g_RawFrameBufferInfo.cyPixels <= 0){ + g_bRawBufferAvailable = 0; + } + +#if WITHOUT_GAPI + return g_bRawBufferAvailable; +#endif + +#if USE_GAPI_EMU + g_hGapiLib = LoadLibrary(_T("GAPI_Emu.dll")); + if( !g_hGapiLib ) + { + SDL_SetError("Gapi Emu not found!"); + } + return g_hGapiLib != 0; +#endif + + // try to find gx.dll + g_hGapiLib = LoadLibrary(_T("\\Windows\\gx.dll")); + if( !g_hGapiLib ) + { + g_hGapiLib = LoadLibrary(_T("gx.dll")); + if( !g_hGapiLib ) return g_bRawBufferAvailable; + } + + return(1); +} + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static int GAPI_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<gapi->SDL_nummodes[index]; ++i ) { + mode = gapi->SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = gapi->SDL_nummodes[index]; + gapi->SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(gapi->SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( gapi->SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + gapi->SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + gapi->SDL_modelist[index][next_mode] = mode; + gapi->SDL_modelist[index][next_mode+1] = NULL; + gapi->SDL_nummodes[index]++; + + return(0); +} + +static void GAPI_DeleteDevice(SDL_VideoDevice *device) +{ + if( g_hGapiLib ) + { + FreeLibrary(g_hGapiLib); + g_hGapiLib = 0; + } + SDL_free(device->hidden->gapiInfo); + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GAPI_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + if( !g_hGapiLib && !g_bRawBufferAvailable) + { + if( !GAPI_Available() ) + { + SDL_SetError("GAPI dll is not found and VGA mode is not available!"); + return 0; + } + } + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if(device->hidden){ + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->gapiInfo = (GapiInfo *)SDL_malloc((sizeof(GapiInfo))); + if(device->hidden->gapiInfo == NULL) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + } + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden->gapiInfo, 0, (sizeof *device->hidden->gapiInfo)); + + /* Set the function pointers */ + device->VideoInit = GAPI_VideoInit; + device->ListModes = GAPI_ListModes; + device->SetVideoMode = GAPI_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->CreateYUVOverlay = NULL; + device->SetColors = GAPI_SetColors; + device->UpdateRects = GAPI_UpdateRects; + device->VideoQuit = GAPI_VideoQuit; + device->AllocHWSurface = GAPI_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = GAPI_LockHWSurface; + device->UnlockHWSurface = GAPI_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = GAPI_FreeHWSurface; + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DIB_InitOSKeymap; + device->PumpEvents = DIB_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = GAPI_Activate; + WIN_RealizePalette = GAPI_RealizePalette; + WIN_PaletteChanged = GAPI_PaletteChanged; + WIN_WinPAINT = GAPI_WinPAINT; + HandleMessage = DIB_HandleMessage; + + device->free = GAPI_DeleteDevice; + + /* Load gapi library */ +#define gx device->hidden->gapiInfo->gxFunc + + LINK( GXOpenDisplay, gx.GXOpenDisplay, "?GXOpenDisplay@@YAHPAUHWND__@@K@Z" ) + LINK( GXCloseDisplay, gx.GXCloseDisplay, "?GXCloseDisplay@@YAHXZ" ) + LINK( GXBeginDraw, gx.GXBeginDraw, "?GXBeginDraw@@YAPAXXZ" ) + LINK( GXEndDraw, gx.GXEndDraw, "?GXEndDraw@@YAHXZ" ) + LINK( GXOpenInput, gx.GXOpenInput, "?GXOpenInput@@YAHXZ" ) + LINK( GXCloseInput, gx.GXCloseInput, "?GXCloseInput@@YAHXZ" ) + LINK( GXGetDisplayProperties, gx.GXGetDisplayProperties,"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ" ) + LINK( GXGetDefaultKeys, gx.GXGetDefaultKeys, "?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z" ) + LINK( GXSuspend, gx.GXSuspend, "?GXSuspend@@YAHXZ" ) + LINK( GXResume, gx.GXResume, "?GXResume@@YAHXZ" ) + LINK( GXSetViewport, gx.GXSetViewport, "?GXSetViewport@@YAHKKKK@Z" ) + LINK( GXIsDisplayDRAMBuffer, gx.GXIsDisplayDRAMBuffer, "?GXIsDisplayDRAMBuffer@@YAHXZ" ) + + /* wrong gapi.dll */ + if( !gx.GXOpenDisplay ) + { + if( g_hGapiLib ) + { + FreeLibrary(g_hGapiLib); + g_hGapiLib = 0; + } + } + + if( !gx.GXOpenDisplay && !g_bRawBufferAvailable) + { + SDL_SetError("Error: damaged or unknown gapi.dll!\n"); + GAPI_DeleteDevice(device); + return 0; + } + + return device; +} + +VideoBootStrap GAPI_bootstrap = { + GAPIVID_DRIVER_NAME, "WinCE GAPI video driver", + GAPI_Available, GAPI_CreateDevice +}; + +static void FillStructs(_THIS, BOOL useVga) +{ +#ifdef _ARM_ + WCHAR oemstr[100]; +#endif + /* fill a device properties */ + + if( !useVga ) + { + gapi->gxProperties = gapi->gxFunc.GXGetDisplayProperties(); + gapi->needUpdate = 1; + gapi->hiresFix = 0; + gapi->useVga = 0; + gapi->useGXOpenDisplay = 1; + +#ifdef _ARM_ + /* check some devices and extract addition info */ + SystemParametersInfo( SPI_GETOEMINFO, sizeof( oemstr ), oemstr, 0 ); + + // buggy iPaq38xx + if ((oemstr[12] == 'H') && (oemstr[13] == '3') && (oemstr[14] == '8') && (gapi->gxProperties.cbxPitch > 0)) + { + gapi->videoMem = (PIXEL*)0xac0755a0; + gapi->gxProperties.cbxPitch = -640; + gapi->gxProperties.cbyPitch = 2; + gapi->needUpdate = 0; + } +#if (EMULATE_AXIM_X30 == 0) + // buggy Dell Axim X30 + if( _tcsncmp(oemstr, L"Dell Axim X30", 13) == 0 ) +#endif + { + GXDeviceInfo gxInfo = {0}; + HDC hdc = GetDC(NULL); + int result; + + gxInfo.Version = 100; + result = ExtEscape(hdc, GETGXINFO, 0, NULL, sizeof(gxInfo), (char *)&gxInfo); + if( result > 0 ) + { + gapi->useGXOpenDisplay = 0; + gapi->videoMem = gxInfo.pvFrameBuffer; + gapi->needUpdate = 0; + gapi->gxProperties.cbxPitch = 2; + gapi->gxProperties.cbyPitch = 480; + gapi->gxProperties.cxWidth = gxInfo.cxWidth; + gapi->gxProperties.cyHeight = gxInfo.cyHeight; + gapi->gxProperties.ffFormat = gxInfo.ffFormat; + } + } +#endif + } else + { + gapi->needUpdate = 0; + gapi->hiresFix = 0; + gapi->gxProperties.cBPP = g_RawFrameBufferInfo.wBPP; + gapi->gxProperties.cbxPitch = g_RawFrameBufferInfo.cxStride; + gapi->gxProperties.cbyPitch = g_RawFrameBufferInfo.cyStride; + gapi->gxProperties.cxWidth = g_RawFrameBufferInfo.cxPixels; + gapi->gxProperties.cyHeight = g_RawFrameBufferInfo.cyPixels; + gapi->videoMem = g_RawFrameBufferInfo.pFramePointer; + gapi->useVga = 1; + + switch( g_RawFrameBufferInfo.wFormat ) + { + case FORMAT_565: + gapi->gxProperties.ffFormat = kfDirect565; + break; + case FORMAT_555: + gapi->gxProperties.ffFormat = kfDirect555; + break; + default: + /* unknown pixel format, try define by BPP! */ + switch( g_RawFrameBufferInfo.wBPP ) + { + case 4: + case 8: + gapi->gxProperties.ffFormat = kfDirect; + case 16: + gapi->gxProperties.ffFormat = kfDirect565; + default: + gapi->gxProperties.ffFormat = kfDirect; + break; + } + } + } + + if( gapi->gxProperties.cBPP != 16 ) + { + gapi->gapiOrientation = SDL_ORIENTATION_UP; + } else + if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch > 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_UP; + } else + if( (gapi->gxProperties.cbxPitch > 0) && (gapi->gxProperties.cbyPitch < 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_RIGHT; // ipaq 3660 + } else + if( (gapi->gxProperties.cbxPitch < 0) && (gapi->gxProperties.cbyPitch > 0 )) + { + gapi->gapiOrientation = SDL_ORIENTATION_LEFT; // ipaq 3800 + } +} + +static void GAPI_CreatePalette(int ncolors, SDL_Color *colors) +{ + // Setup a custom color palette + BYTE buffer[ sizeof(LOGPALETTE) + 255 * sizeof(PALETTEENTRY) ]; + int i; + LOGPALETTE* pLogical = (LOGPALETTE*)buffer; + PALETTEENTRY* entries = pLogical->palPalEntry; + HPALETTE hPalette; + HDC hdc; + + for (i = 0; i < ncolors; ++i) + { + // Find intensity by replicating the bit patterns over a byte + entries[i].peRed = colors[i].r; + entries[i].peGreen = colors[i].g; + entries[i].peBlue = colors[i].b; + entries[i].peFlags = 0; + } + + // Create the GDI palette object + pLogical->palVersion = 0x0300; + pLogical->palNumEntries = ncolors; + + hPalette = CreatePalette( pLogical ); + ASSERT(hPalette); + + + // Realize the palette + hdc = GetDC(0); + + SelectPalette( hdc, hPalette, FALSE ); + RealizePalette( hdc ); + + ReleaseDC( 0, hdc ); + DeleteObject( hPalette ); +} + +int GAPI_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i,bpp; + + /* Create the window */ + if ( DIB_CreateWindow(this) < 0 ) { + return(-1); + } + + if( g_hGapiLib ) + { + FillStructs(this, 0); + + // SDL does not supports 2/4bpp mode, so use 16 bpp + bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; + + /* set up normal and landscape mode */ + GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); + GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); + } + + /* add hi-res mode */ + if( g_bRawBufferAvailable && + !((gapi->gxProperties.cxWidth == (unsigned)g_RawFrameBufferInfo.cxPixels) && (gapi->gxProperties.cyHeight == (unsigned)g_RawFrameBufferInfo.cyPixels))) + { + FillStructs(this, 1); + + // SDL does not supports 2/4bpp mode, so use 16 bpp + bpp = gapi->gxProperties.cBPP < 8 ? 16 : gapi->gxProperties.cBPP; + + /* set up normal and landscape mode */ + GAPI_AddMode(this, bpp, gapi->gxProperties.cyHeight, gapi->gxProperties.cxWidth); + GAPI_AddMode(this, bpp, gapi->gxProperties.cxWidth, gapi->gxProperties.cyHeight); + } + + /* Determine the current screen size. + * This is NOT necessarily the size of the Framebuffer or GAPI, as they return + * the displaysize in ORIENTATION_UP */ + this->info.current_w = GetSystemMetrics(SM_CXSCREEN); + this->info.current_h = GetSystemMetrics(SM_CYSCREEN); + + /* Sort the mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( gapi->SDL_nummodes[i] > 0 ) { + SDL_qsort(gapi->SDL_modelist[i], gapi->SDL_nummodes[i], sizeof *gapi->SDL_modelist[i], cmpmodes); + } + } + + vformat->BitsPerPixel = gapi->gxProperties.cBPP < 8 ? 16 : (unsigned char)gapi->gxProperties.cBPP; + + // Get color mask + if (gapi->gxProperties.ffFormat & kfDirect565) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + gapi->videoMode = GAPI_DIRECT_565; + } + else + if (gapi->gxProperties.ffFormat & kfDirect555) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + gapi->videoMode = GAPI_DIRECT_555; + } + else + if ((gapi->gxProperties.ffFormat & kfDirect) && (gapi->gxProperties.cBPP < 8)) { + // We'll perform the conversion + vformat->BitsPerPixel = 16; + vformat->Rmask = 0x0000f800; // 16 bit 565 + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + if (gapi->gxProperties.ffFormat & kfDirectInverted) + gapi->invert = (1 << gapi->gxProperties.cBPP) - 1; + gapi->colorscale = gapi->gxProperties.cBPP < 8 ? 8 - gapi->gxProperties.cBPP : 0; + gapi->videoMode = GAPI_MONO; + } + else + if (gapi->gxProperties.ffFormat & kfPalette) { + gapi->videoMode = GAPI_PALETTE; + } + + /* We're done! */ + return(0); +} + +SDL_Rect **GAPI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(gapi->SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +// return (SDL_Rect **) -1; +} + +SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + Uint32 Rmask, Gmask, Bmask; + DWORD style; + SDL_Rect allScreen; + + if( bpp < 4 ) + { + SDL_SetError("1 bpp and 2 bpp modes is not implemented yet!"); + return 0; + } + + /* Recalculate bitmasks if necessary */ + if (bpp == current->format->BitsPerPixel) { + video = current; + } + else { + switch(bpp) { + case 8: + Rmask = 0; + Gmask = 0; + Bmask = 0; + break; + case 15: + case 16: + /* Default is 565 unless the display is specifically 555 */ + if (gapi->gxProperties.ffFormat & kfDirect555) { + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } + else { + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + SDL_SetError("Unsupported Bits Per Pixel format requested"); + return NULL; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, + 0, 0, bpp, Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + gapi->userOrientation = SDL_ORIENTATION_UP; + gapi->systemOrientation = SDL_ORIENTATION_UP; + video->flags = SDL_FULLSCREEN; /* Clear flags, GAPI supports fullscreen only */ + + /* GAPI or VGA? */ + if( g_hGapiLib ) + { + FillStructs(this, 0); + if( (((unsigned)width != gapi->gxProperties.cxWidth) || ((unsigned)height != gapi->gxProperties.cyHeight)) + && (((unsigned)width != gapi->gxProperties.cyHeight) || ((unsigned)height != gapi->gxProperties.cxWidth))) + FillStructs(this, 1); // gapi is found but we use VGA resolution + } else + FillStructs(this, 1); + + if ( !gapi->needUpdate && !gapi->videoMem) { + SDL_SetError("Couldn't get address of video memory, may be unsupported device or bug"); + return(NULL); + } + + /* detect user landscape mode */ + if( (width > height) && (gapi->gxProperties.cxWidth < gapi->gxProperties.cyHeight)) + gapi->userOrientation = SDL_ORIENTATION_RIGHT; + + if(GetSystemMetrics(SM_CYSCREEN) < GetSystemMetrics(SM_CXSCREEN)) + gapi->systemOrientation = SDL_ORIENTATION_RIGHT; + + gapi->hiresFix = 0; + + /* check hires */ + if(GetSystemMetrics(SM_CXSCREEN) < width && GetSystemMetrics(SM_CYSCREEN) < height) + { + gapi->hiresFix = 1; + } + + switch( gapi->userOrientation ) + { + case SDL_ORIENTATION_UP: + gapi->startOffset = 0; + gapi->dstLineStep = gapi->gxProperties.cbyPitch; + gapi->dstPixelStep = gapi->gxProperties.cbxPitch; + break; + case SDL_ORIENTATION_RIGHT: + switch( gapi->gapiOrientation ) + { + case SDL_ORIENTATION_UP: + case SDL_ORIENTATION_RIGHT: + case SDL_ORIENTATION_LEFT: + if( (gapi->videoMode == GAPI_MONO) ) + gapi->startOffset = -gapi->gxProperties.cbxPitch + 1; // monochrome mode + else + gapi->startOffset = gapi->gxProperties.cbyPitch * (gapi->gxProperties.cyHeight - 1); + + gapi->dstLineStep = gapi->gxProperties.cbxPitch; + gapi->dstPixelStep = -gapi->gxProperties.cbyPitch; + break; + } + } + + video->w = gapi->w = width; + video->h = gapi->h = height; + video->pitch = SDL_CalculatePitch(video); + + /* Small fix for WinCE/Win32 - when activating window + SDL_VideoSurface is equal to zero, so activating code + is not called properly for fullscreen windows because + macros WINDIB_FULLSCREEN uses SDL_VideoSurface + */ + SDL_VideoSurface = video; + + /* GAPI is always fullscreen, title bar is useless */ + style = 0; + + if (!SDL_windowid) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Allocate bitmap */ + if( gapi->buffer ) + { + SDL_free( gapi->buffer ); + gapi->buffer = NULL; + } + gapi->buffer = SDL_malloc(video->h * video->pitch); + video->pixels = gapi->buffer; + + if ( ! gapi->buffer ) { + SDL_SetError("Couldn't allocate buffer for requested mode"); + return(NULL); + } + + SDL_memset(gapi->buffer, 255, video->h * video->pitch); + MoveWindow(SDL_Window, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE); + ShowWindow(SDL_Window, SW_SHOW); + SetForegroundWindow(SDL_Window); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* Open GAPI display */ + if( !gapi->useVga && gapi->useGXOpenDisplay && !gapi->alreadyGXOpened ) + { +#if REPORT_VIDEO_INFO + printf("system display width (orig): %d\n", GetSystemMetrics(SM_CXSCREEN)); + printf("system display height (orig): %d\n", GetSystemMetrics(SM_CYSCREEN)); +#endif + gapi->alreadyGXOpened = 1; + if( !gapi->gxFunc.GXOpenDisplay(SDL_Window, GX_FULLSCREEN) ) + { + SDL_SetError("Couldn't initialize GAPI"); + return(NULL); + } + } + + if(gapi->useVga) + gapi->coordinateTransform = (4 - gapi->systemOrientation + gapi->userOrientation) % 4; + else + gapi->coordinateTransform = gapi->userOrientation; + +#if REPORT_VIDEO_INFO + printf("Video properties:\n"); + printf("display bpp: %d\n", gapi->gxProperties.cBPP); + printf("display width: %d\n", gapi->gxProperties.cxWidth); + printf("display height: %d\n", gapi->gxProperties.cyHeight); + printf("system display width: %d\n", GetSystemMetrics(SM_CXSCREEN)); + printf("system display height: %d\n", GetSystemMetrics(SM_CYSCREEN)); + printf("x pitch: %d\n", gapi->gxProperties.cbxPitch); + printf("y pitch: %d\n", gapi->gxProperties.cbyPitch); + printf("gapi flags: 0x%x\n", gapi->gxProperties.ffFormat); + printf("user orientation: %d\n", gapi->userOrientation); + printf("system orientation: %d\n", gapi->systemOrientation); + printf("gapi orientation: %d\n", gapi->gapiOrientation); + + + if( !gapi->useVga && gapi->useGXOpenDisplay && gapi->needUpdate) + { + gapi->videoMem = gapi->gxFunc.GXBeginDraw(); + gapi->gxFunc.GXEndDraw(); + } + + printf("video memory: 0x%x\n", gapi->videoMem); + printf("need update: %d\n", gapi->needUpdate); + printf("hi-res fix: %d\n", gapi->hiresFix); + printf("VGA is available on the device: %d\n", g_bRawBufferAvailable); + printf("use raw framebuffer: %d\n", gapi->useVga); + printf("video surface bpp: %d\n", video->format->BitsPerPixel); + printf("video surface width: %d\n", video->w); + printf("video surface height: %d\n", video->h); + printf("mouse/arrows transformation angle: %d\n", gapi->coordinateTransform); +#endif + + + /* Blank screen */ + allScreen.x = allScreen.y = 0; + allScreen.w = video->w - 1; + allScreen.h = video->h - 1; + GAPI_UpdateRects(this, 1, &allScreen); + + /* We're done */ + return(video); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int GAPI_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GAPI_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int GAPI_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void GAPI_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int updateLine8to8(_THIS, unsigned char *srcPointer, unsigned char *destPointer, int width, int height, int lines) +{ + if( gapi->dstPixelStep == 1) /* optimized blitting on most devices */ + { + SDL_memcpy(destPointer, srcPointer, width); + return 1; + } else + { + // TODO: read 4 pixels, write DWORD + int step = gapi->dstPixelStep; + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + } + return 1; +} + +/* Video memory is very slow so lets optimize as much as possible */ +static int updateLine16to16(_THIS, PIXEL *srcPointer, PIXEL *destPointer, int width, int height, int lines) +{ + PIXEL *line1, *line2; + int step = gapi->dstPixelStep / 2; + + if( step == 1 ) /* optimized blitting on most devices */ + { + SDL_memcpy(destPointer, srcPointer, width * sizeof(PIXEL)); + return 1; + } + else + { + if( (gapi->gapiOrientation != SDL_ORIENTATION_UP) && + (gapi->userOrientation == SDL_ORIENTATION_UP )) // iPaq 3660/3800 and user orientation up + { + // to prevent data misalignment copy only one line + if( ((((unsigned)destPointer & 3) != 0) && (gapi->gapiOrientation == SDL_ORIENTATION_LEFT)) + || ((((unsigned)destPointer & 3) == 0) && (gapi->gapiOrientation != SDL_ORIENTATION_LEFT)) + || (lines == 1) ) + { + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + return 1; + } + + /* read two lines at the same time, write DWORD */ + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) + while(width--) // iPaq 3800 + { + *(DWORD*)destPointer =(*line2++ << 16) | *line1++; + destPointer += step; + } + else + { + destPointer += gapi->gxProperties.cbyPitch / 2; + + while(width--) // iPaq 3660 + { + *(DWORD*)destPointer =(*line1++ << 16) | *line2++; + destPointer += step; + } + } + return 2; + } else + { + // iPaq 3800 and user orientation landscape + if( gapi->gapiOrientation == SDL_ORIENTATION_LEFT ) + { + int w1; + + // to prevent data misalignment copy only one pixel + if( (((unsigned)destPointer & 3) == 0) && (width > 0)) + { + *destPointer-- = *srcPointer++; + width--; + } + + destPointer--; + + w1 = width / 2; + + while(w1--) + { + DWORD p = *(DWORD*)srcPointer; + *((DWORD*)destPointer) = (p << 16) | (p >> 16); + destPointer -= 2; + srcPointer += 2; + } + + if( width & 1 ) // copy the last pixel + { + destPointer++; + *destPointer = *srcPointer; + } + + return 1; + } + + // modern iPaqs and user orientation landscape + // read two pixels, write DWORD + + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + if( (((unsigned)destPointer & 3) != 0) || (lines == 1) ) + { + while(width--) + { + *destPointer = *srcPointer++; + destPointer += step; + } + return 1; + } + + while(width--) + { + *(DWORD*)destPointer =(*line2++ << 16) | *line1++; + destPointer -= gapi->gxProperties.cbyPitch / 2; + } + return 2; + } + } +} + +// Color component masks for 565 +#define REDMASK (31<<11) +#define GREENMASK (63<<5) +#define BLUEMASK (31) + + +static int updateLine16to4(_THIS, PIXEL *srcPointer, unsigned char *destPointer, int width, int height, int lines, int yNibble, int xNibble) +{ + PIXEL *line1, *line2; + int step = gapi->dstPixelStep; + + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + { + if( yNibble ) // copy bottom half of a line + { + while(width--) + { + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); + destPointer += step; + } + return 1; + } + + // either 1 pixel picture or tail, anyway this is the last line + if( lines == 1 ) + { + while(width--) + { + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); + destPointer += step; + } + return 1; + } + + line1 = srcPointer; + line2 = srcPointer + SDL_VideoSurface->pitch / 2; + + while(width--) + { + PIXEL c1 = *line1++; + PIXEL c2 = *line2++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); + *destPointer = ~((c1 >> 3) + ((c2 >> 3) << 4)); + destPointer += step; + } + return 2; + } else + { + int w1; + w1 = width / 2; + + if( xNibble ) + { + // copy one pixel + PIXEL c1 = *srcPointer++; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0xF0) | ((~(c1 >> 3) & 0xF)); + destPointer++; + } + + while(w1--) + { + PIXEL c1 = *srcPointer; + PIXEL c2 = *(srcPointer + 1); + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + c2 = ((c2 & REDMASK) >> 11) + ((c2 & GREENMASK) >> 5) + (c2 & BLUEMASK); + *destPointer++ = ~((c2 >> 3) + ((c1 >> 3) << 4)); + srcPointer += 2; + } + + // copy tail + if( (width & 1) && !xNibble ) + { + PIXEL c1 = *srcPointer; + c1 = ((c1 & REDMASK) >> 11) + ((c1 & GREENMASK) >> 5) + (c1 & BLUEMASK); + *destPointer = (*destPointer & 0x0F) | ((~(c1 >> 3) << 4)); + } + + return 1; + } +} + +static void GAPI_UpdateRectsMono(_THIS, int numrects, SDL_Rect *rects) +{ + int i, height; + int linesProcessed; + int xNibble, yNibble; + + for (i=0; i<numrects; i++) + { + unsigned char *destPointer; + unsigned char *srcPointer; + + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset - rects[i].y * gapi->gxProperties.cBPP / 8 + rects[i].x * gapi->dstPixelStep; + else + destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].x * gapi->gxProperties.cBPP / 8 + rects[i].y * gapi->dstLineStep; + + srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * 2; + yNibble = rects[i].y & 1; // TODO: only for 4 bpp + xNibble = rects[i].x & 1; + height = rects[i].h; + while (height > 0) + { + switch(gapi->gxProperties.cBPP) + { + case 2: // TODO + case 4: + linesProcessed = updateLine16to4(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height, yNibble, xNibble); + yNibble = 0; + } + height -= linesProcessed; + if( gapi->userOrientation == SDL_ORIENTATION_UP ) + destPointer--; // always fill 1 byte + else destPointer += gapi->dstLineStep; + srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes + } + } +} + +static void GAPI_UpdateRectsColor(_THIS, int numrects, SDL_Rect *rects) +{ + int i, height; + int bytesPerPixel = (gapi->gxProperties.cBPP + 1) / 8; + int linesProcessed; + for (i=0; i<numrects; i++) { + unsigned char *destPointer = (unsigned char*) gapi->videoMem + gapi->startOffset + rects[i].y * gapi->dstLineStep + rects[i].x * gapi->dstPixelStep; + unsigned char *srcPointer = ((unsigned char*) SDL_VideoSurface->pixels) + rects[i].y * SDL_VideoSurface->pitch + rects[i].x * bytesPerPixel; + height = rects[i].h; + +// fprintf(stderr, "Starting rect %dx%d, dst=0x%x, w = %d, h = %d\n", rects[i].w, rects[i].h,destPointer,rects[i].w,rects[i].h); +// fflush(stderr); + linesProcessed = height; + + while (height > 0) { + switch(bytesPerPixel) + { + case 1: + linesProcessed = updateLine8to8(this, srcPointer, (unsigned char *) destPointer, rects[i].w, rects[i].h, height); + break; + case 2: +#pragma warning(disable: 4133) + linesProcessed = updateLine16to16(this, (PIXEL*) srcPointer, destPointer, rects[i].w, rects[i].h, height); + break; + } + height -= linesProcessed; + destPointer += gapi->dstLineStep * linesProcessed; + srcPointer += SDL_VideoSurface->pitch * linesProcessed; // pitch in bytes + } +// fprintf(stderr, "End of rect\n"); +// fflush(stderr); + } +} + + +static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + // we do not want to corrupt video memory + if( gapi->suspended ) return; + + if( gapi->needUpdate ) + gapi->videoMem = gapi->gxFunc.GXBeginDraw(); + + if( gapi->gxProperties.cBPP < 8 ) + GAPI_UpdateRectsMono(this, numrects, rects); + else + GAPI_UpdateRectsColor(this, numrects, rects); + + if( gapi->needUpdate ) + gapi->gxFunc.GXEndDraw(); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void GAPI_VideoQuit(_THIS) +{ + int i, j; + /* Destroy the window and everything associated with it */ + if ( SDL_Window ) + { + if ((g_hGapiLib != 0) && this && gapi && gapi->gxFunc.GXCloseDisplay && !gapi->useVga) + gapi->gxFunc.GXCloseDisplay(); + + if (this->screen->pixels != NULL) + { + SDL_free(this->screen->pixels); + this->screen->pixels = NULL; + } + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } + + DIB_DestroyWindow(this); + SDL_UnregisterApp(); + + SDL_Window = NULL; +#if defined(_WIN32_WCE) + +// Unload wince aygshell library to prevent leak + if( aygshell ) + { + FreeLibrary(aygshell); + aygshell = NULL; + } +#endif + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( gapi->SDL_modelist[i] != NULL ) { + for ( j=0; gapi->SDL_modelist[i][j]; ++j ) + SDL_free(gapi->SDL_modelist[i][j]); + SDL_free(gapi->SDL_modelist[i]); + gapi->SDL_modelist[i] = NULL; + } + } + + } + +} + +static void GAPI_Activate(_THIS, BOOL active, BOOL minimized) +{ + //Nothing to do here (as far as I know) +} + +static void GAPI_RealizePalette(_THIS) +{ + OutputDebugString(TEXT("GAPI_RealizePalette NOT IMPLEMENTED !\r\n")); +} + +static void GAPI_PaletteChanged(_THIS, HWND window) +{ + OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n")); +} + +static void GAPI_WinPAINT(_THIS, HDC hdc) +{ + // draw current offscreen buffer on hdc + + int bpp = 16; // we always use either 8 or 16 bpp internally + HGDIOBJ prevObject; + unsigned short *bitmapData; + HBITMAP hb; + HDC srcDC; + + // Create a DIB + BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0}; + BITMAPINFO* pBMI = (BITMAPINFO*)buffer; + BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader; + DWORD* pColors = (DWORD*)&pBMI->bmiColors; + + // CreateDIBSection does not support 332 pixel format on wce + if( gapi->gxProperties.cBPP == 8 ) return; + + // DIB Header + pHeader->biSize = sizeof(BITMAPINFOHEADER); + pHeader->biWidth = gapi->w; + pHeader->biHeight = -gapi->h; + pHeader->biPlanes = 1; + pHeader->biBitCount = bpp; + pHeader->biCompression = BI_RGB; + pHeader->biSizeImage = (gapi->w * gapi->h * bpp) / 8; + + // Color masks + if( bpp == 16 ) + { + pColors[0] = REDMASK; + pColors[1] = GREENMASK; + pColors[2] = BLUEMASK; + pHeader->biCompression = BI_BITFIELDS; + } + // Create the DIB + hb = CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 ); + + // copy data + // FIXME: prevent misalignment, but I've never seen non aligned width of screen + memcpy(bitmapData, gapi->buffer, pHeader->biSizeImage); + srcDC = CreateCompatibleDC(hdc); + prevObject = SelectObject(srcDC, hb); + + BitBlt(hdc, 0, 0, gapi->w, gapi->h, srcDC, 0, 0, SRCCOPY); + + SelectObject(srcDC, prevObject); + DeleteObject(hb); + DeleteDC(srcDC); +} + +int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + GAPI_CreatePalette(ncolors, colors); + return 1; +} diff --git a/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h new file mode 100644 index 0000000..842d098 --- /dev/null +++ b/3rdparty/SDL/src/video/gapi/SDL_gapivideo.h @@ -0,0 +1,160 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gapivideo_h +#define _SDL_gapivideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../windib/SDL_gapidibvideo.h" + +/* From gx.h, since it's not really C compliant */ + +struct GXDisplayProperties { + DWORD cxWidth; + DWORD cyHeight; // notice lack of 'th' in the word height. + long cbxPitch; // number of bytes to move right one x pixel - can be negative. + long cbyPitch; // number of bytes to move down one y pixel - can be negative. + long cBPP; // # of bits in each pixel + DWORD ffFormat; // format flags. +}; + +struct GXKeyList { + short vkUp; // key for up + POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates. + short vkDown; + POINT ptDown; + short vkLeft; + POINT ptLeft; + short vkRight; + POINT ptRight; + short vkA; + POINT ptA; + short vkB; + POINT ptB; + short vkC; + POINT ptC; + short vkStart; + POINT ptStart; +}; + +typedef int (*PFNGXOpenDisplay)(HWND hWnd, DWORD dwFlags); +typedef int (*PFNGXCloseDisplay)(); +typedef void* (*PFNGXBeginDraw)(); +typedef int (*PFNGXEndDraw)(); +typedef int (*PFNGXOpenInput)(); +typedef int (*PFNGXCloseInput)(); +typedef struct GXDisplayProperties (*PFNGXGetDisplayProperties)(); +typedef struct GXKeyList (*PFNGXGetDefaultKeys)(int iOptions); +typedef int (*PFNGXSuspend)(); +typedef int (*PFNGXResume)(); +typedef int (*PFNGXSetViewport)( DWORD dwTop, DWORD dwHeight, DWORD dwReserved1, DWORD dwReserved2 ); +typedef BOOL (*PFNGXIsDisplayDRAMBuffer)(); + +struct GapiFunc +{ + PFNGXOpenDisplay GXOpenDisplay; + PFNGXCloseDisplay GXCloseDisplay; + PFNGXBeginDraw GXBeginDraw; + PFNGXEndDraw GXEndDraw; + PFNGXOpenInput GXOpenInput; + PFNGXCloseInput GXCloseInput; + PFNGXGetDisplayProperties GXGetDisplayProperties; + PFNGXGetDefaultKeys GXGetDefaultKeys; + PFNGXSuspend GXSuspend; + PFNGXResume GXResume; + PFNGXSetViewport GXSetViewport; + PFNGXIsDisplayDRAMBuffer GXIsDisplayDRAMBuffer; +}; + +#define kfLandscape 0x8 // Screen is rotated 270 degrees +#define kfPalette 0x10 // Pixel values are indexes into a palette +#define kfDirect 0x20 // Pixel values contain actual level information +#define kfDirect555 0x40 // 5 bits each for red, green and blue values in a pixel. +#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel +#define kfDirect888 0x100 // 8 bits each for red, green and blue values in a pixel. +#define kfDirect444 0x200 // 4 red, 4 green, 4 blue +#define kfDirectInverted 0x400 + +#define GX_FULLSCREEN 0x01 // for OpenDisplay() +#define GX_NORMALKEYS 0x02 +#define GX_LANDSCAPEKEYS 0x03 + + +/* GAPI video mode */ +typedef enum { + GAPI_NONE = 0, + GAPI_DIRECT_565, + GAPI_DIRECT_555, + GAPI_MONO, + GAPI_PALETTE +} GAPIVideoMode; + +typedef unsigned short PIXEL; + +/* Private display data + begin with DIB private structure to allow DIB events code sharing +*/ +struct GapiInfo { + /* Rotation which has to be applied to the key (arrow keys) and mouse events measured in quarters of a circle + * counter clockwise */ + int coordinateTransform; + char hiresFix; /* using hires mode without defining hires resource */ + int invert; //TODO this is only written but never read, so it should be removed + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + + // The orientation of the video mode user wants to get + // Probably restricted to UP and RIGHT + SDL_ScreenOrientation userOrientation; + SDL_ScreenOrientation systemOrientation; +// -------------- + int useGXOpenDisplay; /* use GXOpenDispplay */ + int alreadyGXOpened; + int w, h; + // The orientation of GAPI framebuffer. + // Never changes on the same device. + SDL_ScreenOrientation gapiOrientation; + + void *buffer; // may be 8, 16, 24, 32 bpp + PIXEL *videoMem; + BOOL needUpdate; + struct GXKeyList keyList; + struct GapiFunc gxFunc; + struct GXDisplayProperties gxProperties; + GAPIVideoMode videoMode; + int colorscale; + int dstLineStep; // in bytes + int dstPixelStep; // in bytes + int startOffset; // in bytes + int useVga; + int suspended; // do not pu anything into video memory +}; + + + +#endif /* _SDL_gapivideo_h */ diff --git a/3rdparty/SDL/src/video/gem/SDL_gemevents.c b/3rdparty/SDL/src/video/gem/SDL_gemevents.c new file mode 100644 index 0000000..c5a505d --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemevents.c @@ -0,0 +1,375 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM SDL video driver implementation + * inspired from the Dummy SDL driver + * + * Patrice Mandin + * and work from + * Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard + */ + +#include <gem.h> + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gemvideo.h" +#include "SDL_gemevents_c.h" +#include "SDL_gemmouse_c.h" +#include "../ataricommon/SDL_atarikeys.h" /* for keyboard scancodes */ +#include "../ataricommon/SDL_atarievents_c.h" +#include "../ataricommon/SDL_xbiosevents_c.h" +#include "../ataricommon/SDL_ataridevmouse_c.h" + +/* Variables */ + +static unsigned char gem_currentkeyboard[ATARIBIOS_MAXKEYS]; +static unsigned char gem_previouskeyboard[ATARIBIOS_MAXKEYS]; + +/* Functions prototypes */ + +static int do_messages(_THIS, short *message); +static void do_keyboard(short kc, short ks); +static void do_mouse(_THIS, short mx, short my, short mb, short ks); + +/* Functions */ + +void GEM_InitOSKeymap(_THIS) +{ + SDL_memset(gem_currentkeyboard, 0, sizeof(gem_currentkeyboard)); + SDL_memset(gem_previouskeyboard, 0, sizeof(gem_previouskeyboard)); + + /* Mouse init */ + GEM_mouse_relative = SDL_FALSE; + + SDL_Atari_InitInternalKeymap(this); +} + +void GEM_PumpEvents(_THIS) +{ + short prevkc, prevks; + static short maskmouseb=0; + int i; + SDL_keysym keysym; + + SDL_memset(gem_currentkeyboard,0,sizeof(gem_currentkeyboard)); + prevkc = prevks = 0; + + for (;;) + { + int quit, resultat, event_mask, mouse_event; + short buffer[8], kc; + short x2,y2,w2,h2; + short mousex, mousey, mouseb, dummy; + short kstate; + + quit = + mouse_event = + x2=y2=w2=h2 = 0; + + event_mask = MU_MESAG|MU_TIMER|MU_KEYBD|MU_BUTTON; + if (!GEM_fullscreen && (GEM_handle>=0)) { + wind_get (GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2); + event_mask |= MU_M1; + mouse_event = ( (SDL_GetAppState() & SDL_APPMOUSEFOCUS) + == SDL_APPMOUSEFOCUS) ? MO_LEAVE : MO_ENTER; + } + + resultat = evnt_multi( + event_mask, + 0x101,7,maskmouseb, + mouse_event,x2,y2,w2,h2, + 0,0,0,0,0, + buffer, + 10, + &mousex,&mousey,&mouseb,&kstate,&kc,&dummy + ); + + /* Message event ? */ + if (resultat & MU_MESAG) + quit = do_messages(this, buffer); + + /* Keyboard event ? */ + if (resultat & MU_KEYBD) { + if ((prevkc != kc) || (prevks != kstate)) { + do_keyboard(kc,kstate); + } else { + /* Avoid looping, if repeating same key */ + break; + } + } + + /* Mouse entering/leaving window */ + if (resultat & MU_M1) { + if (this->input_grab == SDL_GRAB_OFF) { + /* Switch mouse focus state */ + SDL_PrivateAppActive((mouse_event == MO_ENTER), + SDL_APPMOUSEFOCUS); + } + GEM_CheckMouseMode(this); + } + + /* Mouse button event ? */ + if (resultat & MU_BUTTON) { + do_mouse(this, mousex, mousey, mouseb, kstate); + maskmouseb = mouseb & 7; + } + + /* Timer event ? */ + if ((resultat & MU_TIMER) || quit) + break; + } + + /* Now generate keyboard events */ + for (i=0; i<ATARIBIOS_MAXKEYS; i++) { + /* Key pressed ? */ + if (gem_currentkeyboard[i] && !gem_previouskeyboard[i]) + SDL_PrivateKeyboard(SDL_PRESSED, + SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE)); + + /* Key unpressed ? */ + if (gem_previouskeyboard[i] && !gem_currentkeyboard[i]) + SDL_PrivateKeyboard(SDL_RELEASED, + SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE)); + } + + SDL_memcpy(gem_previouskeyboard,gem_currentkeyboard,sizeof(gem_previouskeyboard)); + + /* Refresh window name ? */ + if (GEM_refresh_name) { + const char *window_name = + (SDL_GetAppState() & SDL_APPACTIVE) + ? GEM_title_name : GEM_icon_name; + if (window_name) { + wind_set(GEM_handle,WF_NAME, + (short)(((unsigned long)window_name)>>16), + (short)(((unsigned long)window_name) & 0xffff), + 0,0); + } + GEM_refresh_name = SDL_FALSE; + } +} + +static int do_messages(_THIS, short *message) +{ + int quit, check_mouse_mode; + short x2,y2,w2,h2; + + quit = check_mouse_mode = 0; + switch (message[0]) { + case WM_CLOSED: + case AP_TERM: + SDL_PrivateQuit(); + quit=1; + break; + case WM_MOVED: + wind_set(message[3],WF_CURRXYWH,message[4],message[5],message[6],message[7]); + break; + case WM_TOPPED: + wind_set(message[3],WF_TOP,message[4],0,0,0); + /* Continue with TOP event processing */ + case WM_ONTOP: + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + if (VDI_setpalette) { + VDI_setpalette(this, VDI_curpalette); + } + check_mouse_mode = 1; + break; + case WM_REDRAW: + if (!GEM_lock_redraw) { + GEM_wind_redraw(this, message[3],&message[4]); + } + break; + case WM_ICONIFY: + case WM_ALLICONIFY: + wind_set(message[3],WF_ICONIFY,message[4],message[5],message[6],message[7]); + /* If we're active, make ourselves inactive */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + /* Send an internal deactivate event */ + SDL_PrivateAppActive(0, SDL_APPACTIVE); + } + /* Update window title */ + if (GEM_refresh_name && GEM_icon_name) { + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_icon_name)>>16),(short)(((unsigned long)GEM_icon_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + } + check_mouse_mode = 1; + break; + case WM_UNICONIFY: + wind_set(message[3],WF_UNICONIFY,message[4],message[5],message[6],message[7]); + /* If we're not active, make ourselves active */ + if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) { + /* Send an internal activate event */ + SDL_PrivateAppActive(1, SDL_APPACTIVE); + } + if (GEM_refresh_name && GEM_title_name) { + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + } + check_mouse_mode = 1; + break; + case WM_SIZED: + wind_set (message[3], WF_CURRXYWH, message[4], message[5], message[6], message[7]); + wind_get (message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2); + GEM_win_fulled = SDL_FALSE; /* Cancel maximized flag */ + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers resized */ + SDL_PrivateResize(w2, h2); + break; + case WM_FULLED: + { + short x,y,w,h; + + if (GEM_win_fulled) { + wind_get (message[3], WF_PREVXYWH, &x, &y, &w, &h); + GEM_win_fulled = SDL_FALSE; + } else { + x = GEM_desk_x; + y = GEM_desk_y; + w = GEM_desk_w; + h = GEM_desk_h; + GEM_win_fulled = SDL_TRUE; + } + wind_set (message[3], WF_CURRXYWH, x, y, w, h); + wind_get (message[3], WF_WORKXYWH, &x2, &y2, &w2, &h2); + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers resized */ + SDL_PrivateResize(w2, h2); + } + break; + case WM_BOTTOMED: + wind_set(message[3],WF_BOTTOM,0,0,0,0); + /* Continue with BOTTOM event processing */ + case WM_UNTOPPED: + SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + if (VDI_setpalette) { + VDI_setpalette(this, VDI_oldpalette); + } + check_mouse_mode = 1; + break; + } + + if (check_mouse_mode) { + GEM_CheckMouseMode(this); + } + + return quit; +} + +static void do_keyboard(short kc, short ks) +{ + int scancode; + + if (kc) { + scancode=(kc>>8) & (ATARIBIOS_MAXKEYS-1); + gem_currentkeyboard[scancode]=0xFF; + } + + /* Read special keys */ + if (ks & K_RSHIFT) + gem_currentkeyboard[SCANCODE_RIGHTSHIFT]=0xFF; + if (ks & K_LSHIFT) + gem_currentkeyboard[SCANCODE_LEFTSHIFT]=0xFF; + if (ks & K_CTRL) + gem_currentkeyboard[SCANCODE_LEFTCONTROL]=0xFF; + if (ks & K_ALT) + gem_currentkeyboard[SCANCODE_LEFTALT]=0xFF; +} + +static void do_mouse(_THIS, short mx, short my, short mb, short ks) +{ + static short prevmousex=0, prevmousey=0, prevmouseb=0; + short x2, y2, w2, h2; + + /* Don't return mouse events if out of window */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS)==0) { + return; + } + + /* Retrieve window coords, and generate mouse events accordingly */ + x2 = y2 = 0; + w2 = VDI_w; + h2 = VDI_h; + if ((!GEM_fullscreen) && (GEM_handle>=0)) { + wind_get (GEM_handle, WF_WORKXYWH, &x2, &y2, &w2, &h2); + + /* Do not generate mouse button event if out of window working area */ + if ((mx<x2) || (mx>=x2+w2) || (my<y2) || (my>=y2+h2)) { + mb=prevmouseb; + } + } + + /* Mouse motion ? */ + if (GEM_mouse_relative) { + if (GEM_usedevmouse) { + SDL_AtariDevMouse_PostMouseEvents(this, SDL_FALSE); + } else { + SDL_AtariXbios_PostMouseEvents(this, SDL_FALSE); + } + } else { + if ((prevmousex!=mx) || (prevmousey!=my)) { + int posx, posy; + + /* Give mouse position relative to window position */ + posx = mx - x2; + if (posx<0) posx = 0; + if (posx>w2) posx = w2-1; + posy = my - y2; + if (posy<0) posy = 0; + if (posy>h2) posy = h2-1; + + SDL_PrivateMouseMotion(0, 0, posx, posy); + } + prevmousex = mx; + prevmousey = my; + } + + /* Mouse button ? */ + if (prevmouseb!=mb) { + int i; + + for (i=0;i<3;i++) { + int curbutton, prevbutton; + + curbutton = mb & (1<<i); + prevbutton = prevmouseb & (1<<i); + + if (curbutton && !prevbutton) { + SDL_PrivateMouseButton(SDL_PRESSED, i+1, 0, 0); + } + if (!curbutton && prevbutton) { + SDL_PrivateMouseButton(SDL_RELEASED, i+1, 0, 0); + } + } + prevmouseb = mb; + } + + /* Read special keys */ + if (ks & K_RSHIFT) + gem_currentkeyboard[SCANCODE_RIGHTSHIFT]=0xFF; + if (ks & K_LSHIFT) + gem_currentkeyboard[SCANCODE_LEFTSHIFT]=0xFF; + if (ks & K_CTRL) + gem_currentkeyboard[SCANCODE_LEFTCONTROL]=0xFF; + if (ks & K_ALT) + gem_currentkeyboard[SCANCODE_LEFTALT]=0xFF; +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h b/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h new file mode 100644 index 0000000..7d5d9b3 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemevents_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gemvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) */ + +extern void GEM_InitOSKeymap(_THIS); +extern void GEM_PumpEvents(_THIS); + +/* end of SDL_gemevents_c.h */ + diff --git a/3rdparty/SDL/src/video/gem/SDL_gemmouse.c b/3rdparty/SDL/src/video/gem/SDL_gemmouse.c new file mode 100644 index 0000000..c876cff --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemmouse.c @@ -0,0 +1,205 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM Mouse manager + * + * Patrice Mandin + */ + +#include <gem.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gemmouse_c.h" +#include "SDL_gemvideo.h" +#include "../ataricommon/SDL_xbiosevents_c.h" + +/* Defines */ + +/*#define DEBUG_VIDEO_GEM 1*/ + +#define MAXCURWIDTH 16 +#define MAXCURHEIGHT 16 + +void GEM_FreeWMCursor(_THIS, WMcursor *cursor) +{ +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: free cursor\n"); +#endif + + if (cursor == NULL) + return; + + graf_mouse(ARROW, NULL); + + if (cursor->mform_p != NULL) + SDL_free(cursor->mform_p); + + SDL_free(cursor); +} + +WMcursor *GEM_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + MFORM *new_mform; + int i; + +#ifdef DEBUG_VIDEO_GEM + Uint16 *data1, *mask1; + + printf("sdl:video:gem: create cursor\n"); +#endif + + /* Check the size */ + if ( (w > MAXCURWIDTH) || (h > MAXCURHEIGHT) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + MAXCURWIDTH, MAXCURHEIGHT); + return(NULL); + } + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + /* Allocate mform */ + new_mform = (MFORM *)SDL_malloc(sizeof(MFORM)); + if (new_mform == NULL) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + + cursor->mform_p = new_mform; + + new_mform->mf_xhot = hot_x; + new_mform->mf_yhot = hot_y; + new_mform->mf_nplanes = 1; + new_mform->mf_fg = 0; + new_mform->mf_bg = 1; + + for (i=0;i<MAXCURHEIGHT;i++) { + new_mform->mf_mask[i]=0; + new_mform->mf_data[i]=0; +#ifdef DEBUG_VIDEO_GEM + data1 = (Uint16 *) &data[i<<1]; + mask1 = (Uint16 *) &mask[i<<1]; + printf("sdl:video:gem: source: line %d: data=0x%04x, mask=0x%04x\n", + i, data1[i], mask1[i]); +#endif + } + + if (w<=8) { + for (i=0;i<h;i++) { + new_mform->mf_mask[i]= mask[i]<<8; + new_mform->mf_data[i]= data[i]<<8; + } + } else { + for (i=0;i<h;i++) { + new_mform->mf_mask[i]= (mask[i<<1]<<8) | mask[(i<<1)+1]; + new_mform->mf_data[i]= (data[i<<1]<<8) | data[(i<<1)+1]; + } + } + +#ifdef DEBUG_VIDEO_GEM + for (i=0; i<h ;i++) { + printf("sdl:video:gem: cursor: line %d: data=0x%04x, mask=0x%04x\n", + i, new_mform->mf_data[i], new_mform->mf_mask[i]); + } + + printf("sdl:video:gem: CreateWMCursor(): done\n"); +#endif + + return cursor; +} + +int GEM_ShowWMCursor(_THIS, WMcursor *cursor) +{ + GEM_cursor = cursor; + + GEM_CheckMouseMode(this); + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: ShowWMCursor(0x%08x)\n", (long) cursor); +#endif + + return 1; +} + +#if 0 +void GEM_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + /* This seems to work only on AES 3.4 (Falcon) */ + + EVNTREC warpevent; + + warpevent.ap_event = APPEVNT_MOUSE; + warpevent.ap_value = (x << 16) | y; + + appl_tplay(&warpevent, 1, 1000); +} +#endif + +void GEM_CheckMouseMode(_THIS) +{ + const Uint8 full_focus = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + int set_system_cursor = 1, show_system_cursor = 1; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: check mouse mode\n"); +#endif + + /* If the mouse is hidden and input is grabbed, we use relative mode */ + GEM_mouse_relative = (!(SDL_cursorstate & CURSOR_VISIBLE)) + && (this->input_grab != SDL_GRAB_OFF) + && (SDL_GetAppState() & SDL_APPACTIVE); + SDL_AtariXbios_LockMousePosition(GEM_mouse_relative); + + if (SDL_cursorstate & CURSOR_VISIBLE) { + /* Application defined cursor only over the application window */ + if ((SDL_GetAppState() & full_focus) == full_focus) { + if (GEM_cursor) { + graf_mouse(USER_DEF, GEM_cursor->mform_p); + set_system_cursor = 0; + } else { + show_system_cursor = 0; + } + } + } else { + /* Mouse cursor hidden only over the application window */ + if ((SDL_GetAppState() & full_focus) == full_focus) { + set_system_cursor = 0; + show_system_cursor = 0; + } + } + + graf_mouse(show_system_cursor ? M_ON : M_OFF, NULL); + if (set_system_cursor) { + graf_mouse(ARROW, NULL); + } +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h b/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h new file mode 100644 index 0000000..06f90ba --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemmouse_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gemvideo.h" + +/* Functions to be exported */ +extern void GEM_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *GEM_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int GEM_ShowWMCursor(_THIS, WMcursor *cursor); +#if 0 +extern void GEM_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +#endif +extern void GEM_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/gem/SDL_gemvideo.c b/3rdparty/SDL/src/video/gem/SDL_gemvideo.c new file mode 100644 index 0000000..2ce9151 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemvideo.c @@ -0,0 +1,1337 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + GEM video driver + + Patrice Mandin + and work from + Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard +*/ + +/* Mint includes */ +#include <gem.h> +#include <gemx.h> +#include <mint/osbind.h> +#include <mint/cookie.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" + +#include "../ataricommon/SDL_ataric2p_s.h" +#include "../ataricommon/SDL_atarieddi_s.h" +#include "../ataricommon/SDL_atarimxalloc_c.h" +#include "../ataricommon/SDL_atarigl_c.h" + +#include "SDL_gemvideo.h" +#include "SDL_gemevents_c.h" +#include "SDL_gemmouse_c.h" +#include "SDL_gemwm_c.h" +#include "../ataricommon/SDL_xbiosevents_c.h" +#include "../ataricommon/SDL_ataridevmouse_c.h" + +/* Defines */ + +/*#define DEBUG_VIDEO_GEM 1*/ + +#define GEM_VID_DRIVER_NAME "gem" + +#undef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#undef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) + +/* Variables */ + +static unsigned char vdi_index[256] = { + 0, 2, 3, 6, 4, 7, 5, 8, + 9, 10, 11, 14, 12, 15, 13, 255 +}; + +static const char empty_name[]=""; + +/* Initialization/Query functions */ +static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GEM_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GEM_LockHWSurface(_THIS, SDL_Surface *surface); +static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface); +static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface); +static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects); +#if 0 +static int GEM_ToggleFullScreen(_THIS, int on); +#endif + +/* Internal functions */ +static void GEM_FreeBuffers(_THIS); +static void GEM_ClearScreen(_THIS); +static void GEM_ClearRect(_THIS, short *rect); +static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]); +static void GEM_LockScreen(_THIS); +static void GEM_UnlockScreen(_THIS); +static void refresh_window(_THIS, int winhandle, short *rect); + +#if SDL_VIDEO_OPENGL +/* OpenGL functions */ +static void GEM_GL_SwapBuffers(_THIS); +#endif + +/* GEM driver bootstrap functions */ + +static int GEM_Available(void) +{ + /* Test if AES available */ + if (appl_init() == -1) + return 0; + + appl_exit(); + return 1; +} + +static void GEM_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GEM_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + int vectors_mask; +/* unsigned long dummy;*/ + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = GEM_VideoInit; + device->ListModes = GEM_ListModes; + device->SetVideoMode = GEM_SetVideoMode; + device->SetColors = GEM_SetColors; + device->UpdateRects = NULL /*GEM_UpdateRects*/; + device->VideoQuit = GEM_VideoQuit; + device->AllocHWSurface = GEM_AllocHWSurface; + device->LockHWSurface = GEM_LockHWSurface; + device->UnlockHWSurface = GEM_UnlockHWSurface; + device->FlipHWSurface = GEM_FlipHWSurface; + device->FreeHWSurface = GEM_FreeHWSurface; + device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/; + + /* Window manager */ + device->SetCaption = GEM_SetCaption; + device->SetIcon = GEM_SetIcon; + device->IconifyWindow = GEM_IconifyWindow; + device->GrabInput = GEM_GrabInput; + + /* Events */ + device->InitOSKeymap = GEM_InitOSKeymap; + device->PumpEvents = GEM_PumpEvents; + + /* Mouse */ + device->FreeWMCursor = GEM_FreeWMCursor; + device->CreateWMCursor = GEM_CreateWMCursor; + device->ShowWMCursor = GEM_ShowWMCursor; + device->WarpWMCursor = NULL /*GEM_WarpWMCursor*/; + device->CheckMouseMode = GEM_CheckMouseMode; + +#if SDL_VIDEO_OPENGL + /* OpenGL functions */ + device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; + device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; + device->GL_GetAttribute = SDL_AtariGL_GetAttribute; + device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; + device->GL_SwapBuffers = GEM_GL_SwapBuffers; +#endif + + device->hidden->use_dev_mouse = + (SDL_AtariDevMouse_Open()!=0) ? SDL_TRUE : SDL_FALSE; + + vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */ + if (!(device->hidden->use_dev_mouse)) { + vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */ + } +/* if (Getcookie(C_MiNT, &dummy)==C_FOUND) { + vectors_mask = 0; + }*/ + + SDL_AtariXbios_InstallVectors(vectors_mask); + + device->free = GEM_DeleteDevice; + + return device; +} + +VideoBootStrap GEM_bootstrap = { + GEM_VID_DRIVER_NAME, "Atari GEM video driver", + GEM_Available, GEM_CreateDevice +}; + +static void VDI_ReadExtInfo(_THIS, short *work_out) +{ + unsigned long EdDI_version; + long cookie_EdDI; + Uint16 clut_type; + + /* Read EdDI informations */ + if (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) { + return; + } + + EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI); + + vq_scrninfo(VDI_handle, work_out); + + VDI_format = work_out[0]; + clut_type = work_out[1]; + + /* With EdDI>=1.1, we can have screen pitch, address and format + * so we can directly write to screen without using vro_cpyfm + */ + if (EdDI_version >= EDDI_11) { + VDI_pitch = work_out[5]; + VDI_screen = (void *) *((unsigned long *) &work_out[6]); + } + + switch(clut_type) { + case VDI_CLUT_HARDWARE: + { + int i; + Uint16 *tmp_p; + + tmp_p = (Uint16 *)&work_out[16]; + + for (i=0;i<256;i++) { + vdi_index[*tmp_p++] = i; + } + } + break; + case VDI_CLUT_SOFTWARE: + { + int component; /* red, green, blue, alpha, overlay */ + int num_bit; + unsigned short *tmp_p; + + /* We can build masks with info here */ + tmp_p = (unsigned short *) &work_out[16]; + for (component=0;component<5;component++) { + for (num_bit=0;num_bit<16;num_bit++) { + unsigned short valeur; + + valeur = *tmp_p++; + + if (valeur == 0xffff) { + continue; + } + + switch(component) { + case 0: + VDI_redmask |= 1<< valeur; + break; + case 1: + VDI_greenmask |= 1<< valeur; + break; + case 2: + VDI_bluemask |= 1<< valeur; + break; + case 3: + VDI_alphamask |= 1<< valeur; + break; + } + } + } + } + + /* Remove lower green bits for Intel endian screen */ + if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) { + VDI_greenmask &= ~(7<<13); + } + break; + case VDI_CLUT_NONE: + break; + } +} + +int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i, menubar_size; + short work_in[12], work_out[272], dummy; + + /* Open AES (Application Environment Services) */ + if (appl_init() == -1) { + fprintf(stderr,"Can not open AES\n"); + return 1; + } + + /* Read version and features */ + GEM_version = aes_global[0]; + if (GEM_version >= 0x0410) { + short ap_gout[4], errorcode; + + GEM_wfeatures=0; + errorcode=appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3]); + + if (errorcode==0) { + GEM_wfeatures=ap_gout[0]; + } + } + + /* Ask VDI physical workstation handle opened by AES */ + VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy); + if (VDI_handle<1) { + fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle); + return 1; + } + + /* Open virtual VDI workstation */ + work_in[0]=Getrez()+2; + for(i = 1; i < 10; i++) + work_in[i] = 1; + work_in[10] = 2; + + v_opnvwk(work_in, &VDI_handle, work_out); + if (VDI_handle == 0) { + fprintf(stderr,"Can not open VDI virtual workstation\n"); + return 1; + } + + /* Read fullscreen size */ + VDI_w = work_out[0] + 1; + VDI_h = work_out[1] + 1; + + /* Read desktop size and position */ + if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) { + fprintf(stderr,"Can not read desktop properties\n"); + return 1; + } + + /* Read bit depth */ + vq_extnd(VDI_handle, 1, work_out); + VDI_bpp = work_out[4]; + VDI_oldnumcolors=0; + + switch(VDI_bpp) { + case 8: + VDI_pixelsize=1; + break; + case 15: + case 16: + VDI_pixelsize=2; + break; + case 24: + VDI_pixelsize=3; + break; + case 32: + VDI_pixelsize=4; + break; + default: + fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp); + return 1; + } + + /* Setup hardware -> VDI palette mapping */ + for(i = 16; i < 255; i++) { + vdi_index[i] = i; + } + vdi_index[255] = 1; + + /* Save current palette */ + if (VDI_bpp>8) { + VDI_oldnumcolors=1<<8; + } else { + VDI_oldnumcolors=1<<VDI_bpp; + } + + for(i = 0; i < VDI_oldnumcolors; i++) { + short rgb[3]; + + vq_color(VDI_handle, i, 0, rgb); + + VDI_oldpalette[i][0] = rgb[0]; + VDI_oldpalette[i][1] = rgb[1]; + VDI_oldpalette[i][2] = rgb[2]; + } + VDI_setpalette = GEM_SetNewPalette; + SDL_memcpy(VDI_curpalette,VDI_oldpalette,sizeof(VDI_curpalette)); + + /* Setup screen info */ + GEM_title_name = empty_name; + GEM_icon_name = empty_name; + + GEM_handle = -1; + GEM_locked = SDL_FALSE; + GEM_win_fulled = SDL_FALSE; + GEM_fullscreen = SDL_FALSE; + GEM_lock_redraw = SDL_TRUE; /* Prevent redraw till buffers are setup */ + + VDI_screen = NULL; + VDI_pitch = VDI_w * VDI_pixelsize; + VDI_format = ( (VDI_bpp <= 8) ? VDI_FORMAT_INTER : VDI_FORMAT_PACK); + VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0; + VDI_ReadExtInfo(this, work_out); + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: screen: address=0x%08x, pitch=%d\n", VDI_screen, VDI_pitch); + printf("sdl:video:gem: format=%d\n", VDI_format); + printf("sdl:video:gem: masks: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + VDI_alphamask, VDI_redmask, VDI_greenmask, VDI_bluemask + ); +#endif + + /* Setup destination mfdb */ + VDI_dst_mfdb.fd_addr = NULL; + + /* Determine the current screen size */ + this->info.current_w = VDI_w; + this->info.current_h = VDI_h; + + /* Determine the screen depth */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = VDI_bpp; + + /* Set mouse cursor to arrow */ + graf_mouse(ARROW, NULL); + GEM_cursor = NULL; + + /* Init chunky to planar routine */ + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + + /* Setup VDI fill functions */ + vsf_color(VDI_handle,0); + vsf_interior(VDI_handle,1); + vsf_perimeter(VDI_handle,0); + + /* Menu bar save buffer */ + menubar_size = GEM_desk_w * GEM_desk_y * VDI_pixelsize; + GEM_menubar=Atari_SysMalloc(menubar_size,MX_PREFTTRAM); + + /* Fill video modes list */ + SDL_modelist[0] = SDL_malloc(sizeof(SDL_Rect)); + SDL_modelist[0]->x = 0; + SDL_modelist[0]->y = 0; + SDL_modelist[0]->w = VDI_w; + SDL_modelist[0]->h = VDI_h; + + SDL_modelist[1] = NULL; + +#if SDL_VIDEO_OPENGL + SDL_AtariGL_InitPointers(this); +#endif + + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (format->BitsPerPixel != VDI_bpp) { + return ((SDL_Rect **)NULL); + } + + if (flags & SDL_FULLSCREEN) { + return (SDL_modelist); + } + + return((SDL_Rect **)-1); +} + +static void GEM_FreeBuffers(_THIS) +{ + /* Release buffer */ + if ( GEM_buffer2 ) { + Mfree( GEM_buffer2 ); + GEM_buffer2=NULL; + } + + if ( GEM_buffer1 ) { + Mfree( GEM_buffer1 ); + GEM_buffer1=NULL; + } +} + +static void GEM_ClearRect(_THIS, short *rect) +{ + short oldrgb[3], rgb[3]={0,0,0}; + + vq_color(VDI_handle, vdi_index[0], 0, oldrgb); + vs_color(VDI_handle, vdi_index[0], rgb); + + vsf_color(VDI_handle,0); + vsf_interior(VDI_handle,1); + vsf_perimeter(VDI_handle,0); + v_bar(VDI_handle, rect); + + vs_color(VDI_handle, vdi_index[0], oldrgb); +} + +static void GEM_ClearScreen(_THIS) +{ + short pxy[4]; + + v_hide_c(VDI_handle); + + pxy[0] = pxy[1] = 0; + pxy[2] = VDI_w - 1; + pxy[3] = VDI_h - 1; + GEM_ClearRect(this, pxy); + + v_show_c(VDI_handle, 1); +} + +static void GEM_SetNewPalette(_THIS, Uint16 newpal[256][3]) +{ + int i; + short rgb[3]; + + if (VDI_oldnumcolors==0) + return; + + for(i = 0; i < VDI_oldnumcolors; i++) { + rgb[0] = newpal[i][0]; + rgb[1] = newpal[i][1]; + rgb[2] = newpal[i][2]; + + vs_color(VDI_handle, i, rgb); + } +} + +static void GEM_LockScreen(_THIS) +{ + if (!GEM_locked) { + /* Lock AES */ + wind_update(BEG_UPDATE); + wind_update(BEG_MCTRL); + /* Reserve memory space, used to be sure of compatibility */ + form_dial( FMD_START, 0,0,0,0, 0,0,VDI_w,VDI_h); + + /* Save menu bar */ + if (GEM_menubar) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=GEM_menubar; + mfdb_src.fd_w=GEM_desk_w; + mfdb_src.fd_h=GEM_desk_y; + mfdb_src.fd_wdwidth=GEM_desk_w>>4; + mfdb_src.fd_nplanes=VDI_bpp; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = GEM_desk_w-1; + blitcoords[3] = blitcoords[7] = GEM_desk_y-1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &VDI_dst_mfdb, &mfdb_src); + } + + GEM_locked=SDL_TRUE; + } +} + +static void GEM_UnlockScreen(_THIS) +{ + if (GEM_locked) { + /* Restore menu bar */ + if (GEM_menubar) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=GEM_menubar; + mfdb_src.fd_w=GEM_desk_w; + mfdb_src.fd_h=GEM_desk_y; + mfdb_src.fd_wdwidth=GEM_desk_w>>4; + mfdb_src.fd_nplanes=VDI_bpp; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = GEM_desk_w-1; + blitcoords[3] = blitcoords[7] = GEM_desk_y-1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + + /* Restore screen memory, and send REDRAW to all apps */ + form_dial( FMD_FINISH, 0,0,0,0, 0,0,VDI_w,VDI_h); + /* Unlock AES */ + wind_update(END_MCTRL); + wind_update(END_UPDATE); + + GEM_locked=SDL_FALSE; + } +} + +SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 modeflags, screensize; + SDL_bool use_shadow1, use_shadow2; + + /* width must be multiple of 16, for vro_cpyfm() and c2p_convert() */ + if ((width & 15) != 0) { + width = (width | 15) +1; + } + + /*--- Verify if asked mode can be used ---*/ + if (VDI_bpp != bpp) { + SDL_SetError("%d bpp mode not supported", bpp); + return(NULL); + } + + if (flags & SDL_FULLSCREEN) { + if ((VDI_w < width) || (VDI_h < height)) { + SDL_SetError("%dx%d mode is too large", width, height); + return(NULL); + } + } + + /*--- Allocate the new pixel format for the screen ---*/ + if ( ! SDL_ReallocFormat(current, VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, VDI_alphamask) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + screensize = width * height * VDI_pixelsize; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): %dx%dx%d = %d\n", width, height, bpp, screensize); +#endif + + /*--- Allocate shadow buffers if needed, and conversion operations ---*/ + GEM_FreeBuffers(this); + + GEM_bufops=0; + use_shadow1=use_shadow2=SDL_FALSE; + if (VDI_screen && (flags & SDL_FULLSCREEN)) { + if (VDI_format==VDI_FORMAT_INTER) { + use_shadow1=SDL_TRUE; + GEM_bufops = B2S_C2P_1TOS; + } + } else { + use_shadow1=SDL_TRUE; + if (VDI_format==VDI_FORMAT_PACK) { + GEM_bufops = B2S_VROCPYFM_1TOS; + } else { + use_shadow2=SDL_TRUE; + GEM_bufops = B2S_C2P_1TO2|B2S_VROCPYFM_2TOS; + } + } + + if (use_shadow1) { + GEM_buffer1 = Atari_SysMalloc(screensize, MX_PREFTTRAM); + if (GEM_buffer1==NULL) { + SDL_SetError("Can not allocate %d KB for frame buffer", screensize>>10); + return NULL; + } + SDL_memset(GEM_buffer1, 0, screensize); +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): allocated buffer 1\n"); +#endif + } + + if (use_shadow2) { + GEM_buffer2 = Atari_SysMalloc(screensize, MX_PREFTTRAM); + if (GEM_buffer2==NULL) { + SDL_SetError("Can not allocate %d KB for shadow buffer", screensize>>10); + return NULL; + } + SDL_memset(GEM_buffer2, 0, screensize); +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setvideomode(): allocated buffer 2\n"); +#endif + } + + /*--- Initialize screen ---*/ + modeflags = SDL_PREALLOC; + if (VDI_bpp == 8) { + modeflags |= SDL_HWPALETTE; + } + + if (flags & SDL_FULLSCREEN) { + GEM_LockScreen(this); + + GEM_ClearScreen(this); + + modeflags |= SDL_FULLSCREEN; + if (VDI_screen && (VDI_format==VDI_FORMAT_PACK) && !use_shadow1) { + modeflags |= SDL_HWSURFACE; + } else { + modeflags |= SDL_SWSURFACE; + } + + GEM_fullscreen = SDL_TRUE; + } else { + int old_win_type; + short x2,y2,w2,h2; + + GEM_UnlockScreen(this); + + /* Set window gadgets */ + old_win_type = GEM_win_type; + if (!(flags & SDL_NOFRAME)) { + GEM_win_type=NAME|MOVER|CLOSER|SMALLER; + if (flags & SDL_RESIZABLE) { + GEM_win_type |= FULLER|SIZER; + modeflags |= SDL_RESIZABLE; + } + } else { + GEM_win_type=0; + modeflags |= SDL_NOFRAME; + } + modeflags |= SDL_SWSURFACE; + + /* Recreate window ? only for different widget or non-created window */ + if ((old_win_type != GEM_win_type) || (GEM_handle < 0)) { + /* Calculate window size */ + if (!wind_calc(WC_BORDER, GEM_win_type, 0,0,width,height, &x2,&y2,&w2,&h2)) { + GEM_FreeBuffers(this); + SDL_SetError("Can not calculate window attributes"); + return NULL; + } + + /* Center window */ + x2 = (GEM_desk_w-w2)>>1; + y2 = (GEM_desk_h-h2)>>1; + if (x2<0) { + x2 = 0; + } + if (y2<0) { + y2 = 0; + } + x2 += GEM_desk_x; + y2 += GEM_desk_y; + + /* Destroy existing window */ + if (GEM_handle >= 0) { + wind_close(GEM_handle); + wind_delete(GEM_handle); + } + + /* Create window */ + GEM_handle=wind_create(GEM_win_type, x2,y2,w2,h2); + if (GEM_handle<0) { + GEM_FreeBuffers(this); + SDL_SetError("Can not create window"); + return NULL; + } + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: handle=%d\n", GEM_handle); +#endif + + /* Setup window name */ + wind_set(GEM_handle,WF_NAME,(short)(((unsigned long)GEM_title_name)>>16),(short)(((unsigned long)GEM_title_name) & 0xffff),0,0); + GEM_refresh_name = SDL_FALSE; + + /* Open the window */ + wind_open(GEM_handle,x2,y2,w2,h2); + } else { + /* Resize window to fit asked video mode */ + wind_get (GEM_handle, WF_WORKXYWH, &x2,&y2,&w2,&h2); + if (wind_calc(WC_BORDER, GEM_win_type, x2,y2,width,height, &x2,&y2,&w2,&h2)) { + wind_set (GEM_handle, WF_CURRXYWH, x2,y2,w2,h2); + } + } + + GEM_fullscreen = SDL_FALSE; + } + + /* Set up the new mode framebuffer */ + current->w = width; + current->h = height; + if (use_shadow1) { + current->pixels = GEM_buffer1; + current->pitch = width * VDI_pixelsize; + } else { + current->pixels = VDI_screen; + current->pitch = VDI_pitch; + } + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (!SDL_AtariGL_Init(this, current)) { + GEM_FreeBuffers(this); + SDL_SetError("Can not create OpenGL context"); + return NULL; + } + + modeflags |= SDL_OPENGL; + } +#endif + + current->flags = modeflags; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: surface: %dx%d\n", current->w, current->h); +#endif + + this->UpdateRects = GEM_UpdateRects; + GEM_lock_redraw = SDL_FALSE; /* Enable redraw */ + + /* We're done */ + return(current); +} + +static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} + +static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int GEM_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void GEM_UpdateRectsFullscreen(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + int i, surf_width; + + surface = this->screen; + /* Need to be a multiple of 16 pixels */ + surf_width=surface->w; + if ((surf_width & 15) != 0) { + surf_width = (surf_width | 15) + 1; + } + + if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) { + void *destscr; + int destpitch; + + if (GEM_bufops & B2S_C2P_1TOS) { + destscr = VDI_screen; + destpitch = VDI_pitch; + } else { + destscr = GEM_buffer2; + destpitch = surface->pitch; + } + + for (i=0;i<numrects;i++) { + void *source,*destination; + int x1,x2; + + x1 = rects[i].x & ~15; + x2 = rects[i].x+rects[i].w; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + source = surface->pixels; + source += surface->pitch * rects[i].y; + source += x1; + + destination = destscr; + destination += destpitch * rects[i].y; + destination += x1; + + SDL_Atari_C2pConvert( + source, destination, + x2-x1, rects[i].h, + SDL_FALSE, + surface->pitch, destpitch + ); + } + } + + if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_addr=surface->pixels; + mfdb_src.fd_w=surf_width; + mfdb_src.fd_h=surface->h; + mfdb_src.fd_wdwidth= (surface->pitch/VDI_pixelsize) >> 4; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + if (GEM_bufops & B2S_VROCPYFM_2TOS) { + mfdb_src.fd_addr=GEM_buffer2; + } + + for ( i=0; i<numrects; ++i ) { + blitcoords[0] = blitcoords[4] = rects[i].x; + blitcoords[1] = blitcoords[5] = rects[i].y; + blitcoords[2] = blitcoords[6] = rects[i].x + rects[i].w - 1; + blitcoords[3] = blitcoords[7] = rects[i].y + rects[i].h - 1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + } +} + +static void GEM_UpdateRectsWindowed(_THIS, int numrects, SDL_Rect *rects) +{ + short pxy[4], wind_pxy[4]; + int i; + + if (wind_get(GEM_handle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) { + return; + } + + for ( i=0; i<numrects; ++i ) { + pxy[0] = wind_pxy[0] + rects[i].x; + pxy[1] = wind_pxy[1] + rects[i].y; + pxy[2] = rects[i].w; + pxy[3] = rects[i].h; + + GEM_wind_redraw(this, GEM_handle, pxy); + } +} + +static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + + if (GEM_lock_redraw) { + return; + } + + surface = this->screen; + + if (surface->flags & SDL_FULLSCREEN) { + GEM_UpdateRectsFullscreen(this, numrects, rects); + } else { + GEM_UpdateRectsWindowed(this, numrects, rects); + } +} + +static int GEM_FlipHWSurfaceFullscreen(_THIS, SDL_Surface *surface) +{ + int surf_width; + + /* Need to be a multiple of 16 pixels */ + surf_width=surface->w; + if ((surf_width & 15) != 0) { + surf_width = (surf_width | 15) + 1; + } + + if (GEM_bufops & (B2S_C2P_1TO2|B2S_C2P_1TOS)) { + void *destscr; + int destpitch; + + if (GEM_bufops & B2S_C2P_1TOS) { + destscr = VDI_screen; + destpitch = VDI_pitch; + } else { + destscr = GEM_buffer2; + destpitch = surface->pitch; + } + + SDL_Atari_C2pConvert( + surface->pixels, destscr, + surf_width, surface->h, + SDL_FALSE, + surface->pitch, destpitch + ); + } + + if (GEM_bufops & (B2S_VROCPYFM_1TOS|B2S_VROCPYFM_2TOS)) { + MFDB mfdb_src; + short blitcoords[8]; + + mfdb_src.fd_w=surf_width; + mfdb_src.fd_h=surface->h; + mfdb_src.fd_wdwidth=mfdb_src.fd_w >> 4; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + if (GEM_bufops & B2S_VROCPYFM_1TOS) { + mfdb_src.fd_addr=surface->pixels; + } else { + mfdb_src.fd_addr=GEM_buffer2; + } + + blitcoords[0] = blitcoords[4] = 0; + blitcoords[1] = blitcoords[5] = 0; + blitcoords[2] = blitcoords[6] = surface->w - 1; + blitcoords[3] = blitcoords[7] = surface->h - 1; + + vro_cpyfm(VDI_handle, S_ONLY, blitcoords, &mfdb_src, &VDI_dst_mfdb); + } + + return(0); +} + +static int GEM_FlipHWSurfaceWindowed(_THIS, SDL_Surface *surface) +{ + short pxy[8]; + + /* Update the whole window */ + wind_get(GEM_handle, WF_WORKXYWH, &pxy[0], &pxy[1], &pxy[2], &pxy[3]); + + GEM_wind_redraw(this, GEM_handle, pxy); + + return(0); +} + +static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (GEM_lock_redraw) { + return(0); + } + + if (surface->flags & SDL_FULLSCREEN) { + return GEM_FlipHWSurfaceFullscreen(this, surface); + } else { + return GEM_FlipHWSurfaceWindowed(this, surface); + } +} + +static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Surface *surface; + +#ifdef DEBUG_VIDEO_GEM + printf("sdl:video:gem: setcolors()\n"); +#endif + + /* Do not change palette in True Colour */ + surface = this->screen; + if (surface->format->BitsPerPixel > 8) { + return 1; + } + + for(i = 0; i < ncolors; i++) + { + int r, g, b; + short rgb[3]; + + r = colors[i].r; + g = colors[i].g; + b = colors[i].b; + + rgb[0] = VDI_curpalette[i][0] = (1000 * r) / 255; + rgb[1] = VDI_curpalette[i][1] =(1000 * g) / 255; + rgb[2] = VDI_curpalette[i][2] =(1000 * b) / 255; + + vs_color(VDI_handle, vdi_index[firstcolor+i], rgb); + } + + return(1); +} + +#if 0 +static int GEM_ToggleFullScreen(_THIS, int on) +{ + if (on) { + GEM_LockScreen(this); + } else { + GEM_UnlockScreen(this); + } + + return(1); +} +#endif + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void GEM_VideoQuit(_THIS) +{ + SDL_AtariXbios_RestoreVectors(); + if (GEM_usedevmouse) { + SDL_AtariDevMouse_Close(); + } + + GEM_FreeBuffers(this); + +#if SDL_VIDEO_OPENGL + if (gl_active) { + SDL_AtariGL_Quit(this, SDL_TRUE); + } +#endif + + /* Destroy window */ + if (GEM_handle>=0) { + wind_close(GEM_handle); + wind_delete(GEM_handle); + GEM_handle=-1; + } + + GEM_UnlockScreen(this); + if (GEM_menubar) { + Mfree(GEM_menubar); + GEM_menubar=NULL; + } + + appl_exit(); + + GEM_SetNewPalette(this, VDI_oldpalette); + + /* Close VDI workstation */ + if (VDI_handle) { + v_clsvwk(VDI_handle); + } + + /* Free mode list */ + if (SDL_modelist[0]) { + SDL_free(SDL_modelist[0]); + SDL_modelist[0]=NULL; + } + + this->screen->pixels = NULL; +} + +void GEM_wind_redraw(_THIS, int winhandle, short *inside) +{ + short todo[4]; + + /* Tell AES we are going to update */ + wind_update(BEG_UPDATE); + + v_hide_c(VDI_handle); + + /* Browse the rectangle list to redraw */ + if (wind_get(winhandle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])!=0) { + + while (todo[2] && todo[3]) { + + if (rc_intersect((GRECT *)inside,(GRECT *)todo)) { + todo[2] += todo[0]-1; + todo[3] += todo[1]-1; + refresh_window(this, winhandle, todo); + } + + if (wind_get(winhandle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])==0) { + break; + } + } + + } + + /* Update finished */ + wind_update(END_UPDATE); + + v_show_c(VDI_handle,1); +} + +static void refresh_window(_THIS, int winhandle, short *rect) +{ + MFDB mfdb_src; + short pxy[8],wind_pxy[8]; + SDL_Surface *surface; + int iconified; + + /* Is window iconified ? */ + iconified = 0; +/* if (GEM_wfeatures & (1<<WF_ICONIFY))*/ { + if (wind_get(winhandle, WF_ICONIFY, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])!=0) { + iconified = wind_pxy[0]; + } + } + + if (wind_get(winhandle, WF_WORKXYWH, &wind_pxy[0], &wind_pxy[1], &wind_pxy[2], &wind_pxy[3])==0) { + return; + } + + if (iconified && GEM_icon) { + short icon_rect[4], dst_rect[4]; + short iconx,icony; + + surface = GEM_icon; + + GEM_ClearRect(this, rect); + + /* Calculate centered icon(x,y,w,h) relative to window */ + iconx = (wind_pxy[2]-surface->w)>>1; + icony = (wind_pxy[3]-surface->h)>>1; + + icon_rect[0] = iconx; + icon_rect[1] = icony; + icon_rect[2] = surface->w; + icon_rect[3] = surface->h; + + /* Calculate redraw rectangle(x,y,w,h) relative to window */ + dst_rect[0] = rect[0]-wind_pxy[0]; + dst_rect[1] = rect[1]-wind_pxy[1]; + dst_rect[2] = rect[2]-rect[0]+1; + dst_rect[3] = rect[3]-rect[1]+1; + + /* Does the icon rectangle must be redrawn ? */ + if (!rc_intersect((GRECT *)icon_rect, (GRECT *)dst_rect)) { + return; + } + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: clip(0,0,%d,%d) to (%d,%d,%d,%d)\n", + surface->w-1,surface->h-1, dst_rect[0],dst_rect[1],dst_rect[2],dst_rect[3]); + printf("sdl:video:gem: icon(%d,%d,%d,%d)\n", + icon_rect[0], icon_rect[1], icon_rect[2], icon_rect[3]); + printf("sdl:video:gem: refresh_window(): draw icon\n"); +#endif + + /* Calculate icon(x1,y1,x2,y2) relative to screen */ + icon_rect[0] += wind_pxy[0]; + icon_rect[1] += wind_pxy[1]; + icon_rect[2] += icon_rect[0]-1; + icon_rect[3] += icon_rect[1]-1; + + /* Calculate intersection rectangle to redraw */ + pxy[4]=pxy[0]=MAX(icon_rect[0],rect[0]); + pxy[5]=pxy[1]=MAX(icon_rect[1],rect[1]); + pxy[6]=pxy[2]=MIN(icon_rect[2],rect[2]); + pxy[7]=pxy[3]=MIN(icon_rect[3],rect[3]); + + /* Calculate icon source image pos relative to window */ + pxy[0] -= wind_pxy[0]+iconx; + pxy[1] -= wind_pxy[1]+icony; + pxy[2] -= wind_pxy[0]+iconx; + pxy[3] -= wind_pxy[1]+icony; + + } else { + surface = this->screen; + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: refresh_window(): draw frame buffer\n"); +#endif + + /* Redraw all window content */ + pxy[0] = rect[0]-wind_pxy[0]; + pxy[1] = rect[1]-wind_pxy[1]; + pxy[2] = rect[2]-wind_pxy[0]; + pxy[3] = rect[3]-wind_pxy[1]; + + pxy[4] = rect[0]; + pxy[5] = rect[1]; + pxy[6] = rect[2]; + pxy[7] = rect[3]; + } + + if (GEM_bufops & B2S_C2P_1TO2) { + void *src, *dest; + int x1,x2; + + x1 = (rect[0]-wind_pxy[0]) & ~15; + x2 = rect[2]-wind_pxy[0]; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + src = surface->pixels; + src += surface->pitch * (rect[1]-wind_pxy[1]); + src += x1; + + dest = GEM_buffer2; + dest += surface->pitch * (rect[1]-wind_pxy[1]); + dest += x1; + + SDL_Atari_C2pConvert( + src, dest, + x2-x1, rect[3]-rect[1]+1, + SDL_FALSE, + surface->pitch, surface->pitch + ); + } + + mfdb_src.fd_addr=surface->pixels; + { + int width; + + /* Need to be a multiple of 16 pixels */ + width=surface->w; + if ((width & 15) != 0) { + width = (width | 15) + 1; + } + mfdb_src.fd_w=width; + } + mfdb_src.fd_h=surface->h; + mfdb_src.fd_nplanes=surface->format->BitsPerPixel; + mfdb_src.fd_wdwidth=mfdb_src.fd_w>>4; + mfdb_src.fd_stand= + mfdb_src.fd_r1= + mfdb_src.fd_r2= + mfdb_src.fd_r3= 0; + + if (GEM_bufops & B2S_VROCPYFM_2TOS) { + mfdb_src.fd_addr=GEM_buffer2; + } + +#if DEBUG_VIDEO_GEM + printf("sdl:video:gem: redraw %dx%d: (%d,%d,%d,%d) to (%d,%d,%d,%d)\n", + surface->w, surface->h, + pxy[0],pxy[1],pxy[2],pxy[3], + pxy[4],pxy[5],pxy[6],pxy[7] + ); +#endif + + vro_cpyfm( VDI_handle, S_ONLY, pxy, &mfdb_src, &VDI_dst_mfdb); +} + +#if SDL_VIDEO_OPENGL + +static void GEM_GL_SwapBuffers(_THIS) +{ + SDL_AtariGL_SwapBuffers(this); + GEM_FlipHWSurface(this, this->screen); +} + +#endif diff --git a/3rdparty/SDL/src/video/gem/SDL_gemvideo.h b/3rdparty/SDL/src/video/gem/SDL_gemvideo.h new file mode 100644 index 0000000..f3a1954 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemvideo.h @@ -0,0 +1,191 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gemvideo_h +#define _SDL_gemvideo_h + +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + MFORM *mform_p; +}; + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Functions prototypes */ +void GEM_wind_redraw(_THIS, int winhandle, short *inside); + +/* Private display data */ + +#define B2S_C2P_1TO2 (1<<0) /* C2P convert buffer 1 to buffer 2 */ +#define B2S_C2P_1TOS (1<<1) /* C2P convert buffer 1 to screen */ +#define B2S_VROCPYFM_1TOS (1<<2) /* vro_cpyfm() buffer 1 to screen */ +#define B2S_VROCPYFM_2TOS (1<<3) /* vro_cpyfm() buffer 2 to screen */ + +#define SDL_NUMMODES 1 /* Fullscreen */ + +struct SDL_PrivateVideoData { + Uint16 buf2scr_ops; /* Operations to get buffer to screen */ + void *buffer1; /* Our shadow buffers */ + void *buffer2; + + /* VDI infos */ + short vdi_handle; /* VDI handle */ + short full_w, full_h; /* Fullscreen size */ + short bpp; /* Colour depth */ + short pixelsize; /* Bytes per pixel */ + short old_numcolors; /* Number of colors in saved palette */ + Uint16 pitch; /* Line length */ + Uint16 format; /* Screen format */ + void *screen; /* Screen address */ + Uint32 red, green, blue, alpha; /* Screen components */ + Uint32 screensize; + short blit_coords[8]; /* Coordinates for bitblt */ + MFDB src_mfdb, dst_mfdb; /* VDI MFDB for bitblt */ + Uint16 old_palette[256][3]; /* Saved current palette */ + Uint16 cur_palette[256][3]; /* SDL application palette */ + /* Function to set/restore palette */ + void (*setpalette)(_THIS, Uint16 newpal[256][3]); + + /* GEM infos */ + short desk_x, desk_y; /* Desktop properties */ + short desk_w, desk_h; + short win_handle; /* Our window handle */ + int window_type; /* Window type */ + const char *title_name; /* Window title */ + const char *icon_name; /* Icon title */ + short version; /* AES version */ + short wfeatures; /* AES window features */ + SDL_bool refresh_name; /* Change window title ? */ + SDL_bool window_fulled; /* Window maximized ? */ + SDL_bool mouse_relative; /* Report relative mouse movement */ + SDL_bool locked; /* AES locked for fullscreen ? */ + SDL_bool lock_redraw; /* Prevent redraw till buffers are setup */ + short message[8]; /* To self-send an AES message */ + void *menubar; /* Menu bar save buffer when going fullscreen */ + SDL_bool use_dev_mouse; /* Use /dev/mouse ? */ + WMcursor *cursor; /* To restore cursor when leaving/entering window */ + + SDL_bool fullscreen; /* Fullscreen or windowed mode ? */ + SDL_Rect *SDL_modelist[SDL_NUMMODES+1]; /* Mode list */ + SDL_Surface *icon; /* The icon */ +}; + +/* Hidden structure -> variables names */ +#define VDI_handle (this->hidden->vdi_handle) +#define VDI_w (this->hidden->full_w) +#define VDI_h (this->hidden->full_h) +#define VDI_bpp (this->hidden->bpp) +#define VDI_pixelsize (this->hidden->pixelsize) +#define VDI_oldnumcolors (this->hidden->old_numcolors) +#define VDI_oldpalette (this->hidden->old_palette) +#define VDI_curpalette (this->hidden->cur_palette) +#define VDI_setpalette (this->hidden->setpalette) +#define VDI_pitch (this->hidden->pitch) +#define VDI_format (this->hidden->format) +#define VDI_screen (this->hidden->screen) +#define VDI_redmask (this->hidden->red) +#define VDI_greenmask (this->hidden->green) +#define VDI_bluemask (this->hidden->blue) +#define VDI_alphamask (this->hidden->alpha) +#define VDI_screensize (this->hidden->screensize) +#define VDI_src_mfdb (this->hidden->src_mfdb) +#define VDI_dst_mfdb (this->hidden->dst_mfdb) +#define VDI_blit_coords (this->hidden->blit_coords) + +#define GEM_desk_x (this->hidden->desk_x) +#define GEM_desk_y (this->hidden->desk_y) +#define GEM_desk_w (this->hidden->desk_w) +#define GEM_desk_h (this->hidden->desk_h) +#define GEM_handle (this->hidden->win_handle) +#define GEM_win_type (this->hidden->window_type) +#define GEM_title_name (this->hidden->title_name) +#define GEM_icon_name (this->hidden->icon_name) +#define GEM_refresh_name (this->hidden->refresh_name) +#define GEM_version (this->hidden->version) +#define GEM_wfeatures (this->hidden->wfeatures) +#define GEM_win_fulled (this->hidden->window_fulled) +#define GEM_mouse_relative (this->hidden->mouse_relative) +#define GEM_locked (this->hidden->locked) +#define GEM_lock_redraw (this->hidden->lock_redraw) +#define GEM_message (this->hidden->message) +#define SDL_modelist (this->hidden->SDL_modelist) +#define GEM_icon (this->hidden->icon) +#define GEM_fullscreen (this->hidden->fullscreen) +#define GEM_menubar (this->hidden->menubar) +#define GEM_usedevmouse (this->hidden->use_dev_mouse) +#define GEM_cursor (this->hidden->cursor) + +#define GEM_buffer1 (this->hidden->buffer1) +#define GEM_buffer2 (this->hidden->buffer2) +#define GEM_bufops (this->hidden->buf2scr_ops) + +#define VDI_FBMASK(amask, rmask, gmask, bmask) \ + VDI_alphamask = (amask); \ + VDI_redmask = (rmask); \ + VDI_greenmask = (gmask); \ + VDI_bluemask = (bmask); + +/* + Possible buffer to screen operations: + + TC: 8 (chunky),15,16,24,32 bpp + 8I: 8 bpp planes + FB: screen framebuffer address available + FS: fullscreen + + TC, FB, FS: + - draw to screen + 8I, FB, FS: + - draw to buffer 1 + - C2P from buffer 1 to screen + + TC, !FB, FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, !FB, FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen + + TC, FB, !FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, FB, !FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen + + TC, !FB, !FS: + - draw to buffer 1 + - vro_cpyfm() from buffer 1 to screen + 8I, !FB, !FS: + - draw to buffer 1 + - C2P from buffer 1 to buffer 2 + - vro_cpyfm() from buffer 2 to screen +*/ + +#endif /* _SDL_gemvideo_h */ diff --git a/3rdparty/SDL/src/video/gem/SDL_gemwm.c b/3rdparty/SDL/src/video/gem/SDL_gemwm.c new file mode 100644 index 0000000..10776fd --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemwm.c @@ -0,0 +1,116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + GEM SDL video driver + Window manager functions + + Patrice Mandin +*/ + +/* Mint includes */ +#include <gem.h> + +#include "SDL_gemwm_c.h" + +/* Defines */ + +#define ICONWIDTH 64 +#define ICONHEIGHT 64 + +/* Functions */ + +void GEM_SetCaption(_THIS, const char *title, const char *icon) +{ + if (title) { + GEM_title_name = title; + GEM_refresh_name = SDL_TRUE; + } + + if (icon) { + GEM_icon_name = icon; + GEM_refresh_name = SDL_TRUE; + } +} + +void GEM_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + SDL_Surface *sicon; + SDL_Rect bounds; + +#if 0 + if ((GEM_wfeatures & (1<<WF_ICONIFY))==0) { + return; + } +#endif + + if (icon == NULL) { + return; + } + + /* Convert icon to the screen format */ + sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + VDI_bpp, VDI_redmask, VDI_greenmask, VDI_bluemask, 0); + if ( sicon == NULL ) { + return; + } + + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) { + SDL_FreeSurface(sicon); + return; + } + + GEM_icon = sicon; +} + +int GEM_IconifyWindow(_THIS) +{ + if ((GEM_wfeatures & (1<<WF_ICONIFY))==0) + return 0; + + GEM_message[0] = WM_ICONIFY; + GEM_message[1] = gl_apid; + GEM_message[2] = 0; + GEM_message[3] = GEM_handle; + GEM_message[4] = 0; + GEM_message[5] = GEM_desk_h-ICONHEIGHT; + GEM_message[6] = ICONWIDTH; + GEM_message[7] = ICONHEIGHT; + + appl_write(gl_apid, sizeof(GEM_message), GEM_message); + + return 1; +} + +SDL_GrabMode GEM_GrabInput(_THIS, SDL_GrabMode mode) +{ + if (this->screen == NULL) { + return SDL_GRAB_OFF; + } + + return mode; +} diff --git a/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h b/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h new file mode 100644 index 0000000..59828b7 --- /dev/null +++ b/3rdparty/SDL/src/video/gem/SDL_gemwm_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * GEM SDL video driver implementation + * Window manager functions + * + * Patrice Mandin + */ + +#include "SDL_gemvideo.h" + +/* Functions prototypes */ +extern void GEM_SetCaption(_THIS, const char *title, const char *icon); +extern void GEM_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int GEM_IconifyWindow(_THIS); +extern SDL_GrabMode GEM_GrabInput(_THIS, SDL_GrabMode mode); diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggievents.c b/3rdparty/SDL/src/video/ggi/SDL_ggievents.c new file mode 100644 index 0000000..d963fe1 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggievents.c @@ -0,0 +1,264 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting GGI events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#include <ggi/keyboard.h> + +#include "SDL_ggikeys.h" + +#include "SDL.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggivideo.h" +#include "SDL_ggievents_c.h" + +/* The translation tables from a GGI keycode to a SDL keysym */ +static SDLKey keymap[128]; +static SDL_keysym *GGI_TranslateKey(ggi_event *ev, SDL_keysym *keysym); + +static int posted = 0; + +void GGI_PumpEvents(_THIS) +{ + struct timeval *tvp, tv = { 0, 0 }; + ggi_event ev; + + tvp = &tv; + +/* ggiFlush(VIS); */ + + while (ggiEventPoll(VIS, emAll, tvp)) +/* while (ggiEventPoll(VIS, (emKeyboard | emPointer | emCommand), tvp)) */ + { + int queueevent_mouse = 0, queueevent_kbd = 0; + static int buttons = 0; + static int mouse_x = 0, mouse_y = 0, mouse_z = 0; + int x = 0, y = 0, z = 0, rx = 0, ry = 0, rz = 0; + int pressed_mouse, pressed_kbd; + SDL_keysym keysym; + + posted = 0; + + /* FIXME: We do not actually want all events, only + * mouse and keyboard events. Having to handle all + * events will slow things down. */ + + ggiEventRead(VIS, &ev, emAll); +/* ggiEventRead(VIS, &ev, (emKeyboard | emPointer | emCommand)); */ + + switch (ev.any.type) + { + case evPtrRelative: + x = ev.pmove.x; + y = ev.pmove.y; + z = ev.pmove.wheel; + posted += SDL_PrivateMouseMotion(0, 1, x, y); + break; + case evPtrAbsolute: + if (mouse_x != ev.pmove.x || mouse_y != ev.pmove.y || mouse_z != ev.pmove.wheel) + { + x = ev.pmove.x - mouse_x; + y = ev.pmove.y - mouse_y; + z = ev.pmove.wheel - mouse_z; + mouse_x = ev.pmove.x; + mouse_y = ev.pmove.y; + mouse_z = ev.pmove.wheel; + posted += SDL_PrivateMouseMotion(0, 1, x, y); + } + break; + case evPtrButtonPress: + posted += SDL_PrivateMouseButton(SDL_PRESSED, ev.pbutton.button, 0, 0); + break; + case evPtrButtonRelease: + posted += SDL_PrivateMouseButton(SDL_RELEASED, ev.pbutton.button, 0, 0); + break; + case evKeyPress: + case evKeyRepeat: + posted += SDL_PrivateKeyboard(SDL_PRESSED, GGI_TranslateKey(&ev, &keysym)); + break; + case evKeyRelease: + posted += SDL_PrivateKeyboard(SDL_RELEASED, GGI_TranslateKey(&ev, &keysym)); + break; + case evCommand: + fprintf(stderr, "Command event %x recieved\n", ev.cmd.code); + break; + default: + fprintf(stderr, "Unhandled event type %d\n", ev.any.type); + break; + } + } + +} + +void GGI_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the GGI key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + + + +static SDL_keysym *GGI_TranslateKey(gii_event *ev, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = ev->key.button; + keysym->sym = keymap[ev->key.button]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if (SDL_TranslateUNICODE) + { + keysym->unicode = GII_UNICODE(ev->key.sym); + } + + return keysym; +} diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h b/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h new file mode 100644 index 0000000..2c66106 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggievents_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ggivideo.h" + +/* Functions to be exported */ +extern void GGI_InitOSKeymap(_THIS); +extern void GGI_PumpEvents(_THIS); + diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h b/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h new file mode 100644 index 0000000..2868ee6 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggikeys.h @@ -0,0 +1,135 @@ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 90 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 92 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 94 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c b/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c new file mode 100644 index 0000000..52c5337 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggimouse.c @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggimouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h b/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h new file mode 100644 index 0000000..c0ce295 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggimouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ggivideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c new file mode 100644 index 0000000..face495 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.c @@ -0,0 +1,378 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* GGI-based SDL video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +#include <ggi/ggi.h> +#include <ggi/gii.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ggivideo.h" +#include "SDL_ggimouse_c.h" +#include "SDL_ggievents_c.h" + + +struct private_hwdata +{ + ggi_visual_t vis; +}; + +ggi_visual_t VIS; + +/* Initialization/Query functions */ +static int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GGI_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void GGI_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GGI_LockHWSurface(_THIS, SDL_Surface *surface); +static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* GGI driver bootstrap functions */ + +static int GGI_Available(void) +{ + ggi_visual_t *vis; + + vis = NULL; + if (ggiInit() == 0) { + vis = ggiOpen(NULL); + if (vis != NULL) { + ggiClose(vis); + } + } + return (vis != NULL); +} + +static void GGI_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GGI_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = GGI_VideoInit; + device->ListModes = GGI_ListModes; + device->SetVideoMode = GGI_SetVideoMode; + device->SetColors = GGI_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = GGI_VideoQuit; + device->AllocHWSurface = GGI_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = GGI_LockHWSurface; + device->UnlockHWSurface = GGI_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = GGI_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = GGI_InitOSKeymap; + device->PumpEvents = GGI_PumpEvents; + + device->free = GGI_DeleteDevice; + + return device; +} + +VideoBootStrap GGI_bootstrap = { + "ggi", "General Graphics Interface (GGI)", + GGI_Available, GGI_CreateDevice +}; + + +static SDL_Rect video_mode; +static SDL_Rect *SDL_modelist[4] = { NULL, NULL, NULL, NULL }; + +int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + ggi_mode mode = + { + 1, + { GGI_AUTO, GGI_AUTO }, + { GGI_AUTO, GGI_AUTO }, + { 0, 0 }, + GT_AUTO, + { GGI_AUTO, GGI_AUTO } + }; + struct private_hwdata *priv; + ggi_color pal[256], map[256]; + const ggi_directbuffer *db; + int err, num_bufs; + ggi_pixel white, black; + + priv = SDL_malloc(sizeof(struct private_hwdata)); + if (priv == NULL) + { + SDL_SetError("Unhandled GGI mode type!\n"); + GGI_VideoQuit(NULL); + } + + if (ggiInit() != 0) + { + SDL_SetError("Unable to initialize GGI!\n"); + GGI_VideoQuit(NULL); + } + + VIS = ggiOpen(NULL); + if (VIS == NULL) + { + SDL_SetError("Unable to open default GGI visual!\n"); + ggiExit(); + GGI_VideoQuit(NULL); + } + + ggiSetFlags(VIS, GGIFLAG_ASYNC); + + /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ + ggiCheckMode(VIS, &mode); + + /* At this point we should have a valid mode - try to set it */ + err = ggiSetMode(VIS, &mode); + + /* If we couldn't set _any_ modes, something is very wrong */ + if (err) + { + SDL_SetError("Can't set a mode!\n"); + ggiClose(VIS); + ggiExit(); + GGI_VideoQuit(NULL); + } + + /* Determine the current screen size */ + this->info.current_w = mode.virt.x; + this->info.current_h = mode.virt.y; + + /* Set a palette for palletized modes */ + if (GT_SCHEME(mode.graphtype) == GT_PALETTE) + { + ggiSetColorfulPalette(VIS); + ggiGetPalette(VIS, 0, 1 << vformat->BitsPerPixel, pal); + } + + /* Now we try to get the DirectBuffer info, which determines whether + * SDL can access hardware surfaces directly. */ + + num_bufs = ggiDBGetNumBuffers(VIS); + + if (num_bufs > 0) + { + db = ggiDBGetBuffer(VIS, 0); /* Only handle one DB for now */ + + vformat->BitsPerPixel = db->buffer.plb.pixelformat->depth; + + vformat->Rmask = db->buffer.plb.pixelformat->red_mask; + vformat->Gmask = db->buffer.plb.pixelformat->green_mask; + vformat->Bmask = db->buffer.plb.pixelformat->blue_mask; + + /* Fill in our hardware acceleration capabilities */ + + this->info.wm_available = 0; + this->info.hw_available = 1; + this->info.video_mem = db->buffer.plb.stride * mode.virt.y; + } + + video_mode.x = 0; + video_mode.y = 0; + video_mode.w = mode.virt.x; + video_mode.h = mode.virt.y; + SDL_modelist[((vformat->BitsPerPixel + 7) / 8) - 1] = &video_mode; + + /* We're done! */ + return(0); +} + +static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(&SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]); +} + +/* Various screen update functions available */ +static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + ggi_mode mode = + { + 1, + { GGI_AUTO, GGI_AUTO }, + { GGI_AUTO, GGI_AUTO }, + { 0, 0 }, + GT_AUTO, + { GGI_AUTO, GGI_AUTO } + }; + const ggi_directbuffer *db; + ggi_color pal[256]; + int err; + + fprintf(stderr, "GGI_SetVideoMode()\n"); + + mode.visible.x = mode.virt.x = width; + mode.visible.y = mode.virt.y = height; + + /* Translate requested SDL bit depth into a GGI mode */ + switch (bpp) + { + case 1: mode.graphtype = GT_1BIT; break; + case 2: mode.graphtype = GT_2BIT; break; + case 4: mode.graphtype = GT_4BIT; break; + case 8: mode.graphtype = GT_8BIT; break; + case 15: mode.graphtype = GT_15BIT; break; + case 16: mode.graphtype = GT_16BIT; break; + case 24: mode.graphtype = GT_24BIT; break; + case 32: mode.graphtype = GT_32BIT; break; + default: + SDL_SetError("Unknown SDL bit depth, using GT_AUTO....\n"); + mode.graphtype = GT_AUTO; + } + + /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ + ggiCheckMode(VIS, &mode); + + /* At this point we should have a valid mode - try to set it */ + err = ggiSetMode(VIS, &mode); + + /* If we couldn't set _any_ modes, something is very wrong */ + if (err) + { + SDL_SetError("Can't set a mode!\n"); + ggiClose(VIS); + ggiExit(); + GGI_VideoQuit(NULL); + } + + /* Set a palette for palletized modes */ + if (GT_SCHEME(mode.graphtype) == GT_PALETTE) + { + ggiSetColorfulPalette(VIS); + ggiGetPalette(VIS, 0, 1 << bpp, pal); + } + + db = ggiDBGetBuffer(VIS, 0); + + /* Set up the new mode framebuffer */ + current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); + current->w = mode.virt.x; + current->h = mode.virt.y; + current->pitch = db->buffer.plb.stride; + current->pixels = db->read; + + /* Set the blit function */ + this->UpdateRects = GGI_DirectUpdate; + + /* We're done */ + return(current); +} + +static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int GGI_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + +/* ggiFlush(VIS); */ + + for (i = 0; i < numrects; i++) + { + ggiFlushRegion(VIS, rects[i].x, rects[i].y, rects[i].w, rects[i].h); + } + return; +} + +int GGI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + ggi_color pal[256]; + + /* Set up the colormap */ + for (i = 0; i < ncolors; i++) + { + pal[i].r = (colors[i].r << 8) | colors[i].r; + pal[i].g = (colors[i].g << 8) | colors[i].g; + pal[i].b = (colors[i].b << 8) | colors[i].b; + } + + ggiSetPalette(VIS, firstcolor, ncolors, pal); + + return 1; +} + +void GGI_VideoQuit(_THIS) +{ +} +void GGI_FinalQuit(void) +{ +} diff --git a/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h new file mode 100644 index 0000000..014dd09 --- /dev/null +++ b/3rdparty/SDL/src/video/ggi/SDL_ggivideo.h @@ -0,0 +1,48 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_ggivideo_h +#define _SDL_ggivideo_h + +#include <ggi/ggi.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#define _THIS SDL_VideoDevice *this + +/* Private display data */ + +struct SDL_PrivateVideoData +{ + ggi_visual_t *ggivis; +}; + +extern ggi_visual_t VIS; /* FIXME: use the private data struct */ + +extern int SDL_OpenKeyboard(void); +extern void SDL_CloseKeyboard(void); +extern int SDL_OpenMouse(void); +extern void SDL_CloseMouse(void); + +#endif /* _SDL_ggivideo_h */ diff --git a/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c new file mode 100644 index 0000000..a2f3db3 --- /dev/null +++ b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.c @@ -0,0 +1,733 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <termios.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> +#include <linux/fb.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents.h" +#include "SDL_ipodvideo.h" + +#define _THIS SDL_VideoDevice *this + +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects); +static void iPod_VideoQuit (_THIS); +static void iPod_PumpEvents (_THIS); + +static long iPod_GetGeneration(); + +static int initd = 0; +static int kbfd = -1; +static int fbfd = -1; +static int oldvt = -1; +static int curvt = -1; +static int old_kbmode = -1; +static long generation = 0; +static struct termios old_termios, cur_termios; + +FILE *dbgout; + +#define LCD_DATA 0x10 +#define LCD_CMD 0x08 +#define IPOD_OLD_LCD_BASE 0xc0001000 +#define IPOD_OLD_LCD_RTC 0xcf001110 +#define IPOD_NEW_LCD_BASE 0x70003000 +#define IPOD_NEW_LCD_RTC 0x60005010 + +static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height; + +static long iPod_GetGeneration() +{ + int i; + char cpuinfo[256]; + char *ptr; + FILE *file; + + if ((file = fopen("/proc/cpuinfo", "r")) != NULL) { + while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL) + if (SDL_strncmp(cpuinfo, "Revision", 8) == 0) + break; + fclose(file); + } + for (i = 0; !isspace(cpuinfo[i]); i++); + for (; isspace(cpuinfo[i]); i++); + ptr = cpuinfo + i + 2; + + return SDL_strtol(ptr, NULL, 10); +} + +static int iPod_Available() +{ + return 1; +} + +static void iPod_DeleteDevice (SDL_VideoDevice *device) +{ + free (device->hidden); + free (device); +} + +void iPod_InitOSKeymap (_THIS) {} + +static SDL_VideoDevice *iPod_CreateDevice (int devindex) +{ + SDL_VideoDevice *this; + + this = (SDL_VideoDevice *)SDL_malloc (sizeof(SDL_VideoDevice)); + if (this) { + memset (this, 0, sizeof *this); + this->hidden = (struct SDL_PrivateVideoData *) SDL_malloc (sizeof(struct SDL_PrivateVideoData)); + } + if (!this || !this->hidden) { + SDL_OutOfMemory(); + if (this) + SDL_free (this); + return 0; + } + memset (this->hidden, 0, sizeof(struct SDL_PrivateVideoData)); + + generation = iPod_GetGeneration(); + + this->VideoInit = iPod_VideoInit; + this->ListModes = iPod_ListModes; + this->SetVideoMode = iPod_SetVideoMode; + this->SetColors = iPod_SetColors; + this->UpdateRects = iPod_UpdateRects; + this->VideoQuit = iPod_VideoQuit; + this->AllocHWSurface = 0; + this->CheckHWBlit = 0; + this->FillHWRect = 0; + this->SetHWColorKey = 0; + this->SetHWAlpha = 0; + this->LockHWSurface = 0; + this->UnlockHWSurface = 0; + this->FlipHWSurface = 0; + this->FreeHWSurface = 0; + this->SetCaption = 0; + this->SetIcon = 0; + this->IconifyWindow = 0; + this->GrabInput = 0; + this->GetWMInfo = 0; + this->InitOSKeymap = iPod_InitOSKeymap; + this->PumpEvents = iPod_PumpEvents; + this->free = iPod_DeleteDevice; + + return this; +} + +VideoBootStrap iPod_bootstrap = { + "ipod", "iPod Framebuffer Driver", + iPod_Available, iPod_CreateDevice +}; + +//--// + +static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat) +{ + if (!initd) { + /*** Code adapted/copied from SDL fbcon driver. ***/ + + static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 }; + static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 }; + int i, tty0_fd; + + dbgout = fdopen (open ("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND), "a"); + if (dbgout) { + setbuf (dbgout, 0); + fprintf (dbgout, "--> Started SDL <--\n"); + } + + // Try to query for a free VT + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, &curvt); + close(tty0_fd); + + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + + if ( (geteuid() == 0) && (curvt > 0) ) { + for ( i=0; vcs[i] && (kbfd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], curvt); + kbfd = open(vtpath, O_RDWR); + } + } + if ( kbfd < 0 ) { + if (dbgout) fprintf (dbgout, "Couldn't open any VC\n"); + return -1; + } + if (dbgout) fprintf (stderr, "Current VT: %d\n", curvt); + + if (kbfd >= 0) { + /* Switch to the correct virtual terminal */ + if ( curvt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(kbfd, VT_GETSTATE, &vtstate) == 0 ) { + oldvt = vtstate.v_active; + } + if ( ioctl(kbfd, VT_ACTIVATE, curvt) == 0 ) { + if (dbgout) fprintf (dbgout, "Waiting for switch to this VT... "); + ioctl(kbfd, VT_WAITACTIVE, curvt); + if (dbgout) fprintf (dbgout, "done!\n"); + } + } + + // Set terminal input mode + if (tcgetattr (kbfd, &old_termios) < 0) { + if (dbgout) fprintf (dbgout, "Can't get termios\n"); + return -1; + } + cur_termios = old_termios; + // cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); + // cur_termios.c_iflag |= (BRKINT); + // cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN); + // cur_termios.c_oflag &= ~(OPOST); + // cur_termios.c_oflag |= (ONOCR | ONLRET); + cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + cur_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + cur_termios.c_cc[VMIN] = 0; + cur_termios.c_cc[VTIME] = 0; + + if (tcsetattr (kbfd, TCSAFLUSH, &cur_termios) < 0) { + if (dbgout) fprintf (dbgout, "Can't set termios\n"); + return -1; + } + if (ioctl (kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) { + if (dbgout) fprintf (dbgout, "Can't set medium-raw mode\n"); + return -1; + } + if (ioctl (kbfd, KDSETMODE, KD_GRAPHICS) < 0) { + if (dbgout) fprintf (dbgout, "Can't set graphics\n"); + return -1; + } + } + + // Open the framebuffer + if ((fbfd = open ("/dev/fb0", O_RDWR)) < 0) { + if (dbgout) fprintf (dbgout, "Can't open framebuffer\n"); + return -1; + } else { + struct fb_var_screeninfo vinfo; + + if (dbgout) fprintf (dbgout, "Generation: %ld\n", generation); + + if (generation >= 40000) { + lcd_base = IPOD_NEW_LCD_BASE; + } else { + lcd_base = IPOD_OLD_LCD_BASE; + } + + ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo); + close (fbfd); + + if (lcd_base == IPOD_OLD_LCD_BASE) + lcd_rtc = IPOD_OLD_LCD_RTC; + else if (lcd_base == IPOD_NEW_LCD_BASE) + lcd_rtc = IPOD_NEW_LCD_RTC; + else { + SDL_SetError ("Unknown iPod version"); + return -1; + } + + lcd_width = vinfo.xres; + lcd_height = vinfo.yres; + + if (dbgout) fprintf (dbgout, "LCD is %dx%d\n", lcd_width, lcd_height); + } + + fcntl (kbfd, F_SETFL, O_RDWR | O_NONBLOCK); + + /* Determine the current screen size */ + this->info.current_w = lcd_width; + this->info.current_h = lcd_height; + + if ((generation >= 60000) && (generation < 70000)) { + vformat->BitsPerPixel = 16; + vformat->Rmask = 0xF800; + vformat->Gmask = 0x07E0; + vformat->Bmask = 0x001F; + } else { + vformat->BitsPerPixel = 8; + vformat->Rmask = vformat->Gmask = vformat->Bmask = 0; + } + + initd = 1; + if (dbgout) fprintf (dbgout, "Initialized.\n\n"); + } + return 0; +} + +static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int width, height, fd; + static SDL_Rect r; + static SDL_Rect *rs[2] = { &r, 0 }; + + if ((fd = open ("/dev/fb0", O_RDWR)) < 0) { + return 0; + } else { + struct fb_var_screeninfo vinfo; + + ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo); + close (fbfd); + + width = vinfo.xres; + height = vinfo.yres; + } + r.x = r.y = 0; + r.w = width; + r.h = height; + return rs; +} + + +static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, + Uint32 flags) +{ + Uint32 Rmask, Gmask, Bmask; + if (bpp > 8) { + Rmask = 0xF800; + Gmask = 0x07E0; + Bmask = 0x001F; + } else { + Rmask = Gmask = Bmask = 0; + } + + if (this->hidden->buffer) SDL_free (this->hidden->buffer); + this->hidden->buffer = SDL_malloc (width * height * (bpp / 8)); + if (!this->hidden->buffer) { + SDL_SetError ("Couldn't allocate buffer for requested mode"); + return 0; + } + + memset (this->hidden->buffer, 0, width * height * (bpp / 8)); + + if (!SDL_ReallocFormat (current, bpp, Rmask, Gmask, Bmask, 0)) { + SDL_SetError ("Couldn't allocate new pixel format"); + SDL_free (this->hidden->buffer); + this->hidden->buffer = 0; + return 0; + } + + if (bpp <= 8) { + int i, j; + for (i = 0; i < 256; i += 4) { + for (j = 0; j < 4; j++) { + current->format->palette->colors[i+j].r = 85 * j; + current->format->palette->colors[i+j].g = 85 * j; + current->format->palette->colors[i+j].b = 85 * j; + } + } + } + + current->flags = flags & SDL_FULLSCREEN; + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pitch = current->w * (bpp / 8); + current->pixels = this->hidden->buffer; + + return current; +} + +static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + if (SDL_VideoSurface && SDL_VideoSurface->format && SDL_VideoSurface->format->palette) { + int i, j; + for (i = 0; i < 256; i += 4) { + for (j = 0; j < 4; j++) { + SDL_VideoSurface->format->palette->colors[i+j].r = 85 * j; + SDL_VideoSurface->format->palette->colors[i+j].g = 85 * j; + SDL_VideoSurface->format->palette->colors[i+j].b = 85 * j; + } + } + } + return 0; +} + +static void iPod_VideoQuit (_THIS) +{ + ioctl (kbfd, KDSETMODE, KD_TEXT); + tcsetattr (kbfd, TCSAFLUSH, &old_termios); + old_kbmode = -1; + + if (oldvt > 0) + ioctl (kbfd, VT_ACTIVATE, oldvt); + + if (kbfd > 0) + close (kbfd); + + if (dbgout) { + fprintf (dbgout, "<-- Ended SDL -->\n"); + fclose (dbgout); + } + + kbfd = -1; +} + +static char iPod_SC_keymap[] = { + 0, /* 0 - no key */ + '[' - 0x40, /* ESC (Ctrl+[) */ + '1', '2', '3', '4', '5', '6', '7', '8', '9', + '-', '=', + '\b', '\t', /* Backspace, Tab (Ctrl+H,Ctrl+I) */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + '\n', 0, /* Enter, Left CTRL */ + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', + 0, '\\', /* left shift, backslash */ + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, '*', 0, ' ', 0, /* right shift, KP mul, left alt, space, capslock */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */ + 0, 0, /* numlock, scrollock */ + '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */ + 0, 0, /* padding */ + 0, 0, 0, /* "less" (?), F11, F12 */ + 0, 0, 0, 0, 0, 0, 0, /* padding */ + '\n', 0, '/', 0, 0, /* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */ + 0, 0, /* Ins, Del */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */ + 0, 0, /* RWin, LWin */ + 0 /* no key */ +}; + + +static void iPod_keyboard() +{ + unsigned char keybuf[128]; + int i, nread; + SDL_keysym keysym; + SDL_Event ev; + + keysym.mod = 0; + keysym.scancode = 0xff; + memset (&ev, 0, sizeof(SDL_Event)); + + nread = read (kbfd, keybuf, 128); + for (i = 0; i < nread; i++) { + char ascii = iPod_SC_keymap[keybuf[i] & 0x7f]; + + if (dbgout) fprintf (dbgout, "Key! %02x is %c %s", keybuf[i], ascii, (keybuf[i] & 0x80)? "up" : "down"); + + keysym.sym = keysym.unicode = ascii; + ev.type = (keybuf[i] & 0x80)? SDL_KEYUP : SDL_KEYDOWN; + ev.key.state = 0; + ev.key.keysym = keysym; + SDL_PushEvent (&ev); + } +} + +static void iPod_PumpEvents (_THIS) +{ + fd_set fdset; + int max_fd = 0; + static struct timeval zero; + int posted; + + do { + posted = 0; + + FD_ZERO (&fdset); + if (kbfd >= 0) { + FD_SET (kbfd, &fdset); + max_fd = kbfd; + } + if (dbgout) fprintf (dbgout, "Selecting"); + if (select (max_fd + 1, &fdset, 0, 0, &zero) > 0) { + if (dbgout) fprintf (dbgout, " -> match!\n"); + iPod_keyboard(); + posted++; + } + if (dbgout) fprintf (dbgout, "\n"); + } while (posted); +} + +// enough space for 160x128x2 +static char ipod_scr[160 * (128/4)]; + +#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum)) +#define inl(addr) (*(volatile unsigned long *)(addr)) + +/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2, + file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/ + +/* get current usec counter */ +static int M_timer_get_current(void) +{ + return inl(lcd_rtc); +} + +/* check if number of useconds has past */ +static int M_timer_check(int clock_start, int usecs) +{ + unsigned long clock; + clock = inl(lcd_rtc); + + if ( (clock - clock_start) >= usecs ) { + return 1; + } else { + return 0; + } +} + +/* wait for LCD with timeout */ +static void M_lcd_wait_write(void) +{ + if ( (inl(lcd_base) & 0x8000) != 0 ) { + int start = M_timer_get_current(); + + do { + if ( (inl(lcd_base) & (unsigned int)0x8000) == 0 ) + break; + } while ( M_timer_check(start, 1000) == 0 ); + } +} + + +/* send LCD data */ +static void M_lcd_send_data(int data_lo, int data_hi) +{ + M_lcd_wait_write(); + + outl(data_lo, lcd_base + LCD_DATA); + + M_lcd_wait_write(); + + outl(data_hi, lcd_base + LCD_DATA); + +} + +/* send LCD command */ +static void +M_lcd_prepare_cmd(int cmd) +{ + M_lcd_wait_write(); + + outl(0x0, lcd_base + LCD_CMD); + + M_lcd_wait_write(); + + outl(cmd, lcd_base + LCD_CMD); + +} + +/* send LCD command and data */ +static void M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi) +{ + M_lcd_prepare_cmd(cmd); + + M_lcd_send_data(data_lo, data_hi); +} + +// Copied from uW +static void M_update_display(int sx, int sy, int mx, int my) +{ + int y; + unsigned short cursor_pos; + + sx >>= 3; + mx >>= 3; + + cursor_pos = sx + (sy << 5); + + for ( y = sy; y <= my; y++ ) { + unsigned char *img_data; + int x; + + /* move the cursor */ + M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff); + + /* setup for printing */ + M_lcd_prepare_cmd(0x12); + + img_data = ipod_scr + (sx << 1) + (y * (lcd_width/4)); + + /* loops up to 160 times */ + for ( x = sx; x <= mx; x++ ) { + /* display eight pixels */ + M_lcd_send_data(*(img_data + 1), *img_data); + + img_data += 2; + } + + /* update cursor pos counter */ + cursor_pos += 0x20; + } +} + +/* get current usec counter */ +static int C_timer_get_current(void) +{ + return inl(0x60005010); +} + +/* check if number of useconds has past */ +static int C_timer_check(int clock_start, int usecs) +{ + unsigned long clock; + clock = inl(0x60005010); + + if ( (clock - clock_start) >= usecs ) { + return 1; + } else { + return 0; + } +} + +/* wait for LCD with timeout */ +static void C_lcd_wait_write(void) +{ + if ((inl(0x70008A0C) & 0x80000000) != 0) { + int start = C_timer_get_current(); + + do { + if ((inl(0x70008A0C) & 0x80000000) == 0) + break; + } while (C_timer_check(start, 1000) == 0); + } +} +static void C_lcd_cmd_data(int cmd, int data) +{ + C_lcd_wait_write(); + outl(cmd | 0x80000000, 0x70008A0C); + + C_lcd_wait_write(); + outl(data | 0x80000000, 0x70008A0C); +} + +static void C_update_display(int sx, int sy, int mx, int my) +{ + int height = (my - sy) + 1; + int width = (mx - sx) + 1; + + char *addr = SDL_VideoSurface->pixels; + + if (width & 1) width++; + + /* start X and Y */ + C_lcd_cmd_data(0x12, (sy & 0xff)); + C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff)); + + /* max X and Y */ + C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff)); + C_lcd_cmd_data(0x16, (((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff)); + + addr += sx + sy * SDL_VideoSurface->pitch; + + while (height > 0) { + int h, x, y, pixels_to_write; + + pixels_to_write = (width * height) * 2; + + /* calculate how much we can do in one go */ + h = height; + if (pixels_to_write > 64000) { + h = (64000/2) / width; + pixels_to_write = (width * h) * 2; + } + + outl(0x10000080, 0x70008A20); + outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24); + outl(0x34000000, 0x70008A20); + + /* for each row */ + for (x = 0; x < h; x++) + { + /* for each column */ + for (y = 0; y < width; y += 2) { + unsigned two_pixels; + + two_pixels = addr[0] | (addr[1] << 16); + addr += 2; + + while ((inl(0x70008A20) & 0x1000000) == 0); + + /* output 2 pixels */ + outl(two_pixels, 0x70008B00); + } + + addr += SDL_VideoSurface->w - width; + } + + while ((inl(0x70008A20) & 0x4000000) == 0); + + outl(0x0, 0x70008A24); + + height = height - h; + } +} + +// Should work with photo. However, I don't have one, so I'm not sure. +static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects) +{ + if (SDL_VideoSurface->format->BitsPerPixel == 16) { + C_update_display (0, 0, lcd_width, lcd_height); + } else { + int i, y, x; + for (i = 0; i < nrects; i++) { + SDL_Rect *r = rects + i; + if (!r) { + continue; + } + + for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) { + for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) { + ipod_scr[y*(lcd_width/4) + x/4] &= ~(3 << (2 * (x%4))); + ipod_scr[y*(lcd_width/4) + x/4] |= + (((Uint8*)(SDL_VideoSurface->pixels))[ y*SDL_VideoSurface->pitch + x ] & 3) << (2 * (x%4)); + } + } + } + + M_update_display (0, 0, lcd_width, lcd_height); + } +} diff --git a/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h new file mode 100644 index 0000000..921eee8 --- /dev/null +++ b/3rdparty/SDL/src/video/ipod/SDL_ipodvideo.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* iPod SDL framebuffer driver + * Joshua Oreman + * Main header file + */ + +#ifndef _SDL_ipodvideo_h +#define _SDL_ipodvideo_h + +struct SDL_PrivateVideoData { + char *buffer; + int w, h; +}; + + +#endif diff --git a/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h b/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h new file mode 100644 index 0000000..f3dac29 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_lowvideo.h @@ -0,0 +1,102 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Quickdraw.h> +#include <Palettes.h> +#include <Menus.h> +#include <DrawSprocket.h> +#endif + +#if SDL_VIDEO_OPENGL +typedef struct __AGLContextRec *AGLContext; +#endif + +#include "SDL_video.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#if !TARGET_API_MAC_CARBON /* not available in OS X (or more accurately, Carbon) */ +/* Global QuickDraw data */ +extern QDGlobals *theQD; +#endif + +/* Private display data */ +struct SDL_PrivateVideoData { + GDevice **SDL_Display; + WindowRef SDL_Window; + SDL_Rect **SDL_modelist; + CTabHandle SDL_CTab; + PaletteHandle SDL_CPal; + +#if TARGET_API_MAC_CARBON + /* For entering and leaving fullscreen mode */ + Ptr fullscreen_ctx; +#endif + + /* The current window document style */ + int current_style; + + /* Information about the last cursor position */ + Point last_where; + + /* Information about the last keys down */ + EventModifiers last_mods; + KeyMap last_keys; + + /* A handle to the Apple Menu */ + MenuRef apple_menu; + + /* Information used by DrawSprocket driver */ + struct DSpInfo *dspinfo; + +#if SDL_VIDEO_OPENGL + AGLContext appleGLContext; + + void *libraryHandle; +#endif +}; +/* Old variable names */ +#define SDL_Display (this->hidden->SDL_Display) +#define SDL_Window (this->hidden->SDL_Window) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_CTab (this->hidden->SDL_CTab) +#define SDL_CPal (this->hidden->SDL_CPal) +#define fullscreen_ctx (this->hidden->fullscreen_ctx) +#define current_style (this->hidden->current_style) +#define last_where (this->hidden->last_where) +#define last_mods (this->hidden->last_mods) +#define last_keys (this->hidden->last_keys) +#define apple_menu (this->hidden->apple_menu) +#define glContext (this->hidden->appleGLContext) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macevents.c b/3rdparty/SDL/src/video/maccommon/SDL_macevents.c new file mode 100644 index 0000000..6e3fef2 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macevents.c @@ -0,0 +1,746 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Script.h> +#include <LowMem.h> +#include <Devices.h> +#include <DiskInit.h> +#include <ToolUtils.h> +#endif + +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_sysevents.h" +#include "../SDL_cursor_c.h" +#include "SDL_macevents_c.h" +#include "SDL_mackeys.h" +#include "SDL_macmouse_c.h" + +/* Define this to be able to collapse SDL windows. +#define USE_APPEARANCE_MANAGER + */ + +/* Macintosh resource constants */ +#define mApple 128 /* Apple menu resource */ +#define iAbout 1 /* About menu item */ + +/* Functions to handle the About menu */ +static void Mac_DoAppleMenu(_THIS, long item); + +/* The translation table from a macintosh key scancode to a SDL keysym */ +static SDLKey MAC_keymap[256]; +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed); + +/* Handle activation and deactivation -- returns whether an event was posted */ +static int Mac_HandleActivate(int activate) +{ + if ( activate ) { + /* Show the current SDL application cursor */ + SDL_SetCursor(NULL); + + /* put our mask back case it changed during context switch */ + SetEventMask(everyEvent & ~autoKeyMask); + } else { +#if TARGET_API_MAC_CARBON + { Cursor cursor; + SetCursor(GetQDGlobalsArrow(&cursor)); + } +#else + SetCursor(&theQD->arrow); +#endif + if ( ! Mac_cursor_showing ) { + ShowCursor(); + Mac_cursor_showing = 1; + } + } + return(SDL_PrivateAppActive(activate, SDL_APPINPUTFOCUS)); +} + +static void myGlobalToLocal(_THIS, Point *pt) +{ + if ( SDL_VideoSurface && !(SDL_VideoSurface->flags&SDL_FULLSCREEN) ) { + GrafPtr saveport; + GetPort(&saveport); +#if TARGET_API_MAC_CARBON + SetPort(GetWindowPort(SDL_Window)); +#else + SetPort(SDL_Window); +#endif + GlobalToLocal(pt); + SetPort(saveport); + } +} + +/* The main MacOS event handler */ +static int Mac_HandleEvents(_THIS, int wait4it) +{ + static int mouse_button = 1; + int i; + EventRecord event; + +#if TARGET_API_MAC_CARBON + /* There's no GetOSEvent() in the Carbon API. *sigh* */ +#define cooperative_multitasking 1 +#else + int cooperative_multitasking; + /* If we're running fullscreen, we can hog the MacOS events, + otherwise we had better play nicely with the other apps. + */ + if ( this->screen && (this->screen->flags & SDL_FULLSCREEN) ) { + cooperative_multitasking = 0; + } else { + cooperative_multitasking = 1; + } +#endif + + /* If we call WaitNextEvent(), MacOS will check other processes + * and allow them to run, and perform other high-level processing. + */ + if ( cooperative_multitasking || wait4it ) { + UInt32 wait_time; + + /* Are we polling or not? */ + if ( wait4it ) { + wait_time = 2147483647; + } else { + wait_time = 0; + } + WaitNextEvent(everyEvent, &event, wait_time, nil); + } else { +#if ! TARGET_API_MAC_CARBON + GetOSEvent(everyEvent, &event); +#endif + } + +#if TARGET_API_MAC_CARBON + /* for some reason, event.where isn't set ? */ + GetGlobalMouse ( &event.where ); +#endif + + /* Check for mouse motion */ + if ( (event.where.h != last_where.h) || + (event.where.v != last_where.v) ) { + Point pt; + pt = last_where = event.where; + myGlobalToLocal(this, &pt); + SDL_PrivateMouseMotion(0, 0, pt.h, pt.v); + } + + /* Check the current state of the keyboard */ + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + KeyMap keys; + const Uint32 *keysptr = (Uint32 *) &keys; + const Uint32 *last_keysptr = (Uint32 *) &last_keys; + + /* Check for special non-event keys */ + if ( event.modifiers != last_mods ) { + static struct { + EventModifiers mask; + SDLKey key; + } mods[] = { + { alphaLock, SDLK_CAPSLOCK }, +#if 0 /* These are handled below in the GetKeys() code */ + { cmdKey, SDLK_LMETA }, + { shiftKey, SDLK_LSHIFT }, + { rightShiftKey, SDLK_RSHIFT }, + { optionKey, SDLK_LALT }, + { rightOptionKey, SDLK_RALT }, + { controlKey, SDLK_LCTRL }, + { rightControlKey, SDLK_RCTRL }, +#endif /* 0 */ + { 0, 0 } + }; + SDL_keysym keysym; + Uint8 mode; + EventModifiers mod, mask; + + + /* Set up the keyboard event */ + keysym.scancode = 0; + keysym.sym = SDLK_UNKNOWN; + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + /* See what has changed, and generate events */ + mod = event.modifiers; + for ( i=0; mods[i].mask; ++i ) { + mask = mods[i].mask; + if ( (mod&mask) != (last_mods&mask) ) { + keysym.sym = mods[i].key; + if ( (mod&mask) || + (mods[i].key == SDLK_CAPSLOCK) ) { + mode = SDL_PRESSED; + } else { + mode = SDL_RELEASED; + } + SDL_PrivateKeyboard(mode, &keysym); + } + } + + /* Save state for next time */ + last_mods = mod; + } + + /* Check for normal event keys, but we have to scan the + actual keyboard state because on Mac OS X a keydown event + is immediately followed by a keyup event. + */ + GetKeys(keys); + if ( (keysptr[0] != last_keysptr[0]) || + (keysptr[1] != last_keysptr[1]) || + (keysptr[2] != last_keysptr[2]) || + (keysptr[3] != last_keysptr[3]) ) { + SDL_keysym keysym; + int old_bit, new_bit; + +#ifdef DEBUG_KEYBOARD + fprintf(sterr, "New keys: 0x%x 0x%x 0x%x 0x%x\n", + new_keys[0], new_keys[1], + new_keys[2], new_keys[3]); +#endif + for ( i=0; i<128; ++i ) { + old_bit = (((Uint8 *)last_keys)[i/8]>>(i%8)) & 0x01; + new_bit = (((Uint8 *)keys)[i/8]>>(i%8)) & 0x01; + if ( old_bit != new_bit ) { + /* Post the keyboard event */ +#ifdef DEBUG_KEYBOARD + fprintf(stderr,"Scancode: 0x%2.2X\n",i); +#endif + SDL_PrivateKeyboard(new_bit, + TranslateKey(i, event.modifiers, + &keysym, new_bit)); + } + } + + /* Save state for next time */ + last_keys[0] = keys[0]; + last_keys[1] = keys[1]; + last_keys[2] = keys[2]; + last_keys[3] = keys[3]; + } + } + + /* Handle normal events */ + switch (event.what) { + case mouseDown: { + WindowRef win; + short area; + + area = FindWindow(event.where, &win); + /* Support switching between the SIOUX console + and SDL_Window by clicking in the window. + */ + if ( win && (win != FrontWindow()) ) { + SelectWindow(win); + } + switch (area) { + case inMenuBar: /* Only the apple menu exists */ + Mac_DoAppleMenu(this, MenuSelect(event.where)); + HiliteMenu(0); + break; + case inDrag: +#if TARGET_API_MAC_CARBON + DragWindow(win, event.where, NULL); +#else + DragWindow(win, event.where, &theQD->screenBits.bounds); +#endif + break; + case inGoAway: + if ( TrackGoAway(win, event.where) ) { + SDL_PrivateQuit(); + } + break; + case inContent: + myGlobalToLocal(this, &event.where); + /* Treat command-click as right mouse button */ + if ( event.modifiers & optionKey ) { + mouse_button = 2; + } else if ( event.modifiers & cmdKey ) { + mouse_button = 3; + } else { + mouse_button = 1; + } + SDL_PrivateMouseButton(SDL_PRESSED, + mouse_button, event.where.h, event.where.v); + break; + case inGrow: { + int newSize; + + /* Don't allow resize if video mode isn't resizable */ + if ( ! SDL_PublicSurface || + ! (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + break; + } +#if TARGET_API_MAC_CARBON + newSize = GrowWindow(win, event.where, NULL); +#else + newSize = GrowWindow(win, event.where, &theQD->screenBits.bounds); +#endif + if ( newSize ) { +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + SizeWindow ( win, LoWord (newSize), HiWord (newSize), 1 ); + SDL_PrivateResize ( LoWord (newSize), HiWord (newSize) ); + } + } break; + case inZoomIn: + case inZoomOut: + if ( TrackBox (win, event.where, area )) { + Rect rect; +#if !TARGET_API_MAC_CARBON + EraseRect ( &theQD->screenBits.bounds ); +#endif + ZoomWindow ( win, area, 0); + if ( area == inZoomIn ) { + GetWindowUserState(SDL_Window, &rect); + } else { + GetWindowStandardState(SDL_Window, &rect); + } + SDL_PrivateResize (rect.right-rect.left, + rect.bottom-rect.top); + } + break; +#if TARGET_API_MAC_CARBON + case inCollapseBox: + if ( TrackBox (win, event.where, area )) { + if ( IsWindowCollapsable(win) ) { + CollapseWindow (win, !IsWindowCollapsed(win)); + /* There should be something done like in inGrow case, but... */ + } + } + break; +#endif /* TARGET_API_MAC_CARBON */ + case inSysWindow: +#if TARGET_API_MAC_CARBON + /* Never happens in Carbon? */ +#else + SystemClick(&event, win); +#endif + break; + default: + break; + } + } + break; + case mouseUp: { + myGlobalToLocal(this, &event.where); + /* Release the mouse button we simulated in the last press. + The drawback of this methos is we cannot press more than + one button. However, this doesn't matter, since there is + only a single logical mouse button, even if you have a + multi-button mouse, this doesn't matter at all. + */ + SDL_PrivateMouseButton(SDL_RELEASED, + mouse_button, event.where.h, event.where.v); + } + break; +#if 0 /* Handled above the switch statement */ + case keyDown: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 1)); + } + break; + case keyUp: { + SDL_keysym keysym; + + SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey((event.message&keyCodeMask)>>8 + event.modifiers, &keysym, 0)); + } + break; +#endif + case updateEvt: { + BeginUpdate(SDL_Window); + #if SDL_VIDEO_OPENGL + if (SDL_VideoSurface->flags & SDL_OPENGL) + SDL_GL_SwapBuffers(); + else + #endif + if ( (SDL_VideoSurface->flags & SDL_HWSURFACE) == + SDL_SWSURFACE ) { + SDL_UpdateRect(SDL_VideoSurface, 0, 0, 0, 0); + } + EndUpdate(SDL_Window); + } + /* If this was an update event for the SIOUX console, we return 0 + in order to stop an endless series of updates being triggered. + */ + if ( (WindowRef) event.message != SDL_Window ) { + return 0; + } + break; + case activateEvt: { + Mac_HandleActivate(!!(event.modifiers & activeFlag)); + } + break; + case diskEvt: { +#if TARGET_API_MAC_CARBON + /* What are we supposed to do? */; +#else + if ( ((event.message>>16)&0xFFFF) != noErr ) { + Point spot; + SetPt(&spot, 0x0070, 0x0050); + DIBadMount(spot, event.message); + } +#endif + } + break; + case osEvt: { + switch ((event.message>>24) & 0xFF) { +#if 0 /* Handled above the switch statement */ + case mouseMovedMessage: { + myGlobalToLocal(this, &event.where); + SDL_PrivateMouseMotion(0, 0, + event.where.h, event.where.v); + } + break; +#endif /* 0 */ + case suspendResumeMessage: { + Mac_HandleActivate(!!(event.message & resumeFlag)); + } + break; + } + } + break; + default: { + ; + } + break; + } + return (event.what != nullEvent); +} + + +void Mac_PumpEvents(_THIS) +{ + /* Process pending MacOS events */ + while ( Mac_HandleEvents(this, 0) ) { + /* Loop and check again */; + } +} + +void Mac_InitOSKeymap(_THIS) +{ + const void *KCHRPtr; + UInt32 state; + UInt32 value; + int i; + int world = SDLK_WORLD_0; + + /* Map the MAC keysyms */ + for ( i=0; i<SDL_arraysize(MAC_keymap); ++i ) + MAC_keymap[i] = SDLK_UNKNOWN; + + /* Defined MAC_* constants */ + MAC_keymap[MK_ESCAPE] = SDLK_ESCAPE; + MAC_keymap[MK_F1] = SDLK_F1; + MAC_keymap[MK_F2] = SDLK_F2; + MAC_keymap[MK_F3] = SDLK_F3; + MAC_keymap[MK_F4] = SDLK_F4; + MAC_keymap[MK_F5] = SDLK_F5; + MAC_keymap[MK_F6] = SDLK_F6; + MAC_keymap[MK_F7] = SDLK_F7; + MAC_keymap[MK_F8] = SDLK_F8; + MAC_keymap[MK_F9] = SDLK_F9; + MAC_keymap[MK_F10] = SDLK_F10; + MAC_keymap[MK_F11] = SDLK_F11; + MAC_keymap[MK_F12] = SDLK_F12; + MAC_keymap[MK_PRINT] = SDLK_PRINT; + MAC_keymap[MK_SCROLLOCK] = SDLK_SCROLLOCK; + MAC_keymap[MK_PAUSE] = SDLK_PAUSE; + MAC_keymap[MK_POWER] = SDLK_POWER; + MAC_keymap[MK_BACKQUOTE] = SDLK_BACKQUOTE; + MAC_keymap[MK_1] = SDLK_1; + MAC_keymap[MK_2] = SDLK_2; + MAC_keymap[MK_3] = SDLK_3; + MAC_keymap[MK_4] = SDLK_4; + MAC_keymap[MK_5] = SDLK_5; + MAC_keymap[MK_6] = SDLK_6; + MAC_keymap[MK_7] = SDLK_7; + MAC_keymap[MK_8] = SDLK_8; + MAC_keymap[MK_9] = SDLK_9; + MAC_keymap[MK_0] = SDLK_0; + MAC_keymap[MK_MINUS] = SDLK_MINUS; + MAC_keymap[MK_EQUALS] = SDLK_EQUALS; + MAC_keymap[MK_BACKSPACE] = SDLK_BACKSPACE; + MAC_keymap[MK_INSERT] = SDLK_INSERT; + MAC_keymap[MK_HOME] = SDLK_HOME; + MAC_keymap[MK_PAGEUP] = SDLK_PAGEUP; + MAC_keymap[MK_NUMLOCK] = SDLK_NUMLOCK; + MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS; + MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE; + MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + MAC_keymap[MK_TAB] = SDLK_TAB; + MAC_keymap[MK_q] = SDLK_q; + MAC_keymap[MK_w] = SDLK_w; + MAC_keymap[MK_e] = SDLK_e; + MAC_keymap[MK_r] = SDLK_r; + MAC_keymap[MK_t] = SDLK_t; + MAC_keymap[MK_y] = SDLK_y; + MAC_keymap[MK_u] = SDLK_u; + MAC_keymap[MK_i] = SDLK_i; + MAC_keymap[MK_o] = SDLK_o; + MAC_keymap[MK_p] = SDLK_p; + MAC_keymap[MK_LEFTBRACKET] = SDLK_LEFTBRACKET; + MAC_keymap[MK_RIGHTBRACKET] = SDLK_RIGHTBRACKET; + MAC_keymap[MK_BACKSLASH] = SDLK_BACKSLASH; + MAC_keymap[MK_DELETE] = SDLK_DELETE; + MAC_keymap[MK_END] = SDLK_END; + MAC_keymap[MK_PAGEDOWN] = SDLK_PAGEDOWN; + MAC_keymap[MK_KP7] = SDLK_KP7; + MAC_keymap[MK_KP8] = SDLK_KP8; + MAC_keymap[MK_KP9] = SDLK_KP9; + MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS; + MAC_keymap[MK_CAPSLOCK] = SDLK_CAPSLOCK; + MAC_keymap[MK_a] = SDLK_a; + MAC_keymap[MK_s] = SDLK_s; + MAC_keymap[MK_d] = SDLK_d; + MAC_keymap[MK_f] = SDLK_f; + MAC_keymap[MK_g] = SDLK_g; + MAC_keymap[MK_h] = SDLK_h; + MAC_keymap[MK_j] = SDLK_j; + MAC_keymap[MK_k] = SDLK_k; + MAC_keymap[MK_l] = SDLK_l; + MAC_keymap[MK_SEMICOLON] = SDLK_SEMICOLON; + MAC_keymap[MK_QUOTE] = SDLK_QUOTE; + MAC_keymap[MK_RETURN] = SDLK_RETURN; + MAC_keymap[MK_KP4] = SDLK_KP4; + MAC_keymap[MK_KP5] = SDLK_KP5; + MAC_keymap[MK_KP6] = SDLK_KP6; + MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS; + MAC_keymap[MK_LSHIFT] = SDLK_LSHIFT; + MAC_keymap[MK_z] = SDLK_z; + MAC_keymap[MK_x] = SDLK_x; + MAC_keymap[MK_c] = SDLK_c; + MAC_keymap[MK_v] = SDLK_v; + MAC_keymap[MK_b] = SDLK_b; + MAC_keymap[MK_n] = SDLK_n; + MAC_keymap[MK_m] = SDLK_m; + MAC_keymap[MK_COMMA] = SDLK_COMMA; + MAC_keymap[MK_PERIOD] = SDLK_PERIOD; + MAC_keymap[MK_SLASH] = SDLK_SLASH; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RSHIFT] = SDLK_RSHIFT; +#endif + MAC_keymap[MK_UP] = SDLK_UP; + MAC_keymap[MK_KP1] = SDLK_KP1; + MAC_keymap[MK_KP2] = SDLK_KP2; + MAC_keymap[MK_KP3] = SDLK_KP3; + MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_LCTRL] = SDLK_LCTRL; + MAC_keymap[MK_LALT] = SDLK_LALT; + MAC_keymap[MK_LMETA] = SDLK_LMETA; + MAC_keymap[MK_SPACE] = SDLK_SPACE; +#if 0 /* These are the same as the left versions - use left by default */ + MAC_keymap[MK_RMETA] = SDLK_RMETA; + MAC_keymap[MK_RALT] = SDLK_RALT; + MAC_keymap[MK_RCTRL] = SDLK_RCTRL; +#endif + MAC_keymap[MK_LEFT] = SDLK_LEFT; + MAC_keymap[MK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_KP0] = SDLK_KP0; + MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD; + +#if defined(__APPLE__) && defined(__MACH__) + /* Wierd, these keys are on my iBook under Mac OS X + Note that the left arrow keysym is the same as left ctrl!? + */ + MAC_keymap[MK_IBOOK_ENTER] = SDLK_KP_ENTER; + MAC_keymap[MK_IBOOK_RIGHT] = SDLK_RIGHT; + MAC_keymap[MK_IBOOK_DOWN] = SDLK_DOWN; + MAC_keymap[MK_IBOOK_UP] = SDLK_UP; + MAC_keymap[MK_IBOOK_LEFT] = SDLK_LEFT; +#endif /* Mac OS X */ + + /* Up there we setup a static scancode->keysym map. However, it will not + * work very well on international keyboard. Hence we now query MacOS + * for its own keymap to adjust our own mapping table. However, this is + * bascially only useful for ascii char keys. This is also the reason + * why we keep the static table, too. + */ + + /* Get a pointer to the systems cached KCHR */ + KCHRPtr = (void *)GetScriptManagerVariable(smKCHRCache); + if (KCHRPtr) + { + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) + { + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + /* Now translate the key code to a key value */ + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* If the state become 0, it was a dead key. We need to translate again, + passing in the new state, to get the actual key value */ + if (state != 0) + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ + if (value >= 128) /* Some non-ASCII char, map it to SDLK_WORLD_* */ + MAC_keymap[i] = world++; + else if (value >= 32) /* non-control ASCII char */ + MAC_keymap[i] = value; + } + } + + /* The keypad codes are re-setup here, because the loop above cannot + * distinguish between a key on the keypad and a regular key. We maybe + * could get around this problem in another fashion: NSEvent's flags + * include a "NSNumericPadKeyMask" bit; we could check that and modify + * the symbol we return on the fly. However, this flag seems to exhibit + * some weird behaviour related to the num lock key + */ + MAC_keymap[MK_KP0] = SDLK_KP0; + MAC_keymap[MK_KP1] = SDLK_KP1; + MAC_keymap[MK_KP2] = SDLK_KP2; + MAC_keymap[MK_KP3] = SDLK_KP3; + MAC_keymap[MK_KP4] = SDLK_KP4; + MAC_keymap[MK_KP5] = SDLK_KP5; + MAC_keymap[MK_KP6] = SDLK_KP6; + MAC_keymap[MK_KP7] = SDLK_KP7; + MAC_keymap[MK_KP8] = SDLK_KP8; + MAC_keymap[MK_KP9] = SDLK_KP9; + MAC_keymap[MK_KP_MINUS] = SDLK_KP_MINUS; + MAC_keymap[MK_KP_PLUS] = SDLK_KP_PLUS; + MAC_keymap[MK_KP_PERIOD] = SDLK_KP_PERIOD; + MAC_keymap[MK_KP_EQUALS] = SDLK_KP_EQUALS; + MAC_keymap[MK_KP_DIVIDE] = SDLK_KP_DIVIDE; + MAC_keymap[MK_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + MAC_keymap[MK_KP_ENTER] = SDLK_KP_ENTER; +} + +static SDL_keysym *TranslateKey(int scancode, int modifiers, + SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = MAC_keymap[keysym->scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + static unsigned long state = 0; + static Ptr keymap = nil; + Ptr new_keymap; + + /* Get the current keyboard map resource */ + new_keymap = (Ptr)GetScriptManagerVariable(smKCHRCache); + if ( new_keymap != keymap ) { + keymap = new_keymap; + state = 0; + } + keysym->unicode = KeyTranslate(keymap, + keysym->scancode|modifiers, &state) & 0xFFFF; + } + return(keysym); +} + +void Mac_InitEvents(_THIS) +{ + /* Create apple menu bar */ + apple_menu = GetMenu(mApple); + if ( apple_menu != nil ) { + AppendResMenu(apple_menu, 'DRVR'); + InsertMenu(apple_menu, 0); + } + DrawMenuBar(); + + /* Get rid of spurious events at startup */ + FlushEvents(everyEvent, 0); + + /* Allow every event but keyrepeat */ + SetEventMask(everyEvent & ~autoKeyMask); +} + +void Mac_QuitEvents(_THIS) +{ + ClearMenuBar(); + if ( apple_menu != nil ) { + ReleaseResource((char **)apple_menu); + } + + /* Clean up pending events */ + FlushEvents(everyEvent, 0); +} + +static void Mac_DoAppleMenu(_THIS, long choice) +{ +#if !TARGET_API_MAC_CARBON /* No Apple menu in OS X */ + short menu, item; + + item = (choice&0xFFFF); + choice >>= 16; + menu = (choice&0xFFFF); + + switch (menu) { + case mApple: { + switch (item) { + case iAbout: { + /* Run the about box */; + } + break; + default: { + Str255 name; + + GetMenuItemText(apple_menu, item, name); + OpenDeskAcc(name); + } + break; + } + } + break; + default: { + /* Ignore other menus */; + } + } +#endif /* !TARGET_API_MAC_CARBON */ +} + +#if !TARGET_API_MAC_CARBON +/* Since we don't initialize QuickDraw, we need to get a pointer to qd */ +struct QDGlobals *theQD = NULL; +#endif + +/* Exported to the macmain code */ +void SDL_InitQuickDraw(struct QDGlobals *the_qd) +{ +#if !TARGET_API_MAC_CARBON + theQD = the_qd; +#endif +} diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h new file mode 100644 index 0000000..f9a983b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macevents_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions exported by SDL_macevents.c for the video subsystem +*/ +extern void Mac_InitEvents(_THIS); +extern void Mac_QuitEvents(_THIS); + +extern void Mac_InitOSKeymap(_THIS); +extern void Mac_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macgl.c b/3rdparty/SDL/src/video/maccommon/SDL_macgl.c new file mode 100644 index 0000000..b7ded9b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macgl.c @@ -0,0 +1,197 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* AGL implementation of SDL OpenGL support */ + +#include "SDL_lowvideo.h" +#include "SDL_macgl_c.h" +#include "SDL_loadso.h" + + +/* krat: adding OpenGL support */ +int Mac_GL_Init(_THIS) +{ +#if SDL_VIDEO_OPENGL + AGLPixelFormat format; + int i = 0; + GLint attributes [ 26 ]; /* 26 is max possible in this setup */ + GLboolean noerr; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( Mac_GL_LoadLibrary(this, NULL) < 0 ) { + return(-1); + } + } + + attributes[i++] = AGL_RGBA; + if ( this->gl_config.red_size != 0 && + this->gl_config.blue_size != 0 && + this->gl_config.green_size != 0 ) { + attributes[i++] = AGL_RED_SIZE; + attributes[i++] = this->gl_config.red_size; + attributes[i++] = AGL_GREEN_SIZE; + attributes[i++] = this->gl_config.green_size; + attributes[i++] = AGL_BLUE_SIZE; + attributes[i++] = this->gl_config.blue_size; + attributes[i++] = AGL_ALPHA_SIZE; + attributes[i++] = this->gl_config.alpha_size; + } + if ( this->gl_config.double_buffer ) { + attributes[i++] = AGL_DOUBLEBUFFER; + } + if ( this->gl_config.depth_size != 0 ) { + attributes[i++] = AGL_DEPTH_SIZE; + attributes[i++] = this->gl_config.depth_size; + } + if ( this->gl_config.stencil_size != 0 ) { + attributes[i++] = AGL_STENCIL_SIZE; + attributes[i++] = this->gl_config.stencil_size; + } + if ( this->gl_config.accum_red_size != 0 && + this->gl_config.accum_blue_size != 0 && + this->gl_config.accum_green_size != 0 ) { + + attributes[i++] = AGL_ACCUM_RED_SIZE; + attributes[i++] = this->gl_config.accum_red_size; + attributes[i++] = AGL_ACCUM_GREEN_SIZE; + attributes[i++] = this->gl_config.accum_green_size; + attributes[i++] = AGL_ACCUM_BLUE_SIZE; + attributes[i++] = this->gl_config.accum_blue_size; + attributes[i++] = AGL_ACCUM_ALPHA_SIZE; + attributes[i++] = this->gl_config.accum_alpha_size; + } + if ( this->gl_config.stereo ) { + attributes[i++] = AGL_STEREO; + } +#if defined(AGL_SAMPLE_BUFFERS_ARB) && defined(AGL_SAMPLES_ARB) + if ( this->gl_config.multisamplebuffers != 0 ) { + attributes[i++] = AGL_SAMPLE_BUFFERS_ARB; + attributes[i++] = this->gl_config.multisamplebuffers; + } + if ( this->gl_config.multisamplesamples != 0 ) { + attributes[i++] = AGL_SAMPLES_ARB; + attributes[i++] = this->gl_config.multisamplesamples; + } +#endif + if ( this->gl_config.accelerated > 0 ) { + attributes[i++] = AGL_ACCELERATED; + attributes[i++] = AGL_NO_RECOVERY; + } + + attributes[i++] = AGL_ALL_RENDERERS; + attributes[i] = AGL_NONE; + + format = aglChoosePixelFormat(NULL, 0, attributes); + if ( format == NULL ) { + SDL_SetError("Couldn't match OpenGL desired format"); + return(-1); + } + + glContext = aglCreateContext(format, NULL); + if ( glContext == NULL ) { + SDL_SetError("Couldn't create OpenGL context"); + return(-1); + } + aglDestroyPixelFormat(format); + + #if TARGET_API_MAC_CARBON + noerr = aglSetDrawable(glContext, GetWindowPort(SDL_Window)); + #else + noerr = aglSetDrawable(glContext, (AGLDrawable)SDL_Window); + #endif + + if(!noerr) { + SDL_SetError("Unable to bind GL context to window"); + return(-1); + } + return(0); +#else + SDL_SetError("OpenGL support not configured"); + return(-1); +#endif +} + +void Mac_GL_Quit(_THIS) +{ +#if SDL_VIDEO_OPENGL + if ( glContext != NULL ) { + aglSetCurrentContext(NULL); + aglSetDrawable(glContext, NULL); + aglDestroyContext(glContext); + glContext = NULL; + } +#endif +} + +#if SDL_VIDEO_OPENGL + +/* Make the current context active */ +int Mac_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if( ! aglSetCurrentContext(glContext) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + return(retval); +} + +void Mac_GL_SwapBuffers(_THIS) +{ + aglSwapBuffers(glContext); +} + +int Mac_GL_LoadLibrary(_THIS, const char *location) +{ + if (location == NULL) +#if __MACH__ + location = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; +#else + location = "OpenGLLibrary"; +#endif + + this->hidden->libraryHandle = SDL_LoadObject(location); + + this->gl_config.driver_loaded = 1; + return (this->hidden->libraryHandle != NULL) ? 0 : -1; +} + +void Mac_GL_UnloadLibrary(_THIS) +{ + SDL_UnloadObject(this->hidden->libraryHandle); + + this->hidden->libraryHandle = NULL; + this->gl_config.driver_loaded = 0; +} + +void* Mac_GL_GetProcAddress(_THIS, const char *proc) +{ + return SDL_LoadFunction( this->hidden->libraryHandle, proc ); +} + +#endif /* SDL_VIDEO_OPENGL */ + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h new file mode 100644 index 0000000..42cd70f --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macgl_c.h @@ -0,0 +1,47 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* AGL implementation of SDL OpenGL support */ + +#include "SDL_config.h" + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#if __MACOSX__ +#include <AGL/agl.h> /* AGL.framework */ +#else +#include <agl.h> +#endif +#endif /* SDL_VIDEO_OPENGL */ + +/* OpenGL functions */ +extern int Mac_GL_Init(_THIS); +extern void Mac_GL_Quit(_THIS); +#if SDL_VIDEO_OPENGL +extern int Mac_GL_MakeCurrent(_THIS); +extern int Mac_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void Mac_GL_SwapBuffers(_THIS); +extern int Mac_GL_LoadLibrary(_THIS, const char *location); +extern void Mac_GL_UnloadLibrary(_THIS); +extern void* Mac_GL_GetProcAddress(_THIS, const char *proc); +#endif + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h b/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h new file mode 100644 index 0000000..dfed30d --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_mackeys.h @@ -0,0 +1,140 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +/* These are the Macintosh key scancode constants -- from Inside Macintosh */ + +#define MK_ESCAPE 0x35 +#define MK_F1 0x7A +#define MK_F2 0x78 +#define MK_F3 0x63 +#define MK_F4 0x76 +#define MK_F5 0x60 +#define MK_F6 0x61 +#define MK_F7 0x62 +#define MK_F8 0x64 +#define MK_F9 0x65 +#define MK_F10 0x6D +#define MK_F11 0x67 +#define MK_F12 0x6F +#define MK_PRINT 0x69 +#define MK_SCROLLOCK 0x6B +#define MK_PAUSE 0x71 +#define MK_POWER 0x7F +#define MK_BACKQUOTE 0x32 +#define MK_1 0x12 +#define MK_2 0x13 +#define MK_3 0x14 +#define MK_4 0x15 +#define MK_5 0x17 +#define MK_6 0x16 +#define MK_7 0x1A +#define MK_8 0x1C +#define MK_9 0x19 +#define MK_0 0x1D +#define MK_MINUS 0x1B +#define MK_EQUALS 0x18 +#define MK_BACKSPACE 0x33 +#define MK_INSERT 0x72 +#define MK_HOME 0x73 +#define MK_PAGEUP 0x74 +#define MK_NUMLOCK 0x47 +#define MK_KP_EQUALS 0x51 +#define MK_KP_DIVIDE 0x4B +#define MK_KP_MULTIPLY 0x43 +#define MK_TAB 0x30 +#define MK_q 0x0C +#define MK_w 0x0D +#define MK_e 0x0E +#define MK_r 0x0F +#define MK_t 0x11 +#define MK_y 0x10 +#define MK_u 0x20 +#define MK_i 0x22 +#define MK_o 0x1F +#define MK_p 0x23 +#define MK_LEFTBRACKET 0x21 +#define MK_RIGHTBRACKET 0x1E +#define MK_BACKSLASH 0x2A +#define MK_DELETE 0x75 +#define MK_END 0x77 +#define MK_PAGEDOWN 0x79 +#define MK_KP7 0x59 +#define MK_KP8 0x5B +#define MK_KP9 0x5C +#define MK_KP_MINUS 0x4E +#define MK_CAPSLOCK 0x39 +#define MK_a 0x00 +#define MK_s 0x01 +#define MK_d 0x02 +#define MK_f 0x03 +#define MK_g 0x05 +#define MK_h 0x04 +#define MK_j 0x26 +#define MK_k 0x28 +#define MK_l 0x25 +#define MK_SEMICOLON 0x29 +#define MK_QUOTE 0x27 +#define MK_RETURN 0x24 +#define MK_KP4 0x56 +#define MK_KP5 0x57 +#define MK_KP6 0x58 +#define MK_KP_PLUS 0x45 +#define MK_LSHIFT 0x38 +#define MK_z 0x06 +#define MK_x 0x07 +#define MK_c 0x08 +#define MK_v 0x09 +#define MK_b 0x0B +#define MK_n 0x2D +#define MK_m 0x2E +#define MK_COMMA 0x2B +#define MK_PERIOD 0x2F +#define MK_SLASH 0x2C +#if 0 /* These are the same as the left versions - use left by default */ +#define MK_RSHIFT 0x38 +#endif +#define MK_UP 0x7E +#define MK_KP1 0x53 +#define MK_KP2 0x54 +#define MK_KP3 0x55 +#define MK_KP_ENTER 0x4C +#define MK_LCTRL 0x3B +#define MK_LALT 0x3A +#define MK_LMETA 0x37 +#define MK_SPACE 0x31 +#if 0 /* These are the same as the left versions - use left by default */ +#define MK_RMETA 0x37 +#define MK_RALT 0x3A +#define MK_RCTRL 0x3B +#endif +#define MK_LEFT 0x7B +#define MK_DOWN 0x7D +#define MK_RIGHT 0x7C +#define MK_KP0 0x52 +#define MK_KP_PERIOD 0x41 + +/* Wierd, these keys are on my iBook under Mac OS X */ +#define MK_IBOOK_ENTER 0x34 +#define MK_IBOOK_LEFT 0x3B +#define MK_IBOOK_RIGHT 0x3C +#define MK_IBOOK_DOWN 0x3D +#define MK_IBOOK_UP 0x3E diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c b/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c new file mode 100644 index 0000000..f19ad1b --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macmouse.c @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Quickdraw.h> +#endif + +/* Routines that are not supported by the Carbon API... */ +#if !TARGET_API_MAC_CARBON +#include <CursorDevices.h> +#endif + +#include "SDL_mouse.h" +#include "SDL_macmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + Cursor curs; +}; + + +void Mac_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor); +} + +WMcursor *Mac_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + int row, bytes; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cursor, 0, sizeof(*cursor)); + + if (w > 16) + w = 16; + + if (h > 16) + h = 16; + + bytes = (w+7)/8; + + for ( row=0; row<h; ++row ) { + SDL_memcpy(&cursor->curs.data[row], data, bytes); + data += bytes; + } + for ( row=0; row<h; ++row ) { + SDL_memcpy(&cursor->curs.mask[row], mask, bytes); + mask += bytes; + } + cursor->curs.hotSpot.h = hot_x; + cursor->curs.hotSpot.v = hot_y; + + /* That was easy. :) */ + return(cursor); +} + +int Mac_cursor_showing = 1; + +int Mac_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if ( cursor == NULL ) { + if ( Mac_cursor_showing ) { + HideCursor(); + Mac_cursor_showing = 0; + } + } else { + SetCursor(&cursor->curs); + if ( ! Mac_cursor_showing ) { + ShowCursor(); + Mac_cursor_showing = 1; + } + } + return(1); +} + +void Mac_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ +#if !TARGET_API_MAC_CARBON + CursorDevice *cursordevice; + + cursordevice = nil; + CursorDeviceNextDevice(&cursordevice); + if ( cursordevice != nil ) { + WindowPtr saveport; + Point where; + + GetPort(&saveport); + SetPort(SDL_Window); + where.h = x; + where.v = y; + LocalToGlobal(&where); + SetPort(saveport); + CursorDeviceMoveTo(cursordevice, where.h, where.v); + } +#endif /* !TARGET_API_MAC_CARBON */ +} + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h new file mode 100644 index 0000000..18fb438 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macmouse_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions to be exported */ +extern void Mac_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *Mac_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int Mac_ShowWMCursor(_THIS, WMcursor *cursor); +extern void Mac_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + +/* Data to be exported */ +extern int Mac_cursor_showing; diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macwm.c b/3rdparty/SDL/src/video/maccommon/SDL_macwm.c new file mode 100644 index 0000000..6f485a3 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macwm.c @@ -0,0 +1,442 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#else +#include <Windows.h> +#include <Strings.h> +#endif + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +#include <Devices.h> +#include <Files.h> +#include <MacTypes.h> +#include <QDOffscreen.h> +#include <Quickdraw.h> +#include <Video.h> +#endif + +#include "SDL_stdinc.h" +#include "SDL_macwm_c.h" + +void Mac_SetCaption(_THIS, const char *title, const char *icon) +{ + /* Don't convert C to P string in place, because it may be read-only */ + Str255 ptitle; /* MJS */ + ptitle[0] = strlen (title); + SDL_memcpy(ptitle+1, title, ptitle[0]); /* MJS */ + if (SDL_Window) + SetWTitle(SDL_Window, ptitle); /* MJS */ +} + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +/* + * ADC Gamma Ramp support... + * + * Mac Gamma Ramp code was originally from sample code provided by + * Apple Developer Connection, and not written specifically for SDL: + * "Contains: Functions to enable Mac OS device gamma adjustments using 3 channel 256 element 8 bit gamma ramps + * Written by: Geoff Stahl (ggs) + * Copyright: Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved + * Disclaimer: You may incorporate this sample code into your applications without + * restriction, though the sample code has been provided "AS IS" and the + * responsibility for its operation is 100% yours. However, what you are + * not permitted to do is to redistribute the source as "DSC Sample Code" + * after having made changes. If you're going to re-distribute the source, + * we require that you make it clear in the source that the code was + * descended from Apple Sample Code, but that you've made changes." + * (The sample code has been integrated into this file, and thus is modified from the original Apple sources.) + */ + +typedef struct recDeviceGamma /* storage for device handle and gamma table */ +{ + GDHandle hGD; /* handle to device */ + GammaTblPtr pDeviceGamma; /* pointer to device gamma table */ +} recDeviceGamma; +typedef recDeviceGamma * precDeviceGamma; + +typedef struct recSystemGamma /* storage for system devices and gamma tables */ +{ + short numDevices; /* number of devices */ + precDeviceGamma * devGamma; /* array of pointers to device gamma records */ +} recSystemGamma; +typedef recSystemGamma * precSystemGamma; + +static Ptr CopyGammaTable (GammaTblPtr pTableGammaIn) +{ + GammaTblPtr pTableGammaOut = NULL; + short tableSize, dataWidth; + + if (pTableGammaIn) /* if there is a table to copy */ + { + dataWidth = (pTableGammaIn->gDataWidth + 7) / 8; /* number of bytes per entry */ + tableSize = sizeof (GammaTbl) + pTableGammaIn->gFormulaSize + + (pTableGammaIn->gChanCnt * pTableGammaIn->gDataCnt * dataWidth); + pTableGammaOut = (GammaTblPtr) NewPtr (tableSize); /* allocate new table */ + if (pTableGammaOut) + BlockMove( (Ptr)pTableGammaIn, (Ptr)pTableGammaOut, tableSize); /* move everything */ + } + return (Ptr)pTableGammaOut; /* return whatever we allocated, could be NULL */ +} + +static OSErr GetGammaTable (GDHandle hGD, GammaTblPtr * ppTableGammaOut) +{ + VDGammaRecord DeviceGammaRec; + CntrlParam cParam; + OSErr err; + + cParam.ioCompletion = NULL; /* set up control params */ + cParam.ioNamePtr = NULL; + cParam.ioVRefNum = 0; + cParam.ioCRefNum = (**hGD).gdRefNum; + cParam.csCode = cscGetGamma; /* Get Gamma commnd to device */ + *(Ptr *)cParam.csParam = (Ptr) &DeviceGammaRec; /* record for gamma */ + + err = PBStatusSync( (ParmBlkPtr)&cParam ); /* get gamma */ + + *ppTableGammaOut = (GammaTblPtr)(DeviceGammaRec.csGTable); /* pull table out of record */ + + return err; +} + +static Ptr GetDeviceGamma (GDHandle hGD) +{ + GammaTblPtr pTableGammaDevice = NULL; + GammaTblPtr pTableGammaReturn = NULL; + OSErr err; + + err = GetGammaTable (hGD, &pTableGammaDevice); /* get a pointer to the devices table */ + if ((noErr == err) && pTableGammaDevice) /* if succesful */ + pTableGammaReturn = (GammaTblPtr) CopyGammaTable (pTableGammaDevice); /* copy to global */ + + return (Ptr) pTableGammaReturn; +} + +static void DisposeGammaTable (Ptr pGamma) +{ + if (pGamma) + DisposePtr((Ptr) pGamma); /* get rid of it */ +} + +static void DisposeSystemGammas (Ptr* ppSystemGammas) +{ + precSystemGamma pSysGammaIn; + if (ppSystemGammas) + { + pSysGammaIn = (precSystemGamma) *ppSystemGammas; + if (pSysGammaIn) + { + short i; + for (i = 0; i < pSysGammaIn->numDevices; i++) /* for all devices */ + if (pSysGammaIn->devGamma [i]) /* if pointer is valid */ + { + DisposeGammaTable ((Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); /* dump gamma table */ + DisposePtr ((Ptr) pSysGammaIn->devGamma [i]); /* dump device info */ + } + DisposePtr ((Ptr) pSysGammaIn->devGamma); /* dump device pointer array */ + DisposePtr ((Ptr) pSysGammaIn); /* dump system structure */ + *ppSystemGammas = NULL; + } + } +} + +static Boolean GetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp) +{ + GammaTblPtr pTableGammaTemp = NULL; + long indexChan, indexEntry; + OSErr err; + + if (pRamp) /* ensure pRamp is allocated */ + { + err = GetGammaTable (hGD, &pTableGammaTemp); /* get a pointer to the current gamma */ + if ((noErr == err) && pTableGammaTemp) /* if successful */ + { + /* fill ramp */ + unsigned char * pEntry = (unsigned char *) &pTableGammaTemp->gFormulaData + pTableGammaTemp->gFormulaSize; /* base of table */ + short bytesPerEntry = (pTableGammaTemp->gDataWidth + 7) / 8; /* size, in bytes, of the device table entries */ + short shiftRightValue = pTableGammaTemp->gDataWidth - 8; /* number of right shifts device -> ramp */ + short channels = pTableGammaTemp->gChanCnt; + short entries = pTableGammaTemp->gDataCnt; + if (3 == channels) /* RGB format */ + { /* note, this will create runs of entries if dest. is bigger (not linear interpolate) */ + for (indexChan = 0; indexChan < channels; indexChan++) + for (indexEntry = 0; indexEntry < 256; indexEntry++) + *((unsigned char *) pRamp + (indexChan * 256) + indexEntry) = + *(pEntry + indexChan * entries * bytesPerEntry + indexEntry * entries * bytesPerEntry / 256) >> shiftRightValue; + } + else /* single channel format */ + { + for (indexChan = 0; indexChan < 768; indexChan += 256) /* repeat for all 3 channels (step by ramp size) */ + for (indexEntry = 0; indexEntry < 256; indexEntry++) /* for all entries set vramp value */ + *((unsigned char *) pRamp + indexChan + indexEntry) = + *(pEntry + indexEntry * entries * bytesPerEntry / 256) >> shiftRightValue; + } + return true; + } + } + return false; +} + +static Ptr GetSystemGammas (void) +{ + precSystemGamma pSysGammaOut; /* return pointer to system device gamma info */ + short devCount = 0; /* number of devices attached */ + Boolean fail = false; + GDHandle hGDevice; + + pSysGammaOut = (precSystemGamma) NewPtr (sizeof (recSystemGamma)); /* allocate for structure */ + + hGDevice = GetDeviceList (); /* top of device list */ + do /* iterate */ + { + devCount++; /* count devices */ + hGDevice = GetNextDevice (hGDevice); /* next device */ + } while (hGDevice); + + pSysGammaOut->devGamma = (precDeviceGamma *) NewPtr (sizeof (precDeviceGamma) * devCount); /* allocate for array of pointers to device records */ + if (pSysGammaOut) + { + pSysGammaOut->numDevices = devCount; /* stuff count */ + + devCount = 0; /* reset iteration */ + hGDevice = GetDeviceList (); + do + { + pSysGammaOut->devGamma [devCount] = (precDeviceGamma) NewPtr (sizeof (recDeviceGamma)); /* new device record */ + if (pSysGammaOut->devGamma [devCount]) /* if we actually allocated memory */ + { + pSysGammaOut->devGamma [devCount]->hGD = hGDevice; /* stuff handle */ + pSysGammaOut->devGamma [devCount]->pDeviceGamma = (GammaTblPtr)GetDeviceGamma (hGDevice); /* copy gamma table */ + } + else /* otherwise dump record on exit */ + fail = true; + devCount++; /* next device */ + hGDevice = GetNextDevice (hGDevice); + } while (hGDevice); + } + if (!fail) /* if we did not fail */ + return (Ptr) pSysGammaOut; /* return pointer to structure */ + else + { + DisposeSystemGammas ((Ptr *) &pSysGammaOut); /* otherwise dump the current structures (dispose does error checking) */ + return NULL; /* could not complete */ + } +} + +static void RestoreDeviceGamma (GDHandle hGD, Ptr pGammaTable) +{ + VDSetEntryRecord setEntriesRec; + VDGammaRecord gameRecRestore; + CTabHandle hCTabDeviceColors; + Ptr csPtr; + OSErr err = noErr; + + if (pGammaTable) /* if we have a table to restore */ + { + gameRecRestore.csGTable = pGammaTable; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma */ + + if ((noErr == err) && (8 == (**(**hGD).gdPMap).pixelSize)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + } +} + +static void RestoreSystemGammas (Ptr pSystemGammas) +{ + short i; + precSystemGamma pSysGammaIn = (precSystemGamma) pSystemGammas; + if (pSysGammaIn) + for (i = 0; i < pSysGammaIn->numDevices; i++) /* for all devices */ + RestoreDeviceGamma (pSysGammaIn->devGamma [i]->hGD, (Ptr) pSysGammaIn->devGamma [i]->pDeviceGamma); /* restore gamma */ +} + +static Ptr CreateEmptyGammaTable (short channels, short entries, short bits) +{ + GammaTblPtr pTableGammaOut = NULL; + short tableSize, dataWidth; + + dataWidth = (bits + 7) / 8; /* number of bytes per entry */ + tableSize = sizeof (GammaTbl) + (channels * entries * dataWidth); + pTableGammaOut = (GammaTblPtr) NewPtrClear (tableSize); /* allocate new tabel */ + + if (pTableGammaOut) /* if we successfully allocated */ + { + pTableGammaOut->gVersion = 0; /* set parameters based on input */ + pTableGammaOut->gType = 0; + pTableGammaOut->gFormulaSize = 0; + pTableGammaOut->gChanCnt = channels; + pTableGammaOut->gDataCnt = entries; + pTableGammaOut->gDataWidth = bits; + } + return (Ptr)pTableGammaOut; /* return whatever we allocated */ +} + +static Boolean SetDeviceGammaRampGD (GDHandle hGD, Ptr pRamp) +{ + VDSetEntryRecord setEntriesRec; + VDGammaRecord gameRecRestore; + GammaTblPtr pTableGammaNew; + GammaTblPtr pTableGammaCurrent = NULL; + CTabHandle hCTabDeviceColors; + Ptr csPtr; + OSErr err; + short dataBits, entries, channels = 3; /* force three channels in the gamma table */ + + if (pRamp) /* ensure pRamp is allocated */ + { + err= GetGammaTable (hGD, &pTableGammaCurrent); /* get pointer to current table */ + if ((noErr == err) && pTableGammaCurrent) + { + dataBits = pTableGammaCurrent->gDataWidth; /* table must have same data width */ + entries = pTableGammaCurrent->gDataCnt; /* table must be same size */ + pTableGammaNew = (GammaTblPtr) CreateEmptyGammaTable (channels, entries, dataBits); /* our new table */ + if (pTableGammaNew) /* if successful fill table */ + { + unsigned char * pGammaBase = (unsigned char *) &pTableGammaNew->gFormulaData + pTableGammaNew->gFormulaSize; /* base of table */ + if ((256 == entries) && (8 == dataBits)) /* simple case: direct mapping */ + BlockMove ((Ptr)pRamp, (Ptr)pGammaBase, channels * entries); /* move everything */ + else /* tough case handle entry, channel and data size disparities */ + { + short indexChan, indexEntry; + short bytesPerEntry = (dataBits + 7) / 8; /* size, in bytes, of the device table entries */ + short shiftRightValue = 8 - dataBits; /* number of right shifts ramp -> device */ + shiftRightValue += ((bytesPerEntry - 1) * 8); /* multibyte entries and the need to map a byte at a time most sig. to least sig. */ + for (indexChan = 0; indexChan < channels; indexChan++) /* for all the channels */ + for (indexEntry = 0; indexEntry < entries; indexEntry++) /* for all the entries */ + { + short currentShift = shiftRightValue; /* reset current bit shift */ + long temp = *((unsigned char *)pRamp + (indexChan << 8) + (indexEntry << 8) / entries); /* get data from ramp */ + short indexByte; + for (indexByte = 0; indexByte < bytesPerEntry; indexByte++) /* for all bytes */ + { + if (currentShift < 0) /* shift data correctly for current byte */ + *(pGammaBase++) = temp << -currentShift; + else + *(pGammaBase++) = temp >> currentShift; + currentShift -= 8; /* increment shift to align to next less sig. byte */ + } + } + } + + /* set gamma */ + gameRecRestore.csGTable = (Ptr) pTableGammaNew; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma (note, display drivers may delay returning from this until VBL) */ + + if ((8 == (**(**hGD).gdPMap).pixelSize) && (noErr == err)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + DisposeGammaTable ((Ptr) pTableGammaNew); /* dump table */ + if (noErr == err) + return true; + } + } + } + else /* set NULL gamma -> results in linear map */ + { + gameRecRestore.csGTable = (Ptr) NULL; /* setup restore record */ + csPtr = (Ptr) &gameRecRestore; + err = Control((**hGD).gdRefNum, cscSetGamma, (Ptr) &csPtr); /* restore gamma */ + + if ((8 == (**(**hGD).gdPMap).pixelSize) && (noErr == err)) /* if successful and on an 8 bit device */ + { + hCTabDeviceColors = (**(**hGD).gdPMap).pmTable; /* do SetEntries to force CLUT update */ + setEntriesRec.csTable = (ColorSpec *) &(**hCTabDeviceColors).ctTable; + setEntriesRec.csStart = 0; + setEntriesRec.csCount = (**hCTabDeviceColors).ctSize; + csPtr = (Ptr) &setEntriesRec; + err = Control((**hGD).gdRefNum, cscSetEntries, (Ptr) &csPtr); /* SetEntries in CLUT */ + } + if (noErr == err) + return true; + } + return false; /* memory allocation or device control failed if we get here */ +} + +/* end of ADC Gamma Ramp support code... */ + +static Ptr systemGammaPtr; + +void Mac_QuitGamma(_THIS) +{ + if (systemGammaPtr) + { + RestoreSystemGammas(systemGammaPtr); + DisposeSystemGammas(&systemGammaPtr); + } +} + +static unsigned char shiftedRamp[3 * 256]; + +int Mac_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i; + if (!systemGammaPtr) + systemGammaPtr = GetSystemGammas(); + for (i = 0; i < 3 * 256; i++) + { + shiftedRamp[i] = ramp[i] >> 8; + } + + if (SetDeviceGammaRampGD(GetMainDevice(), (Ptr) shiftedRamp)) + return 0; + else + return -1; +} + +int Mac_GetGammaRamp(_THIS, Uint16 *ramp) +{ + if (GetDeviceGammaRampGD(GetMainDevice(), (Ptr) shiftedRamp)) + { + int i; + for (i = 0; i < 3 * 256; i++) + { + ramp[i] = shiftedRamp[i] << 8; + } + return 0; + } + else + return -1; +} + +#endif /* SDL_MACCLASSIC_GAMMA_SUPPORT */ + + diff --git a/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h b/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h new file mode 100644 index 0000000..a0554d1 --- /dev/null +++ b/3rdparty/SDL/src/video/maccommon/SDL_macwm_c.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../macrom/SDL_romvideo.h" + +/* Functions to be exported */ +extern void Mac_SetCaption(_THIS, const char *title, const char *icon); + +/* + * There's no Carbonized gamma support in Mac OS X, since PBStatusSync() and + * Control() aren't supported in OS X's Carbonlib. Use the Quartz driver + * instead. + */ +#define SDL_MACCLASSIC_GAMMA_SUPPORT ((defined(__APPLE__) && defined(__MACH__)) == 0) + +#if SDL_MACCLASSIC_GAMMA_SUPPORT +extern void Mac_QuitGamma(_THIS); +extern int Mac_SetGammaRamp(_THIS, Uint16 *ramp); +extern int Mac_GetGammaRamp(_THIS, Uint16 *ramp); +#endif + diff --git a/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c new file mode 100644 index 0000000..aa31127 --- /dev/null +++ b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.c @@ -0,0 +1,1422 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Written by Darrell Walisser <dwaliss1@purdue.edu> + + Implementation notes ---------------------------------------------------------------------- + + A bit on GWorlds in VRAM from technote 1182: + + There are two important things to note about GWorld's allocated in + VRAM. First, the base address retrieved through GetPixBaseAddr or + read directly from the PixMap structure can become invalid anytime + memory is allocated in VRAM. This can occur either by explicit + allocations, such as calls to NewGWorld, or by implicit ones, such as + those associated with the internal texture allocation of OpenGL. The + stored pixel images themselves will still be valid but may have been + moved in VRAM, thus rendering any stored base addresses invalid. + You should never store an image's base address for longer than is + necessary and especially never across calls to NewGWorld or + texture-creation routines. + + Secondly, an offscreen pixel image allocated in VRAM can be + purged at system task time by the display driver. This means any + time your application yields time such by calling WaitNextEvent or + SystemTask you can lose your VRAM GWorld contents. While this + happens infrequently, usually associated with display resolution or + pixel depth changes you must code for this eventuality. This purge + can occur whether or not the GWorld is locked or not. A return value + of false from LockPixels, a NULL return value from GetPixBaseAddr + or NULL in the baseAddr field of the PixMap mean that the pixel + image has been purged. To reallocate it you can either call + UpdateGWorld or Dispose your current GWorld through + DisposeGWorld and reallocate it via NewGWorld. Either way you must + then rebuild the pixel image. + +------------------------------------------------------------------------------------ + + Currently, I don't account for (1). In my testing, NewGWorld never invalidated + other existing GWorlds in VRAM. However, I do have protection for (2). + Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no + context switches (the app hogs the CPU). Eventually a book-keeping system should + be coded to take care of (1) and (2). + +------------------------------------------------------------------------------------ + + System requirements (* denotes optional): + + 1. DrawSprocket 1.7.3 + 2. *MacOS 9 or later (but *not* Mac OS X) for hardware accelerated blit / fill + 3. *May also require certain graphics hardware for (2). I trust that all Apple OEM + hardware will work. Third party accelerators may work if they have QuickDraw + acceleration in the drivers and the drivers have been updated for OS 9. The current + Voodoo 3 drivers (1.0b12) do not work. + + Coding suggestions: + + 1. Use SDL_UpdateRects ! + + If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer + in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces + for best performance on these cards, since the overhead is nearly zero for VRAM back buffer. + + 2. Load most-resident surfaces first. + + If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one. + Therefore, you should load the surfaces you plan to use the most frequently first. + Sooner or later, I will code LRU replacement to help this. + + TODO: + Some kind of posterized mode for resolutions < 640x480. + Window support / fullscreen toggle. + Figure out how much VRAM is available. Put in video->info->video_mem. + Track VRAM usage. + + BUGS: + I can't create a hardware surface the same size as the screen?! How to fix? + + + + COMPILE OPTIONS: + + DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters + HW color-key blitting gives substantial improvements, + but hw alpha is neck-and-neck with SDL's soft bitter. + + DSP_NO_SYNC_VBL - Define for HWA double-buffered surfaces: don't sync + pseudo-flip to monitor redraw. + + DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer + swap may result in reduced performance, but can eliminate some + tearing artifacts. + CHANGELOG: + 09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts + list first. Compared various methods with ROM methods and fixed rez switch + crashing bug in GL Tron. (Woohoo!) +*/ + +#define DSP_TRY_CC_AND_AA + +/* #define DSP_NO_SYNC_VBL */ + +#define DSP_NO_SYNC_OPENGL + + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#include <DrawSprocket/DrawSprocket.h> +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +#include <DrawSprocket.h> +#else +#include <LowMem.h> +#include <Gestalt.h> +#include <Devices.h> +#include <DiskInit.h> +#include <QDOffscreen.h> +#include <DrawSprocket.h> +#endif + +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_blit.h" +#include "../SDL_pixels_c.h" +#include "SDL_dspvideo.h" +#include "../maccommon/SDL_macgl_c.h" +#include "../maccommon/SDL_macwm_c.h" +#include "../maccommon/SDL_macmouse_c.h" +#include "../maccommon/SDL_macevents_c.h" + +/* Initialization/Query functions */ +static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DSp_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DSp_CreatePalette(_THIS); +static int DSp_DestroyPalette(_THIS); +static void DSp_VideoQuit(_THIS); + +static int DSp_GetMainDevice (_THIS, GDHandle *device); +static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat); +static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects); + +/* Hardware surface functions */ +static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha); +static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height); +static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DSp_LockHWSurface(_THIS, SDL_Surface *surface); +static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface); +static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface); +static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest); +static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect); +static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color); + +#if SDL_VIDEO_OPENGL + static void DSp_GL_SwapBuffers (_THIS); +#endif + +#if ! TARGET_API_MAC_CARBON + + #define GetPortPixRowBytes(x) ( (*(x->portPixMap))->rowBytes ) + #define GetGDevPixMap(x) ((**(x)).gdPMap) + #define GetPortPixMap(x) ((*(x)).portPixMap) + + #define GetPixDepth(y) ((**(y)).pixelSize) + //#define GetPixRowBytes(y) ((**(y)).rowBytes) + //#define GetPixBaseAddr(y) ((**(y)).baseAddr) + #define GetPixCTab(y) ((**(y)).pmTable) + #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits)) + +#else + #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) ) + #define GetGDevPixMap(x) ((**(x)).gdPMap) + +#endif + +typedef struct private_hwdata { + + GWorldPtr offscreen; // offscreen gworld in VRAM or AGP + + #ifdef DSP_TRY_CC_AND_AA + GWorldPtr mask; // transparent mask + RGBColor alpha; // alpha color + RGBColor trans; // transparent color + #endif + +} private_hwdata; + +typedef private_hwdata private_swdata ; /* have same fields */ + +/* Macintosh toolbox driver bootstrap functions */ + +static int DSp_Available(void) +{ + /* Check for DrawSprocket */ +#if ! TARGET_API_MAC_OSX + /* This check is only meaningful if you weak-link DrawSprocketLib */ + return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress); +#else + return 1; // DrawSprocket.framework doesn't have it all, but it's there +#endif +} + +static void DSp_DeleteDevice(SDL_VideoDevice *device) +{ + /* -dw- taking no chances with null pointers */ + if (device) { + + if (device->hidden) { + + if (device->hidden->dspinfo) + SDL_free(device->hidden->dspinfo); + + SDL_free(device->hidden); + } + SDL_free(device); + } +} + +static SDL_VideoDevice *DSp_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, sizeof (*device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if (device->hidden) + SDL_memset(device->hidden, 0, sizeof ( *(device->hidden) ) ); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + + if ( device ) { + + if (device->hidden) + SDL_free(device->hidden); + + SDL_free(device); + } + + return(NULL); + } + + /* Allocate DrawSprocket information */ + device->hidden->dspinfo = (struct DSpInfo *)SDL_malloc( + (sizeof *device->hidden->dspinfo)); + if ( device->hidden->dspinfo == NULL ) { + SDL_OutOfMemory(); + SDL_free(device->hidden); + SDL_free(device); + return(0); + } + SDL_memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo)); + + /* Set the function pointers */ + device->VideoInit = DSp_VideoInit; + device->ListModes = DSp_ListModes; + device->SetVideoMode = DSp_SetVideoMode; + device->SetColors = DSp_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DSp_VideoQuit; + device->AllocHWSurface = DSp_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DSp_LockHWSurface; + device->UnlockHWSurface = DSp_UnlockHWSurface; + device->FlipHWSurface = DSp_FlipHWSurface; + device->FreeHWSurface = DSp_FreeHWSurface; +#if SDL_MACCLASSIC_GAMMA_SUPPORT + device->SetGammaRamp = Mac_SetGammaRamp; + device->GetGammaRamp = Mac_GetGammaRamp; +#endif +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = Mac_GL_MakeCurrent; + device->GL_SwapBuffers = DSp_GL_SwapBuffers; + device->GL_LoadLibrary = Mac_GL_LoadLibrary; + device->GL_GetProcAddress = Mac_GL_GetProcAddress; +#endif + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = Mac_FreeWMCursor; + device->CreateWMCursor = Mac_CreateWMCursor; + device->ShowWMCursor = Mac_ShowWMCursor; + device->WarpWMCursor = Mac_WarpWMCursor; + device->InitOSKeymap = Mac_InitOSKeymap; + device->PumpEvents = Mac_PumpEvents; + + device->GrabInput = NULL; + device->CheckMouseMode = NULL; + + device->free = DSp_DeleteDevice; + + return device; +} + +VideoBootStrap DSp_bootstrap = { + "DSp", "MacOS DrawSprocket", + DSp_Available, DSp_CreateDevice +}; + +/* Use DSp/Display Manager to build mode list for given screen */ +static SDL_Rect** DSp_BuildModeList (const GDHandle gDevice, int *displayWidth, int *displayHeight) +{ + DSpContextAttributes attributes; + DSpContextReference context; + DisplayIDType displayID; + SDL_Rect temp_list [16]; + SDL_Rect **mode_list; + int width, height, i, j; + + #if TARGET_API_MAC_OSX + + displayID = 0; + + #else + /* Ask Display Manager for integer id of screen device */ + if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) { + return NULL; + } + #endif + /* Get the first possible DSp context on this device */ + if ( DSpGetFirstContext (displayID, &context) != noErr ) { + return NULL; + } + + if ( DSpContext_GetAttributes (context, &attributes) != noErr ) + return NULL; + + *displayWidth = attributes.displayWidth; + *displayHeight = attributes.displayHeight; + + for ( i = 0; i < SDL_arraysize(temp_list); i++ ) { + width = attributes.displayWidth; + height = attributes.displayHeight; + + temp_list [i].x = 0 | attributes.displayBestDepth; + temp_list [i].y = 0; + temp_list [i].w = width; + temp_list [i].h = height; + + /* DSp will report many different contexts with the same width and height. */ + /* They will differ in bit depth and refresh rate. */ + /* We will ignore them until we reach one with a different width/height */ + /* When there are no more contexts to look at, we will quit building the list*/ + while ( width == attributes.displayWidth && height == attributes.displayHeight ) { + + OSStatus err = DSpGetNextContext (context, &context); + if (err != noErr) + if (err == kDSpContextNotFoundErr) + goto done; + else + return NULL; + + if ( DSpContext_GetAttributes (context, &attributes) != noErr ) + return NULL; + + temp_list [i].x |= attributes.displayBestDepth; + } + } +done: + i++; /* i was not incremented before kicking out of the loop */ + + mode_list = (SDL_Rect**) SDL_malloc (sizeof (SDL_Rect*) * (i+1)); + if (mode_list) { + + /* -dw- new stuff: build in reverse order so largest sizes list first */ + for (j = i-1; j >= 0; j--) { + mode_list [j] = (SDL_Rect*) SDL_malloc (sizeof (SDL_Rect)); + if (mode_list [j]) + SDL_memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect)); + else { + SDL_OutOfMemory (); + return NULL; + } + } + mode_list [i] = NULL; /* append null to the end */ + } + else { + SDL_OutOfMemory (); + return NULL; + } + + return mode_list; +} + +static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat) +{ + /* + VRAM GWorlds are only available on OS 9 or later. + Even with OS 9, some display drivers won't support it, + so we create a test GWorld and check for errors. + */ + + long versionSystem; + + dsp_vram_available = SDL_FALSE; + dsp_agp_available = SDL_FALSE; + + Gestalt ('sysv', &versionSystem); + if (0x00000860 < (versionSystem & 0x0000FFFF)) { + + GWorldPtr offscreen; + OSStatus err; + Rect bounds; + + SetRect (&bounds, 0, 0, 320, 240); + +#if useDistantHdwrMem && useLocalHdwrMem + err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice); + if (err == noErr) { + dsp_vram_available = SDL_TRUE; + DisposeGWorld (offscreen); + } + + err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice); + if (err == noErr) { + DisposeGWorld (offscreen); + dsp_agp_available = SDL_TRUE; + } +#endif + } +} + +static int DSp_GetMainDevice (_THIS, GDHandle *device) +{ + +#if TARGET_API_MAC_OSX + /* DSpUserSelectContext not available on OS X */ + *device = GetMainDevice(); + return 0; +#else + + DSpContextAttributes attrib; + DSpContextReference context; + DisplayIDType display_id; + GDHandle main_device; + GDHandle device_list; + + device_list = GetDeviceList (); + main_device = GetMainDevice (); + + /* Quick check to avoid slower method when only one display exists */ + if ( (**device_list).gdNextGD == NULL ) { + *device = main_device; + return 0; + } + + SDL_memset (&attrib, 0, sizeof (DSpContextAttributes)); + + /* These attributes are hopefully supported on all devices...*/ + attrib.displayWidth = 640; + attrib.displayHeight = 480; + attrib.displayBestDepth = 8; + attrib.backBufferBestDepth = 8; + attrib.displayDepthMask = kDSpDepthMask_All; + attrib.backBufferDepthMask = kDSpDepthMask_All; + attrib.colorNeeds = kDSpColorNeeds_Require; + attrib.pageCount = 1; + + if (noErr != DMGetDisplayIDByGDevice (main_device, &display_id, SDL_FALSE)) { + SDL_SetError ("Display Manager couldn't associate GDevice with a Display ID"); + return (-1); + } + + /* Put up dialog on main display to select which display to use */ + if (noErr != DSpUserSelectContext (&attrib, display_id, NULL, &context)) { + SDL_SetError ("DrawSprocket couldn't create a context"); + return (-1); + } + + if (noErr != DSpContext_GetDisplayID (context, &display_id)) { + SDL_SetError ("DrawSprocket couldn't get display ID"); + return (-1); + } + + if (noErr != DMGetGDeviceByDisplayID (display_id, &main_device, SDL_FALSE)) { + SDL_SetError ("Display Manager couldn't associate Display ID with GDevice"); + return (-1); + } + + *device = main_device; + return (0); +#endif +} + +static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + NumVersion dsp_version = { 0x01, 0x00, 0x00, 0x00 }; + +#if UNIVERSAL_INTERFACES_VERSION > 0x0320 + dsp_version = DSpGetVersion (); +#endif + + if ( (dsp_version.majorRev == 1 && dsp_version.minorAndBugRev < 0x73) || + (dsp_version.majorRev < 1) ) { + + /* StandardAlert (kAlertStopAlert, "\pError!", + "\pI need DrawSprocket 1.7.3 or later!\n" + "You can find a newer version at http://www.apple.com/swupdates.", + NULL, NULL); + */ + SDL_SetError ("DrawSprocket version is too old. Need 1.7.3 or later."); + return (-1); + } + + if ( DSpStartup () != noErr ) { + SDL_SetError ("DrawSprocket couldn't startup"); + return(-1); + } + + /* Start DSpintosh events */ + Mac_InitEvents(this); + + /* Get a handle to the main monitor, or choose one on multiple monitor setups */ + if ( DSp_GetMainDevice(this, &SDL_Display) < 0) + return (-1); + + /* Determine pixel format */ + vformat->BitsPerPixel = GetPixDepth ( (**SDL_Display).gdPMap ); + dsp_old_depth = vformat->BitsPerPixel; + + switch (vformat->BitsPerPixel) { + case 16: + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + break; + default: + break; + } + + if ( DSp_CreatePalette (this) < 0 ) { + SDL_SetError ("Could not create palette"); + return (-1); + } + + /* Get a list of available fullscreen modes */ + SDL_modelist = DSp_BuildModeList (SDL_Display, + &this->info.current_w, &this->info.current_h); + if (SDL_modelist == NULL) { + SDL_SetError ("DrawSprocket could not build a mode list"); + return (-1); + } + + /* Check for VRAM and AGP GWorlds for HW Blitting */ + DSp_IsHWAvailable (this, vformat); + + this->info.wm_available = 0; + + if (dsp_vram_available || dsp_agp_available) { + + this->info.hw_available = SDL_TRUE; + + this->CheckHWBlit = DSp_CheckHWBlit; + this->info.blit_hw = SDL_TRUE; + + this->FillHWRect = DSp_FillHWRect; + this->info.blit_fill = SDL_TRUE; + + #ifdef DSP_TRY_CC_AND_AA + this->SetHWColorKey = DSp_SetHWColorKey; + this->info.blit_hw_CC = SDL_TRUE; + + this->SetHWAlpha = DSp_SetHWAlpha; + this->info.blit_hw_A = SDL_TRUE; + #endif + + } + + return(0); +} + +static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + static SDL_Rect *dsp_modes[16]; + int i = 0, j = 0; + + if ( format->BitsPerPixel == 0 ) + return ( (SDL_Rect**) NULL ); + + while (SDL_modelist[i] != NULL) { + + if (SDL_modelist[i]->x & format->BitsPerPixel) { + dsp_modes[j] = SDL_modelist[i]; + j++; + } + i++; + } + + dsp_modes[j] = NULL; + + return dsp_modes; +} + +/* Various screen update functions available */ +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +#if ! TARGET_API_MAC_OSX + +static volatile unsigned int retrace_count = 0; /* -dw- need volatile because it updates asychronously */ + +Boolean DSp_VBLProc ( DSpContextReference context, void *ref_con ) +{ + retrace_count++; + + return 1; /* Darrell, is this right? */ +} + +static void DSp_SetHWError (OSStatus err, int is_agp) +{ + char message[1024]; + const char *fmt, *mem; + + if ( is_agp ) { + mem = "AGP Memory"; + } else { + mem = "VRAM"; + } + switch(err) { + case memFullErr: + fmt = "Hardware surface possible but not enough %s available"; + break; + case cDepthErr: + fmt = "Hardware surface possible but invalid color depth"; + break; + default: + fmt = "Hardware surface could not be allocated in %s - unknown error"; + break; + } + SDL_snprintf(message, SDL_arraysize(message), fmt, mem); + SDL_SetError(message); +} +#endif // TARGET_API_MAC_OSX + +/* put up a dialog to verify display change */ +static int DSp_ConfirmSwitch () { + + /* resource id's for dialog */ + const int rDialog = 1002; + const int bCancel = 1; + const int bOK = 2; + + DialogPtr dialog; + OSStatus err; + SInt32 response; + DialogItemIndex item = 0; + GrafPtr savePort; + + GetPort (&savePort); + + dialog = GetNewDialog (rDialog, NULL, (WindowPtr) -1); + if (dialog == NULL) + return (0); + +#if TARGET_API_MAC_CARBON + SetPort (GetDialogPort(dialog)); +#else + SetPort ((WindowPtr) dialog); +#endif + + SetDialogDefaultItem (dialog, bCancel); + SetDialogCancelItem (dialog, bCancel); + + SetEventMask (everyEvent); + FlushEvents (everyEvent, 0); + + /* On MacOS 8.5 or later, we can make the dialog go away after 15 seconds */ + /* This is good since it's possible user can't even see the dialog! */ + /* Requires linking to DialogsLib */ + err = Gestalt(gestaltSystemVersion,&response); + if (err == noErr && response >= 0x00000850) { + SetDialogTimeout(dialog, bCancel, 15); + } + + do { + + ModalDialog ( NULL, &item ); + + } while ( item != bCancel && item != bOK && err != noErr); + + + DisposeDialog (dialog); + SetPort (savePort); + + SetEventMask(everyEvent - autoKeyMask); + FlushEvents(everyEvent, 0); + + return (item - 1); +} + +static void DSp_UnsetVideoMode(_THIS, SDL_Surface *current) +{ + + + if ( current->flags & SDL_OPENGL ) { + Mac_GL_Quit (this); + } + + if (dsp_context != NULL) { + + GWorldPtr front; + DSpContext_GetFrontBuffer (dsp_context, &front); + + if (front != dsp_back_buffer) + DisposeGWorld (dsp_back_buffer); + + if (current->hwdata) + SDL_free(current->hwdata); + + DSpContext_SetState (dsp_context, kDSpContextState_Inactive ); + DSpContext_Release (dsp_context); + + dsp_context = NULL; + } + + if (SDL_Window != NULL) { + DisposeWindow (SDL_Window); + SDL_Window = NULL; + } + + current->pixels = NULL; + current->flags = 0; +} + +static SDL_Surface *DSp_SetVideoMode(_THIS, + SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + +#if !TARGET_API_MAC_OSX + DisplayIDType display_id; + Fixed freq; +#endif + DSpContextAttributes attrib; + OSStatus err; + UInt32 rmask = 0, gmask = 0, bmask = 0; + + int page_count; + int double_buf; + int hw_surface; + int use_dsp_back_buffer; + + DSp_UnsetVideoMode (this, current); + + if (bpp != dsp_old_depth) + DSp_DestroyPalette (this); + + double_buf = (flags & SDL_DOUBLEBUF) != 0; + hw_surface = (flags & SDL_HWSURFACE) != 0; + use_dsp_back_buffer = !dsp_vram_available || !hw_surface ; + + current->flags |= SDL_FULLSCREEN; + +rebuild: + + if ( double_buf && use_dsp_back_buffer ) { + page_count = 2; + } else { + page_count = 1; + } + + SDL_memset (&attrib, 0, sizeof (DSpContextAttributes)); + attrib.displayWidth = width; + attrib.displayHeight = height; + attrib.displayBestDepth = bpp; + attrib.backBufferBestDepth = bpp; + attrib.displayDepthMask = kDSpDepthMask_All; + attrib.backBufferDepthMask = kDSpDepthMask_All; + attrib.colorNeeds = kDSpColorNeeds_Require; + attrib.colorTable = 0; + attrib.pageCount = page_count; + #if TARGET_API_MAC_OSX || UNIVERSAL_INTERFACES_VERSION == 0x0320 + + if ( DSpFindBestContext (&attrib, &dsp_context) != noErr ) { + SDL_SetError ("DrawSprocket couldn't find a context"); + return NULL; + } + + #else + if ( noErr != DMGetDisplayIDByGDevice (SDL_Display, &display_id, SDL_FALSE) ) { + SDL_SetError ("Display Manager couldn't associate GDevice with display_id"); + return NULL; + } + if ( DSpFindBestContextOnDisplayID(&attrib, &dsp_context, display_id) != noErr ) { + SDL_SetError ("DrawSprocket couldn't find a suitable context on given display"); + return NULL; + } + + #endif + if ( DSpContext_Reserve (dsp_context, &attrib) != noErr ) { + SDL_SetError ("DrawSprocket couldn't get the needed resources to build the display"); + return NULL; + } + + if ( (err = DSpContext_SetState (dsp_context, kDSpContextState_Active)) != noErr ) { + + if (err == kDSpConfirmSwitchWarning) { + + if ( ! DSp_ConfirmSwitch () ) { + + DSpContext_Release (dsp_context); + dsp_context = NULL; + SDL_SetError ("User cancelled display switch"); + return NULL; + } + else + /* Have to reactivate context. Why? */ + DSpContext_SetState (dsp_context, kDSpContextState_Active); + + } + else { + SDL_SetError ("DrawSprocket couldn't activate the context"); + return NULL; + } + } + + + if (bpp != dsp_old_depth) { + + DSp_CreatePalette (this); + + /* update format if display depth changed */ + if (bpp == 16) { + + rmask = 0x00007c00; + gmask = 0x000003e0; + bmask = 0x0000001f; + } + if ( ! SDL_ReallocFormat (current, bpp, rmask, gmask, bmask, 0 ) ) { + + SDL_SetError ("Could not reallocate video format."); + return(NULL); + } + } + + if (!double_buf) { + + /* single-buffer context */ + DSpContext_GetFrontBuffer (dsp_context, &dsp_back_buffer); + + current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (current ->hwdata == NULL) { + SDL_OutOfMemory (); + return NULL; + } + current->hwdata->offscreen = dsp_back_buffer; + current->flags |= SDL_HWSURFACE; + this->UpdateRects = DSp_DirectUpdate; + } + else if ( use_dsp_back_buffer ) { + + DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); + + current->flags |= SDL_DOUBLEBUF | SDL_SWSURFACE; /* only front buffer is in VRAM */ + this->UpdateRects = DSp_DSpUpdate; + } + else if ( DSp_NewHWSurface(this, &dsp_back_buffer, bpp, width-1, height-1) == 0 ) { + + current->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (current ->hwdata == NULL) { + SDL_OutOfMemory (); + return NULL; + } + + SDL_memset (current->hwdata, 0, sizeof (private_hwdata)); + current->hwdata->offscreen = dsp_back_buffer; + current->flags |= SDL_DOUBLEBUF | SDL_HWSURFACE; + this->UpdateRects = DSp_DirectUpdate; /* hardware doesn't do update rects, must be page-flipped */ + } + else { + + DSpContext_Release (dsp_context); + use_dsp_back_buffer = SDL_TRUE; + goto rebuild; + } + + current->pitch = GetPortPixRowBytes(dsp_back_buffer) & 0x3FFF; + current->pixels = GetPixBaseAddr(GetPortPixMap(dsp_back_buffer)); + + current->w = width; + current->h = height; + + #if ! TARGET_API_MAC_OSX + + if (use_dsp_back_buffer) { + + DSpContext_GetMonitorFrequency (dsp_context, &freq); + DSpContext_SetMaxFrameRate (dsp_context, freq >> 16); + } + + + if ( (current->flags & SDL_HWSURFACE) || (current->flags & SDL_OPENGL) ) + DSpContext_SetVBLProc (dsp_context, DSp_VBLProc, NULL); + #endif + + if (bpp == 8) + current->flags |= SDL_HWPALETTE; + + if (flags & SDL_OPENGL) { + + Rect rect; + RGBColor rgb = { 0.0, 0.0, 0.0 }; + GrafPtr save_port; + + SetRect (&rect, 0, 0, width, height); + SDL_Window = NewCWindow(nil, &( (**SDL_Display).gdRect), "\p", SDL_TRUE, plainDBox, (WindowPtr)-1, SDL_FALSE, 0); + + if (SDL_Window == NULL) { + + SDL_SetError ("DSp_SetVideoMode : OpenGL window could not be created."); + return NULL; + } + + /* Set window color to black to avoid white flash*/ + GetPort (&save_port); +#if TARGET_API_MAC_CARBON + SetPort (GetWindowPort(SDL_Window)); +#else + SetPort (SDL_Window); +#endif + RGBForeColor (&rgb); + PaintRect (&rect); + SetPort (save_port); + + SetPortWindowPort (SDL_Window); + SelectWindow (SDL_Window); + + if ( Mac_GL_Init (this) < 0 ) { + + SDL_SetError ("DSp_SetVideoMode : could not create OpenGL context."); + return NULL; + } + + current->flags |= SDL_OPENGL; + } + + return current; +} + +#ifdef DSP_TRY_CC_AND_AA + +static int DSp_MakeHWMask (_THIS, SDL_Surface *surface) +{ + GDHandle save_device; + CGrafPtr save_port; + GWorldPtr temp; + RGBColor black = { 0, 0, 0 }; + RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; + Rect rect; + + Uint32 depth = GetPixDepth ( GetGDevPixMap (SDL_Display) ); + + SetRect (&rect, 0, 0, surface->w, surface->h); + + if ( noErr != NewGWorld (&(surface->hwdata->mask), depth, &rect, 0, SDL_Display, 0 ) < 0 ) { + + SDL_OutOfMemory (); + return (-1); + } + + if ( noErr != NewGWorld (&temp, depth, &rect, 0 , SDL_Display, 0 ) ) { + + SDL_OutOfMemory (); + return (-1); + } + + + GetGWorld (&save_port, &save_device); + SetGWorld (surface->hwdata->mask, SDL_Display); + + RGBForeColor (&white); + PaintRect (&rect); + + RGBBackColor (&(surface->hwdata->trans)); + + CopyBits ( GetPortBitMapForCopyBits(surface->hwdata->offscreen), + GetPortBitMapForCopyBits(surface->hwdata->mask), + &rect, &rect, transparent, NULL ); + + SetGWorld (surface->hwdata->mask, SDL_Display); + SetGWorld (save_port, save_device); + return (0); +} + +static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha) +{ + surface->hwdata->alpha.red = (alpha / 255.0) * 65535; + surface->hwdata->alpha.blue = (alpha / 255.0) * 65535; + surface->hwdata->alpha.green = (alpha / 255.0) * 65535; + + surface->flags |= SDL_SRCALPHA; + + if (surface->flags & SDL_SRCCOLORKEY) { + return(DSp_MakeHWMask (this, surface)); + } + return(0); +} + +static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + CGrafPtr save_port; + GDHandle save_device; + + GetGWorld (&save_port, &save_device); + SetGWorld (surface->hwdata->offscreen, NULL); + + Index2Color (key, &(surface->hwdata->trans)); + surface->flags |= SDL_SRCCOLORKEY; + + SetGWorld (save_port, save_device); + + if ( surface->flags & SDL_SRCALPHA ) { + return(DSp_MakeHWMask (this, surface)); + } + return(0); +} + +#endif /* DSP_TRY_CC_AND_AA */ + +static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height) { + + OSStatus err; + Rect bounds; + + SetRect (&bounds, 0, 0, width, height); + + #if useDistantHdwrMem && useLocalHdwrMem + if (dsp_vram_available) { + /* try VRAM */ + err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useDistantHdwrMem | noNewDevice ); + if (err != noErr) + DSp_SetHWError (err, SDL_FALSE); + else + return (0); + } + + if (dsp_agp_available) { + /* try AGP */ + err = NewGWorld (port, depth, &bounds, 0 , SDL_Display, useLocalHdwrMem | noNewDevice ); + + if (err != noErr) + DSp_SetHWError (err, SDL_TRUE); + else + return (0); + } +#endif + + return (-1); +} + +static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + GWorldPtr temp; + + if ( DSp_NewHWSurface (this, &temp, surface->format->BitsPerPixel, surface->w, surface->h) < 0 ) + return (-1); + + surface->hwdata = (private_hwdata*) SDL_malloc (sizeof (private_hwdata)); + if (surface->hwdata == NULL) { + SDL_OutOfMemory (); + return -1; + } + + SDL_memset (surface->hwdata, 0, sizeof(private_hwdata)); + surface->hwdata->offscreen = temp; + surface->pitch = GetPixRowBytes (GetPortPixMap (temp)) & 0x3FFF; + surface->pixels = GetPixBaseAddr (GetPortPixMap (temp)); + surface->flags |= SDL_HWSURFACE; +#ifdef DSP_TRY_CC_AND_AA + surface->flags |= SDL_HWACCEL; +#endif + return 0; +} + +static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->hwdata->offscreen != NULL) + DisposeGWorld (surface->hwdata->offscreen); + SDL_free(surface->hwdata); + + surface->pixels = NULL; +} + +static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = DSp_HWAccelBlit; + } + return(accelerated); +} + +static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + CGrafPtr save_port; + GDHandle save_device; + Rect src_rect, dst_rect; + RGBColor black = { 0, 0, 0 }; + RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF }; + +#ifdef DSP_TRY_CC_AND_AA + UInt32 mode; +#endif + + SetRect (&src_rect, srcrect->x, srcrect->y, srcrect->x + srcrect->w, srcrect->y + srcrect->h); + SetRect (&dst_rect, dstrect->x, dstrect->y, dstrect->x + dstrect->w, dstrect->y + dstrect->h); + + GetGWorld (&save_port, &save_device); + SetGWorld (dst->hwdata->offscreen, NULL); + + RGBForeColor (&black); + RGBBackColor (&white); + +#ifdef DSP_TRY_CC_AND_AA + + if ( (src->flags & SDL_SRCCOLORKEY) && + (src->flags & SDL_SRCALPHA) ) { + + OpColor (&(src->hwdata->alpha)); + + CopyDeepMask ( GetPortBitMapForCopyBits(src->hwdata->offscreen), + GetPortBitMapForCopyBits(src->hwdata->mask), + GetPortBitMapForCopyBits(dst->hwdata->offscreen), + &src_rect, &src_rect, &dst_rect, + blend, + NULL ); + } + else { + + if ( src->flags & SDL_SRCCOLORKEY) { + RGBBackColor (&(src->hwdata->trans) ); + mode = transparent; + } + else if (src->flags & SDL_SRCALPHA) { + + OpColor (&(src->hwdata->alpha)); + mode = blend; + } + else { + + mode = srcCopy; + } + + CopyBits ( GetPortBitMapForCopyBits(src->hwdata->offscreen), + GetPortBitMapForCopyBits(dst->hwdata->offscreen), + &src_rect, &dst_rect, mode, NULL ); + } +#else + + CopyBits ( &(((GrafPtr)(src->hwdata->offscreen))->portBits), + &(((GrafPtr)(dst->hwdata->offscreen))->portBits), + &src_rect, &dst_rect, srcCopy, NULL ); + +#endif /* DSP_TRY_CC_AND_AA */ + + SetGWorld (save_port, save_device); + + return(0); +} + +static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + CGrafPtr save_port; + GDHandle save_device; + Rect fill_rect; + RGBColor rgb; + + SetRect (&fill_rect, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h); + + GetGWorld (&save_port, &save_device); + SetGWorld (dst->hwdata->offscreen, NULL); + + Index2Color (color, &rgb); + + RGBForeColor (&rgb); + PaintRect (&fill_rect); + + SetGWorld (save_port, save_device); + + return(0); +} + +static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( (surface->flags & SDL_HWSURFACE) ) { + CGrafPtr dsp_front_buffer, save_port; + Rect rect; + + #if ! TARGET_API_MAC_OSX + unsigned int old_count; + #endif + + /* pseudo page flipping for VRAM back buffer*/ + DSpContext_GetFrontBuffer (dsp_context, &dsp_front_buffer); + SetRect (&rect, 0, 0, surface->w-1, surface->h-1); + + GetPort ((GrafPtr *)&save_port); + SetPort ((GrafPtr)dsp_front_buffer); + + /* wait for retrace */ + /* I have tried doing the swap in interrupt routine (VBL Proc) to do */ + /* it asynchronously, but apparently CopyBits isn't interrupt safe */ + + #if ! TARGET_API_MAC_OSX + #ifndef DSP_NO_SYNC_VBL + old_count = retrace_count; + while (old_count == retrace_count) + ; + #endif + #endif + + CopyBits ( GetPortBitMapForCopyBits(dsp_back_buffer), + GetPortBitMapForCopyBits(dsp_front_buffer), + &rect, &rect, srcCopy, NULL ); + + SetPort ((GrafPtr)save_port); + + } else { + /* not really page flipping at all: DSp just blits the dirty rectangles from DSp_UpdateRects */ + Boolean busy_flag; + DSpContext_SwapBuffers (dsp_context, NULL, &busy_flag); /* this waits for VBL */ + DSpContext_GetBackBuffer (dsp_context, kDSpBufferKind_Normal, &dsp_back_buffer); + surface->pixels = GetPixBaseAddr( GetPortPixMap(dsp_back_buffer) ); + } + return(0); +} + +static int DSp_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( LockPixels (GetGWorldPixMap (surface->hwdata->offscreen)) ) + return 0; + else + return -1; +} + +static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + UnlockPixels (GetGWorldPixMap (surface->hwdata->offscreen)); +} + +static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) +{ + return; +} + +static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects) +{ +#if ! TARGET_API_MAC_OSX /* Unsupported DSp in here */ + int i; + Rect rect; + + for (i = 0; i < numrects; i++) { + + rect.top = sdl_rects[i].y; + rect.left = sdl_rects[i].x; + rect.bottom = sdl_rects[i].h + sdl_rects[i].y; + rect.right = sdl_rects[i].w + sdl_rects[i].x; + + DSpContext_InvalBackBufferRect (dsp_context, &rect); + } +#endif +} + +static int DSp_CreatePalette(_THIS) { + + + /* Create our palette */ + SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); + if ( SDL_CTab == nil ) { + SDL_OutOfMemory(); + return(-1); + } + (**SDL_CTab).ctSeed = GetCTSeed(); + (**SDL_CTab).ctFlags = 0; + (**SDL_CTab).ctSize = 255; + CTabChanged(SDL_CTab); + SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); + + return 0; +} + +static int DSp_DestroyPalette(_THIS) { + + /* Free palette and restore original one */ + if ( SDL_CTab != nil ) { + DisposeHandle((Handle)SDL_CTab); + SDL_CTab = nil; + } + if ( SDL_CPal != nil ) { + DisposePalette(SDL_CPal); + SDL_CPal = nil; + } + RestoreDeviceClut(SDL_Display); + + return (0); +} + +static int DSp_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + CTabHandle cTab; + + int i; + + cTab = SDL_CTab; + + /* Verify the range of colors */ + if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { + return(0); + } + + /* Set the screen palette and update the display */ + for(i = 0; i < ncolors; i++) { + int j = firstcolor + i; + (**cTab).ctTable[j].value = j; + (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; + (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; + (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; + } + + SetGDevice(SDL_Display); + SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); + + return(1); +} + +void DSp_VideoQuit(_THIS) +{ + int i; + + /* Free current video mode */ + DSp_UnsetVideoMode(this, this->screen); + + /* Free Palette and restore original */ + DSp_DestroyPalette (this); + +#if SDL_MACCLASSIC_GAMMA_SUPPORT + Mac_QuitGamma(this); +#endif + + /* Free list of video modes */ + if ( SDL_modelist != NULL ) { + for ( i=0; SDL_modelist[i]; i++ ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } + + /* Unload DrawSprocket */ + DSpShutdown (); +} + +#if SDL_VIDEO_OPENGL + +/* swap buffers with v-sync */ +static void DSp_GL_SwapBuffers (_THIS) { + + #ifndef DSP_NO_SYNC_OPENGL + + unsigned int old_count; + + old_count = retrace_count; + while (old_count == retrace_count) + ; + #endif + + aglSwapBuffers (glContext); +} + +#endif diff --git a/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h new file mode 100644 index 0000000..7fc0896 --- /dev/null +++ b/3rdparty/SDL/src/video/macdsp/SDL_dspvideo.h @@ -0,0 +1,54 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dspvideo_h +#define _SDL_dspvideo_h + +#if TARGET_API_MAC_OSX +# include <DrawSprocket/DrawSprocket.h> /* Drawsprocket.framework */ +#else +#include <DrawSprocket.h> +#endif + +#include "../maccommon/SDL_lowvideo.h" + +/* DrawSprocket specific information */ +struct DSpInfo { + DSpContextReference dsp_context; + CGrafPtr dsp_back_buffer; + int dsp_old_depth; + + /* Flags for hw acceleration */ + int dsp_vram_available; + int dsp_agp_available; + + +}; +/* Old variable names */ +#define dsp_context (this->hidden->dspinfo->dsp_context) +#define dsp_back_buffer (this->hidden->dspinfo->dsp_back_buffer) +#define dsp_old_depth (this->hidden->dspinfo->dsp_old_depth) +#define dsp_vram_available (this->hidden->dspinfo->dsp_vram_available) +#define dsp_agp_available (this->hidden->dspinfo->dsp_agp_available) + +#endif /* _SDL_dspvideo_h */ diff --git a/3rdparty/SDL/src/video/macrom/SDL_romvideo.c b/3rdparty/SDL/src/video/macrom/SDL_romvideo.c new file mode 100644 index 0000000..4c48881 --- /dev/null +++ b/3rdparty/SDL/src/video/macrom/SDL_romvideo.c @@ -0,0 +1,745 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if defined(__APPLE__) && defined(__MACH__) +#include <Carbon/Carbon.h> +#if USE_QUICKTIME +#include <QuickTime/Movies.h> +#endif +#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +#include <Carbon.h> +/* The fullscreen code requires the QuickTime framework, and the window + is still at the back on Mac OS X, which is where this code is needed. + */ +#if USE_QUICKTIME +#include <Movies.h> +#endif +#else +#include <Quickdraw.h> +#include <LowMem.h> +#include <Gestalt.h> +#include <Devices.h> +#include <DiskInit.h> +#include <QDOffscreen.h> +#endif + +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "SDL_romvideo.h" +#include "../maccommon/SDL_macgl_c.h" +#include "../maccommon/SDL_macwm_c.h" +#include "../maccommon/SDL_macmouse_c.h" +#include "../maccommon/SDL_macevents_c.h" + +/* Initialization/Query functions */ +static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int ROM_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void ROM_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface); +static int ROM_LockHWSurface(_THIS, SDL_Surface *surface); +static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface); + +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ +/* Saved state for the menu bar */ +static RgnHandle gSaveGrayRgn = nil; +static short gSaveMenuBar = 0; +static Boolean gSaveCSVis = true; + +#if powerc +/* Mixed mode glue to activate the 68K emulator and twiddle a register */ +#define ONEWORDSTUB(p1) \ + { 0x41FA, 0x0010, 0x209F, (p1), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +#define TWOWORDSTUB(p1,p2) \ + { 0x41FA, 0x0012, 0x209F, (p1), (p2), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +#define THREEWORDSTUB(p1,p2,p3) \ + { 0x41FA, 0x0014, 0x209F, (p1), (p2), (p3), 0x41FA, \ + 0x0008, 0x2F10, 0x4E75, 0x0000, 0x0000, 0x0000 } + +/* ControlStrip inline glue for PowerPC */ +static pascal Boolean SBIsControlStripVisible(void) +{ + static short procData[] = TWOWORDSTUB(0x7000, 0xAAF2); + ProcInfoType procInfo = kD0DispatchedPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(Boolean))) + | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode); + + return((Boolean) CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x00)); +} + +static pascal void SBShowHideControlStrip(Boolean showIt) +{ + static short procData[] = THREEWORDSTUB(0x303C, 0x0101, 0xAAF2); + ProcInfoType procInfo = kD0DispatchedPascalStackBased + | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode) + | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Boolean))); + + CallUniversalProc((UniversalProcPtr) procData, procInfo, 0x01, showIt); +} +#endif /* powerc */ +#endif /* !TARGET_API_MAC_CARBON */ + +/* Macintosh toolbox driver bootstrap functions */ + +static int ROM_Available(void) +{ + return(1); +} + +static void ROM_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *ROM_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = ROM_VideoInit; + device->ListModes = ROM_ListModes; + device->SetVideoMode = ROM_SetVideoMode; + device->SetColors = ROM_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = ROM_VideoQuit; + device->AllocHWSurface = ROM_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = ROM_LockHWSurface; + device->UnlockHWSurface = ROM_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = ROM_FreeHWSurface; +#if SDL_MACCLASSIC_GAMMA_SUPPORT + device->SetGammaRamp = Mac_SetGammaRamp; + device->GetGammaRamp = Mac_GetGammaRamp; +#endif +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = Mac_GL_MakeCurrent; + device->GL_SwapBuffers = Mac_GL_SwapBuffers; + device->GL_LoadLibrary = Mac_GL_LoadLibrary; + device->GL_GetProcAddress = Mac_GL_GetProcAddress; +#endif /* Have OpenGL */ + device->SetCaption = Mac_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = Mac_FreeWMCursor; + device->CreateWMCursor = Mac_CreateWMCursor; + device->ShowWMCursor = Mac_ShowWMCursor; + device->WarpWMCursor = Mac_WarpWMCursor; + device->InitOSKeymap = Mac_InitOSKeymap; + device->PumpEvents = Mac_PumpEvents; + + device->free = ROM_DeleteDevice; + + return device; +} + +VideoBootStrap TOOLBOX_bootstrap = { + "toolbox", "MacOS ROM Toolbox", + ROM_Available, ROM_CreateDevice +}; + + +static int ROM_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + long info; + + /* Check out some things about the system */ + Gestalt(gestaltQuickdrawVersion, &info); + if ( info == gestaltOriginalQD ) { + SDL_SetError("Color Quickdraw not available"); + return(-1); + } + + /* Start ROMintosh events */ + Mac_InitEvents(this); + + /* Get a handle to the main monitor */ + SDL_Display = GetMainDevice(); + + /* Determine the current screen size */ + this->info.current_w = (**SDL_Display).gdRect.right; + this->info.current_h = (**SDL_Display).gdRect.bottom; + + /* Determine pixel format */ + vformat->BitsPerPixel = (**(**SDL_Display).gdPMap).pixelSize; + switch (vformat->BitsPerPixel) { + case 16: /* 5-5-5 RGB */ + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + break; + default: + break; + } + + /* Create our palette */ + SDL_CTab = (CTabHandle)NewHandle(sizeof(ColorSpec)*256 + 8); + if ( SDL_CTab == nil ) { + SDL_OutOfMemory(); + return(-1); + } + (**SDL_CTab).ctSeed = GetCTSeed(); + (**SDL_CTab).ctFlags = 0; + (**SDL_CTab).ctSize = 255; + CTabChanged(SDL_CTab); + SDL_CPal = NewPalette(256, SDL_CTab, pmExplicit+pmTolerant, 0); + + /* Get a list of available fullscreen modes */ + SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist ) { + SDL_modelist[0] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[0] ) { + SDL_modelist[0]->x = 0; + SDL_modelist[0]->y = 0; + SDL_modelist[0]->w = (**SDL_Display).gdRect.right; + SDL_modelist[0]->h = (**SDL_Display).gdRect.bottom; + } + SDL_modelist[1] = NULL; + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +static SDL_Rect **ROM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( this->screen->format->BitsPerPixel == format->BitsPerPixel ) { + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + return(SDL_modelist); + } else { + return((SDL_Rect **)-1); + } + } else { + return((SDL_Rect **)0); + } +} + +static void ROM_HideMenuBar(_THIS) +{ +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ + RgnHandle drawRgn = nil; + RgnHandle tempRgn = nil; + RgnHandle grayRgn = nil; + WindowPtr window = nil; + GDHandle gd = nil; + GrafPtr savePort; + long response; + short height; + EventRecord theEvent; + + height = GetMBarHeight(); + + if ( height > 0 ) { + tempRgn = NewRgn(); + drawRgn = NewRgn(); + gSaveGrayRgn = NewRgn(); + if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) { + goto CLEANUP; + } + grayRgn = GetGrayRgn(); /* No need to check for this */ + + GetPort(&savePort); + + /* Hide the control strip if it's present, and record its + previous position into the dirty region for redrawing. + This isn't necessary, but may help catch stray bits. */ + CopyRgn(grayRgn, tempRgn); + if (!Gestalt(gestaltControlStripAttr, &response) && + (response & (1L << gestaltControlStripExists))) { + gSaveCSVis = SBIsControlStripVisible(); + if (gSaveCSVis) + SBShowHideControlStrip(false); + } + DiffRgn(grayRgn, tempRgn, drawRgn); + + /* Save the gray region once the control strip is hidden*/ + CopyRgn(grayRgn, gSaveGrayRgn); + + /* Change the menu height in lowmem */ + gSaveMenuBar = height; + LMSetMBarHeight(0); + + /* Walk the monitor rectangles, and combine any pieces that + aren't in GrayRgn: menubar, round corners, fake floaters. */ + for(gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) + { + if (!TestDeviceAttribute(gd, screenDevice)) continue; + if (!TestDeviceAttribute(gd, screenActive)) continue; + + RectRgn(tempRgn, &(*gd)->gdRect); /* Get the whole screen */ + DiffRgn(tempRgn, grayRgn, tempRgn); /* Subtract out GrayRgn */ + UnionRgn(tempRgn, drawRgn, drawRgn);/* Combine all the bits */ + } + + /* Add the bits into the GrayRgn */ + UnionRgn(drawRgn, grayRgn, grayRgn); + + /* Modify the vis regions of exposed windows */ + window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L; + PaintBehind(window, drawRgn); + CalcVisBehind(window, drawRgn); + + SetPort(savePort); + + /* Yield time so that floaters can catch up */ + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + } + +CLEANUP: + + if (tempRgn) DisposeRgn(tempRgn); + if (drawRgn) DisposeRgn(drawRgn); +#endif /* !TARGET_API_MAC_CARBON */ +} + +static void ROM_ShowMenuBar(_THIS) +{ +#if !TARGET_API_MAC_CARBON /* This seems not to be available? -sts Aug 2000 */ + RgnHandle drawRgn = nil; + RgnHandle menuRgn = nil; + RgnHandle tempRgn = nil; + RgnHandle grayRgn = nil; + WindowPtr window = nil; + GrafPtr wMgrPort; + GrafPtr savePort; + Rect menuRect; + long response; + short height; + EventRecord theEvent; + RGBColor saveRGB; + RGBColor blackRGB = { 0, 0, 0 }; + + height = GetMBarHeight(); + + if ((height <= 0) && (gSaveMenuBar > 0)) { + drawRgn = NewRgn(); + menuRgn = NewRgn(); + tempRgn = NewRgn(); + if ( ! tempRgn || ! drawRgn || ! gSaveGrayRgn ) { + goto CLEANUP; + } + grayRgn = GetGrayRgn(); /* No need to check for this */ + + GetPort(&savePort); + GetWMgrPort(&wMgrPort); + + /* Set the height properly */ + LMSetMBarHeight(gSaveMenuBar); + + /* Restore the old GrayRgn: rounded corners, etc, but not + the menubar -- subtract that out first! */ + if (gSaveGrayRgn) + { + menuRect = (*GetMainDevice())->gdRect; + menuRect.bottom = menuRect.top + gSaveMenuBar; + RectRgn(menuRgn, &menuRect); + + DiffRgn(grayRgn, gSaveGrayRgn, drawRgn); /* What do we inval? */ + DiffRgn(drawRgn, menuRgn, drawRgn); /* Clip out the menu */ + + /* Now redraw the corners and other bits black */ + SetPort(wMgrPort); + GetClip(tempRgn); + SetClip(drawRgn); + GetForeColor(&saveRGB); + RGBForeColor(&blackRGB); + PaintRgn(drawRgn); + RGBForeColor(&saveRGB); + SetClip(tempRgn); + SetPort(savePort); + + UnionRgn(drawRgn, menuRgn, drawRgn); /* Put back the menu */ + + /* Now actually restore the GrayRgn */ + CopyRgn(gSaveGrayRgn, grayRgn); + DisposeRgn(gSaveGrayRgn); + gSaveGrayRgn = nil; + } + + /* Modify the vis regions of exposed windows and draw menubar */ + window = (FrontWindow()) ? FrontWindow() : (WindowPtr) -1L; + PaintBehind(window, drawRgn); + CalcVisBehind(window, drawRgn); + DrawMenuBar(); + + SetPort(savePort); + gSaveMenuBar = 0; + + /* Now show the control strip if it's present */ + if (!Gestalt(gestaltControlStripAttr, &response) && + (response & (1L << gestaltControlStripExists))) + { + if (gSaveCSVis && !SBIsControlStripVisible()) + SBShowHideControlStrip(true); + gSaveCSVis = true; + } + + /* Yield time so that floaters can catch up */ + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + EventAvail(0, &theEvent); + } + +CLEANUP: + + if (drawRgn) DisposeRgn(drawRgn); + if (menuRgn) DisposeRgn(menuRgn); + if (tempRgn) DisposeRgn(tempRgn); +#endif /* !TARGET_API_MAC_CARBON */ +} + +/* Various screen update functions available */ +static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects); + +static void ROM_UnsetVideoMode(_THIS, SDL_Surface *current) +{ + /* Free the current window, if any */ + if ( SDL_Window != nil ) { + GWorldPtr memworld; + + /* Handle OpenGL support */ + Mac_GL_Quit(this); + + memworld = (GWorldPtr)GetWRefCon(SDL_Window); + if ( memworld != nil ) { + UnlockPixels(GetGWorldPixMap(memworld)); + DisposeGWorld(memworld); + } + if ( (current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { +#if USE_QUICKTIME + EndFullScreen(fullscreen_ctx, nil); + SDL_Window = nil; +#else + ROM_ShowMenuBar(this); +#endif + } + } + current->pixels = NULL; + current->flags &= ~(SDL_HWSURFACE|SDL_FULLSCREEN); +} + +static SDL_Surface *ROM_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Rect wrect, orect; +#if TARGET_API_MAC_CARBON + Rect tmprect; +#endif + + /* Free any previous video mode */ + ROM_UnsetVideoMode(this, current); + + /* Create the ROM window and SDL video surface */ + current->flags = 0; /* Clear flags */ + current->w = width; + current->h = height; + SetRect(&wrect, 0, 0, width, height); + if ( SDL_Window ) { + /* If we recreate the window, don't move it around */ +#if TARGET_API_MAC_CARBON + orect = *GetWindowPortBounds(SDL_Window, &tmprect); +#else + orect = SDL_Window->portRect; +#endif + OffsetRect(&wrect, orect.left, orect.top); + } else { + /* Center the window the first time we show it */ + OffsetRect(&wrect, + (SDL_modelist[0]->w-width)/2, (SDL_modelist[0]->h-height)/2); + } + +#if defined(__MACOSX__) && !USE_QUICKTIME + /* Hum.. fullscreen mode is broken */ + flags &= ~SDL_FULLSCREEN; +#endif + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* Create the fullscreen window and use screen bits */ + current->flags |= SDL_HWSURFACE|SDL_FULLSCREEN; + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + } +#if USE_QUICKTIME + BeginFullScreen(&fullscreen_ctx, nil, 0,0, &SDL_Window, nil, 0); +#else + SDL_Window = NewCWindow(nil, &wrect, "\p", true, plainDBox, + (WindowPtr)-1, false, 0); + ROM_HideMenuBar(this); +#endif + current->pitch = (**(**SDL_Display).gdPMap).rowBytes & 0x3FFF; + current->pixels = (**(**SDL_Display).gdPMap).baseAddr; + this->UpdateRects = ROM_DirectUpdate; + } else { + GWorldPtr memworld; + PixMapHandle pixmap; + int style; + + style = noGrowDocProc; + if ( flags & SDL_NOFRAME ) { + style = plainDBox; + current->flags |= SDL_NOFRAME; + } else + if ( flags & SDL_RESIZABLE ) { + style = zoomDocProc; + current->flags |= SDL_RESIZABLE; + } + if ( SDL_Window && (style == current_style) ) { + /* Resize existing window, if necessary */ + if ( ((orect.right-orect.left) != width) || + ((orect.bottom-orect.top) != height) ) { + SizeWindow(SDL_Window, width, height, false); + } + } else { + /* Recreate the window in the new style */ + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + } + SDL_Window = NewCWindow(nil, &wrect, "\p", true, + style, (WindowPtr)-1, true, 0); + + /* Set the window title, if any */ + { char *title; + SDL_WM_GetCaption(&title, NULL); + if ( title ) { + Mac_SetCaption(this, title, NULL); + } + } + } + current_style = style; + SetPalette(SDL_Window, SDL_CPal, false); + ActivatePalette(SDL_Window); + if ( NewGWorld(&memworld, 0, +#if TARGET_API_MAC_CARBON + GetWindowPortBounds(SDL_Window, &tmprect), +#else + &SDL_Window->portRect, +#endif + SDL_CTab, nil, 0) != noErr ) { + SDL_SetError("NewGWorld() failed"); + return(NULL); + } + SetWRefCon(SDL_Window, (long)memworld); + pixmap = GetGWorldPixMap(memworld); + LockPixels(pixmap); + current->pitch = (**pixmap).rowBytes & 0x3FFF; + current->pixels = GetPixBaseAddr(pixmap); + this->UpdateRects = ROM_WindowUpdate; + } + SetPortWindowPort(SDL_Window); + SelectWindow(SDL_Window); + + /* Handle OpenGL support */ + if ( flags & SDL_OPENGL ) { + if ( Mac_GL_Init(this) == 0 ) { + current->flags |= SDL_OPENGL; + } else { + current = NULL; + } + } + + if ( (flags & SDL_HWPALETTE) && (flags & SDL_FULLSCREEN) ) + current->flags |= SDL_HWPALETTE; + + /* We're live! */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int ROM_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void ROM_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int ROM_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void ROM_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void ROM_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* The application is already updating the visible video memory */ + return; +} + +static void ROM_WindowUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + GWorldPtr memworld; + GrafPtr saveport; + CGrafPtr thePort; + const BitMap *memBits; + const BitMap *winBits; + int i; + Rect update; + + /* Copy from the offscreen GWorld to the window port */ + GetPort(&saveport); + SetPortWindowPort(SDL_Window); + thePort = GetWindowPort(SDL_Window); + memworld = (GWorldPtr)GetWRefCon(SDL_Window); +#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS + memBits = GetPortBitMapForCopyBits((CGrafPtr) memworld); +#else + memBits = &((GrafPtr)memworld)->portBits; +#endif +#if TARGET_API_MAC_CARBON && ACCESSOR_CALLS_ARE_FUNCTIONS + winBits = GetPortBitMapForCopyBits(thePort); +#else + winBits = &SDL_Window->portBits; +#endif + for ( i=0; i<numrects; ++i ) { + update.left = rects[i].x; + update.right = rects[i].x+rects[i].w; + update.top = rects[i].y; + update.bottom = rects[i].y+rects[i].h; + CopyBits(memBits, winBits, + &update, &update, srcCopy, nil); + } +#if TARGET_API_MAC_CARBON + if ( QDIsPortBuffered(thePort) ) { + QDFlushPortBuffer(thePort, NULL); + } +#endif + SetPort(saveport); +} + +static int ROM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + CTabHandle cTab; + int i; + + /* Get the colortable from the either the display or window */ + if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + cTab = (**(**SDL_Display).gdPMap).pmTable; + } else { + cTab = SDL_CTab; + } + + /* Verify the range of colors */ + if ( (firstcolor+ncolors) > ((**cTab).ctSize+1) ) { + return(0); + } + + /* Set the screen palette and update the display */ + for ( i=0; i< ncolors; ++i ) { + int j = firstcolor + i; + (**cTab).ctTable[j].value = j; + (**cTab).ctTable[j].rgb.red = colors[i].r << 8 | colors[i].r; + (**cTab).ctTable[j].rgb.green = colors[i].g << 8 | colors[i].g; + (**cTab).ctTable[j].rgb.blue = colors[i].b << 8 | colors[i].b; + } + +#if 0 + if ( (this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) +#endif + { + GDevice **odisplay; + odisplay = GetGDevice(); + SetGDevice(SDL_Display); + SetEntries(0, (**cTab).ctSize, (ColorSpec *)&(**cTab).ctTable); + SetGDevice(odisplay); + } + return(1); +} + +void ROM_VideoQuit(_THIS) +{ + int i; + + /* Free current video mode */ + ROM_UnsetVideoMode(this, this->screen); + if ( SDL_Window ) { + DisposeWindow(SDL_Window); + SDL_Window = nil; + } + + /* Free palette and restore original one */ + if ( SDL_CTab != nil ) { + DisposeHandle((Handle)SDL_CTab); + SDL_CTab = nil; + } + if ( SDL_CPal != nil ) { + DisposePalette(SDL_CPal); + SDL_CPal = nil; + } + RestoreDeviceClut(GetMainDevice()); + +#if SDL_MACCLASSIC_GAMMA_SUPPORT + Mac_QuitGamma(this); +#endif + + /* Free list of video modes */ + if ( SDL_modelist != NULL ) { + for ( i=0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/macrom/SDL_romvideo.h b/3rdparty/SDL/src/video/macrom/SDL_romvideo.h new file mode 100644 index 0000000..0380f91 --- /dev/null +++ b/3rdparty/SDL/src/video/macrom/SDL_romvideo.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_romvideo_h +#define _SDL_romvideo_h + +#include "../maccommon/SDL_lowvideo.h" + +#endif /* _SDL_romvideo_h */ diff --git a/3rdparty/SDL/src/video/math_private.h b/3rdparty/SDL/src/video/math_private.h new file mode 100644 index 0000000..1087d7d --- /dev/null +++ b/3rdparty/SDL/src/video/math_private.h @@ -0,0 +1,173 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + * $Id$ + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +#include "SDL_name.h" +#include "SDL_endian.h" + +#define huge really_big /* huge is a reserved keyword in VC++ 6.0 */ +#define u_int32_t uint32_t + +/* The original fdlibm code used statements like: + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +/* + * Math on arm is special: + * For FPA, float words are always big-endian. + * For VFP, floats words follow the memory system mode. + */ + +#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) || \ + (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__))) + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; +} ieee_double_shape_type; + +#else + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + u_int32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#endif /* _MATH_PRIVATE_H_ */ diff --git a/3rdparty/SDL/src/video/mmx.h b/3rdparty/SDL/src/video/mmx.h new file mode 100644 index 0000000..dcee7b0 --- /dev/null +++ b/3rdparty/SDL/src/video/mmx.h @@ -0,0 +1,704 @@ +/* mmx.h + + MultiMedia eXtensions GCC interface library for IA32. + + To use this library, simply include this header file + and compile with GCC. You MUST have inlining enabled + in order for mmx_ok() to work; this can be done by + simply using -O on the GCC command line. + + Compiling with -DMMX_TRACE will cause detailed trace + output to be sent to stderr for each mmx operation. + This adds lots of code, and obviously slows execution to + a crawl, but can be very useful for debugging. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT + LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR ANY PARTICULAR PURPOSE. + + 1997-99 by H. Dietz and R. Fisher + + Notes: + It appears that the latest gas has the pand problem fixed, therefore + I'll undefine BROKEN_PAND by default. +*/ + +#ifndef _MMX_H +#define _MMX_H + + +/* Warning: at this writing, the version of GAS packaged + with most Linux distributions does not handle the + parallel AND operation mnemonic correctly. If the + symbol BROKEN_PAND is defined, a slower alternative + coding will be used. If execution of mmxtest results + in an illegal instruction fault, define this symbol. +*/ +#undef BROKEN_PAND + + +/* The type of an value that fits in an MMX register + (note that long long constant values MUST be suffixed + by LL and unsigned long long values by ULL, lest + they be truncated by the compiler) +*/ +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} __attribute__ ((aligned (8))) mmx_t; /* On an 8-byte (64-bit) boundary */ + + +#if 0 +/* Function to test if multimedia instructions are supported... +*/ +inline extern int +mm_support(void) +{ + /* Returns 1 if MMX instructions are supported, + 3 if Cyrix MMX and Extended MMX instructions are supported + 5 if AMD MMX and 3DNow! instructions are supported + 0 if hardware does not support any of these + */ + register int rval = 0; + + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %%eax\n\t" + "push %%eax\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %%eax\n\t" + + /* ... Compare and test result */ + "xorl %%eax, %%ecx\n\t" + "testl $0x200000, %%ecx\n\t" + "jz NotSupported1\n\t" /* CPUID not supported */ + + + /* Get standard CPUID information, and + go to a specific vendor section */ + "movl $0, %%eax\n\t" + "cpuid\n\t" + + /* Check for Intel */ + "cmpl $0x756e6547, %%ebx\n\t" + "jne TryAMD\n\t" + "cmpl $0x49656e69, %%edx\n\t" + "jne TryAMD\n\t" + "cmpl $0x6c65746e, %%ecx\n" + "jne TryAMD\n\t" + "jmp Intel\n\t" + + /* Check for AMD */ + "\nTryAMD:\n\t" + "cmpl $0x68747541, %%ebx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x69746e65, %%edx\n\t" + "jne TryCyrix\n\t" + "cmpl $0x444d4163, %%ecx\n" + "jne TryCyrix\n\t" + "jmp AMD\n\t" + + /* Check for Cyrix */ + "\nTryCyrix:\n\t" + "cmpl $0x69727943, %%ebx\n\t" + "jne NotSupported2\n\t" + "cmpl $0x736e4978, %%edx\n\t" + "jne NotSupported3\n\t" + "cmpl $0x64616574, %%ecx\n\t" + "jne NotSupported4\n\t" + /* Drop through to Cyrix... */ + + + /* Cyrix Section */ + /* See if extended CPUID level 80000001 is supported */ + /* The value of CPUID/80000001 for the 6x86MX is undefined + according to the Cyrix CPU Detection Guide (Preliminary + Rev. 1.01 table 1), so we'll check the value of eax for + CPUID/0 to see if standard CPUID level 2 is supported. + According to the table, the only CPU which supports level + 2 is also the only one which supports extended CPUID levels. + */ + "cmpl $0x2, %%eax\n\t" + "jne MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported (in theory), so get extended + features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%eax\n\t" /* Test for MMX */ + "jz NotSupported5\n\t" /* MMX not supported */ + "testl $0x01000000, %%eax\n\t" /* Test for Ext'd MMX */ + "jnz EMMXSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "EMMXSupported:\n\t" + "movl $3, %0:\n\n\t" /* EMMX and MMX Supported */ + "jmp Return\n\t" + + + /* AMD Section */ + "AMD:\n\t" + + /* See if extended CPUID is supported */ + "movl $0x80000000, %%eax\n\t" + "cpuid\n\t" + "cmpl $0x80000000, %%eax\n\t" + "jl MMXtest\n\t" /* Use standard CPUID instead */ + + /* Extended CPUID supported, so get extended features */ + "movl $0x80000001, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported6\n\t" /* MMX not supported */ + "testl $0x80000000, %%edx\n\t" /* Test for 3DNow! */ + "jnz ThreeDNowSupported\n\t" + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\n" + "ThreeDNowSupported:\n\t" + "movl $5, %0:\n\n\t" /* 3DNow! and MMX Supported */ + "jmp Return\n\t" + + + /* Intel Section */ + "Intel:\n\t" + + /* Check for MMX */ + "MMXtest:\n\t" + "movl $1, %%eax\n\t" + "cpuid\n\t" + "testl $0x00800000, %%edx\n\t" /* Test for MMX */ + "jz NotSupported7\n\t" /* MMX Not supported */ + "movl $1, %0:\n\n\t" /* MMX Supported */ + "jmp Return\n\t" + + /* Nothing supported */ + "\nNotSupported1:\n\t" + "#movl $101, %0:\n\n\t" + "\nNotSupported2:\n\t" + "#movl $102, %0:\n\n\t" + "\nNotSupported3:\n\t" + "#movl $103, %0:\n\n\t" + "\nNotSupported4:\n\t" + "#movl $104, %0:\n\n\t" + "\nNotSupported5:\n\t" + "#movl $105, %0:\n\n\t" + "\nNotSupported6:\n\t" + "#movl $106, %0:\n\n\t" + "\nNotSupported7:\n\t" + "#movl $107, %0:\n\n\t" + "movl $0, %0:\n\n\t" + + "Return:\n\t" + : "=a" (rval) + : /* no input */ + : "eax", "ebx", "ecx", "edx" + ); + + /* Return */ + return(rval); +} + +/* Function to test if mmx instructions are supported... +*/ +inline extern int +mmx_ok(void) +{ + /* Returns 1 if MMX instructions are supported, 0 otherwise */ + return ( mm_support() & 0x1 ); +} +#endif + +/* Helper functions for the instruction macros that follow... + (note that memory-to-register, m2r, instructions are nearly + as efficient as register-to-register, r2r, instructions; + however, memory-to-memory instructions are really simulated + as a convenience, and are only 1/3 as efficient) +*/ +#ifdef MMX_TRACE + +/* Include the stuff for printing a trace to stderr... +*/ + +#define mmx_i2r(op, imm, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace.uq = (imm); \ + printf(#op "_i2r(" #imm "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (imm)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_m2r(op, mem, reg) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mem); \ + printf(#op "_m2r(" #mem "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (mem)); \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#reg "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_r2m(op, reg, mem) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #reg ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#op "_r2m(" #reg "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + mmx_trace = (mem); \ + printf(#mem "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=y" (mem) \ + : /* nothing */ ); \ + mmx_trace = (mem); \ + printf(#mem "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_r2r(op, regs, regd) \ + { \ + mmx_t mmx_trace; \ + __asm__ __volatile__ ("movq %%" #regs ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#op "_r2r(" #regs "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#regd "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd); \ + __asm__ __volatile__ ("movq %%" #regd ", %0" \ + : "=y" (mmx_trace) \ + : /* nothing */ ); \ + printf(#regd "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#define mmx_m2m(op, mems, memd) \ + { \ + mmx_t mmx_trace; \ + mmx_trace = (mems); \ + printf(#op "_m2m(" #mems "=0x%08x%08x, ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + mmx_trace = (memd); \ + printf(#memd "=0x%08x%08x) => ", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (memd) \ + : "y" (mems)); \ + mmx_trace = (memd); \ + printf(#memd "=0x%08x%08x\n", \ + mmx_trace.d[1], mmx_trace.d[0]); \ + } + +#else + +/* These macros are a lot simpler without the tracing... +*/ + +#define mmx_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "y" (imm) ) + +#define mmx_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define mmx_m2m(op, mems, memd) \ + __asm__ __volatile__ ("movq %0, %%mm0\n\t" \ + #op " %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (memd) \ + : "y" (mems)) + +#endif + + +/* 1x64 MOVe Quadword + (this is both a load and a store... + in fact, it is the only way to store) +*/ +#define movq_m2r(var, reg) mmx_m2r(movq, var, reg) +#define movq_r2m(reg, var) mmx_r2m(movq, reg, var) +#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd) +#define movq(vars, vard) \ + __asm__ __volatile__ ("movq %1, %%mm0\n\t" \ + "movq %%mm0, %0" \ + : "=y" (vard) \ + : "y" (vars)) + + +/* 1x32 MOVe Doubleword + (like movq, this is both load and store... + but is most useful for moving things between + mmx registers and ordinary registers) +*/ +#define movd_m2r(var, reg) mmx_m2r(movd, var, reg) +#define movd_r2m(reg, var) mmx_r2m(movd, reg, var) +#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd) +#define movd(vars, vard) \ + __asm__ __volatile__ ("movd %1, %%mm0\n\t" \ + "movd %%mm0, %0" \ + : "=y" (vard) \ + : "y" (vars)) + + +/* 2x32, 4x16, and 8x8 Parallel ADDs +*/ +#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg) +#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd) +#define paddd(vars, vard) mmx_m2m(paddd, vars, vard) + +#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg) +#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd) +#define paddw(vars, vard) mmx_m2m(paddw, vars, vard) + +#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg) +#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd) +#define paddb(vars, vard) mmx_m2m(paddb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic +*/ +#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg) +#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd) +#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard) + +#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg) +#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd) +#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard) + + +/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic +*/ +#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg) +#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd) +#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard) + +#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg) +#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd) +#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel SUBs +*/ +#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg) +#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd) +#define psubd(vars, vard) mmx_m2m(psubd, vars, vard) + +#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg) +#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd) +#define psubw(vars, vard) mmx_m2m(psubw, vars, vard) + +#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg) +#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd) +#define psubb(vars, vard) mmx_m2m(psubb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic +*/ +#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg) +#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd) +#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard) + +#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg) +#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd) +#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard) + + +/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic +*/ +#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg) +#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd) +#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard) + +#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg) +#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd) +#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard) + + +/* 4x16 Parallel MULs giving Low 4x16 portions of results +*/ +#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg) +#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd) +#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard) + + +/* 4x16 Parallel MULs giving High 4x16 portions of results +*/ +#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg) +#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd) +#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard) + + +/* 4x16->2x32 Parallel Mul-ADD + (muls like pmullw, then adds adjacent 16-bit fields + in the multiply result to make the final 2x32 result) +*/ +#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg) +#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd) +#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard) + + +/* 1x64 bitwise AND +*/ +#ifdef BROKEN_PAND +#define pand_m2r(var, reg) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, reg); \ + mmx_m2r(pandn, var, reg); \ + } +#define pand_r2r(regs, regd) \ + { \ + mmx_m2r(pandn, (mmx_t) -1LL, regd); \ + mmx_r2r(pandn, regs, regd) \ + } +#define pand(vars, vard) \ + { \ + movq_m2r(vard, mm0); \ + mmx_m2r(pandn, (mmx_t) -1LL, mm0); \ + mmx_m2r(pandn, vars, mm0); \ + movq_r2m(mm0, vard); \ + } +#else +#define pand_m2r(var, reg) mmx_m2r(pand, var, reg) +#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd) +#define pand(vars, vard) mmx_m2m(pand, vars, vard) +#endif + + +/* 1x64 bitwise AND with Not the destination +*/ +#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg) +#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd) +#define pandn(vars, vard) mmx_m2m(pandn, vars, vard) + + +/* 1x64 bitwise OR +*/ +#define por_m2r(var, reg) mmx_m2r(por, var, reg) +#define por_r2r(regs, regd) mmx_r2r(por, regs, regd) +#define por(vars, vard) mmx_m2m(por, vars, vard) + + +/* 1x64 bitwise eXclusive OR +*/ +#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg) +#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd) +#define pxor(vars, vard) mmx_m2m(pxor, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality + (resulting fields are either 0 or -1) +*/ +#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd) +#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard) + +#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd) +#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard) + +#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd) +#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard) + + +/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than + (resulting fields are either 0 or -1) +*/ +#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd) +#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard) + +#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd) +#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard) + +#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd) +#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical +*/ +#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg) +#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg) +#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd) +#define psllq(vars, vard) mmx_m2m(psllq, vars, vard) + +#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg) +#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg) +#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd) +#define pslld(vars, vard) mmx_m2m(pslld, vars, vard) + +#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg) +#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg) +#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd) +#define psllw(vars, vard) mmx_m2m(psllw, vars, vard) + + +/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical +*/ +#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg) +#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg) +#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd) +#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard) + +#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg) +#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg) +#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd) +#define psrld(vars, vard) mmx_m2m(psrld, vars, vard) + +#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg) +#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg) +#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd) +#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard) + + +/* 2x32 and 4x16 Parallel Shift Right Arithmetic +*/ +#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg) +#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg) +#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd) +#define psrad(vars, vard) mmx_m2m(psrad, vars, vard) + +#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg) +#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg) +#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd) +#define psraw(vars, vard) mmx_m2m(psraw, vars, vard) + + +/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate + (packs source and dest fields into dest in that order) +*/ +#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg) +#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd) +#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard) + +#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg) +#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd) +#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard) + + +/* 4x16->8x8 PACK and Unsigned Saturate + (packs source and dest fields into dest in that order) +*/ +#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg) +#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd) +#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low + (interleaves low half of dest with low half of source + as padding in each result field) +*/ +#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg) +#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd) +#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard) + +#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg) +#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd) +#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard) + +#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg) +#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd) +#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard) + + +/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High + (interleaves high half of dest with high half of source + as padding in each result field) +*/ +#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg) +#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd) +#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard) + +#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg) +#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd) +#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard) + +#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg) +#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd) +#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard) + + +/* Empty MMx State + (used to clean-up when going from mmx to float use + of the registers that are shared by both; note that + there is no float-to-mmx operation needed, because + only the float tag word info is corruptible) +*/ +#ifdef MMX_TRACE + +#define emms() \ + { \ + printf("emms()\n"); \ + __asm__ __volatile__ ("emms"); \ + } + +#else + +#define emms() __asm__ __volatile__ ("emms") + +#endif + +#endif + diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxevents.c b/3rdparty/SDL/src/video/nanox/SDL_nxevents.c new file mode 100644 index 0000000..788c794 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxevents.c @@ -0,0 +1,382 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_keysym.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nxevents_c.h" +#include "SDL_nximage_c.h" + +// The translation tables from a nanox keysym to a SDL keysym +static SDLKey NX_NONASCII_keymap [MWKEY_LAST + 1] ; + +void NX_InitOSKeymap (_THIS) +{ + int i ; + + Dprintf ("enter NX_InitOSKeymap\n") ; + + // Map the nanox scancodes to SDL keysyms + for (i = 0; i < SDL_arraysize (NX_NONASCII_keymap); ++ i) + NX_NONASCII_keymap [i] = SDLK_UNKNOWN ; + + NX_NONASCII_keymap [MWKEY_LEFT & 0xFF] = SDLK_LEFT ; + NX_NONASCII_keymap [MWKEY_RIGHT & 0xFF] = SDLK_RIGHT ; + NX_NONASCII_keymap [MWKEY_UP & 0xFF] = SDLK_UP ; + NX_NONASCII_keymap [MWKEY_DOWN & 0xFF] = SDLK_DOWN ; + NX_NONASCII_keymap [MWKEY_INSERT & 0xFF] = SDLK_INSERT ; + NX_NONASCII_keymap [MWKEY_DELETE & 0xFF] = SDLK_DELETE ; + NX_NONASCII_keymap [MWKEY_HOME & 0xFF] = SDLK_HOME ; + NX_NONASCII_keymap [MWKEY_END & 0xFF] = SDLK_END ; + NX_NONASCII_keymap [MWKEY_PAGEUP & 0xFF] = SDLK_PAGEUP ; + NX_NONASCII_keymap [MWKEY_PAGEDOWN & 0xFF] = SDLK_PAGEDOWN ; + + NX_NONASCII_keymap [MWKEY_KP0 & 0xFF] = SDLK_KP0 ; + NX_NONASCII_keymap [MWKEY_KP1 & 0xFF] = SDLK_KP1 ; + NX_NONASCII_keymap [MWKEY_KP2 & 0xFF] = SDLK_KP2 ; + NX_NONASCII_keymap [MWKEY_KP3 & 0xFF] = SDLK_KP3 ; + NX_NONASCII_keymap [MWKEY_KP4 & 0xFF] = SDLK_KP4 ; + NX_NONASCII_keymap [MWKEY_KP5 & 0xFF] = SDLK_KP5 ; + NX_NONASCII_keymap [MWKEY_KP6 & 0xFF] = SDLK_KP6 ; + NX_NONASCII_keymap [MWKEY_KP7 & 0xFF] = SDLK_KP7 ; + NX_NONASCII_keymap [MWKEY_KP8 & 0xFF] = SDLK_KP8 ; + NX_NONASCII_keymap [MWKEY_KP9 & 0xFF] = SDLK_KP9 ; + NX_NONASCII_keymap [MWKEY_KP_PERIOD & 0xFF] = SDLK_KP_PERIOD ; + NX_NONASCII_keymap [MWKEY_KP_DIVIDE & 0xFF] = SDLK_KP_DIVIDE ; + NX_NONASCII_keymap [MWKEY_KP_MULTIPLY & 0xFF] = SDLK_KP_MULTIPLY ; + NX_NONASCII_keymap [MWKEY_KP_MINUS & 0xFF] = SDLK_KP_MINUS ; + NX_NONASCII_keymap [MWKEY_KP_PLUS & 0xFF] = SDLK_KP_PLUS ; + NX_NONASCII_keymap [MWKEY_KP_ENTER & 0xFF] = SDLK_KP_ENTER ; + NX_NONASCII_keymap [MWKEY_KP_EQUALS & 0xFF] = SDLK_KP_EQUALS ; + + NX_NONASCII_keymap [MWKEY_F1 & 0xFF] = SDLK_F1 ; + NX_NONASCII_keymap [MWKEY_F2 & 0xFF] = SDLK_F2 ; + NX_NONASCII_keymap [MWKEY_F3 & 0xFF] = SDLK_F3 ; + NX_NONASCII_keymap [MWKEY_F4 & 0xFF] = SDLK_F4 ; + NX_NONASCII_keymap [MWKEY_F5 & 0xFF] = SDLK_F5 ; + NX_NONASCII_keymap [MWKEY_F6 & 0xFF] = SDLK_F6 ; + NX_NONASCII_keymap [MWKEY_F7 & 0xFF] = SDLK_F7 ; + NX_NONASCII_keymap [MWKEY_F8 & 0xFF] = SDLK_F8 ; + NX_NONASCII_keymap [MWKEY_F9 & 0xFF] = SDLK_F9 ; + NX_NONASCII_keymap [MWKEY_F10 & 0xFF] = SDLK_F10 ; + NX_NONASCII_keymap [MWKEY_F11 & 0xFF] = SDLK_F11 ; + NX_NONASCII_keymap [MWKEY_F12 & 0xFF] = SDLK_F12 ; + + NX_NONASCII_keymap [MWKEY_NUMLOCK & 0xFF] = SDLK_NUMLOCK ; + NX_NONASCII_keymap [MWKEY_CAPSLOCK & 0xFF] = SDLK_CAPSLOCK ; + NX_NONASCII_keymap [MWKEY_SCROLLOCK & 0xFF] = SDLK_SCROLLOCK ; + NX_NONASCII_keymap [MWKEY_LSHIFT & 0xFF] = SDLK_LSHIFT ; + NX_NONASCII_keymap [MWKEY_RSHIFT & 0xFF] = SDLK_RSHIFT ; + NX_NONASCII_keymap [MWKEY_LCTRL & 0xFF] = SDLK_LCTRL ; + NX_NONASCII_keymap [MWKEY_RCTRL & 0xFF] = SDLK_RCTRL ; + NX_NONASCII_keymap [MWKEY_LALT & 0xFF] = SDLK_LALT ; + NX_NONASCII_keymap [MWKEY_RALT & 0xFF] = SDLK_RALT ; + NX_NONASCII_keymap [MWKEY_LMETA & 0xFF] = SDLK_LMETA ; + NX_NONASCII_keymap [MWKEY_RMETA & 0xFF] = SDLK_RMETA ; + NX_NONASCII_keymap [MWKEY_ALTGR & 0xFF] = SDLK_MODE ; + + NX_NONASCII_keymap [MWKEY_PRINT & 0xFF] = SDLK_PRINT ; + NX_NONASCII_keymap [MWKEY_SYSREQ & 0xFF] = SDLK_SYSREQ ; + NX_NONASCII_keymap [MWKEY_PAUSE & 0xFF] = SDLK_PAUSE ; + NX_NONASCII_keymap [MWKEY_BREAK & 0xFF] = SDLK_BREAK ; + NX_NONASCII_keymap [MWKEY_MENU & 0xFF] = SDLK_MENU ; + + Dprintf ("leave NX_InitOSKeymap\n") ; +} + +SDL_keysym * NX_TranslateKey (GR_EVENT_KEYSTROKE * keystroke, SDL_keysym * keysym) +{ + GR_KEY ch = keystroke -> ch ; + + Dprintf ("enter NX_TranslateKey\n") ; + + keysym -> scancode = keystroke -> scancode ; + keysym -> sym = SDLK_UNKNOWN ; + + if (ch & MWKEY_NONASCII_MASK) { + keysym -> sym = NX_NONASCII_keymap [ch & 0xFF] ; + } else { + keysym -> sym = ch & 0x7F ; + } + + keysym -> mod = KMOD_NONE ; + +#if 1 // Retrieve more mode information + { + GR_KEYMOD mod = keystroke -> modifiers ; + + if (mod & MWKMOD_LSHIFT) + keysym -> mod |= KMOD_LSHIFT ; + if (mod & MWKMOD_RSHIFT) + keysym -> mod |= KMOD_RSHIFT ; + if (mod & MWKMOD_LCTRL) + keysym -> mod |= KMOD_LCTRL ; + if (mod & MWKMOD_RCTRL) + keysym -> mod |= KMOD_RCTRL ; + if (mod & MWKMOD_LALT) + keysym -> mod |= KMOD_LALT ; + if (mod & MWKMOD_RALT) + keysym -> mod |= KMOD_RALT ; + if (mod & MWKMOD_LMETA) + keysym -> mod |= KMOD_LMETA ; + if (mod & MWKMOD_RMETA) + keysym -> mod |= KMOD_RMETA ; + if (mod & MWKMOD_NUM) + keysym -> mod |= KMOD_NUM ; + if (mod & MWKMOD_CAPS) + keysym -> mod |= KMOD_CAPS ; + if (mod & MWKMOD_ALTGR) + keysym -> mod |= KMOD_MODE ; + } +#endif + + keysym -> unicode = ch ; + + Dprintf ("leave NX_TranslateKey\n") ; + return keysym ; +} + +static int check_boundary (_THIS, int x, int y) +{ + if (x < OffsetX || y < OffsetY || x > OffsetX + this -> screen -> w || + y > OffsetY + this -> screen -> h) + return 0 ; + + return 1 ; +} + +void NX_PumpEvents (_THIS) +{ + GR_EVENT event ; + static GR_BUTTON last_button_down = 0 ; + + GrCheckNextEvent (& event) ; + while (event.type != GR_EVENT_TYPE_NONE) { + + // dispatch event + switch (event.type) { + case GR_EVENT_TYPE_MOUSE_ENTER : + { + Dprintf ("mouse enter\n") ; + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_MOUSE_EXIT : + { + Dprintf ("mouse exit\n") ; + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_FOCUS_IN : + { + Dprintf ("focus in\n") ; + SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_FOCUS_OUT : + { + Dprintf ("focus out\n") ; + SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS) ; + break ; + } + + case GR_EVENT_TYPE_MOUSE_MOTION : + { + Dprintf ("mouse motion\n") ; + + if (SDL_VideoSurface) { + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseMotion (0, 0, event.button.x - OffsetX, + event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseMotion (0, 0, event.button.x, event.button.y) ; + } + } + break ; + } + + case GR_EVENT_TYPE_BUTTON_DOWN : + { + int button = event.button.buttons ; + + Dprintf ("button down\n") ; + + switch (button) { + case MWBUTTON_L : + button = 1 ; + break ; + case MWBUTTON_M : + button = 2 ; + break ; + case MWBUTTON_R : + button = 3 ; + break ; + default : + button = 0 ; + } + last_button_down = button ; + + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseButton (SDL_PRESSED, button, + event.button.x - OffsetX, event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseButton (SDL_PRESSED, button, + event.button.x, event.button.y) ; + } + break ; + } + + // do not konw which button is released + case GR_EVENT_TYPE_BUTTON_UP : + { + Dprintf ("button up\n") ; + + if (currently_fullscreen) { + if (check_boundary (this, event.button.x, event.button.y)) { + SDL_PrivateMouseButton (SDL_RELEASED, last_button_down, + event.button.x - OffsetX, event.button.y - OffsetY) ; + } + } else { + SDL_PrivateMouseButton (SDL_RELEASED, last_button_down, + event.button.x, event.button.y) ; + } + last_button_down = 0 ; + break ; + } + + case GR_EVENT_TYPE_KEY_DOWN : + { + SDL_keysym keysym ; + + Dprintf ("key down\n") ; + SDL_PrivateKeyboard (SDL_PRESSED, + NX_TranslateKey (& event.keystroke, & keysym)) ; + break ; + } + + case GR_EVENT_TYPE_KEY_UP : + { + SDL_keysym keysym ; + + Dprintf ("key up\n") ; + SDL_PrivateKeyboard (SDL_RELEASED, + NX_TranslateKey (& event.keystroke, & keysym)) ; + break ; + } + + case GR_EVENT_TYPE_CLOSE_REQ : + { + Dprintf ("close require\n") ; + SDL_PrivateQuit () ; + break ; + } + + case GR_EVENT_TYPE_EXPOSURE : + { + Dprintf ("event_type_exposure\n") ; + if (SDL_VideoSurface) { + NX_RefreshDisplay (this) ;//, & event.exposure) ; + } + break ; + } + + case GR_EVENT_TYPE_UPDATE : + { + switch (event.update.utype) { + case GR_UPDATE_MAP : + { + Dprintf ("GR_UPDATE_MAP\n") ; + // If we're not active, make ourselves active + if (!(SDL_GetAppState () & SDL_APPACTIVE)) { + // Send an internal activate event + SDL_PrivateAppActive (1, SDL_APPACTIVE) ; + } + if (SDL_VideoSurface) { + NX_RefreshDisplay (this) ; + } + break ; + } + + case GR_UPDATE_UNMAP : + case GR_UPDATE_UNMAPTEMP : + { + Dprintf ("GR_UPDATE_UNMAP or GR_UPDATE_UNMAPTEMP\n") ; + // If we're active, make ourselves inactive + if (SDL_GetAppState () & SDL_APPACTIVE) { + // Send an internal deactivate event + SDL_PrivateAppActive (0, SDL_APPACTIVE | SDL_APPINPUTFOCUS) ; + } + break ; + } + + case GR_UPDATE_SIZE : + { + Dprintf ("GR_UPDATE_SIZE\n") ; + SDL_PrivateResize (event.update.width, event.update.height) ; + break ; + } + + case GR_UPDATE_MOVE : + case GR_UPDATE_REPARENT : + { + Dprintf ("GR_UPDATE_MOVE or GR_UPDATE_REPARENT\n") ; +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + /* Get current window position and fb pointer*/ + if (currently_fullscreen) + GrGetWindowFBInfo(FSwindow, &fbinfo); + else + GrGetWindowFBInfo(SDL_Window, &fbinfo); + } +#endif + break ; + } + + default : + Dprintf ("unknown GR_EVENT_TYPE_UPDATE\n") ; + break ; + } + break ; + } + + default : + { + Dprintf ("pump event default\n") ; + } + } + + GrCheckNextEvent (& event) ; + } +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h new file mode 100644 index 0000000..b3b4f97 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxevents_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +// Functions to be exported +extern void NX_InitOSKeymap (_THIS) ; +extern void NX_PumpEvents (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nximage.c b/3rdparty/SDL/src/video/nanox/SDL_nximage.c new file mode 100644 index 0000000..23d3157 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nximage.c @@ -0,0 +1,230 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nximage_c.h" + +void NX_NormalUpdate (_THIS, int numrects, SDL_Rect * rects) +{ + int i, j, xinc, yinc, destinc, rowinc ; + int x, y, w, h ; + unsigned char * src = NULL, * dest = NULL ; + + Dprintf ("enter NX_NormalUpdate\n") ; + + /* These are the values for the incoming image */ + xinc = this -> screen -> format -> BytesPerPixel ; + yinc = this -> screen -> pitch ; + + for (i = 0; i < numrects; ++ i) { + x = rects [i].x, y = rects [i].y ; + w = rects [i].w, h = rects [i].h ; + src = SDL_Image + y * yinc + x * xinc ; +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + if (currently_fullscreen) + dest = fbinfo.winpixels + (((y+OffsetY) * fbinfo.pitch) + + ((x+OffsetX) * fbinfo.bytespp)); + else + dest = fbinfo.winpixels + ((y * fbinfo.pitch) + (x * fbinfo.bytespp)); + destinc = fbinfo.pitch; + } + else +#endif + { + dest = Image_buff ; + destinc = w * xinc ; + } + rowinc = w * xinc; + + // apply GammaRamp table + if ((pixel_type == MWPF_TRUECOLOR0888 || pixel_type == MWPF_TRUECOLOR888) + && GammaRamp_R && GammaRamp_G && GammaRamp_B) { + Uint8 * ptrsrc ; + Uint8 * ptrdst ; + int k ; + + for (j = h; j > 0; -- j, src += yinc, dest += destinc) { + ptrsrc = src ; + ptrdst = dest ; + for (k = w; k > 0; -- k) { + *ptrdst++ = GammaRamp_B [*ptrsrc++] >> 8; + *ptrdst++ = GammaRamp_G [*ptrsrc++] >> 8; + *ptrdst++ = GammaRamp_R [*ptrsrc++] >> 8; + *ptrdst++ = 0; + ++ptrsrc; + } + } + } +#if 1 /* This is needed for microwindows 0.90 or older */ + else if (pixel_type == MWPF_TRUECOLOR0888 || pixel_type == MWPF_TRUECOLOR888) { + Uint8 * ptrsrc ; + Uint8 * ptrdst ; + int k ; + + for (j = h; j > 0; -- j, src += yinc, dest += destinc) { + ptrsrc = src ; + ptrdst = dest ; + for (k = w; k > 0; -- k) { + *ptrdst++ = *ptrsrc++; + *ptrdst++ = *ptrsrc++; + *ptrdst++ = *ptrsrc++; + *ptrdst++ = 0; + ++ptrsrc; + } + } + } +#endif + else + { + for (j = h; j > 0; -- j, src += yinc, dest += destinc) + SDL_memcpy (dest, src, rowinc) ; + } + if (!Clientfb) { + if (currently_fullscreen) { + GrArea (FSwindow, SDL_GC, x + OffsetX, y + OffsetY, w, h, Image_buff, + pixel_type) ; + } else { + GrArea (SDL_Window, SDL_GC, x, y, w, h, Image_buff, pixel_type) ; + } + } + } + GrFlush(); + + Dprintf ("leave NX_NormalUpdate\n") ; +} + +int NX_SetupImage (_THIS, SDL_Surface * screen) +{ + int size = screen -> h * screen -> pitch ; + + Dprintf ("enter NX_SetupImage\n") ; + + screen -> pixels = (void *) SDL_malloc (size) ; + + if (!Clientfb) { + Image_buff = (unsigned char *) SDL_malloc (size) ; + if (screen -> pixels == NULL || Image_buff == NULL) { + SDL_free (screen -> pixels) ; + SDL_free (Image_buff) ; + SDL_OutOfMemory () ; + return -1 ; + } + } + + SDL_Image = (unsigned char *) screen -> pixels ; + + this -> UpdateRects = NX_NormalUpdate ; + + Dprintf ("leave NX_SetupImage\n") ; + return 0 ; +} + +void NX_DestroyImage (_THIS, SDL_Surface * screen) +{ + Dprintf ("enter NX_DestroyImage\n") ; + + if (SDL_Image) SDL_free (SDL_Image) ; + if (Image_buff) SDL_free (Image_buff) ; + if (screen) screen -> pixels = NULL ; + + Dprintf ("leave NX_DestroyImage\n") ; +} + +int NX_ResizeImage (_THIS, SDL_Surface * screen, Uint32 flags) +{ + int retval ; + GR_SCREEN_INFO si ; + + Dprintf ("enter NX_ResizeImage\n") ; + + NX_DestroyImage (this, screen) ; + retval = NX_SetupImage (this, screen) ; + + GrGetScreenInfo (& si) ; + OffsetX = (si.cols - screen -> w) / 2 ; + OffsetY = (si.rows - screen -> h) / 2 ; + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + /* Get current window position and fb pointer*/ + if (currently_fullscreen) + GrGetWindowFBInfo(FSwindow, &fbinfo); + else + GrGetWindowFBInfo(SDL_Window, &fbinfo); + } +#endif + Dprintf ("leave NX_ResizeImage\n") ; + return retval ; +} + +void NX_RefreshDisplay (_THIS) +{ + Dprintf ("enter NX_RefreshDisplay\n") ; + + // Don't refresh a display that doesn't have an image (like GL) + if (! SDL_Image) { + return; + } + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) { + int j; + char *src, *dest = NULL; + int xinc, yinc, rowinc; + + GrGetWindowFBInfo(SDL_Window, &fbinfo); + + xinc = this -> screen -> format -> BytesPerPixel ; + yinc = this -> screen -> pitch ; + + src = SDL_Image; + if (currently_fullscreen) + dest = fbinfo.winpixels + ((OffsetY * fbinfo.pitch) + + (OffsetX * fbinfo.bytespp)); + else + dest = fbinfo.winpixels; + rowinc = xinc * this -> screen -> w; + + for (j = this -> screen -> h; j > 0; -- j, src += yinc, dest += fbinfo.pitch) + SDL_memcpy (dest, src, rowinc) ; + } + else +#endif + { + if (currently_fullscreen) { + GrArea (FSwindow, SDL_GC, OffsetX, OffsetY, this -> screen -> w, + this -> screen -> h, SDL_Image, pixel_type) ; + } else { + GrArea (SDL_Window, SDL_GC, 0, 0, this -> screen -> w, + this -> screen -> h, SDL_Image, pixel_type) ; + } + } + GrFlush(); + + Dprintf ("leave NX_RefreshDisplay\n") ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h b/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h new file mode 100644 index 0000000..0bf29e5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nximage_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +extern int NX_SetupImage (_THIS, SDL_Surface * screen) ; +extern void NX_DestroyImage (_THIS, SDL_Surface * screen) ; +extern int NX_ResizeImage (_THIS, SDL_Surface * screen, Uint32 flags) ; + +extern void NX_NormalUpdate (_THIS, int numrects, SDL_Rect * rects) ; +extern void NX_RefreshDisplay (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c b/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c new file mode 100644 index 0000000..bcf74e5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmodes.c @@ -0,0 +1,84 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_stdinc.h" +#include "SDL_nxmodes_c.h" + +SDL_Rect ** NX_ListModes (_THIS, SDL_PixelFormat * format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + return SDL_modelist ; + + if (SDL_Visual.bpp == format -> BitsPerPixel) { + return ((SDL_Rect **) -1) ; + } else { + return ((SDL_Rect **) 0) ; + } +} + +void NX_FreeVideoModes (_THIS) +{ + int i ; + + if (SDL_modelist) { + for (i = 0; SDL_modelist [i]; ++ i) { + SDL_free (SDL_modelist [i]) ; + } + SDL_free (SDL_modelist) ; + SDL_modelist = NULL; + } +} + +int NX_EnterFullScreen (_THIS) +{ + if (! currently_fullscreen) { + GR_SCREEN_INFO si ; + + GrGetScreenInfo (& si) ; + GrResizeWindow (FSwindow, si.cols, si.rows) ; + GrUnmapWindow (SDL_Window) ; + GrMapWindow (FSwindow) ; + GrRaiseWindow (FSwindow) ; + GrSetFocus (FSwindow) ; + currently_fullscreen = 1 ; + } + + return 1 ; +} + +int NX_LeaveFullScreen (_THIS) +{ + if (currently_fullscreen) { + GrUnmapWindow (FSwindow) ; + GrMapWindow (SDL_Window) ; + GrRaiseWindow (SDL_Window) ; + GrSetFocus (SDL_Window) ; + currently_fullscreen = 0 ; + } + + return 0 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h new file mode 100644 index 0000000..fe2e655 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmodes_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" +#include <SDL.h> + +extern SDL_Rect ** NX_ListModes (_THIS, SDL_PixelFormat * format, Uint32 flags) ; +extern void NX_FreeVideoModes (_THIS) ; +extern int NX_EnterFullScreen (_THIS) ; +extern int NX_LeaveFullScreen (_THIS) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c b/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c new file mode 100644 index 0000000..9c8f382 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmouse.c @@ -0,0 +1,79 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "../../events/SDL_events_c.h" + +#include "SDL_nxmouse_c.h" + +// The implementation dependent data for the window manager cursor +struct WMcursor { + int unused ; +} ; + +WMcursor * NX_CreateWMCursor (_THIS, + Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor * cursor ; + + Dprintf ("enter NX_CreateWMCursor\n") ; + + cursor = (WMcursor *) SDL_malloc (sizeof (WMcursor)) ; + if (cursor == NULL) { + SDL_OutOfMemory () ; + return NULL ; + } + + Dprintf ("leave NX_CreateWMCursor\n") ; + return cursor ; +} + +void NX_FreeWMCursor (_THIS, WMcursor * cursor) +{ + Dprintf ("NX_FreeWMCursor\n") ; + SDL_free (cursor) ; + return ; +} + +void NX_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + GR_WINDOW_INFO info ; + + Dprintf ("enter NX_WarpWMCursor\n") ; + SDL_Lock_EventThread () ; + + GrGetWindowInfo (SDL_Window, & info) ; + GrMoveCursor (info.x + x, info.y + y) ; + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_WarpWMCursor\n") ; +} + +int NX_ShowWMCursor (_THIS, WMcursor * cursor) +{ + Dprintf ("NX_ShowWMCursor\n") ; + return 1 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h new file mode 100644 index 0000000..d7fedb5 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxmouse_c.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +extern WMcursor * NX_CreateWMCursor (_THIS, Uint8 * data, Uint8 * mask, int w, int h, int hot_x, int hot_y) ; +void NX_FreeWMCursor (_THIS, WMcursor * cursor) ; +extern void NX_WarpWMCursor (_THIS, Uint16 x, Uint16 y) ; +extern int NX_ShowWMCursor (_THIS, WMcursor * cursor) ; diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c new file mode 100644 index 0000000..b188e09 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.c @@ -0,0 +1,544 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + Copyright (C) 2002 Greg Haerr <greg@censoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_thread.h" +#include "SDL_video.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#define MWINCLUDECOLORS +#include "SDL_nxvideo.h" +#include "SDL_nxmodes_c.h" +#include "SDL_nxwm_c.h" +#include "SDL_nxmouse_c.h" +#include "SDL_nximage_c.h" +#include "SDL_nxevents_c.h" + +// Initialization/Query functions +static int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) ; +static SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags) ; +static int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) ; +static void NX_VideoQuit (_THIS) ; +static void NX_DestroyWindow (_THIS, SDL_Surface * screen) ; +static int NX_ToggleFullScreen (_THIS, int on) ; +static void NX_UpdateMouse (_THIS) ; +static int NX_SetGammaRamp (_THIS, Uint16 * ramp) ; +static int NX_GetGammaRamp (_THIS, Uint16 * ramp) ; + +// Microwin driver bootstrap functions +static int NX_Available () +{ + Dprintf ("enter NX_Available\n") ; + + if (GrOpen () < 0) return 0 ; + GrClose () ; + + Dprintf ("leave NX_Available\n") ; + return 1 ; +} + +static void NX_DeleteDevice (SDL_VideoDevice * device) +{ + Dprintf ("enter NX_DeleteDevice\n") ; + + if (device) { + if (device -> hidden) SDL_free (device -> hidden) ; + if (device -> gl_data) SDL_free (device -> gl_data) ; + SDL_free (device) ; + } + + Dprintf ("leave NX_DeleteDevice\n") ; +} + +static SDL_VideoDevice * NX_CreateDevice (int devindex) +{ + SDL_VideoDevice * device ; + + Dprintf ("enter NX_CreateDevice\n") ; + + // Initialize all variables that we clean on shutdown + device = (SDL_VideoDevice *) SDL_malloc (sizeof (SDL_VideoDevice)) ; + if (device) { + SDL_memset (device, 0, (sizeof * device)) ; + device -> hidden = (struct SDL_PrivateVideoData *) + SDL_malloc ((sizeof * device -> hidden)) ; + device -> gl_data = NULL ; + } + if ((device == NULL) || (device -> hidden == NULL)) { + SDL_OutOfMemory () ; + NX_DeleteDevice (device) ; + return 0 ; + } + SDL_memset (device -> hidden, 0, (sizeof * device -> hidden)) ; + + // Set the function pointers + device -> VideoInit = NX_VideoInit ; + device -> ListModes = NX_ListModes ; + device -> SetVideoMode = NX_SetVideoMode ; + device -> ToggleFullScreen = NX_ToggleFullScreen ; + device -> UpdateMouse = NX_UpdateMouse ; + device -> CreateYUVOverlay = NULL ; + device -> SetColors = NX_SetColors ; + device -> UpdateRects = NULL ; + device -> VideoQuit = NX_VideoQuit; + device -> AllocHWSurface = NULL ; + device -> CheckHWBlit = NULL ; + device -> FillHWRect = NULL ; + device -> SetHWColorKey = NULL ; + device -> SetHWAlpha = NULL ; + device -> LockHWSurface = NULL ; + device -> UnlockHWSurface = NULL ; + device -> FlipHWSurface = NULL ; + device -> FreeHWSurface = NULL ; + device -> SetGamma = NULL ; + device -> GetGamma = NULL ; + device -> SetGammaRamp = NX_SetGammaRamp ; + device -> GetGammaRamp = NX_GetGammaRamp ; + +#if SDL_VIDEO_OPENGL + device -> GL_LoadLibrary = NULL ; + device -> GL_GetProcAddress = NULL ; + device -> GL_GetAttribute = NULL ; + device -> GL_MakeCurrent = NULL ; + device -> GL_SwapBuffers = NULL ; +#endif + + device -> SetIcon = NULL ; + device -> SetCaption = NX_SetCaption; + device -> IconifyWindow = NULL ; + device -> GrabInput = NULL ; + device -> GetWMInfo = NX_GetWMInfo ; + device -> FreeWMCursor = NX_FreeWMCursor ; + device -> CreateWMCursor = NX_CreateWMCursor ; + device -> ShowWMCursor = NX_ShowWMCursor ; + device -> WarpWMCursor = NX_WarpWMCursor ; + device -> CheckMouseMode = NULL ; + device -> InitOSKeymap = NX_InitOSKeymap ; + device -> PumpEvents = NX_PumpEvents ; + + device -> free = NX_DeleteDevice ; + + Dprintf ("leave NX_CreateDevice\n") ; + return device ; +} + +VideoBootStrap NX_bootstrap = { + "nanox", "nanox", NX_Available, NX_CreateDevice +} ; + +static void create_aux_windows (_THIS) +{ + GR_WM_PROPERTIES props ; + + Dprintf ("enter create_aux_windows\n") ; + + // Don't create any extra windows if we are being managed + if (SDL_windowid) { + FSwindow = 0 ; + return ; + } + + if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (FSwindow) ; + } + + FSwindow = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, 1, 1, 0, BLACK, BLACK) ; + props.flags = GR_WM_FLAGS_PROPS ; + props.props = GR_WM_PROPS_NODECORATE ; + GrSetWMProperties (FSwindow, & props) ; + + GrSelectEvents (FSwindow, (GR_EVENT_MASK_EXPOSURE | + GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | + GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | + GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | + GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | + GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | + GR_EVENT_MASK_CLOSE_REQ)) ; + + Dprintf ("leave create_aux_windows\n") ; +} + +int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) +{ + GR_SCREEN_INFO si ; + + Dprintf ("enter NX_VideoInit\n") ; + + if (GrOpen () < 0) { + SDL_SetError ("GrOpen() fail") ; + return -1 ; + } + + // use share memory to speed up +#ifdef NANOX_SHARE_MEMORY + GrReqShmCmds (0xFFFF); +#endif + + SDL_Window = 0 ; + FSwindow = 0 ; + + GammaRamp_R = NULL ; + GammaRamp_G = NULL ; + GammaRamp_B = NULL ; + + GrGetScreenInfo (& si) ; + SDL_Visual.bpp = si.bpp ; + + /* Determine the current screen size */ + this->info.current_w = si.cols ; + this->info.current_h = si.rows ; + + // GetVideoMode + SDL_modelist = (SDL_Rect **) SDL_malloc (sizeof (SDL_Rect *) * 2) ; + if (SDL_modelist) { + SDL_modelist [0] = (SDL_Rect *) SDL_malloc (sizeof(SDL_Rect)) ; + if (SDL_modelist [0]) { + SDL_modelist [0] -> x = 0 ; + SDL_modelist [0] -> y = 0 ; + SDL_modelist [0] -> w = si.cols ; + SDL_modelist [0] -> h = si.rows ; + } + SDL_modelist [1] = NULL ; + } + + pixel_type = si.pixtype; + SDL_Visual.red_mask = si.rmask; + SDL_Visual.green_mask = si.gmask; + SDL_Visual.blue_mask = si.bmask; + + vformat -> BitsPerPixel = SDL_Visual.bpp ; + if (vformat -> BitsPerPixel > 8) { + vformat -> Rmask = SDL_Visual.red_mask ; + vformat -> Gmask = SDL_Visual.green_mask ; + vformat -> Bmask = SDL_Visual.blue_mask ; + } + + // See if we have been passed a window to use + SDL_windowid = getenv ("SDL_WINDOWID") ; + + // Create the fullscreen (and managed windows : no implement) + create_aux_windows (this) ; + + Dprintf ("leave NX_VideoInit\n") ; + return 0 ; +} + +void NX_VideoQuit (_THIS) +{ + Dprintf ("enter NX_VideoQuit\n") ; + + // Start shutting down the windows + NX_DestroyImage (this, this -> screen) ; + NX_DestroyWindow (this, this -> screen) ; + if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (FSwindow) ; + } + NX_FreeVideoModes (this) ; + SDL_free (GammaRamp_R) ; + SDL_free (GammaRamp_G) ; + SDL_free (GammaRamp_B) ; + +#ifdef ENABLE_NANOX_DIRECT_FB + if (Clientfb) + GrCloseClientFramebuffer(); +#endif + GrClose () ; + + Dprintf ("leave NX_VideoQuit\n") ; +} + +static void NX_DestroyWindow (_THIS, SDL_Surface * screen) +{ + Dprintf ("enter NX_DestroyWindow\n") ; + + if (! SDL_windowid) { + if (screen && (screen -> flags & SDL_FULLSCREEN)) { + screen -> flags &= ~ SDL_FULLSCREEN ; + NX_LeaveFullScreen (this) ; + } + + // Destroy the output window + if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { + GrDestroyWindow (SDL_Window) ; + } + } + + // Free the graphics context + if (! SDL_GC) { + GrDestroyGC (SDL_GC) ; + SDL_GC = 0; + } + + Dprintf ("leave NX_DestroyWindow\n") ; +} + +static int NX_CreateWindow (_THIS, SDL_Surface * screen, + int w, int h, int bpp, Uint32 flags) +{ + Dprintf ("enter NX_CreateWindow\n") ; + + // If a window is already present, destroy it and start fresh + if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { + NX_DestroyWindow (this, screen) ; + } + + // See if we have been given a window id + if (SDL_windowid) { + SDL_Window = SDL_strtol (SDL_windowid, NULL, 0) ; + } else { + SDL_Window = 0 ; + } + + if ( ! SDL_ReallocFormat (screen, bpp, SDL_Visual.red_mask, + SDL_Visual.green_mask, SDL_Visual.blue_mask, 0)) + return -1; + + // Create (or use) the nanox display window + if (! SDL_windowid) { + + SDL_Window = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, w, h, 0, BLACK, WHITE) ; + + GrSelectEvents (SDL_Window, (GR_EVENT_MASK_EXPOSURE | + GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | + GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | + GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | + GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | + GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | + GR_EVENT_MASK_CLOSE_REQ)) ; + } + + /* Create the graphics context here, once we have a window */ + SDL_GC = GrNewGC () ; + if (SDL_GC == 0) { + SDL_SetError("Couldn't create graphics context"); + return(-1); + } + + // Map them both and go fullscreen, if requested + if (! SDL_windowid) { + GrMapWindow (SDL_Window) ; + if (flags & SDL_FULLSCREEN) { + screen -> flags |= SDL_FULLSCREEN ; + NX_EnterFullScreen (this) ; + } else { + screen -> flags &= ~ SDL_FULLSCREEN ; + } + } + +#ifdef ENABLE_NANOX_DIRECT_FB + /* attempt allocating the client side framebuffer */ + Clientfb = GrOpenClientFramebuffer(); + /* NULL return will default to using GrArea()*/ +#endif + + Dprintf ("leave NX_CreateWindow\n") ; + return 0 ; +} + +SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, + int width, int height, int bpp, Uint32 flags) +{ + Dprintf ("enter NX_SetVideoMode\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + bpp = SDL_Visual.bpp ; + if (NX_CreateWindow (this, current, width, height, bpp, flags) < 0) { + current = NULL; + goto done; + } + + if (current -> w != width || current -> h != height) { + current -> w = width ; + current -> h = height ; + current -> pitch = SDL_CalculatePitch (current) ; + NX_ResizeImage (this, current, flags) ; + } + + /* Clear these flags and set them only if they are in the new set. */ + current -> flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); + current -> flags |= (flags & (SDL_RESIZABLE | SDL_NOFRAME)) ; + + done: + SDL_Unlock_EventThread () ; + + Dprintf ("leave NX_SetVideoMode\n") ; + + // We're done! + return current ; +} + +// ncolors <= 256 +int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) +{ + int i ; + GR_PALETTE pal ; + + Dprintf ("enter NX_SetColors\n") ; + + if (ncolors > 256) return 0 ; + + pal.count = ncolors ; + for (i = 0; i < ncolors; ++ i) { + pal.palette [i].r = colors [i].r ; + pal.palette [i].g = colors [i].g ; + pal.palette [i].b = colors [i].b ; + } + GrSetSystemPalette (firstcolor, & pal) ; + + Dprintf ("leave NX_SetColors\n") ; + return 1 ; +} + +static int NX_ToggleFullScreen (_THIS, int on) +{ + SDL_Rect rect ; + Uint32 event_thread ; + + Dprintf ("enter NX_ToggleFullScreen\n") ; + + // Don't switch if we don't own the window + if (SDL_windowid) return 0 ; + + // Don't lock if we are the event thread + event_thread = SDL_EventThreadID () ; + if (event_thread && (SDL_ThreadID () == event_thread)) { + event_thread = 0 ; + } + if (event_thread) { + SDL_Lock_EventThread() ; + } + + if (on) { + NX_EnterFullScreen (this) ; + } else { + this -> screen -> flags &= ~ SDL_FULLSCREEN ; + NX_LeaveFullScreen (this) ; + } + + rect.x = rect.y = 0 ; + rect.w = this -> screen -> w, rect.h = this -> screen -> h ; + NX_NormalUpdate (this, 1, & rect) ; + + if (event_thread) { + SDL_Unlock_EventThread () ; + } + + Dprintf ("leave NX_ToggleFullScreen\n") ; + return 1 ; +} + +// Update the current mouse state and position +static void NX_UpdateMouse (_THIS) +{ + int x, y ; + GR_WINDOW_INFO info ; + GR_SCREEN_INFO si ; + + + Dprintf ("enter NX_UpdateMouse\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + GrGetScreenInfo (& si) ; + GrGetWindowInfo (SDL_Window, & info) ; + x = si.xpos - info.x ; + y = si.ypos - info.y ; + if (x >= 0 && x <= info.width && y >= 0 && y <= info.height) { + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS) ; + SDL_PrivateMouseMotion (0, 0, x, y); + } else { + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS) ; + } + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_UpdateMouse\n") ; +} + +static int NX_SetGammaRamp (_THIS, Uint16 * ramp) +{ + int i ; + Uint16 * red, * green, * blue ; + + Dprintf ("enter NX_SetGammaRamp\n") ; + + if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; + + if (! GammaRamp_R) GammaRamp_R = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if (! GammaRamp_G) GammaRamp_G = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if (! GammaRamp_B) GammaRamp_B = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; + if ((! GammaRamp_R) || (! GammaRamp_G) || (! GammaRamp_B)) { + SDL_OutOfMemory () ; + return -1 ; + } + + for (i = 0; i < CI_SIZE; ++ i) + GammaRamp_R [i] = GammaRamp_G [i] = GammaRamp_B [i] = i ; + + red = ramp ; + green = ramp + CI_SIZE ; + blue = green + CI_SIZE ; + + for (i = 0; i < CI_SIZE; ++ i) { + GammaRamp_R [i] = red [i] ; + GammaRamp_G [i] = green [i] ; + GammaRamp_B [i] = blue [i] ; + } + SDL_UpdateRect(this->screen, 0, 0, 0, 0); + + Dprintf ("leave NX_SetGammaRamp\n") ; + return 0 ; +} + +static int NX_GetGammaRamp (_THIS, Uint16 * ramp) +{ + int i ; + Uint16 * red, * green, * blue ; + + Dprintf ("enter NX_GetGammaRamp\n") ; + + if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; + red = ramp ; + green = ramp + CI_SIZE ; + blue = green + CI_SIZE ; + if (GammaRamp_R && GammaRamp_G && GammaRamp_B) { + for (i = 0; i < CI_SIZE; ++ i) { + red [i] = GammaRamp_R [i] ; + green [i] = GammaRamp_G [i] ; + blue [i] = GammaRamp_B [i] ; + } + } else { + for (i = 0; i < CI_SIZE; ++ i) + red [i] = green [i] = blue [i] = i ; + } + + Dprintf ("leave NX_GetGammaRamp\n") ; + return 0 ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h new file mode 100644 index 0000000..1d858d9 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxvideo.h @@ -0,0 +1,96 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#ifndef _SDL_nxvideo_h +#define _SDL_nxvideo_h + +#include <microwin/nano-X.h> + +#include "../SDL_sysvideo.h" + +#ifdef ENABLE_NANOX_DEBUG +#define Dprintf printf +#else +#define Dprintf(ignore...) +#endif + +// Hidden "this" pointer for the video functions +#define _THIS SDL_VideoDevice * this + +// Private display data +typedef struct NX_SDL_VISUAL { + int bpp ; + Uint32 red_mask ; + Uint32 green_mask ; + Uint32 blue_mask ; +} nx_sdl_visual_t ; + +struct SDL_PrivateVideoData { + GR_WINDOW_ID SDL_Window ; + GR_WINDOW_ID FSwindow ; + // Flag: true if we have been passed a window + char * SDL_windowid ; + GR_GC_ID GC ; + unsigned char * Image ; + unsigned char * Image_buff ; /* for GrArea*/ + unsigned char * Clientfb; /* for DirectFB*/ + nx_sdl_visual_t SDL_Visual ; + // The current list of available video modes + SDL_Rect ** modelist ; + int currently_fullscreen ; + // for fullscreen + int OffsetX, OffsetY ; + // for GammaRamp + Uint16 * GammaRamp_R, * GammaRamp_G, * GammaRamp_B ; + // for GrArea, r_mask, g_mask, b_mask + int pixel_type ; +#ifdef ENABLE_NANOX_DIRECT_FB + GR_WINDOW_FB_INFO fbinfo; +#endif +} ; + +#define SDL_Window (this -> hidden -> SDL_Window) +#define FSwindow (this -> hidden -> FSwindow) +#define SDL_windowid (this -> hidden -> SDL_windowid) +#define SDL_GC (this -> hidden -> GC) +#define SDL_Image (this -> hidden -> Image) +#define Image_buff (this -> hidden -> Image_buff) +#define Clientfb (this -> hidden -> Clientfb) +#define SDL_Visual (this -> hidden -> SDL_Visual) +#define SDL_modelist (this -> hidden -> modelist) +#define currently_fullscreen (this -> hidden -> currently_fullscreen) +#define OffsetX (this -> hidden -> OffsetX) +#define OffsetY (this -> hidden -> OffsetY) +#define GammaRamp_R (this -> hidden -> GammaRamp_R) +#define GammaRamp_G (this -> hidden -> GammaRamp_G) +#define GammaRamp_B (this -> hidden -> GammaRamp_B) +#define pixel_type (this -> hidden -> pixel_type) +#define fbinfo (this -> hidden -> fbinfo) + +#define CI_SIZE 256 // color index size + +#endif // _SDL_nxvideo_h diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxwm.c b/3rdparty/SDL/src/video/nanox/SDL_nxwm.c new file mode 100644 index 0000000..c60ebb0 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxwm.c @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_syswm.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_nxwm_c.h" + +void NX_SetCaption (_THIS, const char * title, const char * icon) +{ + Dprintf ("enter NX_SetCaption\n") ; + + // Lock the event thread, in multi-threading environments + SDL_Lock_EventThread () ; + + if (SDL_Window) + GrSetWindowTitle (SDL_Window, title) ; + + SDL_Unlock_EventThread () ; + Dprintf ("leave NX_SetCaption\n") ; +} + +int NX_GetWMInfo (_THIS, SDL_SysWMinfo * info) +{ + Dprintf ("enter NX_GetWMInfo\n") ; + + if (info -> version.major <= SDL_MAJOR_VERSION) { + info -> window = SDL_Window ; + return 1 ; + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION) ; + return -1 ; + } + + Dprintf ("leave NX_GetWMInfo\n") ; +} diff --git a/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h b/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h new file mode 100644 index 0000000..77be794 --- /dev/null +++ b/3rdparty/SDL/src/video/nanox/SDL_nxwm_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + Copyright (C) 2001 Hsieh-Fu Tsai + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org + + Hsieh-Fu Tsai + clare@setabox.com +*/ +#include "SDL_config.h" + +#include "SDL_nxvideo.h" + +// Functions to be exported +extern void NX_SetCaption (_THIS, const char * title, const char * icon) ; +extern int NX_GetWMInfo (_THIS, SDL_SysWMinfo * info) ; diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsevents.c b/3rdparty/SDL/src/video/nds/SDL_ndsevents.c new file mode 100644 index 0000000..a4f0fbe --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsevents.c @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Being a nds driver, there's no event stream. We just define stubs for + most of the API. */ +#include <nds.h> +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ndsvideo.h" +#include "SDL_ndsevents_c.h" + +static SDLKey keymap[NDS_NUMKEYS]; +char keymem[NDS_NUMKEYS]; /* memorize states of buttons */ + +void NDS_PumpEvents(_THIS) +{ + scanKeys(); + int i; + SDL_keysym keysym; + keysym.mod=KMOD_NONE; + for(i=0;i<NDS_NUMKEYS;i++) + { + keysym.scancode=i; + keysym.sym=keymap[i]; + if(keysHeld()&(1<<i) && !keymem[i]) + { + keymem[i]=1; + //printf("key released %d\n",i); + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + if(!(keysHeld()&(1<<i)) && keymem[i]) + { + keymem[i]=0; + //printf("key pressed %d\n",i); + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + } + //touchPosition touch; + //touch=touchReadXY(); + //if (touch.px!=0 || touch.py!=0) + // SDL_PrivateMouseMotion(SDL_PRESSED, 0, touch.px, touch.py); +} + +void NDS_InitOSKeymap(_THIS) +{ + SDL_memset(keymem,1,NDS_NUMKEYS); + keymap[KEY_A]=SDLK_a; + keymap[KEY_B]=SDLK_s; + keymap[KEY_X]=SDLK_w; + keymap[KEY_Y]=SDLK_d; + keymap[KEY_L]=SDLK_q; + keymap[KEY_R]=SDLK_e; + keymap[KEY_UP]=SDLK_UP; + keymap[KEY_DOWN]=SDLK_DOWN; + keymap[KEY_LEFT]=SDLK_LEFT; + keymap[KEY_RIGHT]=SDLK_RIGHT; + keymap[KEY_SELECT]=SDLK_SPACE; + keymap[KEY_START]=SDLK_RETURN; +} + +/* end of SDL_gbaevents.c ... */ + diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h b/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h new file mode 100644 index 0000000..fcd0ef2 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsevents_c.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ndsvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void NDS_InitOSKeymap(_THIS); +extern void NDS_PumpEvents(_THIS); + +#define NDS_NUMKEYS 12 + +/* +#define NDS_JOYPADREG 0x4000130 +#define NDS_JOYPAD (*(volatile Uint16*)NDS_JOYPADREG) + +#define NDS_NUMKEYS 10 +#define NDS_KEYA (0) +#define NDS_KEYB (1) +#define NDS_KEYSEL (2) +#define NDS_KEYSTART (3) +#define NDS_KEYRIGHT (4) +#define NDS_KEYLEFT (5) +#define NDS_KEYUP (6) +#define NDS_KEYDOWN (7) +#define NDS_KEYR (8) +#define NDS_KEYL (9) +*/ +/* end of SDL_NDSevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c b/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c new file mode 100644 index 0000000..bba1417 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsmouse.c @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_error.h" +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_ndsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h b/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h new file mode 100644 index 0000000..76adf02 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ndsvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c new file mode 100644 index 0000000..d0ee8bf --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.c @@ -0,0 +1,500 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <nds.h> +#include <nds/registers_alt.h> +#include "SDL.h" +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_ndsvideo.h" +#include "SDL_ndsevents_c.h" +#include "SDL_ndsmouse_c.h" + +#define NDSVID_DRIVER_NAME "nds" + +/* Initialization/Query functions */ +static int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void NDS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int NDS_LockHWSurface(_THIS, SDL_Surface *surface); +static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface); +static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* NDS driver bootstrap functions */ + +static int NDS_Available(void) +{ + return(1); +} + +static void NDS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +void on_irq_vblank() +{ + // Disable interrupts + //REG_IME = 0; + scanKeys(); + + // VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK; + // REG_IF |= IRQ_VBLANK; + //REG_IF = REG_IF; + + // Enable interrupts + //REG_IME = 1; +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) + { + return 0; + } + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if (src->flags & SDL_SRCALPHA) return false; + if (src->flags & SDL_SRCCOLORKEY) return false; + if (src->flags & SDL_HWPALETTE ) return false; + if (dst->flags & SDL_SRCALPHA) return false; + if (dst->flags & SDL_SRCCOLORKEY) return false; + if (dst->flags & SDL_HWPALETTE ) return false; + + if (src->format->BitsPerPixel != dst->format->BitsPerPixel) return false; + if (src->format->BytesPerPixel != dst->format->BytesPerPixel) return false; + + src->map->hw_blit = HWAccelBlit; + return true; +} + +static SDL_VideoDevice *NDS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device=0; + + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = NDS_VideoInit; + device->ListModes = NDS_ListModes; + device->SetVideoMode = NDS_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = NDS_SetColors; + device->UpdateRects = NDS_UpdateRects; + device->VideoQuit = NDS_VideoQuit; + device->AllocHWSurface = NDS_AllocHWSurface; + device->CheckHWBlit = CheckHWBlit; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = NDS_LockHWSurface; + device->UnlockHWSurface = NDS_UnlockHWSurface; + device->FlipHWSurface = NDS_FlipHWSurface; + device->FreeHWSurface = NDS_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = NDS_InitOSKeymap; + device->PumpEvents = NDS_PumpEvents; + device->info.blit_hw=1; + + device->free = NDS_DeleteDevice; + return device; +} + +VideoBootStrap NDS_bootstrap = { + NDSVID_DRIVER_NAME, "SDL NDS video driver", + NDS_Available, NDS_CreateDevice +}; + + u16* frontBuffer;// = (u16*)(0x06000000); + u16* backBuffer;// = (u16*)(0x06000000 + 256 * 256 * 2); +int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + //printf("WARNING: You are using the SDL NDS video driver!\n"); + + /* Determine the screen depth (use default 8-bit depth) */ + /* we change this during the SDL_SetVideoMode implementation... */ + vformat->BitsPerPixel = 16; // mode 3 + vformat->BytesPerPixel = 2; + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + powerON(POWER_ALL); + irqInit(); + irqSet(IRQ_VBLANK, on_irq_vblank); + irqEnable(IRQ_VBLANK); + + //set the mode for 2 text layers and two extended background layers + //videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); + videoSetMode(MODE_6_2D| DISPLAY_BG2_ACTIVE); + + //set the sub background up for text display (we could just print to one + //of the main display text backgrounds just as easily + videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); //sub bg 0 will be used to print text + + //set the first two banks as background memory and the third as sub background memory + //D is not used..if you need a bigger background then you will need to map + //more vram banks consecutivly (VRAM A-D are all 0x20000 bytes in size) + //vramSetMainBanks(VRAM_A_MAIN_BG_0x6000000, VRAM_B_MAIN_BG_0x6020000,VRAM_C_SUB_BG , VRAM_D_LCD); + vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); + //vramSetBankA(VRAM_A_MAIN_BG); + //vramSetBankB(VRAM_B_MAIN_BG); + //vramSetBankC(VRAM_C_MAIN_BG); + //vramSetBankD(VRAM_D_MAIN_BG); + //vramSetBankE(VRAM_E_MAIN_BG); + //vramSetBankF(VRAM_F_MAIN_BG); + //vramSetBankG(VRAM_G_MAIN_BG); + vramSetBankH(VRAM_H_SUB_BG); + vramSetBankI(VRAM_I_LCD); + + ////////////////set up text background for text///////////////////// + SUB_BG0_CR = BG_MAP_BASE(8); + + BG_PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255 + ///////////////set up our bitmap background/////////////////////// + + //BG3_CR = BG_BMP16_512x512; + + //these are rotation backgrounds so you must set the rotation attributes: + //these are fixed point numbers with the low 8 bits the fractional part + //this basicaly gives it a 1:1 translation in x and y so you get a nice flat bitmap + /* BG3_XDX = 1<<8; + BG3_XDY = 0; + BG3_YDX = 0; + BG3_YDY = 1<<8; + //our bitmap looks a bit better if we center it so scroll down (256 - 192) / 2 + BG3_CX = 0; + BG3_CY = 0; + */ + //consoleInit() is a lot more flexible but this gets you up and running quick + consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(8), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); + + + frontBuffer =(u16*)(0x06000000); + //backBuffer =(u16*)(0x06000000 + 1024 * 512*2); + + //lcdSwap(); + /* We're done! */ + return(0); +} + +SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 Rmask, Gmask, Bmask, Amask; + + //if(width > 1024 || height > 512 || bpp > 16) + // return(NULL); + + if(bpp >8) { + bpp=16; + Rmask = 0x0000001F; + Gmask = 0x000003E0; + Bmask = 0x00007C00; + Amask = 0x00008000; + + videoSetMode(MODE_5_2D| DISPLAY_BG2_ACTIVE); + + vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); + + BG2_CR = BG_BMP16_512x512; + BG2_XDX = ((width / 256) << 8) | (width % 256) ; + BG2_XDY = 0; + BG2_YDX = 0; + BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; + BG2_CX = 0; + BG2_CY = 0; +// for (i=0;i<256*192;i++) +// frontBuffer[i] = RGB15(31,0,0)|BIT(15); + } + else + if(bpp <= 8) { + bpp=8; + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + BG2_CR = BG_BMP8_1024x512; + BG2_XDX = ((width / 256) << 8) | (width % 256) ; + BG2_XDY = 0; + BG2_YDX = 0; + BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; + + } + else + if(bpp < 15) bpp=15; + if(width<=256) width=256; + else + if(width<256) width=256; + if(height<=192) height=192; + else + if(height<192) height=192; + + if(bpp==8) + { + if(width<256) width=256; + if(height<192) height=192; + this->hidden->ndsmode=4; + } + + if(bpp==15) + { + if(width<256) this->hidden->ndsmode=5; + else this->hidden->ndsmode=3; + } + + this->hidden->buffer= frontBuffer;//NDS_VRAM_BASE; + + //NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2; + + //fprintf(stderr,"Setting mode %dx%d (ndsmode %d)\n", width, height,this->hidden->ndsmode); + + // FIXME: How do I tell that 15 bits mode is 555? + + SDL_memset(this->hidden->buffer, 0, 1024 * 512* ((this->hidden->ndsmode==4 || this->hidden->ndsmode==5) ? 2 : 1 ) * ((bpp+7) / 8)); + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, Amask) ) { + this->hidden->buffer = NULL; + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | (this->hidden->ndsmode > 0 ? SDL_DOUBLEBUF : 0); + this->hidden->w = current->w = width; + this->hidden->h = current->h = height; + current->pixels = frontBuffer; + + if (flags & SDL_DOUBLEBUF) { + this->hidden->secondbufferallocd=1; + backBuffer=(u16*)SDL_malloc(1024*512*2); + current->pixels = backBuffer; + } + if(bpp==8) + current->pitch =1024; + else + current->pitch =512*2; + + /* We're done */ + return(current); +} + +static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + if(this->hidden->secondbufferallocd) { + //printf("double double buffer alloc\n"); + return -1; + } + //if(this->hidden->ndsmode==3) + //{ + // printf("no 2nd buffer in mode3\n"); + // return -1; + //} + //printf("second buffer\n"); + //this->hidden->secondbufferallocd=1; + //backBuffer=(u16*)malloc(1024*512*2); + //surface->pixels = backBuffer; + + return(0); +} +static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + //free(backBuffer); + this->hidden->secondbufferallocd=0; +} +int z=0; +/* We need to wait for vertical retrace on page flipped displays */ +static int NDS_LockHWSurface(_THIS, SDL_Surface *surface) +{ +/* + uint8* a = surface->pixels; + int i,j; + a += 5 * SCREEN_WIDTH + 5; + for( i = 0; i < 195; ++i) { + uint16* line = a + (SCREEN_WIDTH * i); + for( j = 0; j < 158; ++j) { + *line++ = RGB15(155,155,25); + } + } +*/ + //if (z <256) + // BG_PALETTE[z++]=RGB15(255-z,z,255-z); + + + return(0); +} + +static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if(this->hidden->secondbufferallocd){ + while(DISP_Y!=192); + while(DISP_Y==192); + //printf("flip"); + + dmaCopyAsynch(backBuffer,frontBuffer,1024*512); + } + //printf("flip\n"); + //u16* temp = surface->pixels; + //surface->pixels = frontBuffer; + //frontBuffer = temp; + /* u8* vram=BG_GFX; + int x,y; + for(y = 0; y < 512; y++) + dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); + //unsigned char buf; + + //printf("NDS_FlipHWSurface\n"); + //printf("ptr now: 0x%x\n",surface->pixels); + + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = frontBuffer; + frontBuffer = backBuffer; + backBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG2_CR ^= BG_BMP_BASE( 512 / 16 ); */ +/* + if(surface->pixels == frontBuffer)//NDS_VRAM_BASE) + { + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = backBuffer; + backBuffer = frontBuffer; + frontBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG3_CR ^= BG_BMP_BASE( 128 / 16 ); + } + else + { + + while(DISP_Y!=192); + while(DISP_Y==192); + //swap + u16* temp = frontBuffer; + frontBuffer = backBuffer; + backBuffer = temp; + + //flip + //base is 16KB and screen size is 256x256x2 (128KB) + BG3_CR ^= BG_BMP_BASE( 128 / 16 ); + + } + */ + //printf("ptr then: 0x%x\n",surface->pixels); + + //printf("setting dispcnt to 0x%x\n",NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2| buf); + return(0); +} + +static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + //fprintf(stderr,"update\n"); + /* do nothing. */ + //dmaCopy(frontBuffer,BG_GFX,512*512); + /* + u8* vram=(u8*)BG_GFX; + int x,y; + for(y = 0; y < 512; y++) + dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); + */ + +} + +int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + //printf("SetColors\n"); + short r,g,b; + + if(this->hidden->ndsmode != 4) + { + printf("This is not a palettized mode\n"); + return -1; + } + + int i,j=firstcolor+ncolors; + for(i=firstcolor;i<j;i++) + { + r=colors[i].r>>3; + g=colors[i].g>>3; + b=colors[i].b>>3; + BG_PALETTE[i]=RGB15(r, g, b); + } + + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void NDS_VideoQuit(_THIS) +{ +} diff --git a/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h new file mode 100644 index 0000000..015f655 --- /dev/null +++ b/3rdparty/SDL/src/video/nds/SDL_ndsvideo.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_ndsvideo_h +#define _SDL_ndsvideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + int w, h; + void *buffer; + short ndsmode; + short secondbufferallocd; +}; + +/* +#define NDS_VIDC_BASE 0x4000000 +#define NDS_DISPCNT (*(volatile Uint32*)(NDS_VIDC_BASE)) +#define NDS_VIDC_SCANLINE (NDS_VIDC_BASE+6) +#define NDS_SCANLINE (*(volatile Uint8*)(NDS_VIDC_SCANLINE)) + +#define NDS_DISP_MODE(n) (n&7) +#define NDS_DISP_BG2 0x400 +#define NDS_DISP_FB 0x10 + +#define NDS_PAL_BASE 0x5000000 +#define NDS_BGPAL ((volatile Uint16*)(NDS_PAL_BASE)) +#define NDS_OBJPAL ((volatile Uint16*)(NDS_PAL_BASE+0x200)) + +#define NDS_VRAM_BASE 0x6000000 +#define NDS_VRAM_2NDBUF 0x600a000 +#define NDS_VRAM = ((volatile Uint16* )NDS_VRAM_BASE) +*/ +#endif /* _SDL_ndsvideo_h */ diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c new file mode 100644 index 0000000..a902d1f --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.c @@ -0,0 +1,3018 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define _ULS_CALLCONV_ +#define CALLCONV _System +#include <unidef.h> // Unicode API +#include <uconv.h> // Unicode API (codepage conversion) + +#include <process.h> +#include <time.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_os2fslib.h" + +static ULONG ulFCFToUse = + FCF_TITLEBAR | + FCF_SYSMENU | + FCF_MINBUTTON | + FCF_MAXBUTTON | + FCF_NOBYTEALIGN | + FCF_SIZEBORDER | + FCF_TASKLIST; + +static int bMouseCaptured = 0; +static int bMouseCapturable = 0; +static HPOINTER hptrGlobalPointer = NULL; +static HPOINTER hptrCurrentIcon = NULL; +static int iWindowSizeX = 320; +static int iWindowSizeY = 200; +static int bWindowResized = 0; + +#pragma pack(1) +typedef struct BMPINFO +{ + BITMAPINFO; + RGB clr; +} BMPINFO, *PBMPINFO; +#pragma pack() + + +// Backdoors: +DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF) +{ + ulFCFToUse = ulFCF; +} + +// Configuration defines: + +// We have to report empty alpha mask, otherwise SDL will select +// alpha blitters, and this will have unwanted results, as we don't +// support alpha channel in FSLib yet. +#define REPORT_EMPTY_ALPHA_MASK + +// Experimental: Move every FSLib_BitBlt() call into window message +// processing function. +// This may fix dirt left on desktop. Or not. +//#define BITBLT_IN_WINMESSAGEPROC + +// Experimental-2: Use WinLockWindowUpdate() in around bitblts! +// This is not enabled, because it seems to cause more problems +// than good. +//#define USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS + +// Use the following to show resized image instead of black stuff +// even if the surface is resizable. +//#define RESIZE_EVEN_IF_RESIZABLE + +/* The translation table from a VK keysym to a SDL keysym */ +static SDLKey HWScanKeyMap[256]; +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed); +static int iShiftIsPressed; + +#ifdef BITBLT_IN_WINMESSAGEPROC +#define WM_UPDATERECTSREQUEST WM_USER+50 +#endif + +#ifdef USE_WINLOCKWINDOWUPDATE_AROUND_BITBLTS +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ + { \ + WinLockWindowUpdate(HWND_DESKTOP, HWND_DESKTOP); \ + FSLib_BitBlt(hwnd, buffer, top, left, width, height); \ + WinLockWindowUpdate(HWND_DESKTOP, NULL); \ + } +#else +#define FSLIB_BITBLT(hwnd, buffer, top, left, width, height) \ + FSLib_BitBlt(hwnd, buffer, top, left, width, height); +#endif + +///////////////////////////////////////////////////////////////////// +// +// SetAccessableWindowPos +// +// Same as WinSetWindowPos(), but takes care for the window to be +// always on the screen, the titlebar will be accessable everytime. +// +///////////////////////////////////////////////////////////////////// +static BOOL SetAccessableWindowPos(HWND hwnd, HWND hwndInsertBehind, + LONG x, LONG y, + LONG cx, LONG cy, + ULONG fl) +{ + SWP swpDesktop, swp; + // Get desktop area + WinQueryWindowPos(HWND_DESKTOP, &swpDesktop); + + if ((fl & SWP_MOVE) && (fl & SWP_SIZE)) + { + // If both moving and sizing, then change size and pos now!! + if (x+cx>swpDesktop.cx) + x = swpDesktop.cx - cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+cy>swpDesktop.cy) + y = swpDesktop.cy - cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); + } else + if (fl & SWP_MOVE) + { + // Just moving + WinQueryWindowPos(hwnd, &swp); + if (x+swp.cx>swpDesktop.cx) + x = swpDesktop.cx - swp.cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+swp.cy>swpDesktop.cy) + y = swpDesktop.cy - swp.cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); + } else + if (fl & SWP_SIZE) + { + // Just sizing + WinQueryWindowPos(hwnd, &swp); + x = swp.x; + y = swp.y; + if (x+cx>swpDesktop.cx) + x = swpDesktop.cx - cx; + if (x<0) + x = 0; + if (y<0) + y = 0; + if (y+cy>swpDesktop.cy) + y = swpDesktop.cy - cy; + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl | SWP_MOVE); + } else + return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl); +} + +static UniChar NativeCharToUniChar(int chcode) +{ + UniChar ucResult = (UniChar) chcode; + int rc; + UconvObject ucoTemp; + char achFrom[2]; + char *pchFrom; + size_t iFromCount; + UniChar aucTo[10]; + UniChar *pucTo; + size_t iToCount; + size_t iNonIdentical; + + // Create unicode convert object + rc = UniCreateUconvObject(L"", &ucoTemp); + if (rc!=ULS_SUCCESS) + { + // Could not create convert object! + return ucResult; + } + + // Convert language code string to unicode string + achFrom[0] = (char) chcode; + achFrom[1] = 0; + iFromCount = sizeof(char) * 2; + iToCount = sizeof(UniChar) * 2; + pucTo = &(aucTo[0]); + pchFrom = &(achFrom[0]); + + rc = UniUconvToUcs(ucoTemp, + &pchFrom, + &iFromCount, + &pucTo, + &iToCount, + &iNonIdentical); + + if (rc!=ULS_SUCCESS) + { + // Could not convert language code to UCS string! + UniFreeUconvObject(ucoTemp); + return ucResult; + } + + UniFreeUconvObject(ucoTemp); + +#ifdef DEBUG_BUILD + printf("%02x converted to %02x\n", (int) chcode, (int) (aucTo[0])); +#endif + + return aucTo[0]; +} + +///////////////////////////////////////////////////////////////////// +// +// TranslateKey +// +// This creates SDL Keycodes from VK_ and hardware scan codes +// +///////////////////////////////////////////////////////////////////// +static SDL_keysym *TranslateKey(int vkey, int chcode, int scancode, SDL_keysym *keysym, int iPressed) +{ + keysym->scancode = (unsigned char) scancode; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + + if (iPressed && SDL_TranslateUNICODE) + { + if (chcode) + keysym->unicode = NativeCharToUniChar(chcode); + else + keysym->unicode = vkey; + } + + keysym->sym = HWScanKeyMap[scancode]; + + // Now stuffs based on state of shift key(s)! + if (vkey == VK_SHIFT) + { + iShiftIsPressed = iPressed; + } + + if ((iShiftIsPressed) && (SDL_TranslateUNICODE)) + { + // Change syms, if Unicode stuff is required + // I think it's silly, but it's SDL... + switch (keysym->sym) + { + case SDLK_BACKQUOTE: + keysym->sym = '~'; + break; + case SDLK_1: + keysym->sym = SDLK_EXCLAIM; + break; + case SDLK_2: + keysym->sym = SDLK_AT; + break; + case SDLK_3: + keysym->sym = SDLK_HASH; + break; + case SDLK_4: + keysym->sym = SDLK_DOLLAR; + break; + case SDLK_5: + keysym->sym = '%'; + break; + case SDLK_6: + keysym->sym = SDLK_CARET; + break; + case SDLK_7: + keysym->sym = SDLK_AMPERSAND; + break; + case SDLK_8: + keysym->sym = SDLK_ASTERISK; + break; + case SDLK_9: + keysym->sym = SDLK_LEFTPAREN; + break; + case SDLK_0: + keysym->sym = SDLK_RIGHTPAREN; + break; + case SDLK_MINUS: + keysym->sym = SDLK_UNDERSCORE; + break; + case SDLK_PLUS: + keysym->sym = SDLK_EQUALS; + break; + + case SDLK_LEFTBRACKET: + keysym->sym = '{'; + break; + case SDLK_RIGHTBRACKET: + keysym->sym = '}'; + break; + + case SDLK_SEMICOLON: + keysym->sym = SDLK_COLON; + break; + case SDLK_QUOTE: + keysym->sym = SDLK_QUOTEDBL; + break; + case SDLK_BACKSLASH: + keysym->sym = '|'; + break; + + case SDLK_COMMA: + keysym->sym = SDLK_LESS; + break; + case SDLK_PERIOD: + keysym->sym = SDLK_GREATER; + break; + case SDLK_SLASH: + keysym->sym = SDLK_QUESTION; + break; + + default: + break; + } + } + return keysym; +} + +#define CONVERTMOUSEPOSITION() \ + /* We have to inverse the mouse position, because every non-os/2 system */ \ + /* has a coordinate system where the (0;0) is the top-left corner, */ \ + /* while on os/2 it's the bottom left corner! */ \ + if (FSLib_QueryFSMode(hwnd)) \ + { \ + /* We're in FS mode! */ \ + /* In FS mode our window is as big as fullscreen mode, but not necessary as */ \ + /* big as the source buffer (can be bigger) */ \ + /* So, limit mouse pos to source buffer size! */ \ + if (ppts->x<0) ppts->x = 0; \ + if (ppts->y<0) ppts->y = 0; \ + if (ppts->x>=pVideo->hidden->SrcBufferDesc.uiXResolution) ppts->x = pVideo->hidden->SrcBufferDesc.uiXResolution-1; \ + if (ppts->y>=pVideo->hidden->SrcBufferDesc.uiYResolution) ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution-1; \ + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ \ + ptl.x = ppts->x; ptl.y = ppts->y; \ + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); \ + WinSetPointerPos(HWND_DESKTOP, ptl.x, ptl.y); \ + /* Then convert OS/2 position to SDL position */ \ + ppts->y = pVideo->hidden->SrcBufferDesc.uiYResolution - ppts->y - 1; \ + } else \ + { \ + SWP swpClient; \ + /* We're in windowed mode! */ \ + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); \ + /* Convert OS/2 mouse position to SDL position, and also scale it! */ \ + (ppts->x) = (ppts->x) * pVideo->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; \ + (ppts->y) = (ppts->y) * pVideo->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; \ + (ppts->y) = pVideo->hidden->SrcBufferDesc.uiYResolution - (ppts->y) - 1; \ + } + + + +///////////////////////////////////////////////////////////////////// +// +// WndProc +// +// This is the message processing window procedure for the +// SDLWindowClass, which is the client window in our application. +// It handles switching back and away from the app (taking care of +// going out and back to and from fullscreen mode), sending keystrokes +// and mouse events to where it has to be sent, etc... +// +///////////////////////////////////////////////////////////////////// +static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + HPS ps; + RECTL rcl; + SDL_VideoDevice *pVideo = NULL; + + switch (msg) + { + case WM_CHAR: // Keypress notification +#ifdef DEBUG_BUILD +// printf("WM_CHAR\n"); fflush(stdout); +#endif + pVideo = WinQueryWindowPtr(hwnd, 0); + if (pVideo) + { + /* + // We skip repeated keys: + if (CHARMSG(&msg)->cRepeat>1) + { +#ifdef DEBUG_BUILD +// printf("Repeated key (%d), skipping...\n", CHARMSG(&msg)->cRepeat); fflush(stdout); +#endif + return (MRESULT) TRUE; + } + */ + + // If it's not repeated, then let's see if its pressed or released! + if (SHORT1FROMMP(mp1) & KC_KEYUP) + { + // A key has been released + SDL_keysym keysym; + +#ifdef DEBUG_BUILD +// printf("WM_CHAR, keyup, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code +#endif + + // One problem is with F1, which gets only the keyup message because + // it is a system key. + // So, when we get keyup message, we simulate keydown too! + // UPDATE: + // This problem should be solved now, that the accelerator keys are + // disabled for this window! + /* + if (SHORT2FROMMP(mp2)==VK_F1) + { + SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,0)); + }*/ + + SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,0)); + + } else + { + // A key has been pressed + SDL_keysym keysym; + +#ifdef DEBUG_BUILD +// printf("WM_CHAR, keydown, code is [0x%0x]\n", CHAR4FROMMP(mp1)); // HW scan code +#endif + // Check for fastkeys: ALT+HOME to toggle FS mode + // ALT+END to close app + if ((SHORT1FROMMP(mp1) & KC_ALT) && + (SHORT2FROMMP(mp2) == VK_HOME)) + { +#ifdef DEBUG_BUILD + printf(" Pressed ALT+HOME!\n"); fflush(stdout); +#endif + // Only switch between fullscreen and back if it's not + // a resizable mode! + if ( + (!pVideo->hidden->pSDLSurface) || + ((pVideo->hidden->pSDLSurface) + && ((pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE)==0) + ) + ) + FSLib_ToggleFSMode(hwnd, !FSLib_QueryFSMode(hwnd)); +#ifdef DEBUG_BUILD + else + printf(" Resizable mode, so discarding ALT+HOME!\n"); fflush(stdout); +#endif + } else + if ((SHORT1FROMMP(mp1) & KC_ALT) && + (SHORT2FROMMP(mp2) == VK_END)) + { +#ifdef DEBUG_BUILD + printf(" Pressed ALT+END!\n"); fflush(stdout); +#endif + // Close window, and get out of loop! + // Also send event to SDL application, but we won't + // wait for it to be processed! + SDL_PrivateQuit(); + WinPostMsg(hwnd, WM_QUIT, 0, 0); + } else + { + + SDL_PrivateKeyboard(SDL_PRESSED, TranslateKey(SHORT2FROMMP(mp2), // VK_ code + SHORT1FROMMP(mp2), // Character code + CHAR4FROMMP(mp1), // HW Scan code + &keysym,1)); + + } + } + } + return (MRESULT) TRUE; + + case WM_TRANSLATEACCEL: + { + PQMSG pqmsg; + pqmsg = (PQMSG) mp1; + if (mp1) + { + if (pqmsg->msg == WM_CHAR) + { + // WM_CHAR message! + // Let's filter the ALT keypress and all other acceleration keys! + return (MRESULT) FALSE; + } + } + break; // Default processing (pass to parent until frame control) + } + + case WM_PAINT: // Window redraw! +#ifdef DEBUG_BUILD + printf("WM_PAINT (0x%x)\n", hwnd); fflush(stdout); +#endif + ps = WinBeginPaint(hwnd,0,&rcl); + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (!pVideo->hidden->pSDLSurface) + { + RECTL rclRect; + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_PAINT : Skipping blit while resizing (Pre!)!\n"); fflush(stdout); +#endif + WinQueryWindowRect(hwnd, &rclRect); + // Fill with black + WinFillRect(ps, &rclRect, CLR_BLACK); + } else + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR) + { + int iTop, iLeft, iWidth, iHeight; + int iXScaleError, iYScaleError; + int iXScaleError2, iYScaleError2; + SWP swp; + + // Re-blit the modified area! + // For this, we have to calculate the points, scaled! + WinQueryWindowPos(hwnd, &swp); +#ifdef DEBUG_BUILD + printf("WM_PAINT : WinSize: %d %d, BufSize: %d %d\n", + swp.cx, + swp.cy, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution + ); + fflush(stdout); +#endif + +#ifndef RESIZE_EVEN_IF_RESIZABLE + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + if ((!pVideo->hidden->pSDLSurface) || + ((pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + RECTL rclRect; + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_PAINT : Skipping blit while resizing!\n"); fflush(stdout); +#endif + WinQueryWindowRect(hwnd, &rclRect); + // Fill with black + WinFillRect(ps, &rclRect, CLR_BLACK); + } else +#endif + { + + iXScaleError = (pVideo->hidden->SrcBufferDesc.uiXResolution-1) / swp.cx; + iYScaleError = (pVideo->hidden->SrcBufferDesc.uiYResolution-1) / swp.cy; + if (iXScaleError<0) iXScaleError = 0; + if (iYScaleError<0) iYScaleError = 0; + iXScaleError2 = (swp.cx-1)/(pVideo->hidden->SrcBufferDesc.uiXResolution); + iYScaleError2 = (swp.cy-1)/(pVideo->hidden->SrcBufferDesc.uiYResolution); + if (iXScaleError2<0) iXScaleError2 = 0; + if (iYScaleError2<0) iYScaleError2 = 0; + + iTop = (swp.cy - rcl.yTop) * pVideo->hidden->SrcBufferDesc.uiYResolution / swp.cy - iYScaleError; + iLeft = rcl.xLeft * pVideo->hidden->SrcBufferDesc.uiXResolution / swp.cx - iXScaleError; + iWidth = ((rcl.xRight-rcl.xLeft) * pVideo->hidden->SrcBufferDesc.uiXResolution + swp.cx-1) + / swp.cx + 2*iXScaleError; + iHeight = ((rcl.yTop-rcl.yBottom) * pVideo->hidden->SrcBufferDesc.uiYResolution + swp.cy-1) + / swp.cy + 2*iYScaleError; + + iWidth+=iXScaleError2; + iHeight+=iYScaleError2; + + if (iTop<0) iTop = 0; + if (iLeft<0) iLeft = 0; + if (iTop+iHeight>pVideo->hidden->SrcBufferDesc.uiYResolution) iHeight = pVideo->hidden->SrcBufferDesc.uiYResolution-iTop; + if (iLeft+iWidth>pVideo->hidden->SrcBufferDesc.uiXResolution) iWidth = pVideo->hidden->SrcBufferDesc.uiXResolution-iLeft; + +#ifdef DEBUG_BUILD + printf("WM_PAINT : BitBlt: %d %d -> %d %d (Buf %d x %d)\n", + iTop, iLeft, iWidth, iHeight, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution + ); + fflush(stdout); +#endif + + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, iTop, iLeft, iWidth, iHeight); + } + + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + } +#ifdef DEBUG_BUILD + else + { + printf("WM_PAINT : No pVideo!\n"); fflush(stdout); + } +#endif + WinEndPaint(ps); +#ifdef DEBUG_BUILD + printf("WM_PAINT : Done.\n"); + fflush(stdout); +#endif + return 0; + + case WM_SIZE: + { +#ifdef DEBUG_BUILD + printf("WM_SIZE : (%d %d)\n", + SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); fflush(stdout); +#endif + iWindowSizeX = SHORT1FROMMP(mp2); + iWindowSizeY = SHORT2FROMMP(mp2); + bWindowResized = 1; + + // Make sure the window will be redrawn + WinInvalidateRegion(hwnd, NULL, TRUE); + } + break; + + case WM_FSLIBNOTIFICATION: +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION\n"); fflush(stdout); +#endif + if ((int)mp1 == FSLN_TOGGLEFSMODE) + { + // FS mode changed, reblit image! + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (!pVideo->hidden->pSDLSurface) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Can not blit if there is no surface, doing nothing.\n"); fflush(stdout); +#endif + } else + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, 1000)==NO_ERROR) + { + if (pVideo->hidden->pSDLSurface) + { +#ifndef RESIZE_EVEN_IF_RESIZABLE + SWP swp; + + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + WinQueryWindowPos(hwnd, &swp); + if ((!pVideo->hidden->pSDLSurface) || + ( + (pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Cannot blit while resizing, doing nothing.\n"); fflush(stdout); +#endif + } else +#endif + { +#ifdef DEBUG_BUILD + printf("WM_FSLIBNOTIFICATION : Blitting!\n"); fflush(stdout); +#endif + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, + 0, 0, + pVideo->hidden->SrcBufferDesc.uiXResolution, + pVideo->hidden->SrcBufferDesc.uiYResolution); + } + } +#ifdef DEBUG_BUILD + else + printf("WM_FSLIBNOTIFICATION : No public surface!\n"); fflush(stdout); +#endif + + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + } + } + return (MPARAM) 1; + + case WM_ACTIVATE: +#ifdef DEBUG_BUILD + printf("WM_ACTIVATE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + pVideo->hidden->fInFocus = (int) mp1; + if (pVideo->hidden->fInFocus) + { + // Went into focus + if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured)) + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + else + WinSetPointer(HWND_DESKTOP, NULL); + + if (bMouseCapturable) + { + // Re-capture the mouse, if we captured it before! + WinSetCapture(HWND_DESKTOP, hwnd); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } else + { + // Went out of focus + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + + if (bMouseCaptured) + { + // Release the mouse + WinSetCapture(HWND_DESKTOP, hwnd); + bMouseCaptured = 0; + } + } + } +#ifdef DEBUG_BUILD + printf("WM_ACTIVATE done\n"); fflush(stdout); +#endif + + break; + + case WM_BUTTON1DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON1DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_LEFT, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + } + break; + case WM_BUTTON1UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON1UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_LEFT, + 0, 0); // Don't report mouse movement! + break; + case WM_BUTTON2DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON2DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_RIGHT, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + + } + break; + case WM_BUTTON2UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON2UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_RIGHT, + 0, 0); // Don't report mouse movement! + break; + case WM_BUTTON3DOWN: +#ifdef DEBUG_BUILD + printf("WM_BUTTON3DOWN\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + SDL_PrivateMouseButton(SDL_PRESSED, + SDL_BUTTON_MIDDLE, + 0, 0); // Don't report mouse movement! + + if (bMouseCapturable) + { + // We should capture the mouse! + if (!bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, hwnd); + WinSetPointer(HWND_DESKTOP, NULL); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + } + break; + case WM_BUTTON3UP: +#ifdef DEBUG_BUILD + printf("WM_BUTTON3UP\n"); fflush(stdout); +#endif + SDL_PrivateMouseButton(SDL_RELEASED, + SDL_BUTTON_MIDDLE, + 0, 0); // Don't report mouse movement! + break; + case WM_MOUSEMOVE: +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + if (pVideo->hidden->iSkipWMMOUSEMOVE) + { + pVideo->hidden->iSkipWMMOUSEMOVE--; + } else + { + POINTS *ppts = (POINTS *) (&mp1); + POINTL ptl; + + if (bMouseCaptured) + { + SWP swpClient; + + WinQueryWindowPos(pVideo->hidden->hwndClient, &swpClient); + + // Send relative mouse position, and re-center the mouse + // Reposition the mouse to the center of the screen/window + SDL_PrivateMouseMotion(0, // Buttons not changed + 1, // Relative position + ppts->x - (swpClient.cx/2), + (swpClient.cy/2) - ppts->y); + + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(pVideo->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + pVideo->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + // Center the mouse to the middle of the window! + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } else + { + CONVERTMOUSEPOSITION(); + + // Send absolute mouse position + SDL_PrivateMouseMotion(0, // Buttons not changed + 0, // Absolute position + ppts->x, + ppts->y); + } + } + if ((pVideo->hidden->iMouseVisible) && (!bMouseCaptured)) + { +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE : ptr = %p\n", hptrGlobalPointer); fflush(stdout); +#endif + + if (hptrGlobalPointer) + WinSetPointer(HWND_DESKTOP, hptrGlobalPointer); + else + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + } + else + { + WinSetPointer(HWND_DESKTOP, NULL); + } + } +#ifdef DEBUG_BUILD +// printf("WM_MOUSEMOVE done\n"); fflush(stdout); +#endif + + return (MRESULT) FALSE; + case WM_CLOSE: // Window close +#ifdef DEBUG_BUILD + printf("WM_CLOSE\n"); fflush(stdout); +#endif + + pVideo = FSLib_GetUserParm(hwnd); + if (pVideo) + { + // Send Quit message to the SDL application! + SDL_PrivateQuit(); + return 0; + } + break; + +#ifdef BITBLT_IN_WINMESSAGEPROC + case WM_UPDATERECTSREQUEST: + pVideo = FSLib_GetUserParm(hwnd); + if ((pVideo) && (pVideo->hidden->pSDLSurface)) + { + if (DosRequestMutexSem(pVideo->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { + int numrects; + SDL_Rect *rects; + int i; + SWP swp; + + numrects = (int) mp1; + rects = (SDL_Rect *) mp2; + + WinQueryWindowPos(hwnd, &swp); +#ifndef RESIZE_EVEN_IF_RESIZABLE + if ((!pVideo->hidden->pSDLSurface) || + ( + (pVideo->hidden->pSDLSurface) && + (pVideo->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != pVideo->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != pVideo->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(hwnd)) + ) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("[WM_UPDATERECTSREQUEST] : Skipping blit while resizing!\n"); fflush(stdout); +#endif + } else +#endif + { +#ifdef DEBUG_BUILD + printf("[WM_UPDATERECTSREQUEST] : Blitting!\n"); fflush(stdout); +#endif + + // Blit the changed areas + for (i=0; i<numrects; i++) + FSLIB_BITBLT(hwnd, pVideo->hidden->pchSrcBuffer, + rects[i].y, rects[i].x, rects[i].w, rects[i].h); + } + DosReleaseMutexSem(pVideo->hidden->hmtxUseSrcBuffer); + } + } + return 0; +#endif + + default: +#ifdef DEBUG_BUILD + printf("Unhandled: %x\n", msg); fflush(stdout); +#endif + + break; + } + // Run the default window procedure for unhandled stuffs + return WinDefWindowProc(hwnd, msg, mp1, mp2); +} + +///////////////////////////////////////////////////////////////////// +// +// FrameWndProc +// +// This is the message processing window procedure for the +// frame window of SDLWindowClass. +// +///////////////////////////////////////////////////////////////////// +static MRESULT EXPENTRY FrameWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) +{ + PFNWP pOldFrameProc; + MRESULT result; + PTRACKINFO ti; + int cx, cy, ncx, ncy; + RECTL rclTemp; + PSWP pswpTemp; + + SDL_VideoDevice *pVideo = NULL; + + pVideo = (SDL_VideoDevice *) WinQueryWindowULong(hwnd, QWL_USER); + + pOldFrameProc = pVideo->hidden->pfnOldFrameProc; + + if ((pVideo->hidden->bProportionalResize) && + (msg==WM_ADJUSTWINDOWPOS) && + (!FSLib_QueryFSMode(pVideo->hidden->hwndClient)) + ) + { + pswpTemp = (PSWP) mp1; + + /* Resizing? */ + if (pswpTemp->fl & SWP_SIZE) + { + /* Calculate client size */ + rclTemp.xLeft = pswpTemp->x; + rclTemp.xRight = pswpTemp->x + pswpTemp->cx; + rclTemp.yBottom = pswpTemp->y; + rclTemp.yTop = pswpTemp->y + pswpTemp->cy; + WinCalcFrameRect(hwnd, &rclTemp, TRUE); + + ncx = cx = rclTemp.xRight - rclTemp.xLeft; + ncy = cy = rclTemp.yTop - rclTemp.yBottom; + + /* Calculate new size to keep it proportional */ + + if ((pVideo->hidden->ulResizingFlag & TF_LEFT) || (pVideo->hidden->ulResizingFlag & TF_RIGHT)) + { + /* The window is resized horizontally */ + ncy = pVideo->hidden->SrcBufferDesc.uiYResolution * cx / pVideo->hidden->SrcBufferDesc.uiXResolution; + } else + if ((pVideo->hidden->ulResizingFlag & TF_TOP) || (pVideo->hidden->ulResizingFlag & TF_BOTTOM)) + { + /* The window is resized vertically */ + ncx = pVideo->hidden->SrcBufferDesc.uiXResolution * cy / pVideo->hidden->SrcBufferDesc.uiYResolution; + } + + /* Calculate back frame coordinates */ + rclTemp.xLeft = pswpTemp->x; + rclTemp.xRight = pswpTemp->x + ncx; + rclTemp.yBottom = pswpTemp->y; + rclTemp.yTop = pswpTemp->y + ncy; + WinCalcFrameRect(hwnd, &rclTemp, FALSE); + + /* Store new size/position info */ + pswpTemp->cx = rclTemp.xRight - rclTemp.xLeft; + + if (!(pVideo->hidden->ulResizingFlag & TF_TOP)) + { + pswpTemp->y = pswpTemp->y + pswpTemp->cy - (rclTemp.yTop - rclTemp.yBottom); + pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom; + } else + { + pswpTemp->cy = rclTemp.yTop - rclTemp.yBottom; + } + } + } + + result = (*pOldFrameProc)(hwnd, msg, mp1, mp2); + + if ((pVideo->hidden->bProportionalResize) && (msg==WM_QUERYTRACKINFO)) + { + ti = (PTRACKINFO) mp2; + + /* Store the direction of resizing */ + if ((ti->fs & TF_LEFT) || (ti->fs & TF_RIGHT) || + (ti->fs & TF_TOP) || (ti->fs & TF_BOTTOM)) + pVideo->hidden->ulResizingFlag = ti->fs; + } + + return result; +} + +///////////////////////////////////////////////////////////////////// +// +// PMThreadFunc +// +// This function implements the PM-Thread, which initializes the +// application window itself, the DIVE, and start message processing. +// +///////////////////////////////////////////////////////////////////// +int iNumOfPMThreadInstances = 0; // Global! +static void PMThreadFunc(void *pParm) +{ + SDL_VideoDevice *pVideo = pParm; + HAB hab; + HMQ hmq; + QMSG msg; + ULONG fcf; + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Starting\n"); fflush(stdout); +#endif + + iNumOfPMThreadInstances++; + + // Initialize PM, create a message queue. + + hab=WinInitialize(0); + hmq=WinCreateMsgQueue(hab,0); + if (hmq==0) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Could not create message queue!\n"); + printf(" It might be that the application using SDL is not a PM app!\n"); + fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 2; + } else + { + int rc; + RECTL rectl; + + fcf = ulFCFToUse; // Get from global setting + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_CreateWindow()!\n"); + fflush(stdout); +#endif + + rc = FSLib_CreateWindow(HWND_DESKTOP, 0, &fcf, + "SDL Application", + NULLHANDLE, 0, + &(pVideo->hidden->SrcBufferDesc), + WndProc, + &(pVideo->hidden->hwndClient), + &(pVideo->hidden->hwndFrame)); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_CreateWindow() rc = %d\n", rc); + fflush(stdout); +#endif + + if (!rc) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Could not create FSLib window!\n"); + fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 3; + } else + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : FSLib_AddUserParm()!\n"); + fflush(stdout); +#endif + + // Store pVideo pointer in window data for client window, so + // it will know the instance to which it belongs to. + FSLib_AddUserParm(pVideo->hidden->hwndClient, pVideo); + + // Now set default image width height and fourcc! +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : SetWindowPos()!\n"); + fflush(stdout); +#endif + + // Set the position and size of the main window, + // and make it visible! + // Calculate frame window size from client window size + rectl.xLeft = 0; + rectl.yBottom = 0; + rectl.xRight = pVideo->hidden->SrcBufferDesc.uiXResolution; // Noninclusive + rectl.yTop = pVideo->hidden->SrcBufferDesc.uiYResolution; // Noninclusive + WinCalcFrameRect(pVideo->hidden->hwndFrame, &rectl, FALSE); + + SetAccessableWindowPos(pVideo->hidden->hwndFrame, + HWND_TOP, + (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - (rectl.xRight-rectl.xLeft)) / 2, + (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - (rectl.yTop-rectl.yBottom)) / 2, + (rectl.xRight-rectl.xLeft), + (rectl.yTop-rectl.yBottom), + SWP_SIZE | SWP_ACTIVATE | SWP_SHOW | SWP_MOVE); + + // Subclass frame procedure and store old window proc address + pVideo->hidden->pfnOldFrameProc = + WinSubclassWindow(pVideo->hidden->hwndFrame, FrameWndProc); + WinSetWindowULong(pVideo->hidden->hwndFrame, QWL_USER, (ULONG) pVideo); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Entering message loop\n"); fflush(stdout); +#endif + pVideo->hidden->iPMThreadStatus = 1; + + while (WinGetMsg(hab, (PQMSG)&msg, 0, 0, 0)) + WinDispatchMsg(hab, (PQMSG) &msg); + +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : Leaving message loop\n"); fflush(stdout); +#endif + // We should release the captured the mouse! + if (bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, NULLHANDLE); + bMouseCaptured = 0; + } + // Destroy our window + WinDestroyWindow(pVideo->hidden->hwndFrame); pVideo->hidden->hwndFrame=NULL; + // Show pointer to make sure it will not be left hidden. + WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE)); + WinShowPointer(HWND_DESKTOP, TRUE); + } + // Uninitialize PM + WinDestroyMsgQueue(hmq); + // All done! + pVideo->hidden->iPMThreadStatus = 0; + } + WinTerminate(hab); + /* Commented out, should not be needed anymore, because we send it + from WM_CLOSE. + // Notify SDL that it should really die now... + SDL_PrivateQuit(); SDL_PrivateQuit(); SDL_PrivateQuit(); //... :)) + */ +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : End, status is %d!\n", pVideo->hidden->iPMThreadStatus); fflush(stdout); +#endif + + iNumOfPMThreadInstances--; + + // HACK to prevent zombie and hanging SDL applications, which does not take + // care of closing the window for some reason: + // There are some apps which do not process messages, so do a lot of things + // without noticing that the application should close. To close these, + // I've thought about the following: + // If the window is closed (the execution came here), I wait a bit to + // give time to the app to finish its execution. If it does not, I kill it + // using DosExit(). Brute force, but should work. + if (pVideo->hidden->iPMThreadStatus==0) + { + DosSleep(5000); // Wait 5 secs + // If a new PM thread has been spawned (reinitializing video mode), then all right. + // Otherwise, we have a problem, the app doesn't want to stop. Kill! + if (iNumOfPMThreadInstances==0) + { +#ifdef DEBUG_BUILD + printf("[PMThreadFunc] : It seems that the application haven't terminated itself\n"); fflush(stdout); + printf("[PMThreadFunc] : in the last 5 seconds, so we go berserk.\n"); fflush(stdout); + printf("[PMThreadFunc] : Brute force mode. :) Killing process! Dieeeee...\n"); fflush(stdout); +#endif + DosExit(EXIT_PROCESS, -1); + } + } + _endthread(); +} + +struct WMcursor +{ + HBITMAP hbm; + HPOINTER hptr; + char *pchData; +}; + +/* Free a window manager cursor */ +void os2fslib_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if (cursor) + { + GpiDeleteBitmap(cursor->hbm); + WinDestroyPointer(cursor->hptr); + SDL_free(cursor->pchData); + SDL_free(cursor); + } +} + +/* Local functions to convert the SDL cursor mask into OS/2 format */ +static void memnot(Uint8 *dst, Uint8 *src, int len) +{ + while ( len-- > 0 ) + *dst++ = ~*src++; +} +static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len) +{ + while ( len-- > 0 ) + *dst++ = (*src1++)^(*src2++); +} + +/* Create a black/white window manager cursor */ +WMcursor *os2fslib_CreateWMCursor_Win(_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ + HPOINTER hptr; + HBITMAP hbm; + BITMAPINFOHEADER bmih; + BMPINFO bmi; + HPS hps; + char *pchTemp; + char *xptr, *aptr; + int maxx, maxy; + int i, run, pad; + WMcursor *pResult; + + maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXPOINTER); + maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER); + + // Check for max size! + if ((w>maxx) || (h>maxy)) + return (WMcursor *) NULL; + + pResult = (WMcursor *) SDL_malloc(sizeof(WMcursor)); + if (!pResult) return (WMcursor *) NULL; + + pchTemp = (char *) SDL_malloc((maxx + 7)/8 * maxy*2); + if (!pchTemp) + { + SDL_free(pResult); + return (WMcursor *) NULL; + } + + SDL_memset(pchTemp, 0, (maxx + 7)/8 * maxy*2); + + hps = WinGetPS(_this->hidden->hwndClient); + + bmi.cbFix = sizeof(BITMAPINFOHEADER); + bmi.cx = maxx; + bmi.cy = 2*maxy; + bmi.cPlanes = 1; + bmi.cBitCount = 1; + bmi.argbColor[0].bBlue = 0x00; + bmi.argbColor[0].bGreen = 0x00; + bmi.argbColor[0].bRed = 0x00; + bmi.argbColor[1].bBlue = 0x00; + bmi.argbColor[1].bGreen = 0x00; + bmi.argbColor[1].bRed = 0xff; + + SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.cbFix = sizeof(BITMAPINFOHEADER); + bmih.cx = maxx; + bmih.cy = 2*maxy; + bmih.cPlanes = 1; + bmih.cBitCount = 1; + + run = (w+7)/8; + pad = (maxx+7)/8 - run; + + for (i=0; i<h; i++) + { + xptr = pchTemp + (maxx+7)/8 * (maxy-1-i); + aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i); + memxor(xptr, data, mask, run); + xptr += run; + data += run; + memnot(aptr, mask, run); + mask += run; + aptr += run; + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + pad += run; + for (i=h ; i<maxy; i++ ) + { + xptr = pchTemp + (maxx+7)/8 * (maxy-1-i); + aptr = pchTemp + (maxx+7)/8 * (maxy+maxy-1-i); + + SDL_memset(xptr, 0, (maxx+7)/8); + xptr += (maxx+7)/8; + SDL_memset(aptr, ~0, (maxx+7)/8); + aptr += (maxx+7)/8; + } + + hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi); + hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, hot_x, maxy - hot_y - 1); + +#ifdef DEBUG_BUILD + printf("HotSpot : %d ; %d\n", hot_x, hot_y); + printf("HPS returned : %x\n", (ULONG)hps); + printf("HBITMAP returned : %x\n", (ULONG)hbm); + printf("HPOINTER returned: %x\n", (ULONG)hptr); +#endif + + WinReleasePS(hps); + +#ifdef DEBUG_BUILD + printf("[CreateWMCursor] : ptr = %p\n", hptr); fflush(stdout); +#endif + + pResult->hptr = hptr; + pResult->hbm = hbm; + pResult->pchData = pchTemp; + +#ifdef DEBUG_BUILD + printf("[CreateWMCursor] : ptr = %p return.\n", hptr); fflush(stdout); +#endif + + return (WMcursor *) pResult; +} + +WMcursor *os2fslib_CreateWMCursor_FS(_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) +{ +#ifdef DEBUG_BUILD + printf("[CreateWMCursor_FS] : returning pointer NULL\n"); fflush(stdout); +#endif + + // In FS mode we'll use software cursor + return (WMcursor *) NULL; +} + +/* Show the specified cursor, or hide if cursor is NULL */ +int os2fslib_ShowWMCursor(_THIS, WMcursor *cursor) +{ +#ifdef DEBUG_BUILD + printf("[ShowWMCursor] : ptr = %p\n", cursor); fflush(stdout); +#endif + + if (cursor) + { + WinSetPointer(HWND_DESKTOP, cursor->hptr); + hptrGlobalPointer = cursor->hptr; + _this->hidden->iMouseVisible = 1; + } + else + { + WinSetPointer(HWND_DESKTOP, FALSE); + hptrGlobalPointer = NULL; + _this->hidden->iMouseVisible = 0; + } + +#ifdef DEBUG_BUILD + printf("[ShowWMCursor] : ptr = %p, DONE\n", cursor); fflush(stdout); +#endif + + return 1; +} + +/* Warp the window manager cursor to (x,y) + If NULL, a mouse motion event is posted internally. + */ +void os2fslib_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + LONG lx, ly; + SWP swpClient; + POINTL ptlPoints; + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + ptlPoints.x = swpClient.x; + ptlPoints.y = swpClient.y; + WinMapWindowPoints(_this->hidden->hwndFrame, HWND_DESKTOP, &ptlPoints, 1); + lx = ptlPoints.x + (x*swpClient.cx) / _this->hidden->SrcBufferDesc.uiXResolution; + ly = ptlPoints.y + swpClient.cy - ((y*swpClient.cy) / _this->hidden->SrcBufferDesc.uiYResolution) - 1; + + SDL_PrivateMouseMotion(0, // Buttons not changed + 0, // Absolute position + x, + y); + + WinSetPointerPos(HWND_DESKTOP, lx, ly); + +} + +/* If not NULL, this is called when a mouse motion event occurs */ +void os2fslib_MoveWMCursor(_THIS, int x, int y) +{ + /* + SDL_Rect rect; + +#ifdef DEBUG_BUILD + printf("[MoveWMCursor] : at %d ; %d\n", x, y); fflush(stdout); +#endif + + rect.x = x; + rect.y = y; + rect.w = 32; + rect.h = 32; + os2fslib_UpdateRects(_this, 1, &rect); + // TODO! + */ +} + +/* Determine whether the mouse should be in relative mode or not. + This function is called when the input grab state or cursor + visibility state changes. + If the cursor is not visible, and the input is grabbed, the + driver can place the mouse in relative mode, which may result + in higher accuracy sampling of the pointer motion. + */ +void os2fslib_CheckMouseMode(_THIS) +{ +} + +static void os2fslib_PumpEvents(_THIS) +{ + // Notify SDL that if window has been resized! + if ( + (_this->hidden->pSDLSurface) && + (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ( + (_this->hidden->SrcBufferDesc.uiXResolution!=iWindowSizeX) || + (_this->hidden->SrcBufferDesc.uiYResolution!=iWindowSizeY) + ) && + (iWindowSizeX>0) && + (iWindowSizeY>0) + ) + { + static time_t prev_time; + time_t curr_time; + + curr_time = time(NULL); + if ((difftime(curr_time, prev_time)>=0.25) || + (bWindowResized)) + { + // Make sure we won't flood the event queue with resize events, + // only send them at 250 msecs! + // (or when the window is resized) +#ifdef DEBUG_BUILD + printf("[os2fslib_PumpEvents] : Calling PrivateResize (%d %d).\n", + iWindowSizeX, iWindowSizeY); + fflush(stdout); +#endif + // Tell SDL the new size + SDL_PrivateResize(iWindowSizeX, iWindowSizeY); + prev_time = curr_time; + bWindowResized = 0; + } + } +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int os2fslib_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void os2fslib_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int os2fslib_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void os2fslib_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int os2fslib_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + printf("[os2fslib_SetColors] : TODO!\n"); fflush(stdout); + // TODO: Implement paletted modes + return(1); +} + +static void os2fslib_DestroyIcon(HWND hwndFrame) +{ + if (hptrCurrentIcon) + { + WinDestroyPointer(hptrCurrentIcon); + hptrCurrentIcon = NULL; + + WinSendMsg(hwndFrame, + WM_SETICON, + NULL, + NULL); + } + +} + +/* Set the window icon image */ +void os2fslib_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + HWND hwndFrame; + SDL_Surface *icon_rgb; + HPOINTER hptrIcon; + HBITMAP hbm; + BITMAPINFOHEADER bmih; + BMPINFO bmi; + HPS hps; + char *pchTemp; + char *pptr, *mptr, *dptr, *dmptr; + int maxx, maxy, w, h, x, y; + SDL_Rect bounds; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetIcon] : Creating and setting new icon\n"); fflush(stdout); +#endif + + hwndFrame = WinQueryWindow(_this->hidden->hwndClient, QW_PARENT); + + // Make sure the old icon resource will be free'd! + os2fslib_DestroyIcon(hwndFrame); + + if ((!icon) || (!mask)) + return; + + w = icon->w; + h = icon->h; + + maxx = WinQuerySysValue(HWND_DESKTOP, SV_CXICON); + maxy = WinQuerySysValue(HWND_DESKTOP, SV_CYICON); + + // Check for max size! + if ((w>maxx) || (h>maxy)) + return; + + pchTemp = (char *) SDL_malloc(w * h*2 * 4); + if (!pchTemp) + return; + + SDL_memset(pchTemp, 0, w * h*2 * 4); + + // Convert surface to RGB, if it's not RGB yet! + icon_rgb = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + 32, 0, 0, 0, 0); + if ( icon_rgb == NULL ) + { + SDL_free(pchTemp); + return; + } + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, icon_rgb, &bounds) < 0 ) + { + SDL_FreeSurface(icon_rgb); + SDL_free(pchTemp); + return; + } + + /* Copy pixels upside-down from RGB surface into BMP, masked with the icon mask */ + + // Pixels + pptr = (char *) (icon_rgb->pixels); + // Mask + mptr = mask; + + for (y=0; y<h; y++) + { + unsigned char uchMaskByte; + + // Destination + dptr = pchTemp + w*4 * (h-y-1); + // Destination mask + dmptr = pchTemp + w*h*4 + w*4 * (h-y-1); + + for (x=0; x<w; x++) + { + if (x%8==0) + { + uchMaskByte = (unsigned char) (*mptr); + mptr++; + } else + uchMaskByte <<= 1; + + if (uchMaskByte & 0x80) + { + // Copy RGB + *dptr++ = *pptr++; + *dptr++ = *pptr++; + *dptr++ = *pptr++; + *dptr++ = *pptr++; + + *dmptr++ = 0; + *dmptr++ = 0; + *dmptr++ = 0; + *dmptr++ = 0; + } else + { + // Set pixels to fully transparent + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + *dptr++ = 0; pptr++; + + *dmptr++ = 255; + *dmptr++ = 255; + *dmptr++ = 255; + *dmptr++ = 255; + } + } + } + + // There is no more need for the RGB surface + SDL_FreeSurface(icon_rgb); + + hps = WinGetPS(_this->hidden->hwndClient); + + bmi.cbFix = sizeof(BITMAPINFOHEADER); + bmi.cx = w; + bmi.cy = 2*h; + bmi.cPlanes = 1; + bmi.cBitCount = 32; + + SDL_memset(&bmih, 0, sizeof(BITMAPINFOHEADER)); + bmih.cbFix = sizeof(BITMAPINFOHEADER); + bmih.cx = w; + bmih.cy = 2*h; + bmih.cPlanes = 1; + bmih.cBitCount = 32; + + hbm = GpiCreateBitmap(hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT, (PBYTE) pchTemp, (PBITMAPINFO2)&bmi); + hptrIcon = WinCreatePointer(HWND_DESKTOP, hbm, FALSE, 0, 0); + + WinReleasePS(hps); + + // Free pixel array + SDL_free(pchTemp); + + // Change icon in frame window + WinSendMsg(hwndFrame, + WM_SETICON, + (MPARAM) hptrIcon, + NULL); + + /* + // Change icon in switchlist + // Seems like it's not needed, the WM_SETICON already does it. + { + PID pidFrame; + HSWITCH hswitchFrame; + SWCNTRL swctl; + + WinQueryWindowProcess(hwndFrame, &pidFrame, NULL); + hswitchFrame = WinQuerySwitchHandle(hwndFrame, pidFrame); + WinQuerySwitchEntry(hswitchFrame, &swctl); + + swctl.hwndIcon = hptrIcon; + + WinChangeSwitchEntry(hswitchFrame, &swctl); + } + */ + + // Store icon handle in global variable + hptrCurrentIcon = hptrIcon; +} + +// ------------------------ REAL FUNCTIONS ----------------- + + +static void os2fslib_SetCursorManagementFunctions(_THIS, int iForWindowedMode) +{ + if (iForWindowedMode) + { + _this->FreeWMCursor = os2fslib_FreeWMCursor; + _this->CreateWMCursor = os2fslib_CreateWMCursor_Win; + _this->ShowWMCursor = os2fslib_ShowWMCursor; + _this->WarpWMCursor = os2fslib_WarpWMCursor; + _this->MoveWMCursor = os2fslib_MoveWMCursor; + _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode; + } else + { + // We'll have software mouse cursor in FS mode! + _this->FreeWMCursor = os2fslib_FreeWMCursor; + _this->CreateWMCursor = os2fslib_CreateWMCursor_FS; + _this->ShowWMCursor = os2fslib_ShowWMCursor; + _this->WarpWMCursor = os2fslib_WarpWMCursor; + _this->MoveWMCursor = os2fslib_MoveWMCursor; + _this->CheckMouseMode = NULL;//os2fslib_CheckMouseMode; + } +} + +static void os2fslib_InitOSKeymap(_THIS) +{ + int i; + + iShiftIsPressed = 0; + + /* Map the VK and CH keysyms */ + for ( i=0; i<=255; ++i ) + HWScanKeyMap[i] = SDLK_UNKNOWN; + + // First line of keyboard: + HWScanKeyMap[0x1] = SDLK_ESCAPE; + HWScanKeyMap[0x3b] = SDLK_F1; + HWScanKeyMap[0x3c] = SDLK_F2; + HWScanKeyMap[0x3d] = SDLK_F3; + HWScanKeyMap[0x3e] = SDLK_F4; + HWScanKeyMap[0x3f] = SDLK_F5; + HWScanKeyMap[0x40] = SDLK_F6; + HWScanKeyMap[0x41] = SDLK_F7; + HWScanKeyMap[0x42] = SDLK_F8; + HWScanKeyMap[0x43] = SDLK_F9; + HWScanKeyMap[0x44] = SDLK_F10; + HWScanKeyMap[0x57] = SDLK_F11; + HWScanKeyMap[0x58] = SDLK_F12; + HWScanKeyMap[0x5d] = SDLK_PRINT; + HWScanKeyMap[0x46] = SDLK_SCROLLOCK; + HWScanKeyMap[0x5f] = SDLK_PAUSE; + + // Second line of keyboard: + HWScanKeyMap[0x29] = SDLK_BACKQUOTE; + HWScanKeyMap[0x2] = SDLK_1; + HWScanKeyMap[0x3] = SDLK_2; + HWScanKeyMap[0x4] = SDLK_3; + HWScanKeyMap[0x5] = SDLK_4; + HWScanKeyMap[0x6] = SDLK_5; + HWScanKeyMap[0x7] = SDLK_6; + HWScanKeyMap[0x8] = SDLK_7; + HWScanKeyMap[0x9] = SDLK_8; + HWScanKeyMap[0xa] = SDLK_9; + HWScanKeyMap[0xb] = SDLK_0; + HWScanKeyMap[0xc] = SDLK_MINUS; + HWScanKeyMap[0xd] = SDLK_EQUALS; + HWScanKeyMap[0xe] = SDLK_BACKSPACE; + HWScanKeyMap[0x68] = SDLK_INSERT; + HWScanKeyMap[0x60] = SDLK_HOME; + HWScanKeyMap[0x62] = SDLK_PAGEUP; + HWScanKeyMap[0x45] = SDLK_NUMLOCK; + HWScanKeyMap[0x5c] = SDLK_KP_DIVIDE; + HWScanKeyMap[0x37] = SDLK_KP_MULTIPLY; + HWScanKeyMap[0x4a] = SDLK_KP_MINUS; + + // Third line of keyboard: + HWScanKeyMap[0xf] = SDLK_TAB; + HWScanKeyMap[0x10] = SDLK_q; + HWScanKeyMap[0x11] = SDLK_w; + HWScanKeyMap[0x12] = SDLK_e; + HWScanKeyMap[0x13] = SDLK_r; + HWScanKeyMap[0x14] = SDLK_t; + HWScanKeyMap[0x15] = SDLK_y; + HWScanKeyMap[0x16] = SDLK_u; + HWScanKeyMap[0x17] = SDLK_i; + HWScanKeyMap[0x18] = SDLK_o; + HWScanKeyMap[0x19] = SDLK_p; + HWScanKeyMap[0x1a] = SDLK_LEFTBRACKET; + HWScanKeyMap[0x1b] = SDLK_RIGHTBRACKET; + HWScanKeyMap[0x1c] = SDLK_RETURN; + HWScanKeyMap[0x69] = SDLK_DELETE; + HWScanKeyMap[0x65] = SDLK_END; + HWScanKeyMap[0x67] = SDLK_PAGEDOWN; + HWScanKeyMap[0x47] = SDLK_KP7; + HWScanKeyMap[0x48] = SDLK_KP8; + HWScanKeyMap[0x49] = SDLK_KP9; + HWScanKeyMap[0x4e] = SDLK_KP_PLUS; + + // Fourth line of keyboard: + HWScanKeyMap[0x3a] = SDLK_CAPSLOCK; + HWScanKeyMap[0x1e] = SDLK_a; + HWScanKeyMap[0x1f] = SDLK_s; + HWScanKeyMap[0x20] = SDLK_d; + HWScanKeyMap[0x21] = SDLK_f; + HWScanKeyMap[0x22] = SDLK_g; + HWScanKeyMap[0x23] = SDLK_h; + HWScanKeyMap[0x24] = SDLK_j; + HWScanKeyMap[0x25] = SDLK_k; + HWScanKeyMap[0x26] = SDLK_l; + HWScanKeyMap[0x27] = SDLK_SEMICOLON; + HWScanKeyMap[0x28] = SDLK_QUOTE; + HWScanKeyMap[0x2b] = SDLK_BACKSLASH; + HWScanKeyMap[0x4b] = SDLK_KP4; + HWScanKeyMap[0x4c] = SDLK_KP5; + HWScanKeyMap[0x4d] = SDLK_KP6; + + // Fifth line of keyboard: + HWScanKeyMap[0x2a] = SDLK_LSHIFT; + HWScanKeyMap[0x56] = SDLK_WORLD_1; // Code 161, letter i' on hungarian keyboard + HWScanKeyMap[0x2c] = SDLK_z; + HWScanKeyMap[0x2d] = SDLK_x; + HWScanKeyMap[0x2e] = SDLK_c; + HWScanKeyMap[0x2f] = SDLK_v; + HWScanKeyMap[0x30] = SDLK_b; + HWScanKeyMap[0x31] = SDLK_n; + HWScanKeyMap[0x32] = SDLK_m; + HWScanKeyMap[0x33] = SDLK_COMMA; + HWScanKeyMap[0x34] = SDLK_PERIOD; + HWScanKeyMap[0x35] = SDLK_SLASH; + HWScanKeyMap[0x36] = SDLK_RSHIFT; + HWScanKeyMap[0x61] = SDLK_UP; + HWScanKeyMap[0x4f] = SDLK_KP1; + HWScanKeyMap[0x50] = SDLK_KP2; + HWScanKeyMap[0x51] = SDLK_KP3; + HWScanKeyMap[0x5a] = SDLK_KP_ENTER; + + // Sixth line of keyboard: + HWScanKeyMap[0x1d] = SDLK_LCTRL; + HWScanKeyMap[0x7e] = SDLK_LSUPER; // Windows key + HWScanKeyMap[0x38] = SDLK_LALT; + HWScanKeyMap[0x39] = SDLK_SPACE; + HWScanKeyMap[0x5e] = SDLK_RALT;// Actually, altgr on my keyboard... + HWScanKeyMap[0x7f] = SDLK_RSUPER; + HWScanKeyMap[0x7c] = SDLK_MENU; + HWScanKeyMap[0x5b] = SDLK_RCTRL; + HWScanKeyMap[0x63] = SDLK_LEFT; + HWScanKeyMap[0x66] = SDLK_DOWN; + HWScanKeyMap[0x64] = SDLK_RIGHT; + HWScanKeyMap[0x52] = SDLK_KP0; + HWScanKeyMap[0x53] = SDLK_KP_PERIOD; +} + + +/* Iconify the window. + This function returns 1 if there is a window manager and the + window was actually iconified, it returns 0 otherwise. + */ +int os2fslib_IconifyWindow(_THIS) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return 0; + + // Cannot do anything in fullscreen mode! + if (FSLib_QueryFSMode(_this->hidden->hwndClient)) + return 0; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + WinSetWindowPos(_this->hidden->hwndFrame, HWND_TOP, + 0, 0, 0, 0, SWP_MINIMIZE); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + + return 1; +} + +static SDL_GrabMode os2fslib_GrabInput(_THIS, SDL_GrabMode mode) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) + return SDL_GRAB_OFF; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + if (mode == SDL_GRAB_OFF) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_GrabInput] : Releasing mouse\n"); fflush(stdout); +#endif + + // Release the mouse + bMouseCapturable = 0; + if (bMouseCaptured) + { + WinSetCapture(HWND_DESKTOP, NULLHANDLE); + bMouseCaptured = 0; + } + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_GrabInput] : Capturing mouse\n"); fflush(stdout); +#endif + + // Capture the mouse + bMouseCapturable = 1; + if (WinQueryFocus(HWND_DESKTOP) == _this->hidden->hwndClient) + { + WinSetCapture(HWND_DESKTOP, _this->hidden->hwndClient); + bMouseCaptured = 1; + { + SWP swpClient; + POINTL ptl; + // Center the mouse to the middle of the window! + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + ptl.x = 0; ptl.y = 0; + WinMapWindowPoints(_this->hidden->hwndClient, HWND_DESKTOP, &ptl, 1); + _this->hidden->iSkipWMMOUSEMOVE++; /* Don't take next WM_MOUSEMOVE into account! */ + WinSetPointerPos(HWND_DESKTOP, + ptl.x + swpClient.cx/2, + ptl.y + swpClient.cy/2); + } + } + } + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + + return mode; +} + +/* Set the title and icon text */ +static void os2fslib_SetCaption(_THIS, const char *title, const char *icon) +{ + HAB hab; + HMQ hmq; + ERRORID hmqerror; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + WinSetWindowText(_this->hidden->hwndFrame, (char *) title); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); +} + +static int os2fslib_ToggleFullScreen(_THIS, int on) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_ToggleFullScreen] : %d\n", on); fflush(stdout); +#endif + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return 0; + + FSLib_ToggleFSMode(_this->hidden->hwndClient, on); + /* Cursor manager functions to Windowed/FS mode*/ + os2fslib_SetCursorManagementFunctions(_this, !on); + return 1; +} + +/* This is called after the video mode has been set, to get the + initial mouse state. It should queue events as necessary to + properly represent the current mouse focus and position. + */ +static void os2fslib_UpdateMouse(_THIS) +{ + POINTL ptl; + HAB hab; + HMQ hmq; + ERRORID hmqerror; + SWP swpClient; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + + if (_this->hidden->fInFocus) + { + // If our app is in focus + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + SDL_PrivateAppActive(1, SDL_APPACTIVE); + WinQueryPointerPos(HWND_DESKTOP, &ptl); + WinMapWindowPoints(HWND_DESKTOP, _this->hidden->hwndClient, &ptl, 1); + WinQueryWindowPos(_this->hidden->hwndClient, &swpClient); + // Convert OS/2 mouse position to SDL position, and also scale it! + ptl.x = ptl.x * _this->hidden->SrcBufferDesc.uiXResolution / swpClient.cx; + ptl.y = ptl.y * _this->hidden->SrcBufferDesc.uiYResolution / swpClient.cy; + ptl.y = _this->hidden->SrcBufferDesc.uiYResolution - ptl.y - 1; + SDL_PrivateMouseMotion(0, 0, (Sint16) (ptl.x), (Sint16) (ptl.y)); + } else + { + // If we're not in focus + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + SDL_PrivateAppActive(0, SDL_APPACTIVE); + SDL_PrivateMouseMotion(0, 0, (Sint16) -1, (Sint16) -1); + } + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + WinDestroyMsgQueue(hmq); + +} + +/* This pointer should exist in the native video subsystem and should + point to an appropriate update function for the current video mode + */ +static void os2fslib_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return; + +#ifdef BITBLT_IN_WINMESSAGEPROC + WinSendMsg(_this->hidden->hwndClient, + WM_UPDATERECTSREQUEST, + (MPARAM) numrects, + (MPARAM) rects); +#else + if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { + int i; + + if (_this->hidden->pSDLSurface) + { +#ifndef RESIZE_EVEN_IF_RESIZABLE + SWP swp; + // But only blit if the window is not resizable, or if + // the window is resizable and the source buffer size is the + // same as the destination buffer size! + WinQueryWindowPos(_this->hidden->hwndClient, &swp); + if ((_this->hidden->pSDLSurface) && + (_this->hidden->pSDLSurface->flags & SDL_RESIZABLE) && + ((swp.cx != _this->hidden->SrcBufferDesc.uiXResolution) || + (swp.cy != _this->hidden->SrcBufferDesc.uiYResolution) + ) && + (!FSLib_QueryFSMode(_this->hidden->hwndClient)) + ) + { + // Resizable surface and in resizing! + // So, don't blit now! +#ifdef DEBUG_BUILD + printf("[UpdateRects] : Skipping blit while resizing!\n"); fflush(stdout); +#endif + } else +#endif + { + /* + // Blit the whole window + FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer, + 0, 0, + _this->hidden->SrcBufferDesc.uiXResolution, + _this->hidden->SrcBufferDesc.uiYResolution); + */ +#ifdef DEBUG_BUILD + printf("[os2fslib_UpdateRects] : Blitting!\n"); fflush(stdout); +#endif + + // Blit the changed areas + for (i=0; i<numrects; i++) + FSLIB_BITBLT(_this->hidden->hwndClient, _this->hidden->pchSrcBuffer, + rects[i].y, rects[i].x, rects[i].w, rects[i].h); + } + } +#ifdef DEBUG_BUILD + else + printf("[os2fslib_UpdateRects] : No public surface!\n"); fflush(stdout); +#endif + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + } +#ifdef DEBUG_BUILD + else + printf("[os2fslib_UpdateRects] : Error in mutex!\n"); fflush(stdout); +#endif +#endif +} + + +/* Reverse the effects VideoInit() -- called if VideoInit() fails + or if the application is shutting down the video subsystem. + */ +static void os2fslib_VideoQuit(_THIS) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit]\n"); fflush(stdout); +#endif + // Close PM stuff if running! + if (_this->hidden->iPMThreadStatus == 1) + { + int iTimeout; + WinPostMsg(_this->hidden->hwndFrame, WM_QUIT, (MPARAM) 0, (MPARAM) 0); + // HACK: We had this line before: + //DosWaitThread((TID *) &(_this->hidden->tidPMThread), DCWW_WAIT); + // We don't use it, because the PMThread will never stop, or if it stops, + // it will kill the whole process as a emergency fallback. + // So, we only check for the iPMThreadStatus stuff! +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Waiting for PM thread to die\n"); fflush(stdout); +#endif + + iTimeout=0; + while ((_this->hidden->iPMThreadStatus == 1) && (iTimeout<100)) + { + iTimeout++; + DosSleep(64); + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : End of wait.\n"); fflush(stdout); +#endif + + if (_this->hidden->iPMThreadStatus == 1) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Killing PM thread!\n"); fflush(stdout); +#endif + + _this->hidden->iPMThreadStatus = 0; + DosKillThread(_this->hidden->tidPMThread); + + if (_this->hidden->hwndFrame) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoQuit] : Destroying PM window!\n"); fflush(stdout); +#endif + + WinDestroyWindow(_this->hidden->hwndFrame); _this->hidden->hwndFrame=NULL; + } + } + + } + + // Free result of an old ListModes() call, because there is + // no FreeListModes() call in SDL! + if (_this->hidden->pListModesResult) + { + SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL; + } + + // Free list of available fullscreen modes + if (_this->hidden->pAvailableFSLibVideoModes) + { + FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes); + _this->hidden->pAvailableFSLibVideoModes = NULL; + } + + // Free application icon if we had one + if (hptrCurrentIcon) + { + WinDestroyPointer(hptrCurrentIcon); + hptrCurrentIcon = NULL; + } +} + +/* Set the requested video mode, returning a surface which will be + set to the SDL_VideoSurface. The width and height will already + be verified by ListModes(), and the video subsystem is free to + set the mode to a supported bit depth different from the one + specified -- the desired bpp will be emulated with a shadow + surface if necessary. If a new mode is returned, this function + should take care of cleaning up the current mode. + */ +static SDL_Surface *os2fslib_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + static int bFirstCall = 1; + FSLib_VideoMode_p pModeInfo, pModeInfoFound; + FSLib_VideoMode TempModeInfo; + HAB hab; + HMQ hmq; + ERRORID hmqerror; + RECTL rectl; + SDL_Surface *pResult; + + // If there is no more window, nothing we can do! + if (_this->hidden->iPMThreadStatus!=1) return NULL; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Request for %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout); +#endif + + // We don't support palette modes! + if (bpp==8) bpp=32; + + // Also, we don't support resizable modes in fullscreen mode. + if (flags & SDL_RESIZABLE) + flags &= ~SDL_FULLSCREEN; + + // No double buffered mode + if (flags & SDL_DOUBLEBUF) + flags &= ~SDL_DOUBLEBUF; + + // And, we don't support HWSURFACE yet. + if (flags & SDL_HWSURFACE) + { + flags &= ~SDL_HWSURFACE; + flags |= SDL_SWSURFACE; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Changed request to %dx%d @ %dBPP, flags=0x%x\n", width, height, bpp, flags); fflush(stdout); +#endif + + // First check if there is such a video mode they want! + pModeInfoFound = NULL; + + // For fullscreen mode we don't support every resolution! + // So, go through the video modes, and check for such a resolution! + pModeInfoFound = NULL; + pModeInfo = _this->hidden->pAvailableFSLibVideoModes; + + while (pModeInfo) + { + // Check all available fullscreen modes for this resolution + if ((pModeInfo->uiXResolution == width) && + (pModeInfo->uiYResolution == height) && + (pModeInfo->uiBPP!=8)) // palettized modes not yet supported + { + // If good resolution, try to find the exact BPP, or at least + // something similar... + if (!pModeInfoFound) + pModeInfoFound = pModeInfo; + else + if ((pModeInfoFound->uiBPP!=bpp) && + (pModeInfoFound->uiBPP<pModeInfo->uiBPP)) + pModeInfoFound = pModeInfo; + } + pModeInfo = pModeInfo->pNext; + } + + // If we did not find a good fullscreen mode, then try a similar + if (!pModeInfoFound) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested video mode not found, looking for a similar one!\n"); fflush(stdout); +#endif + // Go through the video modes again, and find a similar resolution! + pModeInfo = _this->hidden->pAvailableFSLibVideoModes; + while (pModeInfo) + { + // Check all available fullscreen modes for this resolution + if ((pModeInfo->uiXResolution >= width) && + (pModeInfo->uiYResolution >= height) && + (pModeInfo->uiBPP == bpp)) + { + if (!pModeInfoFound) + pModeInfoFound = pModeInfo; + else + if (((pModeInfoFound->uiXResolution-width)*(pModeInfoFound->uiYResolution-height))> + ((pModeInfo->uiXResolution-width)*(pModeInfo->uiYResolution-height))) + { + // Found a mode which is closer than the current one + pModeInfoFound = pModeInfo; + } + } + pModeInfo = pModeInfo->pNext; + } + } + + // If we did not find a good fullscreen mode, then return NULL + if (!pModeInfoFound) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested video mode not found!\n"); fflush(stdout); +#endif + return NULL; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Found mode!\n"); fflush(stdout); +#endif + + // We'll possibly adjust the structure, so copy out the values + // into TempModeInfo! + SDL_memcpy(&TempModeInfo, pModeInfoFound, sizeof(TempModeInfo)); + pModeInfoFound = &TempModeInfo; + + if (flags & SDL_RESIZABLE) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Requested mode is resizable, changing width/height\n"); fflush(stdout); +#endif + // Change width and height to requested one! + TempModeInfo.uiXResolution = width; + TempModeInfo.uiYResolution = height; + TempModeInfo.uiScanLineSize = width * ((TempModeInfo.uiBPP+7)/8); + } + + // We can try create new surface! + + // Make sure this thread is prepared for using the Presentation Manager! + hab = WinInitialize(0); + hmq = WinCreateMsgQueue(hab,0); + // Remember if there was an error at WinCreateMsgQueue(), because we don't + // want to destroy somebody else's queue later. :) + hmqerror = WinGetLastError(hab); + + + + if (DosRequestMutexSem(_this->hidden->hmtxUseSrcBuffer, SEM_INDEFINITE_WAIT)==NO_ERROR) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Creating new SW surface\n"); fflush(stdout); +#endif + + // Create new software surface! + pResult = SDL_CreateRGBSurface(SDL_SWSURFACE, + pModeInfoFound->uiXResolution, + pModeInfoFound->uiYResolution, + pModeInfoFound->uiBPP, + ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition, + ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition); + + if (pResult == NULL) + { + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + SDL_OutOfMemory(); + return NULL; + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Adjusting pixel format\n"); fflush(stdout); +#endif + + // Adjust pixel format mask! + pResult->format->Rmask = ((unsigned int) pModeInfoFound->PixelFormat.ucRedMask) << pModeInfoFound->PixelFormat.ucRedPosition; + pResult->format->Rshift = pModeInfoFound->PixelFormat.ucRedPosition; + pResult->format->Rloss = pModeInfoFound->PixelFormat.ucRedAdjust; + pResult->format->Gmask = ((unsigned int) pModeInfoFound->PixelFormat.ucGreenMask) << pModeInfoFound->PixelFormat.ucGreenPosition; + pResult->format->Gshift = pModeInfoFound->PixelFormat.ucGreenPosition; + pResult->format->Gloss = pModeInfoFound->PixelFormat.ucGreenAdjust; + pResult->format->Bmask = ((unsigned int) pModeInfoFound->PixelFormat.ucBlueMask) << pModeInfoFound->PixelFormat.ucBluePosition; + pResult->format->Bshift = pModeInfoFound->PixelFormat.ucBluePosition; + pResult->format->Bloss = pModeInfoFound->PixelFormat.ucBlueAdjust; + pResult->format->Amask = ((unsigned int) pModeInfoFound->PixelFormat.ucAlphaMask) << pModeInfoFound->PixelFormat.ucAlphaPosition; + pResult->format->Ashift = pModeInfoFound->PixelFormat.ucAlphaPosition; + pResult->format->Aloss = pModeInfoFound->PixelFormat.ucAlphaAdjust; + +#ifdef REPORT_EMPTY_ALPHA_MASK + pResult->format->Amask = + pResult->format->Ashift = + pResult->format->Aloss = 0; +#endif + + // Adjust surface flags + pResult->flags |= (flags & SDL_FULLSCREEN); + pResult->flags |= (flags & SDL_RESIZABLE); + + // It might be that the software surface pitch is not the same as + // the pitch we have, so adjust that! + pModeInfoFound->uiScanLineSize = pResult->pitch; + + // Store new source buffer parameters! + SDL_memcpy(&(_this->hidden->SrcBufferDesc), pModeInfoFound, sizeof(*pModeInfoFound)); + _this->hidden->pchSrcBuffer = pResult->pixels; + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Telling FSLib the stuffs\n"); fflush(stdout); +#endif + + // Tell the FSLib window the new source image format + FSLib_SetSrcBufferDesc(_this->hidden->hwndClient, &(_this->hidden->SrcBufferDesc)); + + if ( + ((flags & SDL_RESIZABLE)==0) || + (bFirstCall) + ) + { + bFirstCall = 0; +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Modifying window size\n"); fflush(stdout); +#endif + + // Calculate frame window size from client window size + rectl.xLeft = 0; + rectl.yBottom = 0; + rectl.xRight = pModeInfoFound->uiXResolution; // Noninclusive + rectl.yTop = pModeInfoFound->uiYResolution; // Noninclusive + WinCalcFrameRect(_this->hidden->hwndFrame, &rectl, FALSE); + + // Set the new size of the main window + SetAccessableWindowPos(_this->hidden->hwndFrame, + HWND_TOP, + 0, 0, + (rectl.xRight-rectl.xLeft), + (rectl.yTop-rectl.yBottom), + SWP_SIZE | SWP_ACTIVATE | SWP_SHOW); + } + + // Set fullscreen mode flag, and switch to fullscreen if needed! + if (flags & SDL_FULLSCREEN) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Also trying to switch to fullscreen\n"); + fflush(stdout); +#endif + FSLib_ToggleFSMode(_this->hidden->hwndClient, 1); + /* Cursor manager functions to FS mode*/ + os2fslib_SetCursorManagementFunctions(_this, 0); + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Also trying to switch to desktop mode\n"); + fflush(stdout); +#endif + FSLib_ToggleFSMode(_this->hidden->hwndClient, 0); + /* Cursor manager functions to Windowed mode*/ + os2fslib_SetCursorManagementFunctions(_this, 1); + } + + _this->hidden->pSDLSurface = pResult; + + DosReleaseMutexSem(_this->hidden->hmtxUseSrcBuffer); + } else + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Could not get hmtxUseSrcBuffer!\n"); fflush(stdout); +#endif + + pResult = NULL; + } + + // As we have the new surface, we don't need the current one anymore! + if ((pResult) && (current)) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Freeing old surface\n"); fflush(stdout); +#endif + SDL_FreeSurface(current); + } + + // Redraw window + WinInvalidateRegion(_this->hidden->hwndClient, NULL, TRUE); + + // Now destroy the message queue, if we've created it! + if (ERRORIDERROR(hmqerror)==0) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Destroying message queue\n"); fflush(stdout); +#endif + WinDestroyMsgQueue(hmq); + } + +#ifdef DEBUG_BUILD + printf("[os2fslib_SetVideoMode] : Done\n"); fflush(stdout); +#endif + + /* We're done */ + + // Return with the new surface! + return pResult; +} + +/* List the available video modes for the given pixel format, sorted + from largest to smallest. + */ +static SDL_Rect **os2fslib_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_ListModes] : ListModes of %d Bpp\n", format->BitsPerPixel); +#endif + // Destroy result of previous call, if there is any + if (_this->hidden->pListModesResult) + { + SDL_free(_this->hidden->pListModesResult); _this->hidden->pListModesResult = NULL; + } + + // For resizable and windowed mode we support every resolution! + if ((flags & SDL_RESIZABLE) && ((flags & SDL_FULLSCREEN) == 0)) + return (SDL_Rect **)-1; + + // Check if they need fullscreen or non-fullscreen video modes! + if ((flags & SDL_FULLSCREEN) == 0) + + { + // For windowed mode we support every resolution! + return (SDL_Rect **)-1; + } else + { + FSLib_VideoMode_p pFSMode; + // For fullscreen mode we don't support every resolution! + // Now create a new list + pFSMode = _this->hidden->pAvailableFSLibVideoModes; + while (pFSMode) + { + if (pFSMode->uiBPP == format->BitsPerPixel) + { + SDL_Rect *pRect = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect)); + if (pRect) + { + // Fill description + pRect->x = 0; + pRect->y = 0; + pRect->w = pFSMode->uiXResolution; + pRect->h = pFSMode->uiYResolution; +#ifdef DEBUG_BUILD +// printf("!!! Seems to be good!\n"); +// printf("F: %dx%d\n", pRect->w, pRect->h); +#endif + // And insert into list of pRects + if (!(_this->hidden->pListModesResult)) + { +#ifdef DEBUG_BUILD +// printf("!!! Inserting to beginning\n"); +#endif + + // We're the first one to be inserted! + _this->hidden->pListModesResult = (SDL_Rect**) SDL_malloc(2*sizeof(SDL_Rect*)); + if (_this->hidden->pListModesResult) + { + _this->hidden->pListModesResult[0] = pRect; + _this->hidden->pListModesResult[1] = NULL; + } else + { + SDL_free(pRect); + } + } else + { + // We're not the first ones, so find the place where we + // have to insert ourselves + SDL_Rect **pNewList; + int iPlace, iNumOfSlots, i; + +#ifdef DEBUG_BUILD +// printf("!!! Searching where to insert\n"); +#endif + + iPlace = -1; iNumOfSlots = 1; // Count the last NULL too! + for (i=0; _this->hidden->pListModesResult[i]; i++) + { + iNumOfSlots++; + if (iPlace==-1) + { + if ((_this->hidden->pListModesResult[i]->w*_this->hidden->pListModesResult[i]->h)< + (pRect->w*pRect->h)) + { + iPlace = i; + } + } + } + if (iPlace==-1) iPlace = iNumOfSlots-1; + +#ifdef DEBUG_BUILD +// printf("!!! From %d slots, it will be at %d\n", iNumOfSlots, iPlace); +#endif + + pNewList = (SDL_Rect**) SDL_realloc(_this->hidden->pListModesResult, (iNumOfSlots+1)*sizeof(SDL_Rect*)); + if (pNewList) + { + for (i=iNumOfSlots;i>iPlace;i--) + pNewList[i] = pNewList[i-1]; + pNewList[iPlace] = pRect; + _this->hidden->pListModesResult = pNewList; + } else + { + SDL_free(pRect); + } + } + } + } + pFSMode = pFSMode->pNext; + } + } +#ifdef DEBUG_BUILD +// printf("Returning list\n"); +#endif + return _this->hidden->pListModesResult; +} + +/* Initialize the native video subsystem, filling 'vformat' with the + "best" display pixel format, returning 0 or -1 if there's an error. + */ +static int os2fslib_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + FSLib_VideoMode_p pDesktopMode; + +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Enter\n"); fflush(stdout); +#endif + + // Report the best pixel format. For this, + // we'll use the current desktop format. + pDesktopMode = FSLib_GetDesktopVideoMode(); + if (!pDesktopMode) + { + SDL_SetError("Could not query desktop video mode!"); +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Could not query desktop video mode!\n"); +#endif + return -1; + } + + /* Determine the current screen size */ + _this->info.current_w = pDesktopMode->uiXResolution; + _this->info.current_h = pDesktopMode->uiYResolution; + + /* Determine the screen depth */ + vformat->BitsPerPixel = pDesktopMode->uiBPP; + vformat->BytesPerPixel = (vformat->BitsPerPixel+7)/8; + + vformat->Rmask = ((unsigned int) pDesktopMode->PixelFormat.ucRedMask) << pDesktopMode->PixelFormat.ucRedPosition; + vformat->Rshift = pDesktopMode->PixelFormat.ucRedPosition; + vformat->Rloss = pDesktopMode->PixelFormat.ucRedAdjust; + vformat->Gmask = ((unsigned int) pDesktopMode->PixelFormat.ucGreenMask) << pDesktopMode->PixelFormat.ucGreenPosition; + vformat->Gshift = pDesktopMode->PixelFormat.ucGreenPosition; + vformat->Gloss = pDesktopMode->PixelFormat.ucGreenAdjust; + vformat->Bmask = ((unsigned int) pDesktopMode->PixelFormat.ucBlueMask) << pDesktopMode->PixelFormat.ucBluePosition; + vformat->Bshift = pDesktopMode->PixelFormat.ucBluePosition; + vformat->Bloss = pDesktopMode->PixelFormat.ucBlueAdjust; + vformat->Amask = ((unsigned int) pDesktopMode->PixelFormat.ucAlphaMask) << pDesktopMode->PixelFormat.ucAlphaPosition; + vformat->Ashift = pDesktopMode->PixelFormat.ucAlphaPosition; + vformat->Aloss = pDesktopMode->PixelFormat.ucAlphaAdjust; + +#ifdef REPORT_EMPTY_ALPHA_MASK + vformat->Amask = + vformat->Ashift = + vformat->Aloss = 0; +#endif + + // Fill in some window manager capabilities + _this->info.wm_available = 1; + + // Initialize some internal variables + _this->hidden->pListModesResult = NULL; + _this->hidden->fInFocus = 0; + _this->hidden->iSkipWMMOUSEMOVE = 0; + _this->hidden->iMouseVisible = 1; + + if (getenv("SDL_USE_PROPORTIONAL_WINDOW")) + _this->hidden->bProportionalResize = 1; + else + { + PPIB pib; + PTIB tib; + char *pchFileName, *pchTemp; + char achConfigFile[CCHMAXPATH]; + FILE *hFile; + + /* No environment variable to have proportional window. + * Ok, let's check if this executable is in config file! + */ + _this->hidden->bProportionalResize = 0; + + DosGetInfoBlocks(&tib, &pib); + pchTemp = pchFileName = pib->pib_pchcmd; + while (*pchTemp) + { + if (*pchTemp=='\\') + pchFileName = pchTemp+1; + pchTemp++; + } + if (getenv("HOME")) + { + sprintf(achConfigFile, "%s\\.sdl.proportionals", getenv("HOME")); + hFile = fopen(achConfigFile, "rt"); + if (!hFile) + { + /* Seems like the file cannot be opened or does not exist. + * Let's try to create it with defaults! + */ + hFile = fopen(achConfigFile, "wt"); + if (hFile) + { + fprintf(hFile, "; This file is a config file of SDL/2, containing\n"); + fprintf(hFile, "; the list of executables that must have proportional\n"); + fprintf(hFile, "; windows.\n"); + fprintf(hFile, ";\n"); + fprintf(hFile, "; You can add executable filenames into this file,\n"); + fprintf(hFile, "; one under the other. If SDL finds that a given\n"); + fprintf(hFile, "; program is in this list, then that application\n"); + fprintf(hFile, "; will have proportional windows, just like if\n"); + fprintf(hFile, "; the SET SDL_USE_PROPORTIONAL_WINDOW env. variable\n"); + fprintf(hFile, "; would have been set for that process.\n"); + fprintf(hFile, ";\n"); + fprintf(hFile, "\n"); + fprintf(hFile, "dosbox.exe\n"); + fclose(hFile); + } + + hFile = fopen(achConfigFile, "rt"); + } + + if (hFile) + { + while (fgets(achConfigFile, sizeof(achConfigFile), hFile)) + { + /* Cut \n from end of string */ + + while (achConfigFile[strlen(achConfigFile)-1] == '\n') + achConfigFile[strlen(achConfigFile)-1] = 0; + + /* Compare... */ + if (stricmp(achConfigFile, pchFileName)==0) + { + /* Found it in config file! */ + _this->hidden->bProportionalResize = 1; + break; + } + } + fclose(hFile); + } + } + } + + DosCreateMutexSem(NULL, &(_this->hidden->hmtxUseSrcBuffer), 0, FALSE); + + // Now create our window with a default size + + // For this, we select the first available fullscreen mode as + // current window size! + SDL_memcpy(&(_this->hidden->SrcBufferDesc), _this->hidden->pAvailableFSLibVideoModes, sizeof(_this->hidden->SrcBufferDesc)); + // Allocate new video buffer! + _this->hidden->pchSrcBuffer = (char *) SDL_malloc(_this->hidden->pAvailableFSLibVideoModes->uiScanLineSize * _this->hidden->pAvailableFSLibVideoModes->uiYResolution); + if (!_this->hidden->pchSrcBuffer) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Yikes, not enough memory for new video buffer!\n"); fflush(stdout); +#endif + SDL_SetError("Not enough memory for new video buffer!\n"); + return -1; + } + + // For this, we need a message processing thread. + // We'll create a new thread for this, which will do everything + // what is related to PM + _this->hidden->iPMThreadStatus = 0; + _this->hidden->tidPMThread = _beginthread(PMThreadFunc, NULL, 65536, (void *) _this); + if (_this->hidden->tidPMThread <= 0) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : Could not create PM thread!\n"); +#endif + SDL_SetError("Could not create PM thread"); + return -1; + } +#ifdef USE_DOSSETPRIORITY + // Burst the priority of PM Thread! + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, _this->hidden->tidPMThread); +#endif + // Wait for the PM thread to initialize! + while (_this->hidden->iPMThreadStatus==0) + DosSleep(32); + // If the PM thread could not set up everything, then + // report an error! + if (_this->hidden->iPMThreadStatus!=1) + { +#ifdef DEBUG_BUILD + printf("[os2fslib_VideoInit] : PMThread reported an error : %d\n", _this->hidden->iPMThreadStatus); +#endif + SDL_SetError("Error initializing PM thread"); + return -1; + } + + return 0; +} + + +static void os2fslib_DeleteDevice(_THIS) +{ +#ifdef DEBUG_BUILD + printf("[os2fslib_DeleteDevice]\n"); fflush(stdout); +#endif + // Free used memory + FSLib_FreeVideoModeList(_this->hidden->pAvailableFSLibVideoModes); + if (_this->hidden->pListModesResult) + SDL_free(_this->hidden->pListModesResult); + if (_this->hidden->pchSrcBuffer) + SDL_free(_this->hidden->pchSrcBuffer); + DosCloseMutexSem(_this->hidden->hmtxUseSrcBuffer); + SDL_free(_this->hidden); + SDL_free(_this); + FSLib_Uninitialize(); +} + +static int os2fslib_Available(void) +{ + + // If we can run, it means that we could load FSLib, + // so we assume that it's available then! + return 1; +} + +static void os2fslib_MorphToPM() +{ + PPIB pib; + PTIB tib; + + DosGetInfoBlocks(&tib, &pib); + + // Change flag from VIO to PM: + if (pib->pib_ultype==2) pib->pib_ultype = 3; +} + +static SDL_VideoDevice *os2fslib_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : Enter\n"); fflush(stdout); +#endif + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) + { + SDL_memset(device, 0, (sizeof *device)); + // Also allocate memory for private data + device->hidden = (struct SDL_PrivateVideoData *) SDL_malloc((sizeof(struct SDL_PrivateVideoData))); + } + if ( (device == NULL) || (device->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( device ) + SDL_free(device); + return NULL; + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : VideoInit is %p\n", os2fslib_VideoInit); fflush(stdout); +#endif + + /* Initialization/Query functions */ + device->VideoInit = os2fslib_VideoInit; + device->ListModes = os2fslib_ListModes; + device->SetVideoMode = os2fslib_SetVideoMode; + device->ToggleFullScreen = os2fslib_ToggleFullScreen; + device->UpdateMouse = os2fslib_UpdateMouse; + device->CreateYUVOverlay = NULL; + device->SetColors = os2fslib_SetColors; + device->UpdateRects = os2fslib_UpdateRects; + device->VideoQuit = os2fslib_VideoQuit; + /* Hardware acceleration functions */ + device->AllocHWSurface = os2fslib_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = os2fslib_LockHWSurface; + device->UnlockHWSurface = os2fslib_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = os2fslib_FreeHWSurface; + /* Window manager functions */ + device->SetCaption = os2fslib_SetCaption; + device->SetIcon = os2fslib_SetIcon; + device->IconifyWindow = os2fslib_IconifyWindow; + device->GrabInput = os2fslib_GrabInput; + device->GetWMInfo = NULL; + /* Cursor manager functions to Windowed mode*/ + os2fslib_SetCursorManagementFunctions(device, 1); + /* Event manager functions */ + device->InitOSKeymap = os2fslib_InitOSKeymap; + device->PumpEvents = os2fslib_PumpEvents; + /* The function used to dispose of this structure */ + device->free = os2fslib_DeleteDevice; + + // Make sure we'll be able to use Win* API even if the application + // was linked to be a VIO application! + os2fslib_MorphToPM(); + + // Now initialize FSLib, and query available video modes! + if (!FSLib_Initialize()) + { + // Could not initialize FSLib! +#ifdef DEBUG_BUILD + printf("[os2fslib_CreateDevice] : Could not initialize FSLib!\n"); +#endif + SDL_SetError("Could not initialize FSLib!"); + SDL_free(device->hidden); + SDL_free(device); + return NULL; + } + device->hidden->pAvailableFSLibVideoModes = + FSLib_GetVideoModeList(); + + return device; +} + +VideoBootStrap OS2FSLib_bootstrap = { + "os2fslib", "OS/2 Video Output using FSLib", + os2fslib_Available, os2fslib_CreateDevice +}; + diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h new file mode 100644 index 0000000..6d58baf --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_os2fslib.h @@ -0,0 +1,71 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_os2fslib_h +#define _SDL_os2fslib_h + + +// OS2 specific includes +#define INCL_TYPES +#define INCL_DOS +#define INCL_DOSERRORS +#define INCL_DOSPROCESS +#define INCL_WIN +#define INCL_GPI +#include <os2.h> + +#include <FSLib.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData +{ + FSLib_VideoMode_p pAvailableFSLibVideoModes; + SDL_Rect **pListModesResult; // Allocated memory to return list of modes for os2fslib_ListModes() API + + FSLib_VideoMode SrcBufferDesc; // Description of current source image buffer + char *pchSrcBuffer; // The source image buffer itself + SDL_Surface *pSDLSurface; // The SDL surface describing the buffer + HMTX hmtxUseSrcBuffer; // Mutex semaphore to manipulate src buffer + HWND hwndFrame, hwndClient; // Window handle of frame and client + int iPMThreadStatus; // 0: Not running + // 1: Running + // Other: Not running, had an error + int tidPMThread; // Thread ID of PM Thread + int fInFocus; // True if we're in focus! + int iSkipWMMOUSEMOVE; // Number of WM_MOUSEMOVE messages to skip! + int iMouseVisible; // + + PFNWP pfnOldFrameProc; // Old window frame procedure + int bProportionalResize; // 0: No proportional resizing + // 1: Do proportional resizing + ULONG ulResizingFlag; // First resizing flag value +}; + +/* OS/2 specific backdoor function to be able to set FrameControlFlags of */ +/* the SDL window before creating it. */ +extern DECLSPEC void SDLCALL SDL_OS2FSLIB_SetFCFToUse(ULONG ulFCF); + +#endif /* _SDL_os2fslib_h */ diff --git a/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h b/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h new file mode 100644 index 0000000..79380d5 --- /dev/null +++ b/3rdparty/SDL/src/video/os2fslib/SDL_vkeys.h @@ -0,0 +1,74 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef VK_0 +#define VK_0 '0' +#define VK_1 '1' +#define VK_2 '2' +#define VK_3 '3' +#define VK_4 '4' +#define VK_5 '5' +#define VK_6 '6' +#define VK_7 '7' +#define VK_8 '8' +#define VK_9 '9' +#define VK_A 'A' +#define VK_B 'B' +#define VK_C 'C' +#define VK_D 'D' +#define VK_E 'E' +#define VK_F 'F' +#define VK_G 'G' +#define VK_H 'H' +#define VK_I 'I' +#define VK_J 'J' +#define VK_K 'K' +#define VK_L 'L' +#define VK_M 'M' +#define VK_N 'N' +#define VK_O 'O' +#define VK_P 'P' +#define VK_Q 'Q' +#define VK_R 'R' +#define VK_S 'S' +#define VK_T 'T' +#define VK_U 'U' +#define VK_V 'V' +#define VK_W 'W' +#define VK_X 'X' +#define VK_Y 'Y' +#define VK_Z 'Z' +#endif /* VK_0 */ + +/* These keys haven't been defined, but were experimentally determined */ +#define VK_SEMICOLON 0xBA +#define VK_EQUALS 0xBB +#define VK_COMMA 0xBC +#define VK_MINUS 0xBD +#define VK_PERIOD 0xBE +#define VK_SLASH 0xBF +#define VK_GRAVE 0xC0 +#define VK_LBRACKET 0xDB +#define VK_BACKSLASH 0xDC +#define VK_RBRACKET 0xDD +#define VK_APOSTROPHE 0xDE +#define VK_BACKTICK 0xDF diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_events.c b/3rdparty/SDL/src/video/photon/SDL_ph_events.c new file mode 100644 index 0000000..9b7538c --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_events.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting photon events into SDL events */ + +#include <stdio.h> +#include <setjmp.h> +#include <sys/time.h> + +#include <Ph.h> +#include <photon/PkKeyDef.h> + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_phyuv_c.h" + +/* The translation tables from a photon keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[0xFF + 1]; +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) */ +static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) +{ + PhRect_t *rect = PhGetRects( winEvent ); + + int centre_x, centre_y; + int dx, dy; + short abs_x, abs_y; + int posted; + + centre_x = SDL_VideoSurface->w / 2; + centre_y = SDL_VideoSurface->h / 2; + + dx = rect->ul.x - centre_x; + dy = rect->ul.y - centre_y; + + posted = SDL_PrivateMouseMotion( 0, 1, dx, dy ); + + /* Move mouse cursor to middle of the window */ + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + centre_x, abs_y + centre_y); + + return (posted); +} + +/* Control which motion flags the window has set, a flags value of -1 sets + * MOTION_BUTTON and MOTION_NOBUTTON */ + +static void set_motion_sensitivity(_THIS, unsigned int flags) +{ + int rid; + int fields = Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON; + PhRegion_t region; + + if( window ) + { + rid = PtWidgetRid(window); + if( rid != 0 && PhRegionQuery(rid, ®ion, NULL, NULL, 0) == 0 ) + { + region.events_sense=(region.events_sense & ~fields)|(flags & fields); + PhRegionChange(Ph_REGION_EV_SENSE, 0, ®ion, NULL, NULL); + } + } +} + +/* Convert the photon button state value to an SDL value */ +static Uint8 ph2sdl_mousebutton(unsigned short button_state) +{ + Uint8 mouse_button = 0; + + if (button_state & Ph_BUTTON_SELECT) + mouse_button |= SDL_BUTTON_LEFT; + if (button_state & Ph_BUTTON_MENU) + mouse_button |= SDL_BUTTON_RIGHT; + if (button_state & Ph_BUTTON_ADJUST) + mouse_button |= SDL_BUTTON_MIDDLE; + + return (mouse_button); +} + +static int ph_DispatchEvent(_THIS) +{ + int posted; + PhRect_t* rect; + PhPointerEvent_t* pointerEvent; + PhKeyEvent_t* keyEvent; + PhWindowEvent_t* winEvent; + int i, buttons; + SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; + + posted = 0; + + switch (phevent->type) + { + case Ph_EV_BOUNDARY: + { + if (phevent->subtype == Ph_EV_PTR_ENTER) + { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + else if (phevent->subtype ==Ph_EV_PTR_LEAVE) + { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + break; + + case Ph_EV_PTR_MOTION_BUTTON: + case Ph_EV_PTR_MOTION_NOBUTTON: + { + if (SDL_VideoSurface) + { + pointerEvent = PhGetData(phevent); + rect = PhGetRects(phevent); + + if (mouse_relative) + { + posted = ph_WarpedMotion(this, phevent); + } + else + { + posted = SDL_PrivateMouseMotion(0, 0, rect->ul.x, rect->ul.y); + } + } + } + break; + + case Ph_EV_BUT_PRESS: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, buttons, 0, 0); + } + } + break; + + case Ph_EV_BUT_RELEASE: + { + pointerEvent = PhGetData(phevent); + buttons = ph2sdl_mousebutton(pointerEvent->buttons); + if (phevent->subtype == Ph_EV_RELEASE_REAL && buttons != 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + else if(phevent->subtype == Ph_EV_RELEASE_PHANTOM) + { + /* If the mouse is outside the window, + * only a phantom release event is sent, so + * check if the window doesn't have mouse focus. + * Not perfect, maybe checking the mouse button + * state for Ph_EV_BOUNDARY events would be + * better. */ + if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) == 0) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, buttons, 0, 0); + } + } + } + break; + + case Ph_EV_WM: + { + winEvent = PhGetData(phevent); + + /* losing focus */ + if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUSLOST)) + { + set_motion_sensitivity(this, Ph_EV_PTR_MOTION_BUTTON); + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + } + /* gaining focus */ + else if ((winEvent->event_f==Ph_WM_FOCUS) && (winEvent->event_state==Ph_WM_EVSTATE_FOCUS)) + { + set_motion_sensitivity(this, -1); + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + } + /* request quit */ + else if (winEvent->event_f==Ph_WM_CLOSE) + { + posted = SDL_PrivateQuit(); + } + /* request hide/unhide */ + else if (winEvent->event_f==Ph_WM_HIDE) + { + if (currently_hided) + { + /* got unhide window event */ + /* TODO: restore application's palette if in palette mode */ + currently_hided=0; + } + else + { + /* got hide window event */ + /* TODO: restore original palette if in palette mode */ + currently_hided=1; + } + } + /* request to resize */ + else if (winEvent->event_f==Ph_WM_RESIZE) + { + currently_maximized=0; + #if (_NTO_VERSION < 630) + SDL_PrivateResize(winEvent->size.w+1, winEvent->size.h+1); + #else + /* QNX 6.3.0 have this bug fixed */ + SDL_PrivateResize(winEvent->size.w, winEvent->size.h); + #endif /* _NTO_VERSION */ + } + /* request to move */ + else if (winEvent->event_f==Ph_WM_MOVE) + { + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int chromastate=current_overlay->hwdata->ischromakey; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->ischromakey=0; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->ischromakey=chromastate; + current_overlay->hwdata->locked=lockedstate; + } + } + } + /* maximize request */ + else if (winEvent->event_f==Ph_WM_MAX) + { + /* window already moved and resized here */ + currently_maximized=1; + } + /* restore request */ + else if (winEvent->event_f==Ph_WM_RESTORE) + { + /* window already moved and resized here */ + currently_maximized=0; + } + } + break; + + /* window has been resized, moved or removed */ + case Ph_EV_EXPOSE: + { + if (phevent->num_rects!=0) + { + int numrects; + + if (SDL_VideoSurface) + { + rect = PhGetRects(phevent); + if (phevent->num_rects>PH_SDL_MAX_RECTS) + { + /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ + numrects=PH_SDL_MAX_RECTS; + } + + for(i=0; i<phevent->num_rects; i++) + { + sdlrects[i].x = rect[i].ul.x; + sdlrects[i].y = rect[i].ul.y; + sdlrects[i].w = rect[i].lr.x - rect[i].ul.x + 1; + sdlrects[i].h = rect[i].lr.y - rect[i].ul.y + 1; + } + + this->UpdateRects(this, phevent->num_rects, sdlrects); + + if (current_overlay!=NULL) + { + int lockedstate=current_overlay->hwdata->locked; + int error; + SDL_Rect src, dst; + + current_overlay->hwdata->locked=1; + src.x = 0; + src.y = 0; + src.w = current_overlay->w; + src.y = current_overlay->h; + dst.x=current_overlay->hwdata->CurrentViewPort.pos.x; + dst.y=current_overlay->hwdata->CurrentViewPort.pos.y; + dst.w=current_overlay->hwdata->CurrentViewPort.size.w; + dst.h=current_overlay->hwdata->CurrentViewPort.size.h; + current_overlay->hwdata->forcedredraw=1; + error=ph_DisplayYUVOverlay(this, current_overlay, &src, &dst); + if (!error) + { + current_overlay->hwdata->forcedredraw=0; + current_overlay->hwdata->locked=lockedstate; + } + } + } + } + } + break; + + case Ph_EV_KEY: + { + SDL_keysym keysym; + + posted = 0; + + keyEvent = PhGetData(phevent); + + if (Pk_KF_Key_Down & keyEvent->key_flags) + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_PRESSED, ph_TranslateKey(keyEvent, &keysym)); + } + else /* must be key release */ + { + /* split the wheel events from real key events */ + if ((keyEvent->key_cap==Pk_Up) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + break; + } + if ((keyEvent->key_cap==Pk_Down) && (keyEvent->key_scan==0) && ((keyEvent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)) + { + posted = SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + break; + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, ph_TranslateKey( keyEvent, &keysym)); + } + } + break; + + case Ph_EV_INFO: + { + if (phevent->subtype==Ph_OFFSCREEN_INVALID) + { + unsigned long* EvInfoData; + + EvInfoData=(unsigned long*)PhGetData(phevent); + + switch (*EvInfoData) + { + case Pg_VIDEO_MODE_SWITCHED: + { + } + break; + case Pg_ENTERED_DIRECT: + { + } + break; + case Pg_EXITED_DIRECT: + { + } + break; + case Pg_DRIVER_STARTED: + { + } + break; + } + } + } + break; + } + + return(posted); +} + +/* perform a blocking read if no events available */ +int ph_Pending(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (1) + { + switch(PhEventPeek(phevent, EVENT_SIZE)) + { + case Ph_EVENT_MSG: + return 1; + case -1: + SDL_SetError("ph_Pending(): PhEventNext failed.\n"); + return 0; + default: + return 0; + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void ph_PumpEvents(_THIS) +{ + /* Flush the display connection and look to see if events are queued */ + PgFlush(); + + while (ph_Pending(this)) + { + PtEventHandler(phevent); + ph_DispatchEvent(this); + } +} + +void ph_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for (i=0; i<SDL_arraysize(ODD_keymap); ++i) + { + ODD_keymap[i] = SDLK_UNKNOWN; + } + + /* Map the miscellaneous keys */ + for (i=0; i<SDL_arraysize(MISC_keymap); ++i) + { + MISC_keymap[i] = SDLK_UNKNOWN; + } + + MISC_keymap[Pk_BackSpace&0xFF] = SDLK_BACKSPACE; + MISC_keymap[Pk_Tab&0xFF] = SDLK_TAB; + MISC_keymap[Pk_Clear&0xFF] = SDLK_CLEAR; + MISC_keymap[Pk_Return&0xFF] = SDLK_RETURN; + MISC_keymap[Pk_Pause&0xFF] = SDLK_PAUSE; + MISC_keymap[Pk_Escape&0xFF] = SDLK_ESCAPE; + MISC_keymap[Pk_Delete&0xFF] = SDLK_DELETE; + + MISC_keymap[Pk_KP_0&0xFF] = SDLK_KP0; + MISC_keymap[Pk_KP_1&0xFF] = SDLK_KP1; + MISC_keymap[Pk_KP_2&0xFF] = SDLK_KP2; + MISC_keymap[Pk_KP_3&0xFF] = SDLK_KP3; + MISC_keymap[Pk_KP_4&0xFF] = SDLK_KP4; + MISC_keymap[Pk_KP_5&0xFF] = SDLK_KP5; + MISC_keymap[Pk_KP_6&0xFF] = SDLK_KP6; + MISC_keymap[Pk_KP_7&0xFF] = SDLK_KP7; + MISC_keymap[Pk_KP_8&0xFF] = SDLK_KP8; + MISC_keymap[Pk_KP_9&0xFF] = SDLK_KP9; + + MISC_keymap[Pk_KP_Decimal&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[Pk_KP_Divide&0xFF] = SDLK_KP_DIVIDE; + MISC_keymap[Pk_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; + MISC_keymap[Pk_KP_Subtract&0xFF] = SDLK_KP_MINUS; + MISC_keymap[Pk_KP_Add&0xFF] = SDLK_KP_PLUS; + MISC_keymap[Pk_KP_Enter&0xFF] = SDLK_KP_ENTER; + MISC_keymap[Pk_KP_Equal&0xFF] = SDLK_KP_EQUALS; + + MISC_keymap[Pk_Up&0xFF] = SDLK_UP; + MISC_keymap[Pk_Down&0xFF] = SDLK_DOWN; + MISC_keymap[Pk_Right&0xFF] = SDLK_RIGHT; + MISC_keymap[Pk_Left&0xFF] = SDLK_LEFT; + MISC_keymap[Pk_Insert&0xFF] = SDLK_INSERT; + MISC_keymap[Pk_Home&0xFF] = SDLK_HOME; + MISC_keymap[Pk_End&0xFF] = SDLK_END; + MISC_keymap[Pk_Pg_Up&0xFF] = SDLK_PAGEUP; + MISC_keymap[Pk_Pg_Down&0xFF] = SDLK_PAGEDOWN; + + MISC_keymap[Pk_F1&0xFF] = SDLK_F1; + MISC_keymap[Pk_F2&0xFF] = SDLK_F2; + MISC_keymap[Pk_F3&0xFF] = SDLK_F3; + MISC_keymap[Pk_F4&0xFF] = SDLK_F4; + MISC_keymap[Pk_F5&0xFF] = SDLK_F5; + MISC_keymap[Pk_F6&0xFF] = SDLK_F6; + MISC_keymap[Pk_F7&0xFF] = SDLK_F7; + MISC_keymap[Pk_F8&0xFF] = SDLK_F8; + MISC_keymap[Pk_F9&0xFF] = SDLK_F9; + MISC_keymap[Pk_F10&0xFF] = SDLK_F10; + MISC_keymap[Pk_F11&0xFF] = SDLK_F11; + MISC_keymap[Pk_F12&0xFF] = SDLK_F12; + MISC_keymap[Pk_F13&0xFF] = SDLK_F13; + MISC_keymap[Pk_F14&0xFF] = SDLK_F14; + MISC_keymap[Pk_F15&0xFF] = SDLK_F15; + + MISC_keymap[Pk_Num_Lock&0xFF] = SDLK_NUMLOCK; + MISC_keymap[Pk_Caps_Lock&0xFF] = SDLK_CAPSLOCK; + MISC_keymap[Pk_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; + MISC_keymap[Pk_Shift_R&0xFF] = SDLK_RSHIFT; + MISC_keymap[Pk_Shift_L&0xFF] = SDLK_LSHIFT; + MISC_keymap[Pk_Control_R&0xFF] = SDLK_RCTRL; + MISC_keymap[Pk_Control_L&0xFF] = SDLK_LCTRL; + MISC_keymap[Pk_Alt_R&0xFF] = SDLK_RALT; + MISC_keymap[Pk_Alt_L&0xFF] = SDLK_LALT; + MISC_keymap[Pk_Meta_R&0xFF] = SDLK_RMETA; + MISC_keymap[Pk_Meta_L&0xFF] = SDLK_LMETA; + MISC_keymap[Pk_Super_L&0xFF] = SDLK_LSUPER; + MISC_keymap[Pk_Super_R&0xFF] = SDLK_RSUPER; + MISC_keymap[Pk_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ + + MISC_keymap[Pk_Help&0xFF] = SDLK_HELP; + MISC_keymap[Pk_Print&0xFF] = SDLK_PRINT; + MISC_keymap[Pk_Break&0xFF] = SDLK_BREAK; + MISC_keymap[Pk_Menu&0xFF] = SDLK_MENU; /* Windows "Menu" key */ + + MISC_keymap[Pk_Hyper_R&0xFF] = SDLK_RSUPER; /* Right "Windows" */ + + /* Left "Windows" key, but it can't be catched by application */ + MISC_keymap[Pk_Hyper_L&0xFF] = SDLK_LSUPER; +} + +static unsigned long cap; + +SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym) +{ + /* 'sym' is set to the value of the key with modifiers applied to it. + This member is valid only if Pk_KF_Sym_Valid is set in the key_flags. + We will assume it is valid. */ + + /* FIXME: This needs to check whether the cap & scancode is valid */ + + cap = key->key_cap; + + switch (cap>>8) + { + case 0x00: /* Latin 1 */ + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + keysym->sym = (SDLKey)(cap&0xFF); + /* Map capital letter syms to lowercase */ + if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z')) + keysym->sym += ('a'-'A'); + break; + case 0xF0: + keysym->sym = MISC_keymap[cap&0xFF]; + break; + default: + keysym->sym = SDLK_UNKNOWN; + break; + } + + keysym->scancode = key->key_scan; + keysym->unicode = 0; + + if (SDL_TranslateUNICODE) + { + char utf8[MB_CUR_MAX]; + int utf8len; + wchar_t unicode; + + switch (keysym->scancode) + { + /* Esc key */ + case 0x01: keysym->unicode = 27; + break; + /* BackSpace key */ + case 0x0E: keysym->unicode = 127; + break; + /* Enter key */ + case 0x1C: keysym->unicode = 10; + break; + default: + utf8len = PhKeyToMb(utf8, key); + if (utf8len > 0) + { + utf8len = mbtowc(&unicode, utf8, utf8len); + if (utf8len > 0) + { + keysym->unicode = unicode; + } + } + break; + } + + } + + return (keysym); +} + +void ph_InitOSKeymap(_THIS) +{ + ph_InitKeymap(); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h new file mode 100644 index 0000000..4aa939b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_events_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_EVENTS_H__ +#define __SDL_PH_EVENTS_H__ + +#include "SDL_ph_video.h" + +#define PH_SDL_MAX_RECTS 256 +#define PH_EVENT_SAFETY_POOL 512 +#define EVENT_SIZE (sizeof(PhEvent_t) + 1000 + PH_EVENT_SAFETY_POOL) + +/* Functions to be exported */ +extern void ph_InitOSKeymap(_THIS); +extern void ph_PumpEvents(_THIS); + +#endif /* __SDL_PH_EVENTS_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_gl.c b/3rdparty/SDL/src/video/photon/SDL_ph_gl.c new file mode 100644 index 0000000..3121777 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_gl.c @@ -0,0 +1,406 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <dlfcn.h> +#include "SDL.h" +#include "SDL_ph_gl.h" + +#if SDL_VIDEO_OPENGL + +#if (_NTO_VERSION >= 630) + /* PhotonGL functions */ + GLPH_DECLARE_FUNCS; +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void ph_GL_SwapBuffers(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + PdOpenGLContextSwapBuffers(oglctx); +} +#else +void ph_GL_SwapBuffers(_THIS) +{ + qnxgl_swap_buffers(oglbuffers); +} +#endif /* 6.3.0 */ + +int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + switch (attrib) + { + case SDL_GL_DOUBLEBUFFER: + *value=this->gl_config.double_buffer; + break; + case SDL_GL_STENCIL_SIZE: + *value=this->gl_config.stencil_size; + break; + case SDL_GL_DEPTH_SIZE: + *value=this->gl_config.depth_size; + break; +#if (_NTO_VERSION >= 630) + case SDL_GL_RED_SIZE: + *value=this->gl_config.red_size; + break; + case SDL_GL_GREEN_SIZE: + *value=this->gl_config.green_size; + break; + case SDL_GL_BLUE_SIZE: + *value=this->gl_config.blue_size; + break; + case SDL_GL_ALPHA_SIZE: + *value=this->gl_config.alpha_size; + break; + case SDL_GL_ACCUM_RED_SIZE: + *value=this->gl_config.accum_red_size; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + *value=this->gl_config.accum_green_size; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + *value=this->gl_config.accum_blue_size; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + *value=this->gl_config.accum_alpha_size; + break; + case SDL_GL_STEREO: + *value=this->gl_config.stereo; + break; +#endif /* 6.3.0 */ + default: + *value=0; + return(-1); + } + return 0; +} + +#if (_NTO_VERSION < 630) +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + /* if code compiled with SDL_VIDEO_OPENGL, that mean that library already linked */ + this->gl_config.driver_loaded = 1; + + return 0; +} +#else +int ph_GL_LoadLibrary(_THIS, const char* path) +{ + void* handle; + int dlopen_flags=RTLD_WORLD | RTLD_GROUP; + + if (this->gl_config.dll_handle!=NULL) + { + return 0; + } + + handle = dlopen(path, dlopen_flags); + + if (handle==NULL) + { + SDL_SetError("ph_GL_LoadLibrary(): Could not load OpenGL library"); + return -1; + } + + this->gl_config.dll_handle = handle; + this->gl_config.driver_loaded = 1; + + SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + return NULL; +} +#else +void* ph_GL_GetProcAddress(_THIS, const char* proc) +{ + void* function; + + if (this->gl_config.dll_handle==NULL) + { + ph_GL_LoadLibrary(this, DEFAULT_OPENGL); + if (this->gl_config.dll_handle==NULL) + { + return NULL; + } + } + + function=qnxgl_get_func(proc, oglctx, 0); + if (function==NULL) + { + function=dlsym(this->gl_config.dll_handle, proc); + } + + return function; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + PhDCSetCurrent(oglctx); + } + + return 0; +} +#else +int ph_GL_MakeCurrent(_THIS) +{ + PgSetRegion(PtWidgetRid(window)); + + if (oglctx!=NULL) + { + if (qnxgl_set_current(oglctx) == -1) + { + return -1; + } + } + + return 0; +} +#endif /* 6.3.0 */ + +#if (_NTO_VERSION < 630) + +/* This code is actual for the Photon3D Runtime which was available prior to 6.3 only */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + PhDim_t dim; + uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS]; + int exposepost=0; + int OGLargc; + + dim.w=width; + dim.h=height; + + if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp)) + { + PdOpenGLContextResize(oglctx, &dim); + PhDCSetCurrent(oglctx); + return 0; + } + else + { + if (oglctx!=NULL) + { + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + oglctx=NULL; + exposepost=1; + } + } + + OGLargc=0; + if (this->gl_config.depth_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS; + OGLAttrib[OGLargc++]=this->gl_config.depth_size; + } + if (this->gl_config.stencil_size) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS; + OGLAttrib[OGLargc++]=this->gl_config.stencil_size; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW; + if (flags & SDL_FULLSCREEN) + { + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST; + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER; + } + OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE; + + if (this->gl_config.double_buffer) + { + oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib); + } + else + { + oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib); + } + + if (oglctx==NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n"); + return -1; + } + + PhDCSetCurrent(oglctx); + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + if (exposepost!=0) + { + /* OpenGL context has been recreated, so report about this fact */ + SDL_PrivateExpose(); + } + + return 0; +} + +#else /* _NTO_VERSION */ + +/* This code is actual for the built-in PhGL support, which became available since 6.3 */ + +int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) +{ + qnxgl_buf_attrib_t qnxgl_attribs[PH_OGL_MAX_ATTRIBS]; + qnxgl_buf_attrib_t* qnxgl_attribs_slide; + int num_interfaces = 0; + int num_buffers = 0; + + /* Initialize the OpenGL subsystem */ + + num_interfaces = qnxgl_init(NULL, NULL, 0); + + if (num_interfaces < 0) + { + SDL_SetError("ph_SetupOpenGLContext(): cannot initialize OpenGL subsystem !\n"); + return -1; + } + if (num_interfaces == 0) + { + SDL_SetError("ph_SetupOpenGLContext(): there are no available OpenGL renderers was found !\n"); + return -1; + } + + /* Driver is linked */ + this->gl_config.driver_loaded=1; + + /* Initialize the OpenGL context attributes */ + qnxgl_attribs_slide=qnxgl_attribs; + + /* Depth size */ + if (this->gl_config.depth_size) + { + fprintf(stderr, "setted depth size %d\n", this->gl_config.depth_size); + qnxgl_attribs_slide = qnxgl_attrib_set_depth(qnxgl_attribs_slide, this->gl_config.depth_size); + } + + /* Stencil size */ + if (this->gl_config.stencil_size) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stencil(qnxgl_attribs_slide, this->gl_config.stencil_size); + } + + /* The sum of the accum bits of each channel */ + if ((this->gl_config.accum_red_size != 0) && (this->gl_config.accum_blue_size != 0) && + (this->gl_config.accum_green_size != 0)) + { + qnxgl_attribs_slide = qnxgl_attrib_set_accum(qnxgl_attribs_slide, + this->gl_config.accum_red_size + this->gl_config.accum_blue_size + + this->gl_config.accum_green_size + this->gl_config.accum_alpha_size); + } + + /* Stereo mode */ + if (this->gl_config.stereo) + { + qnxgl_attribs_slide = qnxgl_attrib_set_stereo(qnxgl_attribs_slide); + } + + /* Fullscreen mode */ + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + qnxgl_attribs_slide = qnxgl_attrib_set_hint_fullscreen(qnxgl_attribs_slide); + } + + /* Double buffering mode */ + if (this->gl_config.double_buffer) + { + num_buffers=2; + } + else + { + num_buffers=1; + } + + /* Loading the function pointers so we can use the extensions */ + GLPH_LOAD_FUNCS_GC(oglctx); + + /* Set the buffers region to be that of our window's region */ + qnxgl_attribs_slide = glph_attrib_set_region(qnxgl_attribs_slide, PtWidgetRid(window)); + + /* End of the attributes array */ + qnxgl_attribs_slide = qnxgl_attrib_set_end(qnxgl_attribs_slide); + + /* Create the buffers with the specified color model */ + fprintf(stderr, "ARGB: %d, %d, %d, %d\n", this->gl_config.alpha_size, this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size); + oglbuffers = qnxgl_buffers_create( + QNXGL_FORMAT_BEST_RGB, +/* __QNXGL_BUILD_FORMAT(0, __QNXGL_COLOR_MODEL_RGB, this->gl_config.alpha_size, + this->gl_config.red_size, this->gl_config.green_size, this->gl_config.blue_size), */ + num_buffers, width, height, qnxgl_attribs, -1); + + + if (oglbuffers == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL buffers !\n"); + qnxgl_finish(); + return -1; + } + + /* Create a QNXGL context for the previously created buffer */ + oglctx = qnxgl_context_create(oglbuffers, NULL); + + if (oglctx == NULL) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to create OpenGL context !\n"); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + /* Attempt to make the context current so we can use OpenGL commands */ + if (qnxgl_set_current(oglctx) == -1) + { + SDL_SetError("ph_SetupOpenGLContext(): failed to make the OpenGL context current !\n"); + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + return -1; + } + + PtFlush(); + + oglflags=flags; + oglbpp=bpp; + + return 0; +} + +#endif /* _NTO_VERSION */ + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_gl.h b/3rdparty/SDL/src/video/photon/SDL_ph_gl.h new file mode 100644 index 0000000..1fb134a --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_gl.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_GL_H__ +#define __SDL_PH_GL_H__ + +#include "SDL_ph_video.h" + +#define DEFAULT_OPENGL "/usr/lib/libGL.so" + +#if SDL_VIDEO_OPENGL + void ph_GL_SwapBuffers(_THIS); + int ph_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); + int ph_GL_LoadLibrary(_THIS, const char* path); + void* ph_GL_GetProcAddress(_THIS, const char* proc); + int ph_GL_MakeCurrent(_THIS); + + int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags); +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_GL_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_image.c b/3rdparty/SDL/src/video/photon/SDL_ph_image.c new file mode 100644 index 0000000..7d64970 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_image.c @@ -0,0 +1,1059 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <Ph.h> +#include <photon/Pg.h> + +#include "SDL_endian.h" +#include "SDL_video.h" +#include "../SDL_pixels_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_gl.h" + +int ph_SetupImage(_THIS, SDL_Surface *screen) +{ + PgColor_t* palette=NULL; + int type=0; + int bpp; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8:{ + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* palette emulation code */ + if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE)) + { + /* creating image palette */ + palette=SDL_malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t)); + if (palette==NULL) + { + SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n"); + return -1; + } + PgGetPalette(palette); + + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n"); + SDL_free(palette); + return -1; + } + } + else + { + /* using shared memory for speed (set last param to 1) */ + if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL) + { + SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp); + return -1; + } + } + + screen->pixels = SDL_Image->image; + screen->pitch = SDL_Image->bpl; + + this->UpdateRects = ph_NormalUpdate; + + return 0; +} + +int ph_SetupOCImage(_THIS, SDL_Surface *screen) +{ + int type = 0; + int bpp; + + OCImage.flags = screen->flags; + + bpp=screen->format->BitsPerPixel; + + /* Determine image type */ + switch(bpp) + { + case 8: { + type = Pg_IMAGE_PALETTE_BYTE; + } + break; + case 15:{ + type = Pg_IMAGE_DIRECT_555; + } + break; + case 16:{ + type = Pg_IMAGE_DIRECT_565; + } + break; + case 24:{ + type = Pg_IMAGE_DIRECT_888; + } + break; + case 32:{ + type = Pg_IMAGE_DIRECT_8888; + } + break; + default:{ + SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp); + return -1; + } + break; + } + + /* Currently offscreen contexts with the same bit depth as display bpp only can be created */ + OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN); + + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + screen->pitch = OCImage.offscreen_context->pitch; + + OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + + if (OCImage.dc_ptr == NULL) + { + SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n"); + PhDCRelease(OCImage.offscreen_context); + return -1; + } + + OCImage.FrameData0 = OCImage.dc_ptr; + OCImage.CurrentFrameData = OCImage.FrameData0; + OCImage.current = 0; + + PhDCSetCurrent(OCImage.offscreen_context); + + screen->pixels = OCImage.CurrentFrameData; + + this->UpdateRects = ph_OCUpdate; + + return 0; +} + +int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) +{ + OCImage.flags = screen->flags; + + /* Begin direct and fullscreen mode */ + if (!ph_EnterFullScreen(this, screen, PH_ENTER_DIRECTMODE)) + { + return -1; + } + + /* store palette for fullscreen */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + + OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_context == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); + if (OCImage.offscreen_backcontext == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n"); + return -1; + } + } + + OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); + if (OCImage.FrameData0 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext); + if (OCImage.FrameData1 == NULL) + { + SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n"); + ph_DestroyImage(this, screen); + return -1; + } + } + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + PgSwapDisplay(OCImage.offscreen_backcontext, 0); + } + else + { + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + SDL_memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + } + + this->UpdateRects = ph_OCDCUpdate; + + /* wait for the hardware */ + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +#if SDL_VIDEO_OPENGL + +int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) +{ + this->UpdateRects = ph_OpenGLUpdate; + screen->pixels=NULL; + screen->pitch=NULL; + + #if (_NTO_VERSION >= 630) + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (!ph_EnterFullScreen(this, screen, PH_IGNORE_DIRECTMODE)) + { + screen->flags &= ~SDL_FULLSCREEN; + return -1; + } + } + #endif /* 6.3.0 */ + + if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) + { + screen->flags &= ~SDL_OPENGL; + return -1; + } + + return 0; +} + +#endif /* SDL_VIDEO_OPENGL */ + +void ph_DestroyImage(_THIS, SDL_Surface* screen) +{ + +#if SDL_VIDEO_OPENGL + if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) + { + if (oglctx) + { + #if (_NTO_VERSION < 630) + PhDCSetCurrent(NULL); + PhDCRelease(oglctx); + #else + qnxgl_context_destroy(oglctx); + qnxgl_buffers_destroy(oglbuffers); + qnxgl_finish(); + #endif /* 6.3.0 */ + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; + } + + #if (_NTO_VERSION >= 630) + if (currently_fullscreen) + { + ph_LeaveFullScreen(this); + } + #endif /* 6.3.0 */ + + return; + } +#endif /* SDL_VIDEO_OPENGL */ + + if (currently_fullscreen) + { + /* if we right now in 8bpp fullscreen we must release palette */ + if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + ph_LeaveFullScreen(this); + } + + if (OCImage.offscreen_context != NULL) + { + PhDCRelease(OCImage.offscreen_context); + OCImage.offscreen_context = NULL; + OCImage.FrameData0 = NULL; + } + if (OCImage.offscreen_backcontext != NULL) + { + PhDCRelease(OCImage.offscreen_backcontext); + OCImage.offscreen_backcontext = NULL; + OCImage.FrameData1 = NULL; + } + OCImage.CurrentFrameData = NULL; + + if (SDL_Image) + { + /* if palette allocated, free it */ + if (SDL_Image->palette) + { + SDL_free(SDL_Image->palette); + } + PgShmemDestroy(SDL_Image->image); + SDL_free(SDL_Image); + } + + /* Must be zeroed everytime */ + SDL_Image = NULL; + + if (screen) + { + screen->pixels = NULL; + } +} + +int ph_UpdateHWInfo(_THIS) +{ + PgVideoModeInfo_t vmode; + PgHWCaps_t hwcaps; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + /* obtain current mode capabilities */ + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n"); + return -1; + } + + if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN) + { + /* this is a special test for drivers which tries to lie about offscreen capability */ + if (hwcaps.currently_available_video_ram!=0) + { + this->info.hw_available = 1; + } + else + { + this->info.hw_available = 0; + } + } + else + { + this->info.hw_available = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE) + { + this->info.blit_fill = 1; + } + else + { + this->info.blit_fill = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT) + { + this->info.blit_hw = 1; + } + else + { + this->info.blit_hw = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND) + { + this->info.blit_hw_A = 1; + } + else + { + this->info.blit_hw_A = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA) + { + this->info.blit_hw_CC = 1; + } + else + { + this->info.blit_hw_CC = 0; + } + + return 0; +} + +int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) +{ + int setupresult=-1; + + ph_DestroyImage(this, screen); + +#if SDL_VIDEO_OPENGL + if ((flags & SDL_OPENGL)==SDL_OPENGL) + { + setupresult=ph_SetupOpenGLImage(this, screen); + } + else + { +#endif + if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) + { + setupresult=ph_SetupFullScreenImage(this, screen); + } + else + { + if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) + { + setupresult=ph_SetupOCImage(this, screen); + } + else + { + setupresult=ph_SetupImage(this, screen); + } + } +#if SDL_VIDEO_OPENGL + } +#endif + if (setupresult!=-1) + { + ph_UpdateHWInfo(this); + } + + return setupresult; +} + +int ph_AllocHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata!=NULL) + { + SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n"); + return -1; + } + surface->hwdata=SDL_malloc(sizeof(struct private_hwdata)); + SDL_memset(surface->hwdata, 0x00, sizeof(struct private_hwdata)); + surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN); + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx); + if (surface->pixels==NULL) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n"); + return -1; + } + surface->pitch=surface->hwdata->offscreenctx->pitch; + surface->flags|=SDL_HWSURFACE; + surface->flags|=SDL_PREALLOC; + +#if 0 /* FIXME */ + /* create simple offscreen lock */ + surface->hwdata->crlockparam.flags=0; + if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n"); + return -1; + } +#endif /* 0 */ + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return 0; +} + +void ph_FreeHWSurface(_THIS, SDL_Surface* surface) +{ + PgHWCaps_t hwcaps; + + if (surface->hwdata==NULL) + { + SDL_SetError("ph_FreeHWSurface(): no hwdata!\n"); + return; + } + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n"); + return; + } + +#if 0 /* FIXME */ + /* unlock the offscreen context if it has been locked before destroy it */ + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + PdUnlockOffscreen(surface->hwdata->offscreenctx); + } + + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); +#endif /* 0 */ + + PhDCRelease(surface->hwdata->offscreenctx); + + SDL_free(surface->hwdata); + surface->hwdata=NULL; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return; +} + +int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if ((src->hwdata==NULL) && (src != this->screen)) + { + SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE) + { + SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + if (this->info.blit_hw_CC!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + if (this->info.blit_hw_A!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + src->flags|=SDL_HWACCEL; + src->map->hw_blit = ph_HWAccelBlit; + + return 1; +} + +PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color) +{ + Uint32 truecolor; + + /* Photon API accepts true colors only during hw filling operations */ + switch(surface->format->BitsPerPixel) + { + case 8: + { + if ((surface->format->palette) && (color<=surface->format->palette->ncolors)) + { + truecolor=PgRGB(surface->format->palette->colors[color].r, + surface->format->palette->colors[color].g, + surface->format->palette->colors[color].b); + } + else + { + SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n"); + return 0xFFFFFFFFUL; + } + } + break; + case 15: + { + truecolor = ((color & 0x00007C00UL) << 9) | /* R */ + ((color & 0x000003E0UL) << 6) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x00007000UL) << 4) | /* R compensation */ + ((color & 0x00000380UL) << 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + } + break; + case 16: + { + truecolor = ((color & 0x0000F800UL) << 8) | /* R */ + ((color & 0x000007E0UL) << 5) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x0000E000UL) << 3) | /* R compensation */ + ((color & 0x00000600UL) >> 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + + } + break; + case 24: + { + truecolor=color & 0x00FFFFFFUL; + } + break; + case 32: + { + truecolor=color; + } + break; + default: + { + SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n"); + return 0xFFFFFFFFUL; + } + } + + return truecolor; +} + +int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color) +{ + PgColor_t oldcolor; + Uint32 truecolor; + int ydisp=0; + + if (this->info.blit_fill!=1) + { + return -1; + } + + truecolor=ph_ExpandColor(this, surface, color); + if (truecolor==0xFFFFFFFFUL) + { + return -1; + } + + oldcolor=PgSetFillColor(truecolor); + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL); + PgSetFillColor(oldcolor); + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_FlipHWSurface(_THIS, SDL_Surface* screen) +{ + PhArea_t farea; + + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* flush all drawing ops before blitting */ + PgFlush(); + PgWaitHWIdle(); + + farea.pos.x=0; + farea.pos.y=0; + farea.size.w=screen->w; + farea.size.h=screen->h; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + farea.pos.y+=40; + } + + PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea); + + /* flush the blitting */ + PgFlush(); + PgWaitHWIdle(); + } + return 0; +} + +int ph_LockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int lockresult; + + if (surface->hwdata == NULL) + { + return; + } + + surface->hwdata->lockparam.flags=0; + surface->hwdata->lockparam.time_out=NULL; + lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam); + + switch (lockresult) + { + case EOK: + break; + case Pg_OSC_LOCK_DEADLOCK: + SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n"); + return -1; + case Pg_OSC_LOCK_INVALID: + SDL_SetError("ph_LockHWSurface(): Lock invalid !\n"); + return -1; + default: + SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n"); + return -1; + } +#endif /* 0 */ + + return 0; +} + +void ph_UnlockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int unlockresult; + + if ((surface == NULL) || (surface->hwdata == NULL)) + { + return; + } + + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx); + } +#endif /* 0 */ + + return; +} + +int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) +{ + SDL_VideoDevice* this=current_video; + PhArea_t srcarea; + PhArea_t dstarea; + int ydisp=0; + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + srcarea.pos.x=srcrect->x; + srcarea.pos.y=srcrect->y; + srcarea.size.w=srcrect->w; + srcarea.size.h=srcrect->h; + + dstarea.pos.x=dstrect->x; + dstarea.pos.y=dstrect->y; + dstarea.size.w=dstrect->w; + dstarea.size.h=dstrect->h; + + if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL))) + { + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + ph_SetHWColorKey(this, src, src->format->colorkey); + PgChromaOn(); + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + ph_SetHWAlpha(this, src, src->format->alpha); + PgAlphaOn(); + } + + if (dst == this->screen) + { + if (src == this->screen) + { + /* blitting from main screen to main screen */ + dstarea.pos.y+=ydisp; + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea); + } + else + { + /* blitting from offscreen to main screen */ + dstarea.pos.y+=ydisp; + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea); + } + } + else + { + if (src == this->screen) + { + /* blitting from main screen to offscreen */ + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + else + { + /* blitting offscreen to offscreen */ + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + PgAlphaOff(); + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + PgChromaOff(); + } + } + else + { + SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n"); + return -1; + } + + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + +int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + if (this->info.blit_hw_CC!=1) + { + return -1; + } + + if (surface->hwdata!=NULL) + { + surface->hwdata->colorkey=ph_ExpandColor(this, surface, key); + if (surface->hwdata->colorkey==0xFFFFFFFFUL) + { + return -1; + } + } + PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); + + return 0; +} + +int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) +{ + if (this->info.blit_hw_A!=1) + { + return -1; + } + + PgSetAlphaBlend(NULL, alpha); + + return 0; +} + +#if SDL_VIDEO_OPENGL +void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects) +{ + this->GL_SwapBuffers(this); + + return; +} +#endif /* SDL_VIDEO_OPENGL */ + +void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + PhPoint_t ph_pos; + PhRect_t ph_rect; + int i; + + for (i=0; i<numrects; ++i) + { + if (rects[i].w==0) /* Clipped? dunno why but this occurs sometime. */ + { + continue; + } + + if (rects[i].h==0) /* Clipped? dunno why but this occurs sometime. */ + { + continue; + } + + ph_pos.x = rects[i].x; + ph_pos.y = rects[i].y; + ph_rect.ul.x = rects[i].x; + ph_rect.ul.y = rects[i].y; + ph_rect.lr.x = rects[i].x + rects[i].w; + ph_rect.lr.y = rects[i].y + rects[i].h; + + if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0) + { + SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed!\n"); + return; + } + } + + if (PgFlush() < 0) + { + SDL_SetError("ph_NormalUpdate(): PgFlush() function failed!\n"); + } +} + +void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + PhPoint_t zero = {0, 0}; + PhArea_t src_rect; + PhArea_t dest_rect; + + PgSetTranslation(&zero, 0); + PgSetRegion(PtWidgetRid(window)); + PgSetClipping(0, NULL); + + PgFlush(); + PgWaitHWIdle(); + + for (i=0; i<numrects; ++i) + { + if (rects[i].w == 0) /* Clipped? */ + { + continue; + } + + if (rects[i].h == 0) /* Clipped? */ + { + continue; + } + + src_rect.pos.x=rects[i].x; + src_rect.pos.y=rects[i].y; + dest_rect.pos.x=rects[i].x; + dest_rect.pos.y=rects[i].y; + + src_rect.size.w=rects[i].w; + src_rect.size.h=rects[i].h; + dest_rect.size.w=rects[i].w; + dest_rect.size.h=rects[i].h; + + PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect); + } + + if (PgFlush() < 0) + { + SDL_SetError("ph_OCUpdate(): PgFlush failed.\n"); + } +} + +void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + PgWaitHWIdle(); + + if (PgFlush() < 0) + { + SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n"); + } +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h new file mode 100644 index 0000000..cfd9669 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_image_c.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_IMAGE_H__ +#define __SDL_PH_IMAGE_H__ + +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" + +struct private_hwdata +{ + PdOffscreenContext_t* offscreenctx; + PdOSCCreateLockParams_t crlockparam; + PdOSCLockParams_t lockparam; + Uint32 colorkey; +}; + +extern int ph_SetupImage(_THIS, SDL_Surface* screen); +extern void ph_DestroyImage(_THIS, SDL_Surface* screen); +extern int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags); + +extern int ph_AllocHWSurface(_THIS, SDL_Surface* surface); +extern void ph_FreeHWSurface(_THIS, SDL_Surface* surface); +extern int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +extern int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color); +extern int ph_LockHWSurface(_THIS, SDL_Surface* surface); +extern void ph_UnlockHWSurface(_THIS, SDL_Surface* surface); +extern int ph_FlipHWSurface(_THIS, SDL_Surface* surface); +extern int ph_SetHWColorKey(_THIS, SDL_Surface* surface, Uint32 key); +extern int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha); +extern int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect *srcrect, SDL_Surface* dst, SDL_Rect* dstrect); +extern int ph_UpdateHWInfo(_THIS); + +extern void ph_NormalUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OCUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect* rects); +extern void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects); + +#endif /* __SDL_PH_IMAGE_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_modes.c b/3rdparty/SDL/src/video/photon/SDL_ph_modes.c new file mode 100644 index 0000000..8c2bf7e --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_modes.c @@ -0,0 +1,390 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_ph_modes_c.h" + +static PgVideoModeInfo_t mode_info; +static PgVideoModes_t mode_list; + +/* The current list of available video modes */ +SDL_Rect SDL_modelist[PH_MAX_VIDEOMODES]; +SDL_Rect* SDL_modearray[PH_MAX_VIDEOMODES]; + +static int compare_modes_by_res(const void* mode1, const void* mode2) +{ + PgVideoModeInfo_t mode1_info; + PgVideoModeInfo_t mode2_info; + + if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode1_info) < 0) + { + return 0; + } + + if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode2_info) < 0) + { + return 0; + } + + if (mode1_info.width == mode2_info.width) + { + return mode2_info.height - mode1_info.height; + } + else + { + return mode2_info.width - mode1_info.width; + } +} + +SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int i = 0; + int j = 0; + SDL_Rect Amodelist[PH_MAX_VIDEOMODES]; + + for (i=0; i<PH_MAX_VIDEOMODES; i++) + { + SDL_modearray[i]=&SDL_modelist[i]; + } + + if (PgGetVideoModeList(&mode_list) < 0) + { + SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n"); + return NULL; + } + + mode_info.bits_per_pixel = 0; + + for (i=0; i < mode_list.num_modes; i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]); + return NULL; + } + if(mode_info.bits_per_pixel == format->BitsPerPixel) + { + Amodelist[j].w = mode_info.width; + Amodelist[j].h = mode_info.height; + Amodelist[j].x = 0; + Amodelist[j].y = 0; + j++; + } + } + + /* reorder biggest for smallest, assume width dominates */ + + for(i=0; i<j; i++) + { + SDL_modelist[i].w = Amodelist[j - i - 1].w; + SDL_modelist[i].h = Amodelist[j - i - 1].h; + SDL_modelist[i].x = Amodelist[j - i - 1].x; + SDL_modelist[i].y = Amodelist[j - i - 1].y; + } + SDL_modearray[j]=NULL; + + return SDL_modearray; +} + +void ph_FreeVideoModes(_THIS) +{ + return; +} + +/* return the mode associated with width, height and bpp */ +/* if there is no mode then zero is returned */ +int ph_GetVideoMode(int width, int height, int bpp) +{ + int i; + int modestage=0; + int closestmode=0; + + if (PgGetVideoModeList(&mode_list) < 0) + { + return -1; + } + + /* special case for the double-sized 320x200 mode */ + if ((width==640) && (height==400)) + { + modestage=1; + } + + /* search list for exact match */ + for (i=0; i<mode_list.num_modes; i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + + if ((mode_info.width == width) && (mode_info.height == height) && + (mode_info.bits_per_pixel == bpp)) + { + return mode_list.modes[i]; + } + else + { + if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && + (mode_info.bits_per_pixel == bpp)) + { + modestage=2; + closestmode=mode_list.modes[i]; + } + } + } + + /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */ + if (modestage==2) + { + return closestmode; + } + + return (i == mode_list.num_modes) ? 0 : mode_list.modes[i]; +} + +/* return the mode associated with width, height and bpp */ +/* if requested bpp is not found the mode with closest bpp is returned */ +int get_mode_any_format(int width, int height, int bpp) +{ + int i, closest, delta, min_delta; + + if (PgGetVideoModeList(&mode_list) < 0) + { + return -1; + } + + SDL_qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res); + + for(i=0;i<mode_list.num_modes;i++) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + if ((mode_info.width == width) && (mode_info.height == height)) + { + break; + } + } + + if (i<mode_list.num_modes) + { + /* get closest bpp */ + closest = i++; + if (mode_info.bits_per_pixel == bpp) + { + return mode_list.modes[closest]; + } + + min_delta = abs(mode_info.bits_per_pixel - bpp); + + while(1) + { + if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) + { + return 0; + } + + if ((mode_info.width != width) || (mode_info.height != height)) + { + break; + } + else + { + if (mode_info.bits_per_pixel == bpp) + { + closest = i; + break; + } + else + { + delta = abs(mode_info.bits_per_pixel - bpp); + if (delta < min_delta) + { + closest = i; + min_delta = delta; + } + i++; + } + } + } + return mode_list.modes[closest]; + } + + return 0; +} + +int ph_ToggleFullScreen(_THIS, int on) +{ + return -1; +} + +int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode) +{ + PgDisplaySettings_t settings; + int mode; + char* refreshrate; + int refreshratenum; + + if (!currently_fullscreen) + { + /* Get the video mode and set it */ + if (screen->flags & SDL_ANYFORMAT) + { + if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + } + else + { + if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) + { + SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); + return 0; + } + if (PgGetVideoModeInfo(mode, &mode_info) < 0) + { + SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n"); + return 0; + } + if (mode_info.height != screen->h) + { + if ((mode_info.height==480) && (screen->h==400)) + { + videomode_emulatemode=1; + } + } + else + { + videomode_emulatemode=0; + } + } + + /* save old video mode caps */ + PgGetVideoMode(&settings); + old_video_mode=settings.mode; + old_refresh_rate=settings.refresh; + + /* setup new video mode */ + settings.mode = mode; + settings.refresh = 0; + settings.flags = 0; + + refreshrate=SDL_getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); + if (refreshrate!=NULL) + { + if (SDL_sscanf(refreshrate, "%d", &refreshratenum)==1) + { + settings.refresh = refreshratenum; + } + } + + if (PgSetVideoMode(&settings) < 0) + { + SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); + return 0; + } + + if (this->screen) + { + if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; /* 6.3.0 */ +#endif + } + } + + if (fmode==0) + { + if (OCImage.direct_context==NULL) + { + OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext(); + if (!OCImage.direct_context) + { + SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n"); + ph_LeaveFullScreen(this); + return 0; + } + } + OCImage.oldDC=PdDirectStart(OCImage.direct_context); + } + + currently_fullscreen = 1; + } + PgFlush(); + + return 1; +} + +int ph_LeaveFullScreen(_THIS) +{ + PgDisplaySettings_t oldmode_settings; + + if (currently_fullscreen) + { + if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) + { +#if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) + return 0; +#endif + } + + /* release routines starts here */ + { + if (OCImage.direct_context) + { + PdDirectStop(OCImage.direct_context); + PdReleaseDirectContext(OCImage.direct_context); + OCImage.direct_context=NULL; + } + if (OCImage.oldDC) + { + PhDCSetCurrent(OCImage.oldDC); + OCImage.oldDC=NULL; + } + + currently_fullscreen=0; + + /* Restore old video mode */ + if (old_video_mode != -1) + { + oldmode_settings.mode = (unsigned short) old_video_mode; + oldmode_settings.refresh = (unsigned short) old_refresh_rate; + oldmode_settings.flags = 0; + + if (PgSetVideoMode(&oldmode_settings) < 0) + { + SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n"); + return 0; + } + } + + old_video_mode=-1; + old_refresh_rate=-1; + } + } + return 1; +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h new file mode 100644 index 0000000..117c5a3 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_modes_c.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MODES_H__ +#define __SDL_PH_MODES_H__ + +#include "SDL_ph_video.h" + +#define PH_MAX_VIDEOMODES 127 + +#define PH_ENTER_DIRECTMODE 0 +#define PH_IGNORE_DIRECTMODE 1 + +extern SDL_Rect **ph_ListModes(_THIS,SDL_PixelFormat *format, Uint32 flags); +extern void ph_FreeVideoModes(_THIS); +extern int ph_ResizeFullScreen(_THIS); +extern int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode); +extern int ph_LeaveFullScreen(_THIS); +extern int ph_GetVideoMode(int width, int height, int bpp); +extern int get_mode_any_format(int width, int height, int bpp); +extern int ph_ToggleFullScreen(_THIS, int on); + +#endif /* __SDL_PH_MODES_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c b/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c new file mode 100644 index 0000000..a25aa1f --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_mouse.c @@ -0,0 +1,220 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_ph_mouse_c.h" + +struct WMcursor +{ + PhCursorDef_t *ph_cursor ; +}; + +void ph_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if (window != NULL) + { + SDL_Lock_EventThread(); + + if (PtSetResource(window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_INHERIT, 0) < 0) + { + /* TODO: output error msg */ + } + + SDL_Unlock_EventThread(); + } + + SDL_free(cursor); +} + +WMcursor *ph_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor* cursor; + int clen, i; + unsigned char bit, databit, maskbit; + + /* Allocate and initialize the cursor memory */ + if ((cursor = (WMcursor*)SDL_malloc(sizeof(WMcursor))) == NULL) + { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(cursor,0,sizeof(WMcursor)); + + cursor->ph_cursor = (PhCursorDef_t *) SDL_malloc(sizeof(PhCursorDef_t) + 32*4*2); + + if (cursor->ph_cursor == NULL) + { + SDL_SetError("ph_CreateWMCursor(): cursor malloc failed !\n"); + return NULL; + } + + SDL_memset(cursor->ph_cursor,0,(sizeof(PhCursorDef_t) + 32*4*2)); + + cursor->ph_cursor->hdr.type =Ph_RDATA_CURSOR; + cursor->ph_cursor->size1.x = (short)w; + cursor->ph_cursor->size1.y = (short)h; + cursor->ph_cursor->offset1.x = (short)hot_x; + cursor->ph_cursor->offset1.y = (short)hot_y; + cursor->ph_cursor->bytesperline1 = (char)w/8; + cursor->ph_cursor->color1 = Pg_WHITE; + cursor->ph_cursor->size2.x = (short)w; + cursor->ph_cursor->size2.y = (short)h; + cursor->ph_cursor->offset2.x = (short)hot_x; + cursor->ph_cursor->offset2.y = (short)hot_y; + cursor->ph_cursor->bytesperline2 = (char)w/8; + cursor->ph_cursor->color2 = Pg_BLACK; + + clen = (w/8)*h; + + /* Copy the mask and the data to different bitmap planes */ + for (i=0; i<clen; ++i) + { + for (bit = 0; bit < 8; bit++) + { + databit = data[i] & (1 << bit); + maskbit = mask[i] & (1 << bit); + + cursor->ph_cursor->images[i] |= (databit == 0) ? maskbit : 0; + /* If the databit != 0, treat it as a black pixel and + * ignore the maskbit (can't do an inverted color) */ + cursor->ph_cursor->images[i+clen] |= databit; + } + } + + /* #bytes following the hdr struct */ + cursor->ph_cursor->hdr.len =sizeof(PhCursorDef_t) + clen*2 - sizeof(PhRegionDataHdr_t); + + return (cursor); +} + +PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor) +{ + return (*cursor->ph_cursor); +} + +int ph_ShowWMCursor(_THIS, WMcursor* cursor) +{ + PtArg_t args[3]; + int nargs = 0; + + /* Don't do anything if the display is gone */ + if (window == NULL) + { + return (0); + } + + /* looks like photon can't draw mouse cursor in direct mode */ + if ((this->screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + /* disable the fake mouse in the fullscreen OpenGL mode */ + if ((this->screen->flags & SDL_OPENGL) == SDL_OPENGL) + { + cursor=NULL; + } + else + { + return (0); + } + } + + /* Set the photon cursor, or blank if cursor is NULL */ + if (cursor!=NULL) + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0); + /* Could set next to any PgColor_t value */ + PtSetArg(&args[1], Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR , 0); + PtSetArg(&args[2], Pt_ARG_BITMAP_CURSOR, cursor->ph_cursor, (cursor->ph_cursor->hdr.len + sizeof(PhRegionDataHdr_t))); + nargs = 3; + } + else /* Ph_CURSOR_NONE */ + { + PtSetArg(&args[0], Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0); + nargs = 1; + } + + SDL_Lock_EventThread(); + + if (PtSetResources(window, nargs, args) < 0 ) + { + return (0); + } + + SDL_Unlock_EventThread(); + + return (1); +} + + +void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + short abs_x, abs_y; + + SDL_Lock_EventThread(); + PtGetAbsPosition( window, &abs_x, &abs_y ); + PhMoveCursorAbs( PhInputGroup(NULL), x + abs_x, y + abs_y ); + SDL_Unlock_EventThread(); +} + + +void ph_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && (this->input_grab != SDL_GRAB_OFF)) + { + mouse_relative = 1; + } + else + { + mouse_relative = 0; + } +} + + +void ph_UpdateMouse(_THIS) +{ + PhCursorInfo_t phcursor; + short abs_x; + short abs_y; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + /* synchronizing photon mouse cursor position and SDL mouse position, if cursor appears over window. */ + PtGetAbsPosition(window, &abs_x, &abs_y); + PhQueryCursor(PhInputGroup(NULL), &phcursor); + if (((phcursor.pos.x >= abs_x) && (phcursor.pos.x <= abs_x + this->screen->w)) && + ((phcursor.pos.y >= abs_y) && (phcursor.pos.y <= abs_y + this->screen->h))) + { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, phcursor.pos.x-abs_x, phcursor.pos.y-abs_y); + } + else + { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + + /* Unlock the event thread, in multi-threading environments */ + SDL_Unlock_EventThread(); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h new file mode 100644 index 0000000..55a92b6 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_mouse_c.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_MOUSE_H__ +#define __SDL_PH_MOUSE_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *ph_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern PhCursorDef_t ph_GetWMPhCursor(WMcursor *cursor); +extern int ph_ShowWMCursor(_THIS, WMcursor *cursor); +extern void ph_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void ph_CheckMouseMode(_THIS); +extern void ph_UpdateMouse(_THIS); + +#endif /* __SDL_PH_MOUSE_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_video.c b/3rdparty/SDL/src/video/photon/SDL_ph_video.c new file mode 100644 index 0000000..5e1a82b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_video.c @@ -0,0 +1,648 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <unistd.h> +#include <sys/ioctl.h> + +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_video.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_image_c.h" +#include "SDL_ph_events_c.h" +#include "SDL_ph_mouse_c.h" +#include "SDL_ph_wm_c.h" +#include "SDL_ph_gl.h" +#include "SDL_phyuv_c.h" +#include "../blank_cursor.h" + +static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void ph_VideoQuit(_THIS); +static void ph_DeleteDevice(SDL_VideoDevice *device); + +static int phstatus=-1; + +static int ph_Available(void) +{ + if (phstatus!=0) + { + phstatus=PtInit(NULL); + if (phstatus==0) + { + return 1; + } + else + { + return 0; + } + } + return 1; +} + +static SDL_VideoDevice* ph_CreateDevice(int devindex) +{ + SDL_VideoDevice* device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData*)SDL_malloc((sizeof *device->hidden)); + device->gl_data = NULL; + } + if ((device == NULL) || (device->hidden == NULL)) + { + SDL_OutOfMemory(); + ph_DeleteDevice(device); + return NULL; + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the driver flags */ + device->handles_any_size = 1; + + /* Set the function pointers */ + device->CreateYUVOverlay = ph_CreateYUVOverlay; + device->VideoInit = ph_VideoInit; + device->ListModes = ph_ListModes; + device->SetVideoMode = ph_SetVideoMode; + device->ToggleFullScreen = ph_ToggleFullScreen; + device->UpdateMouse = ph_UpdateMouse; + device->SetColors = ph_SetColors; + device->UpdateRects = NULL; /* set up in ph_SetupUpdateFunction */ + device->VideoQuit = ph_VideoQuit; + device->AllocHWSurface = ph_AllocHWSurface; + device->CheckHWBlit = ph_CheckHWBlit; + device->FillHWRect = ph_FillHWRect; + device->SetHWColorKey = ph_SetHWColorKey; + device->SetHWAlpha = ph_SetHWAlpha; + device->LockHWSurface = ph_LockHWSurface; + device->UnlockHWSurface = ph_UnlockHWSurface; + device->FlipHWSurface = ph_FlipHWSurface; + device->FreeHWSurface = ph_FreeHWSurface; + device->SetCaption = ph_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = ph_IconifyWindow; + device->GrabInput = ph_GrabInput; + device->GetWMInfo = ph_GetWMInfo; + device->FreeWMCursor = ph_FreeWMCursor; + device->CreateWMCursor = ph_CreateWMCursor; + device->ShowWMCursor = ph_ShowWMCursor; + device->WarpWMCursor = ph_WarpWMCursor; + device->MoveWMCursor = NULL; + device->CheckMouseMode = ph_CheckMouseMode; + device->InitOSKeymap = ph_InitOSKeymap; + device->PumpEvents = ph_PumpEvents; + + /* OpenGL support. */ +#if SDL_VIDEO_OPENGL + device->GL_MakeCurrent = ph_GL_MakeCurrent; + device->GL_SwapBuffers = ph_GL_SwapBuffers; + device->GL_GetAttribute = ph_GL_GetAttribute; + device->GL_LoadLibrary = ph_GL_LoadLibrary; + device->GL_GetProcAddress = ph_GL_GetProcAddress; +#endif /* SDL_VIDEO_OPENGL */ + + device->free = ph_DeleteDevice; + + return device; +} + +VideoBootStrap ph_bootstrap = { + "photon", "QNX Photon video output", + ph_Available, ph_CreateDevice +}; + +static void ph_DeleteDevice(SDL_VideoDevice *device) +{ + if (device) + { + if (device->hidden) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + if (device->gl_data) + { + SDL_free(device->gl_data); + device->gl_data = NULL; + } + SDL_free(device); + device = NULL; + } +} + +static PtWidget_t *ph_CreateWindow(_THIS) +{ + PtWidget_t *widget; + + widget = PtCreateWidget(PtWindow, NULL, 0, NULL); + + return widget; +} + +static int ph_SetupWindow(_THIS, int w, int h, int flags) +{ + PtArg_t args[32]; + PhPoint_t pos = {0, 0}; + PhDim_t* olddim; + PhDim_t dim = {w, h}; + PhRect_t desktopextent; + int nargs = 0; + const char* windowpos; + const char* iscentered; + int x, y; + + /* check if window size has been changed by Window Manager */ + PtGetResource(window, Pt_ARG_DIM, &olddim, 0); + if ((olddim->w!=w) || (olddim->h!=h)) + { + PtSetArg(&args[nargs++], Pt_ARG_DIM, &dim, 0); + } + + if ((flags & SDL_RESIZABLE) == SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_RESIZE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_RESIZE | Ph_WM_MOVE | Ph_WM_CLOSE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_TRUE, Pt_RESIZE_XY_AS_REQUIRED); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE, Ph_WM_RESIZE | Ph_WM_MAX | Ph_WM_RESTORE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_MOVE | Ph_WM_CLOSE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX | Ph_WM_RENDER_COLLAPSE | Ph_WM_RENDER_RETURN); + PtSetArg(&args[nargs++], Pt_ARG_RESIZE_FLAGS, Pt_FALSE, Pt_RESIZE_XY_AS_REQUIRED); + } + + if (((flags & SDL_NOFRAME)==SDL_NOFRAME) || ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN)) + { + if ((flags & SDL_RESIZABLE) != SDL_RESIZABLE) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Pt_TRUE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_BORDER); + } + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE | + Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN); + } + + if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_FFRONT | Ph_WM_MAX | Ph_WM_TOFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFRONT | Ph_WM_STATE_ISFOCUS | Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_FFRONT | Ph_WM_CONSWITCH); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISFRONT); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0); + } + if (!currently_maximized) + { + windowpos = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + iscentered = SDL_getenv("SDL_VIDEO_CENTERED"); + + if ((iscentered) || ((windowpos) && (SDL_strcmp(windowpos, "center")==0))) + { + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent); + if (desktop_mode.width>w) + { + pos.x = (desktop_mode.width - w)/2; + } + if (desktop_mode.height>h) + { + pos.y = (desktop_mode.height - h)/2; + } + + pos.x+=desktopextent.ul.x; + pos.y+=desktopextent.ul.y; + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + } + else + { + if (windowpos) + { + if (SDL_sscanf(windowpos, "%d,%d", &x, &y) == 2) + { + if ((x<desktop_mode.width) && (y<desktop_mode.height)) + { + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, 0, &desktopextent); + pos.x=x+desktopextent.ul.x; + pos.y=y+desktopextent.ul.y; + } + PtSetArg(&args[nargs++], Pt_ARG_POS, &pos, 0); + } + } + } + } + + /* if window is maximized render it as maximized */ + if (currently_maximized) + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISMAX); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISMAX); + } + + /* do not grab the keyboard by default */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY); + + /* bring the focus to the window */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFOCUS); + + /* allow to catch hide event */ + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_HIDE); + PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_HIDE); + } + + PtSetResources(window, nargs, args); + PtRealizeWidget(window); + PtWindowToFront(window); + +#if 0 /* FIXME */ + PtGetResource(window, Pt_ARG_POS, &olddim, 0); + fprintf(stderr, "POSITION: %d, %d\n", olddim->w, olddim->h); +#endif + + return 0; +} + +static const struct ColourMasks* ph_GetColourMasks(int bpp) +{ + /* The alpha mask doesn't appears to be needed */ + static const struct ColourMasks phColorMasks[5] = { + /* 8 bit */ {0, 0, 0, 0, 8}, + /* 15 bit ARGB */ {0x7C00, 0x03E0, 0x001F, 0x8000, 15}, + /* 16 bit RGB */ {0xF800, 0x07E0, 0x001F, 0x0000, 16}, + /* 24 bit RGB */ {0xFF0000, 0x00FF00, 0x0000FF, 0x000000, 24}, + /* 32 bit ARGB */ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, 32}, + }; + + switch (bpp) + { + case 8: + return &phColorMasks[0]; + case 15: + return &phColorMasks[1]; + case 16: + return &phColorMasks[2]; + case 24: + return &phColorMasks[3]; + case 32: + return &phColorMasks[4]; + } + return NULL; +} + +static int ph_VideoInit(_THIS, SDL_PixelFormat* vformat) +{ + PgHWCaps_t hwcaps; + int i; + + window=NULL; + desktoppal=SDLPH_PAL_NONE; + +#if SDL_VIDEO_OPENGL + oglctx=NULL; + oglbuffers=NULL; + oglflags=0; + oglbpp=0; +#endif + + old_video_mode=-1; + old_refresh_rate=-1; + + if (NULL == (phevent = SDL_malloc(EVENT_SIZE))) + { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(phevent, 0x00, EVENT_SIZE); + + window = ph_CreateWindow(this); + if (window == NULL) + { + SDL_SetError("ph_VideoInit(): Couldn't create video window !\n"); + return -1; + } + + /* Create the blank cursor */ + SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, + (int)BLANK_CWIDTH, (int)BLANK_CHEIGHT, + (int)BLANK_CHOTX, (int)BLANK_CHOTY); + + if (SDL_BlankCursor == NULL) + { + return -1; + } + + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_VideoInit(): GetGraphicsHWCaps function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &desktop_mode) < 0) + { + SDL_SetError("ph_VideoInit(): PgGetVideoModeInfo function failed !\n"); + this->FreeWMCursor(this, SDL_BlankCursor); + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = desktop_mode.width; + this->info.current_h = desktop_mode.height; + + /* We need to return BytesPerPixel as it in used by CreateRGBsurface */ + vformat->BitsPerPixel = desktop_mode.bits_per_pixel; + vformat->BytesPerPixel = desktop_mode.bytes_per_scanline/desktop_mode.width; + desktopbpp = desktop_mode.bits_per_pixel; + + /* save current palette */ + if (desktopbpp==8) + { + PgGetPalette(savedpal); + PgGetPalette(syspalph); + } + else + { + for(i=0; i<_Pg_MAX_PALETTE; i++) + { + savedpal[i]=PgRGB(0, 0, 0); + syspalph[i]=PgRGB(0, 0, 0); + } + } + + currently_fullscreen = 0; + currently_hided = 0; + currently_maximized = 0; + current_overlay = NULL; + + OCImage.direct_context = NULL; + OCImage.offscreen_context = NULL; + OCImage.offscreen_backcontext = NULL; + OCImage.oldDC = NULL; + OCImage.CurrentFrameData = NULL; + OCImage.FrameData0 = NULL; + OCImage.FrameData1 = NULL; + videomode_emulatemode = 0; + + this->info.wm_available = 1; + + ph_UpdateHWInfo(this); + + return 0; +} + +static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) +{ + const struct ColourMasks* mask; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + current->flags = flags; + + /* if we do not have desired fullscreen mode, then fallback into window mode */ + if (((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && (ph_GetVideoMode(width, height, bpp)==0)) + { + current->flags &= ~SDL_FULLSCREEN; + current->flags &= ~SDL_NOFRAME; + current->flags &= ~SDL_RESIZABLE; + } + + ph_SetupWindow(this, width, height, current->flags); + + mask = ph_GetColourMasks(bpp); + if (mask != NULL) + { + SDL_ReallocFormat(current, mask->bpp, mask->red, mask->green, mask->blue, 0); + } + else + { + SDL_SetError("ph_SetVideoMode(): desired bpp is not supported by photon !\n"); + return NULL; + } + + if ((current->flags & SDL_OPENGL)==SDL_OPENGL) + { +#if !SDL_VIDEO_OPENGL + /* if no built-in OpenGL support */ + SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n"); + current->flags &= ~SDL_OPENGL; + return NULL; +#endif /* SDL_VIDEO_OPENGL */ + } + else + { + /* Initialize internal variables */ + if ((current->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + { + if (bpp==8) + { + desktoppal=SDLPH_PAL_SYSTEM; + } + + current->flags &= ~SDL_RESIZABLE; /* no resize for Direct Context */ + current->flags |= SDL_HWSURFACE; + } + else + { + /* remove this if we'll have support for the non-fullscreen sw/hw+doublebuf one day */ + current->flags &= ~SDL_DOUBLEBUF; + + /* Use offscreen memory if SDL_HWSURFACE flag is set */ + if ((current->flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + if (desktopbpp!=bpp) + { + current->flags &= ~SDL_HWSURFACE; + } + } + + /* using palette emulation code in window mode */ + if (bpp==8) + { + if (desktopbpp>=15) + { + desktoppal = SDLPH_PAL_EMULATE; + } + else + { + desktoppal = SDLPH_PAL_SYSTEM; + } + } + else + { + desktoppal = SDLPH_PAL_NONE; + } + } + } + + current->w = width; + current->h = height; + + if (desktoppal==SDLPH_PAL_SYSTEM) + { + current->flags|=SDL_HWPALETTE; + } + + /* Must call at least once for setup image planes */ + if (ph_SetupUpdateFunction(this, current, current->flags)==-1) + { + /* Error string was filled in the ph_SetupUpdateFunction() */ + return NULL; + } + + /* finish window drawing, if we are not in fullscreen, of course */ + if ((current->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + PtFlush(); + } + else + { + PgFlush(); + } + + visualbpp=bpp; + + ph_UpdateHWInfo(this); + + SDL_Unlock_EventThread(); + + /* We've done! */ + return (current); +} + +static void ph_VideoQuit(_THIS) +{ + /* restore palette */ + if (desktopbpp==8) + { + PgSetPalette(syspalph, 0, -1, 0, 0, 0); + PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); + PgFlush(); + } + + ph_DestroyImage(this, SDL_VideoSurface); + + if (window) + { + PtUnrealizeWidget(window); + PtDestroyWidget(window); + window=NULL; + } + + if (phevent!=NULL) + { + SDL_free(phevent); + phevent=NULL; + } +} + +static int ph_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + SDL_Rect updaterect; + + updaterect.x = updaterect.y = 0; + updaterect.w = this->screen->w; + updaterect.h = this->screen->h; + + /* palette emulation code, using palette of the PhImage_t struct */ + if (desktoppal==SDLPH_PAL_EMULATE) + { + if ((SDL_Image) && (SDL_Image->palette)) + { + for (i=firstcolor; i<firstcolor+ncolors; i++) + { + syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b); + SDL_Image->palette[i] = syspalph[i]; + } + + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + } + else + { + if (desktoppal==SDLPH_PAL_SYSTEM) + { + for (i=firstcolor; i<firstcolor+ncolors; i++) + { + syspalph[i] = PgRGB(colors[i-firstcolor].r, colors[i-firstcolor].g, colors[i-firstcolor].b); + } + + if ((this->screen->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) + { + /* window mode must use soft palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + /* image needs to be redrawn */ + this->UpdateRects(this, 1, &updaterect); + } + else + { + /* fullscreen mode must use hardware palette */ + PgSetPalette(&syspalph[firstcolor], 0, firstcolor, ncolors, Pg_PALSET_GLOBAL, 0); + } + } + else + { + /* SDLPH_PAL_NONE do nothing */ + } + } + + return 1; +} + diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_video.h b/3rdparty/SDL/src/video/photon/SDL_ph_video.h new file mode 100644 index 0000000..3995d35 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_video.h @@ -0,0 +1,157 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_VIDEO_H__ +#define __SDL_PH_VIDEO_H__ + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#include <sys/neutrino.h> + +#include <Ph.h> +#include <Pt.h> +#include <photon/Pg.h> +#include <photon/PdDirect.h> + +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + #include <photon/PdGL.h> + #else + #include <GL/qnxgl.h> + #include <GL/GLPh.h> + #endif /* 6.3.0 */ +#endif /* SDL_VIDEO_OPENGL */ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice* this + +#define PH_OGL_MAX_ATTRIBS 32 + +#define SDLPH_PAL_NONE 0x00000000L +#define SDLPH_PAL_EMULATE 0x00000001L +#define SDLPH_PAL_SYSTEM 0x00000002L + +typedef struct +{ + unsigned char* Y; + unsigned char* V; + unsigned char* U; +} FRAMEDATA; + +/* Mask values for SDL_ReallocFormat() */ +struct ColourMasks +{ + Uint32 red; + Uint32 green; + Uint32 blue; + Uint32 alpha; + Uint32 bpp; +}; + +/* Private display data */ +struct SDL_PrivateVideoData +{ + PgDisplaySettings_t mode_settings; + PtWidget_t *Window; /* used to handle input events */ + PhImage_t *image; /* used to display image */ +#if SDL_VIDEO_OPENGL + #if (_NTO_VERSION < 630) + PdOpenGLContext_t* OGLContext; /* OpenGL context */ + void* OGLBuffers; /* OpenGL buffers (unused) */ + #else + qnxglc_t* OGLContext; /* OpenGL context for the 6.3 */ + qnxgl_bufs_t* OGLBuffers; /* OpenGL buffers for the 6.3 */ + #endif /* 630 */ + + Uint32 OGLFlags; /* OpenGL flags */ + Uint32 OGLBPP; /* OpenGL bpp */ +#endif /* SDL_VIDEO_OPENGL */ + PgColor_t savedpal[_Pg_MAX_PALETTE]; + PgColor_t syspalph[_Pg_MAX_PALETTE]; + + struct + { + PdDirectContext_t* direct_context; + PdOffscreenContext_t* offscreen_context; + PdOffscreenContext_t* offscreen_backcontext; + PhDrawContext_t* oldDC; + uint8_t* dc_ptr; + unsigned char* CurrentFrameData; + unsigned char* FrameData0; + unsigned char* FrameData1; + Uint32 current; + Uint32 flags; + } ocimage; + + PgHWCaps_t graphics_card_caps; /* Graphics card caps at the moment of start */ + PgVideoModeInfo_t desktop_mode; /* Current desktop video mode information */ + int old_video_mode; /* Stored mode before fullscreen switch */ + int old_refresh_rate; /* Stored refresh rate befor fullscreen switch */ + + int mouse_relative; + WMcursor* BlankCursor; + uint32_t videomode_emulatemode; + + Uint32 visualbpp; /* current visual bpp */ + Uint32 desktopbpp; /* bpp of desktop at the moment of start */ + Uint32 desktoppal; /* palette mode emulation or system */ + + int currently_fullscreen; + int currently_hided; /* 1 - window hided (minimazed), 0 - normal */ + int currently_maximized; /* 1 - window hided (minimazed), 0 - normal */ + + PhEvent_t* event; + SDL_Overlay* overlay; +}; + +#define mode_settings (this->hidden->mode_settings) +#define window (this->hidden->Window) +#define SDL_Image (this->hidden->image) +#define OCImage (this->hidden->ocimage) +#define old_video_mode (this->hidden->old_video_mode) +#define old_refresh_rate (this->hidden->old_refresh_rate) +#define graphics_card_caps (this->hidden->graphics_card_caps) +#define desktopbpp (this->hidden->desktopbpp) +#define visualbpp (this->hidden->visualbpp) +#define desktoppal (this->hidden->desktoppal) +#define savedpal (this->hidden->savedpal) +#define syspalph (this->hidden->syspalph) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define currently_hided (this->hidden->currently_hided) +#define currently_maximized (this->hidden->currently_maximized) +#define phevent (this->hidden->event) +#define current_overlay (this->hidden->overlay) +#define desktop_mode (this->hidden->desktop_mode) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define videomode_emulatemode (this->hidden->videomode_emulatemode) + +#if SDL_VIDEO_OPENGL + #define oglctx (this->hidden->OGLContext) + #define oglbuffers (this->hidden->OGLBuffers) + #define oglflags (this->hidden->OGLFlags) + #define oglbpp (this->hidden->OGLBPP) +#endif /* SDL_VIDEO_OPENGL */ + +#endif /* __SDL_PH_VIDEO_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_wm.c b/3rdparty/SDL/src/video/photon/SDL_ph_wm.c new file mode 100644 index 0000000..8e75d0b --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_wm.c @@ -0,0 +1,118 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <Ph.h> +#include <photon/PpProto.h> +#include <photon/PhWm.h> +#include <photon/wmapi.h> + +#include "SDL_version.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ph_modes_c.h" +#include "SDL_ph_wm_c.h" + +void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + return; +} + +/* Set window caption */ +void ph_SetCaption(_THIS, const char *title, const char *icon) +{ + SDL_Lock_EventThread(); + + /* sanity check for set caption call before window init */ + if (window!=NULL) + { + PtSetResource(window, Pt_ARG_WINDOW_TITLE, title, 0); + } + + SDL_Unlock_EventThread(); +} + +/* Iconify current window */ +int ph_IconifyWindow(_THIS) +{ + PhWindowEvent_t windowevent; + + SDL_Lock_EventThread(); + + SDL_memset(&windowevent, 0, sizeof(windowevent)); + windowevent.event_f = Ph_WM_HIDE; + windowevent.event_state = Ph_WM_EVSTATE_HIDE; + windowevent.rid = PtWidgetRid(window); + PtForwardWindowEvent(&windowevent); + + SDL_Unlock_EventThread(); + + return 0; +} + +SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode) +{ + short abs_x, abs_y; + + if( mode == SDL_GRAB_OFF ) + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISALTKEY); + } + else + { + PtSetResource(window, Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY); + + PtGetAbsPosition(window, &abs_x, &abs_y); + PhMoveCursorAbs(PhInputGroup(NULL), abs_x + SDL_VideoSurface->w/2, abs_y + SDL_VideoSurface->h/2); + } + + SDL_Unlock_EventThread(); + + return(mode); +} + +SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode) +{ + SDL_Lock_EventThread(); + mode = ph_GrabInputNoLock(this, mode); + SDL_Unlock_EventThread(); + + return(mode); +} + + +int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) + { + return 1; + } + else + { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return -1; + } +} diff --git a/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h b/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h new file mode 100644 index 0000000..72bbfd2 --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_ph_wm_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_WM_H__ +#define __SDL_PH_WM_H__ + +#include "SDL_ph_video.h" + +/* Functions to be exported */ +extern void ph_SetCaption(_THIS, const char *title, const char *icon); +extern void ph_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int ph_IconifyWindow(_THIS); +extern SDL_GrabMode ph_GrabInputNoLock(_THIS, SDL_GrabMode mode); +extern SDL_GrabMode ph_GrabInput(_THIS, SDL_GrabMode mode); +extern int ph_GetWMInfo(_THIS, SDL_SysWMinfo *info); + +#endif /* __SDL_PH_WM_H__ */ diff --git a/3rdparty/SDL/src/video/photon/SDL_phyuv.c b/3rdparty/SDL/src/video/photon/SDL_phyuv.c new file mode 100644 index 0000000..06c72fd --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_phyuv.c @@ -0,0 +1,504 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the QNX Realtime Platform version of SDL YUV video overlays */ + +#include <errno.h> + +#include <Ph.h> +#include <Pt.h> + +#include "SDL_video.h" +#include "SDL_phyuv_c.h" +#include "../SDL_yuvfuncs.h" + +#define OVERLAY_STATE_UNINIT 0 +#define OVERLAY_STATE_ACTIVE 1 + +/* The functions are used to manipulate software video overlays */ +static struct private_yuvhwfuncs ph_yuvfuncs = +{ + ph_LockYUVOverlay, + ph_UnlockYUVOverlay, + ph_DisplayYUVOverlay, + ph_FreeYUVOverlay +}; + +int grab_ptrs2(PgVideoChannel_t* channel, FRAMEDATA* Frame0, FRAMEDATA* Frame1) +{ + int planes = 0; + + /* Buffers have moved; re-obtain the pointers */ + Frame0->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane1); + Frame1->Y = (unsigned char *)PdGetOffscreenContextPtr(channel->yplane2); + Frame0->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane1); + Frame1->U = (unsigned char *)PdGetOffscreenContextPtr(channel->vplane2); + Frame0->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane1); + Frame1->V = (unsigned char *)PdGetOffscreenContextPtr(channel->uplane2); + + if (Frame0->Y) + planes++; + + if (Frame0->U) + planes++; + + if (Frame0->V) + planes++; + + return planes; +} + +SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display) +{ + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + int vidport; + int rtncode; + int planes; + int i=0; + PhPoint_t pos; + + /* Create the overlay structure */ + overlay = SDL_calloc(1, sizeof(SDL_Overlay)); + + if (overlay == NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &ph_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); + + if (hwdata == NULL) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata = hwdata; + + PhDCSetCurrent(0); + if (overlay->hwdata->channel == NULL) + { + if ((overlay->hwdata->channel = PgCreateVideoChannel(Pg_VIDEO_CHANNEL_SCALER, 0)) == NULL) + { + SDL_SetError("ph_CreateYUVOverlay(): Create channel failed: %s\n", strerror(errno)); + SDL_FreeYUVOverlay(overlay); + return NULL; + + } + } + + overlay->hwdata->forcedredraw=0; + + PtGetAbsPosition(window, &pos.x, &pos.y); + overlay->hwdata->CurrentWindowPos.x = pos.x; + overlay->hwdata->CurrentWindowPos.y = pos.y; + overlay->hwdata->CurrentViewPort.pos.x = 0; + overlay->hwdata->CurrentViewPort.pos.y = 0; + overlay->hwdata->CurrentViewPort.size.w = width; + overlay->hwdata->CurrentViewPort.size.h = height; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + overlay->hwdata->FrameData0 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + overlay->hwdata->FrameData1 = (FRAMEDATA *) SDL_calloc(1, sizeof(FRAMEDATA)); + + vidport = -1; + i=0; + + overlay->hwdata->ischromakey=0; + + do { + SDL_memset(&overlay->hwdata->caps, 0x00, sizeof(PgScalerCaps_t)); + overlay->hwdata->caps.size = sizeof(PgScalerCaps_t); + rtncode = PgGetScalerCapabilities(overlay->hwdata->channel, i, &overlay->hwdata->caps); + if (rtncode==0) + { + if (overlay->hwdata->caps.format==format) + { + if ((overlay->hwdata->caps.flags & Pg_SCALER_CAP_DST_CHROMA_KEY) == Pg_SCALER_CAP_DST_CHROMA_KEY) + { + overlay->hwdata->ischromakey=1; + } + vidport=1; + break; + } + } + else + { + break; + } + i++; + } while(1); + + + if (vidport == -1) + { + SDL_SetError("No available video ports for requested format\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + + overlay->hwdata->format = format; + overlay->hwdata->props.format = format; + overlay->hwdata->props.size = sizeof(PgScalerProps_t); + overlay->hwdata->props.src_dim.w = width; + overlay->hwdata->props.src_dim.h = height; + + /* overlay->hwdata->chromakey = PgGetOverlayChromaColor(); */ + overlay->hwdata->chromakey = PgRGB(12, 6, 12); /* very dark pink color */ + overlay->hwdata->props.color_key = overlay->hwdata->chromakey; + + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + + overlay->hwdata->props.flags = Pg_SCALER_PROP_DOUBLE_BUFFER; + + if ((overlay->hwdata->ischromakey)&&(overlay->hwdata->chromakey)) + { + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE; + overlay->hwdata->props.flags |= Pg_SCALER_PROP_CHROMA_SPECIFY_KEY_MASK; + } + else + { + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_CHROMA_ENABLE; + } + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &overlay->hwdata->props); + + switch(rtncode) + { + case -1: SDL_SetError("PgConfigScalerChannel failed\n"); + SDL_FreeYUVOverlay(overlay); + return NULL; + case 1: + case 0: + default: + break; + } + + planes = grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + + if(overlay->hwdata->channel->yplane1 != NULL) + overlay->hwdata->YStride = overlay->hwdata->channel->yplane1->pitch; + if(overlay->hwdata->channel->vplane1 != NULL) + overlay->hwdata->UStride = overlay->hwdata->channel->vplane1->pitch; + if(overlay->hwdata->channel->uplane1 != NULL) + overlay->hwdata->VStride = overlay->hwdata->channel->uplane1->pitch; + + /* check for the validness of all planes */ + if ((overlay->hwdata->channel->yplane1 == NULL) && + (overlay->hwdata->channel->uplane1 == NULL) && + (overlay->hwdata->channel->vplane1 == NULL)) + { + SDL_FreeYUVOverlay(overlay); + SDL_SetError("PgConfigScaler() returns all planes equal NULL\n"); + return NULL; + } +/* + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + + if (overlay->hwdata->current==0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } +*/ + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + +/* + overlay->hwdata->locked = 1; +*/ + + /* Find the pitch and offset values for the overlay */ + overlay->planes = planes; + overlay->pitches = SDL_calloc(overlay->planes, sizeof(Uint16)); + overlay->pixels = SDL_calloc(overlay->planes, sizeof(Uint8*)); + if (!overlay->pitches || !overlay->pixels) + { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + + overlay->hwdata->State = OVERLAY_STATE_ACTIVE; + overlay->hwdata->scaler_on = 0; + overlay->hw_overlay = 1; + + current_overlay=overlay; + + return overlay; +} + +int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return -1; + } + + overlay->hwdata->locked = 1; + +/* overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } +*/ + + return(0); +} + +void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay) +{ + if (overlay == NULL) + { + return; + } + + overlay->hwdata->locked = 0; +} + +int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst) +{ + int rtncode; + PhPoint_t pos; + SDL_Rect backrect; + PhRect_t windowextent; + int winchanged=0; + + if ((overlay == NULL) || (overlay->hwdata==NULL)) + { + return -1; + } + + if (overlay->hwdata->State == OVERLAY_STATE_UNINIT) + { + return -1; + } + + PtGetAbsPosition(window, &pos.x, &pos.y); + if ((pos.x!=overlay->hwdata->CurrentWindowPos.x) || + (pos.y!=overlay->hwdata->CurrentWindowPos.y)) + { + winchanged=1; + overlay->hwdata->CurrentWindowPos.x=pos.x; + overlay->hwdata->CurrentWindowPos.y=pos.y; + } + + /* If CurrentViewPort position/size has been changed, then move/resize the viewport */ + if ((overlay->hwdata->CurrentViewPort.pos.x != dst->x) || + (overlay->hwdata->CurrentViewPort.pos.y != dst->y) || + (overlay->hwdata->CurrentViewPort.size.w != dst->w) || + (overlay->hwdata->CurrentViewPort.size.h != dst->h) || + (overlay->hwdata->scaler_on==0) || (winchanged==1) || + (overlay->hwdata->forcedredraw==1)) + { + + if (overlay->hwdata->ischromakey==1) + { + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* Draw the new rectangle of the chroma color at the viewport position */ + PgSetFillColor(overlay->hwdata->chromakey); + PgDrawIRect(dst->x, dst->y, dst->x+dst->w-1, dst->y+dst->h-1, Pg_DRAW_FILL); + PgFlush(); + } + + overlay->hwdata->props.flags |= Pg_SCALER_PROP_SCALER_ENABLE; + overlay->hwdata->scaler_on = 1; + + PhWindowQueryVisible(Ph_QUERY_CONSOLE, 0, PtWidgetRid(window), &windowextent); + overlay->hwdata->CurrentViewPort.pos.x = pos.x-windowextent.ul.x+dst->x; + overlay->hwdata->CurrentViewPort.pos.y = pos.y-windowextent.ul.y+dst->y; + overlay->hwdata->CurrentViewPort.size.w = dst->w; + overlay->hwdata->CurrentViewPort.size.h = dst->h; + PhAreaToRect(&overlay->hwdata->CurrentViewPort, &overlay->hwdata->props.viewport); + overlay->hwdata->CurrentViewPort.pos.x = dst->x; + overlay->hwdata->CurrentViewPort.pos.y = dst->y; + + rtncode = PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + switch(rtncode) + { + case -1: + SDL_SetError("PgConfigScalerChannel() function failed\n"); + SDL_FreeYUVOverlay(overlay); + return -1; + case 1: + grab_ptrs2(overlay->hwdata->channel, overlay->hwdata->FrameData0, overlay->hwdata->FrameData1); + break; + case 0: + default: + break; + } + } + + +/* + if (overlay->hwdata->locked==0) + { + overlay->hwdata->current = PgNextVideoFrame(overlay->hwdata->channel); + if (overlay->hwdata->current == -1) + { + SDL_SetError("ph_LockYUVOverlay: PgNextFrame() failed, bailing out\n"); + SDL_FreeYUVOverlay(overlay); + return 0; + } + + if (overlay->hwdata->current == 0) + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData0; + } + else + { + overlay->hwdata->CurrentFrameData = overlay->hwdata->FrameData1; + } + + if (overlay->planes > 0) + { + overlay->pitches[0] = overlay->hwdata->channel->yplane1->pitch; + overlay->pixels[0] = overlay->hwdata->CurrentFrameData->Y; + } + if (overlay->planes > 1) + { + overlay->pitches[1] = overlay->hwdata->channel->uplane1->pitch; + overlay->pixels[1] = overlay->hwdata->CurrentFrameData->U; + } + if (overlay->planes > 2) + { + overlay->pitches[2] = overlay->hwdata->channel->vplane1->pitch; + overlay->pixels[2] = overlay->hwdata->CurrentFrameData->V; + } + } +*/ + + return 0; +} + +void ph_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + SDL_Rect backrect; + + if (overlay == NULL) + { + return; + } + + if (overlay->hwdata == NULL) + { + return; + } + + current_overlay=NULL; + + /* restore screen behind the overlay/chroma color. */ + backrect.x=overlay->hwdata->CurrentViewPort.pos.x; + backrect.y=overlay->hwdata->CurrentViewPort.pos.y; + backrect.w=overlay->hwdata->CurrentViewPort.size.w; + backrect.h=overlay->hwdata->CurrentViewPort.size.h; + this->UpdateRects(this, 1, &backrect); + + /* it is need for some buggy drivers, that can't hide overlay before */ + /* freeing buffer, so we got trash on the srceen */ + overlay->hwdata->props.flags &= ~Pg_SCALER_PROP_SCALER_ENABLE; + PgConfigScalerChannel(overlay->hwdata->channel, &(overlay->hwdata->props)); + + overlay->hwdata->scaler_on = 0; + overlay->hwdata->State = OVERLAY_STATE_UNINIT; + + if (overlay->hwdata->channel != NULL) + { + PgDestroyVideoChannel(overlay->hwdata->channel); + overlay->hwdata->channel = NULL; + return; + } + + overlay->hwdata->CurrentFrameData = NULL; + + SDL_free(overlay->hwdata->FrameData0); + SDL_free(overlay->hwdata->FrameData1); + overlay->hwdata->FrameData0 = NULL; + overlay->hwdata->FrameData1 = NULL; + SDL_free(overlay->hwdata); +} diff --git a/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h b/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h new file mode 100644 index 0000000..c6f73fe --- /dev/null +++ b/3rdparty/SDL/src/video/photon/SDL_phyuv_c.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef __SDL_PH_YUV_H__ +#define __SDL_PH_YUV_H__ + +/* This is the photon implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_ph_video.h" + +struct private_yuvhwdata +{ + FRAMEDATA* CurrentFrameData; + FRAMEDATA* FrameData0; + FRAMEDATA* FrameData1; + PgScalerProps_t props; + PgScalerCaps_t caps; + PgVideoChannel_t* channel; + PhArea_t CurrentViewPort; + PhPoint_t CurrentWindowPos; + long format; + int scaler_on; + int current; + long YStride; + long VStride; + long UStride; + int ischromakey; + long chromakey; + int forcedredraw; + unsigned long State; + long flags; + int locked; +}; + +extern SDL_Overlay* ph_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display); +extern int ph_LockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern void ph_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay); +extern int ph_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect* dst); +extern void ph_FreeYUVOverlay(_THIS, SDL_Overlay* overlay); + +#endif /* __SDL_PH_YUV_H__ */ diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgevents.c b/3rdparty/SDL/src/video/picogui/SDL_pgevents.c new file mode 100644 index 0000000..5006c07 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgevents.c @@ -0,0 +1,117 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_pgvideo.h" +#include "SDL_pgevents_c.h" + +int PG_HandleClose(struct pgEvent *evt) +{ + SDL_PrivateQuit(); + return 1; /* Intercept the event's normal quit handling */ +} + +int PG_HandleResize(struct pgEvent *evt) +{ + SDL_PrivateResize(evt->e.size.w, evt->e.size.h); + return 0; +} + +int PG_HandleKey(struct pgEvent *evt) +{ + SDL_keysym sym; + SDL_memset(&sym,0,sizeof(sym)); + sym.sym = evt->e.kbd.key; + sym.mod = evt->e.kbd.mods; + SDL_PrivateKeyboard(evt->type == PG_WE_KBD_KEYDOWN, &sym); + return 0; +} + +int PG_HandleChar(struct pgEvent *evt) +{ + SDL_keysym sym; + SDL_memset(&sym,0,sizeof(sym)); + sym.unicode = evt->e.kbd.key; + sym.mod = evt->e.kbd.mods; + SDL_PrivateKeyboard(evt->type == PG_WE_KBD_KEYDOWN, &sym); + return 0; +} + +int PG_HandleMouseButton(struct pgEvent *evt) +{ + /* We need to focus the canvas when it's clicked */ + if (evt->extra) { + SDL_VideoDevice *this = (SDL_VideoDevice *) evt->extra; + pgFocus(this->hidden->wCanvas); + } + SDL_PrivateMouseButton(evt->type == PG_WE_PNTR_DOWN, evt->e.pntr.chbtn, + evt->e.pntr.x, evt->e.pntr.y); + return 0; +} + +int PG_HandleMouseMotion(struct pgEvent *evt) +{ + SDL_PrivateMouseMotion(evt->e.pntr.btn,0,evt->e.pntr.x, evt->e.pntr.y); + return 0; +} + +void PG_PumpEvents(_THIS) +{ + /* Process all pending events */ + pgEventPoll(); +} + +void PG_InitOSKeymap(_THIS) +{ + /* We need no keymap */ +} + +void PG_InitEvents(_THIS) +{ + /* Turn on all the mouse and keyboard triggers for our canvas, normally less important + * events like mouse movement are ignored to save bandwidth. */ + pgSetWidget(this->hidden->wCanvas, PG_WP_TRIGGERMASK, + pgGetWidget(this->hidden->wCanvas, PG_WP_TRIGGERMASK) | + PG_TRIGGER_UP | PG_TRIGGER_DOWN | PG_TRIGGER_MOVE | + PG_TRIGGER_KEYUP | PG_TRIGGER_KEYDOWN | PG_TRIGGER_CHAR,0); + + /* Start our canvas out focused, so we get keyboard input */ + pgFocus(this->hidden->wCanvas); + + /* Set up bindings for all the above event handlers */ + pgBind(this->hidden->wApp, PG_WE_CLOSE, &PG_HandleClose, NULL); + pgBind(this->hidden->wCanvas, PG_WE_BUILD, &PG_HandleResize, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_CHAR, &PG_HandleChar, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_KEYUP, &PG_HandleKey, NULL); + pgBind(this->hidden->wCanvas, PG_WE_KBD_KEYDOWN, &PG_HandleKey, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_MOVE, &PG_HandleMouseMotion, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_UP, &PG_HandleMouseButton, NULL); + pgBind(this->hidden->wCanvas, PG_WE_PNTR_DOWN, &PG_HandleMouseButton, this); +} + +/* end of SDL_pgevents.c ... */ diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h b/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h new file mode 100644 index 0000000..a54e225 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgevents_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL_pgvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void PG_PumpEvents(_THIS); +extern void PG_InitEvents(_THIS); +extern void PG_InitOSKeymap(_THIS); + +/* end of SDL_pgevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c new file mode 100644 index 0000000..18b3fe4 --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.c @@ -0,0 +1,364 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_pgvideo.h" +#include "SDL_pgevents_c.h" + +#define PGVID_DRIVER_NAME "picogui" + +/* Initialization/Query functions */ +static int PG_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void PG_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int PG_AllocHWSurface(_THIS, SDL_Surface *surface); +static int PG_LockHWSurface(_THIS, SDL_Surface *surface); +static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void PG_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +// The implementation dependent data for the window manager cursor +struct WMcursor { + /* Our cursor is a PicoGUI theme */ + pghandle theme; +} ; + +/* WM functions */ +void PG_SetCaption(_THIS, const char *title, const char *icon); +WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, + int w, int h, int hot_x, int hot_y); +void PG_FreeWMCursor (_THIS, WMcursor * cursor); +void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +int PG_ShowWMCursor (_THIS, WMcursor * cursor); + +/* PicoGUI driver bootstrap functions */ + +static int PG_Available(void) +{ + /* FIXME: The current client lib doesn't give a way to see if the picogui + * server is reachable without causing a fatal error if it isn't. + * This should be fixed in cli_c2, but until then assume we can + * connect. Since more common drivers like X11 are probed first anyway, + * this shouldn't be a huge problem. + */ + return(1); +} + +static void PG_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *PG_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = PG_VideoInit; + device->ListModes = PG_ListModes; + device->SetVideoMode = PG_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->SetColors = PG_SetColors; + device->UpdateRects = PG_UpdateRects; + device->VideoQuit = PG_VideoQuit; + device->AllocHWSurface = PG_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = PG_LockHWSurface; + device->UnlockHWSurface = PG_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = PG_FreeHWSurface; + device->SetCaption = PG_SetCaption; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + + device->PumpEvents = PG_PumpEvents; + device->InitOSKeymap = PG_InitOSKeymap; + + device->ShowWMCursor = PG_ShowWMCursor; + device->CreateWMCursor = PG_CreateWMCursor; + device->FreeWMCursor = PG_FreeWMCursor; + device->WarpWMCursor = PG_WarpWMCursor; + + device->free = PG_DeleteDevice; + + return device; +} + +VideoBootStrap PG_bootstrap = { + PGVID_DRIVER_NAME, "PicoGUI SDL driver", + PG_Available, PG_CreateDevice +}; + + +int PG_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + /* Connect to the PicoGUI server. No way to process command line args yet, + * but since this is based on SHM it's not important to be able to specify + * a remote PicoGUI server. + * + * FIXME: Another nitpick about the current client lib is there's no + * clean way to indicate that command line args are not available. + */ + pgInit(0,(char**)""); + this->hidden->mi = *pgGetVideoMode(); + + /* Create a picogui application and canvas. We'll populate the canvas later. */ + this->hidden->wApp = pgRegisterApp(PG_APP_NORMAL,"SDL",0); + this->hidden->wCanvas = pgNewWidget(PG_WIDGET_CANVAS,0,0); + pgSetWidget(PGDEFAULT, + PG_WP_SIDE, PG_S_ALL, + 0); + + PG_InitEvents(this); + + /* Determine the current screen size */ + this->info.current_w = this->hidden->mi.lxres; + this->info.current_h = this->hidden->mi.lyres; + + /* Determine the screen depth. + * We change this during the SDL_SetVideoMode implementation... + * Round up to the nearest Bytes per pixel + */ + vformat->BitsPerPixel = this->hidden->mi.bpp; + vformat->BytesPerPixel = this->hidden->mi.bpp >> 3; + if (this->hidden->mi.bpp & 7) + vformat->BytesPerPixel++; + + /* We're done! */ + return(0); +} + +SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return (SDL_Rect **) -1; +} + +SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if ( this->hidden->bitmap ) { + /* Free old bitmap */ + if (current->pixels) { + shmdt(current->pixels); + current->pixels = NULL; + } + pgDelete(this->hidden->bitmap); + } + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Create a new picogui bitmap */ + this->hidden->bitmap = pgCreateBitmap(width,height); + this->hidden->shm = *pgMakeSHMBitmap(this->hidden->bitmap); + current->pixels = shmat(shmget(this->hidden->shm.shm_key, + this->hidden->shm.shm_length,0),NULL,0); + + /* Reset the canvas, and draw persistent and incremental grops. + * Use mapping and offsets to center it. + */ + + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_NUKE, 0); + + /* 0. Set the source position during incremental rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 5, PG_GROP_SETSRC,0,0,0,0); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); + + /* 1. Incremental bitmap rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, + 0,0,0,0,this->hidden->bitmap); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); + + /* 2. Normal bitmap rendering + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, + 0,0,this->hidden->shm.width,this->hidden->shm.height,this->hidden->bitmap); + + /* Set up the new mode framebuffer */ + current->flags = 0; + current->w = this->hidden->shm.width; + current->h = this->hidden->shm.height; + current->pitch = this->hidden->shm.pitch; + + /* Set up pixel format */ + current->format->BitsPerPixel = this->hidden->shm.bpp; + current->format->BytesPerPixel = this->hidden->shm.bpp >> 3; + if (this->hidden->shm.bpp & 7) + current->format->BytesPerPixel++; + current->format->palette = NULL; + current->format->Rmask = this->hidden->shm.red_mask; + current->format->Gmask = this->hidden->shm.green_mask; + current->format->Bmask = this->hidden->shm.blue_mask; + current->format->Amask = this->hidden->shm.alpha_mask; + current->format->Rshift = this->hidden->shm.red_shift; + current->format->Gshift = this->hidden->shm.green_shift; + current->format->Bshift = this->hidden->shm.blue_shift; + current->format->Ashift = this->hidden->shm.alpha_shift; + current->format->Rloss = 8 - this->hidden->shm.red_length; + current->format->Gloss = 8 - this->hidden->shm.green_length; + current->format->Bloss = 8 - this->hidden->shm.blue_length; + current->format->Aloss = 8 - this->hidden->shm.alpha_length; + + /* Draw the app */ + pgUpdate(); + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int PG_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void PG_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int PG_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + for (i = 0; i < numrects; i++) { + if (rects[i].w <= 0 || rects[i].h <= 0) + continue; + + /* Schedule an incremental update for this rectangle, using + * the canvas gropnodes we've loaded beforehand. + */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 0); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, + rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 1); + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, + rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + + /* Go perform the update */ + pgWriteCmd(this->hidden->wCanvas, PGCANVAS_INCREMENTAL, 0); + pgSubUpdate(this->hidden->wCanvas); + } +} + +int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + /* do nothing of note. */ + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void PG_VideoQuit(_THIS) +{ + if (this->screen->pixels != NULL) + { + shmdt(this->screen->pixels); + this->screen->pixels = NULL; + pgDelete(this->hidden->bitmap); + } + pgDelete(this->hidden->wCanvas); + pgDelete(this->hidden->wApp); +} + +void PG_SetCaption(_THIS, const char *title, const char *icon) +{ + if (title != NULL) + pgReplaceText(this->hidden->wApp, title); + pgUpdate(); +} + +/* FIXME: The cursor stuff isn't implemented yet! */ + +WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, + int w, int h, int hot_x, int hot_y) +{ + static WMcursor dummy; + return &dummy; +} + +void PG_FreeWMCursor (_THIS, WMcursor * cursor) +{ +} + +void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ +} + +int PG_ShowWMCursor (_THIS, WMcursor * cursor) +{ + return 1; +} diff --git a/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h new file mode 100644 index 0000000..155f86b --- /dev/null +++ b/3rdparty/SDL/src/video/picogui/SDL_pgvideo.h @@ -0,0 +1,50 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + Micah Dowty + micahjd@users.sourceforge.net +*/ +#include "SDL_config.h" + +#ifndef _SDL_pgvideo_h +#define _SDL_pgvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +#include <picogui.h> +#include <sys/shm.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + pghandle wApp, wCanvas; /* PicoGUI widgets */ + pghandle bitmap; + struct pgshmbitmap shm; /* shared memory info */ + struct pgmodeinfo mi; /* PicoGUI video mode info structure */ +}; + +#endif /* _SDL_pgvideo_h */ diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c new file mode 100644 index 0000000..1b842af --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents.c @@ -0,0 +1,977 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting console events into SDL events */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +/* For parsing /proc */ +#include <dirent.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsevents_c.h" +#include "SDL_gskeys.h" + +#ifndef GPM_NODE_FIFO +#define GPM_NODE_FIFO "/dev/gpmdata" +#endif + +/* The translation tables from a console scancode to a SDL keysym */ +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +static SDLKey keymap[128]; +static Uint16 keymap_temp[128]; /* only used at startup */ +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +static void GS_vgainitkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Don't do anything if we are passed a closed keyboard */ + if ( fd < 0 ) { + return; + } + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* fill keytemp. This replaces SDL_fbkeys.h */ + if ( (map == 0) && (i<128) ) { + keymap_temp[i] = entry.kb_value; + } + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } +} + +int GS_InGraphicsMode(_THIS) +{ + return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); +} + +int GS_EnterGraphicsMode(_THIS) +{ + struct termios keyboard_termios; + + /* Set medium-raw keyboard mode */ + if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) { + + /* Switch to the correct virtual terminal */ + if ( current_vt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + saved_vt = vtstate.v_active; + } + if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); + } + } + + /* Set the terminal input mode */ + if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { + SDL_SetError("Unable to get terminal attributes"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { + SDL_SetError("Unable to get current keyboard mode"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + keyboard_termios = saved_kbd_termios; + keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + keyboard_termios.c_cc[VMIN] = 0; + keyboard_termios.c_cc[VTIME] = 0; + if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set terminal attributes"); + return(-1); + } + /* This will fail if we aren't root or this isn't our tty */ + if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in raw mode"); + return(-1); + } + if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { + GS_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in graphics mode"); + return(-1); + } + } + return(keyboard_fd); +} + +void GS_LeaveGraphicsMode(_THIS) +{ + if ( GS_InGraphicsMode(this) ) { + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); + tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); + saved_kbd_mode = -1; + + /* Head back over to the original virtual terminal */ + if ( saved_vt > 0 ) { + ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); + } + } +} + +void GS_CloseKeyboard(_THIS) +{ + if ( keyboard_fd >= 0 ) { + GS_LeaveGraphicsMode(this); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + } + keyboard_fd = -1; +} + +int GS_OpenKeyboard(_THIS) +{ + /* Open only if not already opened */ + if ( keyboard_fd < 0 ) { + char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + int i, tty0_fd; + + /* Try to query for a free virtual terminal */ + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); + close(tty0_fd); + if ( (geteuid() == 0) && (current_vt > 0) ) { + for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt); + keyboard_fd = open(vtpath, O_RDWR, 0); +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "vtpath = %s, fd = %d\n", + vtpath, keyboard_fd); +#endif /* DEBUG_KEYBOARD */ + + /* This needs to be our controlling tty + so that the kernel ioctl() calls work + */ + if ( keyboard_fd >= 0 ) { + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + } + } + } + if ( keyboard_fd < 0 ) { + /* Last resort, maybe our tty is a usable VT */ + current_vt = 0; + keyboard_fd = open("/dev/tty", O_RDWR); + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "Current VT: %d\n", current_vt); +#endif + saved_kbd_mode = -1; + + /* Make sure that our input is a console terminal */ + { int dummy; + if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { + close(keyboard_fd); + keyboard_fd = -1; + SDL_SetError("Unable to open a console terminal"); + } + } + + /* Set up keymap */ + GS_vgainitkeymaps(keyboard_fd); + } + return(keyboard_fd); +} + +static enum { + MOUSE_NONE = -1, + MOUSE_GPM, /* Note: GPM uses the MSC protocol */ + MOUSE_PS2, + MOUSE_IMPS2, + MOUSE_MS, + MOUSE_BM, + NUM_MOUSE_DRVS +} mouse_drv = MOUSE_NONE; + +void GS_CloseMouse(_THIS) +{ + if ( mouse_fd > 0 ) { + close(mouse_fd); + } + mouse_fd = -1; +} + +/* Returns processes listed in /proc with the desired name */ +static int find_pid(DIR *proc, const char *wanted_name) +{ + struct dirent *entry; + int pid; + + /* First scan proc for the gpm process */ + pid = 0; + while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { + if ( isdigit(entry->d_name[0]) ) { + FILE *status; + char path[PATH_MAX]; + char name[PATH_MAX]; + + SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name); + status=fopen(path, "r"); + if ( status ) { + name[0] = '\0'; + fscanf(status, "Name: %s", name); + if ( SDL_strcmp(name, wanted_name) == 0 ) { + pid = atoi(entry->d_name); + } + fclose(status); + } + } + } + return pid; +} + +/* Returns true if /dev/gpmdata is being written to by gpm */ +static int gpm_available(void) +{ + int available; + DIR *proc; + int pid; + int cmdline, len, arglen; + char path[PATH_MAX]; + char args[PATH_MAX], *arg; + + /* Don't bother looking if the fifo isn't there */ + if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { + return(0); + } + + available = 0; + proc = opendir("/proc"); + if ( proc ) { + while ( (pid=find_pid(proc, "gpm")) > 0 ) { + SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); + cmdline = open(path, O_RDONLY, 0); + if ( cmdline >= 0 ) { + len = read(cmdline, args, sizeof(args)); + arg = args; + while ( len > 0 ) { + if ( SDL_strcmp(arg, "-R") == 0 ) { + available = 1; + } + arglen = SDL_strlen(arg)+1; + len -= arglen; + arg += arglen; + } + close(cmdline); + } + } + closedir(proc); + } + return available; +} + + +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives + * us access to the mousewheel, etc. Returns zero if + * writes to device failed, but you still need to query the + * device to see which mode it's actually in. + */ +static int set_imps2_mode(int fd) +{ + /* If you wanted to control the mouse mode (and we do :) ) ... + Set IMPS/2 protocol: + {0xf3,200,0xf3,100,0xf3,80} + Reset mouse device: + {0xFF} + */ + Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; + Uint8 reset = 0xff; + fd_set fdset; + struct timeval tv; + int retval = 0; + + if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { + if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) { + retval = 1; + } + } + + /* Get rid of any chatter from the above */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + read(fd, temp, sizeof(temp)); + } + + return retval; +} + + +/* Returns true if the mouse uses the IMPS/2 protocol */ +static int detect_imps2(int fd) +{ + int imps2; + + imps2 = 0; + + if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) { + imps2 = 1; + } + if ( ! imps2 ) { + Uint8 query_ps2 = 0xF2; + fd_set fdset; + struct timeval tv; + + /* Get rid of any mouse motion noise */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + read(fd, temp, sizeof(temp)); + } + + /* Query for the type of mouse protocol */ + if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) { + Uint8 ch = 0; + + /* Get the mouse protocol response */ + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 1; + tv.tv_usec = 0; + if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { + break; + } + } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) && + ((ch == 0xFA) || (ch == 0xAA)) ); + + /* Experimental values (Logitech wheelmouse) */ +#ifdef DEBUG_MOUSE +fprintf(stderr, "Last mouse mode: 0x%x\n", ch); +#endif + if ( ch == 3 ) { + imps2 = 1; + } + } + } + return imps2; +} + +int GS_OpenMouse(_THIS) +{ + int i; + const char *mousedev; + const char *mousedrv; + + mousedrv = SDL_getenv("SDL_MOUSEDRV"); + mousedev = SDL_getenv("SDL_MOUSEDEV"); + mouse_fd = -1; + + /* STD MICE */ + + if ( mousedev == NULL ) { + /* FIXME someday... allow multiple mice in this driver */ + char *ps2mice[] = { + "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL + }; + /* First try to use GPM in repeater mode */ + if ( mouse_fd < 0 ) { + if ( gpm_available() ) { + mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using GPM mouse\n"); +#endif + mouse_drv = MOUSE_GPM; + } + } + } + /* Now try to use a modern PS/2 mouse */ + for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { + mouse_fd = open(ps2mice[i], O_RDWR, 0); + if (mouse_fd < 0) { + mouse_fd = open(ps2mice[i], O_RDONLY, 0); + } + if (mouse_fd >= 0) { + /* rcg06112001 Attempt to set IMPS/2 mode */ + if ( i == 0 ) { + set_imps2_mode(mouse_fd); + } + if (detect_imps2(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using IMPS2 mouse\n"); +#endif + mouse_drv = MOUSE_IMPS2; + } else { + mouse_drv = MOUSE_PS2; +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using PS2 mouse\n"); +#endif + } + } + } + /* Next try to use a PPC ADB port mouse */ + if ( mouse_fd < 0 ) { + mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ADB mouse\n"); +#endif + mouse_drv = MOUSE_BM; + } + } + } + /* Default to a serial Microsoft mouse */ + if ( mouse_fd < 0 ) { + if ( mousedev == NULL ) { + mousedev = "/dev/mouse"; + } + mouse_fd = open(mousedev, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + struct termios mouse_termios; + + /* Set the sampling speed to 1200 baud */ + tcgetattr(mouse_fd, &mouse_termios); + mouse_termios.c_iflag = IGNBRK | IGNPAR; + mouse_termios.c_oflag = 0; + mouse_termios.c_lflag = 0; + mouse_termios.c_line = 0; + mouse_termios.c_cc[VTIME] = 0; + mouse_termios.c_cc[VMIN] = 1; + mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; + mouse_termios.c_cflag |= CS8; + mouse_termios.c_cflag |= B1200; + tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using Microsoft mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_MS; + } + } + if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + return(mouse_fd); +} + +static int posted = 0; + +void GS_vgamousecallback(int button, int dx, int dy) +{ + int button_1, button_3; + int button_state; + int state_changed; + int i; + Uint8 state; + + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, 1, dx, dy); + } + + /* Swap button 1 and 3 */ + button_1 = (button & 0x04) >> 2; + button_3 = (button & 0x01) << 2; + button &= ~0x05; + button |= (button_1|button_3); + + /* See what changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ button; + for ( i=0; i<8; ++i ) { + if ( state_changed & (1<<i) ) { + if ( button & (1<<i) ) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i+1, 0, 0); + } + } +} + +/* For now, use GPM, PS/2, and MS protocols + Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) + */ +static void handle_mouse(_THIS) +{ + static int start = 0; + static unsigned char mousebuf[BUFSIZ]; + int i, nread; + int button = 0; + int dx = 0, dy = 0; + int packetsize = 0; + + /* Figure out the mouse packet size */ + switch (mouse_drv) { + case MOUSE_NONE: + /* Ack! */ + read(mouse_fd, mousebuf, BUFSIZ); + return; + case MOUSE_GPM: + packetsize = 5; + break; + case MOUSE_IMPS2: + packetsize = 4; + break; + case MOUSE_PS2: + case MOUSE_MS: + case MOUSE_BM: + packetsize = 3; + break; + case NUM_MOUSE_DRVS: + /* Uh oh.. */ + packetsize = 0; + break; + } + + /* Read as many packets as possible */ + nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); + if ( nread < 0 ) { + return; + } + nread += start; +#ifdef DEBUG_MOUSE + fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); +#endif + for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { + switch (mouse_drv) { + case MOUSE_NONE: + break; + case MOUSE_GPM: + /* GPM protocol has 0x80 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)(mousebuf[i+1]) + + (signed char)(mousebuf[i+3]); + dy = -((signed char)(mousebuf[i+2]) + + (signed char)(mousebuf[i+4])); + break; + case MOUSE_PS2: + /* PS/2 protocol has nothing in high byte */ + if ( (mousebuf[i] & 0xC0) != 0 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2; /*Left*/ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + break; + case MOUSE_IMPS2: + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2 | /*Left*/ + (mousebuf[i] & 0x40) >> 3 | /* 4 */ + (mousebuf[i] & 0x80) >> 3; /* 5 */ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + switch (mousebuf[i+3]&0x0F) { + case 0x0E: /* DX = +1 */ + case 0x02: /* DX = -1 */ + break; + case 0x0F: /* DY = +1 (map button 4) */ + FB_vgamousecallback(button | (1<<3), + 1, 0, 0); + break; + case 0x01: /* DY = -1 (map button 5) */ + FB_vgamousecallback(button | (1<<4), + 1, 0, 0); + break; + } + break; + case MOUSE_MS: + /* Microsoft protocol has 0x40 in high byte */ + if ( (mousebuf[i] & 0x40) != 0x40 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = ((mousebuf[i] & 0x20) >> 3) | + ((mousebuf[i] & 0x10) >> 4); + dx = (signed char)(((mousebuf[i] & 0x03) << 6) | + (mousebuf[i + 1] & 0x3F)); + dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | + (mousebuf[i + 2] & 0x3F)); + break; + case MOUSE_BM: + /* BusMouse protocol has 0xF8 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)mousebuf[i+1]; + dy = -(signed char)mousebuf[i+2]; + break; + case NUM_MOUSE_DRVS: + /* Uh oh.. */ + dx = 0; + dy = 0; + break; + } + GS_vgamousecallback(button, dx, dy); + } + if ( i < nread ) { + SDL_memcpy(mousebuf, &mousebuf[i], (nread-i)); + start = (nread-i); + } else { + start = 0; + } + return; +} + +static void handle_keyboard(_THIS) +{ + unsigned char keybuf[BUFSIZ]; + int i, nread; + int pressed; + int scancode; + SDL_keysym keysym; + + nread = read(keyboard_fd, keybuf, BUFSIZ); + for ( i=0; i<nread; ++i ) { + scancode = keybuf[i] & 0x7F; + if ( keybuf[i] & 0x80 ) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + TranslateKey(scancode, &keysym); + posted += SDL_PrivateKeyboard(pressed, &keysym); + } +} + +void GS_PumpEvents(_THIS) +{ + fd_set fdset; + int max_fd; + static struct timeval zero; + + do { + posted = 0; + + FD_ZERO(&fdset); + max_fd = 0; + if ( keyboard_fd >= 0 ) { + FD_SET(keyboard_fd, &fdset); + if ( max_fd < keyboard_fd ) { + max_fd = keyboard_fd; + } + } + if ( mouse_fd >= 0 ) { + FD_SET(mouse_fd, &fdset); + if ( max_fd < mouse_fd ) { + max_fd = mouse_fd; + } + } + if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { + if ( keyboard_fd >= 0 ) { + if ( FD_ISSET(keyboard_fd, &fdset) ) { + handle_keyboard(this); + } + } + if ( mouse_fd >= 0 ) { + if ( FD_ISSET(mouse_fd, &fdset) ) { + handle_mouse(this); + } + } + } + } while ( posted ); +} + +void GS_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the Linux key translation table */ + + /* First get the ascii keys and others not well handled */ + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(i) { + /* These aren't handled by the x86 kernel keymapping (?) */ + case SCANCODE_PRINTSCREEN: + keymap[i] = SDLK_PRINT; + break; + case SCANCODE_BREAK: + keymap[i] = SDLK_BREAK; + break; + case SCANCODE_BREAK_ALTERNATIVE: + keymap[i] = SDLK_PAUSE; + break; + case SCANCODE_LEFTSHIFT: + keymap[i] = SDLK_LSHIFT; + break; + case SCANCODE_RIGHTSHIFT: + keymap[i] = SDLK_RSHIFT; + break; + case SCANCODE_LEFTCONTROL: + keymap[i] = SDLK_LCTRL; + break; + case SCANCODE_RIGHTCONTROL: + keymap[i] = SDLK_RCTRL; + break; + case SCANCODE_RIGHTWIN: + keymap[i] = SDLK_RSUPER; + break; + case SCANCODE_LEFTWIN: + keymap[i] = SDLK_LSUPER; + break; + case 127: + keymap[i] = SDLK_MENU; + break; + /* this should take care of all standard ascii keys */ + default: + keymap[i] = KVAL(vga_keymap[0][i]); + break; + } + } + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(keymap_temp[i]) { + case K_F1: keymap[i] = SDLK_F1; break; + case K_F2: keymap[i] = SDLK_F2; break; + case K_F3: keymap[i] = SDLK_F3; break; + case K_F4: keymap[i] = SDLK_F4; break; + case K_F5: keymap[i] = SDLK_F5; break; + case K_F6: keymap[i] = SDLK_F6; break; + case K_F7: keymap[i] = SDLK_F7; break; + case K_F8: keymap[i] = SDLK_F8; break; + case K_F9: keymap[i] = SDLK_F9; break; + case K_F10: keymap[i] = SDLK_F10; break; + case K_F11: keymap[i] = SDLK_F11; break; + case K_F12: keymap[i] = SDLK_F12; break; + + case K_DOWN: keymap[i] = SDLK_DOWN; break; + case K_LEFT: keymap[i] = SDLK_LEFT; break; + case K_RIGHT: keymap[i] = SDLK_RIGHT; break; + case K_UP: keymap[i] = SDLK_UP; break; + + case K_P0: keymap[i] = SDLK_KP0; break; + case K_P1: keymap[i] = SDLK_KP1; break; + case K_P2: keymap[i] = SDLK_KP2; break; + case K_P3: keymap[i] = SDLK_KP3; break; + case K_P4: keymap[i] = SDLK_KP4; break; + case K_P5: keymap[i] = SDLK_KP5; break; + case K_P6: keymap[i] = SDLK_KP6; break; + case K_P7: keymap[i] = SDLK_KP7; break; + case K_P8: keymap[i] = SDLK_KP8; break; + case K_P9: keymap[i] = SDLK_KP9; break; + case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; + case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; + case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; + case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; + case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; + case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; + + case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) + keymap[i] = SDLK_LSHIFT; + break; + case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; + case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; + case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) + keymap[i] = SDLK_LCTRL; + break; + case K_CTRLL: keymap[i] = SDLK_LCTRL; break; + case K_CTRLR: keymap[i] = SDLK_RCTRL; break; + case K_ALT: keymap[i] = SDLK_LALT; break; + case K_ALTGR: keymap[i] = SDLK_RALT; break; + + case K_INSERT: keymap[i] = SDLK_INSERT; break; + case K_REMOVE: keymap[i] = SDLK_DELETE; break; + case K_PGUP: keymap[i] = SDLK_PAGEUP; break; + case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; + case K_FIND: keymap[i] = SDLK_HOME; break; + case K_SELECT: keymap[i] = SDLK_END; break; + + case K_NUM: keymap[i] = SDLK_NUMLOCK; break; + case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; + + case K_F13: keymap[i] = SDLK_PRINT; break; + case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; + case K_PAUSE: keymap[i] = SDLK_PAUSE; break; + + case 127: keymap[i] = SDLK_BACKSPACE; break; + + default: break; + } + } +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_ALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_MODE ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h new file mode 100644 index 0000000..6758ab3 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsevents_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gsvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int GS_OpenKeyboard(_THIS); +extern void GS_CloseKeyboard(_THIS); +extern int GS_OpenMouse(_THIS); +extern void GS_CloseMouse(_THIS); +extern int GS_EnterGraphicsMode(_THIS); +extern int GS_InGraphicsMode(_THIS); +extern void GS_LeaveGraphicsMode(_THIS); + +extern void GS_InitOSKeymap(_THIS); +extern void GS_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h b/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h new file mode 100644 index 0000000..2b01b6b --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gskeys.h @@ -0,0 +1,139 @@ + +/* Scancodes for the Linux framebuffer console + - Taken with thanks from SVGAlib 1.4.0 +*/ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c new file mode 100644 index 0000000..e0d320d --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse.c @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/ioctl.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + +/* There isn't any implementation dependent data */ +void GS_FreeWMCursor(_THIS, WMcursor *cursor) +{ + return; +} + +/* There isn't any implementation dependent data */ +WMcursor *GS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + return((WMcursor *)0x01); +} + +static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y) +{ + SDL_Surface *screen; + struct ps2_image image; + SDL_Rect area; + int mouse_y1, mouse_y2; + void *saved_pixels; + int screen_updated; + + /* Lock so we don't interrupt an update with mouse motion */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* Remove the cursor image from the DMA area */ + screen = this->screen; + saved_pixels = screen->pixels; + screen->pixels = mapped_mem + screen->offset; + screen_updated = 0; + if ( cursor_drawn ) { + SDL_EraseCursorNoLock(screen); + cursor_drawn = 0; + screen_updated = 1; + } + + /* Save the current mouse area */ + SDL_MouseRect(&area); + mouse_y1 = area.y; + mouse_y2 = area.y+area.h; + + /* Only draw the new cursor if there was one passed in */ + if ( cursor ) { + /* Set the new location */ + cursor->area.x = (x - cursor->hot_x); + cursor->area.y = (y - cursor->hot_y); + + /* Draw the cursor at the new location */ + if ( (SDL_cursorstate & CURSOR_VISIBLE) && screen->pixels ) { + SDL_DrawCursorNoLock(screen); + cursor_drawn = 1; + screen_updated = 1; + } + } + screen->pixels = saved_pixels; + + /* Update the affected area of the screen */ + if ( screen_updated ) { + SDL_MouseRect(&area); + if ( area.y < mouse_y1 ) { + mouse_y1 = area.y; + } + if ( (area.y+area.h) > mouse_y2 ) { + mouse_y2 = area.y+area.h; + } + image = screen_image; + image.y += screen->offset / screen->pitch + mouse_y1; + image.h = mouse_y2 - mouse_y1; + image.ptr = mapped_mem + + (image.y - screen_image.y) * screen->pitch; + ioctl(console_fd, PS2IOC_LOADIMAGE, &image); + + /* Need to scale offscreen image to TV output */ + if ( image.y > 0 ) { + scaleimage_nonblock(console_fd, + tex_tags_mem, scale_tags_mem); + } + } + + /* We're finished */ + SDL_UnlockCursor(); +} + +void GS_MoveWMCursor(_THIS, int x, int y) +{ + GS_MoveCursor(this, SDL_cursor, x, y); +} + +int GS_ShowWMCursor(_THIS, WMcursor *wmcursor) +{ + SDL_Cursor *cursor; + int x, y; + + /* Draw the cursor at the appropriate location */ + SDL_GetMouseState(&x, &y); + if ( wmcursor ) { + cursor = SDL_cursor; + } else { + cursor = NULL; + } + GS_MoveCursor(this, cursor, x, y); + return(1); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h new file mode 100644 index 0000000..c507ed4 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsmouse_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_gsvideo.h" + +/* This is the maximum size of the cursor sprite */ +#define CURSOR_W 32 +#define CURSOR_H 32 +#define CURSOR_W_POW 5 /* 32 = 2^5 */ +#define CURSOR_H_POW 5 /* 32 = 2^5 */ + +/* Functions to be exported */ +extern void GS_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *GS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern void GS_MoveWMCursor(_THIS, int x, int y); +extern int GS_ShowWMCursor(_THIS, WMcursor *cursor); diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c new file mode 100644 index 0000000..e172c60 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.c @@ -0,0 +1,689 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Framebuffer console based SDL video driver implementation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_gsvideo.h" +#include "SDL_gsmouse_c.h" +#include "SDL_gsevents_c.h" +#include "SDL_gsyuv_c.h" + + +/* Initialization/Query functions */ +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void GS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int GS_LockHWSurface(_THIS, SDL_Surface *surface); +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* GS driver bootstrap functions */ + +static int GS_Available(void) +{ + int console, memory; + + console = open(PS2_DEV_GS, O_RDWR, 0); + if ( console >= 0 ) { + close(console); + } + memory = open(PS2_DEV_MEM, O_RDWR, 0); + if ( memory >= 0 ) { + close(memory); + } + return((console >= 0) && (memory >= 0)); +} + +static void GS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *GS_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + mouse_fd = -1; + keyboard_fd = -1; + + /* Set the function pointers */ + this->VideoInit = GS_VideoInit; + this->ListModes = GS_ListModes; + this->SetVideoMode = GS_SetVideoMode; + this->CreateYUVOverlay = GS_CreateYUVOverlay; + this->SetColors = GS_SetColors; + this->UpdateRects = NULL; + this->VideoQuit = GS_VideoQuit; + this->AllocHWSurface = GS_AllocHWSurface; + this->CheckHWBlit = NULL; + this->FillHWRect = NULL; + this->SetHWColorKey = NULL; + this->SetHWAlpha = NULL; + this->LockHWSurface = GS_LockHWSurface; + this->UnlockHWSurface = GS_UnlockHWSurface; + this->FlipHWSurface = NULL; + this->FreeHWSurface = GS_FreeHWSurface; + this->SetIcon = NULL; + this->SetCaption = NULL; + this->GetWMInfo = NULL; + this->FreeWMCursor = GS_FreeWMCursor; + this->CreateWMCursor = GS_CreateWMCursor; + this->ShowWMCursor = GS_ShowWMCursor; + this->MoveWMCursor = GS_MoveWMCursor; + this->InitOSKeymap = GS_InitOSKeymap; + this->PumpEvents = GS_PumpEvents; + + this->free = GS_DeleteDevice; + + return this; +} + +VideoBootStrap PS2GS_bootstrap = { + "ps2gs", "PlayStation 2 Graphics Synthesizer", + GS_Available, GS_CreateDevice +}; + +/* These are the pixel formats for the 32, 24, and 16 bit video modes */ +static struct { + int bpp; + Uint32 r; + Uint32 g; + Uint32 b; +} GS_pixelmasks[] = { + { 32, 0x000000FF, /* RGB little-endian */ + 0x0000FF00, + 0x00FF0000 }, + { 24, 0x000000FF, /* RGB little-endian */ + 0x0000FF00, + 0x00FF0000 }, + { 16, 0x0000001f, /* RGB little-endian */ + 0x000003e0, + 0x00007c00 }, +}; +/* This is a mapping from SDL bytes-per-pixel to GS pixel format */ +static int GS_formatmap[] = { + -1, /* 0 bpp, not a legal value */ + -1, /* 8 bpp, not supported (yet?) */ + PS2_GS_PSMCT16, /* 16 bpp */ + PS2_GS_PSMCT24, /* 24 bpp */ + PS2_GS_PSMCT32 /* 32 bpp */ +}; + +static unsigned long long head_tags[] __attribute__((aligned(16))) = { + 4 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 0, /* 2 */ + PS2_GS_BITBLTBUF, + 0, /* 4 */ + PS2_GS_TRXPOS, + 0, /* 6 */ + PS2_GS_TRXREG, + 0, /* 8 */ + PS2_GS_TRXDIR +}; + +#define MAXIMG (32767 * 16) +#define MAXTAGS 8 + +static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size, + unsigned long long *hm, + unsigned long long *im) +{ + struct ps2_plist plist; + struct ps2_packet packet[1 + MAXTAGS * 2]; + int isize; + int pnum, it, eop; + char *data; + + /* initialize the variables */ + data = (char *)image->ptr; + pnum = it = eop = 0; + plist.packet = packet; + + /* make BITBLT packet */ + packet[pnum].ptr = hm; + packet[pnum].len = sizeof(head_tags); + pnum++; + hm[2] = ((unsigned long long)image->fbp << 32) | + ((unsigned long long)image->fbw << 48) | + ((unsigned long long)image->psm << 56); + hm[4] = ((unsigned long long)image->x << 32) | + ((unsigned long long)image->y << 48); + hm[6] = (unsigned long long)image->w | + ((unsigned long long)image->h << 32); + + /* make image mode tags */ + while (!eop) { + isize = size > MAXIMG ? MAXIMG : size; + size -= isize; + eop = (size == 0); + + packet[pnum].ptr = &im[it]; + packet[pnum].len = sizeof(unsigned long long) * 2; + pnum++; + im[it++] = (isize >> 4) | (eop ? (1 << 15) : 0) | (2LL << 58); + im[it++] = 0; + + packet[pnum].ptr = (void *)data; + packet[pnum].len = isize; + pnum++; + data += isize; + } + plist.num = pnum; + + return ioctl(fd, PS2IOC_SENDL, &plist); +} + +static unsigned long long tex_tags[] __attribute__((aligned(16))) = { + 3 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 0, /* 2 */ + PS2_GS_TEX0_1, + (1 << 5) + (1 << 6), + PS2_GS_TEX1_1, + 0, + PS2_GS_TEXFLUSH +}; +static unsigned long long scale_tags[] __attribute__((aligned(16))) = { + 5 | (1LL << 60), /* GIFtag */ + 0x0e, /* A+D */ + 6 + (1 << 4) + (1 << 8), + PS2_GS_PRIM, + ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), + PS2_GS_UV, + ((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16), + PS2_GS_XYZ2, + 0, /* 8 */ + PS2_GS_UV, + 0, /* 10 */ + PS2_GS_XYZ2 +}; + + +int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm) +{ + struct ps2_plist plist; + struct ps2_packet packet[2]; + + /* initialize the variables */ + plist.num = 2; + plist.packet = packet; + + packet[0].ptr = tm; + packet[0].len = sizeof(tex_tags); + packet[1].ptr = sm; + packet[1].len = sizeof(scale_tags); + + return ioctl(fd, PS2IOC_SENDL, &plist); +} + +static int power_of_2(int value) +{ + int shift; + + for ( shift = 0; (1<<shift) < value; ++shift ) { + /* Keep looking */ ; + } + return(shift); +} + +static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + struct ps2_screeninfo vinfo; + + /* Initialize the library */ + console_fd = open(PS2_DEV_GS, O_RDWR, 0); + if ( console_fd < 0 ) { + SDL_SetError("Unable to open %s", PS2_DEV_GS); + return(-1); + } + memory_fd = open(PS2_DEV_MEM, O_RDWR, 0); + if ( memory_fd < 0 ) { + close(console_fd); + console_fd = -1; + SDL_SetError("Unable to open %s", PS2_DEV_MEM); + return(-1); + } + + if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { + close(memory_fd); + close(console_fd); + console_fd = -1; + SDL_SetError("Couldn't get console pixel format"); + return(-1); + } + + /* Determine the current screen size */ + this->info.current_w = vinfo.w; + this->info.current_h = vinfo.h; + + /* Determine the current screen depth */ + switch (vinfo.psm) { + /* Supported pixel formats */ + case PS2_GS_PSMCT32: + case PS2_GS_PSMCT24: + case PS2_GS_PSMCT16: + break; + default: + GS_VideoQuit(this); + SDL_SetError("Unknown console pixel format: %d", vinfo.psm); + return(-1); + } + vformat->BitsPerPixel = GS_pixelmasks[vinfo.psm].bpp; + vformat->Rmask = GS_pixelmasks[vinfo.psm].r; + vformat->Gmask = GS_pixelmasks[vinfo.psm].g; + vformat->Bmask = GS_pixelmasks[vinfo.psm].b; + saved_vinfo = vinfo; + + /* Enable mouse and keyboard support */ + if ( GS_OpenKeyboard(this) < 0 ) { + GS_VideoQuit(this); + SDL_SetError("Unable to open keyboard"); + return(-1); + } + if ( GS_OpenMouse(this) < 0 ) { + const char *sdl_nomouse; + + sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); + if ( ! sdl_nomouse ) { + GS_VideoQuit(this); + SDL_SetError("Unable to open mouse"); + return(-1); + } + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + static SDL_Rect GS_vesa_mode_list[] = { + { 0, 0, 1280, 1024 }, + { 0, 0, 1024, 768 }, + { 0, 0, 800, 600 }, + { 0, 0, 640, 480 } + }; + static SDL_Rect *GS_vesa_modes[] = { + &GS_vesa_mode_list[0], + &GS_vesa_mode_list[1], + &GS_vesa_mode_list[2], + &GS_vesa_mode_list[3], + NULL + }; + static SDL_Rect GS_tvout_stretch; + static SDL_Rect GS_tvout_mode; + static SDL_Rect *GS_tvout_modes[3]; + SDL_Rect **modes = NULL; + + switch (format->BitsPerPixel) { + case 16: + case 24: + case 32: + if ( saved_vinfo.mode == PS2_GS_VESA ) { + modes = GS_vesa_modes; + } else { + int i, j = 0; + +// FIXME - what's wrong with the stretch code at 16 bpp? +if ( format->BitsPerPixel != 32 ) break; + /* Add a mode that we could possibly stretch to */ + for ( i=0; GS_vesa_modes[i]; ++i ) { + if ( (GS_vesa_modes[i]->w == saved_vinfo.w) && + (GS_vesa_modes[i]->h != saved_vinfo.h) ) { + GS_tvout_stretch.w=GS_vesa_modes[i]->w; + GS_tvout_stretch.h=GS_vesa_modes[i]->h; + GS_tvout_modes[j++] = &GS_tvout_stretch; + break; + } + } + /* Add the current TV video mode */ + GS_tvout_mode.w = saved_vinfo.w; + GS_tvout_mode.h = saved_vinfo.h; + GS_tvout_modes[j++] = &GS_tvout_mode; + GS_tvout_modes[j++] = NULL; + + /* Return the created list of modes */ + modes = GS_tvout_modes; + } + break; + default: + break; + } + return(modes); +} + +/* Various screen update functions available */ +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects); + +static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct ps2_screeninfo vinfo; + + /* Set the terminal into graphics mode */ + if ( GS_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, PS2IOC_GSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } + if ( (vinfo.w != width) || (vinfo.h != height) || + (GS_pixelmasks[vinfo.psm].bpp != bpp) ) { + /* If we're not in VESA mode, we have to scale resolution */ + if ( saved_vinfo.mode == PS2_GS_VESA ) { + switch (width) { + case 640: + vinfo.res = PS2_GS_640x480; + break; + case 800: + vinfo.res = PS2_GS_800x600; + break; + case 1024: + vinfo.res = PS2_GS_1024x768; + break; + case 1280: + vinfo.res = PS2_GS_1280x1024; + break; + default: + SDL_SetError("Unsupported resolution: %dx%d\n", + width, height); + return(NULL); + } + vinfo.res |= (PS2_GS_75Hz << 8); + vinfo.w = width; + vinfo.h = height; + } + vinfo.fbp = 0; + vinfo.psm = GS_formatmap[bpp/8]; + if ( vinfo.psm < 0 ) { + SDL_SetError("Unsupported depth: %d bpp\n", bpp); + return(NULL); + } + if ( ioctl(console_fd, PS2IOC_SSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't set console screen info"); + return(NULL); + } + + /* Unmap the previous DMA buffer */ + if ( mapped_mem ) { + munmap(mapped_mem, mapped_len); + mapped_mem = NULL; + } + } + if ( ! SDL_ReallocFormat(current, GS_pixelmasks[vinfo.psm].bpp, + GS_pixelmasks[vinfo.psm].r, + GS_pixelmasks[vinfo.psm].g, + GS_pixelmasks[vinfo.psm].b, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + + /* Memory map the DMA area for block memory transfer */ + if ( ! mapped_mem ) { + pixels_len = height * current->pitch; + mapped_len = pixels_len + + /* Screen update DMA command area */ + sizeof(head_tags) + ((2 * MAXTAGS) * 16); + if ( saved_vinfo.mode != PS2_GS_VESA ) { + mapped_len += sizeof(tex_tags) + sizeof(scale_tags); + } + mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE, + MAP_SHARED, memory_fd, 0); + if ( mapped_mem == MAP_FAILED ) { + SDL_SetError("Unable to map %d bytes for DMA", + mapped_len); + mapped_mem = NULL; + return(NULL); + } + + /* Set up the entire screen for DMA transfer */ + screen_image.ptr = mapped_mem; + screen_image.fbp = 0; + screen_image.fbw = (vinfo.w + 63) / 64; + screen_image.psm = vinfo.psm; + screen_image.x = 0; + if ( vinfo.h == height ) { + screen_image.y = 0; + } else { + /* Put image offscreen and scale to screen height */ + screen_image.y = vinfo.h; + } + screen_image.w = current->w; + screen_image.h = current->h; + + /* get screen image data size (qword aligned) */ + screen_image_size = (screen_image.w * screen_image.h); + switch (screen_image.psm) { + case PS2_GS_PSMCT32: + screen_image_size *= 4; + break; + case PS2_GS_PSMCT24: + screen_image_size *= 3; + break; + case PS2_GS_PSMCT16: + screen_image_size *= 2; + break; + } + screen_image_size = (screen_image_size + 15) & ~15; + + /* Set up the memory for screen update DMA commands */ + head_tags_mem = (unsigned long long *) + (mapped_mem + pixels_len); + image_tags_mem = (unsigned long long *) + ((caddr_t)head_tags_mem + sizeof(head_tags)); + SDL_memcpy(head_tags_mem, head_tags, sizeof(head_tags)); + if ( saved_vinfo.mode != PS2_GS_VESA ) { + tex_tags_mem = (unsigned long long *) + ((caddr_t)image_tags_mem + ((2*MAXTAGS)*16)); + scale_tags_mem = (unsigned long long *) + ((caddr_t)tex_tags_mem + sizeof(tex_tags)); + SDL_memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags)); + tex_tags_mem[2] = + (vinfo.h * vinfo.w) / 64 + + ((unsigned long long)screen_image.fbw << 14) + + ((unsigned long long)screen_image.psm << 20) + + ((unsigned long long)power_of_2(screen_image.w) << 26) + + ((unsigned long long)power_of_2(screen_image.h) << 30) + + ((unsigned long long)1 << 34) + + ((unsigned long long)1 << 35); + SDL_memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags)); + scale_tags_mem[8] = + ((unsigned long long)screen_image.w * 16) + + (((unsigned long long)screen_image.h * 16) << 16); + scale_tags_mem[10] = + ((unsigned long long)vinfo.w * 16) + + (((unsigned long long)vinfo.h * 16) << 16); + } + } + current->pixels = NULL; + if ( SDL_getenv("SDL_FULLSCREEN_UPDATE") ) { + /* Correct semantics */ + current->flags |= SDL_ASYNCBLIT; + } else { + /* We lie here - the screen memory isn't really the visible + display memory and still requires an update, but this + has the desired effect for most applications. + */ + current->flags |= SDL_HWSURFACE; + } + + /* Set the update rectangle function */ + this->UpdateRects = GS_DMAFullUpdate; + + /* We're done */ + return(current); +} + +/* We don't support hardware surfaces yet */ +static int GS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void GS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int GS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + /* Since mouse motion affects 'pixels', lock it */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* If the cursor is drawn on the DMA area, remove it */ + if ( cursor_drawn ) { + surface->pixels = mapped_mem + surface->offset; + SDL_EraseCursorNoLock(this->screen); + cursor_drawn = 0; + } + + /* Set the surface pixels to the base of the DMA area */ + surface->pixels = mapped_mem; + + /* We're finished! */ + SDL_UnlockCursor(); + } + return(0); +} +static void GS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + /* Since mouse motion affects 'pixels', lock it */ + SDL_LockCursor(); + surface->pixels = NULL; + SDL_UnlockCursor(); + } +} + +static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + /* Lock so we aren't interrupted by a mouse update */ + SDL_LockCursor(); + + /* Make sure any pending DMA has completed */ + if ( dma_pending ) { + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + } + + /* If the mouse is visible, draw it on the DMA area */ + if ( (SDL_cursorstate & CURSOR_VISIBLE) && !cursor_drawn ) { + this->screen->pixels = mapped_mem + this->screen->offset; + SDL_DrawCursorNoLock(this->screen); + this->screen->pixels = NULL; + cursor_drawn = 1; + } + + /* Put the image onto the screen */ + loadimage_nonblock(console_fd, + &screen_image, screen_image_size, + head_tags_mem, image_tags_mem); + if ( screen_image.y > 0 ) { + /* Need to scale offscreen image to TV output */ + ioctl(console_fd, PS2IOC_SENDQCT, 1); + dma_pending = 0; + scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem); + } else { + dma_pending = 1; + } + + /* We're finished! */ + SDL_UnlockCursor(); +} + +static int GS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + return(0); +} + +static void GS_VideoQuit(_THIS) +{ + /* Close console and input file descriptors */ + if ( console_fd > 0 ) { + /* Unmap the video framebuffer */ + if ( mapped_mem ) { + /* Unmap the video framebuffer */ + munmap(mapped_mem, mapped_len); + mapped_mem = NULL; + } + close(memory_fd); + + /* Restore the original video mode */ + if ( GS_InGraphicsMode(this) ) { + ioctl(console_fd, PS2IOC_SSCREENINFO, &saved_vinfo); + } + + /* We're all done with the graphics device */ + close(console_fd); + console_fd = -1; + } + GS_CloseMouse(this); + GS_CloseKeyboard(this); +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h new file mode 100644 index 0000000..8972d70 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsvideo.h @@ -0,0 +1,95 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gsvideo_h +#define _SDL_gsvideo_h + +#include <sys/types.h> +#include <termios.h> +#include <linux/ps2/dev.h> +#include <linux/ps2/gs.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ +struct SDL_PrivateVideoData { + /* Gotta love that simple PS2 graphics interface. :) */ + int console_fd; + int memory_fd; + struct ps2_screeninfo saved_vinfo; + + /* Ye olde linux keyboard code */ + int current_vt; + int saved_vt; + int keyboard_fd; + int saved_kbd_mode; + struct termios saved_kbd_termios; + + /* Ye olde linux mouse code */ + int mouse_fd; + int cursor_drawn; + + /* The memory mapped DMA area and associated variables */ + caddr_t mapped_mem; + int pixels_len; + int mapped_len; + struct ps2_image screen_image; + int screen_image_size; + unsigned long long *head_tags_mem; + unsigned long long *image_tags_mem; + unsigned long long *tex_tags_mem; + unsigned long long *scale_tags_mem; + int dma_pending; +}; +/* Old variable names */ +#define console_fd (this->hidden->console_fd) +#define memory_fd (this->hidden->memory_fd) +#define saved_vinfo (this->hidden->saved_vinfo) +#define current_vt (this->hidden->current_vt) +#define saved_vt (this->hidden->saved_vt) +#define keyboard_fd (this->hidden->keyboard_fd) +#define saved_kbd_mode (this->hidden->saved_kbd_mode) +#define saved_kbd_termios (this->hidden->saved_kbd_termios) +#define mouse_fd (this->hidden->mouse_fd) +#define cursor_drawn (this->hidden->cursor_drawn) +#define mapped_mem (this->hidden->mapped_mem) +#define pixels_len (this->hidden->pixels_len) +#define mapped_len (this->hidden->mapped_len) +#define screen_image (this->hidden->screen_image) +#define screen_image_size (this->hidden->screen_image_size) +#define head_tags_mem (this->hidden->head_tags_mem) +#define image_tags_mem (this->hidden->image_tags_mem) +#define tex_tags_mem (this->hidden->tex_tags_mem) +#define scale_tags_mem (this->hidden->scale_tags_mem) +#define dma_pending (this->hidden->dma_pending) + +/* Shared between the mouse and video code for screen update scaling */ +extern int scaleimage_nonblock(int fd, + unsigned long long *tm, unsigned long long *sm); +#endif /* _SDL_gsvideo_h */ diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c new file mode 100644 index 0000000..ec52a69 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv.c @@ -0,0 +1,461 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the Playstation 2 implementation of YUV video overlays */ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <asm/page.h> /* For definition of PAGE_SIZE */ + +#include "SDL_video.h" +#include "SDL_gsyuv_c.h" +#include "../SDL_yuvfuncs.h" + +/* The maximum number of 16x16 pixel block converted at once */ +#define MAX_MACROBLOCKS 1024 /* 2^10 macroblocks at once */ + +/* The functions used to manipulate video overlays */ +static struct private_yuvhwfuncs gs_yuvfuncs = { + GS_LockYUVOverlay, + GS_UnlockYUVOverlay, + GS_DisplayYUVOverlay, + GS_FreeYUVOverlay +}; + +struct private_yuvhwdata { + int ipu_fd; + Uint8 *pixels; + int macroblocks; + int dma_len; + caddr_t dma_mem; + caddr_t ipu_imem; + caddr_t ipu_omem; + caddr_t dma_tags; + unsigned long long *stretch_x1y1; + unsigned long long *stretch_x2y2; + struct ps2_plist plist; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + +static int power_of_2(int value) +{ + int shift; + + for ( shift = 0; (1<<shift) < value; ++shift ) { + /* Keep looking */ ; + } + return(shift); +} + +SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + int map_offset; + unsigned long long *tags; + caddr_t base; + int bpp; + int fbp, fbw, psm; + int x, y, w, h; + int pnum; + struct ps2_packet *packet; + struct ps2_packet tex_packet; + + /* We can only decode blocks of 16x16 pixels */ + if ( (width & 15) || (height & 15) ) { + SDL_SetError("Overlay width/height must be multiples of 16"); + return(NULL); + } + /* Make sure the image isn't too large for a single DMA transfer */ + if ( ((width/16) * (height/16)) > MAX_MACROBLOCKS ) { + SDL_SetError("Overlay too large (maximum size: %d pixels)", + MAX_MACROBLOCKS * 16 * 16); + return(NULL); + } + + /* Double-check the requested format. For simplicity, we'll only + support planar YUV formats. + */ + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Supported planar YUV format */ + break; + default: + SDL_SetError("Unsupported YUV format"); + return(NULL); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &gs_yuvfuncs; + overlay->hw_overlay = 1; + + /* Create the pixel data */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + hwdata->ipu_fd = -1; + hwdata->pixels = (Uint8 *)SDL_malloc(width*height*2); + if ( hwdata->pixels == NULL ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + hwdata->macroblocks = (width/16) * (height/16); + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = hwdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* Theoretically we could support several concurrent decode + streams queueing up on the same file descriptor, but for + simplicity we'll support only one. Opening the IPU more + than once will fail with EBUSY. + */ + hwdata->ipu_fd = open("/dev/ps2ipu", O_RDWR); + if ( hwdata->ipu_fd < 0 ) { + SDL_FreeYUVOverlay(overlay); + SDL_SetError("Playstation 2 IPU busy"); + return(NULL); + } + + /* Allocate a DMA area for pixel conversion */ + bpp = this->screen->format->BytesPerPixel; + map_offset = (mapped_len + (sysconf(_SC_PAGESIZE) - 1)) & ~(sysconf(_SC_PAGESIZE) - 1); + hwdata->dma_len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8) + + width * height * bpp + + hwdata->macroblocks * (16 * sizeof(long long)) + + 12 * sizeof(long long); + hwdata->dma_mem = mmap(0, hwdata->dma_len, PROT_READ|PROT_WRITE, + MAP_SHARED, memory_fd, map_offset); + if ( hwdata->dma_mem == MAP_FAILED ) { + hwdata->ipu_imem = (caddr_t)0; + SDL_FreeYUVOverlay(overlay); + SDL_SetError("Unable to map %d bytes for DMA", hwdata->dma_len); + return(NULL); + } + hwdata->ipu_imem = hwdata->dma_mem; + hwdata->ipu_omem = hwdata->ipu_imem + + hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); + hwdata->dma_tags = hwdata->ipu_omem + width * height * bpp; + + /* Allocate memory for the DMA packets */ + hwdata->plist.num = hwdata->macroblocks * 4 + 1; + hwdata->plist.packet = (struct ps2_packet *)SDL_malloc( + hwdata->plist.num*sizeof(struct ps2_packet)); + if ( ! hwdata->plist.packet ) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + pnum = 0; + packet = hwdata->plist.packet; + + /* Set up the tags to send the image to the screen */ + tags = (unsigned long long *)hwdata->dma_tags; + base = hwdata->ipu_omem; + fbp = screen_image.fbp; + fbw = screen_image.fbw; + psm = screen_image.psm; + y = screen_image.y + screen_image.h; /* Offscreen video memory */ + for ( h=height/16; h; --h ) { + x = 0; /* Visible video memory */ + for ( w=width/16; w; --w ) { + /* The head tag */ + packet[pnum].ptr = &tags[0]; + packet[pnum].len = 10 * sizeof(*tags); + ++pnum; + tags[0] = 4 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = ((unsigned long long)fbp << 32) | + ((unsigned long long)fbw << 48) | + ((unsigned long long)psm << 56); + tags[3] = PS2_GS_BITBLTBUF; + tags[4] = ((unsigned long long)x << 32) | + ((unsigned long long)y << 48); + tags[5] = PS2_GS_TRXPOS; + tags[6] = (unsigned long long)16 | + ((unsigned long long)16 << 32); + tags[7] = PS2_GS_TRXREG; + tags[8] = 0; + tags[9] = PS2_GS_TRXDIR; + /* Now the actual image data */ + packet[pnum].ptr = &tags[10]; + packet[pnum].len = 2 * sizeof(*tags); + ++pnum; + tags[10] = ((16*16*bpp) >> 4) | (2LL << 58); + tags[11] = 0; + packet[pnum].ptr = (void *)base; + packet[pnum].len = 16 * 16 * bpp; + ++pnum; + packet[pnum].ptr = &tags[12]; + packet[pnum].len = 2 * sizeof(*tags); + ++pnum; + tags[12] = (0 >> 4) | (1 << 15) | (2LL << 58); + tags[13] = 0; + + tags += 16; + base += 16 * 16 * bpp; + + x += 16; + } + y += 16; + } + + /* Set up the texture memory area for the video */ + tex_packet.ptr = tags; + tex_packet.len = 8 * sizeof(*tags); + tags[0] = 3 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 + + ((unsigned long long)fbw << 14) + + ((unsigned long long)psm << 20) + + ((unsigned long long)power_of_2(width) << 26) + + ((unsigned long long)power_of_2(height) << 30) + + ((unsigned long long)1 << 34) + + ((unsigned long long)1 << 35); + tags[3] = PS2_GS_TEX0_1; + tags[4] = (1 << 5) + (1 << 6); + tags[5] = PS2_GS_TEX1_1; + tags[6] = 0; + tags[7] = PS2_GS_TEXFLUSH; + ioctl(console_fd, PS2IOC_SEND, &tex_packet); + + /* Set up the tags for scaling the image */ + packet[pnum].ptr = tags; + packet[pnum].len = 12 * sizeof(*tags); + ++pnum; + tags[0] = 5 | (1LL << 60); /* GIFtag */ + tags[1] = 0x0e; /* A+D */ + tags[2] = 6 + (1 << 4) + (1 << 8); + tags[3] = PS2_GS_PRIM; + tags[4] = ((unsigned long long)0 * 16) + + (((unsigned long long)0 * 16) << 16); + tags[5] = PS2_GS_UV; + tags[6] = 0; /* X1, Y1 */ + tags[7] = PS2_GS_XYZ2; + hwdata->stretch_x1y1 = &tags[6]; + tags[8] = ((unsigned long long)overlay->w * 16) + + (((unsigned long long)overlay->h * 16) << 16); + tags[9] = PS2_GS_UV; + tags[10] = 0; /* X2, Y2 */ + tags[11] = PS2_GS_XYZ2; + hwdata->stretch_x2y2 = &tags[10]; + + /* We're all done.. */ + return(overlay); +} + +int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *hwdata; + __u32 cmd; + struct ps2_packet packet; + int h, w, i; + Uint32 *lum, *Cr, *Cb; + int lum_pitch; + int crb_pitch; + Uint32 *lum_src, *Cr_src, *Cb_src; + Uint32 *srcp, *dstp; + unsigned int x, y; + SDL_Surface *screen; + + /* Find out where the various portions of the image are */ + hwdata = overlay->hwdata; + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = (Uint32 *)overlay->pixels[0]; + Cr = (Uint32 *)overlay->pixels[1]; + Cb = (Uint32 *)overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = (Uint32 *)overlay->pixels[0]; + Cr = (Uint32 *)overlay->pixels[2]; + Cb = (Uint32 *)overlay->pixels[1]; + default: + SDL_SetError("Unsupported YUV format in blit (?)"); + return(-1); + } + dstp = (Uint32 *)hwdata->ipu_imem; + lum_pitch = overlay->w/4; + crb_pitch = (overlay->w/2)/4; + + /* Copy blocks of 16x16 pixels to the DMA area */ + for ( h=overlay->h/16; h; --h ) { + lum_src = lum; + Cr_src = Cr; + Cb_src = Cb; + for ( w=overlay->w/16; w; --w ) { + srcp = lum_src; + for ( i=0; i<16; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + dstp[2] = srcp[2]; + dstp[3] = srcp[3]; + srcp += lum_pitch; + dstp += 4; + } + srcp = Cb_src; + for ( i=0; i<8; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + srcp += crb_pitch; + dstp += 2; + } + srcp = Cr_src; + for ( i=0; i<8; ++i ) { + dstp[0] = srcp[0]; + dstp[1] = srcp[1]; + srcp += crb_pitch; + dstp += 2; + } + lum_src += 16 / 4; + Cb_src += 8 / 4; + Cr_src += 8 / 4; + } + lum += lum_pitch * 16; + Cr += crb_pitch * 8; + Cb += crb_pitch * 8; + } + + /* Send the macroblock data to the IPU */ +#ifdef DEBUG_YUV + fprintf(stderr, "Sending data to IPU..\n"); +#endif + packet.ptr = hwdata->ipu_imem; + packet.len = hwdata->macroblocks * (16 * 16 + 8 * 8 + 8 * 8); + ioctl(hwdata->ipu_fd, PS2IOC_SENDA, &packet); + + /* Trigger the DMA to the IPU for conversion */ +#ifdef DEBUG_YUV + fprintf(stderr, "Trigging conversion command\n"); +#endif + cmd = (7 << 28) + hwdata->macroblocks; + if ( screen_image.psm == PS2_GS_PSMCT16 ) { + cmd += (1 << 27) + /* Output RGB 555 */ + (1 << 26); /* Dither output */ + } + ioctl(hwdata->ipu_fd, PS2IOC_SIPUCMD, &cmd); + + /* Retrieve the converted image from the IPU */ +#ifdef DEBUG_YUV + fprintf(stderr, "Retrieving data from IPU..\n"); +#endif + packet.ptr = hwdata->ipu_omem; + packet.len = overlay->w * overlay->h * + this->screen->format->BytesPerPixel; + ioctl(hwdata->ipu_fd, PS2IOC_RECV, &packet); + +#ifdef DEBUG_YUV + fprintf(stderr, "Copying image to screen..\n"); +#endif + /* Wait for previous DMA to complete */ + ioctl(console_fd, PS2IOC_SENDQCT, 1); + + /* Send the current image to the screen and scale it */ + screen = this->screen; + x = (unsigned int)dst->x; + y = (unsigned int)dst->y; + if ( screen->offset ) { + x += (screen->offset % screen->pitch) / + screen->format->BytesPerPixel; + y += (screen->offset / screen->pitch); + } + y += screen_image.y; + *hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16); + x += (unsigned int)dst->w; + y += (unsigned int)dst->h; + *hwdata->stretch_x2y2 = (x * 16) + ((y * 16) << 16); + return ioctl(console_fd, PS2IOC_SENDL, &hwdata->plist); +} + +void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + if ( hwdata->ipu_fd >= 0 ) { + close(hwdata->ipu_fd); + } + if ( hwdata->dma_mem ) { + munmap(hwdata->dma_mem, hwdata->dma_len); + } + if ( hwdata->plist.packet ) { + SDL_free(hwdata->plist.packet); + } + if ( hwdata->pixels ) { + SDL_free(hwdata->pixels); + } + SDL_free(hwdata); + } +} diff --git a/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h new file mode 100644 index 0000000..d9ffad6 --- /dev/null +++ b/3rdparty/SDL/src/video/ps2gs/SDL_gsyuv_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the Playstation 2 implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_gsvideo.h" + +extern SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int GS_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void GS_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void GS_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3events.c b/3rdparty/SDL/src/video/ps3/SDL_ps3events.c new file mode 100644 index 0000000..e39efcc --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3events.c @@ -0,0 +1,44 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_ps3video.h" +#include "SDL_ps3events_c.h" + +void PS3_PumpEvents(_THIS) +{ + return; +} + +void PS3_InitOSKeymap(_THIS) +{ + return; +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h b/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h new file mode 100644 index 0000000..fd11209 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3events_c.h @@ -0,0 +1,41 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#ifndef _SDL_ps3events_h +#define _SDL_ps3events_h + +#include "SDL_ps3video.h" + +extern void PS3_InitOSKeymap(_THIS); +extern void PS3_PumpEvents(_THIS); + +extern void enable_cursor(int enable); + +#endif /* _SDL_ps3events_h */ + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3video.c b/3rdparty/SDL/src/video/ps3/SDL_ps3video.c new file mode 100644 index 0000000..d5519e0 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3video.c @@ -0,0 +1,621 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_sysvideo.h" +#include "SDL_ps3events_c.h" +#include "SDL_ps3video.h" +#include "SDL_ps3yuv_c.h" +#include "spulibs/spu_common.h" + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <linux/kd.h> +#include <sys/mman.h> + +#include <linux/fb.h> +#include <asm/ps3fb.h> +#include <libspe2.h> +#include <malloc.h> + +/* SDL_VideoDevice functions */ +static int PS3_Available(); +static SDL_VideoDevice *PS3_CreateDevice(int devindex); +static int PS3_VideoInit(_THIS, SDL_PixelFormat * vformat); +static void PS3_VideoQuit(_THIS); +static void PS3_DeleteDevice(SDL_VideoDevice * device); +static SDL_Surface *PS3_SetVideoMode(_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags); +static SDL_Rect **PS3_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags); + +/* Hardware surface functions */ +static int PS3_AllocHWSurface(_THIS, SDL_Surface * surface); +static void PS3_FreeHWSurface(_THIS, SDL_Surface * surface); +static int PS3_LockHWSurface(_THIS, SDL_Surface * surface); +static void PS3_UnlockHWSurface(_THIS, SDL_Surface * surface); +static int PS3_FlipDoubleBuffer(_THIS, SDL_Surface * surface); +static void PS3_DoubleBufferUpdate(_THIS, int numrects, SDL_Rect * rects); + +/* SPU specific functions */ +int SPE_Start(_THIS, spu_data_t * spe_data); +int SPE_Stop(_THIS, spu_data_t * spe_data); +int SPE_Boot(_THIS, spu_data_t * spe_data); +int SPE_Shutdown(_THIS, spu_data_t * spe_data); +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +void SPE_RunContext(void *thread_argp); + +/* Helpers */ +void enable_cursor(int enable); + +/* Stores the SPE executable name of fb_writer_spu */ +extern spe_program_handle_t fb_writer_spu; + +/* SDL PS3 bootstrap function for checking availability */ +static int PS3_Available() +{ + return 1; +} + +/* SDL PS3 bootstrap function for creating the device */ +static SDL_VideoDevice *PS3_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialise SDL_VideoDevice */ + this = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice)); + if (this) { + memset(this, 0, sizeof *this); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc(sizeof(struct SDL_PrivateVideoData)); + } + /* Error handling */ + if ((this == NULL) || (this->hidden == NULL)) { + SDL_OutOfMemory(); + if (this) + SDL_free(this); + return 0; + } + memset(this->hidden, 0, sizeof(struct SDL_PrivateVideoData)); + + /* Set the function pointers */ + this->VideoInit = PS3_VideoInit; + this->ListModes = PS3_ListModes; + this->SetVideoMode = PS3_SetVideoMode; + this->SetColors = 0; + this->CreateYUVOverlay = PS3_CreateYUVOverlay; + this->UpdateRects = 0; + this->VideoQuit = PS3_VideoQuit; + this->AllocHWSurface = PS3_AllocHWSurface; + this->CheckHWBlit = 0; + this->FillHWRect = 0; + this->SetHWColorKey = 0; + this->SetHWAlpha = 0; + this->LockHWSurface = PS3_LockHWSurface; + this->UnlockHWSurface = PS3_UnlockHWSurface; + this->FlipHWSurface = PS3_FlipDoubleBuffer; + this->FreeHWSurface = PS3_FreeHWSurface; + this->SetCaption = 0; + this->SetIcon = 0; + this->IconifyWindow = 0; + this->GrabInput = 0; + this->GetWMInfo = 0; + this->InitOSKeymap = PS3_InitOSKeymap; + this->PumpEvents = PS3_PumpEvents; + + this->free = PS3_DeleteDevice; + + return this; +} + + +/* Bootstraping (see SDL_sysvideo.h) */ +VideoBootStrap PS3_bootstrap = { + "ps3", "PS3 Cell SPU Driver", + PS3_Available, PS3_CreateDevice +}; + + +/* Delete the device */ +static void PS3_DeleteDevice(SDL_VideoDevice * device) +{ + free(device->hidden); + free(device); +} + + +/* Initialise the PS3 video device */ +static int PS3_VideoInit(_THIS, SDL_PixelFormat * vformat) +{ + /* Hide the cursor */ + enable_cursor(0); + + /* Create SPU fb_parms and thread structure */ + fb_parms = (struct fb_writer_parms_t *) + memalign(16, sizeof(struct fb_writer_parms_t)); + fb_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + if (fb_parms == NULL || fb_thread_data == NULL) { + SDL_OutOfMemory(); + return -1; + } + fb_thread_data->program = fb_writer_spu; + fb_thread_data->program_name = "fb_writer_spu"; + fb_thread_data->argp = (void *)fb_parms; + fb_thread_data->keepalive = 1; + fb_thread_data->booted = 0; + + SPE_Start(this, fb_thread_data); + + /* Open the device */ + fb_dev_fd = open(PS3_DEV_FB, O_RDWR); + if (fb_dev_fd < 0) { + SDL_SetError("[PS3] Unable to open device %s", PS3_DEV_FB); + return -1; + } + + /* Get vscreeninfo */ + if (ioctl(fb_dev_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) { + SDL_SetError("[PS3] Can't get VSCREENINFO"); + if (fb_dev_fd >= 0) + close(fb_dev_fd); + fb_dev_fd = -1; + return -1; + } + + /* Fill in our hardware acceleration capabilities */ + this->info.current_w = fb_vinfo.xres; + this->info.current_h = fb_vinfo.yres; + this->info.wm_available = 0; + this->info.hw_available = 1; + + /* Backup the original vinfo to restore later */ + fb_orig_vinfo = fb_vinfo; + + /* 16 and 15 bpp is reported as 16 bpp */ + fb_bits_per_pixel = fb_vinfo.bits_per_pixel; + if (fb_bits_per_pixel == 16) + fb_bits_per_pixel = + fb_vinfo.red.length + fb_vinfo.green.length + + fb_vinfo.blue.length; + + /* Set SDL_PixelFormat */ + vformat->BitsPerPixel = fb_vinfo.bits_per_pixel; + + fb_vinfo.xres_virtual = fb_vinfo.xres; + fb_vinfo.yres_virtual = fb_vinfo.yres; + + /* Put vscreeninfo */ + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) { + SDL_SetError("[PS3] Can't put VSCREENINFO"); + if (fb_dev_fd >= 0) + close(fb_dev_fd); + fb_dev_fd = -1; + return -1; + } + + s_fb_pixel_size = fb_vinfo.bits_per_pixel / 8; + + s_writeable_width = fb_vinfo.xres; + s_writeable_height = fb_vinfo.yres; + + /* Get ps3 screeninfo */ + if (ioctl(fb_dev_fd, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res) < 0) { + SDL_SetError("[PS3] PS3FB_IOCTL_SCREENINFO failed"); + } + deprintf(1, "[PS3] xres:%d yres:%d xoff:%d yoff:%d\n", res.xres, res.yres, res.xoff, res.yoff); + + /* Only use double buffering if enough fb memory is available */ + if (res.num_frames < 2) { + double_buffering = 0; + } else { + double_buffering = 1; + } + + real_width = res.xres; + real_height = res.yres; + + /* + * Take control of frame buffer from kernel, for details see + * http://felter.org/wesley/files/ps3/linux-20061110-docs/ApplicationProgrammingEnvironment.html + * kernel will no longer flip the screen itself + */ + ioctl(fb_dev_fd, PS3FB_IOCTL_ON, 0); + + /* Unblank screen */ + ioctl(fb_dev_fd, FBIOBLANK, 0); + + return 0; +} + + +/* List available PS3 resolutions */ +static SDL_Rect **PS3_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags) +{ + /* A list of video resolutions that we query for (sorted largest to + * smallest) + */ + static SDL_Rect PS3_resolutions[] = { + {0, 0, 1920, 1080}, // 1080p 16:9 HD + {0, 0, 1600, 1200}, // WUXGA + {0, 0, 1280, 1024}, // SXGA + {0, 0, 1280, 720}, // 720p 16:9 HD + {0, 0, 1024, 768}, // WXGA + {0, 0, 1024, 576}, // 576p 16:9 + {0, 0, 853, 480}, // 480p 16:9 + {0, 0, 720, 576}, // 576p 4:3 (PAL) + {0, 0, 720, 480}, // 480p 16:9 (NTSC) + }; + static SDL_Rect *PS3_modes[] = { + &PS3_resolutions[0], + &PS3_resolutions[1], + &PS3_resolutions[2], + &PS3_resolutions[3], + &PS3_resolutions[4], + &PS3_resolutions[5], + &PS3_resolutions[6], + &PS3_resolutions[7], + &PS3_resolutions[8], + NULL + }; + SDL_Rect **modes = PS3_modes; + + return modes; +} + + +/* Get a list of the available display modes */ +static SDL_Surface *PS3_SetVideoMode(_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags) +{ + s_bounded_input_width = width < s_writeable_width ? width : s_writeable_width; + s_bounded_input_height = height < s_writeable_height ? height : s_writeable_height; + s_bounded_input_width_offset = (s_writeable_width - s_bounded_input_width) >> 1; + s_bounded_input_height_offset = (s_writeable_height - s_bounded_input_height) >> 1; + s_input_line_length = width * s_fb_pixel_size; + + current->flags |= flags; + + if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) { + SDL_SetError("[PS3] Can't get fixed screeninfo"); + return NULL; + } + + if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) { + SDL_SetError("[PS3] type %s not supported", + fb_finfo.type); + return NULL; + } + + /* Note: on PS3, fb_finfo.smem_len is enough for double buffering */ + if ((frame_buffer = + (uint8_t *) mmap(0, fb_finfo.smem_len, + PROT_READ | PROT_WRITE, MAP_SHARED, + fb_dev_fd, 0)) == (uint8_t *) - 1) { + SDL_SetError("[PS3] Can't mmap for %s", PS3_DEV_FB); + return NULL; + } else { + current->flags |= SDL_DOUBLEBUF; + } + if (!SDL_ReallocFormat(current, fb_bits_per_pixel, 0, 0, 0, 0)) { + return (NULL); + } + + /* Blank screen */ + memset(frame_buffer, 0x00, fb_finfo.smem_len); + + /* Centering */ + s_center[0] = + frame_buffer + s_bounded_input_width_offset * s_fb_pixel_size + + s_bounded_input_height_offset * fb_finfo.line_length; + s_center[1] = s_center[0] + real_height * fb_finfo.line_length; + s_center_index = 0; + + current->flags |= SDL_FULLSCREEN; + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + + /* Alloc aligned mem for current->pixels */ + s_pixels = memalign(16, current->h * current->pitch); + current->pixels = (void *)s_pixels; + if (!current->pixels) { + SDL_OutOfMemory(); + return NULL; + } + + /* Set the update rectangle function */ + this->UpdateRects = PS3_DoubleBufferUpdate; + + return current; +} + + +/* Copy screen to framebuffer and flip */ +void PS3_DoubleBufferUpdate(_THIS, int numrects, SDL_Rect * rects) +{ + if (converter_thread_data && converter_thread_data->booted) + SPE_WaitForMsg(this, converter_thread_data, SPU_FIN); + + /* Adjust centering */ + s_bounded_input_width_offset = (s_writeable_width - s_bounded_input_width) >> 1; + s_bounded_input_height_offset = (s_writeable_height - s_bounded_input_height) >> 1; + s_center[0] = frame_buffer + s_bounded_input_width_offset * s_fb_pixel_size + + s_bounded_input_height_offset * fb_finfo.line_length; + s_center[1] = s_center[0] + real_height * fb_finfo.line_length; + + /* Set SPU parms for copying the surface to framebuffer */ + fb_parms->data = (unsigned char *)s_pixels; + fb_parms->center = s_center[s_center_index]; + fb_parms->out_line_stride = fb_finfo.line_length; + fb_parms->in_line_stride = s_input_line_length; + fb_parms->bounded_input_height = s_bounded_input_height; + fb_parms->bounded_input_width = s_bounded_input_width; + fb_parms->fb_pixel_size = s_fb_pixel_size; + + deprintf(3, "[PS3->SPU] fb_thread_data->argp = 0x%x\n", fb_thread_data->argp); + + /* Copying.. */ + SPE_SendMsg(this, fb_thread_data, SPU_START); + SPE_SendMsg(this, fb_thread_data, (unsigned int)fb_thread_data->argp); + + SPE_WaitForMsg(this, fb_thread_data, SPU_FIN); + + /* Flip the pages */ + if (double_buffering) + s_center_index = s_center_index ^ 0x01; + PS3_FlipDoubleBuffer(this, this->screen); +} + + +/* Enable/Disable cursor */ +void enable_cursor(int enable) +{ + int fd = open("/dev/console", O_RDWR | O_NONBLOCK); + if (fd >= 0) { + ioctl(fd, KDSETMODE, enable ? KD_TEXT : KD_GRAPHICS); + close(fd); + } +} + + +static int PS3_AllocHWSurface(_THIS, SDL_Surface * surface) +{ + return -1; +} + + +static void PS3_FreeHWSurface(_THIS, SDL_Surface * surface) +{ + return; +} + + +static int PS3_LockHWSurface(_THIS, SDL_Surface * surface) +{ + return 0; +} + + +static void PS3_UnlockHWSurface(_THIS, SDL_Surface * surface) +{ + return; +} + + +/* Blit/Flip buffer to the screen. Must be called after each frame! */ +int PS3_FlipDoubleBuffer(_THIS, SDL_Surface * surface) +{ + unsigned long crt = 0; + /* Wait for vsync */ + deprintf(1, "[PS3] Wait for vsync\n"); + ioctl(fb_dev_fd, FBIO_WAITFORVSYNC, &crt); + /* Page flip */ + deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", s_center_index, s_center[s_center_index]); + ioctl(fb_dev_fd, PS3FB_IOCTL_FSEL, (unsigned long)&s_center_index); + return 1; +} + + +/* Start the SPE thread */ +int SPE_Start(_THIS, spu_data_t * spe_data) +{ + deprintf(2, "[PS3->SPU] Start SPE: %s\n", spe_data->program_name); + if (!(spe_data->booted)) + SPE_Boot(this, spe_data); + + /* To allow re-running of context, spe_ctx_entry has to be set before each call */ + spe_data->entry = SPE_DEFAULT_ENTRY; + spe_data->error_code = 0; + + /* Create SPE thread and run */ + deprintf(2, "[PS3->SPU] Create Thread: %s\n", spe_data->program_name); + if (pthread_create + (&spe_data->thread, NULL, (void *)&SPE_RunContext, (void *)spe_data)) { + deprintf(2, "[PS3->SPU] Could not create pthread for spe: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Could not create pthread for spe"); + return -1; + } + + if (spe_data->keepalive) + SPE_WaitForMsg(this, spe_data, SPU_READY); +} + + +/* Stop the SPE thread */ +int SPE_Stop(_THIS, spu_data_t * spe_data) +{ + deprintf(2, "[PS3->SPU] Stop SPE: %s\n", spe_data->program_name); + /* Wait for SPE thread to complete */ + deprintf(2, "[PS3->SPU] Wait for SPE thread to complete: %s\n", spe_data->program_name); + if (pthread_join(spe_data->thread, NULL)) { + deprintf(2, "[PS3->SPU] Failed joining the thread: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed joining the thread"); + return -1; + } + + return 0; +} + + +/* Create SPE context and load program */ +int SPE_Boot(_THIS, spu_data_t * spe_data) +{ + /* Create SPE context */ + deprintf(2, "[PS3->SPU] Create SPE Context: %s\n", spe_data->program_name); + spe_data->ctx = spe_context_create(0, NULL); + if (spe_data->ctx == NULL) { + deprintf(2, "[PS3->SPU] Failed creating SPE context: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed creating SPE context"); + return -1; + } + + /* Load SPE object into SPE local store */ + deprintf(2, "[PS3->SPU] Load Program into SPE: %s\n", spe_data->program_name); + if (spe_program_load(spe_data->ctx, &spe_data->program)) { + deprintf(2, "[PS3->SPU] Failed loading program into SPE context: %s\n", spe_data->program_name); + SDL_SetError + ("[PS3->SPU] Failed loading program into SPE context"); + return -1; + } + spe_data->booted = 1; + deprintf(2, "[PS3->SPU] SPE boot successful\n"); + + return 0; +} + +/* (Stop and) shutdown the SPE */ +int SPE_Shutdown(_THIS, spu_data_t * spe_data) +{ + if (spe_data->keepalive && spe_data->booted) { + SPE_SendMsg(this, spe_data, SPU_EXIT); + SPE_Stop(this, spe_data); + } + + /* Destroy SPE context */ + deprintf(2, "[PS3->SPU] Destroy SPE context: %s\n", spe_data->program_name); + if (spe_context_destroy(spe_data->ctx)) { + deprintf(2, "[PS3->SPU] Failed destroying context: %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] Failed destroying context"); + return -1; + } + deprintf(2, "[PS3->SPU] SPE shutdown successful: %s\n", spe_data->program_name); + return 0; +} + + +/* Send message to the SPE via mailboxe */ +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg) +{ + deprintf(2, "[PS3->SPU] Sending message %u to %s\n", msg, spe_data->program_name); + /* Send one message, block until message was sent */ + unsigned int spe_in_mbox_msgs[1]; + spe_in_mbox_msgs[0] = msg; + int in_mbox_write = spe_in_mbox_write(spe_data->ctx, spe_in_mbox_msgs, 1, SPE_MBOX_ALL_BLOCKING); + + if (1 > in_mbox_write) { + deprintf(2, "[PS3->SPU] No message could be written to %s\n", spe_data->program_name); + SDL_SetError("[PS3->SPU] No message could be written"); + return -1; + } + return 0; +} + + +/* Read 1 message from SPE, block until at least 1 message was received */ +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg) +{ + deprintf(2, "[PS3->SPU] Waiting for message from %s\n", spe_data->program_name); + unsigned int out_messages[1]; + while (!spe_out_mbox_status(spe_data->ctx)); + int mbox_read = spe_out_mbox_read(spe_data->ctx, out_messages, 1); + deprintf(2, "[PS3->SPU] Got message from %s, message was %u\n", spe_data->program_name, out_messages[0]); + if (out_messages[0] == msg) + return 0; + else + return -1; +} + + +/* Re-runnable invocation of the spe_context_run call */ +void SPE_RunContext(void *thread_argp) +{ + /* argp is the pointer to argument to be passed to the SPE program */ + spu_data_t *args = (spu_data_t *) thread_argp; + deprintf(3, "[PS3->SPU] void* argp=0x%x\n", (unsigned int)args->argp); + + /* Run it.. */ + deprintf(2, "[PS3->SPU] Run SPE program: %s\n", args->program_name); + if (spe_context_run + (args->ctx, &args->entry, 0, (void *)args->argp, NULL, + NULL) < 0) { + deprintf(2, "[PS3->SPU] Failed running SPE context: %s\n", args->program_name); + SDL_SetError("[PS3->SPU] Failed running SPE context: %s", args->program_name); + exit(1); + } + + pthread_exit(NULL); +} + + +/* Quits the video driver */ +static void PS3_VideoQuit(_THIS) +{ + if (fb_dev_fd > 0) { + /* Restore the original video mode */ + if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_orig_vinfo)) + SDL_SetError("[PS3] Can't restore original fb_var_screeninfo"); + + /* Give control of frame buffer to kernel */ + ioctl(fb_dev_fd, PS3FB_IOCTL_OFF, 0); + close(fb_dev_fd); + fb_dev_fd = -1; + } + + if (frame_buffer) { + munmap(frame_buffer, fb_finfo.smem_len); + frame_buffer = 0; + } + + if (fb_parms) + free((void *)fb_parms); + if (fb_thread_data) { + SPE_Shutdown(this, fb_thread_data); + free((void *)fb_thread_data); + } + + if (this->screen) { + if (double_buffering && this->screen->pixels) { + free(this->screen->pixels); + } + this->screen->pixels = NULL; + } + + enable_cursor(1); + deprintf(1, "[PS3] VideoQuit\n"); +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3video.h b/3rdparty/SDL/src/video/ps3/SDL_ps3video.h new file mode 100644 index 0000000..4fe5a2b --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3video.h @@ -0,0 +1,165 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" +#include "../SDL_sysvideo.h" +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "spulibs/spu_common.h" + +#include <libspe2.h> +#include <pthread.h> +#include <linux/types.h> +#include <linux/fb.h> +#include <asm/ps3fb.h> +#include <linux/vt.h> +#include <termios.h> + +#ifndef _SDL_ps3video_h +#define _SDL_ps3video_h + +/* Debugging + * 0: No debug messages + * 1: Video debug messages + * 2: SPE debug messages + * 3: Memory adresses + */ +#define DEBUG_LEVEL 0 + +#ifdef DEBUG_LEVEL +#define deprintf( level, fmt, args... ) \ + do \ +{ \ + if ( (unsigned)(level) <= DEBUG_LEVEL ) \ + { \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); \ + } \ +} while ( 0 ) +#else +#define deprintf( level, fmt, args... ) +#endif + +/* Framebuffer device */ +#define PS3_DEV_FB "/dev/fb0" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice * this + +/* SPU thread data */ +typedef struct spu_data { + spe_context_ptr_t ctx; + pthread_t thread; + spe_program_handle_t program; + char * program_name; + unsigned int booted; + unsigned int keepalive; + unsigned int entry; + int error_code; + void * argp; +} spu_data_t; + +/* Private video driver data needed for Cell support */ +struct SDL_PrivateVideoData +{ + const char * const fb_dev_name; /* FB-device name */ + int fb_dev_fd; /* Descriptor-handle for fb_dev_name */ + uint8_t * frame_buffer; /* mmap'd access to fbdev */ + + /* SPE threading stuff */ + spu_data_t * fb_thread_data; + spu_data_t * scaler_thread_data; + spu_data_t * converter_thread_data; + + /* screeninfo (from linux/fb.h) */ + struct fb_fix_screeninfo fb_finfo; + struct fb_var_screeninfo fb_vinfo; + struct fb_var_screeninfo fb_orig_vinfo; + + /* screeninfo (from asm/ps3fb.h) */ + struct ps3fb_ioctl_res res; + + unsigned int double_buffering; + uint32_t real_width; // real width of screen + uint32_t real_height; // real height of screen + + uint32_t s_fb_pixel_size; // 32: 4 24: 3 16: 2 15: 2 + uint32_t fb_bits_per_pixel; // 32: 32 24: 24 16: 16 15: 15 + + uint32_t config_count; + + uint32_t s_input_line_length; // precalculated: input_width * fb_pixel_size + uint32_t s_bounded_input_width; // width of input (bounded by writeable width) + uint32_t s_bounded_input_height;// height of input (bounded by writeable height) + uint32_t s_bounded_input_width_offset; // offset from the left side (used for centering) + uint32_t s_bounded_input_height_offset; // offset from the upper side (used for centering) + uint32_t s_writeable_width; // width of screen which is writeable + uint32_t s_writeable_height; // height of screen which is writeable + + uint8_t * s_center[2]; // where to begin writing our image (centered?) + uint32_t s_center_index; + + volatile void * s_pixels __attribute__((aligned(128))); + + /* Framebuffer data */ + volatile struct fb_writer_parms_t * fb_parms __attribute__((aligned(128))); +}; + +#define fb_dev_name (this->hidden->fb_dev_name) +#define fb_dev_fd (this->hidden->fb_dev_fd) +#define frame_buffer (this->hidden->frame_buffer) +#define fb_thread_data (this->hidden->fb_thread_data) +#define scaler_thread_data (this->hidden->scaler_thread_data) +#define converter_thread_data (this->hidden->converter_thread_data) +#define fb_parms (this->hidden->fb_parms) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_videomode (this->hidden->SDL_videomode) +#define fb_finfo (this->hidden->fb_finfo) +#define fb_vinfo (this->hidden->fb_vinfo) +#define fb_orig_vinfo (this->hidden->fb_orig_vinfo) +#define res (this->hidden->res) +#define double_buffering (this->hidden->double_buffering) +#define real_width (this->hidden->real_width) +#define real_height (this->hidden->real_height) +#define s_fb_pixel_size (this->hidden->s_fb_pixel_size) +#define fb_bits_per_pixel (this->hidden->fb_bits_per_pixel) +#define config_count (this->hidden->config_count) +#define s_input_line_length (this->hidden->s_input_line_length) +#define s_bounded_input_width (this->hidden->s_bounded_input_width) +#define s_bounded_input_height (this->hidden->s_bounded_input_height) +#define s_bounded_input_width_offset (this->hidden->s_bounded_input_width_offset) +#define s_bounded_input_height_offset (this->hidden->s_bounded_input_height_offset) +#define s_writeable_width (this->hidden->s_writeable_width) +#define s_writeable_height (this->hidden->s_writeable_height) +#define s_center (this->hidden->s_center) +#define s_center_index (this->hidden->s_center_index) +#define s_pixels (this->hidden->s_pixels) + +#endif /* _SDL_ps3video_h */ + + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c new file mode 100644 index 0000000..b1e17da --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv.c @@ -0,0 +1,340 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#include "SDL_video.h" +#include "SDL_ps3video.h" +#include "SDL_ps3yuv_c.h" +#include "../SDL_yuvfuncs.h" +#include "spulibs/spu_common.h" + +/* Stores the executable name */ +extern spe_program_handle_t yuv2rgb_spu; +extern spe_program_handle_t bilin_scaler_spu; + +int SPE_Start(_THIS, spu_data_t * spe_data); +int SPE_Stop(_THIS, spu_data_t * spe_data); +int SPE_Boot(_THIS, spu_data_t * spe_data); +int SPE_Shutdown(_THIS, spu_data_t * spe_data); +int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg); +void SPE_RunContext(void *thread_argp); + + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs ps3_yuvfuncs = { + PS3_LockYUVOverlay, + PS3_UnlockYUVOverlay, + PS3_DisplayYUVOverlay, + PS3_FreeYUVOverlay +}; + + +struct private_yuvhwdata { + SDL_Surface *display; + SDL_Surface *stretch; + volatile void * pixels __attribute__((aligned(128))); + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 * planes[3]; + + unsigned int scale; + + /* Scaled YUV picture */ + Uint8 * scaler_out __attribute__((aligned(128))); + + /* YUV2RGB converter data */ + volatile struct yuv2rgb_parms_t * converter_parms __attribute__((aligned(128))); + + /* Scaler data */ + volatile struct scale_parms_t * scaler_parms __attribute__((aligned(128))); + + Uint8 locked; +}; + + +SDL_Overlay *PS3_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) { + /* Only RGB packed pixel conversion supported */ + if ((display->format->BytesPerPixel != 2) && + (display->format->BytesPerPixel != 3) && + (display->format->BytesPerPixel != 4)) + { + SDL_SetError ("Can't use YUV data on non 16/24/32 bit surfaces"); + return NULL; + } + + /* Double-check the requested format. We'll only support YV12 */ + switch (format) { + case SDL_IYUV_OVERLAY: + case SDL_YV12_OVERLAY: + /* Supported YUV format */ + break; + default: + SDL_SetError("Unsupported YUV format"); + return NULL; + } + + SDL_Overlay* overlay; + struct private_yuvhwdata* hwdata; + + /* Create the overlay structure */ + overlay = (SDL_Overlay *) SDL_calloc(1, sizeof(SDL_Overlay)); + if (overlay == NULL) { + SDL_OutOfMemory(); + return NULL; + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Set the basic attributes */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->hwdata = NULL; + + /* Set up the PS3 YUV surface function structure */ + overlay->hwfuncs = &ps3_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *) SDL_calloc(1, sizeof(struct private_yuvhwdata)); + if (hwdata == NULL) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return NULL; + } + overlay->hwdata = hwdata; + + hwdata->stretch = NULL; + hwdata->display = display; + + /* Create SPU parms structure */ + hwdata->converter_parms = (struct yuv2rgb_parms_t *) memalign(16, sizeof(struct yuv2rgb_parms_t)); + hwdata->scaler_parms = (struct scale_parms_t *) memalign(16, sizeof(struct scale_parms_t)); + if (hwdata->converter_parms == NULL || hwdata->scaler_parms == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + /* Set up the SPEs */ + scaler_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + converter_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t)); + if (converter_thread_data == NULL || scaler_thread_data == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + scaler_thread_data->program = bilin_scaler_spu; + scaler_thread_data->program_name = "bilin_scaler_spu"; + scaler_thread_data->keepalive = 0; + scaler_thread_data->booted = 0; + + converter_thread_data->program = yuv2rgb_spu; + converter_thread_data->program_name = "yuv2rgb_spu"; + converter_thread_data->keepalive = 1; + converter_thread_data->booted = 0; + + SPE_Start(this, converter_thread_data); + + hwdata->pixels = (Uint8 *) memalign(16, width * height + ((width * height) >> 1)); + if (hwdata->pixels == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return(NULL); + } + + /* Find the pitch and offset values for the overlay */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->pitches[0] = overlay->w; + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[0] = (Uint8 *)hwdata->pixels; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + overlay->planes = 3; + break; + default: + /* We should never get here (caught above) */ + break; + } + + /* We're all done.. */ + return overlay; +} + + +int PS3_LockYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return -1; + } + overlay->hwdata->locked = 1; + + return 0; +} + + +void PS3_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return; + } + overlay->hwdata->locked = 0; + + return; +} + + +int PS3_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) { + if ((overlay == NULL) || (overlay->hwdata == NULL)) { + return -1; + } + + Uint8 *lum, *Cr, *Cb; + struct private_yuvhwdata *hwdata; + SDL_Surface *display; + + hwdata = overlay->hwdata; + display = hwdata->display; + + /* Do we have to scale? */ + if ((src->w != dst->w) || (src->h != dst->h) ) { + hwdata->scale = 1; + deprintf(1, "[PS3] We need to scale\n"); + } else { + hwdata->scale = 0; + deprintf(1, "[PS3] No scaling\n"); + } + + /* Find out where the various portions of the image are */ + switch (overlay->format) { + case SDL_YV12_OVERLAY: + lum = (Uint8 *)overlay->pixels[0]; + Cr = (Uint8 *)overlay->pixels[1]; + Cb = (Uint8 *)overlay->pixels[2]; + break; + case SDL_IYUV_OVERLAY: + lum = (Uint8 *)overlay->pixels[0]; + Cr = (Uint8 *)overlay->pixels[2]; + Cb = (Uint8 *)overlay->pixels[1]; + break; + default: + SDL_SetError("Unsupported YUV format in blit"); + return -1; + } + + if (hwdata->scale) { + /* Alloc mem for scaled YUV picture */ + hwdata->scaler_out = (Uint8 *) memalign(16, dst->w * dst->h + ((dst->w * dst->h) >> 1)); + if (hwdata->scaler_out == NULL) { + SDL_FreeYUVOverlay(overlay); + SDL_OutOfMemory(); + return -1; + } + + /* Set parms for scaling */ + hwdata->scaler_parms->src_pixel_width = src->w; + hwdata->scaler_parms->src_pixel_height = src->h; + hwdata->scaler_parms->dst_pixel_width = dst->w; + hwdata->scaler_parms->dst_pixel_height = dst->h; + hwdata->scaler_parms->y_plane = lum; + hwdata->scaler_parms->v_plane = Cr; + hwdata->scaler_parms->u_plane = Cb; + hwdata->scaler_parms->dstBuffer = hwdata->scaler_out; + scaler_thread_data->argp = (void *)hwdata->scaler_parms; + + /* Scale the YUV overlay to given size */ + SPE_Start(this, scaler_thread_data); + SPE_Stop(this, scaler_thread_data); + + /* Set parms for converting after scaling */ + hwdata->converter_parms->y_plane = hwdata->scaler_out; + hwdata->converter_parms->v_plane = hwdata->scaler_out + dst->w * dst->h; + hwdata->converter_parms->u_plane = hwdata->scaler_out + dst->w * dst->h + ((dst->w * dst->h) >> 2); + } else { + /* Set parms for converting */ + hwdata->converter_parms->y_plane = lum; + hwdata->converter_parms->v_plane = Cr; + hwdata->converter_parms->u_plane = Cb; + } + + hwdata->converter_parms->src_pixel_width = dst->w; + hwdata->converter_parms->src_pixel_height = dst->h; + hwdata->converter_parms->dstBuffer = (Uint8 *) s_pixels; + converter_thread_data->argp = (void *)hwdata->converter_parms; + + /* Convert YUV overlay to RGB */ + SPE_SendMsg(this, converter_thread_data, SPU_START); + SPE_SendMsg(this, converter_thread_data, (unsigned int)converter_thread_data->argp); + + /* Centering */ + s_bounded_input_width = dst->w; + s_bounded_input_height = dst->h; + + /* UpdateRects() will do the rest.. */ + SDL_UpdateRects(display, 1, dst); + + if (hwdata->scale) + SDL_free((void *)hwdata->scaler_out); + + return 0; +} + + +void PS3_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) { + if (overlay == NULL) { + return; + } + + if (overlay->hwdata == NULL) { + return; + } + + struct private_yuvhwdata * hwdata; + hwdata = overlay->hwdata; + + if (scaler_thread_data) + SDL_free(scaler_thread_data); + if (converter_thread_data) { + SPE_Shutdown(this, converter_thread_data); + SDL_free(converter_thread_data); + } + + if (hwdata) { + if (hwdata->pixels) + SDL_free((void *)hwdata->pixels); + SDL_free(hwdata); + } + return; +} + diff --git a/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h new file mode 100644 index 0000000..49f9d70 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/SDL_ps3yuv_c.h @@ -0,0 +1,44 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "SDL_config.h" + +#ifndef _SDL_ps3yuv_h +#define _SDL_ps3yuv_h + +/* This is the PS3 implementation of YUV video overlays */ + +#include "SDL_video.h" + +extern SDL_Overlay *PS3_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); +extern int PS3_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); +extern int PS3_LockYUVOverlay(_THIS, SDL_Overlay *overlay); +extern void PS3_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); +extern void PS3_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + +#endif /* _SDL_ps3yuv_h */ + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/Makefile b/3rdparty/SDL/src/video/ps3/spulibs/Makefile new file mode 100644 index 0000000..dc580d9 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/Makefile @@ -0,0 +1,83 @@ +# This Makefile is for building the CELL BE SPU libs +# libfb_writer_spu.so, libyuv2rgb_spu.so, libbilin_scaler_spu.so + +# Toolchain +SPU_GCC=/usr/bin/spu-gcc +PPU_GCC=/usr/bin/gcc +PPU_EMBEDSPU=/usr/bin/embedspu +PPU_AR=/usr/bin/ar +PPU_LD=/usr/bin/ld +INSTALL=/usr/bin/install + +SPU_CFLAGS=-W -Wall -Winline -Wno-main -I. -I /usr/spu/include -I /opt/cell/sdk/usr/spu/include -finline-limit=10000 -Winline -ftree-vectorize -funroll-loops -fmodulo-sched -ffast-math -fPIC -O2 + +# Usually /usr/lib, depending on your distribution +PREFIX=/usr/lib + + +all: libfb_writer_spu.a libfb_writer_spu.so \ + libyuv2rgb_spu.so libyuv2rgb_spu.a \ + libbilin_scaler_spu.so libbilin_scaler_spu.a + + +# fb_writer +fb_writer_spu-embed.o: fb_writer.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o fb_writer_spu fb_writer.c -lm + $(PPU_EMBEDSPU) -m32 fb_writer_spu fb_writer_spu fb_writer_spu-embed.o + +libfb_writer_spu.so: fb_writer_spu-embed.o + $(PPU_LD) -o libfb_writer_spu.so -shared -soname=libfb_writer_spu.so fb_writer_spu-embed.o + +libfb_writer_spu.a: fb_writer_spu-embed.o + $(PPU_AR) -qcs libfb_writer_spu.a fb_writer_spu-embed.o + + +# yuv2rgb_converter +yuv2rgb_spu-embed.o: yuv2rgb_converter.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o yuv2rgb_spu yuv2rgb_converter.c -lm + $(PPU_EMBEDSPU) -m32 yuv2rgb_spu yuv2rgb_spu yuv2rgb_spu-embed.o + +libyuv2rgb_spu.a: yuv2rgb_spu-embed.o + $(PPU_AR) -qcs libyuv2rgb_spu.a yuv2rgb_spu-embed.o + +libyuv2rgb_spu.so: yuv2rgb_spu-embed.o + $(PPU_LD) -o libyuv2rgb_spu.so -shared -soname=libyuv2rgb_spu.so yuv2rgb_spu-embed.o + + +# bilin_scaler +bilin_scaler_spu-embed.o: bilin_scaler.c spu_common.h + $(SPU_GCC) $(SPU_CFLAGS) -o bilin_scaler_spu bilin_scaler.c -lm + $(PPU_EMBEDSPU) -m32 bilin_scaler_spu bilin_scaler_spu bilin_scaler_spu-embed.o + +libbilin_scaler_spu.a: bilin_scaler_spu-embed.o + $(PPU_AR) -qcs libbilin_scaler_spu.a bilin_scaler_spu-embed.o + +libbilin_scaler_spu.so: bilin_scaler_spu-embed.o + $(PPU_LD) -o libbilin_scaler_spu.so -shared -soname=libbilin_scaler_spu.so bilin_scaler_spu-embed.o + +install: libfb_writer_spu.a libfb_writer_spu.so \ + libyuv2rgb_spu.so libyuv2rgb_spu.a \ + libbilin_scaler_spu.so libbilin_scaler_spu.a + $(INSTALL) -c -m 0755 libfb_writer_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libfb_writer_spu.a $(PREFIX)/. + $(INSTALL) -c -m 0755 libyuv2rgb_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libyuv2rgb_spu.a $(PREFIX)/. + $(INSTALL) -c -m 0755 libbilin_scaler_spu.so $(PREFIX)/. + $(INSTALL) -c -m 0655 libbilin_scaler_spu.a $(PREFIX)/. + + +uninstall: $(PREFIX)/libfb_writer_spu.so $(PREFIX)/libfb_writer_spu.a \ + $(PREFIX)/libyuv2rgb_spu.so $(PREFIX)/libyuv2rgb_spu.a \ + $(PREFIX)/libbilin_scaler_spu.so $(PREFIX)/libbilin_scaler_spu.a + rm -f $(PREFIX)/libfb_writer_spu.a + rm -f $(PREFIX)/libfb_writer_spu.so + rm -f $(PREFIX)/libyuv2rgb_spu.so + rm -f $(PREFIX)/libyuv2rgb_spu.a + rm -f $(PREFIX)/libbilin_scaler_spu.so + rm -f $(PREFIX)/libbilin_scaler_spu.a + + +clean: + rm -f bilin_scaler_spu-embed.o libbilin_scaler_spu.so libbilin_scaler_spu.a bilin_scaler_spu + rm -f yuv2rgb_spu-embed.o libyuv2rgb_spu.so libyuv2rgb_spu.a yuv2rgb_spu + rm -f fb_writer_spu-embed.o libfb_writer_spu.so libfb_writer_spu.a fb_writer_spu diff --git a/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c b/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c new file mode 100644 index 0000000..be9b5c6 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/bilin_scaler.c @@ -0,0 +1,2050 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +struct scale_parms_t parms __attribute__((aligned(128))); + +/* A maximum of 8 lines Y, therefore 4 lines V, 4 lines U are stored + * there might be the need to retrieve misaligned data, adjust + * incoming v and u plane to be able to handle this (add 128) + */ +unsigned char y_plane[2][(MAX_HDTV_WIDTH+128)*4] __attribute__((aligned(128))); +unsigned char v_plane[2][(MAX_HDTV_WIDTH+128)*2] __attribute__((aligned(128))); +unsigned char u_plane[2][(MAX_HDTV_WIDTH+128)*2] __attribute__((aligned(128))); + +/* temp-buffer for scaling: 4 lines Y, therefore 2 lines V, 2 lines U */ +unsigned char scaled_y_plane[2][MAX_HDTV_WIDTH*2] __attribute__((aligned(128))); +unsigned char scaled_v_plane[2][MAX_HDTV_WIDTH/2] __attribute__((aligned(128))); +unsigned char scaled_u_plane[2][MAX_HDTV_WIDTH/2] __attribute__((aligned(128))); + +/* some vectors needed by the float to int conversion */ +static const vector float vec_255 = { 255.0f, 255.0f, 255.0f, 255.0f }; +static const vector float vec_0_1 = { 0.1f, 0.1f, 0.1f, 0.1f }; + +void bilinear_scale_line_w8(unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride); +void bilinear_scale_line_w16(unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride); + +void scale_srcw16_dstw16(); +void scale_srcw16_dstw32(); +void scale_srcw32_dstw16(); +void scale_srcw32_dstw32(); + +int main( unsigned long long spe_id __attribute__((unused)), unsigned long long argp ) +{ + deprintf("[SPU] bilin_scaler_spu is up... (on SPE #%llu)\n", spe_id); + /* DMA transfer for the input parameters */ + spu_mfcdma32(&parms, (unsigned int)argp, sizeof(struct scale_parms_t), TAG_INIT, MFC_GET_CMD); + DMA_WAIT_TAG(TAG_INIT); + + deprintf("[SPU] Scale %ux%u to %ux%u\n", parms.src_pixel_width, parms.src_pixel_height, + parms.dst_pixel_width, parms.dst_pixel_height); + + if(parms.src_pixel_width & 0x1f) { + if(parms.dst_pixel_width & 0x1F) { + deprintf("[SPU] Using scale_srcw16_dstw16\n"); + scale_srcw16_dstw16(); + } else { + deprintf("[SPU] Using scale_srcw16_dstw32\n"); + scale_srcw16_dstw32(); + } + } else { + if(parms.dst_pixel_width & 0x1F) { + deprintf("[SPU] Using scale_srcw32_dstw16\n"); + scale_srcw32_dstw16(); + } else { + deprintf("[SPU] Using scale_srcw32_dstw32\n"); + scale_srcw32_dstw32(); + } + } + deprintf("[SPU] bilin_scaler_spu... done!\n"); + + return 0; +} + + +/* + * vfloat_to_vuint() + * + * converts a float vector to an unsinged int vector using saturated + * arithmetic + * + * @param vec_s float vector for conversion + * @returns converted unsigned int vector + */ +inline static vector unsigned int vfloat_to_vuint(vector float vec_s) { + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return spu_convtu(vec_s,0); +} + + +/* + * scale_srcw16_dstw16() + * + * processes an input image of width 16 + * scaling is done to a width 16 + * result stored in RAM + */ +void scale_srcw16_dstw16() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + // for handling misalignment, addresses are precalculated + unsigned char* precalc_src_addr_v = src_addr_v; + unsigned char* precalc_src_addr_u = src_addr_u; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // offset for the v and u plane to handle misalignement + unsigned int curr_lsoff_v = 0, next_lsoff_v; + unsigned int curr_lsoff_u = 0, next_lsoff_u; + + // calculate lower line indices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + /* iteration loop + * within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + * the scaled output is 2 lines y, 1 line v, 1 line u + * the yuv2rgb-converted output is stored to RAM + */ + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + precalc_src_addr_v = src_addr_v+(next_interpl_vu*src_linestride_vu); + next_lsoff_v = ((unsigned int)precalc_src_addr_v)&0x0F; + mfc_get( v_plane[next_src_idx], + ((unsigned int) precalc_src_addr_v)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + precalc_src_addr_u = src_addr_u+(next_interpl_vu*src_linestride_vu); + next_lsoff_u = ((unsigned int)precalc_src_addr_u)&0x0F; + mfc_get( u_plane[next_src_idx], + ((unsigned int) precalc_src_addr_u)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + + curr_lsoff_v = next_lsoff_v; + curr_lsoff_u = next_lsoff_u; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int)dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * scale_srcw16_dstw32() + * + * processes an input image of width 16 + * scaling is done to a width 32 + * yuv2rgb conversion on a width of 32 + * result stored in RAM + */ +void scale_srcw16_dstw32() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + + // for handling misalignment, addresses are precalculated + unsigned char* precalc_src_addr_v = src_addr_v; + unsigned char* precalc_src_addr_u = src_addr_u; + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // offset for the v and u plane to handle misalignement + unsigned int curr_lsoff_v = 0, next_lsoff_v; + unsigned int curr_lsoff_u = 0, next_lsoff_u; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + precalc_src_addr_v = src_addr_v+(next_interpl_vu*src_linestride_vu); + next_lsoff_v = ((unsigned int)precalc_src_addr_v)&0x0F; + mfc_get( v_plane[next_src_idx], + ((unsigned int) precalc_src_addr_v)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + precalc_src_addr_u = src_addr_u+(next_interpl_vu*src_linestride_vu); + next_lsoff_u = ((unsigned int)precalc_src_addr_u)&0x0F; + mfc_get( u_plane[next_src_idx], + ((unsigned int) precalc_src_addr_u)&0xFFFFFFF0, + src_dbl_linestride_vu+(next_lsoff_v<<1), + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + + curr_lsoff_v = next_lsoff_v; + curr_lsoff_u = next_lsoff_u; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w8( v_plane[curr_src_idx]+curr_lsoff_v, + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w8( u_plane[curr_src_idx]+curr_lsoff_u, + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * scale_srcw32_dstw16() + * + * processes an input image of width 32 + * scaling is done to a width 16 + * yuv2rgb conversion on a width of 16 + * result stored in RAM + */ +void scale_srcw32_dstw16() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + mfc_get( v_plane[next_src_idx], + (unsigned int) src_addr_v+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + mfc_get( u_plane[next_src_idx], + (unsigned int) src_addr_u+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/** + * scale_srcw32_dstw32() + * + * processes an input image of width 32 + * scaling is done to a width 32 + * yuv2rgb conversion on a width of 32 + * result stored in RAM + */ +void scale_srcw32_dstw32() { + // extract parameters + unsigned char* dst_addr = (unsigned char *)parms.dstBuffer; + + unsigned int src_width = parms.src_pixel_width; + unsigned int src_height = parms.src_pixel_height; + unsigned int dst_width = parms.dst_pixel_width; + unsigned int dst_height = parms.dst_pixel_height; + + // YVU + unsigned int src_linestride_y = src_width; + unsigned int src_dbl_linestride_y = src_width<<1; + unsigned int src_linestride_vu = src_width>>1; + unsigned int src_dbl_linestride_vu = src_width; + + // scaled YVU + unsigned int scaled_src_linestride_y = dst_width; + + // ram addresses + unsigned char* src_addr_y = parms.y_plane; + unsigned char* src_addr_v = parms.v_plane; + unsigned char* src_addr_u = parms.u_plane; + + unsigned int dst_picture_size = dst_width*dst_height; + + // Sizes for destination + unsigned int dst_dbl_linestride_y = dst_width<<1; + unsigned int dst_dbl_linestride_vu = dst_width>>1; + + // Perform address calculation for Y, V and U in main memory with dst_addr as base + unsigned char* dst_addr_main_memory_y = dst_addr; + unsigned char* dst_addr_main_memory_v = dst_addr + dst_picture_size; + unsigned char* dst_addr_main_memory_u = dst_addr_main_memory_v +(dst_picture_size>>2); + + // calculate scale factors + vector float vf_x_scale = spu_splats( (float)src_width/(float)dst_width ); + float y_scale = (float)src_height/(float)dst_height; + + // double buffered processing + // buffer switching + unsigned int curr_src_idx = 0; + unsigned int curr_dst_idx = 0; + unsigned int next_src_idx, next_dst_idx; + + // 2 lines y as output, upper and lowerline + unsigned int curr_interpl_y_upper = 0; + unsigned int next_interpl_y_upper; + unsigned int curr_interpl_y_lower, next_interpl_y_lower; + // only 1 line v/u output, both planes have the same dimension + unsigned int curr_interpl_vu = 0; + unsigned int next_interpl_vu; + + // weights, calculated in every loop iteration + vector float vf_curr_NSweight_y_upper = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_y_upper; + vector float vf_curr_NSweight_y_lower, vf_next_NSweight_y_lower; + vector float vf_curr_NSweight_vu = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector float vf_next_NSweight_vu; + + // line indices for the src picture + float curr_src_y_upper = 0.0f, next_src_y_upper; + float curr_src_y_lower, next_src_y_lower; + float curr_src_vu = 0.0f, next_src_vu; + + // line indices for the dst picture + unsigned int dst_y=0, dst_vu=0; + + // calculate lower line idices + curr_src_y_lower = ((float)curr_interpl_y_upper+1)*y_scale; + curr_interpl_y_lower = (unsigned int)curr_src_y_lower; + // lower line weight + vf_curr_NSweight_y_lower = spu_splats( curr_src_y_lower-(float)curr_interpl_y_lower ); + + + // start partially double buffered processing + // get initial data, 2 sets of y, 1 set v, 1 set u + mfc_get( y_plane[curr_src_idx], (unsigned int) src_addr_y, src_dbl_linestride_y, RETR_BUF, 0, 0 ); + mfc_get( y_plane[curr_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(curr_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF, + 0, 0 ); + mfc_get( v_plane[curr_src_idx], (unsigned int) src_addr_v, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + mfc_get( u_plane[curr_src_idx], (unsigned int) src_addr_u, src_dbl_linestride_vu, RETR_BUF, 0, 0 ); + + // iteration loop + // within each iteration 4 lines y, 2 lines v, 2 lines u are retrieved + // the scaled output is 2 lines y, 1 line v, 1 line u + // the yuv2rgb-converted output is stored to RAM + for( dst_vu=0; dst_vu<(dst_height>>1)-1; dst_vu++ ) { + dst_y = dst_vu<<1; + + // calculate next indices + next_src_vu = ((float)dst_vu+1)*y_scale; + next_src_y_upper = ((float)dst_y+2)*y_scale; + next_src_y_lower = ((float)dst_y+3)*y_scale; + + next_interpl_vu = (unsigned int) next_src_vu; + next_interpl_y_upper = (unsigned int) next_src_y_upper; + next_interpl_y_lower = (unsigned int) next_src_y_lower; + + // calculate weight NORTH-SOUTH + vf_next_NSweight_vu = spu_splats( next_src_vu-(float)next_interpl_vu ); + vf_next_NSweight_y_upper = spu_splats( next_src_y_upper-(float)next_interpl_y_upper ); + vf_next_NSweight_y_lower = spu_splats( next_src_y_lower-(float)next_interpl_y_lower ); + + // get next lines + next_src_idx = curr_src_idx^1; + next_dst_idx = curr_dst_idx^1; + + // 4 lines y + mfc_get( y_plane[next_src_idx], + (unsigned int) src_addr_y+(next_interpl_y_upper*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + mfc_get( y_plane[next_src_idx]+src_dbl_linestride_y, + (unsigned int) src_addr_y+(next_interpl_y_lower*src_linestride_y), + src_dbl_linestride_y, + RETR_BUF+next_src_idx, + 0, 0 ); + + // 2 lines v + mfc_get( v_plane[next_src_idx], + (unsigned int) src_addr_v+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + // 2 lines u + mfc_get( u_plane[next_src_idx], + (unsigned int) src_addr_u+(next_interpl_vu*src_linestride_vu), + src_dbl_linestride_vu, + RETR_BUF+next_src_idx, + 0, 0 ); + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + //--------------------------------------------------------------------------------------------- + + + // update for next cycle + curr_src_idx = next_src_idx; + curr_dst_idx = next_dst_idx; + + curr_interpl_y_upper = next_interpl_y_upper; + curr_interpl_y_lower = next_interpl_y_lower; + curr_interpl_vu = next_interpl_vu; + + vf_curr_NSweight_y_upper = vf_curr_NSweight_y_upper; + vf_curr_NSweight_y_lower = vf_curr_NSweight_y_lower; + vf_curr_NSweight_vu = vf_next_NSweight_vu; + + curr_src_y_upper = next_src_y_upper; + curr_src_y_lower = next_src_y_lower; + curr_src_vu = next_src_vu; + } + + + + DMA_WAIT_TAG( (RETR_BUF+curr_src_idx) ); + + // scaling + // work line y_upper + bilinear_scale_line_w16( y_plane[curr_src_idx], + scaled_y_plane[curr_src_idx], + dst_width, + vf_x_scale, + vf_curr_NSweight_y_upper, + src_linestride_y ); + // work line y_lower + bilinear_scale_line_w16( y_plane[curr_src_idx]+src_dbl_linestride_y, + scaled_y_plane[curr_src_idx]+scaled_src_linestride_y, + dst_width, + vf_x_scale, + vf_curr_NSweight_y_lower, + src_linestride_y ); + // work line v + bilinear_scale_line_w16( v_plane[curr_src_idx], + scaled_v_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + // work line u + bilinear_scale_line_w16( u_plane[curr_src_idx], + scaled_u_plane[curr_src_idx], + dst_width>>1, + vf_x_scale, + vf_curr_NSweight_vu, + src_linestride_vu ); + + + // Store the result back to main memory into a destination buffer in YUV format + //--------------------------------------------------------------------------------------------- + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + + // Perform three DMA transfers to 3 different locations in the main memory! + // dst_width: Pixel width of destination image + // dst_addr: Destination address in main memory + // dst_vu: Counter which is incremented one by one + // dst_y: Counter which is twice larger than dst_vu (dst_y = 2*dst_vu) + + mfc_put( scaled_y_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_y + (dst_vu*dst_dbl_linestride_y), // Destination in main memory (addr) + dst_dbl_linestride_y, // Two Y lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_v_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_v + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two V lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + mfc_put( scaled_u_plane[curr_src_idx], // What from local store (addr) + (unsigned int) dst_addr_main_memory_u + (dst_vu*dst_dbl_linestride_vu), // Destination in main memory (addr) + dst_dbl_linestride_vu, // Two U lines (depending on the widht of the destination resolution) + STR_BUF+curr_dst_idx, // Tag + 0, 0 ); + + // wait for completion + DMA_WAIT_TAG( (STR_BUF+curr_dst_idx) ); + //--------------------------------------------------------------------------------------------- +} + + +/* + * bilinear_scale_line_w8() + * + * processes a line of yuv-input, width has to be a multiple of 8 + * scaled yuv-output is written to local store buffer + * + * @param src buffer for 2 lines input + * @param dst_ buffer for 1 line output + * @param dst_width the width of the destination line + * @param vf_x_scale a float vector, at each entry is the x_scale-factor + * @param vf_NSweight a float vector, at each position is the weight NORTH/SOUTH for the current line + * @param src_linestride the stride of the srcline + */ +void bilinear_scale_line_w8( unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride ) { + + unsigned char* dst = dst_; + + unsigned int dst_x; + for( dst_x=0; dst_x<dst_width; dst_x+=8) { + // address calculation for loading the 4 surrounding pixel of each calculated + // destination pixel + vector unsigned int vui_dst_x_tmp = spu_splats( dst_x ); + // lower range->first 4 pixel + // upper range->next 4 pixel + vector unsigned int vui_inc_dst_x_lower_range = { 0, 1, 2, 3 }; + vector unsigned int vui_inc_dst_x_upper_range = { 4, 5, 6, 7 }; + vector unsigned int vui_dst_x_lower_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_lower_range ); + vector unsigned int vui_dst_x_upper_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_upper_range ); + + // calculate weight EAST-WEST + vector float vf_dst_x_lower_range = spu_convtf( vui_dst_x_lower_range, 0 ); + vector float vf_dst_x_upper_range = spu_convtf( vui_dst_x_upper_range, 0 ); + vector float vf_src_x_lower_range = spu_mul( vf_dst_x_lower_range, vf_x_scale ); + vector float vf_src_x_upper_range = spu_mul( vf_dst_x_upper_range, vf_x_scale ); + vector unsigned int vui_interpl_x_lower_range = spu_convtu( vf_src_x_lower_range, 0 ); + vector unsigned int vui_interpl_x_upper_range = spu_convtu( vf_src_x_upper_range, 0 ); + vector float vf_interpl_x_lower_range = spu_convtf( vui_interpl_x_lower_range, 0 ); + vector float vf_interpl_x_upper_range = spu_convtf( vui_interpl_x_upper_range, 0 ); + vector float vf_EWweight_lower_range = spu_sub( vf_src_x_lower_range, vf_interpl_x_lower_range ); + vector float vf_EWweight_upper_range = spu_sub( vf_src_x_upper_range, vf_interpl_x_upper_range ); + + // calculate address offset + // + // pixel NORTH WEST + vector unsigned int vui_off_pixelNW_lower_range = vui_interpl_x_lower_range; + vector unsigned int vui_off_pixelNW_upper_range = vui_interpl_x_upper_range; + + // pixel NORTH EAST-->(offpixelNW+1) + vector unsigned int vui_add_1 = { 1, 1, 1, 1 }; + vector unsigned int vui_off_pixelNE_lower_range = spu_add( vui_off_pixelNW_lower_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_upper_range = spu_add( vui_off_pixelNW_upper_range, vui_add_1 ); + + // SOUTH-WEST-->(offpixelNW+src_linestride) + vector unsigned int vui_srclinestride = spu_splats( src_linestride ); + vector unsigned int vui_off_pixelSW_lower_range = spu_add( vui_srclinestride, vui_off_pixelNW_lower_range ); + vector unsigned int vui_off_pixelSW_upper_range = spu_add( vui_srclinestride, vui_off_pixelNW_upper_range ); + + // SOUTH-EAST-->(offpixelNW+src_linestride+1) + vector unsigned int vui_off_pixelSE_lower_range = spu_add( vui_srclinestride, vui_off_pixelNE_lower_range ); + vector unsigned int vui_off_pixelSE_upper_range = spu_add( vui_srclinestride, vui_off_pixelNE_upper_range ); + + // calculate each address + vector unsigned int vui_src_ls = spu_splats( (unsigned int) src ); + vector unsigned int vui_addr_pixelNW_lower_range = spu_add( vui_src_ls, vui_off_pixelNW_lower_range ); + vector unsigned int vui_addr_pixelNW_upper_range = spu_add( vui_src_ls, vui_off_pixelNW_upper_range ); + vector unsigned int vui_addr_pixelNE_lower_range = spu_add( vui_src_ls, vui_off_pixelNE_lower_range ); + vector unsigned int vui_addr_pixelNE_upper_range = spu_add( vui_src_ls, vui_off_pixelNE_upper_range ); + + vector unsigned int vui_addr_pixelSW_lower_range = spu_add( vui_src_ls, vui_off_pixelSW_lower_range ); + vector unsigned int vui_addr_pixelSW_upper_range = spu_add( vui_src_ls, vui_off_pixelSW_upper_range ); + vector unsigned int vui_addr_pixelSE_lower_range = spu_add( vui_src_ls, vui_off_pixelSE_lower_range ); + vector unsigned int vui_addr_pixelSE_upper_range = spu_add( vui_src_ls, vui_off_pixelSE_upper_range ); + + // get each pixel + // + // scalar load, afterwards insertion into the right position + // NORTH WEST + vector unsigned char null_vector = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector unsigned char vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 1 )), + vuc_pixel_NW_lower_range, 7 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 2 )), + vuc_pixel_NW_lower_range, 11 ); + vuc_pixel_NW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_lower_range, 3 )), + vuc_pixel_NW_lower_range, 15 ); + + vector unsigned char vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 1 )), + vuc_pixel_NW_upper_range, 7 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 2 )), + vuc_pixel_NW_upper_range, 11 ); + vuc_pixel_NW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_upper_range, 3 )), + vuc_pixel_NW_upper_range, 15 ); + + // NORTH EAST + vector unsigned char vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 1 )), + vuc_pixel_NE_lower_range, 7 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 2 )), + vuc_pixel_NE_lower_range, 11 ); + vuc_pixel_NE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_lower_range, 3 )), + vuc_pixel_NE_lower_range, 15 ); + + vector unsigned char vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 1 )), + vuc_pixel_NE_upper_range, 7 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 2 )), + vuc_pixel_NE_upper_range, 11 ); + vuc_pixel_NE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_upper_range, 3 )), + vuc_pixel_NE_upper_range, 15 ); + + + // SOUTH WEST + vector unsigned char vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 1 )), + vuc_pixel_SW_lower_range, 7 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 2 )), + vuc_pixel_SW_lower_range, 11 ); + vuc_pixel_SW_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_lower_range, 3 )), + vuc_pixel_SW_lower_range, 15 ); + + vector unsigned char vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 1 )), + vuc_pixel_SW_upper_range, 7 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 2 )), + vuc_pixel_SW_upper_range, 11 ); + vuc_pixel_SW_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_upper_range, 3 )), + vuc_pixel_SW_upper_range, 15 ); + + // SOUTH EAST + vector unsigned char vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 1 )), + vuc_pixel_SE_lower_range, 7 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 2 )), + vuc_pixel_SE_lower_range, 11 ); + vuc_pixel_SE_lower_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_lower_range, 3 )), + vuc_pixel_SE_lower_range, 15 ); + + vector unsigned char vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 1 )), + vuc_pixel_SE_upper_range, 7 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 2 )), + vuc_pixel_SE_upper_range, 11 ); + vuc_pixel_SE_upper_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_upper_range, 3 )), + vuc_pixel_SE_upper_range, 15 ); + + + // convert to float + vector float vf_pixel_NW_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_lower_range, 0 ); + vector float vf_pixel_NW_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_upper_range, 0 ); + + vector float vf_pixel_SW_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_lower_range, 0 ); + vector float vf_pixel_SW_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_upper_range, 0 ); + + vector float vf_pixel_NE_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_lower_range, 0 ); + vector float vf_pixel_NE_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_upper_range, 0 ); + + vector float vf_pixel_SE_lower_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_lower_range, 0 ); + vector float vf_pixel_SE_upper_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_upper_range, 0 ); + + + + // first linear interpolation: EWtop + // EWtop = NW + EWweight*(NE-NW) + // + // lower range + vector float vf_EWtop_lower_range_tmp = spu_sub( vf_pixel_NE_lower_range, vf_pixel_NW_lower_range ); + vector float vf_EWtop_lower_range = spu_madd( vf_EWweight_lower_range, + vf_EWtop_lower_range_tmp, + vf_pixel_NW_lower_range ); + + // upper range + vector float vf_EWtop_upper_range_tmp = spu_sub( vf_pixel_NE_upper_range, vf_pixel_NW_upper_range ); + vector float vf_EWtop_upper_range = spu_madd( vf_EWweight_upper_range, + vf_EWtop_upper_range_tmp, + vf_pixel_NW_upper_range ); + + + + // second linear interpolation: EWbottom + // EWbottom = SW + EWweight*(SE-SW) + // + // lower range + vector float vf_EWbottom_lower_range_tmp = spu_sub( vf_pixel_SE_lower_range, vf_pixel_SW_lower_range ); + vector float vf_EWbottom_lower_range = spu_madd( vf_EWweight_lower_range, + vf_EWbottom_lower_range_tmp, + vf_pixel_SW_lower_range ); + + // upper range + vector float vf_EWbottom_upper_range_tmp = spu_sub( vf_pixel_SE_upper_range, vf_pixel_SW_upper_range ); + vector float vf_EWbottom_upper_range = spu_madd( vf_EWweight_upper_range, + vf_EWbottom_upper_range_tmp, + vf_pixel_SW_upper_range ); + + + + // third linear interpolation: the bilinear interpolated value + // result = EWtop + NSweight*(EWbottom-EWtop); + // + // lower range + vector float vf_result_lower_range_tmp = spu_sub( vf_EWbottom_lower_range, vf_EWtop_lower_range ); + vector float vf_result_lower_range = spu_madd( vf_NSweight, + vf_result_lower_range_tmp, + vf_EWtop_lower_range ); + + // upper range + vector float vf_result_upper_range_tmp = spu_sub( vf_EWbottom_upper_range, vf_EWtop_upper_range ); + vector float vf_result_upper_range = spu_madd( vf_NSweight, + vf_result_upper_range_tmp, + vf_EWtop_upper_range ); + + + // convert back: using saturated arithmetic + vector unsigned int vui_result_lower_range = vfloat_to_vuint( vf_result_lower_range ); + vector unsigned int vui_result_upper_range = vfloat_to_vuint( vf_result_upper_range ); + + // merge results->lower,upper + vector unsigned char vuc_mask_merge_result = { 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + vector unsigned char vuc_result = spu_shuffle( (vector unsigned char) vui_result_lower_range, + (vector unsigned char) vui_result_upper_range, + vuc_mask_merge_result ); + + // partial storing + vector unsigned char vuc_mask_out = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF }; + + + // get currently stored data + vector unsigned char vuc_orig = *((vector unsigned char*)dst); + + // clear currently stored data + vuc_orig = spu_and( vuc_orig, + spu_rlqwbyte( vuc_mask_out, ((unsigned int)dst)&0x0F) ); + + // rotate result according to storing address + vuc_result = spu_rlqwbyte( vuc_result, ((unsigned int)dst)&0x0F ); + + // store result + *((vector unsigned char*)dst) = spu_or( vuc_result, + vuc_orig ); + dst += 8; + } +} + + +/* + * bilinear_scale_line_w16() + * + * processes a line of yuv-input, width has to be a multiple of 16 + * scaled yuv-output is written to local store buffer + * + * @param src buffer for 2 lines input + * @param dst_ buffer for 1 line output + * @param dst_width the width of the destination line + * @param vf_x_scale a float vector, at each entry is the x_scale-factor + * @param vf_NSweight a float vector, at each position is the weight NORTH/SOUTH for the current line + * @param src_linestride the stride of the srcline + */ +void bilinear_scale_line_w16( unsigned char* src, unsigned char* dst_, unsigned int dst_width, vector float vf_x_scale, vector float vf_NSweight, unsigned int src_linestride ) { + + unsigned char* dst = dst_; + + unsigned int dst_x; + for( dst_x=0; dst_x<dst_width; dst_x+=16) { + // address calculation for loading the 4 surrounding pixel of each calculated + // destination pixel + vector unsigned int vui_dst_x_tmp = spu_splats( dst_x ); + // parallelised processing + // first range->pixel 1 2 3 4 + // second range->pixel 5 6 7 8 + // third range->pixel 9 10 11 12 + // fourth range->pixel 13 14 15 16 + vector unsigned int vui_inc_dst_x_first_range = { 0, 1, 2, 3 }; + vector unsigned int vui_inc_dst_x_second_range = { 4, 5, 6, 7 }; + vector unsigned int vui_inc_dst_x_third_range = { 8, 9, 10, 11 }; + vector unsigned int vui_inc_dst_x_fourth_range = { 12, 13, 14, 15 }; + vector unsigned int vui_dst_x_first_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_first_range ); + vector unsigned int vui_dst_x_second_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_second_range ); + vector unsigned int vui_dst_x_third_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_third_range ); + vector unsigned int vui_dst_x_fourth_range = spu_add( vui_dst_x_tmp, vui_inc_dst_x_fourth_range ); + + // calculate weight EAST-WEST + vector float vf_dst_x_first_range = spu_convtf( vui_dst_x_first_range, 0 ); + vector float vf_dst_x_second_range = spu_convtf( vui_dst_x_second_range, 0 ); + vector float vf_dst_x_third_range = spu_convtf( vui_dst_x_third_range, 0 ); + vector float vf_dst_x_fourth_range = spu_convtf( vui_dst_x_fourth_range, 0 ); + vector float vf_src_x_first_range = spu_mul( vf_dst_x_first_range, vf_x_scale ); + vector float vf_src_x_second_range = spu_mul( vf_dst_x_second_range, vf_x_scale ); + vector float vf_src_x_third_range = spu_mul( vf_dst_x_third_range, vf_x_scale ); + vector float vf_src_x_fourth_range = spu_mul( vf_dst_x_fourth_range, vf_x_scale ); + vector unsigned int vui_interpl_x_first_range = spu_convtu( vf_src_x_first_range, 0 ); + vector unsigned int vui_interpl_x_second_range = spu_convtu( vf_src_x_second_range, 0 ); + vector unsigned int vui_interpl_x_third_range = spu_convtu( vf_src_x_third_range, 0 ); + vector unsigned int vui_interpl_x_fourth_range = spu_convtu( vf_src_x_fourth_range, 0 ); + vector float vf_interpl_x_first_range = spu_convtf( vui_interpl_x_first_range, 0 ); + vector float vf_interpl_x_second_range = spu_convtf( vui_interpl_x_second_range, 0 ); + vector float vf_interpl_x_third_range = spu_convtf( vui_interpl_x_third_range, 0 ); + vector float vf_interpl_x_fourth_range = spu_convtf( vui_interpl_x_fourth_range, 0 ); + vector float vf_EWweight_first_range = spu_sub( vf_src_x_first_range, vf_interpl_x_first_range ); + vector float vf_EWweight_second_range = spu_sub( vf_src_x_second_range, vf_interpl_x_second_range ); + vector float vf_EWweight_third_range = spu_sub( vf_src_x_third_range, vf_interpl_x_third_range ); + vector float vf_EWweight_fourth_range = spu_sub( vf_src_x_fourth_range, vf_interpl_x_fourth_range ); + + // calculate address offset + // + // pixel NORTH WEST + vector unsigned int vui_off_pixelNW_first_range = vui_interpl_x_first_range; + vector unsigned int vui_off_pixelNW_second_range = vui_interpl_x_second_range; + vector unsigned int vui_off_pixelNW_third_range = vui_interpl_x_third_range; + vector unsigned int vui_off_pixelNW_fourth_range = vui_interpl_x_fourth_range; + + // pixel NORTH EAST-->(offpixelNW+1) + vector unsigned int vui_add_1 = { 1, 1, 1, 1 }; + vector unsigned int vui_off_pixelNE_first_range = spu_add( vui_off_pixelNW_first_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_second_range = spu_add( vui_off_pixelNW_second_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_third_range = spu_add( vui_off_pixelNW_third_range, vui_add_1 ); + vector unsigned int vui_off_pixelNE_fourth_range = spu_add( vui_off_pixelNW_fourth_range, vui_add_1 ); + + // SOUTH-WEST-->(offpixelNW+src_linestride) + vector unsigned int vui_srclinestride = spu_splats( src_linestride ); + vector unsigned int vui_off_pixelSW_first_range = spu_add( vui_srclinestride, vui_off_pixelNW_first_range ); + vector unsigned int vui_off_pixelSW_second_range = spu_add( vui_srclinestride, vui_off_pixelNW_second_range ); + vector unsigned int vui_off_pixelSW_third_range = spu_add( vui_srclinestride, vui_off_pixelNW_third_range ); + vector unsigned int vui_off_pixelSW_fourth_range = spu_add( vui_srclinestride, vui_off_pixelNW_fourth_range ); + + // SOUTH-EAST-->(offpixelNW+src_linestride+1) + vector unsigned int vui_off_pixelSE_first_range = spu_add( vui_srclinestride, vui_off_pixelNE_first_range ); + vector unsigned int vui_off_pixelSE_second_range = spu_add( vui_srclinestride, vui_off_pixelNE_second_range ); + vector unsigned int vui_off_pixelSE_third_range = spu_add( vui_srclinestride, vui_off_pixelNE_third_range ); + vector unsigned int vui_off_pixelSE_fourth_range = spu_add( vui_srclinestride, vui_off_pixelNE_fourth_range ); + + // calculate each address + vector unsigned int vui_src_ls = spu_splats( (unsigned int) src ); + vector unsigned int vui_addr_pixelNW_first_range = spu_add( vui_src_ls, vui_off_pixelNW_first_range ); + vector unsigned int vui_addr_pixelNW_second_range = spu_add( vui_src_ls, vui_off_pixelNW_second_range ); + vector unsigned int vui_addr_pixelNW_third_range = spu_add( vui_src_ls, vui_off_pixelNW_third_range ); + vector unsigned int vui_addr_pixelNW_fourth_range = spu_add( vui_src_ls, vui_off_pixelNW_fourth_range ); + + vector unsigned int vui_addr_pixelNE_first_range = spu_add( vui_src_ls, vui_off_pixelNE_first_range ); + vector unsigned int vui_addr_pixelNE_second_range = spu_add( vui_src_ls, vui_off_pixelNE_second_range ); + vector unsigned int vui_addr_pixelNE_third_range = spu_add( vui_src_ls, vui_off_pixelNE_third_range ); + vector unsigned int vui_addr_pixelNE_fourth_range = spu_add( vui_src_ls, vui_off_pixelNE_fourth_range ); + + vector unsigned int vui_addr_pixelSW_first_range = spu_add( vui_src_ls, vui_off_pixelSW_first_range ); + vector unsigned int vui_addr_pixelSW_second_range = spu_add( vui_src_ls, vui_off_pixelSW_second_range ); + vector unsigned int vui_addr_pixelSW_third_range = spu_add( vui_src_ls, vui_off_pixelSW_third_range ); + vector unsigned int vui_addr_pixelSW_fourth_range = spu_add( vui_src_ls, vui_off_pixelSW_fourth_range ); + + vector unsigned int vui_addr_pixelSE_first_range = spu_add( vui_src_ls, vui_off_pixelSE_first_range ); + vector unsigned int vui_addr_pixelSE_second_range = spu_add( vui_src_ls, vui_off_pixelSE_second_range ); + vector unsigned int vui_addr_pixelSE_third_range = spu_add( vui_src_ls, vui_off_pixelSE_third_range ); + vector unsigned int vui_addr_pixelSE_fourth_range = spu_add( vui_src_ls, vui_off_pixelSE_fourth_range ); + + + // get each pixel + // + // scalar load, afterwards insertion into the right position + // NORTH WEST + // first range + vector unsigned char null_vector = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + vector unsigned char vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 1 )), + vuc_pixel_NW_first_range, 7 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 2 )), + vuc_pixel_NW_first_range, 11 ); + vuc_pixel_NW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_first_range, 3 )), + vuc_pixel_NW_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 1 )), + vuc_pixel_NW_second_range, 7 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 2 )), + vuc_pixel_NW_second_range, 11 ); + vuc_pixel_NW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_second_range, 3 )), + vuc_pixel_NW_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 1 )), + vuc_pixel_NW_third_range, 7 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 2 )), + vuc_pixel_NW_third_range, 11 ); + vuc_pixel_NW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_third_range, 3 )), + vuc_pixel_NW_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 1 )), + vuc_pixel_NW_fourth_range, 7 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 2 )), + vuc_pixel_NW_fourth_range, 11 ); + vuc_pixel_NW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNW_fourth_range, 3 )), + vuc_pixel_NW_fourth_range, 15 ); + + // NORTH EAST + // first range + vector unsigned char vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 1 )), + vuc_pixel_NE_first_range, 7 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 2 )), + vuc_pixel_NE_first_range, 11 ); + vuc_pixel_NE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_first_range, 3 )), + vuc_pixel_NE_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 1 )), + vuc_pixel_NE_second_range, 7 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 2 )), + vuc_pixel_NE_second_range, 11 ); + vuc_pixel_NE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_second_range, 3 )), + vuc_pixel_NE_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 1 )), + vuc_pixel_NE_third_range, 7 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 2 )), + vuc_pixel_NE_third_range, 11 ); + vuc_pixel_NE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_third_range, 3 )), + vuc_pixel_NE_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 1 )), + vuc_pixel_NE_fourth_range, 7 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 2 )), + vuc_pixel_NE_fourth_range, 11 ); + vuc_pixel_NE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelNE_fourth_range, 3 )), + vuc_pixel_NE_fourth_range, 15 ); + + // SOUTH WEST + // first range + vector unsigned char vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 1 )), + vuc_pixel_SW_first_range, 7 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 2 )), + vuc_pixel_SW_first_range, 11 ); + vuc_pixel_SW_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_first_range, 3 )), + vuc_pixel_SW_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 1 )), + vuc_pixel_SW_second_range, 7 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 2 )), + vuc_pixel_SW_second_range, 11 ); + vuc_pixel_SW_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_second_range, 3 )), + vuc_pixel_SW_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 1 )), + vuc_pixel_SW_third_range, 7 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 2 )), + vuc_pixel_SW_third_range, 11 ); + vuc_pixel_SW_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_third_range, 3 )), + vuc_pixel_SW_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 1 )), + vuc_pixel_SW_fourth_range, 7 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 2 )), + vuc_pixel_SW_fourth_range, 11 ); + vuc_pixel_SW_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSW_fourth_range, 3 )), + vuc_pixel_SW_fourth_range, 15 ); + + // NORTH EAST + // first range + vector unsigned char vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 1 )), + vuc_pixel_SE_first_range, 7 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 2 )), + vuc_pixel_SE_first_range, 11 ); + vuc_pixel_SE_first_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_first_range, 3 )), + vuc_pixel_SE_first_range, 15 ); + // second range + vector unsigned char vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 1 )), + vuc_pixel_SE_second_range, 7 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 2 )), + vuc_pixel_SE_second_range, 11 ); + vuc_pixel_SE_second_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_second_range, 3 )), + vuc_pixel_SE_second_range, 15 ); + // third range + vector unsigned char vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 1 )), + vuc_pixel_SE_third_range, 7 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 2 )), + vuc_pixel_SE_third_range, 11 ); + vuc_pixel_SE_third_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_third_range, 3 )), + vuc_pixel_SE_third_range, 15 ); + // fourth range + vector unsigned char vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 0 )), null_vector, 3 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 1 )), + vuc_pixel_SE_fourth_range, 7 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 2 )), + vuc_pixel_SE_fourth_range, 11 ); + vuc_pixel_SE_fourth_range = spu_insert( + *((unsigned char*) spu_extract( vui_addr_pixelSE_fourth_range, 3 )), + vuc_pixel_SE_fourth_range, 15 ); + + + + // convert to float + vector float vf_pixel_NW_first_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_first_range, 0 ); + vector float vf_pixel_NW_second_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_second_range, 0 ); + vector float vf_pixel_NW_third_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_third_range, 0 ); + vector float vf_pixel_NW_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_NW_fourth_range, 0 ); + + vector float vf_pixel_NE_first_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_first_range, 0 ); + vector float vf_pixel_NE_second_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_second_range, 0 ); + vector float vf_pixel_NE_third_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_third_range, 0 ); + vector float vf_pixel_NE_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_NE_fourth_range, 0 ); + + vector float vf_pixel_SW_first_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_first_range, 0 ); + vector float vf_pixel_SW_second_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_second_range, 0 ); + vector float vf_pixel_SW_third_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_third_range, 0 ); + vector float vf_pixel_SW_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_SW_fourth_range, 0 ); + + vector float vf_pixel_SE_first_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_first_range, 0 ); + vector float vf_pixel_SE_second_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_second_range, 0 ); + vector float vf_pixel_SE_third_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_third_range, 0 ); + vector float vf_pixel_SE_fourth_range = spu_convtf( (vector unsigned int) vuc_pixel_SE_fourth_range, 0 ); + + // first linear interpolation: EWtop + // EWtop = NW + EWweight*(NE-NW) + // + // first range + vector float vf_EWtop_first_range_tmp = spu_sub( vf_pixel_NE_first_range, vf_pixel_NW_first_range ); + vector float vf_EWtop_first_range = spu_madd( vf_EWweight_first_range, + vf_EWtop_first_range_tmp, + vf_pixel_NW_first_range ); + + // second range + vector float vf_EWtop_second_range_tmp = spu_sub( vf_pixel_NE_second_range, vf_pixel_NW_second_range ); + vector float vf_EWtop_second_range = spu_madd( vf_EWweight_second_range, + vf_EWtop_second_range_tmp, + vf_pixel_NW_second_range ); + + // third range + vector float vf_EWtop_third_range_tmp = spu_sub( vf_pixel_NE_third_range, vf_pixel_NW_third_range ); + vector float vf_EWtop_third_range = spu_madd( vf_EWweight_third_range, + vf_EWtop_third_range_tmp, + vf_pixel_NW_third_range ); + + // fourth range + vector float vf_EWtop_fourth_range_tmp = spu_sub( vf_pixel_NE_fourth_range, vf_pixel_NW_fourth_range ); + vector float vf_EWtop_fourth_range = spu_madd( vf_EWweight_fourth_range, + vf_EWtop_fourth_range_tmp, + vf_pixel_NW_fourth_range ); + + + + // second linear interpolation: EWbottom + // EWbottom = SW + EWweight*(SE-SW) + // + // first range + vector float vf_EWbottom_first_range_tmp = spu_sub( vf_pixel_SE_first_range, vf_pixel_SW_first_range ); + vector float vf_EWbottom_first_range = spu_madd( vf_EWweight_first_range, + vf_EWbottom_first_range_tmp, + vf_pixel_SW_first_range ); + + // second range + vector float vf_EWbottom_second_range_tmp = spu_sub( vf_pixel_SE_second_range, vf_pixel_SW_second_range ); + vector float vf_EWbottom_second_range = spu_madd( vf_EWweight_second_range, + vf_EWbottom_second_range_tmp, + vf_pixel_SW_second_range ); + // first range + vector float vf_EWbottom_third_range_tmp = spu_sub( vf_pixel_SE_third_range, vf_pixel_SW_third_range ); + vector float vf_EWbottom_third_range = spu_madd( vf_EWweight_third_range, + vf_EWbottom_third_range_tmp, + vf_pixel_SW_third_range ); + + // first range + vector float vf_EWbottom_fourth_range_tmp = spu_sub( vf_pixel_SE_fourth_range, vf_pixel_SW_fourth_range ); + vector float vf_EWbottom_fourth_range = spu_madd( vf_EWweight_fourth_range, + vf_EWbottom_fourth_range_tmp, + vf_pixel_SW_fourth_range ); + + + + // third linear interpolation: the bilinear interpolated value + // result = EWtop + NSweight*(EWbottom-EWtop); + // + // first range + vector float vf_result_first_range_tmp = spu_sub( vf_EWbottom_first_range, vf_EWtop_first_range ); + vector float vf_result_first_range = spu_madd( vf_NSweight, + vf_result_first_range_tmp, + vf_EWtop_first_range ); + + // second range + vector float vf_result_second_range_tmp = spu_sub( vf_EWbottom_second_range, vf_EWtop_second_range ); + vector float vf_result_second_range = spu_madd( vf_NSweight, + vf_result_second_range_tmp, + vf_EWtop_second_range ); + + // third range + vector float vf_result_third_range_tmp = spu_sub( vf_EWbottom_third_range, vf_EWtop_third_range ); + vector float vf_result_third_range = spu_madd( vf_NSweight, + vf_result_third_range_tmp, + vf_EWtop_third_range ); + + // fourth range + vector float vf_result_fourth_range_tmp = spu_sub( vf_EWbottom_fourth_range, vf_EWtop_fourth_range ); + vector float vf_result_fourth_range = spu_madd( vf_NSweight, + vf_result_fourth_range_tmp, + vf_EWtop_fourth_range ); + + + + // convert back: using saturated arithmetic + vector unsigned int vui_result_first_range = vfloat_to_vuint( vf_result_first_range ); + vector unsigned int vui_result_second_range = vfloat_to_vuint( vf_result_second_range ); + vector unsigned int vui_result_third_range = vfloat_to_vuint( vf_result_third_range ); + vector unsigned int vui_result_fourth_range = vfloat_to_vuint( vf_result_fourth_range ); + + // merge results->lower,upper + vector unsigned char vuc_mask_merge_result_first_second = { 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + vector unsigned char vuc_mask_merge_result_third_fourth = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x03, 0x07, 0x0B, 0x0F, + 0x13, 0x17, 0x1B, 0x1F }; + + vector unsigned char vuc_result_first_second = + spu_shuffle( (vector unsigned char) vui_result_first_range, + (vector unsigned char) vui_result_second_range, + vuc_mask_merge_result_first_second ); + + vector unsigned char vuc_result_third_fourth = + spu_shuffle( (vector unsigned char) vui_result_third_range, + (vector unsigned char) vui_result_fourth_range, + vuc_mask_merge_result_third_fourth ); + + // store result + *((vector unsigned char*)dst) = spu_or( vuc_result_first_second, + vuc_result_third_fourth ); + dst += 16; + } +} + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c b/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c new file mode 100644 index 0000000..0eb51cc --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/fb_writer.c @@ -0,0 +1,193 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> +#include <stdio.h> +#include <string.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +void cpy_to_fb(unsigned int); + +/* fb_writer_spu parms */ +static volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128))); + +/* Code running on SPU */ +int main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused))) +{ + deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id); + uint32_t ea_mfc, mbox; + // send ready message + spu_write_out_mbox(SPU_READY); + + while (1) { + /* Check mailbox */ + mbox = spu_read_in_mbox(); + deprintf("[SPU] Message is %u\n", mbox); + switch (mbox) { + case SPU_EXIT: + deprintf("[SPU] fb_writer goes down...\n"); + return 0; + case SPU_START: + break; + default: + deprintf("[SPU] Cannot handle message\n"); + continue; + } + + /* Tag Manager setup */ + unsigned int tags; + tags = mfc_multi_tag_reserve(5); + if (tags == MFC_TAG_INVALID) { + deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n"); + return 0; + } + + /* Framebuffer parms */ + ea_mfc = spu_read_in_mbox(); + deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc); + spu_mfcdma32(&parms, (unsigned int)ea_mfc, + sizeof(struct fb_writer_parms_t), tags, + MFC_GET_CMD); + deprintf("[SPU] argp = %u\n", (unsigned int)argp); + DMA_WAIT_TAG(tags); + + /* Copy parms->data to framebuffer */ + deprintf("[SPU] Copying to framebuffer started\n"); + cpy_to_fb(tags); + deprintf("[SPU] Copying to framebuffer done!\n"); + + mfc_multi_tag_release(tags, 5); + deprintf("[SPU] fb_writer_spu... done!\n"); + /* Send FIN msg */ + spu_write_out_mbox(SPU_FIN); + } + + return 0; +} + +void cpy_to_fb(unsigned int tag_id_base) +{ + unsigned int i; + unsigned char current_buf; + uint8_t *in = parms.data; + + /* Align fb pointer which was centered before */ + uint8_t *fb = + (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0); + + uint32_t bounded_input_height = parms.bounded_input_height; + uint32_t bounded_input_width = parms.bounded_input_width; + uint32_t fb_pixel_size = parms.fb_pixel_size; + + uint32_t out_line_stride = parms.out_line_stride; + uint32_t in_line_stride = parms.in_line_stride; + uint32_t in_line_size = bounded_input_width * fb_pixel_size; + + current_buf = 0; + + /* Local store buffer */ + static volatile uint8_t buf[4][BUFFER_SIZE] + __attribute__ ((aligned(128))); + /* do 4-times multibuffering using DMA list, process in two steps */ + for (i = 0; i < bounded_input_height >> 2; i++) { + /* first buffer */ + DMA_WAIT_TAG(tag_id_base + 1); + // retrieve buffer + spu_mfcdma32(buf[0], (unsigned int)in, in_line_size, + tag_id_base + 1, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 1); + // store buffer + spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size, + tag_id_base + 1, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* second buffer */ + DMA_WAIT_TAG(tag_id_base + 2); + // retrieve buffer + spu_mfcdma32(buf[1], (unsigned int)in, in_line_size, + tag_id_base + 2, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 2); + // store buffer + spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size, + tag_id_base + 2, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* third buffer */ + DMA_WAIT_TAG(tag_id_base + 3); + // retrieve buffer + spu_mfcdma32(buf[2], (unsigned int)in, in_line_size, + tag_id_base + 3, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 3); + // store buffer + spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size, + tag_id_base + 3, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in, + fb); + + /* fourth buffer */ + DMA_WAIT_TAG(tag_id_base + 4); + // retrieve buffer + spu_mfcdma32(buf[3], (unsigned int)in, in_line_size, + tag_id_base + 4, MFC_GETB_CMD); + DMA_WAIT_TAG(tag_id_base + 4); + // store buffer + spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size, + tag_id_base + 4, MFC_PUTB_CMD); + in += in_line_stride; + fb += out_line_stride; + deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in, + fb); + deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i, + bounded_input_height >> 2); + } + DMA_WAIT_TAG(tag_id_base + 2); + DMA_WAIT_TAG(tag_id_base + 3); + DMA_WAIT_TAG(tag_id_base + 4); +} + + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h b/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h new file mode 100644 index 0000000..42c328c --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/spu_common.h @@ -0,0 +1,108 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +/* Common definitions/makros for SPUs */ + +#ifndef _SPU_COMMON_H +#define _SPU_COMMON_H + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +/* Tag management */ +#define DMA_WAIT_TAG(_tag) \ + mfc_write_tag_mask(1<<(_tag)); \ + mfc_read_tag_status_all(); + +/* SPU mailbox messages */ +#define SPU_READY 0 +#define SPU_START 1 +#define SPU_FIN 2 +#define SPU_EXIT 3 + +/* Tags */ +#define RETR_BUF 0 +#define STR_BUF 1 +#define TAG_INIT 2 + +/* Buffersizes */ +#define MAX_HDTV_WIDTH 1920 +#define MAX_HDTV_HEIGHT 1080 +/* One stride of HDTV */ +#define BUFFER_SIZE 7680 + +/* fb_writer ppu/spu exchange parms */ +struct fb_writer_parms_t { + uint8_t *data; + uint8_t *center; + uint32_t out_line_stride; + uint32_t in_line_stride; + uint32_t bounded_input_height; + uint32_t bounded_input_width; + uint32_t fb_pixel_size; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[4]; +} __attribute__((aligned(128))); + +/* yuv2rgb ppu/spu exchange parms */ +struct yuv2rgb_parms_t { + uint8_t* y_plane; + uint8_t* v_plane; + uint8_t* u_plane; + + uint8_t* dstBuffer; + + unsigned int src_pixel_width; + unsigned int src_pixel_height; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[128 - ((4 * sizeof(uint8_t *) + 2 * sizeof(unsigned int)) & 0x7F)]; +} __attribute__((aligned(128))); + +/* bilin_scaler ppu/spu exchange parms */ +struct scale_parms_t { + uint8_t* y_plane; + uint8_t* v_plane; + uint8_t* u_plane; + + uint8_t* dstBuffer; + + unsigned int src_pixel_width; + unsigned int src_pixel_height; + + unsigned int dst_pixel_width; + unsigned int dst_pixel_height; + + /* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */ + char padding[128 - ((4 * sizeof(uint8_t *) + 4 * sizeof(unsigned int)) & 0x7F)]; +} __attribute__((aligned(128))); + +#endif /* _SPU_COMMON_H */ + + diff --git a/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c b/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c new file mode 100644 index 0000000..5e16691 --- /dev/null +++ b/3rdparty/SDL/src/video/ps3/spulibs/yuv2rgb_converter.c @@ -0,0 +1,629 @@ +/* + * SDL - Simple DirectMedia Layer + * CELL BE Support for PS3 Framebuffer + * Copyright (C) 2008, 2009 International Business Machines Corporation + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> + * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include <spu_intrinsics.h> +#include <spu_mfcio.h> + +// Debugging +//#define DEBUG + +#ifdef DEBUG +#define deprintf(fmt, args... ) \ + fprintf( stdout, fmt, ##args ); \ + fflush( stdout ); +#else +#define deprintf( fmt, args... ) +#endif + +struct yuv2rgb_parms_t parms_converter __attribute__((aligned(128))); + +/* A maximum of 8 lines Y, therefore 4 lines V, 4 lines U are stored + * there might be the need to retrieve misaligned data, adjust + * incoming v and u plane to be able to handle this (add 128) + */ +unsigned char y_plane[2][(MAX_HDTV_WIDTH + 128) * 4] __attribute__((aligned(128))); +unsigned char v_plane[2][(MAX_HDTV_WIDTH + 128) * 2] __attribute__((aligned(128))); +unsigned char u_plane[2][(MAX_HDTV_WIDTH + 128) * 2] __attribute__((aligned(128))); + +/* A maximum of 4 lines BGRA are stored, 4 byte per pixel */ +unsigned char bgra[4 * MAX_HDTV_WIDTH * 4] __attribute__((aligned(128))); + +/* some vectors needed by the float to int conversion */ +static const vector float vec_255 = { 255.0f, 255.0f, 255.0f, 255.0f }; +static const vector float vec_0_1 = { 0.1f, 0.1f, 0.1f, 0.1f }; + +void yuv_to_rgb_w16(); +void yuv_to_rgb_w32(); + +void yuv_to_rgb_w16_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr, unsigned int width); +void yuv_to_rgb_w32_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width); + + +int main(unsigned long long spe_id __attribute__((unused)), unsigned long long argp __attribute__ ((unused))) +{ + deprintf("[SPU] yuv2rgb_spu is up... (on SPE #%llu)\n", spe_id); + uint32_t ea_mfc, mbox; + // send ready message + spu_write_out_mbox(SPU_READY); + + while (1) { + /* Check mailbox */ + mbox = spu_read_in_mbox(); + deprintf("[SPU] Message is %u\n", mbox); + switch (mbox) { + case SPU_EXIT: + deprintf("[SPU] fb_writer goes down...\n"); + return 0; + case SPU_START: + break; + default: + deprintf("[SPU] Cannot handle message\n"); + continue; + } + + /* Tag Manager setup */ + unsigned int tag_id; + tag_id = mfc_multi_tag_reserve(1); + if (tag_id == MFC_TAG_INVALID) { + deprintf("[SPU] Failed to reserve mfc tags on yuv2rgb_converter\n"); + return 0; + } + + /* DMA transfer for the input parameters */ + ea_mfc = spu_read_in_mbox(); + deprintf("[SPU] Message on yuv2rgb_converter is %u\n", ea_mfc); + spu_mfcdma32(&parms_converter, (unsigned int)ea_mfc, sizeof(struct yuv2rgb_parms_t), tag_id, MFC_GET_CMD); + DMA_WAIT_TAG(tag_id); + + /* There are alignment issues that involve handling of special cases + * a width of 32 results in a width of 16 in the chrominance + * --> choose the proper handling to optimize the performance + */ + deprintf("[SPU] Convert %ix%i from YUV to RGB\n", parms_converter.src_pixel_width, parms_converter.src_pixel_height); + if (parms_converter.src_pixel_width & 0x1f) { + deprintf("[SPU] Using yuv_to_rgb_w16\n"); + yuv_to_rgb_w16(); + } else { + deprintf("[SPU] Using yuv_to_rgb_w32\n"); + yuv_to_rgb_w32(); + } + + mfc_multi_tag_release(tag_id, 1); + deprintf("[SPU] yuv2rgb_spu... done!\n"); + /* Send FIN message */ + spu_write_out_mbox(SPU_FIN); + } + + return 0; +} + + +/* + * float_to_char() + * + * converts a float to a character using saturated + * arithmetic + * + * @param s float for conversion + * @returns converted character + */ +inline static unsigned char float_to_char(float s) { + vector float vec_s = spu_splats(s); + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return (unsigned char) spu_extract(vec_s,0); +} + + +/* + * vfloat_to_vuint() + * + * converts a float vector to an unsinged int vector using saturated + * arithmetic + * + * @param vec_s float vector for conversion + * @returns converted unsigned int vector + */ +inline static vector unsigned int vfloat_to_vuint(vector float vec_s) { + vector unsigned int select_1 = spu_cmpgt(vec_0_1, vec_s); + vec_s = spu_sel(vec_s, vec_0_1, select_1); + + vector unsigned int select_2 = spu_cmpgt(vec_s, vec_255); + vec_s = spu_sel(vec_s, vec_255, select_2); + return spu_convtu(vec_s,0); +} + + +void yuv_to_rgb_w16() { + // Pixel dimensions of the picture + uint32_t width, height; + + // Extract parameters + width = parms_converter.src_pixel_width; + height = parms_converter.src_pixel_height; + + // Plane data management + // Y + unsigned char* ram_addr_y = parms_converter.y_plane; + // V + unsigned char* ram_addr_v = parms_converter.v_plane; + // U + unsigned char* ram_addr_u = parms_converter.u_plane; + + // BGRA + unsigned char* ram_addr_bgra = parms_converter.dstBuffer; + + // Strides + unsigned int stride_y = width; + unsigned int stride_vu = width>>1; + + // Buffer management + unsigned int buf_idx = 0; + unsigned int size_4lines_y = stride_y<<2; + unsigned int size_2lines_y = stride_y<<1; + unsigned int size_2lines_vu = stride_vu<<1; + + // 2*width*4byte_per_pixel + unsigned int size_2lines_bgra = width<<3; + + + // start double-buffered processing + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y, size_4lines_y, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // Wait for these transfers to be completed + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + unsigned int i; + for(i=0; i<(height>>2)-1; i++) { + + buf_idx^=1; + + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y+size_4lines_y, size_4lines_y, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v+size_2lines_vu, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u+size_2lines_vu, size_2lines_vu, RETR_BUF+buf_idx, MFC_GET_CMD); + + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + buf_idx^=1; + + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w16_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w16_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + + // Store converted lines in two steps->max transfer size 16384 + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra+size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + + // Move 4 lines + ram_addr_y += size_4lines_y; + ram_addr_v += size_2lines_vu; + ram_addr_u += size_2lines_vu; + + buf_idx^=1; + } + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w16_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w16_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra+size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + + // wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + +} + + +void yuv_to_rgb_w32() { + // Pixel dimensions of the picture + uint32_t width, height; + + // Extract parameters + width = parms_converter.src_pixel_width; + height = parms_converter.src_pixel_height; + + // Plane data management + // Y + unsigned char* ram_addr_y = parms_converter.y_plane; + // V + unsigned char* ram_addr_v = parms_converter.v_plane; + // U + unsigned char* ram_addr_u = parms_converter.u_plane; + + // BGRA + unsigned char* ram_addr_bgra = parms_converter.dstBuffer; + + // Strides + unsigned int stride_y = width; + unsigned int stride_vu = width>>1; + + // Buffer management + unsigned int buf_idx = 0; + unsigned int size_4lines_y = stride_y<<2; + unsigned int size_2lines_y = stride_y<<1; + unsigned int size_2lines_vu = stride_vu<<1; + + // 2*width*4byte_per_pixel + unsigned int size_2lines_bgra = width<<3; + + // start double-buffered processing + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y, size_4lines_y, RETR_BUF + buf_idx, MFC_GET_CMD); + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + + // Wait for these transfers to be completed + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + unsigned int i; + for(i=0; i < (height>>2)-1; i++) { + buf_idx^=1; + // 4 lines y + spu_mfcdma32(y_plane[buf_idx], (unsigned int) ram_addr_y+size_4lines_y, size_4lines_y, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("4lines = %d\n", size_4lines_y); + // 2 lines v + spu_mfcdma32(v_plane[buf_idx], (unsigned int) ram_addr_v+size_2lines_vu, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("2lines = %d\n", size_2lines_vu); + // 2 lines u + spu_mfcdma32(u_plane[buf_idx], (unsigned int) ram_addr_u+size_2lines_vu, size_2lines_vu, RETR_BUF + buf_idx, MFC_GET_CMD); + deprintf("2lines = %d\n", size_2lines_vu); + + DMA_WAIT_TAG((RETR_BUF + buf_idx)); + + buf_idx^=1; + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w32_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w32_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + + // Store converted lines in two steps->max transfer size 16384 + spu_mfcdma32(bgra, (unsigned int)ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra + size_2lines_bgra, (unsigned int)ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + + // Move 4 lines + ram_addr_y += size_4lines_y; + ram_addr_v += size_2lines_vu; + ram_addr_u += size_2lines_vu; + + buf_idx^=1; + } + + // Convert YUV to BGRA, store it back (first two lines) + yuv_to_rgb_w32_line(y_plane[buf_idx], v_plane[buf_idx], u_plane[buf_idx], bgra, width); + + // Next two lines + yuv_to_rgb_w32_line(y_plane[buf_idx] + size_2lines_y, + v_plane[buf_idx] + stride_vu, + u_plane[buf_idx] + stride_vu, + bgra + size_2lines_bgra, + width); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); + spu_mfcdma32(bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + ram_addr_bgra += size_2lines_bgra; + spu_mfcdma32(bgra + size_2lines_bgra, (unsigned int) ram_addr_bgra, size_2lines_bgra, STR_BUF, MFC_PUT_CMD); + + // Wait for previous storing transfer to be completed + DMA_WAIT_TAG(STR_BUF); +} + + +/* Some vectors needed by the yuv 2 rgb conversion algorithm */ +const vector float vec_minus_128 = { -128.0f, -128.0f, -128.0f, -128.0f }; +const vector unsigned char vec_null = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +const vector unsigned char vec_char2int_first = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13 }; +const vector unsigned char vec_char2int_second = { 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17 }; +const vector unsigned char vec_char2int_third = { 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x1B }; +const vector unsigned char vec_char2int_fourth = { 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1F }; + +const vector float vec_R_precalc_coeff = {1.403f, 1.403f, 1.403f, 1.403f}; +const vector float vec_Gu_precalc_coeff = {-0.344f, -0.344f, -0.344f, -0.344f}; +const vector float vec_Gv_precalc_coeff = {-0.714f, -0.714f, -0.714f, -0.714f}; +const vector float vec_B_precalc_coeff = {1.773f, 1.773f, 1.773f, 1.773f}; + +const vector unsigned int vec_alpha = { 255 << 24, 255 << 24, 255 << 24, 255 << 24 }; + +const vector unsigned char vec_select_floats_upper = { 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07 }; +const vector unsigned char vec_select_floats_lower = { 0x08, 0x09, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0C, 0x0D, 0x0E, 0x0F }; + + +/* + * yuv_to_rgb_w16() + * + * processes to line of yuv-input, width has to be a multiple of 16 + * two lines of yuv are taken as input + * + * @param y_addr address of the y plane in local store + * @param v_addr address of the v plane in local store + * @param u_addr address of the u plane in local store + * @param bgra_addr_ address of the bgra output buffer + * @param width the width in pixel + */ +void yuv_to_rgb_w16_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width) { + // each pixel is stored as an integer + unsigned int* bgra_addr = (unsigned int*) bgra_addr_; + + unsigned int x; + for(x = 0; x < width; x+=2) { + // Gehe zweischrittig durch die zeile, da jeder u und v wert fuer 4 pixel(zwei hoch, zwei breit) gilt + const unsigned char Y_1 = *(y_addr + x); + const unsigned char Y_2 = *(y_addr + x + 1); + const unsigned char Y_3 = *(y_addr + x + width); + const unsigned char Y_4 = *(y_addr + x + width + 1); + const unsigned char U = *(u_addr + (x >> 1)); + const unsigned char V = *(v_addr + (x >> 1)); + + float V_minus_128 = (float)((float)V - 128.0f); + float U_minus_128 = (float)((float)U - 128.0f); + + float R_precalculate = 1.403f * V_minus_128; + float G_precalculate = -(0.344f * U_minus_128 + 0.714f * V_minus_128); + float B_precalculate = 1.773f * U_minus_128; + + const unsigned char R_1 = float_to_char((Y_1 + R_precalculate)); + const unsigned char R_2 = float_to_char((Y_2 + R_precalculate)); + const unsigned char R_3 = float_to_char((Y_3 + R_precalculate)); + const unsigned char R_4 = float_to_char((Y_4 + R_precalculate)); + const unsigned char G_1 = float_to_char((Y_1 + G_precalculate)); + const unsigned char G_2 = float_to_char((Y_2 + G_precalculate)); + const unsigned char G_3 = float_to_char((Y_3 + G_precalculate)); + const unsigned char G_4 = float_to_char((Y_4 + G_precalculate)); + const unsigned char B_1 = float_to_char((Y_1 + B_precalculate)); + const unsigned char B_2 = float_to_char((Y_2 + B_precalculate)); + const unsigned char B_3 = float_to_char((Y_3 + B_precalculate)); + const unsigned char B_4 = float_to_char((Y_4 + B_precalculate)); + + *(bgra_addr + x) = (B_1 << 0)| (G_1 << 8) | (R_1 << 16) | (255 << 24); + *(bgra_addr + x + 1) = (B_2 << 0)| (G_2 << 8) | (R_2 << 16) | (255 << 24); + *(bgra_addr + x + width) = (B_3 << 0)| (G_3 << 8) | (R_3 << 16) | (255 << 24); + *(bgra_addr + x + width + 1) = (B_4 << 0)| (G_4 << 8) | (R_4 << 16) | (255 << 24); + } +} + + +/* + * yuv_to_rgb_w32() + * + * processes to line of yuv-input, width has to be a multiple of 32 + * two lines of yuv are taken as input + * + * @param y_addr address of the y plane in local store + * @param v_addr address of the v plane in local store + * @param u_addr address of the u plane in local store + * @param bgra_addr_ address of the bgra output buffer + * @param width the width in pixel + */ +void yuv_to_rgb_w32_line(unsigned char* y_addr, unsigned char* v_addr, unsigned char* u_addr, unsigned char* bgra_addr_, unsigned int width) { + // each pixel is stored as an integer + unsigned int* bgra_addr = (unsigned int*) bgra_addr_; + + unsigned int x; + for(x = 0; x < width; x+=32) { + // Gehe zweischrittig durch die zeile, da jeder u und v wert fuer 4 pixel(zwei hoch, zwei breit) gilt + + const vector unsigned char vchar_Y_1 = *((vector unsigned char*)(y_addr + x)); + const vector unsigned char vchar_Y_2 = *((vector unsigned char*)(y_addr + x + 16)); + const vector unsigned char vchar_Y_3 = *((vector unsigned char*)(y_addr + x + width)); + const vector unsigned char vchar_Y_4 = *((vector unsigned char*)(y_addr + x + width + 16)); + const vector unsigned char vchar_U = *((vector unsigned char*)(u_addr + (x >> 1))); + const vector unsigned char vchar_V = *((vector unsigned char*)(v_addr + (x >> 1))); + + const vector float vfloat_U_1 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_first), 0),vec_minus_128); + const vector float vfloat_U_2 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_second), 0),vec_minus_128); + const vector float vfloat_U_3 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_third), 0),vec_minus_128); + const vector float vfloat_U_4 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_U, vec_char2int_fourth), 0),vec_minus_128); + + const vector float vfloat_V_1 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_first), 0),vec_minus_128); + const vector float vfloat_V_2 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_second), 0),vec_minus_128); + const vector float vfloat_V_3 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_third), 0),vec_minus_128); + const vector float vfloat_V_4 = spu_add(spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_V, vec_char2int_fourth), 0),vec_minus_128); + + vector float Y_1 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_first), 0); + vector float Y_2 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_second), 0); + vector float Y_3 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_third), 0); + vector float Y_4 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_1, vec_char2int_fourth), 0); + vector float Y_5 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_first), 0); + vector float Y_6 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_second), 0); + vector float Y_7 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_third), 0); + vector float Y_8 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_2, vec_char2int_fourth), 0); + vector float Y_9 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_first), 0); + vector float Y_10 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_second), 0); + vector float Y_11 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_third), 0); + vector float Y_12 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_3, vec_char2int_fourth), 0); + vector float Y_13 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_first), 0); + vector float Y_14 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_second), 0); + vector float Y_15 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_third), 0); + vector float Y_16 = spu_convtf((vector unsigned int)spu_shuffle(vec_null, vchar_Y_4, vec_char2int_fourth), 0); + + const vector float R1a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_1); + const vector float R2a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_2); + const vector float R3a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_3); + const vector float R4a_precalculate = spu_mul(vec_R_precalc_coeff, vfloat_V_4); + + const vector float R1_precalculate = spu_shuffle(R1a_precalculate, R1a_precalculate, vec_select_floats_upper); + const vector float R2_precalculate = spu_shuffle(R1a_precalculate, R1a_precalculate, vec_select_floats_lower); + const vector float R3_precalculate = spu_shuffle(R2a_precalculate, R2a_precalculate, vec_select_floats_upper); + const vector float R4_precalculate = spu_shuffle(R2a_precalculate, R2a_precalculate, vec_select_floats_lower); + const vector float R5_precalculate = spu_shuffle(R3a_precalculate, R3a_precalculate, vec_select_floats_upper); + const vector float R6_precalculate = spu_shuffle(R3a_precalculate, R3a_precalculate, vec_select_floats_lower); + const vector float R7_precalculate = spu_shuffle(R4a_precalculate, R4a_precalculate, vec_select_floats_upper); + const vector float R8_precalculate = spu_shuffle(R4a_precalculate, R4a_precalculate, vec_select_floats_lower); + + + const vector float G1a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_1, spu_mul(vfloat_V_1, vec_Gv_precalc_coeff)); + const vector float G2a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_2, spu_mul(vfloat_V_2, vec_Gv_precalc_coeff)); + const vector float G3a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_3, spu_mul(vfloat_V_3, vec_Gv_precalc_coeff)); + const vector float G4a_precalculate = spu_madd(vec_Gu_precalc_coeff, vfloat_U_4, spu_mul(vfloat_V_4, vec_Gv_precalc_coeff)); + + const vector float G1_precalculate = spu_shuffle(G1a_precalculate, G1a_precalculate, vec_select_floats_upper); + const vector float G2_precalculate = spu_shuffle(G1a_precalculate, G1a_precalculate, vec_select_floats_lower); + const vector float G3_precalculate = spu_shuffle(G2a_precalculate, G2a_precalculate, vec_select_floats_upper); + const vector float G4_precalculate = spu_shuffle(G2a_precalculate, G2a_precalculate, vec_select_floats_lower); + const vector float G5_precalculate = spu_shuffle(G3a_precalculate, G3a_precalculate, vec_select_floats_upper); + const vector float G6_precalculate = spu_shuffle(G3a_precalculate, G3a_precalculate, vec_select_floats_lower); + const vector float G7_precalculate = spu_shuffle(G4a_precalculate, G4a_precalculate, vec_select_floats_upper); + const vector float G8_precalculate = spu_shuffle(G4a_precalculate, G4a_precalculate, vec_select_floats_lower); + + + const vector float B1a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_1); + const vector float B2a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_2); + const vector float B3a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_3); + const vector float B4a_precalculate = spu_mul(vec_B_precalc_coeff, vfloat_U_4); + + const vector float B1_precalculate = spu_shuffle(B1a_precalculate, B1a_precalculate, vec_select_floats_upper); + const vector float B2_precalculate = spu_shuffle(B1a_precalculate, B1a_precalculate, vec_select_floats_lower); + const vector float B3_precalculate = spu_shuffle(B2a_precalculate, B2a_precalculate, vec_select_floats_upper); + const vector float B4_precalculate = spu_shuffle(B2a_precalculate, B2a_precalculate, vec_select_floats_lower); + const vector float B5_precalculate = spu_shuffle(B3a_precalculate, B3a_precalculate, vec_select_floats_upper); + const vector float B6_precalculate = spu_shuffle(B3a_precalculate, B3a_precalculate, vec_select_floats_lower); + const vector float B7_precalculate = spu_shuffle(B4a_precalculate, B4a_precalculate, vec_select_floats_upper); + const vector float B8_precalculate = spu_shuffle(B4a_precalculate, B4a_precalculate, vec_select_floats_lower); + + + const vector unsigned int R_1 = vfloat_to_vuint(spu_add( Y_1, R1_precalculate)); + const vector unsigned int R_2 = vfloat_to_vuint(spu_add( Y_2, R2_precalculate)); + const vector unsigned int R_3 = vfloat_to_vuint(spu_add( Y_3, R3_precalculate)); + const vector unsigned int R_4 = vfloat_to_vuint(spu_add( Y_4, R4_precalculate)); + const vector unsigned int R_5 = vfloat_to_vuint(spu_add( Y_5, R5_precalculate)); + const vector unsigned int R_6 = vfloat_to_vuint(spu_add( Y_6, R6_precalculate)); + const vector unsigned int R_7 = vfloat_to_vuint(spu_add( Y_7, R7_precalculate)); + const vector unsigned int R_8 = vfloat_to_vuint(spu_add( Y_8, R8_precalculate)); + const vector unsigned int R_9 = vfloat_to_vuint(spu_add( Y_9, R1_precalculate)); + const vector unsigned int R_10 = vfloat_to_vuint(spu_add(Y_10, R2_precalculate)); + const vector unsigned int R_11 = vfloat_to_vuint(spu_add(Y_11, R3_precalculate)); + const vector unsigned int R_12 = vfloat_to_vuint(spu_add(Y_12, R4_precalculate)); + const vector unsigned int R_13 = vfloat_to_vuint(spu_add(Y_13, R5_precalculate)); + const vector unsigned int R_14 = vfloat_to_vuint(spu_add(Y_14, R6_precalculate)); + const vector unsigned int R_15 = vfloat_to_vuint(spu_add(Y_15, R7_precalculate)); + const vector unsigned int R_16 = vfloat_to_vuint(spu_add(Y_16, R8_precalculate)); + + const vector unsigned int G_1 = vfloat_to_vuint(spu_add( Y_1, G1_precalculate)); + const vector unsigned int G_2 = vfloat_to_vuint(spu_add( Y_2, G2_precalculate)); + const vector unsigned int G_3 = vfloat_to_vuint(spu_add( Y_3, G3_precalculate)); + const vector unsigned int G_4 = vfloat_to_vuint(spu_add( Y_4, G4_precalculate)); + const vector unsigned int G_5 = vfloat_to_vuint(spu_add( Y_5, G5_precalculate)); + const vector unsigned int G_6 = vfloat_to_vuint(spu_add( Y_6, G6_precalculate)); + const vector unsigned int G_7 = vfloat_to_vuint(spu_add( Y_7, G7_precalculate)); + const vector unsigned int G_8 = vfloat_to_vuint(spu_add( Y_8, G8_precalculate)); + const vector unsigned int G_9 = vfloat_to_vuint(spu_add( Y_9, G1_precalculate)); + const vector unsigned int G_10 = vfloat_to_vuint(spu_add(Y_10, G2_precalculate)); + const vector unsigned int G_11 = vfloat_to_vuint(spu_add(Y_11, G3_precalculate)); + const vector unsigned int G_12 = vfloat_to_vuint(spu_add(Y_12, G4_precalculate)); + const vector unsigned int G_13 = vfloat_to_vuint(spu_add(Y_13, G5_precalculate)); + const vector unsigned int G_14 = vfloat_to_vuint(spu_add(Y_14, G6_precalculate)); + const vector unsigned int G_15 = vfloat_to_vuint(spu_add(Y_15, G7_precalculate)); + const vector unsigned int G_16 = vfloat_to_vuint(spu_add(Y_16, G8_precalculate)); + + const vector unsigned int B_1 = vfloat_to_vuint(spu_add( Y_1, B1_precalculate)); + const vector unsigned int B_2 = vfloat_to_vuint(spu_add( Y_2, B2_precalculate)); + const vector unsigned int B_3 = vfloat_to_vuint(spu_add( Y_3, B3_precalculate)); + const vector unsigned int B_4 = vfloat_to_vuint(spu_add( Y_4, B4_precalculate)); + const vector unsigned int B_5 = vfloat_to_vuint(spu_add( Y_5, B5_precalculate)); + const vector unsigned int B_6 = vfloat_to_vuint(spu_add( Y_6, B6_precalculate)); + const vector unsigned int B_7 = vfloat_to_vuint(spu_add( Y_7, B7_precalculate)); + const vector unsigned int B_8 = vfloat_to_vuint(spu_add( Y_8, B8_precalculate)); + const vector unsigned int B_9 = vfloat_to_vuint(spu_add( Y_9, B1_precalculate)); + const vector unsigned int B_10 = vfloat_to_vuint(spu_add(Y_10, B2_precalculate)); + const vector unsigned int B_11 = vfloat_to_vuint(spu_add(Y_11, B3_precalculate)); + const vector unsigned int B_12 = vfloat_to_vuint(spu_add(Y_12, B4_precalculate)); + const vector unsigned int B_13 = vfloat_to_vuint(spu_add(Y_13, B5_precalculate)); + const vector unsigned int B_14 = vfloat_to_vuint(spu_add(Y_14, B6_precalculate)); + const vector unsigned int B_15 = vfloat_to_vuint(spu_add(Y_15, B7_precalculate)); + const vector unsigned int B_16 = vfloat_to_vuint(spu_add(Y_16, B8_precalculate)); + + *((vector unsigned int*)(bgra_addr + x)) = spu_or(spu_or(vec_alpha, B_1), spu_or(spu_slqwbyte( R_1, 2),spu_slqwbyte(G_1, 1))); + *((vector unsigned int*)(bgra_addr + x + 4)) = spu_or(spu_or(vec_alpha, B_2), spu_or(spu_slqwbyte( R_2, 2),spu_slqwbyte(G_2, 1))); + *((vector unsigned int*)(bgra_addr + x + 8)) = spu_or(spu_or(vec_alpha, B_3), spu_or(spu_slqwbyte( R_3, 2),spu_slqwbyte(G_3, 1))); + *((vector unsigned int*)(bgra_addr + x + 12)) = spu_or(spu_or(vec_alpha, B_4), spu_or(spu_slqwbyte( R_4, 2),spu_slqwbyte(G_4, 1))); + *((vector unsigned int*)(bgra_addr + x + 16)) = spu_or(spu_or(vec_alpha, B_5), spu_or(spu_slqwbyte( R_5, 2),spu_slqwbyte(G_5, 1))); + *((vector unsigned int*)(bgra_addr + x + 20)) = spu_or(spu_or(vec_alpha, B_6), spu_or(spu_slqwbyte( R_6, 2),spu_slqwbyte(G_6, 1))); + *((vector unsigned int*)(bgra_addr + x + 24)) = spu_or(spu_or(vec_alpha, B_7), spu_or(spu_slqwbyte( R_7, 2),spu_slqwbyte(G_7, 1))); + *((vector unsigned int*)(bgra_addr + x + 28)) = spu_or(spu_or(vec_alpha, B_8), spu_or(spu_slqwbyte( R_8, 2),spu_slqwbyte(G_8, 1))); + *((vector unsigned int*)(bgra_addr + x + width)) = spu_or(spu_or(vec_alpha, B_9), spu_or(spu_slqwbyte( R_9, 2),spu_slqwbyte(G_9, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 4)) = spu_or(spu_or(vec_alpha, B_10), spu_or(spu_slqwbyte(R_10, 2),spu_slqwbyte(G_10, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 8)) = spu_or(spu_or(vec_alpha, B_11), spu_or(spu_slqwbyte(R_11, 2),spu_slqwbyte(G_11, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 12)) = spu_or(spu_or(vec_alpha, B_12), spu_or(spu_slqwbyte(R_12, 2),spu_slqwbyte(G_12, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 16)) = spu_or(spu_or(vec_alpha, B_13), spu_or(spu_slqwbyte(R_13, 2),spu_slqwbyte(G_13, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 20)) = spu_or(spu_or(vec_alpha, B_14), spu_or(spu_slqwbyte(R_14, 2),spu_slqwbyte(G_14, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 24)) = spu_or(spu_or(vec_alpha, B_15), spu_or(spu_slqwbyte(R_15, 2),spu_slqwbyte(G_15, 1))); + *((vector unsigned int*)(bgra_addr + x + width + 28)) = spu_or(spu_or(vec_alpha, B_16), spu_or(spu_slqwbyte(R_16, 2),spu_slqwbyte(G_16, 1))); + } +} + diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc new file mode 100644 index 0000000..8daf1c5 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.cc @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <qpe/qpeapplication.h> +#include <qapplication.h> +#include <qevent.h> + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" + +/* Flag to tell whether or not the Be application is active or not */ +int SDL_QPEAppActive = 0; +static QPEApplication *app; + +int SDL_InitQPEApp() { + if(SDL_QPEAppActive <= 0) { + if(!qApp) { + int argc = 1; + char *argv[] = { { "SDLApp" } }; + app = new QPEApplication(argc, argv); + QWidget dummy; + app->showMainWidget(&dummy); + } else { + app = (QPEApplication*)qApp; + } + SDL_QPEAppActive++; + } + return 0; +} + +/* Quit the QPE Application, if there's nothing left to do */ +void SDL_QuitQPEApp(void) +{ + /* Decrement the application reference count */ + SDL_QPEAppActive--; + /* If the reference count reached zero, clean up the app */ + if ( SDL_QPEAppActive == 0 && app) { + delete app; + app = 0; + qApp = 0; + } +} diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h new file mode 100644 index 0000000..8a9ab77 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QPEApp.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the QPE application loop */ + +/* Initialize the QPE Application, if it's not already started */ +extern int SDL_InitQPEApp(void); + +/* Quit the QPE Application, if there's nothing left to do */ +extern void SDL_QuitQPEApp(void); + +/* Flag to tell whether the app is active or not */ +extern int SDL_QPEAppActive; diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc b/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc new file mode 100644 index 0000000..04474ed --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QWin.cc @@ -0,0 +1,527 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" +#include <qapplication.h> +#include <qdirectpainter_qws.h> + +screenRotationT screenRotation = SDL_QT_NO_ROTATION; + +SDL_QWin::SDL_QWin(const QSize& size) + : QWidget(0, "SDL_main"), my_painter(0), my_image(0), + my_inhibit_resize(false), my_mouse_pos(-1,-1), my_flags(0), + my_has_fullscreen(false), my_locked(0) +{ + setBackgroundMode(NoBackground); +} + +SDL_QWin::~SDL_QWin() { + // Nothing to do yet. + if(my_image) { + delete my_image; + } +} + +void SDL_QWin::setImage(QImage *image) { + if ( my_image ) { + delete my_image; + } + my_image = image; + // setFixedSize(image->size()); +} + +void SDL_QWin::resizeEvent(QResizeEvent *e) { + if(size() != qApp->desktop()->size()) { + // Widget is not the correct size, so do the fullscreen magic + my_has_fullscreen = false; + enableFullscreen(); + } + if(my_inhibit_resize) { + my_inhibit_resize = false; + } else { + SDL_PrivateResize(e->size().width(), e->size().height()); + } +} + +void SDL_QWin::focusInEvent(QFocusEvent *) { + // Always do it here, no matter the size. + enableFullscreen(); + SDL_PrivateAppActive(true, SDL_APPINPUTFOCUS); +} + +void SDL_QWin::focusOutEvent(QFocusEvent *) { + my_has_fullscreen = false; + SDL_PrivateAppActive(false, SDL_APPINPUTFOCUS); +} + +void SDL_QWin::closeEvent(QCloseEvent *e) { + SDL_PrivateQuit(); + e->ignore(); +} + +void SDL_QWin::setMousePos(const QPoint &pos) { + if(my_image->width() == height()) { + if (screenRotation == SDL_QT_ROTATION_90) + my_mouse_pos = QPoint(height()-pos.y(), pos.x()); + else if (screenRotation == SDL_QT_ROTATION_270) + my_mouse_pos = QPoint(pos.y(), width()-pos.x()); + } else { + my_mouse_pos = pos; + } +} + +void SDL_QWin::mouseMoveEvent(QMouseEvent *e) { + Qt::ButtonState button = e->button(); + int sdlstate = 0; + if( (button & Qt::LeftButton)) { + sdlstate |= SDL_BUTTON_LMASK; + } + if( (button & Qt::RightButton)) { + sdlstate |= SDL_BUTTON_RMASK; + } + if( (button & Qt::MidButton)) { + sdlstate |= SDL_BUTTON_MMASK; + } + setMousePos(e->pos()); + SDL_PrivateMouseMotion(sdlstate, 0, my_mouse_pos.x(), my_mouse_pos.y()); +} + +void SDL_QWin::mousePressEvent(QMouseEvent *e) { + mouseMoveEvent(e); + Qt::ButtonState button = e->button(); + SDL_PrivateMouseButton(SDL_PRESSED, + (button & Qt::LeftButton) ? 1 : + ((button & Qt::RightButton) ? 2 : 3), + my_mouse_pos.x(), my_mouse_pos.y()); +} + +void SDL_QWin::mouseReleaseEvent(QMouseEvent *e) { + setMousePos(e->pos()); + Qt::ButtonState button = e->button(); + SDL_PrivateMouseButton(SDL_RELEASED, + (button & Qt::LeftButton) ? 1 : + ((button & Qt::RightButton) ? 2 : 3), + my_mouse_pos.x(), my_mouse_pos.y()); + my_mouse_pos = QPoint(-1, -1); +} + +static inline void +gs_fastRotateBlit_3 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) +{ + // FIXME: this only works correctly for 240x320 displays + int startx, starty; + int width, height; + + startx = rect.left() >> 1; + starty = rect.top() >> 1; + width = ((rect.right() - rect.left()) >> 1) + 2; + height = ((rect.bottom() - rect.top()) >> 1) + 2; + + if((startx+width) > 120) { + width = 120 - startx; // avoid horizontal overflow + } + if((starty+height) > 160) { + height = 160 - starty; // avoid vertical overflow + } + + ulong *sp1, *sp2, *dp1, *dp2; + ulong stop, sbot, dtop, dbot; + + sp1 = (ulong*)bits + startx + starty*240; + sp2 = sp1 + 120; + dp1 = (ulong *)fb + (159 - starty) + startx*320; + dp2 = dp1 + 160; + int rowadd = (-320*width) - 1; + int rowadd2 = 240 - width; + // transfer in cells of 2x2 pixels in words + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + // read source pixels + stop = *sp1; + sbot = *sp2; + // rotate pixels + dtop = (sbot & 0xffff) + ((stop & 0xffff)<<16); + dbot = ((sbot & 0xffff0000)>>16) + (stop & 0xffff0000); + // write to framebuffer + *dp1 = dtop; + *dp2 = dbot; + // update source ptrs + sp1++; sp2++; + // update dest ptrs - 2 pix at a time + dp1 += 320; + dp2 += 320; + } + // adjust src ptrs - skip a row as we work in pairs + sp1 += rowadd2; + sp2 += rowadd2; + // adjust dest ptrs for rotation + dp1 += rowadd; + dp2 += rowadd; + } +} + +static inline void +gs_fastRotateBlit_1 ( unsigned short *fb, + unsigned short *bits, + const QRect& rect ) { + // FIXME: this only works correctly for 240x320 displays + int startx, starty; + int width, height; + + startx = rect.left() >> 1; + starty = rect.top() >> 1; + width = ((rect.right() - rect.left()) >> 1) + 2; + height = ((rect.bottom() - rect.top()) >> 1) + 2; + + if((startx+width) > 120) { + width = 120 - startx; // avoid horizontal overflow + } + if((starty+height) > 160) { + height = 160 - starty; // avoid vertical overflow + } + + ulong *sp1, *sp2, *dp1, *dp2; + ulong stop, sbot, dtop, dbot; + fb += 320*239; // Move "fb" to top left corner + sp1 = (ulong*)bits + startx + starty*240; + sp2 = sp1 + 120; + dp1 = (ulong*)fb - startx * 320 - starty; + dp2 = dp1 - 160; + int rowadd = (320*width) + 1; + int rowadd2 = 240 - width; + // transfer in cells of 2x2 pixels in words + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + // read + stop = *sp1; + sbot = *sp2; + // rotate + dtop = (stop & 0xffff) + ((sbot & 0xffff)<<16); + dbot = ((stop & 0xffff0000)>>16) + (sbot & 0xffff0000); + // write + *dp1 = dtop; + *dp2 = dbot; + // update source ptrs + sp1++; sp2++; + // update dest ptrs - 2 pix at a time + dp1 -= 320; + dp2 -= 320; + } + // adjust src ptrs - skip a row as we work in pairs + sp1 += rowadd2; + sp2 += rowadd2; + // adjust dest ptrs for rotation + dp1 += rowadd; + dp2 += rowadd; + } +} + +// desktop, SL-A300 etc +bool SDL_QWin::repaintRotation0(const QRect& rect) { + if(my_image->width() == width()) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + SDL_memcpy(fb, buf, width()*height()*2); + } else { + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + SDL_memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; + } + } + } else { + return false; // FIXME: Landscape + } +#ifdef __i386__ + my_painter->fillRect( rect, QBrush( Qt::NoBrush ) ); +#endif + return true; +} + + +// Sharp Zaurus SL-5500 etc +bool SDL_QWin::repaintRotation3(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_3(fb, buf, rect); + } else { + // landscape mode + if (screenRotation == SDL_QT_ROTATION_90) { + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + if(rect == my_image->rect()) { + SDL_memcpy(fb, buf, width()*height()*2); + } else { + int h = rect.height(); + int wd = rect.width()<<1; + int fblineadd = my_painter->lineStep(); + int buflineadd = my_image->bytesPerLine(); + fb += (rect.left()<<1) + rect.top() * my_painter->lineStep(); + buf += (rect.left()<<1) + rect.top() * my_image->bytesPerLine(); + while(h--) { + SDL_memcpy(fb, buf, wd); + fb += fblineadd; + buf += buflineadd; + } + } + } else if (screenRotation == SDL_QT_ROTATION_270) { + int h = rect.height(); + int wd = rect.width(); + int fblineadd = my_painter->lineStep() - (rect.width() << 1); + int buflineadd = my_image->bytesPerLine() - (rect.width() << 1); + int w; + + uchar *fb = (uchar*)my_painter->frameBuffer(); + uchar *buf = (uchar*)my_image->bits(); + + fb += ((my_painter->width() - (rect.top() + rect.height())) * + my_painter->lineStep()) + ((my_painter->height() - ((rect.left() + + rect.width()))) << 1); + + buf += my_image->bytesPerLine() * (rect.top() + rect.height()) - + (((my_image->width() - (rect.left() + rect.width())) << 1) + 2); + + while(h--) { + w = wd; + while(w--) *((unsigned short*)fb)++ = *((unsigned short*)buf)--; + fb += fblineadd; + buf -= buflineadd; + } + } + } + return true; +} + +// ipaq 3800... +bool SDL_QWin::repaintRotation1(const QRect& rect) { + if(my_image->width() == width()) { + ushort *fb = (ushort*)my_painter->frameBuffer(); + ushort *buf = (ushort*)my_image->bits(); + gs_fastRotateBlit_1(fb, buf, rect); + } else { + return false; // FIXME: landscape mode + } + return true; +} + +void SDL_QWin::repaintRect(const QRect& rect) { + if(!my_painter || !rect.width() || !rect.height()) { + return; + } + + if(QPixmap::defaultDepth() == 16) { + switch(my_painter->transformOrientation()) { + case 3: + if(repaintRotation3(rect)) { return; } + break; + case 1: + if(repaintRotation1(rect)) { return; } + break; + case 0: + if(repaintRotation0(rect)) { return; } + break; + } + } + my_painter->drawImage(rect.topLeft(), *my_image, rect); +} + +// This paints the current buffer to the screen, when desired. +void SDL_QWin::paintEvent(QPaintEvent *ev) { + if(my_image) { + lockScreen(true); + repaintRect(ev->rect()); + unlockScreen(); + } +} + +/* Function to translate a keyboard transition and queue the key event + * This should probably be a table although this method isn't exactly + * slow. + */ +void SDL_QWin::QueueKey(QKeyEvent *e, int pressed) +{ + SDL_keysym keysym; + int scancode = e->key(); + /* Set the keysym information */ + if(scancode >= 'A' && scancode <= 'Z') { + // Qt sends uppercase, SDL wants lowercase + keysym.sym = static_cast<SDLKey>(scancode + 32); + } else if(scancode >= 0x1000) { + // Special keys + switch(scancode) { + case Qt::Key_Escape: scancode = SDLK_ESCAPE; break; + case Qt::Key_Tab: scancode = SDLK_TAB; break; + case Qt::Key_Backspace: scancode = SDLK_BACKSPACE; break; + case Qt::Key_Return: scancode = SDLK_RETURN; break; + case Qt::Key_Enter: scancode = SDLK_KP_ENTER; break; + case Qt::Key_Insert: scancode = SDLK_INSERT; break; + case Qt::Key_Delete: scancode = SDLK_DELETE; break; + case Qt::Key_Pause: scancode = SDLK_PAUSE; break; + case Qt::Key_Print: scancode = SDLK_PRINT; break; + case Qt::Key_SysReq: scancode = SDLK_SYSREQ; break; + case Qt::Key_Home: scancode = SDLK_HOME; break; + case Qt::Key_End: scancode = SDLK_END; break; + // We want the control keys to rotate with the screen + case Qt::Key_Left: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_UP; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_DOWN; + else scancode = SDLK_LEFT; + break; + case Qt::Key_Up: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_RIGHT; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_LEFT; + else scancode = SDLK_UP; + break; + case Qt::Key_Right: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_DOWN; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_UP; + else scancode = SDLK_RIGHT; + break; + case Qt::Key_Down: + if (screenRotation == SDL_QT_ROTATION_90) scancode = SDLK_LEFT; + else if (screenRotation == SDL_QT_ROTATION_270) scancode = SDLK_RIGHT; + else scancode = SDLK_DOWN; + break; + case Qt::Key_Prior: scancode = SDLK_PAGEUP; break; + case Qt::Key_Next: scancode = SDLK_PAGEDOWN; break; + case Qt::Key_Shift: scancode = SDLK_LSHIFT; break; + case Qt::Key_Control: scancode = SDLK_LCTRL; break; + case Qt::Key_Meta: scancode = SDLK_LMETA; break; + case Qt::Key_Alt: scancode = SDLK_LALT; break; + case Qt::Key_CapsLock: scancode = SDLK_CAPSLOCK; break; + case Qt::Key_NumLock: scancode = SDLK_NUMLOCK; break; + case Qt::Key_ScrollLock: scancode = SDLK_SCROLLOCK; break; + case Qt::Key_F1: scancode = SDLK_F1; break; + case Qt::Key_F2: scancode = SDLK_F2; break; + case Qt::Key_F3: scancode = SDLK_F3; break; + case Qt::Key_F4: scancode = SDLK_F4; break; + case Qt::Key_F5: scancode = SDLK_F5; break; + case Qt::Key_F6: scancode = SDLK_F6; break; + case Qt::Key_F7: scancode = SDLK_F7; break; + case Qt::Key_F8: scancode = SDLK_F8; break; + case Qt::Key_F9: scancode = SDLK_F9; break; + case Qt::Key_F10: scancode = SDLK_F10; break; + case Qt::Key_F11: scancode = SDLK_F11; break; + case Qt::Key_F12: scancode = SDLK_F12; break; + case Qt::Key_F13: scancode = SDLK_F13; break; + case Qt::Key_F14: scancode = SDLK_F14; break; + case Qt::Key_F15: scancode = SDLK_F15; break; + case Qt::Key_Super_L: scancode = SDLK_LSUPER; break; + case Qt::Key_Super_R: scancode = SDLK_RSUPER; break; + case Qt::Key_Menu: scancode = SDLK_MENU; break; + case Qt::Key_Help: scancode = SDLK_HELP; break; + + case Qt::Key_F33: + // FIXME: This is a hack to enable the OK key on + // Zaurii devices. SDLK_RETURN is a suitable key to use + // since it often is used as such. + // david@hedbor.org + scancode = SDLK_RETURN; + break; + default: + scancode = SDLK_UNKNOWN; + break; + } + keysym.sym = static_cast<SDLKey>(scancode); + } else { + keysym.sym = static_cast<SDLKey>(scancode); + } + keysym.scancode = scancode; + keysym.mod = KMOD_NONE; + ButtonState st = e->state(); + if( (st & ShiftButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LSHIFT); } + if( (st & ControlButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LCTRL); } + if( (st & AltButton) ) { keysym.mod = static_cast<SDLMod>(keysym.mod | KMOD_LALT); } + if ( SDL_TranslateUNICODE ) { + QChar qchar = e->text()[0]; + keysym.unicode = qchar.unicode(); + } else { + keysym.unicode = 0; + } + + /* NUMLOCK and CAPSLOCK are implemented as double-presses in reality */ + // if ( (keysym.sym == SDLK_NUMLOCK) || (keysym.sym == SDLK_CAPSLOCK) ) { + // pressed = 1; + // } + + /* Queue the key event */ + if ( pressed ) { + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } else { + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } +} + +void SDL_QWin::setFullscreen(bool fs_on) { + my_has_fullscreen = false; + enableFullscreen(); +} + +void SDL_QWin::enableFullscreen() { + // Make sure size is correct + if(!my_has_fullscreen) { + setFixedSize(qApp->desktop()->size()); + // This call is needed because showFullScreen won't work + // correctly if the widget already considers itself to be fullscreen. + showNormal(); + // This is needed because showNormal() forcefully changes the window + // style to WSTyle_TopLevel. + setWFlags(WStyle_Customize | WStyle_NoBorder); + // Enable fullscreen. + showFullScreen(); + my_has_fullscreen = true; + } +} + +bool SDL_QWin::lockScreen(bool force) { + if(!my_painter) { + if(force || (isVisible() && isActiveWindow())) { + my_painter = new QDirectPainter(this); + } else { + return false; + } + } + my_locked++; // Increate lock refcount + return true; +} + +void SDL_QWin::unlockScreen() { + if(my_locked > 0) { + my_locked--; // decrease lock refcount; + } + if(!my_locked && my_painter) { + my_painter->end(); + delete my_painter; + my_painter = 0; + } +} diff --git a/3rdparty/SDL/src/video/qtopia/SDL_QWin.h b/3rdparty/SDL/src/video/qtopia/SDL_QWin.h new file mode 100644 index 0000000..2531834 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_QWin.h @@ -0,0 +1,110 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_QWin_h +#define _SDL_QWin_h + +#include <stdio.h> + +#include <qimage.h> +#include <qpixmap.h> +#include <qwidget.h> +#include <qpainter.h> +#include <qdirectpainter_qws.h> + +#include "SDL_events.h" + +extern "C" { +#include "../../events/SDL_events_c.h" +}; + +typedef enum { + SDL_QT_NO_ROTATION = 0, + SDL_QT_ROTATION_90, + SDL_QT_ROTATION_270 +} screenRotationT; + +extern screenRotationT screenRotation; + +class SDL_QWin : public QWidget +{ + void QueueKey(QKeyEvent *e, int pressed); + public: + SDL_QWin(const QSize& size); + virtual ~SDL_QWin(); + virtual bool shown(void) { + return isVisible(); + } + /* If called, the next resize event will not be forwarded to SDL. */ + virtual void inhibitResize(void) { + my_inhibit_resize = true; + } + void setImage(QImage *image); + void setOffset(int x, int y) { + my_offset = QPoint(x, y); + } + void GetXYOffset(int &x, int &y) { + x = my_offset.x(); + y = my_offset.y(); + } + QImage *image(void) { return my_image; } + + void setWFlags(WFlags flags) { + QWidget::setWFlags(flags); + my_flags = flags; + } + const QPoint& mousePos() const { return my_mouse_pos; } + void setMousePos(const QPoint& newpos); + void setFullscreen(bool); + + bool lockScreen(bool force=false); + void unlockScreen(); + void repaintRect(const QRect& rect); + protected: + /* Handle resizing of the window */ + virtual void resizeEvent(QResizeEvent *e); + void focusInEvent(QFocusEvent *); + void focusOutEvent(QFocusEvent *); + void closeEvent(QCloseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *ev); + void keyPressEvent(QKeyEvent *e) { QueueKey(e, 1); } + void keyReleaseEvent(QKeyEvent *e) { QueueKey(e, 0); } + private: + bool repaintRotation0(const QRect& rect); + bool repaintRotation1(const QRect& rect); + bool repaintRotation3(const QRect& rect); + void enableFullscreen(); + QDirectPainter *my_painter; + QImage *my_image; + bool my_inhibit_resize; + QPoint my_offset; + QPoint my_mouse_pos; + WFlags my_flags; + WFlags my_has_fullscreen; + unsigned int my_locked; +}; + +#endif /* _SDL_QWin_h */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h b/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h new file mode 100644 index 0000000..1d05c72 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_lowvideo.h @@ -0,0 +1,65 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this + +/* Private display data */ +struct SDL_PrivateVideoData { + /* The main window */ + SDL_QWin *SDL_Win; + + /* The fullscreen mode list */ +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + /* A completely clear cursor */ + WMcursor *BlankCursor; + + /* Mouse state variables */ + Uint32 last_buttons; + QPoint last_point; + + /* Keyboard state variables */ + int key_flip; + //struct key_info keyinfo[2]; +}; +/* Old variable names */ +#define SDL_Win (_this->hidden->SDL_Win) +#define saved_mode (_this->hidden->saved_mode) +#define SDL_nummodes (_this->hidden->SDL_nummodes) +#define SDL_modelist (_this->hidden->SDL_modelist) +#define SDL_BlankCursor (_this->hidden->BlankCursor) +#define last_buttons (_this->hidden->last_buttons) +#define last_point (_this->hidden->last_point) +#define key_flip (_this->hidden->key_flip) +#define keyinfo (_this->hidden->keyinfo) + +#endif /* _SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc new file mode 100644 index 0000000..4aaf814 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysevents.cc @@ -0,0 +1,269 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <qpe/qpeapplication.h> + +#include <stdio.h> +#include <string.h> +#include "SDL_error.h" +#include "SDL_events.h" +#include "SDL_QWin.h" +#include "SDL_lowvideo.h" +#include "SDL_timer.h" + +extern "C" { +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" + + // static SDLKey keymap[128]; +/* This is special because we know it will be run in a loop in a separate + thread. Normally this function should loop as long as there are input + states changing, i.e. new events arriving. +*/ +void QT_PumpEvents(_THIS) +{ + if(!qApp) { + return; + } + // printf("processing events: %p\n", qApp); + //qApp->processOneEvent(); // wait for a event + qApp->processEvents(); // and process all outstanding ones +#if 0 + BView *view; + BRect bounds; + BPoint point; + uint32 buttons; + const uint32 button_masks[3] = { + B_PRIMARY_MOUSE_BUTTON, + B_TERTIARY_MOUSE_BUTTON, + B_SECONDARY_MOUSE_BUTTON, + }; + unsigned int i, j; + + /* Check out the mouse buttons and position (slight race condition) */ + if ( SDL_Win->Lock() ) { + /* Don't do anything if we have no view */ + view = SDL_Win->View(); + if ( ! view ) { + SDL_Win->Unlock(); + return; + } + bounds = view->Bounds(); + /* Get new input state, if still active */ + if ( SDL_Win->IsActive() ) { + key_flip = !key_flip; + get_key_info(&keyinfo[key_flip]); + view->GetMouse(&point, &buttons, true); + } else { + key_flip = key_flip; + point = last_point; + buttons = last_buttons; + } + SDL_Win->Unlock(); + } else { + return; + } + + /* If our view is active, we'll find key changes here */ + if ( SDL_memcmp(keyinfo[0].key_states, keyinfo[1].key_states, 16) != 0 ) { + for ( i=0; i<16; ++i ) { + Uint8 new_state, transition; + + new_state = keyinfo[key_flip].key_states[i]; + transition = keyinfo[!key_flip].key_states[i] ^ + keyinfo[ key_flip].key_states[i]; + for ( j=0; j<8; ++j ) { + if ( transition&0x80 ) + QueueKey(i*8+j, new_state&0x80); + transition <<= 1; + new_state <<= 1; + } + } + } + + /* We check keyboard, but not mouse if mouse isn't in window */ + if ( ! bounds.Contains(point) ) { + /* Mouse moved outside our view? */ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + be_app->SetCursor(B_HAND_CURSOR); + } + return; + } + /* Has the mouse moved back into our view? */ + if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + /* Reset the B_HAND_CURSOR to our own */ + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_SetCursor(NULL); + } + + /* Check for mouse motion */ + if ( point != last_point ) { + int x, y; + + SDL_Win->GetXYOffset(x, y); + x = (int)point.x - x; + y = (int)point.y - y; + SDL_PrivateMouseMotion(0, 0, x, y); + } + last_point = point; + + /* Add any mouse button events */ + for ( i=0; i<SDL_TABLESIZE(button_masks); ++i ) { + if ( (buttons ^ last_buttons) & button_masks[i] ) { + if ( buttons & button_masks[i] ) { + SDL_PrivateMouseButton(SDL_PRESSED, 1+i, 0, 0); + } else { + SDL_PrivateMouseButton(SDL_RELEASED, 1+i, 0, 0); + } + } + } + last_buttons = buttons; +#endif +} + +void QT_InitOSKeymap(_THIS) +{ +#if 0 + unsigned int i; + + /* Initialize all the key states as "up" */ + key_flip = 0; + SDL_memset(keyinfo[key_flip].key_states, 0, 16); + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + // keymap[0x01] = SDLK_ESCAPE; + // keymap[B_F1_KEY] = SDLK_F1; + // keymap[B_F2_KEY] = SDLK_F2; + // keymap[B_F3_KEY] = SDLK_F3; + // keymap[B_F4_KEY] = SDLK_F4; + // keymap[B_F5_KEY] = SDLK_F5; + // keymap[B_F6_KEY] = SDLK_F6; + // keymap[B_F7_KEY] = SDLK_F7; + // keymap[B_F8_KEY] = SDLK_F8; + // keymap[B_F9_KEY] = SDLK_F9; + // keymap[B_F10_KEY] = SDLK_F10; + // keymap[B_F11_KEY] = SDLK_F11; + // keymap[B_F12_KEY] = SDLK_F12; + // keymap[B_PRINT_KEY] = SDLK_PRINT; + //keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK; + // keymap[B_PAUSE_KEY] = SDLK_PAUSE; + keymap[0x11] = SDLK_BACKQUOTE; + keymap[0x12] = SDLK_1; + keymap[0x13] = SDLK_2; + keymap[0x14] = SDLK_3; + keymap[0x15] = SDLK_4; + keymap[0x16] = SDLK_5; + keymap[0x17] = SDLK_6; + keymap[0x18] = SDLK_7; + keymap[0x19] = SDLK_8; + keymap[0x1a] = SDLK_9; + keymap[0x1b] = SDLK_0; + keymap[0x1c] = SDLK_MINUS; + keymap[0x1d] = SDLK_EQUALS; + keymap[0x1e] = SDLK_BACKSPACE; + keymap[0x1f] = SDLK_INSERT; + keymap[0x20] = SDLK_HOME; + keymap[0x21] = SDLK_PAGEUP; + //keymap[0x22] = SDLK_NUMLOCK; + keymap[0x23] = SDLK_KP_DIVIDE; + keymap[0x24] = SDLK_KP_MULTIPLY; + keymap[0x25] = SDLK_KP_MINUS; + keymap[0x26] = SDLK_TAB; + keymap[0x27] = SDLK_q; + keymap[0x28] = SDLK_w; + keymap[0x29] = SDLK_e; + keymap[0x2a] = SDLK_r; + keymap[0x2b] = SDLK_t; + keymap[0x2c] = SDLK_y; + keymap[0x2d] = SDLK_u; + keymap[0x2e] = SDLK_i; + keymap[0x2f] = SDLK_o; + keymap[0x30] = SDLK_p; + keymap[0x31] = SDLK_LEFTBRACKET; + keymap[0x32] = SDLK_RIGHTBRACKET; + keymap[0x33] = SDLK_BACKSLASH; + keymap[0x34] = SDLK_DELETE; + keymap[0x35] = SDLK_END; + keymap[0x36] = SDLK_PAGEDOWN; + keymap[0x37] = SDLK_KP7; + keymap[0x38] = SDLK_KP8; + keymap[0x39] = SDLK_KP9; + keymap[0x3a] = SDLK_KP_PLUS; + //keymap[0x3b] = SDLK_CAPSLOCK; + keymap[0x3c] = SDLK_a; + keymap[0x3d] = SDLK_s; + keymap[0x3e] = SDLK_d; + keymap[0x3f] = SDLK_f; + keymap[0x40] = SDLK_g; + keymap[0x41] = SDLK_h; + keymap[0x42] = SDLK_j; + keymap[0x43] = SDLK_k; + keymap[0x44] = SDLK_l; + keymap[0x45] = SDLK_SEMICOLON; + keymap[0x46] = SDLK_QUOTE; + keymap[0x47] = SDLK_RETURN; + keymap[0x48] = SDLK_KP4; + keymap[0x49] = SDLK_KP5; + keymap[0x4a] = SDLK_KP6; + keymap[0x4b] = SDLK_LSHIFT; + keymap[0x4c] = SDLK_z; + keymap[0x4d] = SDLK_x; + keymap[0x4e] = SDLK_c; + keymap[0x4f] = SDLK_v; + keymap[0x50] = SDLK_b; + keymap[0x51] = SDLK_n; + keymap[0x52] = SDLK_m; + keymap[0x53] = SDLK_COMMA; + keymap[0x54] = SDLK_PERIOD; + keymap[0x55] = SDLK_SLASH; + keymap[0x56] = SDLK_RSHIFT; + keymap[0x57] = SDLK_UP; + keymap[0x58] = SDLK_KP1; + keymap[0x59] = SDLK_KP2; + keymap[0x5a] = SDLK_KP3; + keymap[0x5b] = SDLK_KP_ENTER; + //keymap[0x5c] = SDLK_LCTRL; + //keymap[0x5d] = SDLK_LALT; + keymap[0x5e] = SDLK_SPACE; + //keymap[0x5f] = SDLK_RALT; + //keymap[0x60] = SDLK_RCTRL; + keymap[0x61] = SDLK_LEFT; + keymap[0x62] = SDLK_DOWN; + keymap[0x63] = SDLK_RIGHT; + keymap[0x64] = SDLK_KP0; + keymap[0x65] = SDLK_KP_PERIOD; + //keymap[0x66] = SDLK_LMETA; + //keymap[0x67] = SDLK_RMETA; + //keymap[0x68] = SDLK_MENU; + keymap[0x69] = SDLK_EURO; + keymap[0x6a] = SDLK_KP_EQUALS; + keymap[0x6b] = SDLK_POWER; +#endif +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h b/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h new file mode 100644 index 0000000..5e26759 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysevents_c.h @@ -0,0 +1,31 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +extern void QT_InitOSKeymap(_THIS); +extern void QT_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc new file mode 100644 index 0000000..1a655b6 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse.cc @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "SDL_sysmouse_c.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + char *bits; +}; +WMcursor *QT_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + static WMcursor dummy; + dummy.bits = 0; + return &dummy; +} + +int QT_ShowWMCursor(_THIS, WMcursor *cursor) +{ + return 1; +} + +void QT_FreeWMCursor(_THIS, WMcursor *cursor) +{ +} + +void QT_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + SDL_Win->setMousePos(QPoint(x, y)); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h new file mode 100644 index 0000000..98e4cf5 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysmouse_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void QT_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *QT_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int QT_ShowWMCursor(_THIS, WMcursor *cursor); +extern void QT_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc b/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc new file mode 100644 index 0000000..0e07874 --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_sysvideo.cc @@ -0,0 +1,403 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Qtopia based framebuffer implementation */ + +#include <unistd.h> + +#include <qapplication.h> +#include <qpe/qpeapplication.h> + +#include "SDL_timer.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_events_c.h" +#include "SDL_sysevents_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_syswm_c.h" +#include "SDL_lowvideo.h" + + //#define QTOPIA_DEBUG +#define QT_HIDDEN_SIZE 32 /* starting hidden window size */ + + /* Name of the environment variable used to invert the screen rotation or not: + Possible values: + !=0 : Screen is 270 rotated + 0: Screen is 90 rotated*/ +#define SDL_QT_ROTATION_ENV_NAME "SDL_QT_INVERT_ROTATION" + + /* Initialization/Query functions */ + static int QT_VideoInit(_THIS, SDL_PixelFormat *vformat); + static SDL_Rect **QT_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); + static SDL_Surface *QT_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); + static void QT_UpdateMouse(_THIS); + static int QT_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); + static void QT_VideoQuit(_THIS); + + /* Hardware surface functions */ + static int QT_AllocHWSurface(_THIS, SDL_Surface *surface); + static int QT_LockHWSurface(_THIS, SDL_Surface *surface); + static void QT_UnlockHWSurface(_THIS, SDL_Surface *surface); + static void QT_FreeHWSurface(_THIS, SDL_Surface *surface); + + static int QT_ToggleFullScreen(_THIS, int fullscreen); + + static int QT_IconifyWindow(_THIS); + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode); + + /* FB driver bootstrap functions */ + + static int QT_Available(void) + { + return(1); + } + + static void QT_DeleteDevice(SDL_VideoDevice *device) + { + SDL_free(device->hidden); + SDL_free(device); + } + + static SDL_VideoDevice *QT_CreateDevice(int devindex) + { + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = QT_VideoInit; + device->ListModes = QT_ListModes; + device->SetVideoMode = QT_SetVideoMode; + device->UpdateMouse = QT_UpdateMouse; + device->SetColors = QT_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = QT_VideoQuit; + device->AllocHWSurface = QT_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = QT_LockHWSurface; + device->UnlockHWSurface = QT_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = QT_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = QT_SetWMCaption; + device->IconifyWindow = QT_IconifyWindow; + device->GrabInput = QT_GrabInput; + device->GetWMInfo = NULL; + device->FreeWMCursor = QT_FreeWMCursor; + device->CreateWMCursor = QT_CreateWMCursor; + device->ShowWMCursor = QT_ShowWMCursor; + device->WarpWMCursor = QT_WarpWMCursor; + device->InitOSKeymap = QT_InitOSKeymap; + device->PumpEvents = QT_PumpEvents; + + device->free = QT_DeleteDevice; + device->ToggleFullScreen = QT_ToggleFullScreen; + + /* Set the driver flags */ + device->handles_any_size = 0; + + return device; + } + + VideoBootStrap Qtopia_bootstrap = { + "qtopia", "Qtopia / QPE graphics", + QT_Available, QT_CreateDevice + }; + + /* Function to sort the display_list */ + static int CompareModes(const void *A, const void *B) + { +#if 0 + const display_mode *a = (display_mode *)A; + const display_mode *b = (display_mode *)B; + + if ( a->space == b->space ) { + return((b->virtual_width*b->virtual_height)- + (a->virtual_width*a->virtual_height)); + } else { + return(ColorSpaceToBitsPerPixel(b->space)- + ColorSpaceToBitsPerPixel(a->space)); + } +#endif + return 0; + } + + /* Yes, this isn't the fastest it could be, but it works nicely */ + static int QT_AddMode(_THIS, int index, unsigned int w, unsigned int h) + { + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef QTOPIA_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); + } + + int QT_VideoInit(_THIS, SDL_PixelFormat *vformat) + { + /* Initialize the QPE Application */ + /* Determine the screen depth */ + vformat->BitsPerPixel = QPixmap::defaultDepth(); + + // For now we hardcode the current depth because anything else + // might as well be emulated by SDL rather than by Qtopia. + + QSize desktop_size = qApp->desktop()->size(); + QT_AddMode(_this, ((vformat->BitsPerPixel+7)/8)-1, + desktop_size.width(), desktop_size.height()); + QT_AddMode(_this, ((vformat->BitsPerPixel+7)/8)-1, + desktop_size.height(), desktop_size.width()); + + /* Determine the current screen size */ + _this->info.current_w = desktop_size.width(); + _this->info.current_h = desktop_size.height(); + + /* Create the window / widget */ + SDL_Win = new SDL_QWin(QSize(QT_HIDDEN_SIZE, QT_HIDDEN_SIZE)); + ((QPEApplication*)qApp)->showMainWidget(SDL_Win); + /* Fill in some window manager capabilities */ + _this->info.wm_available = 0; + + /* We're done! */ + return(0); + } + + /* We support any dimension at our bit-depth */ + SDL_Rect **QT_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) + { + SDL_Rect **modes; + + modes = ((SDL_Rect **)0); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; + } else { + if ( format->BitsPerPixel == + _this->screen->format->BitsPerPixel ) { + modes = ((SDL_Rect **)-1); + } + } + return(modes); + } + + /* Various screen update functions available */ + static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + + + static int QT_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) + { + return -1; + } + + static int QT_ToggleFullScreen(_THIS, int fullscreen) + { + return -1; + } + + /* FIXME: check return values and cleanup here */ + SDL_Surface *QT_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) + { + + QImage *qimage; + QSize desktop_size = qApp->desktop()->size(); + + + current->flags = 0; //SDL_FULLSCREEN; // We always run fullscreen. + + if(width <= desktop_size.width() + && height <= desktop_size.height()) { + current->w = desktop_size.width(); + current->h = desktop_size.height(); + } else if(width <= desktop_size.height() && height <= desktop_size.width()) { + // Landscape mode + char * envString = SDL_getenv(SDL_QT_ROTATION_ENV_NAME); + int envValue = envString ? atoi(envString) : 0; + screenRotation = envValue ? SDL_QT_ROTATION_270 : SDL_QT_ROTATION_90; + current->h = desktop_size.width(); + current->w = desktop_size.height(); + } else { + SDL_SetError("Unsupported resolution, %dx%d\n", width, height); + } + if ( flags & SDL_OPENGL ) { + SDL_SetError("OpenGL not supported"); + return(NULL); + } + /* Create the QImage framebuffer */ + qimage = new QImage(current->w, current->h, bpp); + if (qimage->isNull()) { + SDL_SetError("Couldn't create screen bitmap"); + delete qimage; + return(NULL); + } + current->pitch = qimage->bytesPerLine(); + current->pixels = (void *)qimage->bits(); + SDL_Win->setImage(qimage); + _this->UpdateRects = QT_NormalUpdate; + SDL_Win->setFullscreen(true); + /* We're done */ + return(current); + } + + /* Update the current mouse state and position */ + void QT_UpdateMouse(_THIS) + { + QPoint point(-1, -1); + if ( SDL_Win->isActiveWindow() ) { + point = SDL_Win->mousePos(); + } + + if ( (point.x() >= 0) && (point.x() < SDL_VideoSurface->w) && + (point.y() >= 0) && (point.y() < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, + (Sint16)point.x(), (Sint16)point.y()); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + + /* We don't actually allow hardware surfaces other than the main one */ + static int QT_AllocHWSurface(_THIS, SDL_Surface *surface) + { + return(-1); + } + static void QT_FreeHWSurface(_THIS, SDL_Surface *surface) + { + return; + } + static int QT_LockHWSurface(_THIS, SDL_Surface *surface) + { + return(0); + } + static void QT_UnlockHWSurface(_THIS, SDL_Surface *surface) + { + return; + } + + static void QT_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) + { + if(SDL_Win->lockScreen()) { + for(int i=0; i<numrects; ++i ) { + QRect rect(rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + SDL_Win->repaintRect(rect); + } + SDL_Win->unlockScreen(); + } + } + /* Is the system palette settable? */ + int QT_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) + { + return -1; + } + + void QT_VideoQuit(_THIS) + { + // This is dumb, but if I free this, the app doesn't exit correctly. + // Of course, this will leak memory if init video is done more than once. + // Sucks but such is life. + + // -- David Hedbor + // delete SDL_Win; + // SDL_Win = 0; + _this->screen->pixels = NULL; + QT_GrabInput(_this, SDL_GRAB_OFF); + } + + static int QT_IconifyWindow(_THIS) { + SDL_Win->hide(); + + return true; + } + + static SDL_GrabMode QT_GrabInput(_THIS, SDL_GrabMode mode) { + if(mode == SDL_GRAB_OFF) { + QPEApplication::grabKeyboard(); + qApp->processEvents(); + QPEApplication::ungrabKeyboard(); + } else { + QPEApplication::grabKeyboard(); + } + qApp->processEvents(); + return mode; + } + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc b/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc new file mode 100644 index 0000000..47f988f --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_syswm.cc @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QWin.h" + +extern "C" { + +#include "SDL_syswm_c.h" + +void QT_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_Win->setCaption(title); +} + +}; /* Extern C */ diff --git a/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h b/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h new file mode 100644 index 0000000..4e4326b --- /dev/null +++ b/3rdparty/SDL/src/video/qtopia/SDL_syswm_c.h @@ -0,0 +1,28 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void QT_SetWMCaption(_THIS, const char *title, const char *icon); + diff --git a/3rdparty/SDL/src/video/quartz/CGS.h b/3rdparty/SDL/src/video/quartz/CGS.h new file mode 100644 index 0000000..abe47f7 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/CGS.h @@ -0,0 +1,84 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Obscuring code: maximum number of windows above ours (inclusive) + + Note: this doesn't work too well in practice and should be + phased out when we add OpenGL 2D acceleration. It was never + enabled in the first place, so this shouldn't be a problem ;-) +*/ +#define kMaxWindows 256 + +/* Some of the Core Graphics Server API for obscuring code */ +#define kCGSWindowLevelTop 2147483632 +#define kCGSWindowLevelDockIconDrag 500 +#define kCGSWindowLevelDockMenu 101 +#define kCGSWindowLevelMenuIgnore 21 +#define kCGSWindowLevelMenu 20 +#define kCGSWindowLevelDockLabel 12 +#define kCGSWindowLevelDockIcon 11 +#define kCGSWindowLevelDock 10 +#define kCGSWindowLevelUtility 3 +#define kCGSWindowLevelNormal 0 + +/* + For completeness; We never use these window levels, they are always below us + #define kCGSWindowLevelMBarShadow -20 + #define kCGSWindowLevelDesktopPicture -2147483647 + #define kCGSWindowLevelDesktop -2147483648 +*/ + +typedef CGError CGSError; +typedef long CGSWindowCount; +typedef void * CGSConnectionID; +typedef int CGSWindowID; +typedef CGSWindowID* CGSWindowIDList; +typedef CGWindowLevel CGSWindowLevel; +typedef NSRect CGSRect; + +extern CGSConnectionID _CGSDefaultConnection (); + +extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, + CGSConnectionID owner, + CGSWindowCount listCapacity, + CGSWindowIDList list, + CGSWindowCount *listCount); + +extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, + CGSWindowID wid, + CGSRect *rect); + +extern CGWindowLevel CGSGetWindowLevel (CGSConnectionID cid, + CGSWindowID wid, + CGSWindowLevel *level); + +extern CGSError CGSDisplayHWFill (CGDirectDisplayID id, unsigned int x, unsigned int y, + unsigned int w, unsigned int h, unsigned int color); + +extern CGSError CGSDisplayCanHWFill (CGDirectDisplayID id); + +extern CGSError CGSGetMouseEnabledFlags (CGSConnectionID cid, CGSWindowID wid, int *flags); + +int CGSDisplayHWSync (CGDirectDisplayID id); + diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m new file mode 100644 index 0000000..773eb01 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzEvents.m @@ -0,0 +1,1063 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" + +#include <IOKit/IOMessage.h> /* For wake from sleep detection */ +#include <IOKit/pwr_mgt/IOPMLib.h> /* For wake from sleep detection */ +#include "SDL_QuartzKeys.h" + +/* + * On Leopard, this is missing from the 64-bit headers + */ +#if defined(__LP64__) && !defined(__POWER__) +/* + * Workaround for a bug in the 10.5 SDK: By accident, OSService.h does + * not include Power.h at all when compiling in 64bit mode. This has + * been fixed in 10.6, but for 10.5, we manually define UsrActivity + * to ensure compilation works. + */ +#define UsrActivity 1 +#endif + +/* + * In Panther, this header defines device dependent masks for + * right side keys. These definitions only exist in Panther, but + * the header seems to exist at least in Jaguar and probably earlier + * versions of the OS, so this should't break anything. + */ +#include <IOKit/hidsystem/IOLLEvent.h> +/* + * These are not defined before Panther. To keep the code compiling + * on systems without these, I will define if they don't exist. + */ +#ifndef NX_DEVICERCTLKEYMASK + #define NX_DEVICELCTLKEYMASK 0x00000001 +#endif +#ifndef NX_DEVICELSHIFTKEYMASK + #define NX_DEVICELSHIFTKEYMASK 0x00000002 +#endif +#ifndef NX_DEVICERSHIFTKEYMASK + #define NX_DEVICERSHIFTKEYMASK 0x00000004 +#endif +#ifndef NX_DEVICELCMDKEYMASK + #define NX_DEVICELCMDKEYMASK 0x00000008 +#endif +#ifndef NX_DEVICERCMDKEYMASK + #define NX_DEVICERCMDKEYMASK 0x00000010 +#endif +#ifndef NX_DEVICELALTKEYMASK + #define NX_DEVICELALTKEYMASK 0x00000020 +#endif +#ifndef NX_DEVICERALTKEYMASK + #define NX_DEVICERALTKEYMASK 0x00000040 +#endif +#ifndef NX_DEVICERCTLKEYMASK + #define NX_DEVICERCTLKEYMASK 0x00002000 +#endif + +void QZ_InitOSKeymap (_THIS) { + BOOL saw_layout = NO; + UInt32 state; + UInt32 value; + Uint16 i; + int world = SDLK_WORLD_0; + + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + /* This keymap is almost exactly the same as the OS 9 one */ + keymap[QZ_ESCAPE] = SDLK_ESCAPE; + keymap[QZ_F1] = SDLK_F1; + keymap[QZ_F2] = SDLK_F2; + keymap[QZ_F3] = SDLK_F3; + keymap[QZ_F4] = SDLK_F4; + keymap[QZ_F5] = SDLK_F5; + keymap[QZ_F6] = SDLK_F6; + keymap[QZ_F7] = SDLK_F7; + keymap[QZ_F8] = SDLK_F8; + keymap[QZ_F9] = SDLK_F9; + keymap[QZ_F10] = SDLK_F10; + keymap[QZ_F11] = SDLK_F11; + keymap[QZ_F12] = SDLK_F12; + keymap[QZ_F13] = SDLK_F13; + keymap[QZ_F14] = SDLK_F14; + keymap[QZ_F15] = SDLK_F15; +/* + keymap[QZ_PRINT] = SDLK_PRINT; + keymap[QZ_SCROLLOCK] = SDLK_SCROLLOCK; + keymap[QZ_PAUSE] = SDLK_PAUSE; +*/ + keymap[QZ_POWER] = SDLK_POWER; + keymap[QZ_BACKQUOTE] = SDLK_BACKQUOTE; + keymap[QZ_1] = SDLK_1; + keymap[QZ_2] = SDLK_2; + keymap[QZ_3] = SDLK_3; + keymap[QZ_4] = SDLK_4; + keymap[QZ_5] = SDLK_5; + keymap[QZ_6] = SDLK_6; + keymap[QZ_7] = SDLK_7; + keymap[QZ_8] = SDLK_8; + keymap[QZ_9] = SDLK_9; + keymap[QZ_0] = SDLK_0; + keymap[QZ_MINUS] = SDLK_MINUS; + keymap[QZ_EQUALS] = SDLK_EQUALS; + keymap[QZ_BACKSPACE] = SDLK_BACKSPACE; + keymap[QZ_INSERT] = SDLK_INSERT; + keymap[QZ_HOME] = SDLK_HOME; + keymap[QZ_PAGEUP] = SDLK_PAGEUP; + keymap[QZ_NUMLOCK] = SDLK_NUMLOCK; + keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; + keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; + keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + keymap[QZ_TAB] = SDLK_TAB; + keymap[QZ_q] = SDLK_q; + keymap[QZ_w] = SDLK_w; + keymap[QZ_e] = SDLK_e; + keymap[QZ_r] = SDLK_r; + keymap[QZ_t] = SDLK_t; + keymap[QZ_y] = SDLK_y; + keymap[QZ_u] = SDLK_u; + keymap[QZ_i] = SDLK_i; + keymap[QZ_o] = SDLK_o; + keymap[QZ_p] = SDLK_p; + keymap[QZ_LEFTBRACKET] = SDLK_LEFTBRACKET; + keymap[QZ_RIGHTBRACKET] = SDLK_RIGHTBRACKET; + keymap[QZ_BACKSLASH] = SDLK_BACKSLASH; + keymap[QZ_DELETE] = SDLK_DELETE; + keymap[QZ_END] = SDLK_END; + keymap[QZ_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[QZ_KP7] = SDLK_KP7; + keymap[QZ_KP8] = SDLK_KP8; + keymap[QZ_KP9] = SDLK_KP9; + keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; + keymap[QZ_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[QZ_a] = SDLK_a; + keymap[QZ_s] = SDLK_s; + keymap[QZ_d] = SDLK_d; + keymap[QZ_f] = SDLK_f; + keymap[QZ_g] = SDLK_g; + keymap[QZ_h] = SDLK_h; + keymap[QZ_j] = SDLK_j; + keymap[QZ_k] = SDLK_k; + keymap[QZ_l] = SDLK_l; + keymap[QZ_SEMICOLON] = SDLK_SEMICOLON; + keymap[QZ_QUOTE] = SDLK_QUOTE; + keymap[QZ_RETURN] = SDLK_RETURN; + keymap[QZ_KP4] = SDLK_KP4; + keymap[QZ_KP5] = SDLK_KP5; + keymap[QZ_KP6] = SDLK_KP6; + keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; + keymap[QZ_LSHIFT] = SDLK_LSHIFT; + keymap[QZ_RSHIFT] = SDLK_RSHIFT; + keymap[QZ_z] = SDLK_z; + keymap[QZ_x] = SDLK_x; + keymap[QZ_c] = SDLK_c; + keymap[QZ_v] = SDLK_v; + keymap[QZ_b] = SDLK_b; + keymap[QZ_n] = SDLK_n; + keymap[QZ_m] = SDLK_m; + keymap[QZ_COMMA] = SDLK_COMMA; + keymap[QZ_PERIOD] = SDLK_PERIOD; + keymap[QZ_SLASH] = SDLK_SLASH; + keymap[QZ_UP] = SDLK_UP; + keymap[QZ_KP1] = SDLK_KP1; + keymap[QZ_KP2] = SDLK_KP2; + keymap[QZ_KP3] = SDLK_KP3; + keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; + keymap[QZ_LCTRL] = SDLK_LCTRL; + keymap[QZ_LALT] = SDLK_LALT; + keymap[QZ_LMETA] = SDLK_LMETA; + keymap[QZ_RCTRL] = SDLK_RCTRL; + keymap[QZ_RALT] = SDLK_RALT; + keymap[QZ_RMETA] = SDLK_RMETA; + keymap[QZ_SPACE] = SDLK_SPACE; + keymap[QZ_LEFT] = SDLK_LEFT; + keymap[QZ_DOWN] = SDLK_DOWN; + keymap[QZ_RIGHT] = SDLK_RIGHT; + keymap[QZ_KP0] = SDLK_KP0; + keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; + keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER; + keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; + keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; + keymap[QZ_IBOOK_UP] = SDLK_UP; + keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; + + /* + Up there we setup a static scancode->keysym map. However, it will not + work very well on international keyboard. Hence we now query MacOS + for its own keymap to adjust our own mapping table. However, this is + basically only useful for ascii char keys. This is also the reason + why we keep the static table, too. + */ + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1050) + if (TISCopyCurrentKeyboardLayoutInputSource != NULL) { + TISInputSourceRef src = TISCopyCurrentKeyboardLayoutInputSource(); + if (src != NULL) { + CFDataRef data = (CFDataRef) + TISGetInputSourceProperty(src, + kTISPropertyUnicodeKeyLayoutData); + if (data != NULL) { + const UCKeyboardLayout *layout = (const UCKeyboardLayout *) + CFDataGetBytePtr(data); + if (layout != NULL) { + const UInt32 kbdtype = LMGetKbdType(); + saw_layout = YES; + + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) { + UniChar buf[16]; + UniCharCount count = 0; + + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + + /* If the state become 0, it was a dead key. We need to + translate again, passing in the new state, to get + the actual key value */ + if (state != 0) { + if (UCKeyTranslate(layout, i, kUCKeyActionDown, 0, kbdtype, + 0, &state, 16, &count, buf) != noErr) { + continue; + } + } + + if (count != 1) { + continue; /* no multi-char. Use SDL 1.3 instead. :) */ + } + + value = (UInt32) buf[0]; + if (value >= 128) { + /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } + } + } + CFRelease(src); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1050) + if (!saw_layout) { + /* Get a pointer to the systems cached KCHR */ + const void *KCHRPtr = (const void *)GetScriptManagerVariable(smKCHRCache); + if (KCHRPtr) + { + /* Loop over all 127 possible scan codes */ + for (i = 0; i < 0x7F; i++) + { + /* We pretend a clean start to begin with (i.e. no dead keys active */ + state = 0; + + /* Now translate the key code to a key value */ + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* If the state become 0, it was a dead key. We need to translate again, + passing in the new state, to get the actual key value */ + if (state != 0) + value = KeyTranslate(KCHRPtr, i, &state) & 0xff; + + /* Now we should have an ascii value, or 0. Try to figure out to which SDL symbol it maps */ + if (value >= 128) { /* Some non-ASCII char, map it to SDLK_WORLD_* */ + if (world < 0xFF) { + keymap[i] = world++; + } + } else if (value >= 32) { /* non-control ASCII char */ + keymap[i] = value; + } + } + } + } +#endif + + /* + The keypad codes are re-setup here, because the loop above cannot + distinguish between a key on the keypad and a regular key. We maybe + could get around this problem in another fashion: NSEvent's flags + include a "NSNumericPadKeyMask" bit; we could check that and modify + the symbol we return on the fly. However, this flag seems to exhibit + some weird behaviour related to the num lock key + */ + keymap[QZ_KP0] = SDLK_KP0; + keymap[QZ_KP1] = SDLK_KP1; + keymap[QZ_KP2] = SDLK_KP2; + keymap[QZ_KP3] = SDLK_KP3; + keymap[QZ_KP4] = SDLK_KP4; + keymap[QZ_KP5] = SDLK_KP5; + keymap[QZ_KP6] = SDLK_KP6; + keymap[QZ_KP7] = SDLK_KP7; + keymap[QZ_KP8] = SDLK_KP8; + keymap[QZ_KP9] = SDLK_KP9; + keymap[QZ_KP_MINUS] = SDLK_KP_MINUS; + keymap[QZ_KP_PLUS] = SDLK_KP_PLUS; + keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; + keymap[QZ_KP_EQUALS] = SDLK_KP_EQUALS; + keymap[QZ_KP_DIVIDE] = SDLK_KP_DIVIDE; + keymap[QZ_KP_MULTIPLY] = SDLK_KP_MULTIPLY; + keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; +} + +static void QZ_DoKey (_THIS, int state, NSEvent *event) { + + NSString *chars = NULL; + unsigned int i, numChars; + SDL_keysym key; + + /* + A key event can contain multiple characters, + or no characters at all. In most cases, it + will contain a single character. If it contains + 0 characters, we'll use 0 as the unicode. If it + contains multiple characters, we'll use 0 as + the scancode/keysym. + */ + if (SDL_TranslateUNICODE && state == SDL_PRESSED) { + [field_edit interpretKeyEvents:[NSArray arrayWithObject:event]]; + chars = [ event characters ]; + numChars = [ chars length ]; + if (numChars > 0) + [field_edit setString:@""]; + } else { + numChars = 0; + } + + if (numChars == 0) { + + key.scancode = [ event keyCode ]; + key.sym = keymap [ key.scancode ]; + key.unicode = 0; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + } + else if (numChars >= 1) { + + key.scancode = [ event keyCode ]; + key.sym = keymap [ key.scancode ]; + key.unicode = [ chars characterAtIndex:0 ]; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + + for (i = 1; i < numChars; i++) { + + key.scancode = 0; + key.sym = 0; + key.unicode = [ chars characterAtIndex:i]; + key.mod = KMOD_NONE; + + SDL_PrivateKeyboard (state, &key); + } + } + + if (SDL_getenv ("SDL_ENABLEAPPEVENTS")) + [ NSApp sendEvent:event ]; +} + +/* This is the original behavior, before support was added for + * differentiating between left and right versions of the keys. + */ +static void QZ_DoUnsidedModifiers (_THIS, unsigned int newMods) { + + const int mapping[] = { SDLK_CAPSLOCK, SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; + + int i; + int bit; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_UNKNOWN; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Iterate through the bits, testing each against the current modifiers */ + for (i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + + unsigned int currentMask, newMask; + + currentMask = current_mods & bit; + newMask = newMods & bit; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + + key.sym = mapping[i]; + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + if (bit == NSAlphaShiftKeyMask) + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + + key.sym = mapping[i]; + SDL_PrivateKeyboard (SDL_PRESSED, &key); + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + if (bit == NSAlphaShiftKeyMask) + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + } +} + +/* This is a helper function for QZ_HandleModifierSide. This + * function reverts back to behavior before the distinction between + * sides was made. + */ +static void QZ_HandleNonDeviceModifier ( _THIS, unsigned int device_independent_mask, unsigned int newMods, unsigned int key_sym) { + unsigned int currentMask, newMask; + SDL_keysym key; + + key.scancode = 0; + key.sym = key_sym; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Isolate just the bits we care about in the depedent bits so we can + * figure out what changed + */ + currentMask = current_mods & device_independent_mask; + newMask = newMods & device_independent_mask; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + } +} + +/* This is a helper function for QZ_HandleModifierSide. + * This function sets the actual SDL_PrivateKeyboard event. + */ +static void QZ_HandleModifierOneSide ( _THIS, unsigned int newMods, + unsigned int key_sym, + unsigned int sided_device_dependent_mask ) { + + SDL_keysym key; + unsigned int current_dep_mask, new_dep_mask; + + key.scancode = 0; + key.sym = key_sym; + key.unicode = 0; + key.mod = KMOD_NONE; + + /* Isolate just the bits we care about in the depedent bits so we can + * figure out what changed + */ + current_dep_mask = current_mods & sided_device_dependent_mask; + new_dep_mask = newMods & sided_device_dependent_mask; + + /* We now know that this side bit flipped. But we don't know if + * it went pressed to released or released to pressed, so we must + * find out which it is. + */ + if( new_dep_mask && + current_dep_mask != new_dep_mask ) { + /* Modifier down event */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + } + else /* Modifier up event */ { + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function will figure out if the modifier key is the left or right side, + * e.g. left-shift vs right-shift. + */ +static void QZ_HandleModifierSide ( _THIS, int device_independent_mask, + unsigned int newMods, + unsigned int left_key_sym, + unsigned int right_key_sym, + unsigned int left_device_dependent_mask, + unsigned int right_device_dependent_mask ) { + unsigned int device_dependent_mask = 0; + unsigned int diff_mod = 0; + + device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; + /* On the basis that the device independent mask is set, but there are + * no device dependent flags set, we'll assume that we can't detect this + * keyboard and revert to the unsided behavior. + */ + if ( (device_dependent_mask & newMods) == 0 ) { + /* Revert to the old behavior */ + QZ_HandleNonDeviceModifier ( this, device_independent_mask, newMods, left_key_sym ); + return; + } + + /* XOR the previous state against the new state to see if there's a change */ + diff_mod = (device_dependent_mask & current_mods) + ^ (device_dependent_mask & newMods); + + if ( diff_mod ) { + /* A change in state was found. Isolate the left and right bits + * to handle them separately just in case the values can simulataneously + * change or if the bits don't both exist. + */ + if ( left_device_dependent_mask & diff_mod ) { + QZ_HandleModifierOneSide ( this, newMods, left_key_sym, left_device_dependent_mask ); + } + if ( right_device_dependent_mask & diff_mod ) { + QZ_HandleModifierOneSide ( this, newMods, right_key_sym, right_device_dependent_mask ); + } + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function will release a key press in the case that + * it is clear that the modifier has been released (i.e. one side + * can't still be down). + */ +static void QZ_ReleaseModifierSide ( _THIS, + unsigned int device_independent_mask, + unsigned int newMods, + unsigned int left_key_sym, + unsigned int right_key_sym, + unsigned int left_device_dependent_mask, + unsigned int right_device_dependent_mask ) { + unsigned int device_dependent_mask = 0; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_UNKNOWN; + key.unicode = 0; + key.mod = KMOD_NONE; + + device_dependent_mask = left_device_dependent_mask | right_device_dependent_mask; + /* On the basis that the device independent mask is set, but there are + * no device dependent flags set, we'll assume that we can't detect this + * keyboard and revert to the unsided behavior. + */ + if ( (device_dependent_mask & current_mods) == 0 ) { + /* In this case, we can't detect the keyboard, so use the left side + * to represent both, and release it. + */ + key.sym = left_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + + return; + } + + + /* + * This could have been done in an if-else case because at this point, + * we know that all keys have been released when calling this function. + * But I'm being paranoid so I want to handle each separately, + * so I hope this doesn't cause other problems. + */ + if ( left_device_dependent_mask & current_mods ) { + key.sym = left_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + if ( right_device_dependent_mask & current_mods ) { + key.sym = right_key_sym; + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This is a helper function for QZ_DoSidedModifiers. + * This function handles the CapsLock case. + */ +static void QZ_HandleCapsLock (_THIS, unsigned int newMods) { + unsigned int currentMask, newMask; + SDL_keysym key; + + key.scancode = 0; + key.sym = SDLK_CAPSLOCK; + key.unicode = 0; + key.mod = KMOD_NONE; + + currentMask = current_mods & NSAlphaShiftKeyMask; + newMask = newMods & NSAlphaShiftKeyMask; + + if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else if ( newMask && + currentMask != newMask ) { /* modifier down event */ + /* If this was Caps Lock, we need some additional voodoo to make SDL happy */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } +} + +/* This function will handle the modifier keys and also determine the + * correct side of the key. + */ +static void QZ_DoSidedModifiers (_THIS, unsigned int newMods) { + /* Set up arrays for the key syms for the left and right side. */ + const unsigned int left_mapping[] = { SDLK_LSHIFT, SDLK_LCTRL, SDLK_LALT, SDLK_LMETA }; + const unsigned int right_mapping[] = { SDLK_RSHIFT, SDLK_RCTRL, SDLK_RALT, SDLK_RMETA }; + /* Set up arrays for the device dependent masks with indices that + * correspond to the _mapping arrays + */ + const unsigned int left_device_mapping[] = { NX_DEVICELSHIFTKEYMASK, NX_DEVICELCTLKEYMASK, NX_DEVICELALTKEYMASK, NX_DEVICELCMDKEYMASK }; + const unsigned int right_device_mapping[] = { NX_DEVICERSHIFTKEYMASK, NX_DEVICERCTLKEYMASK, NX_DEVICERALTKEYMASK, NX_DEVICERCMDKEYMASK }; + + unsigned int i; + unsigned int bit; + + /* Handle CAPSLOCK separately because it doesn't have a left/right side */ + QZ_HandleCapsLock ( this, newMods ); + + /* Iterate through the bits, testing each against the current modifiers */ + for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + + unsigned int currentMask, newMask; + + currentMask = current_mods & bit; + newMask = newMods & bit; + + /* If the bit is set, we must always examine it because the left + * and right side keys may alternate or both may be pressed. + */ + if ( newMask ) { + QZ_HandleModifierSide ( this, bit, newMods, + left_mapping[i], + right_mapping[i], + left_device_mapping[i], + right_device_mapping[i] ); + } + /* If the state changed from pressed to unpressed, we must examine + * the device dependent bits to release the correct keys. + */ + else if ( currentMask && + currentMask != newMask ) { /* modifier up event */ + QZ_ReleaseModifierSide ( this, bit, newMods, + left_mapping[i], + right_mapping[i], + left_device_mapping[i], + right_device_mapping[i] ); + } + } +} + +/* This function is called to handle the modifiers. + * It will try to distinguish between the left side and right side + * of the keyboard for those modifiers that qualify if the + * operating system version supports it. Otherwise, the code + * will not try to make the distinction. + */ +static void QZ_DoModifiers (_THIS, unsigned int newMods) { + + if (current_mods == newMods) + return; + + /* + * Starting with Panther (10.3.0), the ability to distinguish between + * left side and right side modifiers is available. + */ + if( system_version >= 0x1030 ) { + QZ_DoSidedModifiers (this, newMods); + } + else { + QZ_DoUnsidedModifiers (this, newMods); + } + + current_mods = newMods; +} + +static void QZ_GetMouseLocation (_THIS, NSPoint *p) { + *p = [ NSEvent mouseLocation ]; /* global coordinates */ + if (qz_window) + QZ_PrivateGlobalToLocal (this, p); + QZ_PrivateCocoaToSDL (this, p); +} + +void QZ_DoActivate (_THIS) { + + SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0)); + + QZ_UpdateCursor(this); + + /* Regrab input, only if it was previously grabbed */ + if ( current_grab_mode == SDL_GRAB_ON ) { + + /* Restore cursor location if input was grabbed */ + QZ_PrivateWarpCursor (this, cursor_loc.x, cursor_loc.y); + QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); + } + else { + /* Update SDL's mouse location */ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); + } + + QZ_UpdateCursor(this); +} + +void QZ_DoDeactivate (_THIS) { + + SDL_PrivateAppActive (0, SDL_APPINPUTFOCUS | SDL_APPMOUSEFOCUS); + + /* Get the current cursor location, for restore on activate */ + QZ_GetMouseLocation (this, &cursor_loc); + + /* Reassociate mouse and cursor */ + CGAssociateMouseAndMouseCursorPosition (1); + + QZ_UpdateCursor(this); +} + +void QZ_SleepNotificationHandler (void * refcon, + io_service_t service, + natural_t messageType, + void * messageArgument ) +{ + SDL_VideoDevice *this = (SDL_VideoDevice*)refcon; + + switch(messageType) + { + case kIOMessageSystemWillSleep: + IOAllowPowerChange(power_connection, (long) messageArgument); + break; + case kIOMessageCanSystemSleep: + IOAllowPowerChange(power_connection, (long) messageArgument); + break; + case kIOMessageSystemHasPoweredOn: + /* awake */ + SDL_PrivateExpose(); + break; + } +} + +void QZ_RegisterForSleepNotifications (_THIS) +{ + CFRunLoopSourceRef rls; + IONotificationPortRef thePortRef; + io_object_t notifier; + + power_connection = IORegisterForSystemPower (this, &thePortRef, QZ_SleepNotificationHandler, ¬ifier); + + if (power_connection == 0) + NSLog(@"SDL: QZ_SleepNotificationHandler() IORegisterForSystemPower failed."); + + rls = IONotificationPortGetRunLoopSource (thePortRef); + CFRunLoopAddSource (CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease (rls); +} + + +/* Try to map Quartz mouse buttons to SDL's lingo... */ +static int QZ_OtherMouseButtonToSDL(int button) +{ + switch (button) + { + case 0: + return(SDL_BUTTON_LEFT); /* 1 */ + case 1: + return(SDL_BUTTON_RIGHT); /* 3 */ + case 2: + return(SDL_BUTTON_MIDDLE); /* 2 */ + } + + /* >= 3: skip 4 & 5, since those are the SDL mousewheel buttons. */ + return(button + 3); +} + + +void QZ_PumpEvents (_THIS) +{ + int32_t dx, dy; + + NSDate *distantPast; + NSEvent *event; + NSRect winRect; + NSAutoreleasePool *pool; + + if (!SDL_VideoSurface) + return; /* don't do anything if there's no screen surface. */ + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) + { + UpdateSystemActivity(UsrActivity); + screensaverTicks = nowTicks; + } + } + + pool = [ [ NSAutoreleasePool alloc ] init ]; + distantPast = [ NSDate distantPast ]; + + winRect = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + + /* while grabbed, accumulate all mouse moved events into one SDL mouse event */ + dx = 0; + dy = 0; + + do { + + /* Poll for an event. This will not block */ + event = [ NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:distantPast + inMode: NSDefaultRunLoopMode dequeue:YES ]; + if (event != nil) { + + int button; + unsigned int type; + BOOL isInGameWin; + + #define DO_MOUSE_DOWN(button) do { \ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { \ + SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); \ + expect_mouse_up |= 1<<button; \ + } \ + [ NSApp sendEvent:event ]; \ + } while(0) + + #define DO_MOUSE_UP(button) do { \ + if ( expect_mouse_up & (1<<button) ) { \ + SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); \ + expect_mouse_up &= ~(1<<button); \ + } \ + [ NSApp sendEvent:event ]; \ + } while(0) + + type = [ event type ]; + isInGameWin = QZ_IsMouseInWindow (this); + + QZ_DoModifiers(this, [ event modifierFlags ] ); + + switch (type) { + case NSLeftMouseDown: + if ( SDL_getenv("SDL_HAS3BUTTONMOUSE") ) { + DO_MOUSE_DOWN (SDL_BUTTON_LEFT); + } else { + if ( NSCommandKeyMask & current_mods ) { + last_virtual_button = SDL_BUTTON_RIGHT; + DO_MOUSE_DOWN (SDL_BUTTON_RIGHT); + } + else if ( NSAlternateKeyMask & current_mods ) { + last_virtual_button = SDL_BUTTON_MIDDLE; + DO_MOUSE_DOWN (SDL_BUTTON_MIDDLE); + } + else { + DO_MOUSE_DOWN (SDL_BUTTON_LEFT); + } + } + break; + + case NSLeftMouseUp: + if ( last_virtual_button != 0 ) { + DO_MOUSE_UP (last_virtual_button); + last_virtual_button = 0; + } + else { + DO_MOUSE_UP (SDL_BUTTON_LEFT); + } + break; + + case NSOtherMouseDown: + case NSRightMouseDown: + button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); + DO_MOUSE_DOWN (button); + break; + + case NSOtherMouseUp: + case NSRightMouseUp: + button = QZ_OtherMouseButtonToSDL([ event buttonNumber ]); + DO_MOUSE_UP (button); + break; + + case NSSystemDefined: + /* + Future: up to 32 "mouse" buttons can be handled. + if ([event subtype] == 7) { + unsigned int buttons; + buttons = [ event data2 ]; + */ + break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: /* usually middle mouse dragged */ + case NSMouseMoved: + if ( grab_state == QZ_INVISIBLE_GRAB ) { + + /* + If input is grabbed+hidden, the cursor doesn't move, + so we have to call the lowlevel window server + function. This is less accurate but works OK. + */ + int32_t dx1, dy1; + CGGetLastMouseDelta (&dx1, &dy1); + dx += dx1; + dy += dy1; + } + else { + + /* + Get the absolute mouse location. This is not the + mouse location after the currently processed event, + but the *current* mouse location, i.e. after all + pending events. This means that if there are + multiple mouse moved events in the queue, we make + multiple identical calls to SDL_PrivateMouseMotion(), + but that's no problem since the latter only + generates SDL events for nonzero movements. In my + experience on PBG4/10.4.8, this rarely happens anyway. + */ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); + } + + /* + Handle grab input+cursor visible by warping the cursor back + into the game window. This still generates a mouse moved event, + but not as a result of the warp (so it's in the right direction). + */ + if ( grab_state == QZ_VISIBLE_GRAB && !isInGameWin ) { + + NSPoint p; + QZ_GetMouseLocation (this, &p); + + if ( p.x < 0.0 ) + p.x = 0.0; + + if ( p.y < 0.0 ) + p.y = 0.0; + + if ( p.x >= winRect.size.width ) + p.x = winRect.size.width-1; + + if ( p.y >= winRect.size.height ) + p.y = winRect.size.height-1; + + QZ_PrivateWarpCursor (this, p.x, p.y); + } + else + if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + + SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS); + + if (grab_state == QZ_INVISIBLE_GRAB) + /*The cursor has left the window even though it is + disassociated from the mouse (and therefore + shouldn't move): this can happen with Wacom + tablets, and it effectively breaks the grab, since + mouse down events now go to background + applications. The only possibility to avoid this + seems to be talking to the tablet driver + (AppleEvents) to constrain its mapped area to the + window, which may not be worth the effort. For + now, handle the condition more gracefully than + before by reassociating cursor and mouse until the + cursor enters the window again, making it obvious + to the user that the grab is broken.*/ + CGAssociateMouseAndMouseCursorPosition (1); + + QZ_UpdateCursor(this); + } + else + if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) { + + SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS); + + QZ_UpdateCursor(this); + + if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/ + QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); + CGAssociateMouseAndMouseCursorPosition (0); + } + } + break; + case NSScrollWheel: + if ( isInGameWin ) { + float dy, dx; + Uint8 button; + dy = [ event deltaY ]; + dx = [ event deltaX ]; + if ( dy > 0.0 ) /* Scroll up */ + button = SDL_BUTTON_WHEELUP; + else if ( dy < 0.0 ) /* Scroll down */ + button = SDL_BUTTON_WHEELDOWN; + else + break; /* Horizontal scroll */ + /* For now, wheel is sent as a quick down+up */ + SDL_PrivateMouseButton (SDL_PRESSED, button, 0, 0); + SDL_PrivateMouseButton (SDL_RELEASED, button, 0, 0); + } + break; + case NSKeyUp: + QZ_DoKey (this, SDL_RELEASED, event); + break; + case NSKeyDown: + QZ_DoKey (this, SDL_PRESSED, event); + break; + case NSFlagsChanged: + break; + case NSAppKitDefined: + [ NSApp sendEvent:event ]; + if ([ event subtype ] == NSApplicationActivatedEventType && (mode_flags & SDL_FULLSCREEN)) { + /* the default handling of this event seems to reset any cursor set by [NSCursor set] (used by SDL_SetCursor() in fullscreen mode) to the default system arrow cursor */ + SDL_Cursor *sdlc = SDL_GetCursor(); + if (sdlc != NULL && sdlc->wm_cursor != NULL) { + [ sdlc->wm_cursor->nscursor set ]; + } + } + break; + /* case NSApplicationDefined: break; */ + /* case NSPeriodic: break; */ + /* case NSCursorUpdate: break; */ + default: + [ NSApp sendEvent:event ]; + } + } + } while (event != nil); + + /* handle accumulated mouse moved events */ + if (dx != 0 || dy != 0) + SDL_PrivateMouseMotion (0, 1, dx, dy); + + [ pool release ]; +} + +void QZ_UpdateMouse (_THIS) +{ + NSPoint p; + QZ_GetMouseLocation (this, &p); + SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion (0, 0, p.x, p.y); +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m new file mode 100644 index 0000000..d38dceb --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzGL.m @@ -0,0 +1,292 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" + +/* + * GL_ARB_Multisample is supposed to be available in 10.1, according to Apple: + * + * http://developer.apple.com/graphicsimaging/opengl/extensions.html#GL_ARB_multisample + * + * ...but it isn't in the system headers, according to Sam: + * + * http://lists.libsdl.org/pipermail/sdl-libsdl.org/2003-December/039794.html + * + * These are normally enums and not #defines in the system headers. + * + * --ryan. + */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1020) +#define NSOpenGLPFASampleBuffers ((NSOpenGLPixelFormatAttribute) 55) +#define NSOpenGLPFASamples ((NSOpenGLPixelFormatAttribute) 56) +#endif + +#ifdef __powerpc__ /* we lost this in 10.6, which has no PPC support. */ +@implementation NSOpenGLContext (CGLContextAccess) +- (CGLContextObj) cglContext; +{ + return _contextAuxiliary; +} +@end +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return [nsctx cglContext]; +} +#else +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx) +{ + return (CGLContextObj) [nsctx CGLContextObj]; +} +#endif + + +/* OpenGL helper functions (used internally) */ + +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags) { + + NSOpenGLPixelFormatAttribute attr[32]; + NSOpenGLPixelFormat *fmt; + int i = 0; + int colorBits = bpp; + + /* if a GL library hasn't been loaded at this point, load the default. */ + if (!this->gl_config.driver_loaded) { + if (QZ_GL_LoadLibrary(this, NULL) == -1) + return 0; + } + + if ( flags & SDL_FULLSCREEN ) { + + attr[i++] = NSOpenGLPFAFullScreen; + } + /* In windowed mode, the OpenGL pixel depth must match device pixel depth */ + else if ( colorBits != device_bpp ) { + + colorBits = device_bpp; + } + + attr[i++] = NSOpenGLPFAColorSize; + attr[i++] = colorBits; + + attr[i++] = NSOpenGLPFADepthSize; + attr[i++] = this->gl_config.depth_size; + + if ( this->gl_config.double_buffer ) { + attr[i++] = NSOpenGLPFADoubleBuffer; + } + + if ( this->gl_config.stereo ) { + attr[i++] = NSOpenGLPFAStereo; + } + + if ( this->gl_config.stencil_size != 0 ) { + attr[i++] = NSOpenGLPFAStencilSize; + attr[i++] = this->gl_config.stencil_size; + } + + if ( (this->gl_config.accum_red_size + + this->gl_config.accum_green_size + + this->gl_config.accum_blue_size + + this->gl_config.accum_alpha_size) > 0 ) { + attr[i++] = NSOpenGLPFAAccumSize; + attr[i++] = this->gl_config.accum_red_size + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + this->gl_config.accum_alpha_size; + } + + if ( this->gl_config.multisamplebuffers != 0 ) { + attr[i++] = NSOpenGLPFASampleBuffers; + attr[i++] = this->gl_config.multisamplebuffers; + } + + if ( this->gl_config.multisamplesamples != 0 ) { + attr[i++] = NSOpenGLPFASamples; + attr[i++] = this->gl_config.multisamplesamples; + attr[i++] = NSOpenGLPFANoRecovery; + } + + if ( this->gl_config.accelerated > 0 ) { + attr[i++] = NSOpenGLPFAAccelerated; + } + + attr[i++] = NSOpenGLPFAScreenMask; + attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id); + attr[i] = 0; + + fmt = [ [ NSOpenGLPixelFormat alloc ] initWithAttributes:attr ]; + if (fmt == nil) { + SDL_SetError ("Failed creating OpenGL pixel format"); + return 0; + } + + gl_context = [ [ NSOpenGLContext alloc ] initWithFormat:fmt + shareContext:nil]; + + [ fmt release ]; + + if (gl_context == nil) { + SDL_SetError ("Failed creating OpenGL context"); + return 0; + } + + /* Synchronize QZ_GL_SwapBuffers() to vertical retrace. + * (Apple's documentation is not completely clear about what this setting + * exactly does, IMHO - for a detailed explanation see + * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html ) + */ + if ( this->gl_config.swap_control >= 0 ) { + GLint value; + value = this->gl_config.swap_control; + [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ]; + } + + /* + * Wisdom from Apple engineer in reference to UT2003's OpenGL performance: + * "You are blowing a couple of the internal OpenGL function caches. This + * appears to be happening in the VAO case. You can tell OpenGL to up + * the cache size by issuing the following calls right after you create + * the OpenGL context. The default cache size is 16." --ryan. + */ + + #ifndef GLI_ARRAY_FUNC_CACHE_MAX + #define GLI_ARRAY_FUNC_CACHE_MAX 284 + #endif + + #ifndef GLI_SUBMIT_FUNC_CACHE_MAX + #define GLI_SUBMIT_FUNC_CACHE_MAX 280 + #endif + + { + GLint cache_max = 64; + CGLContextObj ctx = QZ_GetCGLContextObj(gl_context); + CGLSetParameter (ctx, GLI_SUBMIT_FUNC_CACHE_MAX, &cache_max); + CGLSetParameter (ctx, GLI_ARRAY_FUNC_CACHE_MAX, &cache_max); + } + + /* End Wisdom from Apple Engineer section. --ryan. */ + + return 1; +} + +void QZ_TearDownOpenGL (_THIS) { + + [ NSOpenGLContext clearCurrentContext ]; + [ gl_context clearDrawable ]; + [ gl_context release ]; +} + + +/* SDL OpenGL functions */ +static const char *DEFAULT_OPENGL_LIB_NAME = + "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; + +int QZ_GL_LoadLibrary (_THIS, const char *location) { + if ( gl_context != NULL ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if (opengl_library != NULL) + SDL_UnloadObject(opengl_library); + + if (location == NULL) + location = DEFAULT_OPENGL_LIB_NAME; + + opengl_library = SDL_LoadObject(location); + if (opengl_library != NULL) { + this->gl_config.driver_loaded = 1; + return 0; + } + + this->gl_config.driver_loaded = 0; + return -1; +} + +void* QZ_GL_GetProcAddress (_THIS, const char *proc) { + return SDL_LoadFunction(opengl_library, proc); +} + +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value) { + + GLenum attr = 0; + + QZ_GL_MakeCurrent (this); + + switch (attrib) { + case SDL_GL_RED_SIZE: attr = GL_RED_BITS; break; + case SDL_GL_BLUE_SIZE: attr = GL_BLUE_BITS; break; + case SDL_GL_GREEN_SIZE: attr = GL_GREEN_BITS; break; + case SDL_GL_ALPHA_SIZE: attr = GL_ALPHA_BITS; break; + case SDL_GL_DOUBLEBUFFER: attr = GL_DOUBLEBUFFER; break; + case SDL_GL_DEPTH_SIZE: attr = GL_DEPTH_BITS; break; + case SDL_GL_STENCIL_SIZE: attr = GL_STENCIL_BITS; break; + case SDL_GL_ACCUM_RED_SIZE: attr = GL_ACCUM_RED_BITS; break; + case SDL_GL_ACCUM_GREEN_SIZE: attr = GL_ACCUM_GREEN_BITS; break; + case SDL_GL_ACCUM_BLUE_SIZE: attr = GL_ACCUM_BLUE_BITS; break; + case SDL_GL_ACCUM_ALPHA_SIZE: attr = GL_ACCUM_ALPHA_BITS; break; + case SDL_GL_STEREO: attr = GL_STEREO; break; + case SDL_GL_MULTISAMPLEBUFFERS: attr = GL_SAMPLE_BUFFERS_ARB; break; + case SDL_GL_MULTISAMPLESAMPLES: attr = GL_SAMPLES_ARB; break; + case SDL_GL_BUFFER_SIZE: + { + GLint bits = 0; + GLint component; + + /* there doesn't seem to be a single flag in OpenGL for this! */ + glGetIntegerv (GL_RED_BITS, &component); bits += component; + glGetIntegerv (GL_GREEN_BITS,&component); bits += component; + glGetIntegerv (GL_BLUE_BITS, &component); bits += component; + glGetIntegerv (GL_ALPHA_BITS, &component); bits += component; + + *value = bits; + return 0; + } + case SDL_GL_ACCELERATED_VISUAL: + { + GLint val; + /* FIXME: How do we get this information here? + [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0]; + */ + val = (this->gl_config.accelerated != 0);; + *value = val; + return 0; + } + case SDL_GL_SWAP_CONTROL: + { + GLint val; + [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ]; + *value = val; + return 0; + } + } + + glGetIntegerv (attr, (GLint *)value); + return 0; +} + +int QZ_GL_MakeCurrent (_THIS) { + [ gl_context makeCurrentContext ]; + return 0; +} + +void QZ_GL_SwapBuffers (_THIS) { + [ gl_context flushBuffer ]; +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h new file mode 100644 index 0000000..82b7859 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzKeys.h @@ -0,0 +1,146 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* These are the Macintosh key scancode constants -- from Inside Macintosh */ + +#define QZ_ESCAPE 0x35 +#define QZ_F1 0x7A +#define QZ_F2 0x78 +#define QZ_F3 0x63 +#define QZ_F4 0x76 +#define QZ_F5 0x60 +#define QZ_F6 0x61 +#define QZ_F7 0x62 +#define QZ_F8 0x64 +#define QZ_F9 0x65 +#define QZ_F10 0x6D +#define QZ_F11 0x67 +#define QZ_F12 0x6F +#define QZ_F13 0x69 +#define QZ_F14 0x6B +#define QZ_F15 0x71 +/* +#define QZ_PRINT 0x69 +#define QZ_SCROLLOCK 0x6B +#define QZ_PAUSE 0x71 +*/ +#define QZ_POWER 0x7F +#define QZ_BACKQUOTE 0x32 +#define QZ_1 0x12 +#define QZ_2 0x13 +#define QZ_3 0x14 +#define QZ_4 0x15 +#define QZ_5 0x17 +#define QZ_6 0x16 +#define QZ_7 0x1A +#define QZ_8 0x1C +#define QZ_9 0x19 +#define QZ_0 0x1D +#define QZ_MINUS 0x1B +#define QZ_EQUALS 0x18 +#define QZ_BACKSPACE 0x33 +#define QZ_INSERT 0x72 +#define QZ_HOME 0x73 +#define QZ_PAGEUP 0x74 +#define QZ_NUMLOCK 0x47 +#define QZ_KP_EQUALS 0x51 +#define QZ_KP_DIVIDE 0x4B +#define QZ_KP_MULTIPLY 0x43 +#define QZ_TAB 0x30 +#define QZ_q 0x0C +#define QZ_w 0x0D +#define QZ_e 0x0E +#define QZ_r 0x0F +#define QZ_t 0x11 +#define QZ_y 0x10 +#define QZ_u 0x20 +#define QZ_i 0x22 +#define QZ_o 0x1F +#define QZ_p 0x23 +#define QZ_LEFTBRACKET 0x21 +#define QZ_RIGHTBRACKET 0x1E +#define QZ_BACKSLASH 0x2A +#define QZ_DELETE 0x75 +#define QZ_END 0x77 +#define QZ_PAGEDOWN 0x79 +#define QZ_KP7 0x59 +#define QZ_KP8 0x5B +#define QZ_KP9 0x5C +#define QZ_KP_MINUS 0x4E +#define QZ_CAPSLOCK 0x39 +#define QZ_a 0x00 +#define QZ_s 0x01 +#define QZ_d 0x02 +#define QZ_f 0x03 +#define QZ_g 0x05 +#define QZ_h 0x04 +#define QZ_j 0x26 +#define QZ_k 0x28 +#define QZ_l 0x25 +#define QZ_SEMICOLON 0x29 +#define QZ_QUOTE 0x27 +#define QZ_RETURN 0x24 +#define QZ_KP4 0x56 +#define QZ_KP5 0x57 +#define QZ_KP6 0x58 +#define QZ_KP_PLUS 0x45 +#define QZ_LSHIFT 0x38 +#define QZ_z 0x06 +#define QZ_x 0x07 +#define QZ_c 0x08 +#define QZ_v 0x09 +#define QZ_b 0x0B +#define QZ_n 0x2D +#define QZ_m 0x2E +#define QZ_COMMA 0x2B +#define QZ_PERIOD 0x2F +#define QZ_SLASH 0x2C +#if 1 /* Panther now defines right side keys */ +#define QZ_RSHIFT 0x3C +#endif +#define QZ_UP 0x7E +#define QZ_KP1 0x53 +#define QZ_KP2 0x54 +#define QZ_KP3 0x55 +#define QZ_KP_ENTER 0x4C +#define QZ_LCTRL 0x3B +#define QZ_LALT 0x3A +#define QZ_LMETA 0x37 +#define QZ_SPACE 0x31 +#if 1 /* Panther now defines right side keys */ +#define QZ_RMETA 0x36 +#define QZ_RALT 0x3D +#define QZ_RCTRL 0x3E +#endif +#define QZ_LEFT 0x7B +#define QZ_DOWN 0x7D +#define QZ_RIGHT 0x7C +#define QZ_KP0 0x52 +#define QZ_KP_PERIOD 0x41 + +/* Wierd, these keys are on my iBook under Mac OS X */ +#define QZ_IBOOK_ENTER 0x34 +#define QZ_IBOOK_LEFT 0x3B +#define QZ_IBOOK_RIGHT 0x3C +#define QZ_IBOOK_DOWN 0x3D +#define QZ_IBOOK_UP 0x3E diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h new file mode 100644 index 0000000..7506e0c --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.h @@ -0,0 +1,229 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + @file SDL_QuartzVideo.h + @author Darrell Walisser, Max Horn, et al. + + @abstract SDL video driver for Mac OS X. + + @discussion + + TODO + - Hardware Cursor support with NSCursor instead of Carbon + - Keyboard repeat/mouse speed adjust (if needed) + - Multiple monitor support (currently only main display) + - Accelerated blitting support + - Fix white OpenGL window on minimize (fixed) (update: broken again on 10.2) + - Find out what events should be sent/ignored if window is minimized + - Find a way to deal with external resolution/depth switch while app is running + - Check accuracy of QZ_SetGamma() + Problems: + - OGL not working in full screen with software renderer + - SetColors sets palette correctly but clears framebuffer + - Crash in CG after several mode switches (I think this has been fixed) + - Retained windows don't draw their title bar quite right (OS Bug) (not using retained windows) + - Cursor in 8 bit modes is screwy (might just be Radeon PCI bug) (update: not just Radeon) + - Warping cursor delays mouse events for a fraction of a second, + there is a hack around this that helps a bit +*/ + +/* Needs to be first, so QuickTime.h doesn't include glext.h (10.4) */ +#include "SDL_opengl.h" + +#include <Cocoa/Cocoa.h> +#include <Carbon/Carbon.h> +#include <OpenGL/OpenGL.h> /* For CGL functions and types */ +#include <IOKit/IOKitLib.h> /* For powersave handling */ +#include <pthread.h> + +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_loadso.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + + +#ifdef __powerpc__ +/* + This is a workaround to directly access NSOpenGLContext's CGL context + We need this to check for errors NSOpenGLContext doesn't support + Please note this is only used on PowerPC (Intel Macs are guaranteed to + have a better API for this, since it showed up in Mac OS X 10.3). +*/ +@interface NSOpenGLContext (CGLContextAccess) +- (CGLContextObj) cglContext; +@end +#endif + +/* use this to get the CGLContext; it handles Cocoa interface changes. */ +CGLContextObj QZ_GetCGLContextObj(NSOpenGLContext *nsctx); + + +/* Main driver structure to store required state information */ +typedef struct SDL_PrivateVideoData { + BOOL use_new_mode_apis; /* 1 == >= 10.6 APIs available */ + BOOL allow_screensaver; /* 0 == disable screensaver */ + CGDirectDisplayID display; /* 0 == main display (only support single display) */ + const void *mode; /* current mode of the display */ + const void *save_mode; /* original mode of the display */ + CGDirectPaletteRef palette; /* palette of an 8-bit display */ + NSOpenGLContext *gl_context; /* OpenGL rendering context */ + NSGraphicsContext *nsgfx_context; /* Cocoa graphics context */ + Uint32 width, height, bpp; /* frequently used data about the display */ + Uint32 flags; /* flags for current mode, for teardown purposes */ + Uint32 video_set; /* boolean; indicates if video was set correctly */ + Uint32 warp_flag; /* boolean; notify to event loop that a warp just occured */ + Uint32 warp_ticks; /* timestamp when the warp occured */ + NSWindow *window; /* Cocoa window to implement the SDL window */ + NSView *view; /* the window's view; draw 2D and OpenGL into this view */ + CGContextRef cg_context; /* CoreGraphics rendering context */ + SDL_Surface *resize_icon; /* icon for the resize badge, we have to draw it by hand */ + SDL_GrabMode current_grab_mode; /* default value is SDL_GRAB_OFF */ + SDL_Rect **client_mode_list; /* resolution list to pass back to client */ + SDLKey keymap[256]; /* Mac OS X to SDL key mapping */ + Uint32 current_mods; /* current keyboard modifiers, to track modifier state */ + NSText *field_edit; /* a field editor for keyboard composition processing */ + Uint32 last_virtual_button;/* last virtual mouse button pressed */ + io_connect_t power_connection; /* used with IOKit to detect wake from sleep */ + Uint8 expect_mouse_up; /* used to determine when to send mouse up events */ + Uint8 grab_state; /* used to manage grab behavior */ + NSPoint cursor_loc; /* saved cursor coords, for activate/deactivate when grabbed */ + BOOL cursor_should_be_visible; /* tells if cursor is supposed to be visible (SDL_ShowCursor) */ + BOOL cursor_visible; /* tells if cursor is *actually* visible or not */ + Uint8* sw_buffers[2]; /* pointers to the two software buffers for double-buffer emulation */ + SDL_Thread *thread; /* thread for async updates to the screen */ + SDL_sem *sem1, *sem2; /* synchronization for async screen updates */ + Uint8 *current_buffer; /* the buffer being copied to the screen */ + BOOL quit_thread; /* used to quit the async blitting thread */ + SInt32 system_version; /* used to dis-/enable workarounds depending on the system version */ + + void *opengl_library; /* dynamically loaded OpenGL library. */ +} SDL_PrivateVideoData; + +#define _THIS SDL_VideoDevice *this +#define display_id (this->hidden->display) +#define mode (this->hidden->mode) +#define save_mode (this->hidden->save_mode) +#define use_new_mode_apis (this->hidden->use_new_mode_apis) +#define allow_screensaver (this->hidden->allow_screensaver) +#define palette (this->hidden->palette) +#define gl_context (this->hidden->gl_context) +#define nsgfx_context (this->hidden->nsgfx_context) +#define device_width (this->hidden->width) +#define device_height (this->hidden->height) +#define device_bpp (this->hidden->bpp) +#define mode_flags (this->hidden->flags) +#define qz_window (this->hidden->window) +#define window_view (this->hidden->view) +#define cg_context (this->hidden->cg_context) +#define video_set (this->hidden->video_set) +#define warp_ticks (this->hidden->warp_ticks) +#define warp_flag (this->hidden->warp_flag) +#define resize_icon (this->hidden->resize_icon) +#define current_grab_mode (this->hidden->current_grab_mode) +#define client_mode_list (this->hidden->client_mode_list) +#define keymap (this->hidden->keymap) +#define current_mods (this->hidden->current_mods) +#define field_edit (this->hidden->field_edit) +#define last_virtual_button (this->hidden->last_virtual_button) +#define power_connection (this->hidden->power_connection) +#define expect_mouse_up (this->hidden->expect_mouse_up) +#define grab_state (this->hidden->grab_state) +#define cursor_loc (this->hidden->cursor_loc) +#define cursor_should_be_visible (this->hidden->cursor_should_be_visible) +#define cursor_visible (this->hidden->cursor_visible) +#define sw_buffers (this->hidden->sw_buffers) +#define sw_contexts (this->hidden->sw_contexts) +#define thread (this->hidden->thread) +#define sem1 (this->hidden->sem1) +#define sem2 (this->hidden->sem2) +#define current_buffer (this->hidden->current_buffer) +#define quit_thread (this->hidden->quit_thread) +#define system_version (this->hidden->system_version) +#define opengl_library (this->hidden->opengl_library) + +/* grab states - the input is in one of these states */ +enum { + QZ_UNGRABBED = 0, + QZ_VISIBLE_GRAB, + QZ_INVISIBLE_GRAB +}; + +/* grab actions - these can change the grabbed state */ +enum { + QZ_ENABLE_GRAB = 0, + QZ_DISABLE_GRAB, + QZ_HIDECURSOR, + QZ_SHOWCURSOR +}; + +/* Gamma Functions */ +int QZ_SetGamma (_THIS, float red, float green, float blue); +int QZ_GetGamma (_THIS, float *red, float *green, float *blue); +int QZ_SetGammaRamp (_THIS, Uint16 *ramp); +int QZ_GetGammaRamp (_THIS, Uint16 *ramp); + +/* OpenGL functions */ +int QZ_SetupOpenGL (_THIS, int bpp, Uint32 flags); +void QZ_TearDownOpenGL (_THIS); +void* QZ_GL_GetProcAddress (_THIS, const char *proc); +int QZ_GL_GetAttribute (_THIS, SDL_GLattr attrib, int* value); +int QZ_GL_MakeCurrent (_THIS); +void QZ_GL_SwapBuffers (_THIS); +int QZ_GL_LoadLibrary (_THIS, const char *location); + +/* Cursor and Mouse functions */ +void QZ_FreeWMCursor (_THIS, WMcursor *cursor); +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y); +int QZ_ShowWMCursor (_THIS, WMcursor *cursor); +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y); +void QZ_MoveWMCursor (_THIS, int x, int y); +void QZ_CheckMouseMode (_THIS); +void QZ_UpdateMouse (_THIS); + +/* Event functions */ +void QZ_InitOSKeymap (_THIS); +void QZ_PumpEvents (_THIS); + +/* Window Manager functions */ +void QZ_SetCaption (_THIS, const char *title, const char *icon); +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask); +int QZ_IconifyWindow (_THIS); +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode); +/*int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info);*/ + +/* Private functions (used internally) */ +void QZ_PrivateWarpCursor (_THIS, int x, int y); +void QZ_ChangeGrabState (_THIS, int action); +void QZ_RegisterForSleepNotifications (_THIS); +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); +BOOL QZ_IsMouseInWindow (_THIS); +void QZ_DoActivate (_THIS); +void QZ_DoDeactivate (_THIS); diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m new file mode 100644 index 0000000..fa04e9d --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzVideo.m @@ -0,0 +1,1689 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" + +/* These APIs aren't just deprecated; they're gone from the headers in the + 10.7 SDK. If we're using a >= 10.7 SDK, but targeting < 10.7, then we + force these function declarations. */ +#if ((MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)) +CG_EXTERN void *CGDisplayBaseAddress(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +CG_EXTERN size_t CGDisplayBytesPerRow(CGDirectDisplayID display) + CG_AVAILABLE_BUT_DEPRECATED(__MAC_10_0, __MAC_10_6, + __IPHONE_NA, __IPHONE_NA); +#endif + + +static inline BOOL IS_LION_OR_LATER(_THIS) +{ + return (system_version >= 0x1070); +} + +static inline BOOL IS_SNOW_LEOPARD_OR_LATER(_THIS) +{ + return (system_version >= 0x1060); +} + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) && !defined(__LP64__) /* Fixed in Snow Leopard */ +/* + Add methods to get at private members of NSScreen. + Since there is a bug in Apple's screen switching code + that does not update this variable when switching + to fullscreen, we'll set it manually (but only for the + main screen). +*/ +@interface NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +@end + +@implementation NSScreen (NSScreenAccess) +- (void) setFrame:(NSRect)frame; +{ + _frame = frame; +} +@end +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) +{ + if (!IS_SNOW_LEOPARD_OR_LATER(this)) { + [nsscreen setFrame:frame]; + } +} +#else +static inline void QZ_SetFrame(_THIS, NSScreen *nsscreen, NSRect frame) +{ +} +#endif + +@interface SDLTranslatorResponder : NSTextView +{ +} +- (void) doCommandBySelector:(SEL)myselector; +@end + +@implementation SDLTranslatorResponder +- (void) doCommandBySelector:(SEL) myselector {} +@end + +/* absent in 10.3.9. */ +CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef); + +/* Bootstrap functions */ +static int QZ_Available (); +static SDL_VideoDevice* QZ_CreateDevice (int device_index); +static void QZ_DeleteDevice (SDL_VideoDevice *device); + +/* Initialization, Query, Setup, and Redrawing functions */ +static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format); + +static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, + Uint32 flags); +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl); + +static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags); +static int QZ_ToggleFullScreen (_THIS, int on); +static int QZ_SetColors (_THIS, int first_color, + int num_colors, SDL_Color *colors); + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) +static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface); +static int QZ_ThreadFlip (_THIS); +static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface); +static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects); +static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects); +#endif + +static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects); +static void QZ_VideoQuit (_THIS); + +static int QZ_LockHWSurface(_THIS, SDL_Surface *surface); +static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface); +static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface); +static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface); + +/* Bootstrap binding, enables entry point into the driver */ +VideoBootStrap QZ_bootstrap = { + "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice +}; + +/* Disable compiler warnings we can't avoid. */ +#if (defined(__GNUC__) && (__GNUC__ >= 4)) +# if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1070) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif + +static void QZ_ReleaseDisplayMode(_THIS, const void *moderef) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRelease((CGDisplayModeRef) moderef); + } +#endif +} + +static void QZ_ReleaseDisplayModeList(_THIS, CFArrayRef mode_list) +{ + /* we only own these references in the 10.6+ API. */ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CFRelease(mode_list); + } +#endif +} + + +/* Bootstrap functions */ +static int QZ_Available () +{ + return 1; +} + +static SDL_VideoDevice* QZ_CreateDevice (int device_index) +{ +#pragma unused (device_index) + + SDL_VideoDevice *device; + SDL_PrivateVideoData *hidden; + + device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) ); + hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) ); + + if (device == NULL || hidden == NULL) + SDL_OutOfMemory (); + + SDL_memset (device, 0, sizeof (*device) ); + SDL_memset (hidden, 0, sizeof (*hidden) ); + + device->hidden = hidden; + + device->VideoInit = QZ_VideoInit; + device->ListModes = QZ_ListModes; + device->SetVideoMode = QZ_SetVideoMode; + device->ToggleFullScreen = QZ_ToggleFullScreen; + device->UpdateMouse = QZ_UpdateMouse; + device->SetColors = QZ_SetColors; + /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */ + device->VideoQuit = QZ_VideoQuit; + + device->LockHWSurface = QZ_LockHWSurface; + device->UnlockHWSurface = QZ_UnlockHWSurface; + device->AllocHWSurface = QZ_AllocHWSurface; + device->FreeHWSurface = QZ_FreeHWSurface; + + device->SetGamma = QZ_SetGamma; + device->GetGamma = QZ_GetGamma; + device->SetGammaRamp = QZ_SetGammaRamp; + device->GetGammaRamp = QZ_GetGammaRamp; + + device->GL_GetProcAddress = QZ_GL_GetProcAddress; + device->GL_GetAttribute = QZ_GL_GetAttribute; + device->GL_MakeCurrent = QZ_GL_MakeCurrent; + device->GL_SwapBuffers = QZ_GL_SwapBuffers; + device->GL_LoadLibrary = QZ_GL_LoadLibrary; + + device->FreeWMCursor = QZ_FreeWMCursor; + device->CreateWMCursor = QZ_CreateWMCursor; + device->ShowWMCursor = QZ_ShowWMCursor; + device->WarpWMCursor = QZ_WarpWMCursor; + device->MoveWMCursor = QZ_MoveWMCursor; + device->CheckMouseMode = QZ_CheckMouseMode; + device->InitOSKeymap = QZ_InitOSKeymap; + device->PumpEvents = QZ_PumpEvents; + + device->SetCaption = QZ_SetCaption; + device->SetIcon = QZ_SetIcon; + device->IconifyWindow = QZ_IconifyWindow; + /*device->GetWMInfo = QZ_GetWMInfo;*/ + device->GrabInput = QZ_GrabInput; + + /* + * This is a big hassle, needing QuickDraw and QuickTime on older + * systems, and god knows what on 10.6, so we immediately fail here, + * which causes SDL to make an RGB surface and manage the YUV overlay + * in software. Sorry. Use SDL 1.3 if you want YUV rendering in a pixel + * shader. :) + */ + /*device->CreateYUVOverlay = QZ_CreateYUVOverlay;*/ + + device->free = QZ_DeleteDevice; + + return device; +} + +static void QZ_DeleteDevice (SDL_VideoDevice *device) +{ + _THIS = device; + QZ_ReleaseDisplayMode(this, save_mode); + QZ_ReleaseDisplayMode(this, mode); + SDL_free (device->hidden); + SDL_free (device); +} + +static void QZ_GetModeInfo(_THIS, const void *_mode, Uint32 *w, Uint32 *h, Uint32 *bpp) +{ + *w = *h = *bpp = 0; + if (_mode == NULL) { + return; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + CGDisplayModeRef vidmode = (CGDisplayModeRef) _mode; + CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode); + + *w = (Uint32) CGDisplayModeGetWidth(vidmode); + *h = (Uint32) CGDisplayModeGetHeight(vidmode); + + /* we only care about the 32-bit modes... */ + if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + *bpp = 32; + } + + CFRelease(fmt); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + CFDictionaryRef vidmode = (CFDictionaryRef) _mode; + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayBitsPerPixel), + kCFNumberSInt32Type, bpp); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayWidth), + kCFNumberSInt32Type, w); + + CFNumberGetValue ( + CFDictionaryGetValue (vidmode, kCGDisplayHeight), + kCFNumberSInt32Type, h); + } +#endif + + /* we only care about the 32-bit modes... */ + if (*bpp != 32) { + *bpp = 0; + } +} + +static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) +{ + NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0); + const char *env = NULL; + + if ( Gestalt(gestaltSystemVersion, &system_version) != noErr ) + system_version = 0; + + use_new_mode_apis = NO; + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + use_new_mode_apis = IS_SNOW_LEOPARD_OR_LATER(this); +#endif + + /* Initialize the video settings; this data persists between mode switches */ + display_id = kCGDirectMainDisplay; + +#if 0 /* The mouse event code needs to take this into account... */ + env = getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); + if ( env ) { + int monitor = SDL_atoi(env); + CGDirectDisplayID activeDspys [3]; + CGDisplayCount dspyCnt; + CGGetActiveDisplayList (3, activeDspys, &dspyCnt); + if ( monitor >= 0 && monitor < dspyCnt ) { + display_id = activeDspys[monitor]; + } + } +#endif + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + save_mode = CGDisplayCopyDisplayMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + save_mode = CGDisplayCurrentMode(display_id); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + palette = CGPaletteCreateDefaultColorPalette(); + } +#endif + + if (save_mode == NULL) { + SDL_SetError("Couldn't figure out current display mode."); + return -1; + } + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* Gather some information that is useful to know about the display */ + QZ_GetModeInfo(this, save_mode, &device_width, &device_height, &device_bpp); + if (device_bpp == 0) { + QZ_ReleaseDisplayMode(this, save_mode); + save_mode = NULL; + SDL_SetError("Unsupported display mode"); + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = device_width; + this->info.current_h = device_height; + + /* Determine the default screen depth */ + video_format->BitsPerPixel = device_bpp; + + /* Set misc globals */ + current_grab_mode = SDL_GRAB_OFF; + cursor_should_be_visible = YES; + cursor_visible = YES; + current_mods = 0; + field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r]; + + /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ + QZ_RegisterForSleepNotifications (this); + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + return 0; +} + +static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + CFArrayRef mode_list = NULL; /* list of available fullscreen modes */ + CFIndex num_modes; + CFIndex i; + + int list_size = 0; + + /* Any windowed mode is acceptable */ + if ( (flags & SDL_FULLSCREEN) == 0 ) + return (SDL_Rect**)-1; + + /* Free memory from previous call, if any */ + if ( client_mode_list != NULL ) { + int i; + + for (i = 0; client_mode_list[i] != NULL; i++) + SDL_free (client_mode_list[i]); + + SDL_free (client_mode_list); + client_mode_list = NULL; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + mode_list = CGDisplayAvailableModes(display_id); + } +#endif + + num_modes = CFArrayGetCount (mode_list); + + /* Build list of modes with the requested bpp */ + for (i = 0; i < num_modes; i++) { + Uint32 width, height, bpp; + const void *onemode = CFArrayGetValueAtIndex(mode_list, i); + + QZ_GetModeInfo(this, onemode, &width, &height, &bpp); + + if (bpp && (bpp == format->BitsPerPixel)) { + int hasMode = SDL_FALSE; + int i; + + /* Check if mode is already in the list */ + for (i = 0; i < list_size; i++) { + if (client_mode_list[i]->w == width && + client_mode_list[i]->h == height) { + hasMode = SDL_TRUE; + break; + } + } + + /* Grow the list and add mode to the list */ + if ( ! hasMode ) { + SDL_Rect *rect; + + list_size++; + + if (client_mode_list == NULL) + client_mode_list = (SDL_Rect**) + SDL_malloc (sizeof(*client_mode_list) * (list_size+1) ); + else { + /* !!! FIXME: this leaks memory if SDL_realloc() fails! */ + client_mode_list = (SDL_Rect**) + SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1)); + } + + rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list)); + + if (client_mode_list == NULL || rect == NULL) { + QZ_ReleaseDisplayModeList(this, mode_list); + SDL_OutOfMemory (); + return NULL; + } + + rect->x = rect->y = 0; + rect->w = width; + rect->h = height; + + client_mode_list[list_size-1] = rect; + client_mode_list[list_size] = NULL; + } + } + } + + QZ_ReleaseDisplayModeList(this, mode_list); + + /* Sort list largest to smallest (by area) */ + { + int i, j; + for (i = 0; i < list_size; i++) { + for (j = 0; j < list_size-1; j++) { + + int area1, area2; + area1 = client_mode_list[j]->w * client_mode_list[j]->h; + area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h; + + if (area1 < area2) { + SDL_Rect *tmp = client_mode_list[j]; + client_mode_list[j] = client_mode_list[j+1]; + client_mode_list[j+1] = tmp; + } + } + } + } + + return client_mode_list; +} + +static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y) +{ + const char *window = getenv("SDL_VIDEO_WINDOW_POS"); + if ( window ) { + if ( sscanf(window, "%d,%d", x, y) == 2 ) { + return SDL_TRUE; + } + } + return SDL_FALSE; +} + +static CGError QZ_SetDisplayMode(_THIS, const void *vidmode) +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + return CGDisplaySetDisplayMode(display_id, (CGDisplayModeRef) vidmode, NULL); + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + return CGDisplaySwitchToMode(display_id, (CFDictionaryRef) vidmode); + } +#endif + + return kCGErrorFailure; +} + +static inline CGError QZ_RestoreDisplayMode(_THIS) +{ + return QZ_SetDisplayMode(this, save_mode); +} + +static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop, BOOL save_gl) +{ + /* Reset values that may change between switches */ + this->info.blit_fill = 0; + this->FillHWRect = NULL; + this->UpdateRects = NULL; + this->LockHWSurface = NULL; + this->UnlockHWSurface = NULL; + + if (cg_context) { + CGContextFlush (cg_context); + CGContextRelease (cg_context); + cg_context = nil; + } + + /* Release fullscreen resources */ + if ( mode_flags & SDL_FULLSCREEN ) { + + NSRect screen_rect; + + /* Release double buffer stuff */ +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !IS_LION_OR_LATER(this) && (mode_flags & SDL_DOUBLEBUF) ) { + quit_thread = YES; + SDL_SemPost (sem1); + SDL_WaitThread (thread, NULL); + SDL_DestroySemaphore (sem1); + SDL_DestroySemaphore (sem2); + SDL_free (sw_buffers[0]); + } +#endif + + /* If we still have a valid window, close it. */ + if ( qz_window ) { + NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ + [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ + qz_window = nil; + window_view = nil; + } + /* + Release the OpenGL context + Do this first to avoid trash on the display before fade + */ + if ( mode_flags & SDL_OPENGL ) { + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + + #ifdef __powerpc__ /* we only use this for pre-10.3 compatibility. */ + CGLSetFullScreen (NULL); + #endif + } + if (to_desktop) { + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !IS_LION_OR_LATER(this) ) { + ShowMenuBar (); + } + #endif + + /* Restore original screen resolution/bpp */ + QZ_RestoreDisplayMode (this); + CGReleaseAllDisplays (); + /* + Reset the main screen's rectangle + See comment in QZ_SetVideoFullscreen for why we do this + */ + screen_rect = NSMakeRect(0,0,device_width,device_height); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); + } + } + /* Release window mode resources */ + else { + id delegate = [ qz_window delegate ]; + [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ + if (delegate != nil) [ delegate release ]; + qz_window = nil; + window_view = nil; + + /* Release the OpenGL context */ + if ( mode_flags & SDL_OPENGL ) { + if (!save_gl) { + QZ_TearDownOpenGL (this); + } + } + } + + /* Signal successful teardown */ + video_set = SDL_FALSE; +} + +static const void *QZ_BestMode(_THIS, const int bpp, const int w, const int h) +{ + const void *best = NULL; + + if (bpp == 0) { + return NULL; + } + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + if (use_new_mode_apis) { + /* apparently, we have to roll our own now. :/ */ + CFArrayRef mode_list = CGDisplayCopyAllDisplayModes(display_id, NULL); + if (mode_list != NULL) { + const CFIndex num_modes = CFArrayGetCount(mode_list); + CFIndex i; + for (i = 0; i < num_modes; i++) { + const void *vidmode = CFArrayGetValueAtIndex(mode_list, i); + Uint32 thisw, thish, thisbpp; + QZ_GetModeInfo(this, vidmode, &thisw, &thish, &thisbpp); + + /* We only care about exact matches, apparently. */ + if ((thisbpp == bpp) && (thisw == w) && (thish == h)) { + best = vidmode; + break; /* got it! */ + } + } + CGDisplayModeRetain((CGDisplayModeRef) best); /* NULL is ok */ + CFRelease(mode_list); + } + } +#endif + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1060) + if (!use_new_mode_apis) { + boolean_t exact = 0; + best = CGDisplayBestModeForParameters(display_id, bpp, w, h, &exact); + if (!exact) { + best = NULL; + } + } +#endif + + return best; +} + +static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, + int height, int bpp, Uint32 flags, + const BOOL save_gl) +{ + const BOOL isLion = IS_LION_OR_LATER(this); + NSRect screen_rect; + CGError error; + NSRect contentRect; + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + current->flags = SDL_FULLSCREEN; + current->w = width; + current->h = height; + + contentRect = NSMakeRect (0, 0, width, height); + + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + + /* Destroy any previous mode */ + if (video_set == SDL_TRUE) + QZ_UnsetVideoMode (this, FALSE, save_gl); + + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + goto ERR_NO_MATCH; + } + + QZ_ReleaseDisplayMode(this, mode); /* NULL is okay. */ + + /* See if requested mode exists */ + mode = QZ_BestMode(this, bpp, width, height); + + /* Require an exact match to the requested mode */ + if ( mode == NULL ) { + SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp); + goto ERR_NO_MATCH; + } + + /* Put up the blanking window (a window above all other windows) */ + if (getenv ("SDL_SINGLEDISPLAY")) + error = CGDisplayCapture (display_id); + else + error = CGCaptureAllDisplays (); + + if ( CGDisplayNoErr != error ) { + SDL_SetError ("Failed capturing display"); + goto ERR_NO_CAPTURE; + } + + /* Do the physical switch */ + if ( CGDisplayNoErr != QZ_SetDisplayMode(this, mode) ) { + SDL_SetError ("Failed switching display resolution"); + goto ERR_NO_SWITCH; + } + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); + current->pitch = CGDisplayBytesPerRow (display_id); + + current->flags |= SDL_HWSURFACE; + current->flags |= SDL_PREALLOC; + /* current->hwdata = (void *) CGDisplayGetDrawingContext (display_id); */ + + this->UpdateRects = QZ_DirectUpdate; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + + /* Setup double-buffer emulation */ + if ( flags & SDL_DOUBLEBUF ) { + + /* + Setup a software backing store for reasonable results when + double buffering is requested (since a single-buffered hardware + surface looks hideous). + + The actual screen blit occurs in a separate thread to allow + other blitting while waiting on the VBL (and hence results in higher framerates). + */ + this->LockHWSurface = NULL; + this->UnlockHWSurface = NULL; + this->UpdateRects = NULL; + + current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); + this->UpdateRects = QZ_DoubleBufferUpdate; + this->LockHWSurface = QZ_LockDoubleBuffer; + this->UnlockHWSurface = QZ_UnlockDoubleBuffer; + this->FlipHWSurface = QZ_FlipDoubleBuffer; + + current->pixels = SDL_malloc (current->pitch * current->h * 2); + if (current->pixels == NULL) { + SDL_OutOfMemory (); + goto ERR_DOUBLEBUF; + } + + sw_buffers[0] = current->pixels; + sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; + + quit_thread = NO; + sem1 = SDL_CreateSemaphore (0); + sem2 = SDL_CreateSemaphore (1); + thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); + } + + if ( CGDisplayCanSetPalette (display_id) ) + current->flags |= SDL_HWPALETTE; + } +#endif + + /* Check if we should recreate the window */ + if (qz_window == nil) { + /* Manually create a window, avoids having a nib file resource */ + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:contentRect + styleMask:(isLion ? NSBorderlessWindowMask : 0) + backing:NSBackingStoreBuffered + defer:NO ]; + + if (qz_window != nil) { + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setViewsNeedDisplay:NO ]; + if (isLion) { + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; + } + } + } + /* We already have a window, just change its size */ + else { + [ qz_window setContentSize:contentRect.size ]; + current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; + [ window_view setFrameSize:contentRect.size ]; + } + + /* Setup OpenGL for a fullscreen context */ + if (flags & SDL_OPENGL) { + + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { + goto ERR_NO_GL; + } + } + + /* Initialize the NSView and add it to our window. The presence of a valid window and + view allow the cursor to be changed whilst in fullscreen.*/ + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + + if ( isLion ) { + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + } + + [ [ qz_window contentView ] addSubview:window_view ]; + + /* Apparently Lion checks some version flag set by the linker + and changes API behavior. Annoying. */ + if ( isLion ) { + [ qz_window setLevel:CGShieldingWindowLevel() ]; + [ gl_context setView: window_view ]; + //[ gl_context setFullScreen ]; + [ gl_context update ]; + } + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if ( !isLion ) { + CGLError err; + CGLContextObj ctx; + + [ qz_window setLevel:NSNormalWindowLevel ]; + ctx = QZ_GetCGLContextObj (gl_context); + err = CGLSetFullScreen (ctx); + + if (err) { + SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); + goto ERR_NO_GL; + } + } +#endif + + [ window_view release ]; + [ gl_context makeCurrentContext]; + + glClear (GL_COLOR_BUFFER_BIT); + + [ gl_context flushBuffer ]; + + current->flags |= SDL_OPENGL; + } else if (isLion) { /* For 2D, we build a CGBitmapContext */ + CGColorSpaceRef cgColorspace; + + /* Only recreate the view if it doesn't already exist */ + if (window_view == nil) { + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ window_view release ]; + } + + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + + current->flags |= SDL_SWSURFACE; + current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; + + /* Force this window to draw above _everything_. */ + [ qz_window setLevel:CGShieldingWindowLevel() ]; + + this->UpdateRects = QZ_UpdateRects; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + } + + if (isLion) { + [ qz_window setHasShadow:NO]; + [ qz_window setOpaque:YES]; + [ qz_window makeKeyAndOrderFront:nil ]; + } + + /* !!! FIXME: keep an eye on this. + * This API is officially unavailable for 64-bit binaries. + * It happens to work, as of 10.7, but we're going to see if + * we can just simply do without it on newer OSes... + */ + #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__) + if ( !isLion ) { + /* If we don't hide menu bar, it will get events and interrupt the program */ + HideMenuBar (); + } + #endif + + /* Fade in again (asynchronously) */ + if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation(fade_token); + } + + /* + There is a bug in Cocoa where NSScreen doesn't synchronize + with CGDirectDisplay, so the main screen's frame is wrong. + As a result, coordinate translation produces incorrect results. + We can hack around this bug by setting the screen rect + ourselves. This hack should be removed if/when the bug is fixed. + */ + screen_rect = NSMakeRect(0,0,width,height); + QZ_SetFrame(this, [ NSScreen mainScreen ], screen_rect); + + /* Save the flags to ensure correct tear-down */ + mode_flags = current->flags; + + /* Set app state, hide cursor if necessary, ... */ + QZ_DoActivate(this); + + return current; + + /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ +ERR_NO_GL: goto ERR_DOUBLEBUF; /* this goto is to stop a compiler warning on newer SDKs. */ +ERR_DOUBLEBUF: QZ_RestoreDisplayMode(this); +ERR_NO_SWITCH: CGReleaseAllDisplays (); +ERR_NO_CAPTURE: +ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; +} + +static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, + int height, int *bpp, Uint32 flags, + const BOOL save_gl) +{ + unsigned int style; + NSRect contentRect; + int center_window = 1; + int origin_x, origin_y; + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + current->flags = 0; + current->w = width; + current->h = height; + + contentRect = NSMakeRect (0, 0, width, height); + + /* + Check if we should completely destroy the previous mode + - If it is fullscreen + - If it has different noframe or resizable attribute + - If it is OpenGL (since gl attributes could be different) + - If new mode is OpenGL, but previous mode wasn't + */ + if (video_set == SDL_TRUE) { + if (mode_flags & SDL_FULLSCREEN) { + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + QZ_UnsetVideoMode (this, TRUE, save_gl); + } + else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || + (mode_flags & SDL_OPENGL) || + (flags & SDL_OPENGL) ) { + QZ_UnsetVideoMode (this, TRUE, save_gl); + } + } + + /* Sorry, QuickDraw was ripped out. */ + if (getenv("SDL_NSWindowPointer") || getenv("SDL_NSQuickDrawViewPointer")) { + SDL_SetError ("Embedded QuickDraw windows are no longer supported"); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + + /* Check if we should recreate the window */ + if (qz_window == nil) { + + /* Set the window style based on input flags */ + if ( flags & SDL_NOFRAME ) { + style = NSBorderlessWindowMask; + current->flags |= SDL_NOFRAME; + } else { + style = NSTitledWindowMask; + style |= (NSMiniaturizableWindowMask | NSClosableWindowMask); + if ( flags & SDL_RESIZABLE ) { + style |= NSResizableWindowMask; + current->flags |= SDL_RESIZABLE; + } + } + + /* Manually create a window, avoids having a nib file resource */ + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:contentRect + styleMask:style + backing:NSBackingStoreBuffered + defer:NO ]; + + if (qz_window == nil) { + SDL_SetError ("Could not create the Cocoa window"); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + + /*[ qz_window setReleasedWhenClosed:YES ];*/ /* no need to set this as it's the default for NSWindows */ + QZ_SetCaption(this, this->wm_title, this->wm_icon); + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setViewsNeedDisplay:NO ]; + + if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) { + /* have to flip the Y value (NSPoint is lower left corner origin) */ + [ qz_window setFrameTopLeftPoint:NSMakePoint((float) origin_x, (float) (this->info.current_h - origin_y))]; + center_window = 0; + } else if ( center_window ) { + [ qz_window center ]; + } + + [ qz_window setDelegate: + [ [ SDL_QuartzWindowDelegate alloc ] init ] ]; + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; + } + /* We already have a window, just change its size */ + else { + [ qz_window setContentSize:contentRect.size ]; + current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; + [ window_view setFrameSize:contentRect.size ]; + } + + /* For OpenGL, we bind the context to a subview */ + if ( flags & SDL_OPENGL ) { + + if ( ! save_gl ) { + if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + return NULL; + } + } + + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ gl_context setView: window_view ]; + [ window_view release ]; + [ gl_context makeCurrentContext]; + [ qz_window makeKeyAndOrderFront:nil ]; + current->flags |= SDL_OPENGL; + } + /* For 2D, we build a CGBitmapContext */ + else { + CGColorSpaceRef cgColorspace; + + /* Only recreate the view if it doesn't already exist */ + if (window_view == nil) { + + window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; + [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ qz_window contentView ] addSubview:window_view ]; + [ window_view release ]; + [ qz_window makeKeyAndOrderFront:nil ]; + } + + cgColorspace = CGColorSpaceCreateDeviceRGB(); + current->pitch = 4 * current->w; + current->pixels = SDL_malloc (current->h * current->pitch); + + cg_context = CGBitmapContextCreate (current->pixels, current->w, current->h, + 8, current->pitch, cgColorspace, + kCGImageAlphaNoneSkipFirst); + CGColorSpaceRelease (cgColorspace); + + current->flags |= SDL_SWSURFACE; + current->flags |= SDL_ASYNCBLIT; + current->hwdata = (void *) cg_context; + + this->UpdateRects = QZ_UpdateRects; + this->LockHWSurface = QZ_LockHWSurface; + this->UnlockHWSurface = QZ_UnlockHWSurface; + } + + /* Save flags to ensure correct teardown */ + mode_flags = current->flags; + + /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */ + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + + return current; +} + + +static SDL_Surface* QZ_SetVideoModeInternal (_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags, BOOL save_gl) +{ + const BOOL isLion = IS_LION_OR_LATER(this); + + current->flags = 0; + current->pixels = NULL; + + /* Setup full screen video */ + if ( flags & SDL_FULLSCREEN ) { + if ( isLion ) { + bpp = 32; + } + current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags, save_gl ); + if (current == NULL) + return NULL; + } + /* Setup windowed video */ + else { + /* Force bpp to 32 */ + bpp = 32; + current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags, save_gl ); + if (current == NULL) + return NULL; + } + + if (qz_window != nil) { + nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window]; + [NSGraphicsContext setCurrentContext:nsgfx_context]; + } + + /* Setup the new pixel format */ + { + int amask = 0, + rmask = 0, + gmask = 0, + bmask = 0; + + switch (bpp) { + case 16: /* (1)-5-5-5 RGB */ + amask = 0; + rmask = 0x7C00; + gmask = 0x03E0; + bmask = 0x001F; + break; + case 24: + SDL_SetError ("24bpp is not available"); + return NULL; + case 32: /* (8)-8-8-8 ARGB */ + amask = 0x00000000; + if ( (!isLion) && (flags & SDL_FULLSCREEN) ) { + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; + } else { +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + rmask = 0x0000FF00; + gmask = 0x00FF0000; + bmask = 0xFF000000; +#else + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; +#endif + break; + } + } + + if ( ! SDL_ReallocFormat (current, bpp, + rmask, gmask, bmask, amask ) ) { + SDL_SetError ("Couldn't reallocate pixel format"); + return NULL; + } + } + + /* Signal successful completion (used internally) */ + video_set = SDL_TRUE; + + return current; +} + +static SDL_Surface* QZ_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, + Uint32 flags) +{ + /* Don't throw away the GL context if we can just resize the current one. */ +#if 0 /* !!! FIXME: half-finished side project. Reenable this if you ever debug the corner cases. */ + const BOOL save_gl = ( (video_set == SDL_TRUE) && ((flags & SDL_OPENGL) == (current->flags & SDL_OPENGL)) && (bpp == current->format->BitsPerPixel) ); +#else + const BOOL save_gl = NO; +#endif + + NSOpenGLContext *glctx = gl_context; + SDL_Surface* retval = NULL; + + if (save_gl) { + [glctx retain]; /* just so we don't lose this when killing old views, etc */ + } + + retval = QZ_SetVideoModeInternal (this, current, width, height, bpp, flags, save_gl); + + if (save_gl) { + [glctx release]; /* something else should own this now, or we legitimately release it. */ + } + + return retval; +} + + +static int QZ_ToggleFullScreen (_THIS, int on) +{ + return 0; +} + +static int QZ_SetColors (_THIS, int first_color, int num_colors, + SDL_Color *colors) +{ +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + /* we shouldn't have an 8-bit mode on Lion! */ + if (!IS_LION_OR_LATER(this)) { + CGTableCount index; + CGDeviceColor color; + + for (index = first_color; index < first_color+num_colors; index++) { + + /* Clamp colors between 0.0 and 1.0 */ + color.red = colors->r / 255.0; + color.blue = colors->b / 255.0; + color.green = colors->g / 255.0; + + colors++; + + CGPaletteSetColorAtIndex (palette, color, index); + } + + return ( CGDisplayNoErr == CGDisplaySetPalette (display_id, palette) ); + } +#endif + + return 0; +} + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) +static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) +{ + return 1; +} + +static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface) +{ +} + +/* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */ +static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) +{ + union + { + UInt64 i; + Nanoseconds ns; + } temp; + + temp.i = seconds * 1000000000.0; + + return NanosecondsToAbsolute ( temp.ns ); +} + +static int QZ_ThreadFlip (_THIS) +{ + Uint8 *src, *dst; + int skip, len, h; + + /* + Give this thread the highest scheduling priority possible, + in the hopes that it will immediately run after the VBL delay + */ + { + pthread_t current_thread; + int policy; + struct sched_param param; + + current_thread = pthread_self (); + pthread_getschedparam (current_thread, &policy, ¶m); + policy = SCHED_RR; + param.sched_priority = sched_get_priority_max (policy); + pthread_setschedparam (current_thread, policy, ¶m); + } + + while (1) { + + SDL_SemWait (sem1); + if (quit_thread) + return 0; + + /* + * We have to add SDL_VideoSurface->offset here, since we might be a + * smaller surface in the center of the framebuffer (you asked for + * a fullscreen resolution smaller than the hardware could supply + * so SDL is centering it in a bigger resolution)... + */ + dst = ((Uint8 *)((size_t)CGDisplayBaseAddress (display_id))) + SDL_VideoSurface->offset; + src = current_buffer + SDL_VideoSurface->offset; + len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; + h = SDL_VideoSurface->h; + skip = SDL_VideoSurface->pitch; + + /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ + { + + /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ + double refreshRate; + double linesPerSecond; + double target; + double position; + double adjustment; + AbsoluteTime nextTime; + CFNumberRef refreshRateCFNumber; + + refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate); + if ( NULL == refreshRateCFNumber ) { + SDL_SetError ("Mode has no refresh rate"); + goto ERROR; + } + + if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) { + SDL_SetError ("Error getting refresh rate"); + goto ERROR; + } + + if ( 0 == refreshRate ) { + + SDL_SetError ("Display has no refresh rate, using 60hz"); + + /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */ + refreshRate = 60.0; + } + + linesPerSecond = refreshRate * h; + target = h; + + /* Figure out the first delay so we start off about right */ + position = CGDisplayBeamPosition (display_id); + if (position > target) + position = 0; + + adjustment = (target - position) / linesPerSecond; + + nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment)); + + MPDelayUntil (&nextTime); + } + + + /* On error, skip VBL delay */ + ERROR: + + /* TODO: use CGContextDrawImage here too! Create two CGContextRefs the same way we + create two buffers, replace current_buffer with current_context and set it + appropriately in QZ_FlipDoubleBuffer. */ + while ( h-- ) { + + SDL_memcpy (dst, src, len); + src += skip; + dst += skip; + } + + /* signal flip completion */ + SDL_SemPost (sem2); + } + + return 0; +} + +static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface) +{ + /* wait for previous flip to complete */ + SDL_SemWait (sem2); + + current_buffer = surface->pixels; + + if (surface->pixels == sw_buffers[0]) + surface->pixels = sw_buffers[1]; + else + surface->pixels = sw_buffers[0]; + + /* signal worker thread to do the flip */ + SDL_SemPost (sem1); + + return 0; +} + +static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects) +{ + /* perform a flip if someone calls updaterects on a doublebuferred surface */ + this->FlipHWSurface (this, SDL_VideoSurface); +} + +static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) +{ +#pragma unused(this,num_rects,rects) +} +#endif + +/* Resize icon, BMP format */ +static const unsigned char QZ_ResizeIcon[] = { + 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, + 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, + 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87, + 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8, + 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda, + 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda, + 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7, + 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8, + 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb, + 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8, + 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc, + 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b +}; + +static void QZ_DrawResizeIcon (_THIS) +{ + /* Check if we should draw the resize icon */ + if (SDL_VideoSurface->flags & SDL_RESIZABLE) { + + SDL_Rect icon_rect; + + /* Create the icon image */ + if (resize_icon == NULL) { + + SDL_RWops *rw; + SDL_Surface *tmp; + + rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); + tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); + + resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); + SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); + + SDL_FreeSurface (tmp); + } + + icon_rect.x = SDL_VideoSurface->w - 13; + icon_rect.y = SDL_VideoSurface->h - 13; + icon_rect.w = 13; + icon_rect.h = 13; + + SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); + } +} + +static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) +{ + if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { + QZ_GL_SwapBuffers (this); + } + else if ( [ qz_window isMiniaturized ] ) { + + /* Do nothing if miniaturized */ + } + + else { + NSGraphicsContext *ctx = [NSGraphicsContext currentContext]; + if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */ + [NSGraphicsContext setCurrentContext:nsgfx_context]; + ctx = nsgfx_context; + } + CGContextRef cgc = (CGContextRef) [ctx graphicsPort]; + QZ_DrawResizeIcon (this); + CGContextFlush (cg_context); + CGImageRef image = CGBitmapContextCreateImage (cg_context); + CGRect rectangle = CGRectMake (0,0,[window_view frame].size.width,[window_view frame].size.height); + + CGContextDrawImage (cgc, rectangle, image); + CGImageRelease(image); + CGContextFlush (cgc); + } +} + +static void QZ_VideoQuit (_THIS) +{ + CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; + + /* Restore gamma settings */ + CGDisplayRestoreColorSyncSettings (); + + /* Ensure the cursor will be visible and working when we quit */ + CGDisplayShowCursor (display_id); + CGAssociateMouseAndMouseCursorPosition (1); + + if (mode_flags & SDL_FULLSCREEN) { + /* Fade to black to hide resolution-switching flicker (and garbage + that is displayed by a destroyed OpenGL context, if applicable) */ + if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { + CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); + } + QZ_UnsetVideoMode (this, TRUE, FALSE); + if (fade_token != kCGDisplayFadeReservationInvalidToken) { + CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); + CGReleaseDisplayFadeReservation (fade_token); + } + } + else + QZ_UnsetVideoMode (this, TRUE, FALSE); + +#if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) + if (!IS_LION_OR_LATER(this)) { + CGPaletteRelease(palette); + } +#endif + + if (opengl_library) { + SDL_UnloadObject(opengl_library); + opengl_library = NULL; + } + this->gl_config.driver_loaded = 0; + + if (field_edit) { + [field_edit release]; + field_edit = NULL; + } +} + +static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return 1; +} + +static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); /* unallowed (no HWSURFACE support here). */ +} + +static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) +{ +} + +/* Gamma functions */ +int QZ_SetGamma (_THIS, float red, float green, float blue) +{ + const CGGammaValue min = 0.0, max = 1.0; + + if (red == 0.0) + red = FLT_MAX; + else + red = 1.0 / red; + + if (green == 0.0) + green = FLT_MAX; + else + green = 1.0 / green; + + if (blue == 0.0) + blue = FLT_MAX; + else + blue = 1.0 / blue; + + if ( CGDisplayNoErr == CGSetDisplayTransferByFormula + (display_id, min, max, red, min, max, green, min, max, blue) ) { + + return 0; + } + else { + + return -1; + } +} + +int QZ_GetGamma (_THIS, float *red, float *green, float *blue) +{ + CGGammaValue dummy; + if ( CGDisplayNoErr == CGGetDisplayTransferByFormula + (display_id, &dummy, &dummy, red, + &dummy, &dummy, green, &dummy, &dummy, blue) ) + + return 0; + else + return -1; +} + +int QZ_SetGammaRamp (_THIS, Uint16 *ramp) +{ + const uint32_t tableSize = 255; + CGGammaValue redTable[tableSize]; + CGGammaValue greenTable[tableSize]; + CGGammaValue blueTable[tableSize]; + + int i; + + /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ + for (i = 0; i < 256; i++) + redTable[i % 256] = ramp[i] / 65535.0; + + for (i=256; i < 512; i++) + greenTable[i % 256] = ramp[i] / 65535.0; + + for (i=512; i < 768; i++) + blueTable[i % 256] = ramp[i] / 65535.0; + + if ( CGDisplayNoErr == CGSetDisplayTransferByTable + (display_id, tableSize, redTable, greenTable, blueTable) ) + return 0; + else + return -1; +} + +int QZ_GetGammaRamp (_THIS, Uint16 *ramp) +{ + const uint32_t tableSize = 255; + CGGammaValue redTable[tableSize]; + CGGammaValue greenTable[tableSize]; + CGGammaValue blueTable[tableSize]; + uint32_t actual; + int i; + + if ( CGDisplayNoErr != CGGetDisplayTransferByTable + (display_id, tableSize, redTable, greenTable, blueTable, &actual) || + actual != tableSize) + + return -1; + + /* Pack tables into one array, with values from 0 to 65535 */ + for (i = 0; i < 256; i++) + ramp[i] = redTable[i % 256] * 65535.0; + + for (i=256; i < 512; i++) + ramp[i] = greenTable[i % 256] * 65535.0; + + for (i=512; i < 768; i++) + ramp[i] = blueTable[i % 256] * 65535.0; + + return 0; +} + diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h new file mode 100644 index 0000000..0b0767e --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.h @@ -0,0 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +struct WMcursor { + NSCursor *nscursor; +}; + +void QZ_UpdateCursor(_THIS); diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m new file mode 100644 index 0000000..d526424 --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWM.m @@ -0,0 +1,444 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" + + +void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { + + if ( cursor != NULL ) { + [ cursor->nscursor release ]; + free (cursor); + } +} + +WMcursor* QZ_CreateWMCursor (_THIS, Uint8 *data, Uint8 *mask, + int w, int h, int hot_x, int hot_y) { + WMcursor *cursor; + NSBitmapImageRep *imgrep; + NSImage *img; + unsigned char *planes[5]; + int i; + NSAutoreleasePool *pool; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if (cursor == NULL) goto outOfMemory; + + /* create the image representation and get the pointers to its storage */ + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: w pixelsHigh: h bitsPerSample: 1 samplesPerPixel: 2 hasAlpha: YES isPlanar: YES colorSpaceName: NSDeviceWhiteColorSpace bytesPerRow: (w+7)/8 bitsPerPixel: 0 ] autorelease ]; + if (imgrep == nil) goto outOfMemory; + [ imgrep getBitmapDataPlanes: planes ]; + + /* copy data and mask, extending the mask to all black pixels because the inversion effect doesn't work with Cocoa's alpha-blended cursors */ + for (i = 0; i < (w+7)/8*h; i++) { + planes[0][i] = data[i] ^ 0xFF; + planes[1][i] = mask[i] | data[i]; + } + + /* create image and cursor */ + img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(w, h) ] autorelease ]; + if (img == nil) goto outOfMemory; + [ img addRepresentation: imgrep ]; + if (system_version < 0x1030) { /* on 10.2, cursors must be 16*16 */ + if (w > 16 || h > 16) { /* too big: scale it down */ + [ img setScalesWhenResized: YES ]; + hot_x = hot_x*16/w; + hot_y = hot_y*16/h; + } + else { /* too small (or just right): extend it (from the bottom left corner, so hot_y must be adjusted) */ + hot_y += 16 - h; + } + [ img setSize: NSMakeSize(16, 16) ]; + } + cursor->nscursor = [ [ NSCursor alloc ] initWithImage: img hotSpot: NSMakePoint(hot_x, hot_y) ]; + if (cursor->nscursor == nil) goto outOfMemory; + + [ pool release ]; + return(cursor); + +outOfMemory: + [ pool release ]; + if (cursor != NULL) SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); +} + +void QZ_UpdateCursor (_THIS) { + BOOL state; + + if (cursor_should_be_visible || !(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) { + state = YES; + } else { + state = NO; + } + if (state != cursor_visible) { + if (state) { + [ NSCursor unhide ]; + } else { + [ NSCursor hide ]; + } + cursor_visible = state; + } +} + +BOOL QZ_IsMouseInWindow (_THIS) { + if (qz_window == nil || (mode_flags & SDL_FULLSCREEN)) return YES; /*fullscreen*/ + else { + NSPoint p = [ qz_window mouseLocationOutsideOfEventStream ]; + p.y -= 1.0f; /* Apparently y goes from 1 to h, not from 0 to h-1 (i.e. the "location of the mouse" seems to be defined as "the location of the top left corner of the mouse pointer's hot pixel" */ + return NSPointInRect(p, [ window_view frame ]); + } +} + +int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { + + if ( cursor == NULL) { + if ( cursor_should_be_visible ) { + cursor_should_be_visible = NO; + QZ_ChangeGrabState (this, QZ_HIDECURSOR); + } + QZ_UpdateCursor(this); + } + else { + if ( qz_window != nil && !(mode_flags & SDL_FULLSCREEN) ) { + [ qz_window invalidateCursorRectsForView: [ qz_window contentView ] ]; + } + if ( ! cursor_should_be_visible ) { + cursor_should_be_visible = YES; + QZ_ChangeGrabState (this, QZ_SHOWCURSOR); + } + [ cursor->nscursor performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO ]; + QZ_UpdateCursor(this); + } + + return 1; +} + +/* + Coordinate conversion functions, for convenience + Cocoa sets the origin at the lower left corner of the window/screen + SDL, CoreGraphics/WindowServer, and QuickDraw use the origin at the upper left corner + The routines were written so they could be called before SetVideoMode() has finished; + this might have limited usefulness at the moment, but the extra cost is trivial. +*/ + +/* Convert Cocoa screen coordinate to Cocoa window coordinate */ +void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertScreenToBase:*p ]; +} + + +/* Convert Cocoa window coordinate to Cocoa screen coordinate */ +void QZ_PrivateLocalToGlobal (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) + *p = [ qz_window convertBaseToScreen:*p ]; +} + +/* Convert SDL coordinate to Cocoa coordinate */ +void QZ_PrivateSDLToCocoa (_THIS, NSPoint *p) { + + if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ + + p->y = CGDisplayPixelsHigh (display_id) - p->y; + } + else { + + *p = [ window_view convertPoint:*p toView: nil ]; + p->y = [window_view frame].size.height - p->y; + } +} + +/* Convert Cocoa coordinate to SDL coordinate */ +void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p) { + + if ( CGDisplayIsCaptured (display_id) ) { /* capture signals fullscreen */ + + p->y = CGDisplayPixelsHigh (display_id) - p->y; + } + else { + + *p = [ window_view convertPoint:*p fromView: nil ]; + p->y = [window_view frame].size.height - p->y; + } +} + +/* Convert SDL coordinate to window server (CoreGraphics) coordinate */ +CGPoint QZ_PrivateSDLToCG (_THIS, NSPoint *p) { + + CGPoint cgp; + + if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */ + + int height; + + QZ_PrivateSDLToCocoa (this, p); + QZ_PrivateLocalToGlobal (this, p); + + height = CGDisplayPixelsHigh (display_id); + p->y = height - p->y; + } + + cgp.x = p->x; + cgp.y = p->y; + + return cgp; +} + +#if 0 /* Dead code */ +/* Convert window server (CoreGraphics) coordinate to SDL coordinate */ +void QZ_PrivateCGToSDL (_THIS, NSPoint *p) { + + if ( ! CGDisplayIsCaptured (display_id) ) { /* not captured => not fullscreen => local coord */ + + int height; + + /* Convert CG Global to Cocoa Global */ + height = CGDisplayPixelsHigh (display_id); + p->y = height - p->y; + + QZ_PrivateGlobalToLocal (this, p); + QZ_PrivateCocoaToSDL (this, p); + } +} +#endif /* Dead code */ + +void QZ_PrivateWarpCursor (_THIS, int x, int y) { + NSPoint p; + CGPoint cgp; + + p = NSMakePoint (x, y); + cgp = QZ_PrivateSDLToCG (this, &p); + + /* this is the magic call that fixes cursor "freezing" after warp */ + CGAssociateMouseAndMouseCursorPosition (0); + CGWarpMouseCursorPosition (cgp); + if (grab_state != QZ_INVISIBLE_GRAB) { /* can't leave it disassociated? */ + CGAssociateMouseAndMouseCursorPosition (1); + } + SDL_PrivateAppActive (QZ_IsMouseInWindow (this), SDL_APPMOUSEFOCUS); +} + +void QZ_WarpWMCursor (_THIS, Uint16 x, Uint16 y) { + + /* Only allow warping when in foreground */ + if ( ! [ NSApp isActive ] ) + return; + + /* Do the actual warp */ + if (grab_state != QZ_INVISIBLE_GRAB) QZ_PrivateWarpCursor (this, x, y); + + /* Generate the mouse moved event */ + SDL_PrivateMouseMotion (0, 0, x, y); +} + +void QZ_MoveWMCursor (_THIS, int x, int y) { } +void QZ_CheckMouseMode (_THIS) { } + +void QZ_SetCaption (_THIS, const char *title, const char *icon) { + + if ( qz_window != nil ) { + NSString *string; + if ( title != NULL ) { + string = [ [ NSString alloc ] initWithUTF8String:title ]; + [ qz_window setTitle:string ]; + [ string release ]; + } + if ( icon != NULL ) { + string = [ [ NSString alloc ] initWithUTF8String:icon ]; + [ qz_window setMiniwindowTitle:string ]; + [ string release ]; + } + } +} + +void QZ_SetIcon (_THIS, SDL_Surface *icon, Uint8 *mask) +{ + NSBitmapImageRep *imgrep; + NSImage *img; + SDL_Surface *mergedSurface; + NSAutoreleasePool *pool; + Uint8 *pixels; + SDL_bool iconSrcAlpha; + Uint8 iconAlphaValue; + int i, j, maskPitch, index; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + + imgrep = [ [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes: NULL pixelsWide: icon->w pixelsHigh: icon->h bitsPerSample: 8 samplesPerPixel: 4 hasAlpha: YES isPlanar: NO colorSpaceName: NSDeviceRGBColorSpace bytesPerRow: 4*icon->w bitsPerPixel: 32 ] autorelease ]; + if (imgrep == nil) goto freePool; + pixels = [ imgrep bitmapData ]; + SDL_memset(pixels, 0, 4*icon->w*icon->h); /* make the background, which will survive in colorkeyed areas, completely transparent */ + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN +#define BYTEORDER_DEPENDENT_RGBA_MASKS 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF +#else +#define BYTEORDER_DEPENDENT_RGBA_MASKS 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 +#endif + mergedSurface = SDL_CreateRGBSurfaceFrom(pixels, icon->w, icon->h, 32, 4*icon->w, BYTEORDER_DEPENDENT_RGBA_MASKS); + if (mergedSurface == NULL) goto freePool; + + /* blit, with temporarily cleared SRCALPHA flag because we want to copy, not alpha-blend */ + iconSrcAlpha = ((icon->flags & SDL_SRCALPHA) != 0); + iconAlphaValue = icon->format->alpha; + SDL_SetAlpha(icon, 0, 255); + SDL_BlitSurface(icon, NULL, mergedSurface, NULL); + if (iconSrcAlpha) SDL_SetAlpha(icon, SDL_SRCALPHA, iconAlphaValue); + + SDL_FreeSurface(mergedSurface); + + /* apply mask, source alpha, and premultiply color values by alpha */ + maskPitch = (icon->w+7)/8; + for (i = 0; i < icon->h; i++) { + for (j = 0; j < icon->w; j++) { + index = i*4*icon->w + j*4; + if (!(mask[i*maskPitch + j/8] & (128 >> j%8))) { + pixels[index + 3] = 0; + } + else { + if (iconSrcAlpha) { + if (icon->format->Amask == 0) pixels[index + 3] = icon->format->alpha; + } + else { + pixels[index + 3] = 255; + } + } + if (pixels[index + 3] < 255) { + pixels[index + 0] = (Uint16)pixels[index + 0]*pixels[index + 3]/255; + pixels[index + 1] = (Uint16)pixels[index + 1]*pixels[index + 3]/255; + pixels[index + 2] = (Uint16)pixels[index + 2]*pixels[index + 3]/255; + } + } + } + + img = [ [ [ NSImage alloc ] initWithSize: NSMakeSize(icon->w, icon->h) ] autorelease ]; + if (img == nil) goto freePool; + [ img addRepresentation: imgrep ]; + [ NSApp setApplicationIconImage:img ]; + +freePool: + [ pool release ]; +} + +int QZ_IconifyWindow (_THIS) { + + if ( ! [ qz_window isMiniaturized ] ) { + [ qz_window miniaturize:nil ]; + if ( ! [ qz_window isMiniaturized ] ) { + SDL_SetError ("window iconification failed"); + return 0; + } + return 1; + } + else { + SDL_SetError ("window already iconified"); + return 0; + } +} + +/* +int QZ_GetWMInfo (_THIS, SDL_SysWMinfo *info) { + info->nsWindowPtr = qz_window; + return 0; +}*/ + +void QZ_ChangeGrabState (_THIS, int action) { + + /* + Figure out what the next state should be based on the action. + Ignore actions that can't change the current state. + */ + if ( grab_state == QZ_UNGRABBED ) { + if ( action == QZ_ENABLE_GRAB ) { + if ( cursor_should_be_visible ) + grab_state = QZ_VISIBLE_GRAB; + else + grab_state = QZ_INVISIBLE_GRAB; + } + } + else if ( grab_state == QZ_VISIBLE_GRAB ) { + if ( action == QZ_DISABLE_GRAB ) + grab_state = QZ_UNGRABBED; + else if ( action == QZ_HIDECURSOR ) + grab_state = QZ_INVISIBLE_GRAB; + } + else { + assert( grab_state == QZ_INVISIBLE_GRAB ); + + if ( action == QZ_DISABLE_GRAB ) + grab_state = QZ_UNGRABBED; + else if ( action == QZ_SHOWCURSOR ) + grab_state = QZ_VISIBLE_GRAB; + } + + /* now apply the new state */ + if (grab_state == QZ_UNGRABBED) { + + CGAssociateMouseAndMouseCursorPosition (1); + } + else if (grab_state == QZ_VISIBLE_GRAB) { + + CGAssociateMouseAndMouseCursorPosition (1); + } + else { + assert( grab_state == QZ_INVISIBLE_GRAB ); + + QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); + CGAssociateMouseAndMouseCursorPosition (0); + } +} + +SDL_GrabMode QZ_GrabInput (_THIS, SDL_GrabMode grab_mode) { + + int doGrab = grab_mode & SDL_GRAB_ON; + /*int fullscreen = grab_mode & SDL_GRAB_FULLSCREEN;*/ + + if ( this->screen == NULL ) { + SDL_SetError ("QZ_GrabInput: screen is NULL"); + return SDL_GRAB_OFF; + } + + if ( ! video_set ) { + /*SDL_SetError ("QZ_GrabInput: video is not set, grab will take effect on mode switch"); */ + current_grab_mode = grab_mode; + return grab_mode; /* Will be set later on mode switch */ + } + + if ( grab_mode != SDL_GRAB_QUERY ) { + if ( doGrab ) + QZ_ChangeGrabState (this, QZ_ENABLE_GRAB); + else + QZ_ChangeGrabState (this, QZ_DISABLE_GRAB); + + current_grab_mode = doGrab ? SDL_GRAB_ON : SDL_GRAB_OFF; + QZ_UpdateCursor(this); + } + + return current_grab_mode; +} diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h new file mode 100644 index 0000000..d19375b --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050) +typedef unsigned int NSUInteger; +#endif + +/* Subclass of NSWindow to fix genie effect and support resize events */ +@interface SDL_QuartzWindow : NSWindow +{ + BOOL watchForMouseUp; +} + +- (void)miniaturize:(id)sender; +- (void)display; +- (void)setFrame:(NSRect)frameRect display:(BOOL)flag; +- (void)appDidHide:(NSNotification*)note; +- (void)appWillUnhide:(NSNotification*)note; +- (void)appDidUnhide:(NSNotification*)note; +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag; +@end + +/* Delegate for our NSWindow to send SDLQuit() on close */ +@interface SDL_QuartzWindowDelegate : NSObject +- (BOOL)windowShouldClose:(id)sender; +@end + +/* Subclass of NSView to set cursor rectangle */ +@interface SDL_QuartzView : NSView +- (void)resetCursorRects; +@end diff --git a/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m new file mode 100644 index 0000000..375833f --- /dev/null +++ b/3rdparty/SDL/src/video/quartz/SDL_QuartzWindow.m @@ -0,0 +1,231 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" +#include "SDL_QuartzWindow.h" + +/* + This function makes the *SDL region* of the window 100% opaque. + The genie effect uses the alpha component. Otherwise, + it doesn't seem to matter what value it has. +*/ +static void QZ_SetPortAlphaOpaque () { + + SDL_Surface *surface = current_video->screen; + int bpp; + + bpp = surface->format->BitsPerPixel; + + if (bpp == 32) { + + Uint32 *pixels = (Uint32*) surface->pixels; + Uint32 rowPixels = surface->pitch / 4; + Uint32 i, j; + + for (i = 0; i < surface->h; i++) + for (j = 0; j < surface->w; j++) { + + pixels[ (i * rowPixels) + j ] |= 0xFF000000; + } + } +} + +@implementation SDL_QuartzWindow + +/* we override these methods to fix the miniaturize animation/dock icon bug */ +- (void)miniaturize:(id)sender +{ + if (SDL_VideoSurface->flags & SDL_OPENGL) { + + /* + Future: Grab framebuffer and put into NSImage + [ qz_window setMiniwindowImage:image ]; + */ + } + else { + + /* make the alpha channel opaque so anim won't have holes in it */ + QZ_SetPortAlphaOpaque (); + } + + /* window is hidden now */ + SDL_PrivateAppActive (0, SDL_APPACTIVE); + + [ super miniaturize:sender ]; +} + +- (void)display +{ + /* + This method fires just before the window deminaturizes from the Dock. + + We'll save the current visible surface, let the window manager redraw any + UI elements, and restore the SDL surface. This way, no expose event + is required, and the deminiaturize works perfectly. + */ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + /* make sure pixels are fully opaque */ + if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + QZ_SetPortAlphaOpaque (); + + /* save current visible SDL surface */ + [ self cacheImageInRect:[ window_view frame ] ]; + + /* let the window manager redraw controls, border, etc */ + [ super display ]; + + /* restore visible SDL surface */ + [ self restoreCachedImage ]; + + /* window is visible again */ + SDL_PrivateAppActive (1, SDL_APPACTIVE); +} + +- (void)setFrame:(NSRect)frameRect display:(BOOL)flag +{ + + /* + If the video surface is NULL, this originated from QZ_SetVideoMode, + so don't send the resize event. + */ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + if (this && SDL_VideoSurface == NULL) { + + [ super setFrame:frameRect display:flag ]; + } + else if (this && qz_window) { + + NSRect newViewFrame; + + [ super setFrame:frameRect display:flag ]; + + newViewFrame = [ window_view frame ]; + + SDL_PrivateResize (newViewFrame.size.width, newViewFrame.size.height); + } +} + +/* QZ_DoActivate() calls a low-level CoreGraphics routine to adjust + the cursor position, if input is being grabbed. If app activation is + triggered by a mouse click in the title bar, then the window manager + gets confused and thinks we're dragging the window. The solution + below postpones the activate event to avoid this scenario. */ +- (void)becomeKeyWindow +{ + NSEvent *event = [self currentEvent]; + if ([event type] == NSLeftMouseDown && [event window] == self) + watchForMouseUp = YES; + else + [super becomeKeyWindow]; +} + +- (void)sendEvent:(NSEvent *)event +{ + [super sendEvent:event]; + if (watchForMouseUp && [event type] == NSLeftMouseUp) + { + watchForMouseUp = NO; + [super becomeKeyWindow]; + } +} + +- (void)appDidHide:(NSNotification*)note +{ + SDL_PrivateAppActive (0, SDL_APPACTIVE); +} + +- (void)appWillUnhide:(NSNotification*)note +{ + SDL_VideoDevice *this = (SDL_VideoDevice*)current_video; + + if ( this ) { + + /* make sure pixels are fully opaque */ + if (! ( SDL_VideoSurface->flags & SDL_OPENGL ) ) + QZ_SetPortAlphaOpaque (); + + /* save current visible SDL surface */ + [ self cacheImageInRect:[ window_view frame ] ]; + } +} + +- (void)appDidUnhide:(NSNotification*)note +{ + /* restore cached image, since it may not be current, post expose event too */ + [ self restoreCachedImage ]; + + /*SDL_PrivateExpose ();*/ + + SDL_PrivateAppActive (1, SDL_APPACTIVE); +} + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag +{ + /* Make our window subclass receive these application notifications */ + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidHide:) name:NSApplicationDidHideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appDidUnhide:) name:NSApplicationDidUnhideNotification object:NSApp ]; + + [ [ NSNotificationCenter defaultCenter ] addObserver:self + selector:@selector(appWillUnhide:) name:NSApplicationWillUnhideNotification object:NSApp ]; + + return [ super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag ]; +} + +@end + +@implementation SDL_QuartzWindowDelegate +- (BOOL)windowShouldClose:(id)sender +{ + SDL_PrivateQuit(); + return NO; +} + +- (void)windowDidBecomeKey:(NSNotification *)aNotification +{ + QZ_DoActivate (current_video); +} + +- (void)windowDidResignKey:(NSNotification *)aNotification +{ + QZ_DoDeactivate (current_video); +} + +@end + +@implementation SDL_QuartzView + +- (void)resetCursorRects +{ + SDL_Cursor *sdlc = SDL_GetCursor(); + if (sdlc != NULL && sdlc->wm_cursor != NULL) { + [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor]; + } +} + +@end diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S b/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S new file mode 100644 index 0000000..fae32f8 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosASM.S @@ -0,0 +1,116 @@ +; +; SDL - Simple DirectMedia Layer +; Copyright (C) 1997-2012 Sam Lantinga +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Library General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Library General Public License for more details. +; +; You should have received a copy of the GNU Library General Public +; License along with this library; if not, write to the Free +; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +; +; Sam Lantinga +; slouken@libsdl.org +; +; Assembler routines for RISC OS display +; + + AREA |C$$CODE| + + EXPORT |RISCOS_Put32| + +; Display 32bpp to 32bpp, 1:1 +; +; Code provided by Adrain Lees +; +; entry a1 -> destination +; a2 = dest width in pixels +; a3 = dest line length in bytes +; a4 = dest height in scanlines +; arg5 -> source +; arg6 = byte offset from end of source line to start of next + +Arg5 * 10*4 +Arg6 * Arg5+4 + +RISCOS_Put32 ROUT + STMFD sp!,{a2,v1-v6,sl,fp,lr} + LDR ip,[sp,#Arg5] + MOV lr,a1 + B ucp64lp + +00 ;tail strip of 1-15 pixels + + LDR v1,[ip],#4 +01 SUBS a2,a2,#1 + STR v1,[lr],#4 + LDRHI v1,[ip],#4 + BHI %01 + B %02 + +ucp64end ADDS a2,a2,#16 + BNE %00 + +02 SUBS a4,a4,#1 ;height-- + LDRHI v1,[sp,#Arg6] + LDRHI a2,[sp] ;reload width + BLS %03 + + ;move to start of next scanline + + ADD lr,a1,a3 + ADD a1,a1,a3 + ADD ip,ip,v1 + +ucp64lp SUBS a2,a2,#16 + BLO ucp64end + + PLD [ip,#64] + + LDR v1,[ip],#4 + LDR v2,[ip],#4 + LDR v3,[ip],#4 + LDR v4,[ip],#4 + LDR v5,[ip],#4 + LDR v6,[ip],#4 + LDR sl,[ip],#4 + LDR fp,[ip],#4 + STR v1,[lr],#4 + STR v2,[lr],#4 + STR v3,[lr],#4 + STR v4,[lr],#4 + STR v5,[lr],#4 + STR v6,[lr],#4 + STR sl,[lr],#4 + STR fp,[lr],#4 + + PLD [ip,#64] + + LDR v1,[ip],#4 + LDR v2,[ip],#4 + LDR v3,[ip],#4 + LDR v4,[ip],#4 + LDR v5,[ip],#4 + LDR v6,[ip],#4 + LDR sl,[ip],#4 + LDR fp,[ip],#4 + STR v1,[lr],#4 + STR v2,[lr],#4 + STR v3,[lr],#4 + STR v4,[lr],#4 + STR v5,[lr],#4 + STR v6,[lr],#4 + STR sl,[lr],#4 + STR fp,[lr],#4 + + B ucp64lp + +03 LDMFD sp!,{a2,v1-v6,sl,fp,pc} + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c b/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c new file mode 100644 index 0000000..b8c3cf7 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosFullScreenVideo.c @@ -0,0 +1,777 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements RISC OS full screen display. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" +#include "unixlib/os.h" +#include "unixlib/local.h" + +/* Private structures */ +typedef struct tagScreenModeBlock +{ + int flags; // mode selector flags, bit 0 = 1, bit 1-7 format specifier, 8-31 reserved + int x_pixels; + int y_pixels; + int pixel_depth; // 2^pixel_depth = bpp,i.e. 0 = 1, 1 = 2, 4 = 16, 5 = 32 + int frame_rate; // -1 use first match + int mode_vars[5]; // array of index, value pairs terminated by -1 +} SCREENMODEBLOCK; + + +/* Helper functions */ +void FULLSCREEN_SetDeviceMode(_THIS); +int FULLSCREEN_SetMode(int width, int height, int bpp); +void FULLSCREEN_SetupBanks(_THIS); + +/* SDL video device functions for fullscreen mode */ +static int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface); +void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon); +extern int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); + +/* UpdateRects variants */ +static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects); +static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects); + +/* Local helper functions */ +static int cmpmodes(const void *va, const void *vb); +static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h); +void FULLSCREEN_SetWriteBank(int bank); +void FULLSCREEN_SetDisplayBank(int bank); +static void FULLSCREEN_DisableEscape(); +static void FULLSCREEN_EnableEscape(); +void FULLSCREEN_BuildModeList(_THIS); + +/* Following variable is set up in riskosTask.c */ +extern int riscos_backbuffer; /* Create a back buffer in system memory for full screen mode */ + +/* Following is used to create a sprite back buffer */ +extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); + +/* Fast assembler copy */ +extern void RISCOS_Put32(void *to, int pixels, int pitch, int rows, void *from, int src_skip_bytes); + +SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + _kernel_swi_regs regs; + Uint32 Rmask = 0; + Uint32 Gmask = 0; + Uint32 Bmask = 0; + int create_back_buffer = riscos_backbuffer; + + switch(bpp) + { + case 8: + flags |= SDL_HWPALETTE; + break; + + case 15: + case 16: + Bmask = 0x00007c00; + Gmask = 0x000003e0; + Rmask = 0x0000001f; + break; + + case 32: + Bmask = 0x00ff0000; + Gmask = 0x0000ff00; + Rmask = 0x000000ff; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return NULL; + break; + } + + if (FULLSCREEN_SetMode(width, height, bpp) == 0) + { + SDL_SetError("Couldn't set requested mode"); + return (NULL); + } + +/* printf("Setting mode %dx%d\n", width, height); */ + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + RISCOS_RestoreWimpMode(); + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->w = width; + this->hidden->height = current->h = height; + + regs.r[0] = -1; /* -1 for current screen mode */ + + /* Get screen width in bytes */ + regs.r[1] = 6; // Screen Width in bytes + _kernel_swi(OS_ReadModeVariable, ®s, ®s); + + current->pitch = regs.r[2]; + + if (flags & SDL_DOUBLEBUF) + { + regs.r[0] = 2; /* Screen area */ + _kernel_swi(OS_ReadDynamicArea, ®s, ®s); + + /* Reg 1 has amount of memory currently used for display */ + regs.r[0] = 2; /* Screen area */ + regs.r[1] = (current->pitch * height * 2) - regs.r[1]; + if (_kernel_swi(OS_ChangeDynamicArea, ®s, ®s) != NULL) + { + /* Can't allocate enough screen memory for double buffer */ + flags &= ~SDL_DOUBLEBUF; + } + } + + current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | SDL_PREALLOC; + + + /* Need to set display banks here for double buffering */ + if (flags & SDL_DOUBLEBUF) + { + FULLSCREEN_SetWriteBank(0); + FULLSCREEN_SetDisplayBank(1); + + create_back_buffer = 0; /* Don't need a back buffer for a double buffered display */ + } + + FULLSCREEN_SetupBanks(this); + + if (create_back_buffer) + { + /* If not double buffered we may need to create a memory + ** back buffer to simulate processing on other OSes. + ** This is turned on by setting the enviromental variable + ** SDL$<name>$BackBuffer >= 1 + */ + if (riscos_backbuffer == 3) + this->hidden->bank[0] = WIMP_CreateBuffer(width, height, bpp); + else + this->hidden->bank[0] = SDL_malloc(height * current->pitch); + if (this->hidden->bank[0] == 0) + { + RISCOS_RestoreWimpMode(); + SDL_SetError("Couldnt allocate memory for back buffer"); + return (NULL); + } + /* Surface updated in programs is now a software surface */ + current->flags &= ~SDL_HWSURFACE; + } + + /* Store address of allocated screen bank to be freed later */ + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + if (create_back_buffer) + { + this->hidden->alloc_bank = this->hidden->bank[0]; + if (riscos_backbuffer == 3) + { + this->hidden->bank[0] += 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + } + } else + this->hidden->alloc_bank = 0; + + // Clear both banks to black + SDL_memset(this->hidden->bank[0], 0, height * current->pitch); + SDL_memset(this->hidden->bank[1], 0, height * current->pitch); + + this->hidden->current_bank = 0; + current->pixels = this->hidden->bank[0]; + + /* Have to set the screen here, so SetDeviceMode will pick it up */ + this->screen = current; + + /* Reset device functions for the wimp */ + FULLSCREEN_SetDeviceMode(this); + +/* FULLSCREEN_DisableEscape(); */ + + /* We're done */ + return(current); +} + +/* Reset any device functions that have been changed because we have run in WIMP mode */ +void FULLSCREEN_SetDeviceMode(_THIS) +{ + /* Update rects is different if we have a backbuffer */ + + if (riscos_backbuffer && (this->screen->flags & SDL_DOUBLEBUF) == 0) + { + switch(riscos_backbuffer) + { + case 2: /* ARM code full word copy */ + switch(this->screen->format->BytesPerPixel) + { + case 1: /* 8bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects8bpp; + break; + case 2: /* 15/16bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects16bpp; + break; + case 4: /* 32 bpp modes */ + this->UpdateRects = FULLSCREEN_UpdateRects32bpp; + break; + + default: /* Just default to the memcpy routine */ + this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy; + break; + } + break; + + case 3: /* Use OS sprite plot routine */ + this->UpdateRects = FULLSCREEN_UpdateRectsOS; + break; + + default: /* Old but safe memcpy */ + this->UpdateRects = FULLSCREEN_UpdateRectsMemCpy; + break; + } + } else + this->UpdateRects = FULLSCREEN_UpdateRects; /* Default do nothing implementation */ + + this->SetColors = FULLSCREEN_SetColors; + + this->FlipHWSurface = FULLSCREEN_FlipHWSurface; + + this->SetCaption = FULLSCREEN_SetWMCaption; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + + this->ShowWMCursor = RISCOS_ShowWMCursor; + this->WarpWMCursor = FULLSCREEN_WarpWMCursor; + + this->PumpEvents = FULLSCREEN_PumpEvents; +} + +/* Query for the list of available video modes */ +void FULLSCREEN_BuildModeList(_THIS) +{ + _kernel_swi_regs regs; + char *enumInfo = NULL; + char *enum_ptr; + int *blockInfo; + int j; + int num_modes; + + /* Find out how much space we need */ + regs.r[0] = 2; /* Reason code */ + regs.r[2] = 0; /* Number of modes to skip */ + regs.r[6] = 0; /* pointer to block or 0 for count */ + regs.r[7] = 0; /* Size of block in bytes */ + _kernel_swi(OS_ScreenMode, ®s, ®s); + + num_modes = -regs.r[2]; + + /* Video memory should be in r[5] */ + this->info.video_mem = regs.r[5]/1024; + + enumInfo = (unsigned char *)SDL_malloc(-regs.r[7]); + if (enumInfo == NULL) + { + SDL_OutOfMemory(); + return; + } + /* Read mode information into block */ + regs.r[2] = 0; + regs.r[6] = (int)enumInfo; + regs.r[7] = -regs.r[7]; + _kernel_swi(OS_ScreenMode, ®s, ®s); + + enum_ptr = enumInfo; + + for (j =0; j < num_modes;j++) + { + blockInfo = (int *)enum_ptr; + if ((blockInfo[1] & 255) == 1) /* We understand this format */ + { + switch(blockInfo[4]) + { + case 3: /* 8 bits per pixel */ + FULLSCREEN_AddMode(this, 8, blockInfo[2], blockInfo[3]); + break; + case 4: /* 15 bits per pixel */ + FULLSCREEN_AddMode(this, 15, blockInfo[2], blockInfo[3]); + break; + case 5: /* 32 bits per pixel */ + FULLSCREEN_AddMode(this, 32, blockInfo[2], blockInfo[3]); + break; + } + } + + enum_ptr += blockInfo[0]; + } + + SDL_free(enumInfo); + + /* Sort the mode lists */ + for ( j=0; j<NUM_MODELISTS; ++j ) { + if ( SDL_nummodes[j] > 0 ) { + SDL_qsort(SDL_modelist[j], SDL_nummodes[j], sizeof *SDL_modelist[j], cmpmodes); + } + } +} + +static int FULLSCREEN_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + _kernel_swi_regs regs; + regs.r[0] = 19; + + FULLSCREEN_SetDisplayBank(this->hidden->current_bank); + this->hidden->current_bank ^= 1; + FULLSCREEN_SetWriteBank(this->hidden->current_bank); + surface->pixels = this->hidden->bank[this->hidden->current_bank]; + + /* Wait for Vsync */ + _kernel_swi(OS_Byte, ®s, ®s); + + return(0); +} + +/* Nothing to do if we are writing direct to hardware */ +static void FULLSCREEN_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ +} + +/* Safe but slower Memory copy from our allocated back buffer */ +static void FULLSCREEN_UpdateRectsMemCpy(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int row; + int xmult = this->screen->format->BytesPerPixel; + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + rects->x * xmult + rects->y * pitch; + to = this->hidden->bank[1] + rects->x * xmult + rects->y * pitch; + for (row = 0; row < rects->h; row++) + { + SDL_memcpy(to, from, rects->w * xmult); + from += pitch; + to += pitch; + } + rects++; + } +} + +/* Use optimized assembler memory copy. Deliberately copies extra columns if + necessary to ensure the rectangle is word aligned. */ +static void FULLSCREEN_UpdateRects8bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width_bytes; + int src_skip_bytes; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + rects->x + rects->y * pitch; + to = this->hidden->bank[1] + rects->x + rects->y * pitch; + width_bytes = rects->w; + if ((int)from & 3) + { + int extra = ((int)from & 3); + from -= extra; + to -= extra; + width_bytes += extra; + } + if (width_bytes & 3) width_bytes += 4 - (width_bytes & 3); + src_skip_bytes = pitch - width_bytes; + + RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes); + rects++; + } +} + +/* Use optimized assembler memory copy. Deliberately copies extra columns if + necessary to ensure the rectangle is word aligned. */ +static void FULLSCREEN_UpdateRects16bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width_bytes; + int src_skip_bytes; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + (rects->x << 1) + rects->y * pitch; + to = this->hidden->bank[1] + (rects->x << 1) + rects->y * pitch; + width_bytes = (((int)rects->w) << 1); + if ((int)from & 3) + { + from -= 2; + to -= 2; + width_bytes += 2; + } + if (width_bytes & 3) width_bytes += 2; + src_skip_bytes = pitch - width_bytes; + + RISCOS_Put32(to, (width_bytes >> 2), pitch, (int)rects->h, from, src_skip_bytes); + rects++; + } +} + +/* Use optimized assembler memory copy. 32 bpp modes are always word aligned */ +static void FULLSCREEN_UpdateRects32bpp(_THIS, int numrects, SDL_Rect *rects) +{ + int j; + char *to, *from; + int pitch = this->screen->pitch; + int width; + + for (j = 0; j < numrects; j++) + { + from = this->hidden->bank[0] + (rects->x << 2) + rects->y * pitch; + to = this->hidden->bank[1] + (rects->x << 2) + rects->y * pitch; + width = (int)rects->w ; + + RISCOS_Put32(to, width, pitch, (int)rects->h, from, pitch - (width << 2)); + rects++; + } +} + +/* Use operating system sprite plots. Currently this is much slower than the + other variants however accelerated sprite plotting can be seen on the horizon + so this prepares for it. */ +static void FULLSCREEN_UpdateRectsOS(_THIS, int numrects, SDL_Rect *rects) +{ + _kernel_swi_regs regs; + _kernel_oserror *err; + int j; + int y; + + regs.r[0] = 28 + 512; + regs.r[1] = (unsigned int)this->hidden->alloc_bank; + regs.r[2] = (unsigned int)this->hidden->alloc_bank+16; + regs.r[5] = 0; + + for (j = 0; j < numrects; j++) + { + y = this->screen->h - rects->y; /* top of clipping region */ + _kernel_oswrch(24); /* Set graphics clip region */ + _kernel_oswrch((rects->x << this->hidden->xeig) & 0xFF); /* left */ + _kernel_oswrch(((rects->x << this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((y - rects->h) << this->hidden->yeig) & 0xFF); /* bottom */ + _kernel_oswrch((((y - rects->h) << this->hidden->yeig)>> 8) & 0xFF); + _kernel_oswrch(((rects->x + rects->w - 1) << this->hidden->xeig) & 0xFF); /* right */ + _kernel_oswrch((((rects->x + rects->w - 1)<< this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((y-1) << this->hidden->yeig) & 0xFF); /* top */ + _kernel_oswrch((((y-1) << this->hidden->yeig) >> 8) & 0xFF); + + regs.r[3] = 0; + regs.r[4] = 0; + + if ((err = _kernel_swi(OS_SpriteOp, ®s, ®s)) != 0) + { + printf("OS_SpriteOp failed \n%s\n",err->errmess); + } + + rects++; + + /* Reset to full screen clipping */ + _kernel_oswrch(24); /* Set graphics clip region */ + _kernel_oswrch(0); /* left */ + _kernel_oswrch(0); + _kernel_oswrch(0); /* bottom */ + _kernel_oswrch(0); + _kernel_oswrch(((this->screen->w-1) << this->hidden->xeig) & 0xFF); /* right */ + _kernel_oswrch((((this->screen->w-1) << this->hidden->xeig) >> 8) & 0xFF); + _kernel_oswrch(((this->screen->h-1) << this->hidden->yeig) & 0xFF); /* top */ + _kernel_oswrch((((this->screen->h-1) << this->hidden->yeig) >> 8) & 0xFF); + } +} + + +int FULLSCREEN_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + _kernel_swi_regs regs; + int palette[256]; + + regs.r[0] = -1; + regs.r[1] = -1; + regs.r[2] = (int)palette; + regs.r[3] = 1024; + regs.r[4] = 0; + _kernel_swi(ColourTrans_ReadPalette, ®s, ®s); + + while(ncolors--) + { + palette[firstcolor] = ((colors->b) << 24) | ((colors->g) << 16) | ((colors->r) << 8); + firstcolor++; + colors++; + } + + regs.r[0] = -1; + regs.r[1] = -1; + regs.r[2] = (int)palette; + regs.r[3] = 0; + regs.r[4] = 0; + _kernel_swi(ColourTrans_WritePalette, ®s, ®s); + + return(1); +} + + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if(a->w == b->w) + return b->h - a->h; + else + return b->w - a->w; +} + +static int FULLSCREEN_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<SDL_nummodes[index]; ++i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +void FULLSCREEN_SetWriteBank(int bank) +{ + _kernel_swi_regs regs; + regs.r[0] = 112; + regs.r[1] = bank+1; + _kernel_swi(OS_Byte, ®s, ®s); +} + +void FULLSCREEN_SetDisplayBank(int bank) +{ + _kernel_swi_regs regs; + regs.r[0] = 113; + regs.r[1] = bank+1; + _kernel_swi(OS_Byte, ®s, ®s); +} + + +/** Disable special escape key processing */ +static void FULLSCREEN_DisableEscape() +{ + _kernel_swi_regs regs; + regs.r[0] = 229; + regs.r[1] = 1; + regs.r[2] = 0; + _kernel_swi(OS_Byte, ®s, ®s); + +} + +/** Enable special escape key processing */ +static void FULLSCREEN_EnableEscape() +{ + _kernel_swi_regs regs; + regs.r[0] = 229; + regs.r[1] = 0; + regs.r[2] = 0; + _kernel_swi(OS_Byte, ®s, ®s); + +} + +/** Store caption in case this is called before we create a window */ +void FULLSCREEN_SetWMCaption(_THIS, const char *title, const char *icon) +{ + SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title)); +} + +/* Set screen mode +* +* Returns 1 if mode is set ok, otherwise 0 +*/ + +int FULLSCREEN_SetMode(int width, int height, int bpp) +{ + SCREENMODEBLOCK smb; + _kernel_swi_regs regs; + + smb.flags = 1; + smb.x_pixels = width; + smb.y_pixels = height; + smb.mode_vars[0] = -1; + + switch(bpp) + { + case 8: + smb.pixel_depth = 3; + /* Note: Need to set ModeFlags to 128 and NColour variables to 255 get full 8 bit palette */ + smb.mode_vars[0] = 0; smb.mode_vars[1] = 128; /* Mode flags */ + smb.mode_vars[2] = 3; smb.mode_vars[3] = 255; /* NColour (number of colours -1) */ + smb.mode_vars[4] = -1; /* End of list */ + break; + + case 15: + case 16: + smb.pixel_depth = 4; + break; + + case 32: + smb.pixel_depth = 5; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return 0; + break; + } + + smb.frame_rate = -1; + + regs.r[0] = 0; + regs.r[1] = (int)&smb; + + if (_kernel_swi(OS_ScreenMode, ®s, ®s) != 0) + { + SDL_SetError("Couldn't set requested mode"); + return 0; + } + + /* Turn cursor off*/ + _kernel_oswrch(23);_kernel_oswrch(1);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0);_kernel_oswrch(0); + _kernel_oswrch(0);_kernel_oswrch(0); + + return 1; +} + +/* Get Start addresses for the screen banks */ +void FULLSCREEN_SetupBanks(_THIS) +{ + _kernel_swi_regs regs; + int block[5]; + block[0] = 148; /* Write screen start */ + block[1] = 149; /* Display screen start */ + block[2] = 4; /* X eig factor */ + block[3] = 5; /* Y eig factor */ + block[4] = -1; /* End of list of variables to request */ + + regs.r[0] = (int)block; + regs.r[1] = (int)block; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + + this->hidden->bank[0] = (void *)block[0]; + this->hidden->bank[1] = (void *)block[1]; + this->hidden->xeig = block[2]; + this->hidden->yeig = block[3]; +} + +/* Toggle to full screen mode from the WIMP */ + +int FULLSCREEN_ToggleFromWimp(_THIS) +{ + int width = this->screen->w; + int height = this->screen->h; + int bpp = this->screen->format->BitsPerPixel; + + RISCOS_StoreWimpMode(); + if (FULLSCREEN_SetMode(width, height, bpp)) + { + char *buffer = this->hidden->alloc_bank; /* This is start of sprite data */ + /* Support back buffer mode only */ + if (riscos_backbuffer == 0) riscos_backbuffer = 1; + + FULLSCREEN_SetupBanks(this); + + this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->current_bank = 0; + this->screen->pixels = this->hidden->bank[0]; + + /* Copy back buffer to screen memory */ + SDL_memcpy(this->hidden->bank[1], this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel); + + FULLSCREEN_SetDeviceMode(this); + return 1; + } else + RISCOS_RestoreWimpMode(); + + return 0; +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c b/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c new file mode 100644 index 0000000..5487507 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosevents.c @@ -0,0 +1,549 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements keyboard setup, event pump and keyboard and mouse polling +*/ + + +#include "SDL.h" +#include "../../timer/SDL_timer_c.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" + +#include "memory.h" +#include "stdlib.h" +#include "ctype.h" + +#include "kernel.h" +#include "swis.h" + +/* The translation table from a RISC OS internal key numbers to a SDL keysym */ +static SDLKey RO_keymap[SDLK_LAST]; + +/* RISC OS Key codes */ +#define ROKEY_SHIFT 0 +#define ROKEY_CTRL 1 +#define ROKEY_ALT 2 +/* Left shift is first key we will check for */ +#define ROKEY_LEFT_SHIFT 3 + +/* Need to ignore mouse buttons as they are processed separately */ +#define ROKEY_LEFT_MOUSE 9 +#define ROKEY_CENTRE_MOUSE 10 +#define ROKEY_RIGHT_MOUSE 11 + +/* No key has been pressed return value*/ +#define ROKEY_NONE 255 + +/* Id of last key in keyboard */ +#define ROKEY_LAST_KEY 124 + +/* Size of array for all keys */ +#define ROKEYBD_ARRAYSIZE 125 + +static char RO_pressed[ROKEYBD_ARRAYSIZE]; + +static SDL_keysym *TranslateKey(int intkey, SDL_keysym *keysym, int pressed); + +void RISCOS_PollMouse(_THIS); +void RISCOS_PollKeyboard(); + +void RISCOS_PollMouseHelper(_THIS, int fullscreen); + +#if SDL_THREADS_DISABLED +extern void DRenderer_FillBuffers(); + +/* Timer running function */ +extern void RISCOS_CheckTimer(); + +#endif + +void FULLSCREEN_PumpEvents(_THIS) +{ + /* Current implementation requires keyboard and mouse polling */ + RISCOS_PollKeyboard(); + RISCOS_PollMouse(this); +#if SDL_THREADS_DISABLED +// DRenderer_FillBuffers(); + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} + + +void RISCOS_InitOSKeymap(_THIS) +{ + int i; + + /* Map the VK keysyms */ + for ( i=0; i<SDL_arraysize(RO_keymap); ++i ) + RO_keymap[i] = SDLK_UNKNOWN; + + RO_keymap[3] = SDLK_LSHIFT; + RO_keymap[4] = SDLK_LCTRL; + RO_keymap[5] = SDLK_LALT; + RO_keymap[6] = SDLK_RSHIFT; + RO_keymap[7] = SDLK_RCTRL; + RO_keymap[8] = SDLK_RALT; + RO_keymap[16] = SDLK_q; + RO_keymap[17] = SDLK_3; + RO_keymap[18] = SDLK_4; + RO_keymap[19] = SDLK_5; + RO_keymap[20] = SDLK_F4; + RO_keymap[21] = SDLK_8; + RO_keymap[22] = SDLK_F7; + RO_keymap[23] = SDLK_MINUS, + RO_keymap[25] = SDLK_LEFT; + RO_keymap[26] = SDLK_KP6; + RO_keymap[27] = SDLK_KP7; + RO_keymap[28] = SDLK_F11; + RO_keymap[29] = SDLK_F12; + RO_keymap[30] = SDLK_F10; + RO_keymap[31] = SDLK_SCROLLOCK; + RO_keymap[32] = SDLK_PRINT; + RO_keymap[33] = SDLK_w; + RO_keymap[34] = SDLK_e; + RO_keymap[35] = SDLK_t; + RO_keymap[36] = SDLK_7; + RO_keymap[37] = SDLK_i; + RO_keymap[38] = SDLK_9; + RO_keymap[39] = SDLK_0; + RO_keymap[41] = SDLK_DOWN; + RO_keymap[42] = SDLK_KP8; + RO_keymap[43] = SDLK_KP9; + RO_keymap[44] = SDLK_BREAK; + RO_keymap[45] = SDLK_BACKQUOTE; +/* RO_keymap[46] = SDLK_currency; TODO: Figure out if this has a value */ + RO_keymap[47] = SDLK_BACKSPACE; + RO_keymap[48] = SDLK_1; + RO_keymap[49] = SDLK_2; + RO_keymap[50] = SDLK_d; + RO_keymap[51] = SDLK_r; + RO_keymap[52] = SDLK_6; + RO_keymap[53] = SDLK_u; + RO_keymap[54] = SDLK_o; + RO_keymap[55] = SDLK_p; + RO_keymap[56] = SDLK_LEFTBRACKET; + RO_keymap[57] = SDLK_UP; + RO_keymap[58] = SDLK_KP_PLUS; + RO_keymap[59] = SDLK_KP_MINUS; + RO_keymap[60] = SDLK_KP_ENTER; + RO_keymap[61] = SDLK_INSERT; + RO_keymap[62] = SDLK_HOME; + RO_keymap[63] = SDLK_PAGEUP; + RO_keymap[64] = SDLK_CAPSLOCK; + RO_keymap[65] = SDLK_a; + RO_keymap[66] = SDLK_x; + RO_keymap[67] = SDLK_f; + RO_keymap[68] = SDLK_y; + RO_keymap[69] = SDLK_j; + RO_keymap[70] = SDLK_k; + RO_keymap[72] = SDLK_SEMICOLON; + RO_keymap[73] = SDLK_RETURN; + RO_keymap[74] = SDLK_KP_DIVIDE; + RO_keymap[76] = SDLK_KP_PERIOD; + RO_keymap[77] = SDLK_NUMLOCK; + RO_keymap[78] = SDLK_PAGEDOWN; + RO_keymap[79] = SDLK_QUOTE; + RO_keymap[81] = SDLK_s; + RO_keymap[82] = SDLK_c; + RO_keymap[83] = SDLK_g; + RO_keymap[84] = SDLK_h; + RO_keymap[85] = SDLK_n; + RO_keymap[86] = SDLK_l; + RO_keymap[87] = SDLK_SEMICOLON; + RO_keymap[88] = SDLK_RIGHTBRACKET; + RO_keymap[89] = SDLK_DELETE; + RO_keymap[90] = SDLK_KP_MINUS; + RO_keymap[91] = SDLK_KP_MULTIPLY; + RO_keymap[93] = SDLK_EQUALS; + RO_keymap[94] = SDLK_BACKSLASH; + RO_keymap[96] = SDLK_TAB; + RO_keymap[97] = SDLK_z; + RO_keymap[98] = SDLK_SPACE; + RO_keymap[99] = SDLK_v; + RO_keymap[100] = SDLK_b; + RO_keymap[101] = SDLK_m; + RO_keymap[102] = SDLK_COMMA; + RO_keymap[103] = SDLK_PERIOD; + RO_keymap[104] = SDLK_SLASH; + RO_keymap[105] = SDLK_END; + RO_keymap[106] = SDLK_KP0; + RO_keymap[107] = SDLK_KP1; + RO_keymap[108] = SDLK_KP3; + RO_keymap[112] = SDLK_ESCAPE; + RO_keymap[113] = SDLK_F1; + RO_keymap[114] = SDLK_F2; + RO_keymap[115] = SDLK_F3; + RO_keymap[116] = SDLK_F5; + RO_keymap[117] = SDLK_F6; + RO_keymap[118] = SDLK_F8; + RO_keymap[119] = SDLK_F9; + RO_keymap[120] = SDLK_HASH; + RO_keymap[121] = SDLK_RIGHT; + RO_keymap[122] = SDLK_KP4; + RO_keymap[123] = SDLK_KP5; + RO_keymap[124] = SDLK_KP2; + + SDL_memset(RO_pressed, 0, ROKEYBD_ARRAYSIZE); +} + + +/* Variable for mouse relative processing */ +int mouse_relative = 0; + +/* Check to see if we need to enter or leave mouse relative mode */ + +void RISCOS_CheckMouseMode(_THIS) +{ + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +} + + +void RISCOS_PollMouse(_THIS) +{ + RISCOS_PollMouseHelper(this, 1); +} + +extern int mouseInWindow; + +void WIMP_PollMouse(_THIS) +{ + /* Only poll when mouse is over the window */ + if (!mouseInWindow) return; + + RISCOS_PollMouseHelper(this, 0); +} + +/* Static variables so only changes are reported */ +static Sint16 last_x = -1, last_y = -1; +static int last_buttons = 0; + +/* Share routine between WIMP and FULLSCREEN for polling mouse and + passing on events */ +void RISCOS_PollMouseHelper(_THIS, int fullscreen) +{ + _kernel_swi_regs regs; + static int starting = 1; + + if (_kernel_swi(OS_Mouse, ®s, ®s) == NULL) + { + Sint16 new_x = regs.r[0]; /* Initialy get as OS units */ + Sint16 new_y = regs.r[1]; + + /* Discard mouse events until they let go of the mouse after starting */ + if (starting && regs.r[2] != 0) + return; + else + starting = 0; + + if (new_x != last_x || new_y != last_y || last_buttons != regs.r[2]) + { + /* Something changed so generate appropriate events */ + int topLeftX, topLeftY; /* Top left OS units */ + int x, y; /* Mouse position in SDL pixels */ + + if (fullscreen) + { + topLeftX = 0; + topLeftY = (this->hidden->height << this->hidden->yeig) - 1; + } else + { + int window_state[9]; + + /* Get current window state */ + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + topLeftX = window_state[1]; + topLeftY = window_state[4]; + } + + /* Convert co-ordinates to workspace */ + x = new_x - topLeftX; + y = topLeftY - new_y; /* Y goes from top of window/screen */ + + /* Convert OS units to pixels */ + x >>= this->hidden->xeig; + y >>= this->hidden->yeig; + + if (last_x != new_x || last_y != new_y) + { + if (mouse_relative) + { + int centre_x = SDL_VideoSurface->w/2; + int centre_y = SDL_VideoSurface->h/2; + + if (centre_x != x || centre_y != y) + { + if (SDL_VideoSurface) SDL_PrivateMouseMotion(0,1,x - centre_x, y - centre_y); + last_x = topLeftX + (centre_x << this->hidden->xeig); + last_y = topLeftY - (centre_y << this->hidden->yeig); + + /* Re-centre the mouse pointer, so we still get relative + movement when the mouse is at the edge of the window + or screen. + */ + { + unsigned char block[5]; + + block[0] = 3; /* OSWORD move pointer sub-reason code */ + block[1] = last_x & 0xFF; + block[2] = (last_x >> 8) & 0xFF; + block[3] = last_y & 0xFF; + block[4] = (last_y >> 8) & 0xFF; + + regs.r[0] = 21; /* OSWORD pointer stuff code */ + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + } + } + } else + { + last_x = new_x; + last_y = new_y; + SDL_PrivateMouseMotion(0,0,x,y); + } + } + + if (last_buttons != regs.r[2]) + { + int changed = last_buttons ^ regs.r[2]; + last_buttons = regs.r[2]; + if (changed & 4) SDL_PrivateMouseButton((last_buttons & 4) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + if (changed & 2) SDL_PrivateMouseButton((last_buttons & 2) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + if (changed & 1) SDL_PrivateMouseButton((last_buttons & 1) ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + } + } + } +} + +void RISCOS_PollKeyboard() +{ + int which_key = ROKEY_LEFT_SHIFT; + int j; + int min_key, max_key; + SDL_keysym key; + + /* Scan the keyboard to see what is pressed */ + while (which_key <= ROKEY_LAST_KEY) + { + which_key = (_kernel_osbyte(121, which_key, 0) & 0xFF); + if (which_key != ROKEY_NONE) + { + switch(which_key) + { + /* Skip over mouse keys */ + case ROKEY_LEFT_MOUSE: + case ROKEY_CENTRE_MOUSE: + case ROKEY_RIGHT_MOUSE: + which_key = ROKEY_RIGHT_MOUSE; + break; + + /* Ignore keys that cause 2 internal number to be generated */ + case 71: case 24: case 87: case 40: + break; + + /* Ignore break as it can be latched on */ + case 44: + break; + + default: + RO_pressed[which_key] += 2; + break; + } + which_key++; + } + } + + /* Generate key released messages */ + min_key = ROKEY_LAST_KEY+1; + max_key = ROKEY_LEFT_SHIFT; + + for (j = ROKEY_LEFT_SHIFT; j <= ROKEY_LAST_KEY; j++) + { + if (RO_pressed[j]) + { + if (RO_pressed[j] == 1) + { + RO_pressed[j] = 0; + SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(j,&key,0)); + } else + { + if (j < min_key) min_key = j; + if (j > max_key) max_key = j; + } + } + } + + /* Generate key pressed messages */ + for (j = min_key; j <= max_key; j++) + { + if (RO_pressed[j]) + { + if (RO_pressed[j] == 2) + { + SDL_PrivateKeyboard(SDL_PRESSED,TranslateKey(j,&key,1)); + } + RO_pressed[j] = 1; + } + } +} + +static SDL_keysym *TranslateKey(int intkey, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char) intkey; + keysym->sym = RO_keymap[intkey]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) + { + int state; + int ch; + + state = (_kernel_osbyte(202, 0, 255) & 0xFF); + + /*TODO: Take into account other keyboard layouts */ + + ch = keysym->sym; /* This should handle most unshifted keys */ + + if (intkey < 9 || ch == SDLK_UNKNOWN) + { + ch = 0; + + } else if (state & 64) /* Control on */ + { + ch = ch & 31; + + } else + { + int topOfKey = 0; + if (state & 8) /* Shift on */ + { + topOfKey = 1; + } + + if ((state & 16) == 0) /* Caps lock is on */ + { + if (ch >= SDLK_a && ch <= SDLK_z) + { + if ((state & 128) == 0) /* Shift Enable off */ + { + /* All letter become upper case */ + topOfKey = 1; + } else + { + /* Shift+Letters gives lower case */ + topOfKey = 1 - topOfKey; + } + } + } + + if (topOfKey) + { + /* Key produced with shift held down */ + + /* Letters just give upper case version */ + if (ch >= SDLK_a && ch <= SDLK_z) ch = toupper(ch); + else + { + switch(ch) + { + case SDLK_HASH: ch = '~'; break; + case SDLK_QUOTE: ch = '@'; break; + case SDLK_COMMA: ch = '<'; break; + case SDLK_MINUS: ch = '_'; break; + case SDLK_PERIOD: ch = '>'; break; + case SDLK_SLASH: ch = '?'; break; + + case SDLK_0: ch = ')'; break; + case SDLK_1: ch = '!'; break; + case SDLK_2: ch = '"'; break; + case SDLK_3: ch = ''; break; + case SDLK_4: ch = '$'; break; + case SDLK_5: ch = '%'; break; + case SDLK_6: ch = '^'; break; + case SDLK_7: ch = '&'; break; + case SDLK_8: ch = '*'; break; + case SDLK_9: ch = '('; break; + + case SDLK_SEMICOLON: ch = ':'; break; + case SDLK_EQUALS: ch = '+'; break; + case SDLK_LEFTBRACKET: ch = '{'; break; + case SDLK_BACKSLASH: ch = '|'; break; + case SDLK_RIGHTBRACKET: ch = '}'; break; + case SDLK_BACKQUOTE: ch = ''; break; + + default: + ch = 0; /* Map to zero character if we don't understand it */ + break; + } + } + + } else if (ch > 126) + { + /* SDL key code < 126 map directly onto their Unicode equivalents */ + /* Keypad 0 to 9 maps to numeric equivalent */ + if (ch >= SDLK_KP0 && ch <= SDLK_KP9) ch = ch - SDLK_KP0 + '0'; + else + { + /* Following switch maps other keys that produce an Ascii value */ + switch(ch) + { + case SDLK_KP_PERIOD: ch = '.'; break; + case SDLK_KP_DIVIDE: ch = '/'; break; + case SDLK_KP_MULTIPLY: ch = '*'; break; + case SDLK_KP_MINUS: ch = '-'; break; + case SDLK_KP_PLUS: ch = '+'; break; + case SDLK_KP_EQUALS: ch = '='; break; + + default: + /* If we don't know what it is set the Unicode to 0 */ + ch = 0; + break; + } + } + } + } + + keysym->unicode = ch; + } + return(keysym); +} + +/* end of SDL_riscosevents.c ... */ + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h b/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h new file mode 100644 index 0000000..189b3c0 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosevents_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_riscosvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void RISCOS_InitOSKeymap(_THIS); +extern void FULLSCREEN_PumpEvents(_THIS); +extern void WIMP_PumpEvents(_THIS); + +/* end of SDL_nullevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c new file mode 100644 index 0000000..b4a0bff --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse.c @@ -0,0 +1,371 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements mouse cursor shape definitions and positioning +*/ + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +static WMcursor *current_cursor = NULL; +static WMcursor *defined_cursor = NULL; + +extern int mouseInWindow; + +/* Area to save cursor palette colours changed by SDL. + Actual values will be read before we change to the SDL cursor */ +static Uint8 wimp_cursor_palette[2][5] = { + {1, 25, 255, 255, 255}, + {3, 25, 255, 255, 255} +}; + +static int cursor_palette_saved = 0; + +void WIMP_SaveCursorPalette(); +void WIMP_RestoreWimpCursor(); +void WIMP_SetSDLCursorPalette(); + + +void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor) +{ + SDL_free(cursor->data); + SDL_free(cursor); +} + +WMcursor *RISCOS_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + Uint8 *cursor_data; + Uint8 *ptr; + int i,j,k; + int data_byte, mask_byte; + + /* Check to make sure the cursor size is okay */ + if ( (w > 32) || (h > 32) ) { + SDL_SetError("Only with width and height <= 32 pixels are allowed"); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor == NULL ) { + SDL_SetError("Out of memory"); + return(NULL); + } + + /* Note: SDL says width must be a multiple of 8 */ + cursor_data = SDL_malloc(w/4 * h); + if (cursor_data == NULL) + { + SDL_free(cursor); + SDL_SetError("Out of memory"); + return(NULL); + } + + cursor->w = w; + cursor->h = h; + cursor->hot_x = hot_x; + cursor->hot_y = hot_y; + cursor->data = cursor_data; + + +/* Data / Mask Resulting pixel on screen + 0 / 1 White + 1 / 1 Black + 0 / 0 Transparent + 1 / 0 Inverted color if possible, black if not. +*/ + ptr = cursor_data; + + for ( i=0; i<h; ++i ) + { + for (j = 0; j < w/8; ++j) + { + data_byte = *data; + mask_byte = *mask; + *ptr++ = 0; /* Sets whole byte transparent */ + *ptr = 0; + for (k = 0; k < 8; k++) + { + (*ptr) <<= 2; + if (data_byte & 1) *ptr |= 3; /* Black or inverted */ + else if(mask_byte & 1) *ptr |= 1; /* White */ + if ((k&3) == 3) ptr--; + data_byte >>= 1; + mask_byte >>= 1; + } + + ptr+=3; + data++; + mask++; + } + } + + return(cursor); +} + +int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor) +{ + current_cursor = cursor; + + if (cursor == NULL) + { + _kernel_osbyte(106,0,0); + defined_cursor = NULL; + } else + { + WMcursor *old_cursor = defined_cursor; + + if (cursor != defined_cursor) + { + Uint8 cursor_def[10]; + + cursor_def[0] = 0; + cursor_def[1] = 2; /* Use shape number 2 */ + cursor_def[2] = cursor->w/4; /* Width in bytes */ + cursor_def[3] = cursor->h; /* Height (h) in pixels */ + cursor_def[4] = cursor->hot_x; /* ActiveX in pixels from left */ + cursor_def[5] = cursor->hot_y; /* ActiveY in pixels from top */ + cursor_def[6] = ((int)(cursor->data) & 0xFF); /* Least significant byte of pointer to data */ + cursor_def[7] = ((int)(cursor->data) >> 8) & 0xFF; /* ... */ + cursor_def[8] = ((int)(cursor->data) >> 16) & 0xFF; /* ... */ + cursor_def[9] = ((int)(cursor->data) >> 24) & 0xFF; /* Most significant byte of pointer to data */ + + if (_kernel_osword(21, (int *)cursor_def) != 0) + { + SDL_SetError("RISCOS couldn't create the cursor to show"); + return(0); + } + defined_cursor = cursor; + } + + if (old_cursor == NULL) + { + /* First time or reshow in window, so save/setup palette */ + if (!cursor_palette_saved) + { + WIMP_SaveCursorPalette(); + } + WIMP_SetSDLCursorPalette(); + } + + _kernel_osbyte(106, 2, 0); + } + + return(1); +} + +void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + Uint8 move_block[5]; + int eig_block[3]; + _kernel_swi_regs regs; + int os_x, os_y; + + eig_block[0] = 4; /* X eig factor */ + eig_block[1] = 5; /* Y eig factor */ + eig_block[2] = -1; /* End of list of variables to request */ + + regs.r[0] = (int)eig_block; + regs.r[1] = (int)eig_block; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + + os_x = x << eig_block[0]; + os_y = y << eig_block[1]; + + move_block[0] = 3; /* Move cursor */ + move_block[1] = os_x & 0xFF; + move_block[2] = (os_x >> 8) & 0xFF; + move_block[3] = os_y & 0xFF; + move_block[4] = (os_y >> 8) & 0xFF; + + _kernel_osword(21, (int *)move_block); + SDL_PrivateMouseMotion(0, 0, x, y); +} + + +/* Reshow cursor when mouse re-enters the window */ +void WIMP_ReshowCursor(_THIS) +{ + defined_cursor = NULL; + cursor_palette_saved = 0; + RISCOS_ShowWMCursor(this, current_cursor); +} + +void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + _kernel_swi_regs regs; + int window_state[9]; + char block[5]; + int osX, osY; + + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + osX = (x << this->hidden->xeig) + window_state[1]; + osY = window_state[4] - (y << this->hidden->yeig); + + block[0] = 3; + block[1] = osX & 0xFF; + block[2] = (osX >> 8) & 0xFF; + block[3] = osY & 0xFF; + block[4] = (osY >> 8) & 0xFF; + + regs.r[0] = 21; + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + SDL_PrivateMouseMotion(0, 0, x, y); +} + +int WIMP_ShowWMCursor(_THIS, WMcursor *cursor) +{ + if (mouseInWindow) return RISCOS_ShowWMCursor(this, cursor); + else current_cursor = cursor; + + return 1; +} + +SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode) +{ + /* In fullscreen mode we don't need to do anything */ + if (mode < SDL_GRAB_FULLSCREEN) + { + _kernel_swi_regs regs; + unsigned char block[9]; + block[0] = 1; /* Define mouse cursor bounding block */ + + if ( mode == SDL_GRAB_OFF ) + { + /* Clip to whole screen */ + + int r = (this->hidden->screen_width << this->hidden->xeig) - 1; + int t = (this->hidden->screen_height << this->hidden->yeig) - 1; + + block[1] = 0; block[2] = 0; /* Left*/ + block[3] = 0; block[4] = 0; /* Bottom */ + block[5] = r & 0xFF; block[6] = (r >> 8) & 0xFF; /* Right */ + block[7] = t & 0xFF; block[8] = (t >> 8) & 0xFF; /* Top */ + } else + { + /* Clip to window */ + unsigned char window_state[36]; + + *((int *)window_state) = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + block[1] = window_state[4]; + block[2] = window_state[5]; + block[3] = window_state[8]; + block[4] = window_state[9]; + block[5] = window_state[12]; + block[6] = window_state[13]; + block[7] = window_state[16]; + block[8] = window_state[17]; + + } + + regs.r[0] = 21; /* OS word code */ + regs.r[1] = (int)block; + _kernel_swi(OS_Word, ®s, ®s); + } + + return mode; +} + +/* Save mouse cursor palette to be restore when we are no longer + defining a cursor */ + +void WIMP_SaveCursorPalette() +{ + _kernel_swi_regs regs; + int colour; + + for (colour = 0; colour < 2; colour++) + { + regs.r[0] = (int)wimp_cursor_palette[colour][0]; + regs.r[1] = 25; + /* Read settings with OS_ReadPalette */ + if (_kernel_swi(0x2f, ®s, ®s) == NULL) + { + wimp_cursor_palette[colour][2] = (unsigned char)((regs.r[2] >> 8) & 0xFF); + wimp_cursor_palette[colour][3] = (unsigned char)((regs.r[2] >> 16) & 0xFF); + wimp_cursor_palette[colour][4] = (unsigned char)((regs.r[2] >> 24) & 0xFF); + } + } + + cursor_palette_saved = 1; +} + +/* Restore the WIMP's cursor when we leave the SDL window */ +void WIMP_RestoreWimpCursor() +{ + int colour; + + /* Reset to pointer shape 1 */ + _kernel_osbyte(106, 1, 0); + + /* Reset pointer colours */ + if (cursor_palette_saved) + { + for (colour = 0; colour < 2; colour++) + { + _kernel_osword(12, (int *)wimp_cursor_palette[colour]); + } + } + cursor_palette_saved = 0; +} + +/* Set palette used for SDL mouse cursors */ +void WIMP_SetSDLCursorPalette() +{ + /* First time set up the mouse colours */ + Uint8 block[5]; + + /* Set up colour 1 as white */ + block[0] = 1; /* Colour to change 1 - 3 */ + block[1] = 25; /* Set pointer colour */ + block[2] = 255; /* red component*/ + block[3] = 255; /* green component */ + block[4] = 255; /* blue component*/ + _kernel_osword(12, (int *)block); + + /* Set colour 3 to back */ + block[0] = 3; /* Colour to change 1 - 3 */ + block[1] = 25; /* Set pointer colour*/ + block[2] = 0; /* red component*/ + block[3] = 0; /* green component */ + block[4] = 0; /* blue component*/ + _kernel_osword(12, (int *)block); +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h new file mode 100644 index 0000000..9019cb4 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosmouse_c.h @@ -0,0 +1,44 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_riscosvideo.h" + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int w; + int h; + int hot_x; + int hot_y; + Uint8 *data; +}; + +/* Functions to be exported */ +void RISCOS_FreeWMCursor(_THIS, WMcursor *cursor); +WMcursor *RISCOS_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); + +int RISCOS_ShowWMCursor(_THIS, WMcursor *cursor); +void FULLSCREEN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + +int WIMP_ShowWMCursor(_THIS, WMcursor *cursor); +void WIMP_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c b/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c new file mode 100644 index 0000000..70b2f91 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscossprite.c @@ -0,0 +1,265 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements Sprite plotting code for wimp display.window +*/ + +#include "kernel.h" +#include "swis.h" + +#include "SDL_stdinc.h" +#include "SDL_riscosvideo.h" + +extern void WIMP_ReadModeInfo(_THIS); + +void WIMP_PaletteChanged(_THIS); + + +/* Create sprite buffer for screen */ + +unsigned char *WIMP_CreateBuffer(int width, int height, int bpp) +{ + int size; + char sprite_name[12] = "display"; + unsigned char *buffer; + _kernel_swi_regs regs; + int bytesPerPixel; + int bytesPerRow; + int offsetToSpriteData = 60; + + switch(bpp) + { + case 32: bytesPerPixel = 4; break; + case 16: bytesPerPixel = 2; break; + case 8: + bytesPerPixel = 1; + offsetToSpriteData += 2048; /* Add in size of palette */ + break; + default: + return NULL; + break; + } + + bytesPerRow = bytesPerPixel * width; + + if ((bytesPerRow & 3) != 0) + { + bytesPerRow += 4 - (bytesPerRow & 3); + } + size = bytesPerRow * height; + + buffer = SDL_malloc( (size_t) size + offsetToSpriteData ); + if (!buffer) return NULL; + + /* Initialise a sprite area */ + + *(unsigned int *)buffer = size + offsetToSpriteData; + *(unsigned int *)(buffer + 8) = 16; + + regs.r[0] = 256+9; + regs.r[1] = (unsigned int)buffer; + _kernel_swi(OS_SpriteOp, ®s, ®s); + + regs.r[0] = 256+15; + regs.r[1] = (unsigned int)buffer; + regs.r[2] = (unsigned int)&sprite_name; + regs.r[3] = 0; /* Palette flag: 0 = no palette */ + regs.r[4] = width; + regs.r[5] = height; + if (bpp == 8) + { + /* Use old style mode number */ + regs.r[6] = 28; /* 8bpp 90x90dpi */ + } else + { + regs.r[6] = (((bpp == 16) ? 5 : 6) << 27) /* Type 6 = 32bpp sprite, 5 = 16bpp sprite */ + | (90 << 14) /* Vertical dpi */ + | (90 << 1) /* Horizontal dpi */ + | 1; /* Marker to distinguish between mode selectors and sprite modes */ + } + if (_kernel_swi(OS_SpriteOp, ®s, ®s) == NULL) + { + if (bpp == 8) + { + /* Modify sprite to take into account 256 colour palette */ + int *sprite = (int *)(buffer + 16); + /* Adjust sprite offsets */ + sprite[0] += 2048; + sprite[8] += 2048; + sprite[9] += 2048; + /* Adjust sprite area next free pointer */ + (*(int *)(buffer+12)) += 2048; + + /* Don't need to set up palette as SDL sets up the default + 256 colour palette */ +/* { + int *pal = sprite + 11; + unsigned int j; + unsigned int entry; + for (j = 0; j < 255; j++) + { + entry = (j << 24) | (j << 16) | (j << 8); + *pal++ = entry; + *pal++ = entry; + } + } +*/ + } + } else + { + SDL_free(buffer); + buffer = NULL; + } + + return buffer; +} + + +/* Setup translation buffers for the sprite plotting */ + +void WIMP_SetupPlotInfo(_THIS) +{ + _kernel_swi_regs regs; + int *sprite = ((int *)this->hidden->bank[1])+4; + + regs.r[0] = (unsigned int)this->hidden->bank[1]; + regs.r[1] = (unsigned int)sprite; + regs.r[2] = -1; /* Current mode */ + regs.r[3] = -1; /* Current palette */ + regs.r[4] = 0; /* Get size of buffer */ + regs.r[5] = 1|2|16; /* R1 - pointer to sprite and can use full palette words */ + regs.r[6] = 0; + regs.r[7] = 0; + + if (this->hidden->pixtrans) SDL_free(this->hidden->pixtrans); + this->hidden->pixtrans = 0; + + /* Get the size required for the buffer */ + _kernel_swi(ColourTrans_GenerateTable, ®s, ®s); + if (regs.r[4]) + { + this->hidden->pixtrans = SDL_malloc(regs.r[4]); + + regs.r[4] = (unsigned int)this->hidden->pixtrans; + /* Actually read the buffer */ + _kernel_swi(ColourTrans_GenerateTable, ®s, ®s); + } +} + +/* Plot the sprite in the given context */ +void WIMP_PlotSprite(_THIS, int x, int y) +{ + _kernel_swi_regs regs; + _kernel_oserror *err; + + regs.r[0] = 52 + 512; + regs.r[1] = (unsigned int)this->hidden->bank[1]; + regs.r[2] = (unsigned int)this->hidden->bank[1]+16; + regs.r[3] = x; + regs.r[4] = y; + regs.r[5] = 0|32; /* Overwrite screen and pixtrans contains wide colour entries */ + regs.r[6] = 0; /* No scale factors i.e. 1:1 */ + regs.r[7] = (int)this->hidden->pixtrans; + + if ((err = _kernel_swi(OS_SpriteOp, ®s, ®s)) != 0) + { + int *p = (int *)this->hidden->pixtrans; + printf("OS_SpriteOp failed \n%s\n",err->errmess); + printf("pixtrans %d\n", (int)this->hidden->pixtrans); + printf("%x %x %x\n", p[0], p[1], p[2]); + } +} + + +/* Wimp mode has changes so update colour mapping and pixel sizes + of windows and the sprites they plot */ + +void WIMP_ModeChanged(_THIS) +{ + int oldXeig = this->hidden->xeig; + int oldYeig = this->hidden->yeig; + + WIMP_ReadModeInfo(this); + + if (oldXeig == this->hidden->xeig && oldYeig == this->hidden->yeig) + { + /* Only need to update the palette */ + WIMP_PaletteChanged(this); + } else + { + _kernel_swi_regs regs; + int window_state[9]; + int extent[4]; + int currWidth, currHeight; + int newWidth, newHeight; + + /* Need to resize windows and update the palette */ + WIMP_SetupPlotInfo(this); + + + window_state[0] = this->hidden->window_handle; + regs.r[1] = (unsigned int)window_state; + _kernel_swi(Wimp_GetWindowState, ®s, ®s); + + currWidth = window_state[3] - window_state[1]; + currHeight = window_state[4] - window_state[2]; + + newWidth = (currWidth >> oldXeig) << this->hidden->xeig; + newHeight = (currHeight >> oldYeig) << this->hidden->yeig; + /* Need to avoid extent getting too small for visible part + of window */ + extent[0] = 0; + if (currHeight <= newHeight) + { + extent[1] = -newHeight; + } else + { + extent[1] = -currHeight; + } + if (currWidth <= newWidth) + { + extent[2] = newWidth; + } else + { + extent[2] = currWidth; + } + extent[3] = 0; + + regs.r[0] = this->hidden->window_handle; + regs.r[1] = (int)extent; + _kernel_swi(Wimp_SetExtent, ®s, ®s); + + /*TODO: May need to set flag to resize window on next open */ + } +} + +/* Palette has changed so update palettes used for windows sprites */ + +void WIMP_PaletteChanged(_THIS) +{ + WIMP_SetupPlotInfo(this); +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscostask.c b/3rdparty/SDL/src/video/riscos/SDL_riscostask.c new file mode 100644 index 0000000..67dc3e2 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscostask.c @@ -0,0 +1,350 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS + 26 March 2003 + + File includes routines for: + Setting up as a WIMP Task + Reading information about the current desktop + Storing information before a switch to full screen + Restoring desktop after switching to full screen +*/ + +#include "kernel.h" +#include "swis.h" + +#include "SDL_stdinc.h" +#include "SDL_riscostask.h" + +#if !SDL_THREADS_DISABLED +#include <pthread.h> +pthread_t main_thread; +#endif + +/* RISC OS variables */ + +static int task_handle = 0; +static int wimp_version = 0; + +/* RISC OS variables to help compatability with certain programs */ +int riscos_backbuffer = 0; /* Create a back buffer in system memory for full screen mode */ +int riscos_closeaction = 1; /* Close icon action */ + +static int stored_mode = -1; /* -1 when in desktop, mode number or pointer when full screen */ + +extern int mouseInWindow; /* Mouse is in WIMP window */ + +/* Local function */ + +static int RISCOS_GetTaskName(char *task_name, size_t maxlen); + +/* Uncomment next line to copy mode changes/restores to stderr */ +/* #define DUMP_MODE */ +#ifdef DUMP_MODE +#include "stdio.h" +static void dump_mode() +{ + fprintf(stderr, "mode %d\n", stored_mode); + if (stored_mode < -1 || stored_mode >= 256) + { + int blockSize = 0; + int *storeBlock = (int *)stored_mode; + + while(blockSize < 5 || storeBlock[blockSize] != -1) + { + fprintf(stderr, " %d\n", storeBlock[blockSize++]); + } + } +} +#endif + +/****************************************************************** + + Initialise as RISC OS Wimp task + +*******************************************************************/ + +int RISCOS_InitTask() +{ + char task_name[32]; + _kernel_swi_regs regs; + int messages[4]; + + if (RISCOS_GetTaskName(task_name, SDL_arraysize(task_name)) == 0) return 0; + + messages[0] = 9; /* Palette changed */ + messages[1] = 0x400c1; /* Mode changed */ + messages[2] = 8; /* Pre quit */ + messages[2] = 0; + + regs.r[0] = (unsigned int)360; /* Minimum version 3.6 */ + regs.r[1] = (unsigned int)0x4b534154; + regs.r[2] = (unsigned int)task_name; + regs.r[3] = (unsigned int)messages; + + if (_kernel_swi(Wimp_Initialise, ®s, ®s) == 0) + { + wimp_version = regs.r[0]; + task_handle = regs.r[1]; + return 1; + } + +#if !SDL_THREADS_DISABLED + main_thread = pthread_self(); +#endif + + return 0; +} + +/********************************************************************* + + Close down application on exit. + +**********************************************************************/ + +void RISCOS_ExitTask() +{ + _kernel_swi_regs regs; + + if (stored_mode == -1) + { + /* Ensure cursor is put back to standard pointer shape if + we have been running in a window */ + _kernel_osbyte(106,1,0); + } + + /* Ensure we end up back in the wimp */ + RISCOS_RestoreWimpMode(); + + /* Neatly exit the task */ + regs.r[0] = task_handle; + regs.r[1] = (unsigned int)0x4b534154; + _kernel_swi(Wimp_CloseDown, ®s, ®s); + task_handle = 0; +} + +/************************************************************************** + + Get the name of the task for the desktop. + + Param: task_name - name of task 32 characters. + + Returns: 1 is successful, otherwise 0 + + Notes: Works by getting using OS_GetEnv to get the command line + used to run the program and then parsing a name from it + as follows. + + 1. Use name after final period if not !RunImage + 2. If name is !RunImage then process item before the period + in front of !RunImage. + 3. If directory name use that + 4. if in form <XXX$Dir> use the XXX. + + Finally once this value has been retrieved use it unless + there is a variable set up in the form SDL$<name>$TaskName + in which case the value of this variable will be used. + + Now also gets other RISC OS configuration varibles + SDL$<name>$BackBuffer - set to 1 to use a system memory backbuffer in fullscreen mode + so updates wait until a call to SDL_UpdateRects. (default 0) + This is required for programmes where they have assumed this is + always the case which is contrary to the documentation. + SDL$<name>$CloseAction + 0 Don't show close icon + 1 Show close icon + +***************************************************************************/ + +int RISCOS_GetTaskName(char *task_name, size_t maxlen) +{ + _kernel_swi_regs regs; + + task_name[0] = 0; + + /* Figure out a sensible task name */ + if (_kernel_swi(OS_GetEnv, ®s, ®s) == 0) + { + char *command_line = (char *)regs.r[0]; + size_t len = SDL_strlen(command_line)+1; + char *buffer = SDL_stack_alloc(char, len); + char *env_var; + char *p; + + SDL_strlcpy(buffer, command_line, len); + p = SDL_strchr(buffer, ' '); + if (p) *p = 0; + p = SDL_strrchr(buffer, '.'); + if (p == 0) p = buffer; + if (stricmp(p+1,"!RunImage") == 0) + { + *p = 0; + p = SDL_strrchr(buffer, '.'); + if (p == 0) p = buffer; + } + if (*p == '.') p++; + if (*p == '!') p++; /* Skip "!" at beginning of application directories */ + + if (*p == '<') + { + // Probably in the form <appname$Dir> + char *q = SDL_strchr(p, '$'); + if (q == 0) q = SDL_strchr(p,'>'); /* Use variable name if not */ + if (q) *q = 0; + p++; /* Move over the < */ + } + + if (*p) + { + /* Read variables that effect the RISC OS SDL engine for this task */ + len = SDL_strlen(p) + 18; /* 18 is larger than the biggest variable name */ + env_var = SDL_stack_alloc(char, len); + if (env_var) + { + char *env_val; + + /* See if a variable of form SDL$<dirname>$TaskName exists */ + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$TaskName", len); + + env_val = SDL_getenv(env_var); + if (env_val) SDL_strlcpy(task_name, env_val, maxlen); + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$BackBuffer", len); + + env_val = SDL_getenv(env_var); + if (env_val) riscos_backbuffer = atoi(env_val); + + SDL_strlcpy(env_var, "SDL$", len); + SDL_strlcat(env_var, p, len); + SDL_strlcat(env_var, "$CloseAction", len); + + env_val = SDL_getenv(env_var); + if (env_val && SDL_strcmp(env_val,"0") == 0) riscos_closeaction = 0; + + SDL_stack_free(env_var); + } + + if (!*task_name) SDL_strlcpy(task_name, p, maxlen); + } + + SDL_stack_free(buffer); + } + + if (task_name[0] == 0) SDL_strlcpy(task_name, "SDL Task", maxlen); + + return 1; +} + +/***************************************************************** + + Store the current desktop screen mode if we are in the desktop. + +******************************************************************/ + +void RISCOS_StoreWimpMode() +{ + _kernel_swi_regs regs; + + /* Don't store if in full screen mode */ + if (stored_mode != -1) return; + + regs.r[0] = 1; + _kernel_swi(OS_ScreenMode, ®s, ®s); + if (regs.r[1] >= 0 && regs.r[1] < 256) stored_mode = regs.r[1]; + else + { + int blockSize = 0; + int *retBlock = (int *)regs.r[1]; + int *storeBlock; + int j; + + while(blockSize < 5 || retBlock[blockSize] != -1) blockSize++; + blockSize++; + storeBlock = (int *)SDL_malloc(blockSize * sizeof(int)); + retBlock = (int *)regs.r[1]; + for ( j = 0; j < blockSize; j++) + storeBlock[j] = retBlock[j]; + + stored_mode = (int)storeBlock; + } +#if DUMP_MODE + fprintf(stderr, "Stored "); dump_mode(); +#endif +} + +/***************************************************************** + + Restore desktop screen mode if we are in full screen mode. + +*****************************************************************/ + +void RISCOS_RestoreWimpMode() +{ + _kernel_swi_regs regs; + + /* Only need to restore if we are in full screen mode */ + if (stored_mode == -1) return; + +#if DUMP_MODE + fprintf(stderr, "Restored"); dump_mode(); +#endif + + regs.r[0] = stored_mode; + _kernel_swi(Wimp_SetMode, ®s, ®s); + if (stored_mode < 0 || stored_mode > 256) + { + SDL_free((int *)stored_mode); + } + stored_mode = -1; + + /* Flush keyboard buffer to dump the keystrokes we've already polled */ + regs.r[0] = 21; + regs.r[1] = 0; /* Keyboard buffer number */ + _kernel_swi(OS_Byte, ®s, ®s); + + mouseInWindow = 0; + +} + +/********************************************************************* + + Get version of Wimp running when task was initialised. + +*********************************************************************/ + +int RISCOS_GetWimpVersion() +{ + return wimp_version; +} + +int RISCOS_GetTaskHandle() +{ + return task_handle; +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscostask.h b/3rdparty/SDL/src/video/riscos/SDL_riscostask.h new file mode 100644 index 0000000..5744afa --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscostask.h @@ -0,0 +1,39 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + This file added by Alan Buckley (alan_baa@hotmail.com) to support RISC OS + 26 March 2003 +*/ + +/* Task initialisation/Clean up */ + +extern int RISCOS_InitTask(); +extern void RISCOS_ExitTask(); +extern int RISCOS_GetWimpVersion(); +extern int RISCOS_GetTaskHandle(); + + +/* Wimp mode saveing/restoring */ +extern void RISCOS_StoreWimpMode(); +extern void RISCOS_RestoreWimpMode(); diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c new file mode 100644 index 0000000..bae5e37 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.c @@ -0,0 +1,316 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 23 March 2003 + + Implements RISC OS display device management. + Routines for full screen and wimp modes are split + into other source files. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +#define RISCOSVID_DRIVER_NAME "riscos" + +/* Initialization/Query functions */ +static int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static void RISCOS_VideoQuit(_THIS); + +static SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); + +int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info); + +int RISCOS_ToggleFullScreen(_THIS, int fullscreen); +/* Mouse checking */ +void RISCOS_CheckMouseMode(_THIS); +extern SDL_GrabMode RISCOS_GrabInput(_THIS, SDL_GrabMode mode); + +/* Fullscreen mode functions */ +extern SDL_Surface *FULLSCREEN_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern void FULLSCREEN_BuildModeList(_THIS); +extern void FULLSCREEN_SetDeviceMode(_THIS); +extern int FULLSCREEN_ToggleFromWimp(_THIS); + +/* Wimp mode functions */ +extern SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +extern void WIMP_DeleteWindow(_THIS); +extern int WIMP_ToggleFromFullScreen(_THIS); + +/* Hardware surface functions - common to WIMP and FULLSCREEN */ +static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface); +static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* RISC OS driver bootstrap functions */ + +static int RISCOS_Available(void) +{ + return(1); +} + +static void RISCOS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *RISCOS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = RISCOS_VideoInit; + device->VideoQuit = RISCOS_VideoQuit; + + device->ListModes = RISCOS_ListModes; + device->SetVideoMode = RISCOS_SetVideoMode; + device->CreateYUVOverlay = NULL; + device->AllocHWSurface = RISCOS_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = RISCOS_LockHWSurface; + device->UnlockHWSurface = RISCOS_UnlockHWSurface; + device->FreeHWSurface = RISCOS_FreeHWSurface; + + device->FreeWMCursor = RISCOS_FreeWMCursor; + device->CreateWMCursor = RISCOS_CreateWMCursor; + device->CheckMouseMode = RISCOS_CheckMouseMode; + device->GrabInput = RISCOS_GrabInput; + + device->InitOSKeymap = RISCOS_InitOSKeymap; + + device->GetWMInfo = RISCOS_GetWmInfo; + + device->free = RISCOS_DeleteDevice; + +/* Can't get Toggle screen to work if program starts up in Full screen mode so + disable it here and re-enable it when a wimp screen is chosen */ + device->ToggleFullScreen = NULL; /*RISCOS_ToggleFullScreen;*/ + + /* Set other entries for fullscreen mode */ + FULLSCREEN_SetDeviceMode(device); + + /* Mouse pointer needs to use the WIMP ShowCursor version so + that it doesn't modify the pointer until the SDL Window is + entered or the application goes full screen */ + device->ShowWMCursor = WIMP_ShowWMCursor; + + return device; +} + +VideoBootStrap RISCOS_bootstrap = { + RISCOSVID_DRIVER_NAME, "RISC OS video driver", + RISCOS_Available, RISCOS_CreateDevice +}; + + +int RISCOS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + _kernel_swi_regs regs; + int vars[4], vals[3]; + + if (RISCOS_InitTask() == 0) + { + SDL_SetError("Unable to start task"); + return 0; + } + + vars[0] = 9; /* Log base 2 bpp */ + vars[1] = 11; /* XWndLimit - num x pixels -1 */ + vars[2] = 12; /* YWndLimit - num y pixels -1 */ + vars[3] = -1; /* Terminate list */ + regs.r[0] = (int)vars; + regs.r[1] = (int)vals; + + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + vformat->BitsPerPixel = (1 << vals[0]); + + /* Determine the current screen size */ + this->info.current_w = vals[1] + 1; + this->info.current_h = vals[2] + 1; + + /* Minimum bpp for SDL is 8 */ + if (vformat->BitsPerPixel < 8) vformat->BitsPerPixel = 8; + + + switch (vformat->BitsPerPixel) + { + case 15: + case 16: + vformat->Bmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Rmask = 0x0000001f; + vformat->BitsPerPixel = 16; /* SDL wants actual number of bits used */ + vformat->BytesPerPixel = 2; + break; + + case 24: + case 32: + vformat->Bmask = 0x00ff0000; + vformat->Gmask = 0x0000ff00; + vformat->Rmask = 0x000000ff; + vformat->BytesPerPixel = 4; + break; + + default: + vformat->Bmask = 0; + vformat->Gmask = 0; + vformat->Rmask = 0; + vformat->BytesPerPixel = 1; + break; + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void RISCOS_VideoQuit(_THIS) +{ + RISCOS_ExitTask(); + + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + this->hidden->alloc_bank = 0; +} + + +SDL_Rect **RISCOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + { + /* Build mode list when first required. */ + if (SDL_nummodes[0] == 0) FULLSCREEN_BuildModeList(this); + + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); + } else + return (SDL_Rect **)-1; +} + + +/* Set up video mode */ +SDL_Surface *RISCOS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if (flags & SDL_FULLSCREEN) + { + RISCOS_StoreWimpMode(); + /* Dump wimp window on switch to full screen */ + if (this->hidden->window_handle) WIMP_DeleteWindow(this); + + return FULLSCREEN_SetVideoMode(this, current, width, height, bpp, flags); + } else + { + RISCOS_RestoreWimpMode(); + return WIMP_SetVideoMode(this, current, width, height, bpp, flags); + } +} + + +/* We don't actually allow hardware surfaces other than the main one */ +static int RISCOS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void RISCOS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int RISCOS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void RISCOS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + + +int RISCOS_GetWmInfo(_THIS, SDL_SysWMinfo *info) +{ + SDL_VERSION(&(info->version)); + info->wimpVersion = RISCOS_GetWimpVersion(); + info->taskHandle = RISCOS_GetTaskHandle(); + info->window = this->hidden->window_handle; + + return 1; +} +/* Toggle full screen mode. + Returns 1 if successful otherwise 0 +*/ + +int RISCOS_ToggleFullScreen(_THIS, int fullscreen) +{ + if (fullscreen) + { + return FULLSCREEN_ToggleFromWimp(this); + } else + { + return WIMP_ToggleFromFullScreen(this); + } + + return 0; +} + diff --git a/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h new file mode 100644 index 0000000..7c717ad --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_riscosvideo.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_riscosvideo_h +#define _SDL_riscosvideo_h + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + + +/* Private display data */ + +struct SDL_PrivateVideoData { + unsigned char *bank[2]; + int current_bank; + unsigned char *alloc_bank; + int height; + int xeig; + int yeig; + int screen_bpp; + int screen_width; + int screen_height; + char *pixtrans; + + /* Wimp variables */ + unsigned int window_handle; + char title[256]; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; +}; + +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) + +#endif /* _SDL_risosvideo_h */ diff --git a/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c b/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c new file mode 100644 index 0000000..4999664 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_wimppoll.c @@ -0,0 +1,330 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements Pumping of events and WIMP polling +*/ + +#include "SDL.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" +#include "../../timer/SDL_timer_c.h" + +#include "memory.h" +#include "stdlib.h" +#include "ctype.h" + +#include "kernel.h" +#include "swis.h" +#include "unixlib/os.h" + +#if !SDL_THREADS_DISABLED +#include <pthread.h> +#endif + +/* Local functions */ +void WIMP_Poll(_THIS, int waitTime); +void WIMP_SetFocus(int win); + +/* SDL_riscossprite functions */ +void WIMP_PlotSprite(_THIS, int x, int y); +void WIMP_ModeChanged(_THIS); +void WIMP_PaletteChanged(_THIS); + + +extern void WIMP_PollMouse(_THIS); +extern void RISCOS_PollKeyboard(); + +#if SDL_THREADS_DISABLED +/* Timer running function */ +extern void RISCOS_CheckTimer(); +#else +extern int riscos_using_threads; +#endif + +/* Mouse cursor handling */ +extern void WIMP_ReshowCursor(_THIS); +extern void WIMP_RestoreWimpCursor(); + +int hasFocus = 0; +int mouseInWindow = 0; + +/* Flag to ensure window is correct size after a mode change */ +static int resizeOnOpen = 0; + +void WIMP_PumpEvents(_THIS) +{ + WIMP_Poll(this, 0); + if (hasFocus) RISCOS_PollKeyboard(); + if (mouseInWindow) WIMP_PollMouse(this); +#if SDL_THREADS_DISABLED + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} + + +void WIMP_Poll(_THIS, int waitTime) +{ + _kernel_swi_regs regs; + int message[64]; + unsigned int code; + int pollMask = 0; + int doPoll = 1; + int sysEvent; + int sdlWindow = this->hidden->window_handle; + + if (this->PumpEvents != WIMP_PumpEvents) return; + + if (waitTime > 0) + { + _kernel_swi(OS_ReadMonotonicTime, ®s, ®s); + waitTime += regs.r[0]; + } + + while (doPoll) + { +#if !SDL_THREADS_DISABLED + /* Stop thread callbacks while program is paged out */ + if (riscos_using_threads) __pthread_stop_ticker(); +#endif + + if (waitTime <= 0) + { + regs.r[0] = pollMask; /* Poll Mask */ + /* For no wait time mask out null event so we wait until something happens */ + if (waitTime < 0) regs.r[0] |= 1; + regs.r[1] = (int)message; + _kernel_swi(Wimp_Poll, ®s, ®s); + } else + { + regs.r[0] = pollMask; + regs.r[1] = (int)message; + regs.r[2] = waitTime; + _kernel_swi(Wimp_PollIdle, ®s, ®s); + } + + /* Flag to specify if we post a SDL_SysWMEvent */ + sysEvent = 0; + + code = (unsigned int)regs.r[0]; + + switch(code) + { + case 0: /* Null Event - drop out for standard processing*/ + doPoll = 0; + break; + + case 1: /* Redraw window */ + _kernel_swi(Wimp_RedrawWindow, ®s,®s); + if (message[0] == sdlWindow) + { + while (regs.r[0]) + { + WIMP_PlotSprite(this, message[1], message[2]); + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } else + { + /* TODO: Currently we just eat them - we may need to pass them on */ + while (regs.r[0]) + { + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } + break; + + case 2: /* Open window */ + if ( resizeOnOpen && message[0] == sdlWindow) + { + /* Ensure window is correct size */ + resizeOnOpen = 0; + message[3] = message[1] + (this->screen->w << this->hidden->xeig); + message[4] = message[2] + (this->screen->h << this->hidden->yeig); + } + _kernel_swi(Wimp_OpenWindow, ®s, ®s); + break; + + case 3: /* Close window */ + if (message[0] == sdlWindow) + { + /* Documentation makes it looks as if the following line is correct: + ** if (SDL_PrivateQuit() == 1) _kernel_swi(Wimp_CloseWindow, ®s, ®s); + ** However some programs don't process this message and so sit there invisibly + ** in the background so I just post the quit message and hope the application + ** does the correct thing. + */ + SDL_PrivateQuit(); + } else + sysEvent = 1; + doPoll = 0; + break; + + case 4: /* Pointer_Leaving_Window */ + if (message[0] == sdlWindow) + { + mouseInWindow = 0; + //TODO: Lose buttons / dragging + /* Reset to default pointer */ + WIMP_RestoreWimpCursor(); + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } else + sysEvent = 1; + break; + + case 5: /* Pointer_Entering_Window */ + if (message[0] == sdlWindow) + { + mouseInWindow = 1; + WIMP_ReshowCursor(this); + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } else sysEvent = 1; + break; + + case 6: /* Mouse_Click */ + if (hasFocus == 0) + { + /* First click gives focus if it's not a menu */ + /* we only count non-menu clicks on a window that has the focus */ + WIMP_SetFocus(message[3]); + } else + doPoll = 0; // So PollMouse gets a chance to pick it up + break; + + case 7: /* User_Drag_Box - Used for mouse release */ + //TODO: May need to implement this in the future + sysEvent = 1; + break; + + case 8: /* Keypressed */ + doPoll = 0; /* PollKeyboard should pick it up */ + if (message[0] != sdlWindow) sysEvent = 1; + /*TODO: May want to always pass F12 etc to the wimp + { + regs.r[0] = message[6]; + _kernel_swi(Wimp_ProcessKey, ®s, ®s); + } + */ + break; + + case 11: /* Lose Caret */ + hasFocus = 0; + if (message[0] == sdlWindow) SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + else sysEvent = 1; + break; + + case 12: /* Gain Caret */ + hasFocus = 1; + if (message[0] == sdlWindow) SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + else sysEvent = 1; + break; + + case 17: + case 18: + sysEvent = 1; /* All messages are passed on */ + + switch(message[4]) + { + case 0: /* Quit Event */ + /* No choice - have to quit */ + SDL_Quit(); + exit(0); + break; + + case 8: /* Pre Quit */ + SDL_PrivateQuit(); + break; + + case 0x400c1: /* Mode change */ + WIMP_ModeChanged(this); + resizeOnOpen = 1; + break; + + case 9: /* Palette changed */ + WIMP_PaletteChanged(this); + break; + } + break; + + default: + /* Pass unknown events on */ + sysEvent = 1; + break; + } + + if (sysEvent) + { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.eventCode = code; + SDL_memcpy(wmmsg.pollBlock, message, 64 * sizeof(int)); + + /* Fall out of polling loop if message is successfully posted */ + if (SDL_PrivateSysWMEvent(&wmmsg)) doPoll = 0; + } +#if !SDL_THREADS_DISABLED + if (riscos_using_threads) + { + /* Restart ticker here so other thread can not interfere + with the Redraw processing */ + if (riscos_using_threads) __pthread_start_ticker(); + /* Give other threads a better chance of running */ + pthread_yield(); + } +#endif + } +} + +/* Set focus to specified window */ +void WIMP_SetFocus(int win) +{ + _kernel_swi_regs regs; + + regs.r[0] = win; + regs.r[1] = -1; /* Icon handle */ + regs.r[2] = 0; /* X-offset we just put it at position 0 */ + regs.r[3] = 0; /* Y-offset as above */ + regs.r[4] = 1 << 25; /* Caret is invisible */ + regs.r[5] = 0; /* index into string */ + + _kernel_swi(Wimp_SetCaretPosition, ®s, ®s); +} + +/** Run background task while in a sleep command */ +void RISCOS_BackgroundTasks(void) +{ + if (current_video && current_video->hidden->window_handle) + { + WIMP_Poll(current_video, 0); + } +#if SDL_THREADS_DISABLED + if (SDL_timer_running) RISCOS_CheckTimer(); +#endif +} diff --git a/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c b/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c new file mode 100644 index 0000000..0f9c545 --- /dev/null +++ b/3rdparty/SDL/src/video/riscos/SDL_wimpvideo.c @@ -0,0 +1,501 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + File added by Alan Buckley (alan_baa@hotmail.com) for RISC OS compatability + 27 March 2003 + + Implements RISC OS Wimp display. +*/ + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_riscostask.h" +#include "SDL_riscosvideo.h" +#include "SDL_riscosevents_c.h" +#include "SDL_riscosmouse_c.h" + +#include "kernel.h" +#include "swis.h" + +/* Initialization/Query functions */ +SDL_Rect **WIMP_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +void WIMP_SetWMCaption(_THIS, const char *title, const char *icon); + + +extern unsigned char *WIMP_CreateBuffer(int width, int height, int bpp); +extern void WIMP_PumpEvents(_THIS); +extern void WIMP_PlotSprite(_THIS, int x, int y); +extern void WIMP_SetupPlotInfo(_THIS); +extern void WIMP_SetFocus(int win); + +/* etc. */ +static void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +/* RISC OS Wimp handling helpers */ +void WIMP_ReadModeInfo(_THIS); +unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface); +void WIMP_SetDeviceMode(_THIS); +void WIMP_DeleteWindow(_THIS); + +/* FULLSCREEN function required for wimp/fullscreen toggling */ +extern int FULLSCREEN_SetMode(int width, int height, int bpp); + +/* Currently need to set this up here as it only works if you + start up in a Wimp mode */ +extern int RISCOS_ToggleFullScreen(_THIS, int fullscreen); + +extern int riscos_backbuffer; +extern int mouseInWindow; +extern int riscos_closeaction; + +/* Following needed to ensure window is shown immediately */ +extern int hasFocus; +extern void WIMP_Poll(_THIS, int waitTime); + +SDL_Surface *WIMP_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 Rmask = 0; + Uint32 Gmask = 0; + Uint32 Bmask = 0; + char *buffer = NULL; + int bytesPerPixel = 1; + + /* Don't support double buffering in Wimp mode */ + flags &= ~SDL_DOUBLEBUF; + flags &= ~SDL_HWSURFACE; + + switch(bpp) + { + case 8: + /* Emulated palette using ColourTrans */ + flags |= SDL_HWPALETTE; + break; + + case 15: + case 16: + Bmask = 0x00007c00; + Gmask = 0x000003e0; + Rmask = 0x0000001f; + bytesPerPixel = 2; + break; + + case 32: + Bmask = 0x00ff0000; + Gmask = 0x0000ff00; + Rmask = 0x000000ff; + bytesPerPixel = 4; + break; + + default: + SDL_SetError("Pixel depth not supported"); + return NULL; + break; + } + +/* printf("Setting mode %dx%d\n", width, height);*/ + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->w = width; + this->hidden->height = current->h = height; + + if (bpp == 15) bpp = 16; + buffer = WIMP_CreateBuffer(width, height, bpp); + if (buffer == NULL) + { + SDL_SetError("Couldn't create sprite for video memory"); + return (NULL); + } + + this->hidden->bank[0] = buffer + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->bank[1] = buffer; /* Start of buffer */ + + /* Remember sprite buffer so it can be freed later */ + if (this->hidden->alloc_bank) SDL_free(this->hidden->alloc_bank); + this->hidden->alloc_bank = buffer; + + current->pitch = width * bytesPerPixel; + if ((current->pitch & 3)) + { + /* Sprites are 32bit word aligned */ + current->pitch += (4 - (current->pitch & 3)); + } + + current->flags = flags | SDL_PREALLOC; + + WIMP_ReadModeInfo(this); + + SDL_memset(this->hidden->bank[0], 0, height * current->pitch); + + this->hidden->current_bank = 0; + current->pixels = this->hidden->bank[0]; + + + if (WIMP_SetupWindow(this, current) == 0) + { + SDL_SetError("Unable to create window to display surface"); + return NULL; + } + + /* Reset device functions for the wimp */ + WIMP_SetDeviceMode(this); + + /* Needs to set up plot info after window has been created */ + /* Not sure why, but plots don't work if I do it earlier */ + WIMP_SetupPlotInfo(this); + + /* Poll until window is shown */ + { + /* We wait until it gets the focus, but give up after 5 seconds + in case the focus is prevented in any way. + */ + Uint32 now = SDL_GetTicks(); + while (!hasFocus && SDL_GetTicks() - now < 5000) + { + WIMP_Poll(this, 0); + } + } + + /* We're done */ + return(current); +} + + +void WIMP_ReadModeInfo(_THIS) +{ + _kernel_swi_regs regs; + int vars[6]; + int vals[5]; + + vars[0] = 4; /* XEig */ + vars[1] = 5; /* YEig */ + vars[2] = 9; /* Log base 2 bpp */ + vars[3] = 11; /* Screen Width - 1 */ + vars[4] = 12; /* Screen Depth - 1 */ + vars[5] = -1; /* Terminate list */ + + regs.r[0] = (int)vars; + regs.r[1] = (int)vals; + _kernel_swi(OS_ReadVduVariables, ®s, ®s); + this->hidden->xeig = vals[0]; + this->hidden->yeig = vals[1]; + this->hidden->screen_bpp = 1 << vals[2]; + this->hidden->screen_width = vals[3] + 1; + this->hidden->screen_height = vals[4] + 1; +} + +/* Set device function to call the correct versions for running + in a wimp window */ + +void WIMP_SetDeviceMode(_THIS) +{ + if (this->UpdateRects == WIMP_UpdateRects) return; /* Already set up */ + + this->SetColors = WIMP_SetColors; + this->UpdateRects = WIMP_UpdateRects; + + this->FlipHWSurface = NULL; + + this->SetCaption = WIMP_SetWMCaption; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + + this->ShowWMCursor = WIMP_ShowWMCursor; + this->WarpWMCursor = WIMP_WarpWMCursor; + + this->ToggleFullScreen = RISCOS_ToggleFullScreen; + + this->PumpEvents = WIMP_PumpEvents; +} + +/* Setup the Window to display the surface */ +unsigned int WIMP_SetupWindow(_THIS, SDL_Surface *surface) +{ + _kernel_swi_regs regs; + int window_data[23]; + int *window_block = window_data+1; + int x = (this->hidden->screen_width - surface->w) / 2; + int y = (this->hidden->screen_height - surface->h) / 2; + int xeig = this->hidden->xeig; + int yeig = this->hidden->yeig; + + mouseInWindow = 0; + + /* Always delete the window and recreate on a change */ + if (this->hidden->window_handle) WIMP_DeleteWindow(this); + + /* Setup window co-ordinates */ + window_block[0] = x << xeig; + window_block[1] = y << yeig; + window_block[2] = window_block[0] + (surface->w << xeig); + window_block[3] = window_block[1] + (surface->h << yeig); + + + window_block[4] = 0; /* Scroll offsets */ + window_block[5] = 0; + window_block[6] = -1; /* Open on top of window stack */ + + window_block[7] = 0x85040042; /* Window flags */ + if (riscos_closeaction != 0) window_block[7] |= 0x2000000; + + /* TODO: Take into account surface->flags */ + + window_block[8] = 0xff070207; /* Window colours */ + window_block[9] = 0x000c0103; + window_block[10] = 0; /* Work area minimum */ + window_block[11] = -surface->h << yeig; + window_block[12] = surface->w << xeig; /* Work area maximum */ + window_block[13] = 0; + window_block[14] = 0x2700013d; /* Title icon flags */ + window_block[15] = 0x00003000; /* Work area flags - Mouse click down reported */ + window_block[16] = 1; /* Sprite area control block pointer */ + window_block[17] = 0x00100010; /* Minimum window size (width & height) (16x16)*/ + window_block[18] = (int)this->hidden->title; /* Title data */ + window_block[19] = -1; + window_block[20] = 256; + window_block[21] = 0; /* Number of icons */ + + regs.r[1] = (unsigned int)(window_block); + + /* Create the window */ + if (_kernel_swi(Wimp_CreateWindow, ®s, ®s) == NULL) + { + this->hidden->window_handle = window_data[0] = regs.r[0]; + + /* Show the window on the screen */ + regs.r[1] = (unsigned int)window_data; + if (_kernel_swi(Wimp_OpenWindow, ®s, ®s) == NULL) + { + WIMP_SetFocus(this->hidden->window_handle); + } else + { + WIMP_DeleteWindow(this); + } + } + + return this->hidden->window_handle; +} + +/* Destroy the Window */ + +void WIMP_DeleteWindow(_THIS) +{ + _kernel_swi_regs regs; + regs.r[1] = (unsigned int)&(this->hidden->window_handle); + _kernel_swi(Wimp_DeleteWindow, ®s, ®s); + this->hidden->window_handle = 0; +} + + +void WIMP_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + _kernel_swi_regs regs; + int update_block[12]; + int xeig = this->hidden->xeig; + int yeig = this->hidden->yeig; + int j; + update_block[0] = this->hidden->window_handle; + + for (j = 0; j < numrects; j++) + { + update_block[1] = rects[j].x << xeig; /* Min X */ + update_block[4] = -(rects[j].y << yeig); + update_block[3] = update_block[1] + (rects[j].w << xeig); + update_block[2] = update_block[4] - (rects[j].h << yeig); + + regs.r[1] = (int)update_block; + /* Update window can fail if called before first poll */ + if (_kernel_swi(Wimp_UpdateWindow, ®s, ®s) == 0) + { + while (regs.r[0]) + { + WIMP_PlotSprite(this, update_block[1], update_block[2]); + _kernel_swi(Wimp_GetRectangle, ®s, ®s); + } + } + } +} + + +int WIMP_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + unsigned int *pal = (unsigned int *)(this->hidden->bank[1]+60); + int j; + SDL_Rect update; + + pal += firstcolor*2; + for (j = 0; j < ncolors; j++) + { + *pal = (((unsigned int)colors->r) << 8) + + (((unsigned int)colors->g) << 16) + + (((unsigned int)colors->b) << 24); + pal[1] = *pal; + pal += 2; + colors++; + } + + WIMP_SetupPlotInfo(this); + + /* Need to refresh the window */ + update.x = 0; + update.y = 0; + update.w = SDL_VideoSurface->w; + update.h = SDL_VideoSurface->h; + WIMP_UpdateRects(this, 1, &update); + + return 1; +} + +void WIMP_SetWMCaption(_THIS, const char *title, const char *icon) +{ + _kernel_swi_regs regs; + + SDL_strlcpy(this->hidden->title, title, SDL_arraysize(this->hidden->title)); + + if (RISCOS_GetWimpVersion() < 380) + { + int block[6]; + + regs.r[1] = (int)block; + _kernel_swi(Wimp_GetCaretPosition, ®s, ®s); + if (block[0] == (int)this->hidden->window_handle) + { + regs.r[0] = -1; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } else + { + regs.r[0] = this->hidden->window_handle; + regs.r[1] = -1; + regs.r[2] = -1; + regs.r[3] = -1; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } + regs.r[0] = block[0]; + regs.r[1] = block[1]; + regs.r[2] = block[2]; + regs.r[3] = block[3]; + regs.r[4] = block[4]; + regs.r[5] = block[5]; + _kernel_swi(Wimp_SetCaretPosition, ®s,®s); + } else + { + regs.r[0] = this->hidden->window_handle; + regs.r[1] = 0x4b534154; /* "TASK" */ + regs.r[2] = 3; /* Redraw title */ + _kernel_swi(Wimp_ForceRedraw, ®s, ®s); + } +} + +void WIMP_RefreshDesktop(_THIS) +{ + int width = this->hidden->screen_width << this->hidden->xeig; + int height = this->hidden->screen_height << this->hidden->yeig; + _kernel_swi_regs regs; + regs.r[0] = -1; /* Whole screen */ + regs.r[1] = 0; + regs.r[2] = 0; + regs.r[3] = width; + regs.r[4] = height; + _kernel_swi(Wimp_ForceRedraw, ®s, ®s); +} + +/* Toggle to window from full screen */ +int WIMP_ToggleFromFullScreen(_THIS) +{ + int width = this->screen->w; + int height = this->screen->h; + int bpp = this->screen->format->BitsPerPixel; + char *buffer = NULL; + char *old_bank[2]; + char *old_alloc_bank; + + /* Ensure flags are OK */ + this->screen->flags &= ~(SDL_DOUBLEBUF|SDL_HWSURFACE); + + if (this->hidden->bank[0] == this->hidden->alloc_bank || riscos_backbuffer == 0) + { + /* Need to create a sprite for the screen and copy the data to it */ + char *data; + buffer = WIMP_CreateBuffer(width, height, bpp); + data = buffer + 60; /* Start of sprite data */ + if (bpp == 8) data += 2048; /* 8bpp sprite have palette first */ + + if (buffer == NULL) return 0; + SDL_memcpy(data, this->hidden->bank[0], width * height * this->screen->format->BytesPerPixel); + } + /* else We've switch to full screen before so we already have a sprite */ + + old_bank[0] = this->hidden->bank[0]; + old_bank[1] = this->hidden->bank[1]; + old_alloc_bank = this->hidden->alloc_bank; + + if (buffer != NULL) this->hidden->alloc_bank = buffer; + + this->hidden->bank[1] = this->hidden->alloc_bank; + this->hidden->bank[0] = this->hidden->bank[1] + 60; /* Start of sprite data */ + if (bpp == 8) this->hidden->bank[0] += 2048; /* 8bpp sprite have palette first */ + + this->hidden->current_bank = 0; + this->screen->pixels = this->hidden->bank[0]; + + RISCOS_RestoreWimpMode(); + WIMP_ReadModeInfo(this); + if (WIMP_SetupWindow(this, this->screen)) + { + WIMP_SetDeviceMode(this); + WIMP_SetupPlotInfo(this); + + if (riscos_backbuffer == 0) riscos_backbuffer = 1; + + if (buffer && old_alloc_bank) SDL_free(old_alloc_bank); + + return 1; + } else + { + /* Drop back to full screen mode on failure */ + this->hidden->bank[0] = old_bank[0]; + this->hidden->bank[1] = old_bank[1]; + this->hidden->alloc_bank = old_alloc_bank; + if (buffer) SDL_free(buffer); + + RISCOS_StoreWimpMode(); + FULLSCREEN_SetMode(width, height, bpp); + } + + return 0; +} diff --git a/3rdparty/SDL/src/video/svga/SDL_svgaevents.c b/3rdparty/SDL/src/video/svga/SDL_svgaevents.c new file mode 100644 index 0000000..107a702 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgaevents.c @@ -0,0 +1,412 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <vga.h> +#include <vgamouse.h> +#include <vgakeyboard.h> +#if defined(__LINUX__) +#include <linux/kd.h> +#include <linux/keyboard.h> +#elif defined(__FREEBSD__) +#include <sys/kbio.h> +#else +#error You must choose your operating system here +#endif + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +#if defined(linux) +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +#elif defined(__FREEBSD__) +/* FIXME: Free the keymap when we shut down the video mode */ +static keymap_t *vga_keymap = NULL; +#else +#error You must choose your operating system here +#endif +static SDLKey keymap[128]; +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +#if defined(linux) +int SVGA_initkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } + return(0); +} +#elif defined(__FREEBSD__) +int SVGA_initkeymaps(int fd) +{ + vga_keymap = SDL_malloc(sizeof(keymap_t)); + if ( ! vga_keymap ) { + SDL_OutOfMemory(); + return(-1); + } + if (ioctl(fd, GIO_KEYMAP, vga_keymap) == -1) { + SDL_free(vga_keymap); + vga_keymap = NULL; + SDL_SetError("Unable to get keyboard map"); + return(-1); + } + return(0); +} +#else +#error You must choose your operating system here +#endif + +int posted = 0; + +void SVGA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4) +{ + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, 1, dx, dy); + } + if ( button & MOUSE_LEFTBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 1, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 1, 0, 0); + } + } + if ( button & MOUSE_MIDDLEBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 2, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 2, 0, 0); + } + } + if ( button & MOUSE_RIGHTBUTTON ) { + if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { + posted += SDL_PrivateMouseButton(SDL_PRESSED, 3, 0, 0); + } + } else { + if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { + posted += SDL_PrivateMouseButton(SDL_RELEASED, 3, 0, 0); + } + } +} + +void SVGA_keyboardcallback(int scancode, int pressed) +{ + SDL_keysym keysym; + + if ( pressed ) { + posted += SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(scancode, &keysym)); + } else { + posted += SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(scancode, &keysym)); + } +} + +void SVGA_PumpEvents(_THIS) +{ + do { + posted = 0; + mouse_update(); + keyboard_update(); + } while ( posted ); +} + +void SVGA_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the BeOS key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + +#if defined(linux) +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_ALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_MODE ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} +#elif defined(__FREEBSD__) +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE && vga_keymap ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map += 1; + } + if ( modstate & KMOD_CTRL ) { + map += 2; + } + if ( modstate & KMOD_ALT ) { + map += 4; + } + if ( !(vga_keymap->key[scancode].spcl & (0x80 >> map)) ) { + keysym->unicode = vga_keymap->key[scancode].map[map]; + } + + } + return(keysym); +} +#else +#error You must choose your operating system here +#endif diff --git a/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h b/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h new file mode 100644 index 0000000..cd9f888 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgaevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_svgavideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int SVGA_initkeymaps(int fd); +extern void SVGA_mousecallback(int button, int dx, int dy, + int u1,int u2,int u3, int u4); +extern void SVGA_keyboardcallback(int scancode, int pressed); + +extern void SVGA_InitOSKeymap(_THIS); +extern void SVGA_PumpEvents(_THIS); diff --git a/3rdparty/SDL/src/video/svga/SDL_svgamouse.c b/3rdparty/SDL/src/video/svga/SDL_svgamouse.c new file mode 100644 index 0000000..a82dbfd --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgamouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgamouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h b/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h new file mode 100644 index 0000000..78fe8ab --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgamouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_svgavideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/svga/SDL_svgavideo.c b/3rdparty/SDL/src/video/svga/SDL_svgavideo.c new file mode 100644 index 0000000..58ea800 --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgavideo.c @@ -0,0 +1,584 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* SVGAlib based SDL video driver implementation. +*/ + +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <fcntl.h> + +#if defined(__LINUX__) +#include <linux/vt.h> +#elif defined(__FREEBSD__) +#include <sys/consio.h> +#else +#error You must choose your operating system here +#endif +#include <vga.h> +#include <vgamouse.h> +#include <vgakeyboard.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_svgavideo.h" +#include "SDL_svgaevents_c.h" +#include "SDL_svgamouse_c.h" + +/* Initialization/Query functions */ +static int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int SVGA_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void SVGA_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface); +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface); +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface); +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* SVGAlib driver bootstrap functions */ + +static int SVGA_Available(void) +{ + /* Check to see if we are root and stdin is a virtual console */ + int console; + + /* SVGALib 1.9.x+ doesn't require root (via /dev/svga) */ + int svgalib2 = -1; + + /* See if we are connected to a virtual terminal */ + console = STDIN_FILENO; +#if 0 /* This is no longer needed, SVGAlib can switch consoles for us */ + if ( console >= 0 ) { + struct stat sb; + struct vt_mode dummy; + + if ( (fstat(console, &sb) < 0) || + (ioctl(console, VT_GETMODE, &dummy) < 0) ) { + console = -1; + } + } +#endif /* 0 */ + + /* See if SVGAlib 2.0 is available */ + svgalib2 = open("/dev/svga", O_RDONLY); + if (svgalib2 != -1) { + close(svgalib2); + } + + return(((svgalib2 != -1) || (geteuid() == 0)) && (console >= 0)); +} + +static void SVGA_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *SVGA_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = SVGA_VideoInit; + device->ListModes = SVGA_ListModes; + device->SetVideoMode = SVGA_SetVideoMode; + device->SetColors = SVGA_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = SVGA_VideoQuit; + device->AllocHWSurface = SVGA_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = SVGA_LockHWSurface; + device->UnlockHWSurface = SVGA_UnlockHWSurface; + device->FlipHWSurface = SVGA_FlipHWSurface; + device->FreeHWSurface = SVGA_FreeHWSurface; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = SVGA_InitOSKeymap; + device->PumpEvents = SVGA_PumpEvents; + + device->free = SVGA_DeleteDevice; + + return device; +} + +VideoBootStrap SVGALIB_bootstrap = { + "svgalib", "SVGAlib", + SVGA_Available, SVGA_CreateDevice +}; + +static int SVGA_AddMode(_THIS, int mode, int actually_add) +{ + int i, j; + vga_modeinfo *modeinfo; + + modeinfo = vga_getmodeinfo(mode); + + i = modeinfo->bytesperpixel-1; + if ( i < 0 ) { + return 0; + } + if ( actually_add ) { + SDL_Rect saved_rect[2]; + int saved_mode[2]; + int b; + + /* Add the mode, sorted largest to smallest */ + b = 0; + j = 0; + while ( (SDL_modelist[i][j]->w > modeinfo->width) || + (SDL_modelist[i][j]->h > modeinfo->height) ) { + ++j; + } + /* Skip modes that are already in our list */ + if ( (SDL_modelist[i][j]->w == modeinfo->width) && + (SDL_modelist[i][j]->h == modeinfo->height) ) { + return(0); + } + /* Insert the new mode */ + saved_rect[b] = *SDL_modelist[i][j]; + saved_mode[b] = SDL_vgamode[i][j]; + SDL_modelist[i][j]->w = modeinfo->width; + SDL_modelist[i][j]->h = modeinfo->height; + SDL_vgamode[i][j] = mode; + /* Everybody scoot down! */ + if ( saved_rect[b].w && saved_rect[b].h ) { + for ( ++j; SDL_modelist[i][j]->w; ++j ) { + saved_rect[!b] = *SDL_modelist[i][j]; + saved_mode[!b] = SDL_vgamode[i][j]; + *SDL_modelist[i][j] = saved_rect[b]; + SDL_vgamode[i][j] = saved_mode[b]; + b = !b; + } + *SDL_modelist[i][j] = saved_rect[b]; + SDL_vgamode[i][j] = saved_mode[b]; + } + } else { + ++SDL_nummodes[i]; + } + return(1); +} + +static void SVGA_UpdateVideoInfo(_THIS) +{ + vga_modeinfo *modeinfo; + + this->info.wm_available = 0; + this->info.hw_available = (banked ? 0 : 1); + modeinfo = vga_getmodeinfo(vga_getcurrentmode()); + this->info.video_mem = modeinfo->memory; + /* FIXME: Add hardware accelerated blit information */ +#ifdef SVGALIB_DEBUG + printf("Hardware accelerated blit: %savailable\n", modeinfo->haveblit ? "" : "not "); +#endif +} + +int SVGA_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int keyboard; + int i, j; + int mode, total_modes; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_vgamode[i] = NULL; + } + + /* Initialize the library */ + vga_disabledriverreport(); + if ( vga_init() < 0 ) { + SDL_SetError("Unable to initialize SVGAlib"); + return(-1); + } + vga_setmode(TEXT); + + /* Enable mouse and keyboard support */ + vga_setmousesupport(1); + keyboard = keyboard_init_return_fd(); + if ( keyboard < 0 ) { + SDL_SetError("Unable to initialize keyboard"); + return(-1); + } + if ( SVGA_initkeymaps(keyboard) < 0 ) { + return(-1); + } + keyboard_seteventhandler(SVGA_keyboardcallback); + + /* Determine the current screen size */ + this->info.current_w = 0; + this->info.current_h = 0; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + + /* Enumerate the available fullscreen modes */ + total_modes = 0; + for ( mode=vga_lastmodenumber(); mode; --mode ) { + if ( vga_hasmode(mode) ) { + if ( SVGA_AddMode(this, mode, 0) ) { + ++total_modes; + } + } + } + if ( SVGA_AddMode(this, G320x200x256, 0) ) ++total_modes; + if ( total_modes == 0 ) { + SDL_SetError("No linear video modes available"); + return(-1); + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_vgamode[i] = (int *)SDL_malloc(SDL_nummodes[i]*sizeof(int)); + if ( SDL_vgamode[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); + } + SDL_modelist[i][j] = NULL; + } + for ( mode=vga_lastmodenumber(); mode; --mode ) { + if ( vga_hasmode(mode) ) { + SVGA_AddMode(this, mode, 1); + } + } + SVGA_AddMode(this, G320x200x256, 1); + + /* Free extra (duplicated) modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + j = 0; + while ( SDL_modelist[i][j] && SDL_modelist[i][j]->w ) { + j++; + } + while ( SDL_modelist[i][j] ) { + SDL_free(SDL_modelist[i][j]); + SDL_modelist[i][j] = NULL; + j++; + } + } + + /* Fill in our hardware acceleration capabilities */ + SVGA_UpdateVideoInfo(this); + + /* We're done! */ + return(0); +} + +SDL_Rect **SVGA_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *SVGA_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode; + int vgamode; + vga_modeinfo *modeinfo; + int screenpage_len; + + /* Free old pixels if we were in banked mode */ + if ( banked && current->pixels ) { + free(current->pixels); + current->pixels = NULL; + } + + /* Try to set the requested linear video mode */ + bpp = (bpp+7)/8-1; + for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { + if ( (SDL_modelist[bpp][mode]->w == width) && + (SDL_modelist[bpp][mode]->h == height) ) { + break; + } + } + if ( SDL_modelist[bpp][mode] == NULL ) { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + vgamode = SDL_vgamode[bpp][mode]; + vga_setmode(vgamode); + vga_setpage(0); + + if ( (vga_setlinearaddressing() < 0) && (vgamode != G320x200x256) ) { + banked = 1; + } else { + banked = 0; + } + + modeinfo = vga_getmodeinfo(SDL_vgamode[bpp][mode]); + + /* Update hardware acceleration info */ + SVGA_UpdateVideoInfo(this); + + /* Allocate the new pixel format for the screen */ + bpp = (bpp+1)*8; + if ( (bpp == 16) && (modeinfo->colors == 32768) ) { + bpp = 15; + } + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + if ( !banked ) { + current->flags |= SDL_HWSURFACE; + } + if ( bpp == 8 ) { + /* FIXME: What about DirectColor? */ + current->flags |= SDL_HWPALETTE; + } + current->w = width; + current->h = height; + current->pitch = modeinfo->linewidth; + if ( banked ) { + current->pixels = SDL_malloc(current->h * current->pitch); + if ( !current->pixels ) { + SDL_OutOfMemory(); + return(NULL); + } + } else { + current->pixels = vga_getgraphmem(); + } + + /* set double-buffering */ + if ( (flags & SDL_DOUBLEBUF) && !banked ) + { + /* length of one screen page in bytes */ + screenpage_len=current->h*modeinfo->linewidth; + + /* if start address should be aligned */ + if ( modeinfo->linewidth_unit ) + { + if ( screenpage_len % modeinfo->linewidth_unit ) + { + screenpage_len += modeinfo->linewidth_unit - ( screenpage_len % modeinfo->linewidth_unit ); + } + } + + /* if we heve enough videomemory = ak je dost videopamete */ + if ( modeinfo->memory > ( screenpage_len * 2 / 1024 ) ) + { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_offset[0] = 0; + flip_offset[1] = screenpage_len; + flip_address[0] = vga_getgraphmem(); + flip_address[1] = flip_address[0]+screenpage_len; + SVGA_FlipHWSurface(this,current); + } + } + + /* Set the blit function */ + if ( banked ) { + this->UpdateRects = SVGA_BankedUpdate; + } else { + this->UpdateRects = SVGA_DirectUpdate; + } + + /* Set up the mouse handler again (buggy SVGAlib 1.40) */ + mouse_seteventhandler(SVGA_mousecallback); + + /* We're done */ + return(current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int SVGA_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void SVGA_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int SVGA_LockHWSurface(_THIS, SDL_Surface *surface) +{ + /* The waiting is done in SVGA_FlipHWSurface() */ + return(0); +} +static void SVGA_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int SVGA_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( !banked ) { + vga_setdisplaystart(flip_offset[flip_page]); + flip_page=!flip_page; + surface->pixels=flip_address[flip_page]; + vga_waitretrace(); + } + return(0); +} + +static void SVGA_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + return; +} + +static void SVGA_BankedUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i, j; + SDL_Rect *rect; + int page, vp; + int x, y, w, h; + unsigned char *src; + unsigned char *dst; + int bpp = this->screen->format->BytesPerPixel; + int pitch = this->screen->pitch; + + dst = vga_getgraphmem(); + for ( i=0; i < numrects; ++i ) { + rect = &rects[i]; + x = rect->x; + y = rect->y; + w = rect->w * bpp; + h = rect->h; + + vp = y * pitch + x * bpp; + src = (unsigned char *)this->screen->pixels + vp; + page = vp >> 16; + vp &= 0xffff; + vga_setpage(page); + for (j = 0; j < h; j++) { + if (vp + w > 0x10000) { + if (vp >= 0x10000) { + page++; + vga_setpage(page); + vp &= 0xffff; + } else { + SDL_memcpy(dst + vp, src, 0x10000 - vp); + page++; + vga_setpage(page); + SDL_memcpy(dst, src + 0x10000 - vp, + (vp + w) & 0xffff); + vp = (vp + pitch) & 0xffff; + src += pitch; + continue; + } + } + SDL_memcpy(dst + vp, src, w); + src += pitch; + vp += pitch; + } + } +} + +int SVGA_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for(i = 0; i < ncolors; i++) { + vga_setpalette(firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void SVGA_VideoQuit(_THIS) +{ + int i, j; + + /* Reset the console video mode */ + if ( this->screen && (this->screen->w && this->screen->h) ) { + vga_setmode(TEXT); + } + keyboard_close(); + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + if ( SDL_vgamode[i] != NULL ) { + SDL_free(SDL_vgamode[i]); + SDL_vgamode[i] = NULL; + } + } + if ( this->screen ) { + if ( banked && this->screen->pixels ) { + SDL_free(this->screen->pixels); + } + this->screen->pixels = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/svga/SDL_svgavideo.h b/3rdparty/SDL/src/video/svga/SDL_svgavideo.h new file mode 100644 index 0000000..7fb86cb --- /dev/null +++ b/3rdparty/SDL/src/video/svga/SDL_svgavideo.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_svgavideo_h +#define _SDL_svgavideo_h + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Private display data */ +struct SDL_PrivateVideoData { +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + int *SDL_vgamode[NUM_MODELISTS]; + + /* information for double-buffering */ + int flip_page; + int flip_offset[2]; + Uint8 *flip_address[2]; + + /* Set to 1 if we're in banked video mode */ + int banked; +}; +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_vgamode (this->hidden->SDL_vgamode) +#define flip_page (this->hidden->flip_page) +#define flip_offset (this->hidden->flip_offset) +#define flip_address (this->hidden->flip_address) +#define banked (this->hidden->banked) + +#endif /* _SDL_svgavideo_h */ + diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp new file mode 100644 index 0000000..5ceed5f --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocevents.cpp @@ -0,0 +1,626 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents.cpp + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) +*/ + + +#include <stdio.h> +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +}; /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include<linereader.h> +#include<bautils.h> + + +#include <hal.h> + +extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +}; /* extern "C" */ + +TBool isCursorVisible = EFalse; + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { + + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } + + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + TPoint mousePos = pointerEvent->iPosition; + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->EPOC_IsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { +/* + CFbsBitmap* bmp = new (ELeave) CFbsBitmap(); + bmp->Create(Private->EPOC_ScreenSize, Private->EPOC_DisplayMode); + Private->EPOC_WsScreen->CopyScreenToBitmap(bmp); + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + Private->EPOC_WsWindow.BeginRedraw(TRect(Private->EPOC_WsWindow.Size())); + Private->EPOC_WindowGc->BitBlt(TPoint(0, 0), bmp); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + bmp->Save(_L("C:\\scr.mbm")); + delete bmp; +*/ + + Private->EPOC_IsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + RWsSession s; + s.Connect(); + RWindowGroup g(s); + g.Construct(TUint32(&g), EFalse); + g.EnableReceiptOfFocus(EFalse); + RWindow w(s); + w.Construct(g, TUint32(&w)); + w.SetExtent(TPoint(0, 0), Private->EPOC_WsWindow.Size()); + w.SetOrdinalPosition(0); + w.Activate(); + w.Close(); + g.Close(); + s.Close(); + +/* + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(Private->EPOC_WsWindowGroupID, -1); + + + SDL_Delay(500); + TInt focus = -1; + while(focus < 0) + { + const TInt curr = Private->EPOC_WsSession.GetFocusWindowGroup(); + if(curr != Private->EPOC_WsWindowGroupID) + focus = curr; + else + SDL_Delay(500); + } + + if(1 < Private->EPOC_WsSession.GetWindowGroupOrdinalPriority(Private->EPOC_WsWindowGroupID)) + { + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, -1); + SDL_Delay(500); + Private->EPOC_WsSession.SetWindowGroupOrdinalPosition(focus, 0); + } +*/ + /*//and the request redraw + TRawEvent redrawEvent; + redrawEvent.Set(TRawEvent::ERedraw); + Private->EPOC_WsSession.SimulateRawEvent(redrawEvent); + Private->EPOC_WsSession.Flush();*/ +#if 0 + //!! Not used + // Wait and eat events until focus is gained again + while (ETrue) { + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + User::WaitForRequest(Private->EPOC_WsEventStatus); + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + TInt eventType = Private->EPOC_WsEvent.Type(); + Private->EPOC_WsEventStatus = KRequestPending; + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + if (eventType == EEventFocusGained) { + RedrawWindowL(_this); + break; + } + } +#endif + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) +{ + int posted = 0; // !! Do we need this? + //Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + while (Private->EPOC_WsEventStatus != KRequestPending) { + + Private->EPOC_WsSession.GetEvent(Private->EPOC_WsEvent); + posted = EPOC_HandleWsEvent(_this, Private->EPOC_WsEvent); + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + } +} + + +_LIT(KMapFileName, "C:\\sdl_info\\sdlkeymap.cfg"); +LOCAL_C void ReadL(RFs& aFs, RArray<TInt>& aArray) + { + TInt drive = -1; + TFileName name(KMapFileName); + for(TInt i = 'z'; drive < 0 && i >= 'a'; i--) + { + name[0] = (TUint16)i; + if(BaflUtils::FileExists(aFs, name)) + drive = i; + } + if(drive < 0) + return; + CLineReader* reader = CLineReader::NewLC(aFs, name); + while(reader->NextL()) + { + TPtrC ln = reader->Current(); + TLex line(ln); + TInt n = 0; + for(;;) + { + const TPtrC token = line.NextToken(); + if(token.Length() == 0) + break; + if((n & 1) != 0) + { + TInt value; + TLex lex(token); + User::LeaveIfError(lex.Val(value)); + User::LeaveIfError(aArray.Append(value)); + } + n++; + } + } + CleanupStack::PopAndDestroy(); + } + + +void EPOC_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + + /* Numbers */ + for ( i = 0; i<32; ++i ){ + keymap[' ' + i] = (SDLKey)(SDLK_SPACE+i); + } + /* e.g. Alphabet keys */ + for ( i = 0; i<32; ++i ){ + keymap['A' + i] = (SDLKey)(SDLK_a+i); + } + + keymap[EStdKeyBackspace] = SDLK_BACKSPACE; + keymap[EStdKeyTab] = SDLK_TAB; + keymap[EStdKeyEnter] = SDLK_RETURN; + keymap[EStdKeyEscape] = SDLK_ESCAPE; + keymap[EStdKeySpace] = SDLK_SPACE; + keymap[EStdKeyPause] = SDLK_PAUSE; + keymap[EStdKeyHome] = SDLK_HOME; + keymap[EStdKeyEnd] = SDLK_END; + keymap[EStdKeyPageUp] = SDLK_PAGEUP; + keymap[EStdKeyPageDown] = SDLK_PAGEDOWN; + keymap[EStdKeyDelete] = SDLK_DELETE; + keymap[EStdKeyUpArrow] = SDLK_UP; + keymap[EStdKeyDownArrow] = SDLK_DOWN; + keymap[EStdKeyLeftArrow] = SDLK_LEFT; + keymap[EStdKeyRightArrow] = SDLK_RIGHT; + keymap[EStdKeyCapsLock] = SDLK_CAPSLOCK; + keymap[EStdKeyLeftShift] = SDLK_LSHIFT; + keymap[EStdKeyRightShift] = SDLK_RSHIFT; + keymap[EStdKeyLeftAlt] = SDLK_LALT; + keymap[EStdKeyRightAlt] = SDLK_RALT; + keymap[EStdKeyLeftCtrl] = SDLK_LCTRL; + keymap[EStdKeyRightCtrl] = SDLK_RCTRL; + keymap[EStdKeyLeftFunc] = SDLK_LMETA; + keymap[EStdKeyRightFunc] = SDLK_RMETA; + keymap[EStdKeyInsert] = SDLK_INSERT; + keymap[EStdKeyComma] = SDLK_COMMA; + keymap[EStdKeyFullStop] = SDLK_PERIOD; + keymap[EStdKeyForwardSlash] = SDLK_SLASH; + keymap[EStdKeyBackSlash] = SDLK_BACKSLASH; + keymap[EStdKeySemiColon] = SDLK_SEMICOLON; + keymap[EStdKeySingleQuote] = SDLK_QUOTE; + keymap[EStdKeyHash] = SDLK_HASH; + keymap[EStdKeySquareBracketLeft] = SDLK_LEFTBRACKET; + keymap[EStdKeySquareBracketRight] = SDLK_RIGHTBRACKET; + keymap[EStdKeyMinus] = SDLK_MINUS; + keymap[EStdKeyEquals] = SDLK_EQUALS; + + keymap[EStdKeyF1] = SDLK_F1; /* chr + q */ + keymap[EStdKeyF2] = SDLK_F2; /* chr + w */ + keymap[EStdKeyF3] = SDLK_F3; /* chr + e */ + keymap[EStdKeyF4] = SDLK_F4; /* chr + r */ + keymap[EStdKeyF5] = SDLK_F5; /* chr + t */ + keymap[EStdKeyF6] = SDLK_F6; /* chr + y */ + keymap[EStdKeyF7] = SDLK_F7; /* chr + i */ + keymap[EStdKeyF8] = SDLK_F8; /* chr + o */ + + keymap[EStdKeyF9] = SDLK_F9; /* chr + a */ + keymap[EStdKeyF10] = SDLK_F10; /* chr + s */ + keymap[EStdKeyF11] = SDLK_F11; /* chr + d */ + keymap[EStdKeyF12] = SDLK_F12; /* chr + f */ + + #ifndef SYMBIAN_CRYSTAL + //!!7650 additions + #ifdef __WINS__ + keymap[EStdKeyXXX] = SDLK_RETURN; /* "fire" key */ + #else + keymap[EStdKeyDevice3] = SDLK_RETURN; /* "fire" key */ + #endif + keymap[EStdKeyNkpAsterisk] = SDLK_ASTERISK; + keymap[EStdKeyYes] = SDLK_HOME; /* "call" key */ + keymap[EStdKeyNo] = SDLK_END; /* "end call" key */ + keymap[EStdKeyDevice0] = SDLK_SPACE; /* right menu key */ + keymap[EStdKeyDevice1] = SDLK_ESCAPE; /* left menu key */ + keymap[EStdKeyDevice2] = SDLK_POWER; /* power key */ + #endif + + #ifdef SYMBIAN_CRYSTAL + keymap[EStdKeyMenu] = SDLK_ESCAPE; // menu key + keymap[EStdKeyDevice6] = SDLK_LEFT; // Rocker (joystick) left + keymap[EStdKeyDevice7] = SDLK_RIGHT; // Rocker (joystick) right + keymap[EStdKeyDevice8] = SDLK_UP; // Rocker (joystick) up + keymap[EStdKeyDevice9] = SDLK_DOWN; // Rocker (joystick) down + keymap[EStdKeyLeftFunc] = SDLK_LALT; //chr? + keymap[EStdKeyRightFunc] = SDLK_RALT; + keymap[EStdKeyDeviceA] = SDLK_RETURN; /* "fire" key */ +#endif + + /////////////////////////////////////////////////////////// + + RFs fs; + if(KErrNone == fs.Connect()) + { + RArray<TInt> array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close(); + /////////////////////////////////////////////////////////// + + /* !!TODO + EStdKeyNumLock=0x1b, + EStdKeyScrollLock=0x1c, + + EStdKeyNkpForwardSlash=0x84, + EStdKeyNkpAsterisk=0x85, + EStdKeyNkpMinus=0x86, + EStdKeyNkpPlus=0x87, + EStdKeyNkpEnter=0x88, + EStdKeyNkp1=0x89, + EStdKeyNkp2=0x8a, + EStdKeyNkp3=0x8b, + EStdKeyNkp4=0x8c, + EStdKeyNkp5=0x8d, + EStdKeyNkp6=0x8e, + EStdKeyNkp7=0x8f, + EStdKeyNkp8=0x90, + EStdKeyNkp9=0x91, + EStdKeyNkp0=0x92, + EStdKeyNkpFullStop=0x93, + EStdKeyMenu=0x94, + EStdKeyBacklightOn=0x95, + EStdKeyBacklightOff=0x96, + EStdKeyBacklightToggle=0x97, + EStdKeyIncContrast=0x98, + EStdKeyDecContrast=0x99, + EStdKeySliderDown=0x9a, + EStdKeySliderUp=0x9b, + EStdKeyDictaphonePlay=0x9c, + EStdKeyDictaphoneStop=0x9d, + EStdKeyDictaphoneRecord=0x9e, + EStdKeyHelp=0x9f, + EStdKeyOff=0xa0, + EStdKeyDial=0xa1, + EStdKeyIncVolume=0xa2, + EStdKeyDecVolume=0xa3, + EStdKeyDevice0=0xa4, + EStdKeyDevice1=0xa5, + EStdKeyDevice2=0xa6, + EStdKeyDevice3=0xa7, + EStdKeyDevice4=0xa8, + EStdKeyDevice5=0xa9, + EStdKeyDevice6=0xaa, + EStdKeyDevice7=0xab, + EStdKeyDevice8=0xac, + EStdKeyDevice9=0xad, + EStdKeyDeviceA=0xae, + EStdKeyDeviceB=0xaf, + EStdKeyDeviceC=0xb0, + EStdKeyDeviceD=0xb1, + EStdKeyDeviceE=0xb2, + EStdKeyDeviceF=0xb3, + EStdKeyApplication0=0xb4, + EStdKeyApplication1=0xb5, + EStdKeyApplication2=0xb6, + EStdKeyApplication3=0xb7, + EStdKeyApplication4=0xb8, + EStdKeyApplication5=0xb9, + EStdKeyApplication6=0xba, + EStdKeyApplication7=0xbb, + EStdKeyApplication8=0xbc, + EStdKeyApplication9=0xbd, + EStdKeyApplicationA=0xbe, + EStdKeyApplicationB=0xbf, + EStdKeyApplicationC=0xc0, + EStdKeyApplicationD=0xc1, + EStdKeyApplicationE=0xc2, + EStdKeyApplicationF=0xc3, + EStdKeyYes=0xc4, + EStdKeyNo=0xc5, + EStdKeyIncBrightness=0xc6, + EStdKeyDecBrightness=0xc7, + EStdKeyCaseOpen=0xc8, + EStdKeyCaseClose=0xc9 + */ + +} + + + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +}; /* extern "C" */ + + diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp new file mode 100644 index 0000000..06874d5 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.cpp @@ -0,0 +1,1356 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Thanks to Peter van Sebille, the author of EMame. It is a great example of + low level graphics coding in Epoc. + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) + Assembler routines by Kimmo Kinnunen +*/ + + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +}; + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdl_epocruntime.h" + +#include <hal.h> +#include <coedef.h> +#include <flogger.h> + +#ifdef SYMBIAN_QUARTZ +SDL_VideoDevice* _thisDevice; +#endif + +_LIT(KLibName, "SDL"); + +/* For debugging */ + +//if old SOS, from 7.x this is public! +class CLockable : public CFbsBitmap + { + public: + static CLockable* Lockable(CFbsBitmap* aBmp) {return static_cast<CLockable*>(aBmp);} + void Lock() {LockHeap();} + void Unlock() {UnlockHeap();} + }; +#define LockHeap(x) CLockable::Lockable(x)->Lock() +#define UnlockHeap(x) CLockable::Lockable(x)->Unlock() + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + + +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); + + + +/* !!For 12 bit screen HW. Table for fast conversion from 8 bit to 12 bit */ +// TUint16 is enough, but using TUint32 so we can use better instruction selection on ARMI +static TUint32 EPOC_HWPalette_256_to_Screen[256]; + +VideoBootStrap EPOC_bootstrap = { + "epoc", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + +const TUint32 WindowClientHandle = 9210; //!! const + +/* Epoc video driver bootstrap functions */ + +static int EPOC_Available(void) +{ + return 1; /* Always available */ +} + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) +{ + free(device->hidden); + free(device); +} + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) +{ + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + free(device); + } + return(0); + } + memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +int GetBpp(TDisplayMode displaymode) +{ + /*TInt numColors = TDisplayModeUtils::NumDisplayModeColors(displaymode); + TInt bitsPerPixel = 1; + for (TInt32 i = 2; i < numColors; i <<= 1, bitsPerPixel++); + return bitsPerPixel;*/ + return TDisplayModeUtils::NumDisplayModeBitsPerPixel(displaymode); +} + + +void DisableKeyBlocking(_THIS) + { + // Disable key blocking + TRawEvent event; + event.Set((TRawEvent::TType)/*EDisableKeyBlock*/51); // !!EDisableKeyBlock not found in epoc32\include! + Private->EPOC_WsSession.SimulateRawEvent(event); + } + +void ConstructWindowL(_THIS) +{ + TInt error; + + SDL_TRACE("SDL:ConstructWindowL"); + error = Private->EPOC_WsSession.Connect(); + User::LeaveIfError(error); + Private->EPOC_WsScreen=new(ELeave) CWsScreenDevice(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsScreen->Construct()); + User::LeaveIfError(Private->EPOC_WsScreen->CreateContext(Private->EPOC_WindowGc)); + + Private->EPOC_WsWindowGroup=RWindowGroup(Private->EPOC_WsSession); + User::LeaveIfError(Private->EPOC_WsWindowGroup.Construct(WindowClientHandle)); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0); + + // Set window group name (the same as process name)) !!Gives always "EPOC" in WINS + RProcess thisProcess; + TParse exeName; + exeName.Set(thisProcess.FileName(), NULL, NULL); + TBuf<32> winGroupName; + winGroupName.Append(0); + winGroupName.Append(0); + winGroupName.Append(0);// uid + winGroupName.Append(0); + winGroupName.Append(exeName.Name()); // caption + winGroupName.Append(0); + winGroupName.Append(0); //doc name + Private->EPOC_WsWindowGroup.SetName(winGroupName); + + Private->EPOC_WsWindow=RWindow(Private->EPOC_WsSession); + // Markus, it was: + // User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle )); + // but SOS 7.0s debug does not accept same window handle twice + User::LeaveIfError(Private->EPOC_WsWindow.Construct(Private->EPOC_WsWindowGroup,WindowClientHandle - 1)); + Private->EPOC_WsWindow.SetBackgroundColor(KRgbWhite); + Private->EPOC_WsWindow.Activate(); + Private->EPOC_WsWindow.SetSize(Private->EPOC_WsScreen->SizeInPixels()); + Private->EPOC_WsWindow.SetVisible(ETrue); + + Private->EPOC_WsWindowGroupID = Private->EPOC_WsWindowGroup.Identifier(); + Private->EPOC_IsWindowFocused = EFalse; + + DisableKeyBlocking(_this); //disable key blocking +} + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + // !!TODO:handle leave functions! + + int i; + + SDL_TRACE("SDL:EPOC_VideoInit"); + + /* Initialize all variables that we clean on shutdown */ + + for ( i=0; i<SDL_NUMMODES; ++i ) { + Private->SDL_modelist[i] = (SDL_Rect *)malloc(sizeof(SDL_Rect)); + Private->SDL_modelist[i]->x = Private->SDL_modelist[i]->y = 0; + } + + /* Modes sorted largest to smallest */ + Private->SDL_modelist[0]->w = 800; Private->SDL_modelist[0]->h = 250; + Private->SDL_modelist[1]->w = 640; Private->SDL_modelist[1]->h = 480; + Private->SDL_modelist[2]->w = 480; Private->SDL_modelist[2]->h = 600; + Private->SDL_modelist[3]->w = 640; Private->SDL_modelist[3]->h = 400; + Private->SDL_modelist[4]->w = 352; Private->SDL_modelist[4]->h = 416; + Private->SDL_modelist[5]->w = 416; Private->SDL_modelist[5]->h = 352; + Private->SDL_modelist[6]->w = 416; Private->SDL_modelist[6]->h = 312; + Private->SDL_modelist[7]->w = 352; Private->SDL_modelist[7]->h = 264; + Private->SDL_modelist[8]->w = 800; Private->SDL_modelist[8]->h = 240; //for doom all these.. + Private->SDL_modelist[9]->w = 640; Private->SDL_modelist[9]->h = 240; + Private->SDL_modelist[10]->w = 480; Private->SDL_modelist[10]->h = 240; + Private->SDL_modelist[11]->w = 640; Private->SDL_modelist[11]->h = 240; + Private->SDL_modelist[12]->w = 352; Private->SDL_modelist[12]->h = 240; + Private->SDL_modelist[13]->w = 416; Private->SDL_modelist[13]->h = 240; + Private->SDL_modelist[14]->w = 416; Private->SDL_modelist[14]->h = 240; + Private->SDL_modelist[15]->w = 352; Private->SDL_modelist[15]->h = 240; + Private->SDL_modelist[16]->w = 640; Private->SDL_modelist[16]->h = 200; + Private->SDL_modelist[17]->w = 320; Private->SDL_modelist[17]->h = 240; //...for doom, currently engine renders no-higher windows :-(, propably should get fixed + Private->SDL_modelist[18]->w = 320; Private->SDL_modelist[18]->h = 200; + Private->SDL_modelist[19]->w = 256; Private->SDL_modelist[19]->h = 192; + Private->SDL_modelist[20]->w = 176; Private->SDL_modelist[20]->h = 208; + Private->SDL_modelist[21]->w = 208; Private->SDL_modelist[21]->h = 176; // Rotated + Private->SDL_modelist[22]->w = 160; Private->SDL_modelist[22]->h = 144; + + Private->SDL_modelist[23]->w = 640; Private->SDL_modelist[2]->h = 200; //s80 some new modes + Private->SDL_modelist[24]->w = 640; Private->SDL_modelist[2]->h = 320; //s90 modes are added + Private->SDL_modelist[25]->w = 640; Private->SDL_modelist[2]->h = 240; //here + Private->SDL_modelist[26]->w = 640; Private->SDL_modelist[4]->h = 200; //now + + Private->SDL_modelist[27] = NULL; + + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + TDisplayMode displayMode = Private->EPOC_WsScreen->DisplayMode(); + +#if !defined(__WINS__) && !defined(TEST_BM_DRAW) + + TScreenInfoV01 screenInfo; + TPckg<TScreenInfoV01> sInfo(screenInfo); + UserSvr::ScreenInfo(sInfo); + + Private->EPOC_ScreenSize = screenInfo.iScreenSize; + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = screenInfo.iScreenAddressValid; + Private->EPOC_FrameBuffer = Private->EPOC_HasFrameBuffer ? (TUint8*) screenInfo.iScreenAddress : NULL; + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + + Private->EPOC_BytesPerScanLine = screenInfo.iScreenSize.iWidth * Private->EPOC_BytesPerPixel; + Private->EPOC_BytesPerScreen = Private->EPOC_BytesPerScanLine * Private->EPOC_ScreenSize.iHeight; + + SDL_TRACE1("Screen width %d", screenInfo.iScreenSize.iWidth); + SDL_TRACE1("Screen height %d", screenInfo.iScreenSize.iHeight); + SDL_TRACE1("Screen dmode %d", displayMode); + SDL_TRACE1("Screen valid %d", screenInfo.iScreenAddressValid); + + SDL_TRACE1("bpp %d", Private->EPOC_BytesPerPixel); + SDL_TRACE1("bpsl %d", Private->EPOC_BytesPerScanLine); + SDL_TRACE1("bps %d", Private->EPOC_BytesPerScreen); + + + /* It seems that in SA1100 machines for 8bpp displays there is a 512 palette table at the + * beginning of the frame buffer. E.g. Series 7 and Netbook. + * In 12 bpp machines the table has 16 entries. + */ + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 8) + { + Private->EPOC_FrameBuffer += 512; + } + else + { + Private->EPOC_FrameBuffer += 32; + } + /*if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 12) + Private->EPOC_FrameBuffer += 16 * 2; + if (Private->EPOC_HasFrameBuffer && GetBpp(displayMode) == 16) + Private->EPOC_FrameBuffer += 16 * 2; + */ +#else /* defined __WINS__ */ + + /* Create bitmap, device and context for screen drawing */ + Private->EPOC_ScreenSize = Private->EPOC_WsScreen->SizeInPixels(); + + Private->EPOC_Bitmap = new (ELeave) CWsBitmap(Private->EPOC_WsSession); + Private->EPOC_Bitmap->Create(Private->EPOC_ScreenSize, displayMode); + + Private->EPOC_DisplayMode = displayMode; + Private->EPOC_HasFrameBuffer = ETrue; + Private->EPOC_FrameBuffer = NULL; /* Private->EPOC_Bitmap->DataAddress() can change any time */ + Private->EPOC_BytesPerPixel = ((GetBpp(displayMode)-1) / 8) + 1; + Private->EPOC_BytesPerScanLine = Private->EPOC_WsScreen->SizeInPixels().iWidth * Private->EPOC_BytesPerPixel; + +#endif /* __WINS__ */ + +#ifndef SYMBIAN_CRYSTAL + // Get draw device for updating the screen + TScreenInfoV01 screenInfo2; + + Epoc_Runtime::GetScreenInfo(screenInfo2); + + TRAPD(status, Private->EPOC_DrawDevice = CFbsDrawDevice::NewScreenDeviceL(screenInfo2, displayMode)); + User::LeaveIfError(status); +#endif + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = /*!!GetBpp(displayMode) */ 8; + vformat->BytesPerPixel = /*!!Private->EPOC_BytesPerPixel*/ 1; + + /* Activate events for me */ + + Private->EPOC_WsEventStatus = KRequestPending; + Private->EPOC_WsSession.EventReady(&Private->EPOC_WsEventStatus); + + SDL_TRACE("SDL:WsEventStatus"); + User::WaitForRequest(Private->EPOC_WsEventStatus); //Markus: I added this and ... + + Private->EPOC_RedrawEventStatus = KRequestPending; + Private->EPOC_WsSession.RedrawReady(&Private->EPOC_RedrawEventStatus); + + SDL_TRACE("SDL:RedrawEventStatus"); + User::WaitForRequest(Private->EPOC_RedrawEventStatus); //...this, if not catches a stray event is risen + //if there are active objects used, or confucing + //actions with User::WaitForAnyRequest + Private->EPOC_WsWindow.PointerFilter(EPointerFilterDrag, 0); + + Private->EPOC_ScreenOffset = TPoint(0, 0); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap +#endif + + SDL_TRACE("SDL:DrawBackground"); + DrawBackground(_this); // Clear screen + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + UnlockHeap(Private->EPOC_Bitmap); // Unlock bitmap heap +#endif + //!! TODO: error handling + //if (ret != KErrNone) + // return(-1); + //else + return(0); +} + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 /*flags*/) +{ + if (format->BitsPerPixel == 12 || format->BitsPerPixel == 8) + return Private->SDL_modelist; + return NULL; +} + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + if ((firstcolor+ncolors) > 256) + return -1; +// SDL_TRACE1("colors %d", (TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode))); + if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + EPOC_HWPalette_256_to_Screen[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + EPOC_HWPalette_256_to_Screen[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(Private->EPOC_DisplayMode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + EPOC_HWPalette_256_to_Screen[i] = color16M; + } + } + else + { + return -2; + } + return(0); +} + + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 /*flags*/) +{ + SDL_TRACE("SDL:EPOC_SetVideoMode"); + /* Check parameters */ +#ifdef SYMBIAN_CRYSTAL + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 640 && height == 200) || + (width == 640 && height == 400) || + (width == 640 && height == 480) || + (width == 320 && height == 200) || + (width == 320 && height == 240) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#else // SYMBIAN_SERIES60 + if (! (bpp == 8 || bpp == 12 || bpp == 16) && + ( + (width == 320 && height == 200) || + (width == 320 && height == 240) || + (width == 256 && height == 192) || + (width == 176 && height == 208) || + (width == 208 && height == 176) || // Rotated + (width == 160 && height == 144) + )) { + SDL_SetError("Requested video mode is not supported"); + return NULL; + } +#endif + + if (current && current->pixels) { + free(current->pixels); + current->pixels = NULL; + } + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + + /* Set up the new mode framebuffer */ + if (bpp == 8) + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC|SDL_HWPALETTE); + else // 12 bpp, 16 bpp + current->flags = (SDL_FULLSCREEN|SDL_SWSURFACE|SDL_PREALLOC); + current->w = width; + current->h = height; + int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + current->pixels = malloc(width * height * numBytesPerPixel); + memset(current->pixels, 0, width * height * numBytesPerPixel); + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + int w = current->w; + int h = current->h; + + // Rotate, if the screen does not fit horizontally and it is landscape screen +/* + if ((width>Private->EPOC_ScreenSize.iWidth) && (width>height)) { + Private->EPOC_ScreenOrientation = CFbsBitGc::EGraphicsOrientationRotated270; + w = current->h; + h = current->w; + } +*/ + // Get nearest stepwise scale values for width and height. The smallest supported scaled screen is 1/2. + TInt scaleValue = 0; + Private->EPOC_ScreenXScaleValue = 1; + Private->EPOC_ScreenYScaleValue = 1; + if (w > Private->EPOC_ScreenSize.iWidth) { + // Find the biggest scale value that result the width that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledWidth = (w * (scaleValue-1))/scaleValue; + if (scaledWidth > Private->EPOC_ScreenSize.iWidth) + break; + } + Private->EPOC_ScreenXScaleValue = Max(2, scaleValue - 1); + w = (w * (Private->EPOC_ScreenXScaleValue-1))/Private->EPOC_ScreenXScaleValue; + } + if (h > Private->EPOC_ScreenSize.iHeight) { + // Find the biggest scale value that result the height that fits in the screen HW + for (scaleValue = 2; scaleValue++;) { + TInt scaledHeight = (h * (scaleValue-1))/scaleValue; + if (scaledHeight > Private->EPOC_ScreenSize.iHeight) + break; + } + Private->EPOC_ScreenYScaleValue = Max(2, scaleValue - 1); + h = (h * (Private->EPOC_ScreenYScaleValue-1))/Private->EPOC_ScreenYScaleValue; + } + + /* Centralize game window on device screen */ + Private->EPOC_ScreenOffset.iX = (Private->EPOC_ScreenSize.iWidth - w) / 2; + if (Private->EPOC_ScreenOffset.iX < 0) + Private->EPOC_ScreenOffset.iX = 0; + Private->EPOC_ScreenOffset.iY = (Private->EPOC_ScreenSize.iHeight - h) / 2; + if (Private->EPOC_ScreenOffset.iY < 0) + Private->EPOC_ScreenOffset.iY = 0; + + + SDL_TRACE1("View width %d", w); + SDL_TRACE1("View height %d", h); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View s %d", scaleValue); + SDL_TRACE1("View x %d", Private->EPOC_ScreenOffset.iX); + SDL_TRACE1("View y %d", Private->EPOC_ScreenOffset.iY); + + /* We're done */ + return(current); +} + + +void RedrawWindowL(_THIS) +{ + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + LockHeap(Private->EPOC_Bitmap); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); +#endif + + int w = _this->screen->w; + int h = _this->screen->h; + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + w = _this->screen->h; + h = _this->screen->w; + } + if ((w < Private->EPOC_ScreenSize.iWidth) + || (h < Private->EPOC_ScreenSize.iHeight)) { + DrawBackground(_this); + } + + /* Tell the system that something has been drawn */ + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + UnlockHeap(Private->EPOC_Bitmap);; // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#endif + + /* Draw current buffer */ + SDL_Rect fullScreen; + fullScreen.x = 0; + fullScreen.y = 0; + fullScreen.w = _this->screen->w; + fullScreen.h = _this->screen->h; + EPOC_DirectUpdate(_this, 1, &fullScreen); +} + + +void DrawBackground(_THIS) +{ + /* Draw background */ +#if defined(__WINS__) || defined(TEST_BM_DRAW) + //warning heap is not locked! - a function calling must ensure that it's ok + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + // Draw black background + Mem::FillZ(screenBuffer, Private->EPOC_BytesPerScreen); + +#if 0 + for (int y = 0; y < Private->EPOC_ScreenSize.iHeight; y++) { + for (int x = 0; x < Private->EPOC_ScreenSize.iWidth; x++) { +#ifdef SYMBIAN_CRYSTAL + const TUint16 color = 0; // ((x+y)>>1) & 0xf; /* Draw blue stripes pattern, because in e.g. 320x200 mode there is a big background area*/ +#else // SYMBIAN_SERIES60 + const TUint16 color = 0; /* Draw black background */ +#endif + *screenBuffer++ = color; + } + } +#endif +} + + +/* We don't actually allow hardware surfaces other than the main one */ +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(-1); +} +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return; +} + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) +{ + return(0); +} + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + //TInt focusWindowGroupId = Private->EPOC_WsSession.GetFocusWindowGroup();//these are async services + // if (focusWindowGroupId != Private->EPOC_WsWindowGroupID) { //for that cannot be called from + //SDL threads ??? + if (!Private->EPOC_IsWindowFocused) + { + /* Force focus window to redraw again for cleaning away SDL screen graphics */ +/* + TInt pos = Private->EPOC_WsWindowGroup.OrdinalPosition(); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(0, KMaxTInt); + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindowGroup.SetOrdinalPosition(pos, ECoeWinPriorityNormal); + */ /* If this is not the topmost window, wait here! Sleep for 1 second to give cpu time to + multitasking and poll for being the topmost window. + */ + // if (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) { + + /* !!TODO: Could call GetRedraw() etc. for WsSession and redraw the screen if needed. That might be + needed if a small dialog comes in front of Game screen. + */ + // while (Private->EPOC_WsSession.GetFocusWindowGroup() != Private->EPOC_WsWindowGroupID) + + SDL_PauseAudio(1); + SDL_Delay(1000); + return; + // } + + // RedrawWindowL(_this); + } + + SDL_PauseAudio(0); + + // if we are not focused, do not draw +// if (!Private->EPOC_IsWindowFocused) +// return; +#if defined(__WINS__) || defined(TEST_BM_DRAW) + TBitmapUtil lock(Private->EPOC_Bitmap); + lock.Begin(TPoint(0,0)); // Lock bitmap heap + Private->EPOC_WindowGc->Activate(Private->EPOC_WsWindow); + TUint16* screenBuffer = (TUint16*)Private->EPOC_Bitmap->DataAddress(); +#else + TUint16* screenBuffer = (TUint16*)Private->EPOC_FrameBuffer; +#endif + + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) + DirectDrawRotated(_this, numrects, rects, screenBuffer); + else + DirectDraw(_this, numrects, rects, screenBuffer); + + +#if defined(__WINS__) || defined(TEST_BM_DRAW) + + TRect rect = TRect(Private->EPOC_WsWindow.Size()); + Private->EPOC_WsWindow.Invalidate(rect); + Private->EPOC_WsWindow.BeginRedraw(rect); + Private->EPOC_WindowGc->BitBlt(TPoint(), Private->EPOC_Bitmap); + Private->EPOC_WsWindow.EndRedraw(); + Private->EPOC_WindowGc->Deactivate(); + lock.End(); // Unlock bitmap heap + Private->EPOC_WsSession.Flush(); +#else +#ifndef SYMBIAN_CRYSTAL + // This is not needed in Crystal. What is the performance penalty in SERIES60? + TRect rect2 = TRect(Private->EPOC_WsWindow.Size()); + + Private->EPOC_DrawDevice->UpdateRegion(rect2); // Should we update rects parameter area only?? + Private->EPOC_DrawDevice->Update(); +#endif +#endif + + /* Update virtual cursor. !!Do not yet work properly + Private->EPOC_WsSession.SetPointerCursorPosition(Private->EPOC_WsSession.PointerCursorPosition()); + */ + + /*static int foo = 1; + + for ( int i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) + continue; + + + foo++; + if((foo % 200) == 0) + { + SDL_TRACE1("foo %d", foo); + CFbsBitmap* b = new (ELeave) CFbsBitmap; + SDL_TRACE1("bee %d", (int)b); + int e = b->Create(TSize(currentRect.w, currentRect.h), Private->EPOC_DisplayMode); + + SDL_TRACE1("err %d", e); + if(e != KErrNone) + User::Panic(_L("damn"), e); + + TBitmapUtil u(b); + u.Begin(TPoint(0, 0)); + TUint32* d = b->DataAddress(); + + SDL_TRACE1("addr %d", (int)d); + + for(TInt o = 0; o < currentRect.h; o++) + for(TInt p = 0; p < currentRect.w; p++) + { + u.SetPos(TPoint(p, o)); + u.SetPixel(0xFFFF); + } + + SDL_TRACE1("w %d", (int)currentRect.w); + SDL_TRACE1("h %d", (int)currentRect.h); + + SDL_TRACE1("addr %d", (int)Private->EPOC_DisplayMode); + + + const TUint f = (TUint)Private->EPOC_FrameBuffer; + const TUint y = (TUint)Private->EPOC_BytesPerScreen; + + + SDL_TRACE1("frame %u", f); + SDL_TRACE1("bytes %u", y); + + Mem::Copy(d, Private->EPOC_FrameBuffer, Private->EPOC_BytesPerScreen); + + SDL_TRACE("kopied"); + + u.End(); + TBuf<32> name; + name.Format(_L("C:\\nokia\\images\\doom%d.mbm"), (foo / 200)); + e= b->Save(name); + if(e != KErrNone) + User::Panic(_L("damned"), e); + delete b; + }}*/ +} + + +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + const TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = 1; // no skip + + TInt targetStartOffset = fixedOffset.iX + rect2.x + (fixedOffset.iY +rect2.y) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + if(Private->EPOC_BytesPerPixel <= 2) + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + else + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint32* screenMemory = reinterpret_cast<TUint32*>(screenBuffer + targetStartOffset); + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint32* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemoryLinePos < (reinterpret_cast<TUint32*>(screenBuffer) + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= reinterpret_cast<TUint32*>(screenBuffer), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(_L("SDL"), KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(_L("SDL"), KErrCorrupt)); + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos++]; + // bitmapPos+=skipValue; //TODO: optimize: separate loops for 1, 2 and n skip + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + } // switch + } // for +} + +/* +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; + const TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + const TPoint fixedOffset = Private->EPOC_ScreenOffset; + const TInt screenW = _this->screen->w; + const TInt screenH = _this->screen->h; + const TInt sourceScanlineLength = screenW; + const TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + +/* for ( i=0; i < numrects; ++i ) { + const SDL_Rect& currentRect = rects[i]; + SDL_Rect rect2; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ +/* continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ +/* TInt maxX = Min(screenW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(screenH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ +/* continue; + /* Clip from bottom */ +/* maxY = Min(maxY, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + +/* TInt sourceRectWidth = maxX - rect2.x + 1; + const TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + const TInt sourceRectHeight = maxY - rect2.y + 1; + const TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + const TUint skipValue = Private->EPOC_ScreenXScaleValue; //1; // no skip + + const TInt targetStartOffset = // = (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) ; + (skipValue > 1 ? + (fixedOffset.iX + (rect2.x / skipValue) + (fixedOffset.iY + rect2.y) * targetScanlineLength ) : + (fixedOffset.iX + rect2.x + (fixedOffset.iY + rect2.y) * targetScanlineLength )); + + __ASSERT_DEBUG(skipValue >= 1, User::Panic(KLibName, KErrArgument)); + + // Nokia7650 native mode: 12 bpp --> 12 bpp + // + switch (_this->screen->format->BitsPerPixel) + { + case 12: + { + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue == 1) + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + else + { + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + //TODO: optimize: separate loops for 1, 2 and n skip. Mem::Copy() can be used in unscaled case. + TUint16* bitmapPos = bitmapLine; /* 2 bytes per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ +/* for(TInt x = 0 ; x < sourceRectWidth ; x++) + { + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = *bitmapPos; + bitmapPos+=skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } + } + } + break; + // 256 color paletted mode: 8 bpp --> 12 bpp + // + default: + { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + if (skipValue > 1) + sourceRectWidth /= skipValue; +#if defined __MARM_ARMI__ + __asm volatile(" + mov %4, %4, lsl #1 @ targetScanLineLength is in pixels, we need it in bytes + 1: + mov r6, %0 @ bitmapLine + mov r7, %2 @ screenMemory + mov r8, %6 @ sourceRectWidth + 2: + ldrb r4, [%0], %7 @ r4 = *bitmapPos; bitmapPos += skipValue + ldr r5, [%1, r4, lsl #2] @ only 16 lower bits actually used + subs r8, r8, #1 @ x-- + strh r5, [%2], #2 @ *screenMemoryLinePos++ = r4 + bne 2b + + add %0, r6, %3 @ bitmapLine += sourceScanlineLength + add %2, r7, %4 @ screenMemory += targetScanlineLength + subs %5, %5, #1 @ sourceRectHeight-- + bne 1b + " + : // no output + // %0 %1 %2 %3 %4 %5 %6 %7 + : "r" (bitmapLine), "r" (&EPOC_HWPalette_256_to_Screen[0]), "r" (screenMemory), "r" (sourceScanlineLength), "r" (targetScanlineLength), "r" (sourceRectHeight), "r" (sourceRectWidth), "r" (skipValue) + : "r4", "r5", "r6", "r7", "r8" + ); +#else + for(TInt y = 0 ; y < sourceRectHeight ; y++) + { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ +/* TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + /* Convert each pixel from 256 palette to 4k color values */ +/* for (TInt x = 0 ; x < sourceRectWidth ; x++) + { + //__ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + //__ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos++ = EPOC_HWPalette_256_to_Screen[*bitmapPos]; + bitmapPos += skipValue; + } + bitmapLine += sourceScanlineLength; + screenMemory += targetScanlineLength; + } +//#endif + } + } // switch + } // for +} +*/ + +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer) +{ + TInt i; +// TInt sourceNumBytesPerPixel = ((_this->screen->format->BitsPerPixel-1)>>3) + 1; + TPoint fixedScreenOffset = Private->EPOC_ScreenOffset; + TInt bufferW = _this->screen->w; + TInt bufferH = _this->screen->h; + TInt ScreenW = Private->EPOC_ScreenSize.iWidth; +// TInt ScreenH = Private->EPOC_ScreenSize.iWidth; + TInt sourceW = bufferW; + TInt sourceH = bufferH; + TInt targetW = ScreenW - fixedScreenOffset.iX * 2; +// TInt targetH = ScreenH - fixedScreenOffset.iY * 2; + TInt sourceScanlineLength = bufferW; + TInt targetScanlineLength = Private->EPOC_ScreenSize.iWidth; + + /* Render the rectangles in the list */ + + for ( i=0; i < numrects; ++i ) { + SDL_Rect rect2; + const SDL_Rect& currentRect = rects[i]; + rect2.x = currentRect.x; + rect2.y = currentRect.y; + rect2.w = currentRect.w; + rect2.h = currentRect.h; + + if (rect2.w <= 0 || rect2.h <= 0) /* sanity check */ + continue; + + /* All variables are measured in pixels */ + + /* Check rects validity, i.e. upper and lower bounds */ + TInt maxX = Min(sourceW - 1, rect2.x + rect2.w - 1); + TInt maxY = Min(sourceH - 1, rect2.y + rect2.h - 1); + if (maxX < 0 || maxY < 0) /* sanity check */ + continue; + /* Clip from bottom */ + //maxX = Min(maxX, Private->EPOC_ScreenSize.iHeight-1); + /* TODO: Clip from the right side */ + + TInt sourceRectWidth = maxX - rect2.x + 1; +// TInt sourceRectWidthInBytes = sourceRectWidth * sourceNumBytesPerPixel; + TInt sourceRectHeight = maxY - rect2.y + 1; + TInt sourceStartOffset = rect2.x + rect2.y * sourceScanlineLength; + TInt targetStartOffset = fixedScreenOffset.iX + (targetW-1 - rect2.y) + (fixedScreenOffset.iY +rect2.x) * targetScanlineLength; + + // Nokia7650 native mode: 12 bpp --> 12 bpp + if (_this->screen->format->BitsPerPixel == 12) { + + /* !!TODO: not yet implemented + + TUint16* bitmapLine = (TUint16*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + //TODO: optimize: separate loops for 1, 2 and n skip + //Mem::Copy(screenMemory, bitmapLine, sourceRectWidthInBytes); + TUint16* bitmapPos = bitmapLine; // 2 bytes per pixel + TUint16* screenMemoryLinePos = screenMemory; // 2 bytes per pixel + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + + __ASSERT_DEBUG(screenMemory < (screenBuffer + Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemory >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine < ((TUint16*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapLine >= (TUint16*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = *bitmapPos; + bitmapPos++; + screenMemoryLinePos += targetScanlineLength; + } + bitmapLine += sourceScanlineLength; + screenMemory--; + } + + */ + } + // 256 color paletted mode: 8 bpp --> 12 bpp + else { + TUint8* bitmapLine = (TUint8*)_this->screen->pixels + sourceStartOffset; + TUint16* screenMemory = screenBuffer + targetStartOffset; + TInt screenXScaleValue = Private->EPOC_ScreenXScaleValue; + TInt debug_ycount=0; + for(TInt y = 0 ; y < sourceRectHeight ; y++) { + if(--screenXScaleValue) { + TUint8* bitmapPos = bitmapLine; /* 1 byte per pixel */ + TUint16* screenMemoryLinePos = screenMemory; /* 2 bytes per pixel */ + TInt screenYScaleValue = Private->EPOC_ScreenYScaleValue; + TInt debug_xcount=0; + /* Convert each pixel from 256 palette to 4k color values */ + for(TInt x = 0 ; x < sourceRectWidth ; x++) { + if(--screenYScaleValue) { + + __ASSERT_DEBUG(screenMemoryLinePos < (screenBuffer + (Private->EPOC_ScreenSize.iWidth * Private->EPOC_ScreenSize.iHeight)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(screenMemoryLinePos >= screenBuffer, User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos < ((TUint8*)_this->screen->pixels + (_this->screen->w * _this->screen->h)), User::Panic(KLibName, KErrCorrupt)); + __ASSERT_DEBUG(bitmapPos >= (TUint8*)_this->screen->pixels, User::Panic(KLibName, KErrCorrupt)); + + *screenMemoryLinePos = TUint16(EPOC_HWPalette_256_to_Screen[*bitmapPos]); + screenMemoryLinePos += targetScanlineLength; debug_xcount++; + } + else + screenYScaleValue = Private->EPOC_ScreenYScaleValue; + bitmapPos++; + } + screenMemory--; debug_ycount++; + } // endif + else + screenXScaleValue = Private->EPOC_ScreenXScaleValue; + bitmapLine += sourceScanlineLength; + } + } + } +} + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) +{ + int i; + + /* Free video mode lists */ + for ( i=0; i<SDL_NUMMODES; ++i ) { + if ( Private->SDL_modelist[i] != NULL ) { + free(Private->SDL_modelist[i]); + Private->SDL_modelist[i] = NULL; + } + } + + if ( _this->screen && (_this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, no memory buffer */ + _this->screen->pixels = NULL; + } + + if (_this->screen && _this->screen->pixels) { + free(_this->screen->pixels); + _this->screen->pixels = NULL; + } + + /* Free Epoc resources */ + + /* Disable events for me */ + if (Private->EPOC_WsEventStatus != KRequestPending) + Private->EPOC_WsSession.EventReadyCancel(); + if (Private->EPOC_RedrawEventStatus != KRequestPending) + Private->EPOC_WsSession.RedrawReadyCancel(); + + #if defined(__WINS__) || defined(TEST_BM_DRAW) + delete Private->EPOC_Bitmap; + Private->EPOC_Bitmap = NULL; + #else + #endif + +#ifndef SYMBIAN_CRYSTAL + free(Private->EPOC_DrawDevice); +#endif + + if (Private->EPOC_WsWindow.WsHandle()) + Private->EPOC_WsWindow.Close(); + + if (Private->EPOC_WsWindowGroup.WsHandle()) + Private->EPOC_WsWindowGroup.Close(); + + delete Private->EPOC_WindowGc; + Private->EPOC_WindowGc = NULL; + + delete Private->EPOC_WsScreen; + Private->EPOC_WsScreen = NULL; + + if (Private->EPOC_WsSession.WsHandle()) + Private->EPOC_WsSession.Close(); +} + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) +{ + return (WMcursor *) 9210; // it's ok to return something unuseful but true +} + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) +{ + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); +} + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) +{ + + if (cursor == (WMcursor *)9210) { + /* Enable virtual cursor */ + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNormal); + if (isCursorVisible) + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + else + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + Private->EPOC_WsSession.SetPointerCursorMode(EPointerCursorNone); + } + + return(1); +} + +}; // extern "C" diff --git a/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h new file mode 100644 index 0000000..bd0b0e2 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA1/SDL_epocvideo.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef _SDL_epocvideo_h +#define _SDL_epocvideo_h + +#ifndef EKA2 +#include"SDL_epocvideo_org.h" +#else +#include"SDL_epocvideo2.h" +#endif + + +#endif + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp new file mode 100644 index 0000000..2452dae --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocevents.cpp @@ -0,0 +1,521 @@ +#include "epoc_sdl.h" + +#include <stdio.h> +#undef NULL +extern "C" { +//#define DEBUG_TRACE_ENABLED +#include "SDL_error.h" +#include "SDL_video.h" +#include "SDL_keysym.h" +#include "SDL_keyboard.h" +#include "SDL_events_c.h" +#include "SDL_timer.h" +} /* extern "C" */ + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + +#include "sdlepocapi.h" + +#include <eikenv.h> + +#include<bautils.h> + + +extern "C" + { + static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); + } + +//extern "C" { +/* The translation tables from a console scancode to a SDL keysym */ +static SDLKey keymap[MAX_SCANCODE]; +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); +void DisableKeyBlocking(_THIS); +//} /* extern "C" */ + +SDLKey* KeyMap() + { + return keymap; + } + +TBool isCursorVisible = EFalse; + +void ResetKeyMap() + { + int i; + + /* Initialize the key translation table */ + for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + + /* Numbers */ + for ( i = 0; i<32; ++i ){ + keymap[' ' + i] = (SDLKey)(SDLK_SPACE+i); + } + /* e.g. Alphabet keys */ + for ( i = 0; i<32; ++i ){ + keymap['A' + i] = (SDLKey)(SDLK_a+i); + } + + keymap[EStdKeyBackspace] = SDLK_BACKSPACE; + keymap[EStdKeyTab] = SDLK_TAB; + keymap[EStdKeyEnter] = SDLK_RETURN; + keymap[EStdKeyEscape] = SDLK_ESCAPE; + keymap[EStdKeySpace] = SDLK_SPACE; + keymap[EStdKeyPause] = SDLK_PAUSE; + keymap[EStdKeyHome] = SDLK_HOME; + keymap[EStdKeyEnd] = SDLK_END; + keymap[EStdKeyPageUp] = SDLK_PAGEUP; + keymap[EStdKeyPageDown] = SDLK_PAGEDOWN; + keymap[EStdKeyDelete] = SDLK_DELETE; + keymap[EStdKeyUpArrow] = SDLK_UP; + keymap[EStdKeyDownArrow] = SDLK_DOWN; + keymap[EStdKeyLeftArrow] = SDLK_LEFT; + keymap[EStdKeyRightArrow] = SDLK_RIGHT; + keymap[EStdKeyCapsLock] = SDLK_CAPSLOCK; + keymap[EStdKeyLeftShift] = SDLK_LSHIFT; + keymap[EStdKeyRightShift] = SDLK_RSHIFT; + keymap[EStdKeyLeftAlt] = SDLK_LALT; + keymap[EStdKeyRightAlt] = SDLK_RALT; + keymap[EStdKeyLeftCtrl] = SDLK_LCTRL; + keymap[EStdKeyRightCtrl] = SDLK_RCTRL; + keymap[EStdKeyLeftFunc] = SDLK_LMETA; + keymap[EStdKeyRightFunc] = SDLK_RMETA; + keymap[EStdKeyInsert] = SDLK_INSERT; + keymap[EStdKeyComma] = SDLK_COMMA; + keymap[EStdKeyFullStop] = SDLK_PERIOD; + keymap[EStdKeyForwardSlash] = SDLK_SLASH; + keymap[EStdKeyBackSlash] = SDLK_BACKSLASH; + keymap[EStdKeySemiColon] = SDLK_SEMICOLON; + keymap[EStdKeySingleQuote] = SDLK_QUOTE; + keymap[EStdKeyHash] = SDLK_HASH; + keymap[EStdKeySquareBracketLeft] = SDLK_LEFTBRACKET; + keymap[EStdKeySquareBracketRight] = SDLK_RIGHTBRACKET; + keymap[EStdKeyMinus] = SDLK_MINUS; + keymap[EStdKeyEquals] = SDLK_EQUALS; + + keymap[EStdKeyF1] = SDLK_F1; + keymap[EStdKeyF2] = SDLK_F2; + keymap[EStdKeyF3] = SDLK_F3; + keymap[EStdKeyF4] = SDLK_F4; + keymap[EStdKeyF5] = SDLK_F5; + keymap[EStdKeyF6] = SDLK_F6; + keymap[EStdKeyF7] = SDLK_F7; + keymap[EStdKeyF8] = SDLK_F8; + + keymap[EStdKeyF9] = SDLK_F9; + keymap[EStdKeyF10] = SDLK_F10; + keymap[EStdKeyF11] = SDLK_F11; + keymap[EStdKeyF12] = SDLK_F12; + + + keymap[EStdKeyXXX] = SDLK_RETURN; /* "fire" key */ + + keymap[EStdKeyDevice3] = SDLK_RETURN; /* "fire" key */ + keymap[EStdKeyNkpAsterisk] = SDLK_ASTERISK; + keymap[EStdKeyYes] = SDLK_HOME; /* "call" key */ + keymap[EStdKeyNo] = SDLK_END; /* "end call" key */ + keymap[EStdKeyDevice0] = SDLK_SPACE; /* right menu key */ + keymap[EStdKeyDevice1] = SDLK_ESCAPE; /* left menu key */ + keymap[EStdKeyDevice2] = SDLK_POWER; /* power key */ + + keymap[EStdKeyMenu] = SDLK_MENU; // menu key + keymap[EStdKeyDevice6] = SDLK_LEFT; // Rocker (joystick) left + keymap[EStdKeyDevice7] = SDLK_RIGHT; // Rocker (joystick) right + keymap[EStdKeyDevice8] = SDLK_UP; // Rocker (joystick) up + keymap[EStdKeyDevice9] = SDLK_DOWN; // Rocker (joystick) down + keymap[EStdKeyLeftFunc] = SDLK_LALT; //chr? + keymap[EStdKeyRightFunc] = SDLK_RALT; + keymap[EStdKeyDeviceA] = SDLK_RETURN; /* "fire" key */ + + + + + + /////////////////////////////////////////////////////////// + /* + RFs fs; + if(KErrNone == fs.Connect()) + { + RArray<TInt> array; + TRAPD(err, ReadL(fs, array)); + if(err == KErrNone && array.Count() > 0) + { + + SDLKey temp[MAX_SCANCODE]; + Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); + + for(TInt k = 0; k < array.Count(); k+= 2) + { + const TInt oldval = array[k]; + const TInt newval = array[k + 1]; + if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) + { + keymap[oldval] = temp[newval]; + } + } + } + array.Close(); + } + + fs.Close();*/ + /////////////////////////////////////////////////////////// + + + keymap[EStdKeyNumLock] = SDLK_NUMLOCK; + keymap[EStdKeyScrollLock] = SDLK_SCROLLOCK; + + keymap[EStdKeyNkpForwardSlash] = SDLK_KP_DIVIDE; + keymap[EStdKeyNkpAsterisk] = SDLK_KP_MULTIPLY; + keymap[EStdKeyNkpMinus] = SDLK_KP_MINUS; + keymap[EStdKeyNkpPlus] = SDLK_KP_PLUS; + keymap[EStdKeyNkpEnter] = SDLK_KP_ENTER; + keymap[EStdKeyNkp1] = SDLK_KP1; + keymap[EStdKeyNkp2] = SDLK_KP2; + keymap[EStdKeyNkp3] = SDLK_KP3; + keymap[EStdKeyNkp4] = SDLK_KP4; + keymap[EStdKeyNkp5] = SDLK_KP5; + keymap[EStdKeyNkp6] = SDLK_KP6; + keymap[EStdKeyNkp7] = SDLK_KP7; + keymap[EStdKeyNkp8] = SDLK_KP8; + keymap[EStdKeyNkp9] = SDLK_KP9; + keymap[EStdKeyNkp0] = SDLK_KP0; + keymap[EStdKeyNkpFullStop] = SDLK_KP_PERIOD; + /* + keymap[EStdKeyMenu] = SDLK_MENU; should be, but not yet + keymap[EStdKeyBacklightOn] = + keymap[EStdKeyBacklightOff] = + keymap[EStdKeyBacklightToggle] = + keymap[EStdKeyIncContrast] = + keymap[EStdKeyDecContrast] = + keymap[EStdKeySliderDown] = + keymap[EStdKeySliderUp] = + keymap[EStdKeyDictaphonePlay] = + keymap[EStdKeyDictaphoneStop] = + keymap[EStdKeyDictaphoneRecord] = + keymap[EStdKeyHelp] = + keymap[EStdKeyOff] = + keymap[EStdKeyDial] = + keymap[EStdKeyIncVolume] = + keymap[EStdKeyDecVolume] = + keymap[EStdKeyDevice0] = + keymap[EStdKeyDevice1] = + keymap[EStdKeyDevice2] = + keymap[EStdKeyDevice3] = + keymap[EStdKeyDevice4] = + keymap[EStdKeyDevice5] = + keymap[EStdKeyDevice6] = + keymap[EStdKeyDevice7] = + keymap[EStdKeyDevice8] = + keymap[EStdKeyDevice9] = + keymap[EStdKeyDeviceA] = + keymap[EStdKeyDeviceB] = + keymap[EStdKeyDeviceC] = + keymap[EStdKeyDeviceD] = + keymap[EStdKeyDeviceE] = + keymap[EStdKeyDeviceF] = + keymap[EStdKeyApplication0] = + keymap[EStdKeyApplication1] = + keymap[EStdKeyApplication2] = + keymap[EStdKeyApplication3] = + keymap[EStdKeyApplication4] = + keymap[EStdKeyApplication5] = + keymap[EStdKeyApplication6] = + keymap[EStdKeyApplication7] = + keymap[EStdKeyApplication8] = + keymap[EStdKeyApplication9] = + keymap[EStdKeyApplicationA] = + keymap[EStdKeyApplicationB] = + keymap[EStdKeyApplicationC] = + keymap[EStdKeyApplicationD] = + keymap[EStdKeyApplicationE] = + keymap[EStdKeyApplicationF] = + keymap[EStdKeyYes] = + keymap[EStdKeyNo] = + keymap[EStdKeyIncBrightness] = + keymap[EStdKeyDecBrightness] = + keymap[EStdKeyCaseOpen] = + keymap[EStdKeyCaseClose] = */ + + + +} + + +int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) +{ + int posted = 0; + SDL_keysym keysym; + +// SDL_TRACE1("hws %d", aWsEvent.Type()); + + switch (aWsEvent.Type()) + { + case EEventPointer: /* Mouse pointer events */ + { +/* const TPointerCursorMode mode = EpocSdlEnv::PointerMode(); + + + if(mode == EPointerCursorNone) + { + return 0; //TODO: Find out why events are get despite of cursor should be off + } +*/ + const TPointerEvent* pointerEvent = aWsEvent.Pointer(); + const TPoint mousePos = EpocSdlEnv::WindowCoordinates(pointerEvent->iPosition); + + /*!! TODO Pointer do not yet work properly + //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! + + if (Private->EPOC_ShrinkedHeight) { + mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height + } + if (Private->EPOC_ShrinkedWidth) { + mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width + } + */ + + posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ + + switch (pointerEvent->iType) + { + case TPointerEvent::EButton1Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton1Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + break; + case TPointerEvent::EButton2Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton2Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); + break; + case TPointerEvent::EButton3Down: + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); + break; + case TPointerEvent::EButton3Up: + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); + break; + } // switch + break; + } + + case EEventKeyDown: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker down, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); + if(mode != EPointerCursorNone) + posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); + +#ifndef DISABLE_JOYSTICK + /* Special handling */ + switch((int)keysym.sym) { + case SDLK_CAPSLOCK: + if (!isCursorVisible) { + /* Enable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); + } + else { + /* Disable virtual cursor */ + HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); + } + isCursorVisible = !isCursorVisible; + break; + } +#endif + posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + case EEventKeyUp: /* Key events */ + { +#ifdef SYMBIAN_CRYSTAL + // special case: 9300/9500 rocker up, simulate left mouse button + if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) + { + posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); + } +#endif + posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); + break; + } + + case EEventFocusGained: /* SDL window got focus */ + { + Private->iIsWindowFocused = ETrue; + posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + /* Draw window background and screen buffer */ + DisableKeyBlocking(_this); //Markus: guess why:-) + + //RedrawWindowL(_this); + break; + } + + case EEventFocusLost: /* SDL window lost focus */ + { + + Private->iIsWindowFocused = EFalse; + + posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + + + break; + } + + case EEventModifiersChanged: + { + TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); + TUint modstate = KMOD_NONE; + if (modEvent->iModifiers == EModifierLeftShift) + modstate |= KMOD_LSHIFT; + if (modEvent->iModifiers == EModifierRightShift) + modstate |= KMOD_RSHIFT; + if (modEvent->iModifiers == EModifierLeftCtrl) + modstate |= KMOD_LCTRL; + if (modEvent->iModifiers == EModifierRightCtrl) + modstate |= KMOD_RCTRL; + if (modEvent->iModifiers == EModifierLeftAlt) + modstate |= KMOD_LALT; + if (modEvent->iModifiers == EModifierRightAlt) + modstate |= KMOD_RALT; + if (modEvent->iModifiers == EModifierLeftFunc) + modstate |= KMOD_LMETA; + if (modEvent->iModifiers == EModifierRightFunc) + modstate |= KMOD_RMETA; + if (modEvent->iModifiers == EModifierCapsLock) + modstate |= KMOD_CAPS; + SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); + break; + } + case EEventScreenDeviceChanged: + { + EpocSdlEnv::WaitDeviceChange(); + } + break; + default: + break; + } + + return posted; +} + +extern "C" { + +void EPOC_PumpEvents(_THIS) + { + MEventQueue& events = EpocSdlEnv::EventQueue(); + while(events.HasData()) + { + events.Lock(); + + //there have to be a copy, so we can release + //lock immediately. HandleWsEvent may cause + //deadlock otherwise. + + const TWsEvent event = events.Shift(); + events.Unlock(); +// const TWsEvent& event = events.Top(); + EPOC_HandleWsEvent(_this, event); +// events.Shift(); + } + } + + + +void EPOC_InitOSKeymap(_THIS) + { + ResetKeyMap(); + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventKeyMapInit ,0); + } + +static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) +{ +// char debug[256]; + //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! + + /* Set the keysym information */ + + keysym->scancode = scancode; + + if ((scancode >= MAX_SCANCODE) && + ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { + SDL_SetError("Too big scancode"); + keysym->scancode = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + return keysym; + } + + keysym->mod = SDL_GetModState(); + + /* Handle function keys: F1, F2, F3 ... */ + if (keysym->mod & KMOD_META) { + if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ + switch(scancode) { + case 'Q': scancode = EStdKeyF1; break; + case 'W': scancode = EStdKeyF2; break; + case 'E': scancode = EStdKeyF3; break; + case 'R': scancode = EStdKeyF4; break; + case 'T': scancode = EStdKeyF5; break; + case 'Y': scancode = EStdKeyF6; break; + case 'U': scancode = EStdKeyF7; break; + case 'I': scancode = EStdKeyF8; break; + case 'A': scancode = EStdKeyF9; break; + case 'S': scancode = EStdKeyF10; break; + case 'D': scancode = EStdKeyF11; break; + case 'F': scancode = EStdKeyF12; break; + } + keysym->sym = keymap[scancode]; + } + } + + if (scancode >= ENonCharacterKeyBase) { + // Non character keys + keysym->sym = keymap[scancode - + ENonCharacterKeyBase + 0x0081]; // !!hard coded + } else { + keysym->sym = keymap[scancode]; + } + + /* Remap the arrow keys if the device is rotated */ +/* + if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { + switch(keysym->sym) { + case SDLK_UP: keysym->sym = SDLK_LEFT; break; + case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; + case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; + case SDLK_RIGHT:keysym->sym = SDLK_UP; break; + } + } +*/ + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + +#if 0 // !!TODO:unicode + + if ( SDL_TranslateUNICODE ) + { + /* Populate the unicode field with the ASCII value */ + keysym->unicode = scancode; + } +#endif + + //!! + //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", + // keysym->scancode, keysym->sym, keysym->mod); + //SDL_TRACE(debug); //!! + + return(keysym); +} + +} /* extern "C" */ + + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp new file mode 100644 index 0000000..c15506d --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.cpp @@ -0,0 +1,594 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocvideo.cpp + Epoc based SDL video driver implementation + + Markus Mertama +*/ + + + +#include "epoc_sdl.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#include "SDL_error.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#undef NULL +#include "SDL_pixels_c.h" +#include "SDL.h" +#include "SDL_mouse.h" +} + +#include "SDL_epocvideo.h" +#include "SDL_epocevents_c.h" + + + +#include <coedef.h> +#include <flogger.h> + +#include <eikenv.h> +#include <eikappui.h> +#include <eikapp.h> +#include "sdlepocapi.h" + + +//////////////////////////////////////////////////////////////// + + + + +_LIT(KLibName, "SDL"); + +void RDebug_Print_b(char* error_str, void* param) + { + TBuf8<128> error8((TUint8*)error_str); + TBuf<128> error; + error.Copy(error8); + +#ifndef TRACE_TO_FILE + if (param) //!! Do not work if the parameter is really 0!! + RDebug::Print(error, param); + else + RDebug::Print(error); +#else + if (param) //!! Do not work if the parameter is really 0!! + RFileLogger::WriteFormat(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error, param); + else + RFileLogger::Write(KLibName, _L("SDL.txt"), EFileLoggingModeAppend, error); +#endif + + } + +extern "C" void RDebug_Print(char* error_str, void* param) + { + RDebug_Print_b(error_str, param); + } + +/* +int Debug_AvailMem2() + { + //User::CompressAllHeaps(); + TMemoryInfoV1Buf membuf; + User::LeaveIfError(UserHal::MemoryInfo(membuf)); + TMemoryInfoV1 minfo = membuf(); + return(minfo.iFreeRamInBytes); + } + +extern "C" int Debug_AvailMem() + { + return(Debug_AvailMem2()); + } + +*/ + +extern "C" { + +/* Initialization/Query functions */ + +static int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int EPOC_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void EPOC_VideoQuit(_THIS); + +/* Hardware surface functions */ + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_LockHWSurface(_THIS, SDL_Surface *surface); +static int EPOC_FlipHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_FreeHWSurface(_THIS, SDL_Surface *surface); +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +static int EPOC_Available(void); +static SDL_VideoDevice *EPOC_CreateDevice(int devindex); + +void DrawBackground(_THIS); +void DirectDraw(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); +void DirectDrawRotated(_THIS, int numrects, SDL_Rect *rects, TUint16* screenBuffer); + +/* Mouse functions */ + +static WMcursor *EPOC_CreateWMCursor(_THIS, Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +static void EPOC_FreeWMCursor(_THIS, WMcursor *cursor); +static int EPOC_ShowWMCursor(_THIS, WMcursor *cursor); +} + + +extern "C" + { + struct WMcursor + { + }; + } + +/* Epoc video driver bootstrap functions */ + + +static int EPOC_Available(void) + { + return 1; /* Always available */ + } + +static void EPOC_DeleteDevice(SDL_VideoDevice *device) + { + User::Free(device->hidden); + User::Free(device); + } + +static SDL_VideoDevice *EPOC_CreateDevice(int /*devindex*/) + { + SDL_VideoDevice *device; + + SDL_TRACE("SDL:EPOC_CreateDevice"); + + /* Allocate all variables that we free on delete */ + device = static_cast<SDL_VideoDevice*>(User::Alloc(sizeof(SDL_VideoDevice))); + if ( device ) + { + Mem::FillZ(device, (sizeof *device)); + device->hidden = static_cast<struct SDL_PrivateVideoData*> + (User::Alloc((sizeof *device->hidden))); + } + if ( (device == NULL) || (device->hidden == NULL) ) + { + SDL_OutOfMemory(); + if ( device ) { + User::Free(device); + } + return(0); + } + Mem::FillZ(device->hidden, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = EPOC_VideoInit; + device->ListModes = EPOC_ListModes; + device->SetVideoMode = EPOC_SetVideoMode; + device->SetColors = EPOC_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = EPOC_VideoQuit; + device->AllocHWSurface = EPOC_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = EPOC_LockHWSurface; + device->UnlockHWSurface = EPOC_UnlockHWSurface; + device->FlipHWSurface = EPOC_FlipHWSurface; + device->FreeHWSurface = EPOC_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = EPOC_FreeWMCursor; + device->CreateWMCursor = EPOC_CreateWMCursor; + device->ShowWMCursor = EPOC_ShowWMCursor; + device->WarpWMCursor = NULL; + device->InitOSKeymap = EPOC_InitOSKeymap; + device->PumpEvents = EPOC_PumpEvents; + device->free = EPOC_DeleteDevice; + + return device; +} + + +VideoBootStrap EPOC_bootstrap = { + "epoc\0\0\0", "EPOC system", + EPOC_Available, EPOC_CreateDevice +}; + + + +void DisableKeyBlocking(_THIS) + { + EpocSdlEnv::Request(EpocSdlEnv::EDisableKeyBlocking); + } + +void ConstructWindowL(_THIS) + { + SDL_TRACE("SDL:ConstructWindowL"); + DisableKeyBlocking(_this); //disable key blocking + } + + +int EPOC_VideoInit(_THIS, SDL_PixelFormat *vformat) + { + /* Construct Epoc window */ + + ConstructWindowL(_this); + + /* Initialise Epoc frame buffer */ + + + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + + /* The "best" video format should be returned to caller. */ + + vformat->BitsPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode); + vformat->BytesPerPixel = TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) / 8; + + + //?? Private->iWindow->PointerFilter(EPointerFilterDrag, 0); + + Private->iScreenPos = TPoint(0, 0); + + Private->iRect.x = Private->iScreenPos.iX; + Private->iRect.y = Private->iScreenPos.iY; + + const TSize sz = EpocSdlEnv::WindowSize(); + + Private->iRect.w = sz.iWidth; + Private->iRect.h = sz.iHeight; + Private->iRectPtr = &Private->iRect; + + return(0); + } + + +SDL_Rect **EPOC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) + { + if(flags & SDL_HWSURFACE) + { + if(format->BytesPerPixel != 4) //in HW only full color is supported + return NULL; + } + if(flags & SDL_FULLSCREEN) + { + return &Private->iRectPtr; + } + return (SDL_Rect **)(-1); //everythingisok, unless too small shoes + } + + +int EPOC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) + { + if ((firstcolor+ncolors) > 256) + return -1; + TUint32 palette[256]; + const TDisplayMode mode = EpocSdlEnv::DisplayMode(); + if(TDisplayModeUtils::NumDisplayModeColors(mode) == 4096) + { + // Set 12 bit palette + for(int i = firstcolor; i < ncolors; i++) + { + // 4k value: 0000 rrrr gggg bbbb + TUint32 color4K = (colors[i].r & 0x0000f0) << 4; + color4K |= (colors[i].g & 0x0000f0); + color4K |= (colors[i].b & 0x0000f0) >> 4; + palette[i] = color4K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 65536) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 64k-colour displays effectively support RGB values + // with 5 bits allocated to red, 6 to green and 5 to blue + // 64k value: rrrr rggg gggb bbbb + TUint32 color64K = (colors[i].r & 0x0000f8) << 8; + color64K |= (colors[i].g & 0x0000fc) << 3; + color64K |= (colors[i].b & 0x0000f8) >> 3; + palette[i] = color64K; + } + } + else if(TDisplayModeUtils::NumDisplayModeColors(mode) == 16777216) + { + for(int i = firstcolor; i < ncolors; i++) + { + // 16M-colour + //0000 0000 rrrr rrrr gggg gggg bbbb bbbb + TUint32 color16M = colors[i].r << 16; + color16M |= colors[i].g << 8; + color16M |= colors[i].b; + palette[i] = color16M; + } + } + else + { + return -2; + } + if(EpocSdlEnv::SetPalette(firstcolor, ncolors, palette) == KErrNone) + return 0; + return -1; + } + + +/* +void AllocHWSurfaceL(CFbsBitmap*& aBitmap, const TDisplayMode& aMode, const TSize& aSize) + { + aBitmap = new (ELeave) CFbsBitmap(); + if(KErrNone != aBitmap->CreateHardwareBitmap(aSize, aMode, + EpocSdlEnv::EikonEnv().EikAppUi()->Application()->AppDllUid())) + //...if it fails - should we use wsbitmaps??? + {//the good reason to use hw bitmaps is that they wont need lock heap + PANIC_IF_ERROR(aBitmap->Create(aSize, aMode)); + } + } + +int CreateSurfaceL(_THIS, SDL_Surface* surface) + { + __ASSERT_ALWAYS(Private->iFrame == NULL, PANIC(KErrAlreadyExists)); +; + TInt dmode = EColorLast; + + TDisplayMode displayMode; + EpocSdlEnv::GetDiplayMode(displayMode); + + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == surface->format->BitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + surface->format->BitsPerPixel) + --dmode; + } + + __ASSERT_ALWAYS(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)), PANIC(KErrNotSupported)); + TRAPD(err, AllocHWSurfaceL(Private->iFrame, TDisplayMode(dmode), TSize(surface->w, surface->h))); + return err == KErrNone ? 0 : -1; + } +*/ + +TDisplayMode GetDisplayMode(TInt aBitsPerPixel) + { + const TDisplayMode displayMode = EpocSdlEnv::DisplayMode(); + TInt dmode = EColorLast; + if( + TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode) + == aBitsPerPixel) + { + dmode = displayMode; + } + else + { + --dmode; + while(TDisplayModeUtils::IsDisplayModeColor(TDisplayMode(dmode)) && + TDisplayModeUtils::NumDisplayModeBitsPerPixel(TDisplayMode(dmode)) != + aBitsPerPixel) + --dmode; + } + return TDisplayMode(dmode); + } + +SDL_Surface *EPOC_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) + { + const TSize screenSize = EpocSdlEnv::WindowSize(TSize(width, height)); + if(width > screenSize.iWidth || height > screenSize.iHeight) + { + if(flags & SDL_FULLSCREEN) + { + width = screenSize.iWidth; + height = screenSize.iHeight; + } + else + return NULL; + } + + if(current && current->pixels) + { + // free(current->pixels); + current->pixels = NULL; + } + + if(!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0)) + { + return(NULL); + } + + current->flags = 0; + if(width == screenSize.iWidth && height == screenSize.iHeight) + current->flags |= SDL_FULLSCREEN; + + const int numBytesPerPixel = ((bpp-1)>>3) + 1; + current->pitch = numBytesPerPixel * width; // Number of bytes in scanline + + /* Set up the new mode framebuffer */ + current->flags |= SDL_PREALLOC; + + if(bpp <= 8) + current->flags |= SDL_HWPALETTE; + + User::Free(Private->iSwSurface); + current->pixels = NULL; + Private->iSwSurface = NULL; + + if(flags & SDL_HWSURFACE) + { + current->flags |= SDL_HWSURFACE; + // current->pixels = NULL; + // Private->iSwSurface = NULL; + } + else + { + current->flags |= SDL_SWSURFACE; + const TInt surfacesize = width * height * numBytesPerPixel; + Private->iSwSurfaceSize = TSize(width, height); + delete Private->iSwSurface; + Private->iSwSurface = NULL; + current->pixels = (TUint8*) User::AllocL(surfacesize); + Private->iSwSurface = (TUint8*) current->pixels; + const TInt err = EpocSdlEnv::AllocSwSurface + (TSize(width, height), GetDisplayMode(current->format->BitsPerPixel)); + if(err != KErrNone) + return NULL; + } + + current->w = width; + current->h = height; + + + + /* Set the blit function */ + _this->UpdateRects = EPOC_DirectUpdate; + + /* + * Logic for getting suitable screen dimensions, offset, scaling and orientation + */ + + + /* Centralize game window on device screen */ + + + Private->iScreenPos.iX = Max(0, (screenSize.iWidth - width) / 2); + Private->iScreenPos.iY = Max(0, (screenSize.iHeight - height) / 2); + + // delete (Private->iFrame); +// Private->iFrame = NULL; + + // TRAPD(err, CreateSurfaceL(_this, current)); + // PANIC_IF_ERROR(err); + + SDL_TRACE1("View width %d", width); + SDL_TRACE1("View height %d", height); + SDL_TRACE1("View bmode %d", bpp); + SDL_TRACE1("View x %d", Private->iScreenPos.iX); + SDL_TRACE1("View y %d", Private->iScreenPos.iY); + + EpocSdlEnv::LockPalette(EFalse); + /* We're done */ + return(current); +} + + + +static int EPOC_AllocHWSurface(_THIS, SDL_Surface* surface) + { + return KErrNone == EpocSdlEnv::AllocHwSurface(TSize(surface->w, surface->h), GetDisplayMode(surface->format->BitsPerPixel)); + } + +static void EPOC_FreeHWSurface(_THIS, SDL_Surface* /*surface*/) + { + } + +static int EPOC_LockHWSurface(_THIS, SDL_Surface* surface) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + TUint8* address = EpocSdlEnv::LockHwSurface(); + if(address != NULL) + { + surface->pixels = address; + return 1; + } + } + return 0; + } +static void EPOC_UnlockHWSurface(_THIS, SDL_Surface* /*surface*/) + { + EpocSdlEnv::UnlockHwSurface(); + } + +static int EPOC_FlipHWSurface(_THIS, SDL_Surface* /*surface*/) + { + return(0); + } + +static void EPOC_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) + { + if(EpocSdlEnv::IsDsaAvailable()) + { + if(Private->iSwSurface) + { + const TRect target(Private->iScreenPos, Private->iSwSurfaceSize); + for(TInt i = 0; i < numrects ;i++) + { + const TRect rect(TPoint(rects[i].x, rects[i].y), + TSize(rects[i].w, rects[i].h)); + if(!EpocSdlEnv::AddUpdateRect(Private->iSwSurface, rect, target)) + return; //not succesful + } + EpocSdlEnv::UpdateSwSurface(); + } + SDL_PauseAudio(0); + } + else + { + SDL_PauseAudio(1); + EpocSdlEnv::WaitDsaAvailable(); + } + } + + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void EPOC_VideoQuit(_THIS) + { +// delete Private->iFrame; +// Private->iFrame = NULL; + User::Free(Private->iSwSurface); + Private->iSwSurface = NULL; + EpocSdlEnv::FreeSurface(); + } + + + + +WMcursor *EPOC_CreateWMCursor(_THIS, Uint8* /*data*/, Uint8* /*mask*/, int /*w*/, int /*h*/, int /*hot_x*/, int /*hot_y*/) + { + return (WMcursor*) 1; //hii! prevents SDL to view a std cursor + } + +void EPOC_FreeWMCursor(_THIS, WMcursor* /*cursor*/) + { + } + +int EPOC_ShowWMCursor(_THIS, WMcursor *cursor) + { + return true; + } + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h new file mode 100644 index 0000000..5aa3a20 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/SDL_epocvideo.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifndef EPOCVIDEO_H +#define EPOCVIDEO_H + +#include<w32std.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +class CFbsBitmap; + +struct SDL_VideoDevice; +void DisableKeyBlocking(SDL_VideoDevice*); + +struct SDL_PrivateVideoData + { + TPoint iScreenPos; + TBool iIsWindowFocused; + TSize iSwSurfaceSize; + TUint8* iSwSurface; + SDL_Rect iRect; //same info in SDL format + SDL_Rect* iRectPtr; + }; + +#endif + + + + diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp new file mode 100644 index 0000000..07b1ab4 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa.cpp @@ -0,0 +1,1505 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + + + +template<class T> +NONSHARABLE_CLASS(CBitmapSurface) : public T + { +public: + CBitmapSurface(RWsSession& aSession); +private: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + ~CBitmapSurface(); + TUint8* LockSurface(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + TInt ExternalUpdate(); +private: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +template<class T> +void CBitmapSurface<T>::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + delete iCopyBmp; + iCopyBmp = NULL; + iCopyBmp = new (ELeave) CFbsBitmap(); + T::ConstructL(aWindow, aDevice); + } + +template<class T> +CBitmapSurface<T>::CBitmapSurface(RWsSession& aSession) : T(aSession) + { + } + +template<class T> +void CBitmapSurface<T>::Free() + { + delete iBmp; + iBmp = NULL; + T::Free(); + } + +template<class T> +CBitmapSurface<T>::~CBitmapSurface() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +template<class T> +TUint8* CBitmapSurface<T>::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + + +template<class T> +void CBitmapSurface<T>::UnlockHwSurface() + { + iBmp->UnlockHeap(); + T::SetUpdating(EFalse); + Update(*iBmp); + } + + +template<class T> +void CBitmapSurface<T>::Update(CFbsBitmap& aBmp) + { + if(!T::Blitter(aBmp)) + { + if(T::SwSize() == T::HwRect().Size()) + T::Gc().BitBlt(T::HwRect().iTl, &aBmp); + else + T::Gc().DrawBitmap(T::HwRect(), &aBmp); + } + T::DrawOverlays(); + T::CompleteUpdate(); + } + +template<class T> +void CBitmapSurface<T>::CreateSurfaceL() + { + Free(); + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(T::SwSize(), T::DisplayMode())); + T::CreateSurfaceL(*iBmp); + } + +template<class T> +void CBitmapSurface<T>::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +template<class T> +TInt CBitmapSurface<T>::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + + +////////////////////////////////////////////////////////////////////// + + + +NONSHARABLE_CLASS(CDsaBitgdi) : public CDsa + { +public: + CDsaBitgdi(RWsSession& aSession); +protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CBitmapContext& Gc(); + void CompleteUpdate(); + ~CDsaBitgdi(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); +private: + void Resume(); + + CFbsBitGc* iGc; + CFbsDevice* iDevice; + CFbsBitmap* iBitGdiBmp; + CWindowGc* iWinGc; + RWindow* iWindow; + TInt iHandle; + }; + + +CDsaBitgdi::CDsaBitgdi(RWsSession& aSession) : CDsa(aSession) + { + } + +CDsaBitgdi::~CDsaBitgdi() + { + delete iWinGc; + delete iBitGdiBmp; + } + +void CDsaBitgdi::CompleteUpdate() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + + +void CDsaBitgdi::UnlockHWSurfaceRequestComplete() + { + if(iHandle == 0) + return; + + if(iBitGdiBmp == NULL) + { + iBitGdiBmp = new CFbsBitmap(); + if(iBitGdiBmp == NULL) + return; + iBitGdiBmp->Duplicate(iHandle); + } + + iWindow->Invalidate(); + + iWindow->BeginRedraw(); + iWinGc->Activate(*iWindow); + iWinGc->BitBlt(TPoint(0, 0), iBitGdiBmp); + iWinGc->Deactivate(); + iWindow->EndRedraw(); + } + +void CDsaBitgdi::Resume() + { + Start(); + } + +CBitmapContext& CDsaBitgdi::Gc() + { + return *iGc; + } + + void CDsaBitgdi::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + + delete iBitGdiBmp; + iBitGdiBmp = NULL; + delete iWinGc; + iWinGc = NULL; + iHandle = 0; + + iWindow = &aWindow; + User::LeaveIfError(aDevice.CreateContext(iWinGc)); + CDsa::ConstructL(aWindow, aDevice); + Start(); + } + +void CDsaBitgdi::CreateSurfaceL(CFbsBitmap& aBmp) + { + iDevice = CFbsBitmapDevice::NewL(&aBmp); + User::LeaveIfError(iDevice->CreateContext(iGc)); + iHandle = aBmp.Handle(); + } + +void CDsaBitgdi::Free() + { + delete iGc; + iGc = NULL; + delete iDevice; + iDevice = NULL; + } + +//////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaBase) : public CDsa, public MDirectScreenAccess + { +protected: + inline CDirectScreenAccess& Dsa() const; + CDsaBase(RWsSession& aSession); + ~CDsaBase(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Stop(); + void Resume(); + CBitmapContext& Gc(); +protected: + CDirectScreenAccess* iDsa; +private: + void AbortNow(RDirectScreenAccess::TTerminationReasons aReason); + void Restart(RDirectScreenAccess::TTerminationReasons aReason); +private: + void RestartL(); + }; + + +inline CDirectScreenAccess& CDsaBase::Dsa() const + { + return *iDsa; + } + + +CDsaBase::CDsaBase(RWsSession& aSession) : CDsa(aSession) + { + } + +CBitmapContext& CDsaBase::Gc() + { + return *Dsa().Gc(); + } + +void CDsaBase::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsa::ConstructL(aWindow, aDevice); + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + Session(), + aDevice, + aWindow, + *this); + RestartL(); + } + +void CDsaBase::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +CDsaBase::~CDsaBase() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + } + + +void CDsaBase::RestartL() + { + + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != ScreenRect()) + { + return ; + } + + + SetTargetRect(); + RecreateL(); + + Start(); + + + } + +void CDsaBase::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { + Stop(); + } + +void CDsaBase::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + + +void CDsaBase::Stop() + { + CDsa::Stop(); + iDsa->Cancel(); + } + + + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template<class T, class S> +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast<const S*>(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast<T*>(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsaBase + { + public: + CDsaA(RWsSession& aSession); + protected: + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void CompleteUpdate(); + void CreateSurfaceL(CFbsBitmap& aBmp); + void Free(); + void UnlockHWSurfaceRequestComplete(); + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsaBase(aSession) + { + } + + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + CDsaBase::ConstructL(aWindow, aDevice); + } + +void CDsaA::CompleteUpdate() + { + iDsa->ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL(CFbsBitmap& /*aBmp*/) + { + } + +void CDsaA::Free() + { + + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsaBase, + public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsaBase(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsaBase::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrementalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else if(EpocSdlEnv::Flags(CSDL::EDrawModeGdi)) + { + return new (ELeave) CBitmapSurface<CDsaBitgdi>(aSession); + } + else + { + return new (ELeave) CBitmapSurface<CDsaA>(aSession); + } + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + + +void CDsa::SetUpdating(TBool aUpdate) + { + if(aUpdate) + iStateFlags |= EUpdating; + else + iStateFlags &= ~EUpdating; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + iOverlays.Close(); + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& /*aDevice*/) + { + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + + +CDsa::CDsa(RWsSession& aSession) : + iStateFlags(0), + iSession(aSession) + + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +*/ + + +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy<TUint32, TUint8>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy<TUint32, TUint16>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy<TUint32, TUint32>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + + + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; + } + +void CDsa::Start() + { + iStateFlags |= ERunning; + + iStateFlags &= ~ESdlThreadExplicitStop; + + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + + +TBool CDsa::Blitter(CFbsBitmap& aBmp) + { + return iBlitter && iBlitter->BitBlt(Gc(), aBmp, HwRect(), SwSize()); + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); + + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast<const TUint32*>(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template <class T> TUint32 TRgbCopy<T>::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template <class T> TUint32 TRgbCopy<T>::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp new file mode 100644 index 0000000..638fbe8 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa_new.cpp @@ -0,0 +1,1443 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +NONSHARABLE_CLASS(TDsa) + { + public: + inline TDsa(const CDsa& aDsa); + inline TBool IsFlip() const; + inline TBool IsTurn() const; + inline const TSize& SwSize() const; + inline void Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const; + private: + const CDsa& iDsa; + }; + + +inline TDsa::TDsa(const CDsa& aDsa) : iDsa(aDsa) + { + } + +inline TBool TDsa::IsTurn() const + { + return iDsa.iStateFlags & CDsa::EOrientation90; + } + +inline TBool TDsa::IsFlip() const + { + return iDsa.iStateFlags & CDsa::EOrientation180; + } + +inline const TSize& TDsa::SwSize() const + { + return iDsa.SwSize(); + } + +inline void TDsa::Copy(TUint32* aTarget, const TUint8* aSrc, TInt aBytes, TInt aHeight) const + { + iDsa.iCopyFunction(iDsa, aTarget, aSrc, aBytes, aHeight); + } + +template<class T, class S> +void ClipCopy(const TDsa& iDsa, TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) + { + const S* source = reinterpret_cast<const S*>(aSource); + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + T* targetPtr = reinterpret_cast<T*>(aTarget); + + const TInt scanLineWidth = iDsa.SwSize().iWidth; + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * scanLineWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iDsa.IsTurn() ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iDsa.IsFlip()) + { + + targetPtr += scanLineWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr -= scanLineWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iDsa.Copy(reinterpret_cast<TUint32*>(targetPtr), reinterpret_cast<const TUint8*>(source), copyLen, height); + source += lineMove; + targetPtr += scanLineWidth; // >> 2; + } + } + + } + + + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void Free(); + void Update(CFbsBitmap& aBmp); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + TInt ExternalUpdate(); + // void ExternalUpdate(); + protected: + CFbsBitmap* iBmp; + CFbsBitmap* iCopyBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + delete iCopyBmp; + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Update(*iBmp); + } + +void CDsaA::Update(CFbsBitmap& aBmp) + { + if(!Blitter(aBmp)) + { + if(SwSize() == HwRect().Size()) + Dsa().Gc()->BitBlt(HwRect().iTl, &aBmp); + else + Dsa().Gc()->DrawBitmap(HwRect(), &aBmp); + } + DrawOverlays(); + Dsa().ScreenDevice()->Update(); + } +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(SwSize(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + + + +TInt CDsaA::ExternalUpdate() + { + if(iCopyBmp->Handle() == 0) + { + const TInt err = iCopyBmp->Duplicate(iBmp->Handle()); + if(err != KErrNone) + return err; + } + Update(*iCopyBmp); + return KErrNone; + } + +void CDsaA::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + iCopyBmp = new (ELeave) CFbsBitmap(); + CDsa::ConstructL(aWindow, aDevice); + } + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession, TInt aFlags); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate(); + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + TInt iType; + }; + +CDsaB::CDsaB(RWsSession& aSession, TInt aFlags) : CDsa(aSession), iType(aFlags) + { + } + + + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + if(iSurface2 != NULL) + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + __ASSERT_ALWAYS(SwSize() == HwRect().Size(), PANIC(KErrNotSupported)); + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL && iSurface2 != NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + if(iSurface1 == NULL) + iSurface1 = new (ELeave) CDsbSurface(*this); + if(iSurface2 == NULL && iType & CDirectScreenBitmap::EDoubleBuffer) + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::TSettingsFlags(iType)); + } + +TInt CDsaB::ExternalUpdate() + { + if(LockSurface()) + { + UnlockHWSurfaceRequestComplete(); + return KErrNone; + } + return KErrNotReady; + } + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession, flags); + } + else + return new (ELeave) CDsaA(aSession); + } + + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +TSize CDsa::WindowSize() const + { + TSize size = iSwSize; + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + iOverlays.Close(); + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iScreenRect = TRect(aWindow.Position(), aWindow.Size()); + SetTargetRect(); + RestartL(); + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + + iDsa->StartL(); + + const RRegion* r = iDsa->DrawingRegion(); + const TRect rect = r->BoundingRect(); + iDsa->Gc()->SetClippingRegion(r); + + if(rect != iScreenRect) + { + // iDsa->Cancel(); + return ; + } + + + + //iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + //targetrect shall no change + SetTargetRect(); + RecreateL(); + + iStateFlags |= ERunning; + + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + SetCopyFunction(); + + return KErrNone; + } + + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } + +void ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) + { + const TInt iSourceBpp = 1; + const TInt iTargetBpp = 4; + const TInt iScanLineWidth = 800; + + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + const TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + } +*/ +/* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + //TUint8* target = aTarget; + const TUint32* source = (const TUint32*) aSource; + const TInt lineWidth = aSourceRect.Width(); + + source += (aUpdateRect.iTl.iY * lineWidth); + const TInt sourceStartOffset = aUpdateRect.iTl.iX; + source += sourceStartOffset; + + TUint32* targetPtr = reinterpret_cast<TUint32*>(aTarget); + + targetPtr += (aSourceRect.iTl.iY + aUpdateRect.iTl.iY ) * SwSize().iWidth; + const TInt targetStartOffset = (aUpdateRect.iTl.iX + aSourceRect.iTl.iX); + + targetPtr += targetStartOffset; + +// TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + + const TInt targetWidth32 = SwSize().iWidth; + + const TInt height = aUpdateRect.Height(); + + const TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + const TInt copyLen = aUpdateRect.Width(); + + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth32 * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr -= targetWidth32; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, (TUint8*)source, copyLen, height); + source += lineMove; + targetPtr += targetWidth32; // >> 2; + } + } + + } + +*/ + +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TPoint& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = iScanLineWidth >> 2; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + /* +void CDsa::ClipCopy(TUint8* aTarget, + const TUint8* aSource, + const TRect& aUpdateRect, + const TRect& aSourceRect) const + { + const TDsa dsa(*this); + switch(iSourceBpp) + { + case 1: + ::ClipCopy<TUint32, TUint8>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 2: + ::ClipCopy<TUint32, TUint16>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + case 4: + ::ClipCopy<TUint32, TUint32>(dsa, aTarget, aSource, aUpdateRect, aSourceRect); + break; + } + } + + +*/ + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * SwSize().iWidth * SwSize().iHeight); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +/* +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = TRect(TPoint(0, 0), SwSize()); + + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + +// TPoint move(0, 0); + + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + //updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + */ + +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = Rect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect.iTl); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* src = reinterpret_cast<const TUint32*>(aSource); + Mem::Copy(aTarget, src, aBytes << 2); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + +/* + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } +*/ +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; + +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + static TUint32 Gray256(const TUint8& aPixel); + static TUint32 Color256(const TUint8& aPixel); + static TUint32 Color4K(const TUint16& aPixel); + static TUint32 Color64K(const TUint16& aPixel); + static TUint32 Color16M(const TUint32& aPixel); + static TUint32 Color16MU(const TUint32& aPixel); + static TUint32 Color16MA(const TUint32& aPixel); + private: + typedef TUint32 (*TRgbFunc) (const T& aValue); + TRgbFunc iFunc; + }; + + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = (TRgbFunc) Gray256; break; + case EColor256 : iFunc = (TRgbFunc) Color256; break; + case EColor4K : iFunc = (TRgbFunc) Color4K; break; + case EColor64K : iFunc = (TRgbFunc) Color64K; break; + case EColor16M : iFunc = (TRgbFunc) Color16M; break; + case EColor16MU : iFunc = (TRgbFunc) Color16MU; break; + case EColor16MA : iFunc = (TRgbFunc) Color16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + const T value = *source++; + *(--endt) = iFunc(value);//iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + const T value = *source++; + *target++ = iFunc(value);//iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column); + column += aLineLen; + } + } + } + +template <class T> TUint32 TRgbCopy<T>::Gray256(const TUint8& aPixel) + { + const TUint32 px = aPixel << 16 | aPixel << 8 | aPixel; + return px; + } + +template <class T> TUint32 TRgbCopy<T>::Color256(const TUint8& aPixel) + { + return TRgb::Color256(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color4K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF00) << 12; + col |= (aPixel & 0xF00) << 8; + + col |= (aPixel & 0x0F0) << 8; + col |= (aPixel & 0x0F0); + + col |= (aPixel & 0x00F) << 4; + col |= (aPixel & 0x00F); + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color64K(const TUint16& aPixel) + { + TUint32 col = (aPixel & 0xF800)<< 8; + col |= (aPixel & 0xE000) << 3; + + col |= (aPixel & 0x07E0) << 5; + col |= (aPixel & 0xC0) >> 1; + + col |= (aPixel & 0x07E0) << 3; + col |= (aPixel & 0x1C) >> 2; + + return col; + } + +template <class T> TUint32 TRgbCopy<T>::Color16M(const TUint32& aPixel) + { + return TRgb::Color16M(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MU(const TUint32& aPixel) + { + return TRgb::Color16MU(aPixel).Value(); + } + +template <class T> TUint32 TRgbCopy<T>::Color16MA(const TUint32& aPixel) + { + return TRgb::Color16MA(aPixel).Value(); + } + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////7 diff --git a/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp b/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp new file mode 100644 index 0000000..7e32de2 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/EKA2/dsa_old.cpp @@ -0,0 +1,1075 @@ +#include "dsa.h" +#include "sdlepocapi.h" +#include <cdsb.h> + +LOCAL_C TInt BytesPerPixel(TDisplayMode aMode) + { + return ((TDisplayModeUtils::NumDisplayModeBitsPerPixel(aMode) - 1) >> 3) + 1; + } + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(CDsaA) : public CDsa + { + public: + CDsaA(RWsSession& aSession); + private: + ~CDsaA(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void Free(); + TInt ExternalUpdate() {return 0;} + private: + CFbsBitmap* iBmp; + }; + + +CDsaA::CDsaA(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaA::Free() + { + delete iBmp; + iBmp = NULL; + } + +CDsaA::~CDsaA() + { + __ASSERT_DEBUG(iBmp == NULL, PANIC(KErrNotReady)); + } + +TUint8* CDsaA::LockSurface() + { + iBmp->LockHeap(); + return reinterpret_cast<TUint8*>(iBmp->DataAddress()); + } + +void CDsaA::UnlockHWSurfaceRequestComplete() + { + PANIC(KErrNotSupported); + } + +void CDsaA::UnlockHwSurface() + { + iBmp->UnlockHeap(); + SetUpdating(EFalse); + Dsa().Gc()->BitBlt(HwRect().iTl, iBmp); + Dsa().ScreenDevice()->Update(); + } + +void CDsaA::CreateSurfaceL() + { + delete iBmp; + iBmp = NULL; + iBmp = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iBmp->Create(HwRect().Size(), DisplayMode())); + } + +void CDsaA::Wipe(TInt aLength) //dont call in drawing + { + iBmp->LockHeap(); + Mem::FillZ(iBmp->DataAddress(), aLength); + iBmp->UnlockHeap(); + } + +void CDsaA::RecreateL() + { + } + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +NONSHARABLE_CLASS(MDsbObs) + { + public: + virtual void SurfaceReady() = 0; + virtual CDirectScreenBitmap& Dsb() = 0; + }; + +NONSHARABLE_CLASS(CDsbSurface) : public CActive + { + public: + CDsbSurface(MDsbObs& aDsb); + TUint8* Address(); + void Complete(); + ~CDsbSurface(); + private: + void RunL(); + void DoCancel(); + private: + MDsbObs& iDsb; + TUint8* iAddress; + }; + +CDsbSurface::CDsbSurface(MDsbObs& aDsb) : CActive(CActive::EPriorityHigh) , iDsb(aDsb) + { + CActiveScheduler::Add(this); + } + +CDsbSurface::~CDsbSurface() + { + Cancel(); + } + +void CDsbSurface::Complete() + { + if(iAddress != NULL && !IsActive()) + { + iAddress = NULL; + SetActive(); + iDsb.Dsb().EndUpdate(iStatus); + } + } + +TUint8* CDsbSurface::Address() + { + if(iAddress == NULL && !IsActive()) + { + TAcceleratedBitmapInfo info; + if(KErrNone == iDsb.Dsb().BeginUpdate(info)) + iAddress = info.iAddress; + } + return iAddress; + } + +void CDsbSurface::RunL() + { + iDsb.SurfaceReady(); + } + +void CDsbSurface::DoCancel() + { + //empty + } + +NONSHARABLE_CLASS(CDsaB) : public CDsa, public MDsbObs + { + public: + CDsaB(RWsSession& aSession); + private: + ~CDsaB(); + TUint8* LockSurface(); + void UnlockHWSurfaceRequestComplete(); + void UnlockHwSurface(); + void CreateSurfaceL(); + void Wipe(TInt aLength); + void RecreateL(); + void ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice); + void Free(); + CDirectScreenBitmap& Dsb(); + void SurfaceReady(); + TInt ExternalUpdate() {return 0;} + private: + CDsbSurface* iSurface1; + CDsbSurface* iSurface2; + CDirectScreenBitmap* iDsb; + }; + +CDsaB::CDsaB(RWsSession& aSession) : CDsa(aSession) + { + } + +void CDsaB::Free() + { + } + +void CDsaB::UnlockHWSurfaceRequestComplete() + { + iSurface1->Complete(); + iSurface2->Complete(); + } + +void CDsaB::CreateSurfaceL() + { + } + +void CDsaB::Wipe(TInt aLength) //dont call in drawing + { + TUint8* addr = LockSurface(); + if(addr != NULL) + { + Mem::FillZ(addr, aLength); + UnlockHwSurface(); + } + } + +void CDsaB::UnlockHwSurface() + { + EpocSdlEnv::Request(CDsa::ERequestUpdate); + } + +TUint8* CDsaB::LockSurface() + { + TUint8* addr = iSurface1->Address(); + if(addr == NULL) + addr = iSurface2->Address(); + SetUpdating(addr == NULL); + return addr; + } + +void CDsaB::SurfaceReady() + { + SetUpdating(EFalse); + } + +CDirectScreenBitmap& CDsaB::Dsb() + { + return *iDsb; + } + +void CDsaB::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsb == NULL) + iDsb = CDirectScreenBitmap::NewL(); + CDsa::ConstructL(aWindow, aDevice); + iSurface1 = new (ELeave) CDsbSurface(*this); + iSurface2 = new (ELeave) CDsbSurface(*this); + } + +CDsaB::~CDsaB() + { + delete iSurface1; + delete iSurface2; + delete iDsb; + } + +void CDsaB::RecreateL() + { + iDsb->Close(); + iDsb->Create(HwRect(), CDirectScreenBitmap::EDoubleBuffer); + } + +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +TSize CDsa::WindowSize() const + { + TSize size = HwRect().Size(); + if(iStateFlags & EOrientation90) + { + const TInt tmp = size.iWidth; + size.iWidth = size.iHeight; + size.iHeight = tmp; + } + return size; + } + +void CDsa::SetSuspend() + { + iStateFlags |= ESdlThreadSuspend; + } + +void CDsa::ReleaseStop() + { + iStateFlags &= ~ESdlThreadExplicitStop; + } + + +TBool CDsa::Stopped() const + { + return (iStateFlags & ESdlThreadExplicitStop); + } + +void CDsa::SetOrientation(CSDL::TOrientationMode aOrientation) + { + TInt flags = 0; + switch(aOrientation) + { + case CSDL::EOrientation90: + flags = EOrientation90; + break; + case CSDL::EOrientation180: + flags = EOrientation180; + break; + case CSDL::EOrientation270: + flags = EOrientation90 | EOrientation180; + break; + case CSDL::EOrientation0: + flags = 0; + break; + } + if(flags != (iStateFlags & EOrientationFlags)) + { + iStateFlags |= EOrientationChanged; + iNewFlags = flags; //cannot be set during drawing... + } + } + +CDsa::~CDsa() + { + if(iDsa != NULL) + { + iDsa->Cancel(); + } + delete iDsa; + User::Free(iLut256); + } + +void CDsa::ConstructL(RWindow& aWindow, CWsScreenDevice& aDevice) + { + if(iDsa != NULL) + { + iDsa->Cancel(); + delete iDsa; + iDsa = NULL; + } + + + iDsa = CDirectScreenAccess::NewL( + iSession, + aDevice, + aWindow, + *this); + + if(iLut256 == NULL) + iLut256 = (TUint32*) User::AllocL(256 * sizeof(TUint32)); + iTargetMode = aWindow.DisplayMode(); + iTargetBpp = BytesPerPixel(DisplayMode()); + iTargetRect = TRect(aWindow.Position(), aWindow.Size()); + RestartL(); + } + +void CDsa::LockPalette(TBool aLock) + { + if(aLock) + iStateFlags |= EPaletteLocked; + else + iStateFlags &= ~EPaletteLocked; + } +TInt CDsa::SetPalette(TInt aFirst, TInt aCount, TUint32* aPalette) + { + if(iLut256 == NULL) + return KErrNotFound; + const TInt count = aCount - aFirst; + if(count > 256) + return KErrArgument; + if(iStateFlags & EPaletteLocked) + return KErrNone; + for(TInt i = aFirst; i < count; i++) //not so busy here:-) + { + iLut256[i] = aPalette[i]; + } + return KErrNone; + } + + + + +void CDsa::RestartL() + { + //const TBool active = iDsa->IsActive(); + + //if(!active) + iDsa->StartL(); + + RRegion* r = iDsa->DrawingRegion(); + iDsa->Gc()->SetClippingRegion(r); + TRect rect = r->BoundingRect(); + + if(rect.IsEmpty()) + { + return; + } + + iScreenRect = rect; //to ensure properly set, albeit may not(?) match to value SDL has - therefore may has to clip + + RecreateL(); + + iStateFlags |= ERunning; +// iScanLineWidth = iTargetBpp * HwRect().Width(); + ReleaseStop(); + if(iStateFlags & ESdlThreadSuspend) + { + EpocSdlEnv::Resume(); + iStateFlags &= ~ ESdlThreadSuspend; + } + } + +CDsa::CDsa(RWsSession& aSession) : + iSession(aSession), + iStateFlags(0) + { +// CActiveScheduler::Add(this); + iCFTable[0] = CopyMem; + iCFTable[1] = CopyMemFlipReversed; + iCFTable[2] = CopyMemReversed; + iCFTable[3] = CopyMemFlip; + + iCFTable[4] = Copy256; + iCFTable[5] = Copy256FlipReversed; + iCFTable[6] = Copy256Reversed; + iCFTable[7] = Copy256Flip; + + + iCFTable[8] = CopySlow; + iCFTable[9] = CopySlowFlipReversed; + iCFTable[10] = CopySlowReversed; + iCFTable[11] = CopySlowFlip; + } + +RWsSession& CDsa::Session() + { + return iSession; + } + + + +TUint8* CDsa::LockHwSurface() + { + if((iStateFlags & EUpdating) == 0) //else frame is skipped + { + return LockSurface(); + } + return NULL; + } + +/* +void CDsa::RunL() + { + iStateFlags &= ~EUpdating; + } + + +void CDsa::DoCancel() + { + iStateFlags &= ~EUpdating; + //nothing can do, just wait? + } +*/ + +TInt CDsa::AllocSurface(TBool aHwSurface, const TSize& aSize, TDisplayMode aMode) + { + if(aHwSurface && aMode != DisplayMode()) + return KErrArgument; + + iSourceMode = aMode; + + iSourceBpp = BytesPerPixel(aMode); + + const TSize size = WindowSize(); + if(aSize.iWidth > size.iWidth) + return KErrTooBig; + if(aSize.iHeight > size.iHeight) + return KErrTooBig; + + TRAPD(err, CreateSurfaceL()); + if(err != KErrNone) + return err; + + + SetCopyFunction(); + + EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowReserved); + + return KErrNone; + } + + +/* +void SaveBmp(const TDesC& aName, const TAny* aData, TInt aLength, const TSize& aSz, TDisplayMode aMode) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, aMode); + s->LockHeap(); + TUint32* addr = s->DataAddress(); + Mem::Copy(addr, aData, aLength); + s->UnlockHeap(); + s->Save(aName); + s->Reset(); + delete s; + } + +void SaveBmp(const TDesC& aName, const TUint32* aData, const TSize& aSz) + { + CFbsBitmap* s = new CFbsBitmap(); + s->Create(aSz, EColor64K); + TBitmapUtil bmp(s); + bmp.Begin(TPoint(0, 0)); + for(TInt j = 0; j < aSz.iHeight; j++) + { + bmp.SetPos(TPoint(0, j)); + for(TInt i = 0; i < aSz.iWidth; i++) + { + bmp.SetPixel(*aData); + aData++; + bmp.IncXPos(); + } + } + bmp.End(); + s->Save(aName); + s->Reset(); + delete s; + } + +TBuf<16> FooName(TInt aFoo) + { + TBuf<16> b; + b.Format(_L("C:\\pic%d.mbm"), aFoo); + return b; + } +*/ +void CDsa::ClipCopy(TUint8* aTarget, const TUint8* aSource, const TRect& aRect, const TRect& aTargetPos) const + { + TUint8* target = aTarget; + const TUint8* source = aSource; + const TInt lineWidth = aRect.Width(); + source += iSourceBpp * (aRect.iTl.iY * lineWidth); + TInt sourceStartOffset = iSourceBpp * aRect.iTl.iX; + source += sourceStartOffset; + target += iTargetBpp * ((aTargetPos.iTl.iY + aRect.iTl.iY ) * lineWidth); + TInt targetStartOffset = iTargetBpp * (aRect.iTl.iX + aTargetPos.iTl.iX); + target += targetStartOffset; + TUint32* targetPtr = reinterpret_cast<TUint32*>(target); + const TInt targetWidth = HwRect().Size().iWidth; + const TInt height = aRect.Height(); + + TInt lineMove = iStateFlags & EOrientation90 ? 1 : lineWidth; + + if(iStateFlags & EOrientation180) + { + + targetPtr += targetWidth * (height - 1); + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr -= targetWidth; + } + } + else + { + + + for(TInt i = 0; i < height; i++) //source is always smaller + { + iCopyFunction(*this, targetPtr, source, lineWidth, height); + source += lineMove; + targetPtr += targetWidth; + } + } + + } + + + + +void CDsa::Wipe() //dont call in drawing + { + if(IsDsaAvailable()) + Wipe(iTargetBpp * iScreenRect.Width() * iScreenRect.Height()); + } + +void CDsa::SetCopyFunction() + { + //calculate offset to correct function in iCFTable according to given parameters + TInt function = 0; + const TInt KCopyFunctions = 4; + const TInt KOffsetToNative = 0; + const TInt KOffsetTo256 = KOffsetToNative + KCopyFunctions; + const TInt KOffsetToOtherModes = KOffsetTo256 + KCopyFunctions; + const TInt KOffsetTo90Functions = 1; + const TInt KOffsetTo180Functions = 2; + + if(iSourceMode == DisplayMode()) + function = KOffsetToNative; //0 + else if(iSourceMode == EColor256) + function = KOffsetTo256; //4 + else + function = KOffsetToOtherModes; //8 + + if(iStateFlags & EOrientation90) + function += KOffsetTo90Functions; // + 1 + if(iStateFlags & EOrientation180) + function += KOffsetTo180Functions; //+ 2 + + iCopyFunction = iCFTable[function]; + + Wipe(); + } + +inline void Rotate(TRect& aRect) + { + const TInt dx = aRect.iBr.iX - aRect.iTl.iX; + const TInt dy = aRect.iBr.iY - aRect.iTl.iY; + + aRect.iBr.iX = aRect.iTl.iX + dy; + aRect.iBr.iY = aRect.iTl.iY + dx; + + const TInt tmp = aRect.iTl.iX; + aRect.iTl.iX = aRect.iTl.iY; + aRect.iTl.iY = tmp; + } + +/* +int bar = 0; +*/ +TBool CDsa::AddUpdateRect(const TUint8* aBits, const TRect& aUpdateRect, const TRect& aRect) + { + + if(iStateFlags & EOrientationChanged) + { + iStateFlags &= ~EOrientationFlags; + iStateFlags |= iNewFlags; + SetCopyFunction(); + iStateFlags &= ~EOrientationChanged; + EpocSdlEnv::WaitDeviceChange(); + return EFalse; //skip this frame as data is may be changed + } + + if(iTargetAddr == NULL) + { + iTargetAddr = LockHwSurface(); + } + TUint8* target = iTargetAddr; + if(target == NULL) + return EFalse; + + + TRect targetRect = HwRect(); + TRect sourceRect = aRect; + TRect updateRect = aUpdateRect; + + if(iStateFlags & EOrientation90) + { + Rotate(sourceRect); + Rotate(updateRect); + } + + if(iSourceMode != DisplayMode() || targetRect != sourceRect || targetRect != updateRect || ((iStateFlags & EOrientationFlags) != 0)) + { + sourceRect.Intersection(targetRect); //so source always smaller or equal than target + updateRect.Intersection(targetRect); + ClipCopy(target, aBits, updateRect, sourceRect); + } + else + { + const TInt byteCount = aRect.Width() * aRect.Height() * iSourceBpp; //this could be stored + Mem::Copy(target, aBits, byteCount); + } + + return ETrue; + } + +CDsa* CDsa::CreateL(RWsSession& aSession) + { + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)) + { + TInt flags = CDirectScreenBitmap::ENone; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBDoubleBuffer)) + flags |= CDirectScreenBitmap::EDoubleBuffer; + if(EpocSdlEnv::Flags(CSDL::EDrawModeDSBIncrentalUpdate)) + flags |= CDirectScreenBitmap::EIncrementalUpdate; + return new (ELeave) CDsaB(aSession); + } + else + return new (ELeave) CDsaA(aSession); + } + +void CDsa::CreateZoomerL(const TSize& aSize) + { + iSwSize = aSize; + iStateFlags |= EResizeRequest; + CreateSurfaceL(); + SetTargetRect(); + } + +TPoint CDsa::WindowCoordinates(const TPoint& aPoint) const + { + TPoint pos = aPoint - iScreenRect.iTl; + const TSize asz = iScreenRect.Size(); + if(iStateFlags & EOrientation180) + { + pos.iX = asz.iWidth - pos.iX; + pos.iY = asz.iHeight - pos.iY; + } + if(iStateFlags & EOrientation90) + { + pos.iX = aPoint.iY; + pos.iY = aPoint.iX; + } + pos.iX <<= 16; + pos.iY <<= 16; + pos.iX /= asz.iWidth; + pos.iY /= asz.iHeight; + pos.iX *= iSwSize.iWidth; + pos.iY *= iSwSize.iHeight; + pos.iX >>= 16; + pos.iY >>= 16; + return pos; + } + +void CDsa::SetTargetRect() + { + iTargetRect = iScreenRect; + if(iStateFlags & EResizeRequest && EpocSdlEnv::Flags(CSDL::EAllowImageResizeKeepRatio)) + { + const TSize asz = iScreenRect.Size(); + const TSize sz = iSwSize; + + TRect rect; + + const TInt dh = (sz.iHeight << 16) / sz.iWidth; + + if((asz.iWidth * dh ) >> 16 <= asz.iHeight) + { + rect.SetRect(TPoint(0, 0), TSize(asz.iWidth, (asz.iWidth * dh) >> 16)); + } + else + { + const TInt dw = (sz.iWidth << 16) / sz.iHeight; + rect.SetRect(TPoint(0, 0), TSize((asz.iHeight * dw) >> 16, asz.iHeight)); + } + rect.Move((asz.iWidth - rect.Size().iWidth) >> 1, (asz.iHeight - rect.Size().iHeight) >> 1); + + iTargetRect = rect; + iTargetRect.Move(iScreenRect.iTl); + + } + if(!(iStateFlags & EResizeRequest)) + iSwSize = iScreenRect.Size(); +// iScanLineWidth = /*iTargetBpp **/ SwSize().iWidth; + } + +void CDsa::RecreateL() + { + } + +void CDsa::Free() + { + } + +void CDsa::UpdateSwSurface() + { + iTargetAddr = NULL; + UnlockHwSurface(); //could be faster if does not use AO, but only check status before redraw, then no context switch needed + } + +void CDsa::SetBlitter(MBlitter* aBlitter) + { + iBlitter = aBlitter; + } + +void CDsa::DrawOverlays() + { + const TInt last = iOverlays.Count() - 1; + for(TInt i = last; i >= 0 ; i--) + iOverlays[i].iOverlay->Draw(*iDsa->Gc(), HwRect(), SwSize()); + } + +TInt CDsa::AppendOverlay(MOverlay& aOverlay, TInt aPriority) + { + TInt i; + for(i = 0; i < iOverlays.Count() && iOverlays[i].iPriority < aPriority; i++) + {} + const TOverlay overlay = {&aOverlay, aPriority}; + return iOverlays.Insert(overlay, i); + } + +TInt CDsa::RemoveOverlay(MOverlay& aOverlay) + { + for(TInt i = 0; i < iOverlays.Count(); i++) + { + if(iOverlays[i].iOverlay == &aOverlay) + { + iOverlays.Remove(i); + return KErrNone; + } + } + return KErrNotFound; + } + +TInt CDsa::RedrawRequest() + { + if(!(iStateFlags & (EUpdating) && (iStateFlags & ERunning))) + { + return ExternalUpdate(); + } + return KErrNotReady; + } + + +void CDsa::Resume() + { + if(Stopped()) + Restart(RDirectScreenAccess::ETerminateRegion); + } + +void CDsa::DoStop() + { + if(IsDsaAvailable()) + iStateFlags |= ESdlThreadExplicitStop; + Stop(); + } + +void CDsa::Stop() + { + iStateFlags &= ~ERunning; +// Cancel(); //can be called only from main! + iDsa->Cancel(); + } + +void CDsa::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/) + { +// iStateFlags |= EChangeNotify; + Stop(); + } + +void CDsa::Restart(RDirectScreenAccess::TTerminationReasons aReason) + { + if(aReason == RDirectScreenAccess::ETerminateRegion) //auto restart + { + TRAPD(err, RestartL()); + PANIC_IF_ERROR(err); + } + } +/*) +TBool CDsa::ChangeTrigger() + { + const TBool change = iStateFlags & EChangeNotify; + iStateFlags &= ~EChangeNotify; + return change; + } +*/ +///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void CDsa::Copy256(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *target++ = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Reversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* source = aSource; + while(target < endt) + { + *(--endt) = aDsa.iLut256[*source++]; + } + } + +void CDsa::Copy256Flip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *target++ = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::Copy256FlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint8* column = aSource; + + while(target < endt) + { + *(--endt) = aDsa.iLut256[*column]; + column += aLineLen; + } + } + +void CDsa::CopyMem(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + Mem::Copy(aTarget, aSource, aBytes); + } + +void CDsa::CopyMemFlip(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TUint32* target = aTarget; + const TUint32* endt = target + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *target++ = *column; + column += aLineLen; + } + } + +void CDsa::CopyMemReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* source = reinterpret_cast<const TUint32*>(aSource); + while(target < endt) + { + *(--endt) = *source++; + } + } + + +void CDsa::CopyMemFlipReversed(const CDsa& /*aDsa*/, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + const TUint32* target = aTarget; + TUint32* endt = aTarget + aBytes; + const TUint32* column = reinterpret_cast<const TUint32*>(aSource); + + while(target < endt) + { + *(--endt) = *column; + column += aLineLen; + } + } + + +typedef TRgb (*TRgbFunc) (TInt aValue); + +LOCAL_C TRgb rgb16MA(TInt aValue) + { + return TRgb::Color16MA(aValue); + } + +NONSHARABLE_CLASS(MRgbCopy) + { + public: + virtual void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) = 0; + virtual void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) = 0; + }; +template <class T> +NONSHARABLE_CLASS(TRgbCopy) : public MRgbCopy + { + public: + TRgbCopy(TDisplayMode aMode); + void* operator new(TUint aBytes, TAny* aMem); + void Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed); + void FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed); + private: + TRgbFunc iFunc; + }; + +template <class T> +void* TRgbCopy<T>::operator new(TUint /*aBytes*/, TAny* aMem) + { + return aMem; + } + +template <class T> +TRgbCopy<T>::TRgbCopy(TDisplayMode aMode) + { + switch(aMode) + { + case EGray256 : iFunc = TRgb::Gray256; break; + case EColor256 : iFunc = TRgb::Color256; break; + case EColor4K : iFunc = TRgb::Color4K; break; + case EColor64K : iFunc = TRgb::Color64K; break; + case EColor16M : iFunc = TRgb::Color16M; break; + case EColor16MU : iFunc = TRgb::Color16MU; break; + case EColor16MA : iFunc = rgb16MA; break; + default: + PANIC(KErrNotSupported); + } + } + +template <class T> +void TRgbCopy<T>::Copy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TBool aReversed) + { + const T* source = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + TUint32 value = *source++; + *(--endt) = iFunc(value).Value(); + } + } + else + { + while(target < endt) + { + TUint32 value = *source++; + *target++ = iFunc(value).Value(); + } + } + } + +template <class T> +void TRgbCopy<T>::FlipCopy(TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen, TBool aReversed) + { + const T* column = reinterpret_cast<const T*>(aSource); + TUint32* target = aTarget; + TUint32* endt = target + aBytes; + + if(aReversed) + { + while(target < endt) + { + *(--endt) = iFunc(*column).Value(); + column += aLineLen; + } + } + else + { + while(target < endt) + { + *target++ = iFunc(*column).Value(); + column += aLineLen; + } + } + } + + +typedef TUint64 TStackMem; + +LOCAL_C MRgbCopy* GetCopy(TAny* mem, TDisplayMode aMode) + { + if(aMode == EColor256 || aMode == EGray256) + { + return new (mem) TRgbCopy<TUint8>(aMode); + } + if(aMode == EColor4K || aMode == EColor64K) + { + return new (mem) TRgbCopy<TUint16>(aMode); + } + if(aMode == EColor16M || aMode == EColor16MU || aMode == EColor16MA) + { + return new (mem) TRgbCopy<TUint32>(aMode); + } + PANIC(KErrNotSupported); + return NULL; + } + + +void CDsa::CopySlowFlipReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, ETrue); + } + +void CDsa::CopySlowFlip(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt aLineLen) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->FlipCopy(aTarget, aSource, aBytes, aLineLen, EFalse); + } + +void CDsa::CopySlow(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, EFalse); + } + +void CDsa::CopySlowReversed(const CDsa& aDsa, TUint32* aTarget, const TUint8* aSource, TInt aBytes, TInt) + { + TStackMem mem = 0; + GetCopy(&mem, aDsa.iSourceMode)->Copy(aTarget, aSource, aBytes, ETrue); + }
\ No newline at end of file diff --git a/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h b/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h new file mode 100644 index 0000000..8e10a04 --- /dev/null +++ b/3rdparty/SDL/src/video/symbian/SDL_epocevents_c.h @@ -0,0 +1,60 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +/* + SDL_epocevents_c.h + Handle the event stream, converting Epoc events into SDL events + + Epoc version by Hannu Viitala (hannu.j.viitala@mbnet.fi) and Markus Mertama + +*/ + + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id: SDL_aaevents_c.h,v 1.1.2.2 2000/03/16 15:20:39 hercules Exp $"; +#endif + +extern "C" { +#include "SDL_sysvideo.h" +//#include "SDL_epocvideo.h" +} + + + +#define MAX_SCANCODE 255 + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *_this +#define Private _this->hidden + +extern "C" { +extern void EPOC_InitOSKeymap(_THIS); +extern void EPOC_PumpEvents(_THIS); +} + +extern TBool isCursorVisible; + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglevents.c b/3rdparty/SDL/src/video/vgl/SDL_vglevents.c new file mode 100644 index 0000000..fa6c9e7 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglevents.c @@ -0,0 +1,299 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <stdio.h> + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <sys/kbio.h> +#include <vgl.h> + +#include "SDL.h" +#include "SDL_thread.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglevents_c.h" + +/* The translation tables from a console scancode to a SDL keysym */ +/* FIXME: Free the keymap when we shut down the video mode */ +static keymap_t *vga_keymap = NULL; +static SDLKey keymap[128]; +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +static int posted = 0; +static int oldx = -1; +static int oldy = -1; +static struct mouse_info mouseinfo; + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +int VGL_initkeymaps(int fd) +{ + vga_keymap = SDL_malloc(sizeof(keymap_t)); + if ( ! vga_keymap ) { + SDL_OutOfMemory(); + return(-1); + } + if (ioctl(fd, GIO_KEYMAP, vga_keymap) == -1) { + SDL_free(vga_keymap); + vga_keymap = NULL; + SDL_SetError("Unable to get keyboard map"); + return(-1); + } + return(0); +} + +static void handle_keyboard(_THIS) +{ + SDL_keysym keysym; + int c, pressed, scancode; + + while ((c = VGLKeyboardGetCh()) != 0) { + scancode = c & 0x7F; + if (c & 0x80) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + + posted += SDL_PrivateKeyboard(pressed, + TranslateKey(scancode, &keysym)); + } +} + +int VGL_initmouse(int fd) +{ + mouseinfo.operation = MOUSE_GETINFO; + if (ioctl(fd, CONS_MOUSECTL, &mouseinfo) != 0) + return -1; + + return 0; +} + +static void handle_mouse(_THIS) +{ + char buttons; + int x, y; + int button_state, state_changed, state; + int i; + + ioctl(0, CONS_MOUSECTL, &mouseinfo); + x = mouseinfo.u.data.x; + y = mouseinfo.u.data.y; + buttons = mouseinfo.u.data.buttons; + + if ((x != oldx) || (y != oldy)) { + posted += SDL_PrivateMouseMotion(0, 0, x, y); + oldx = x; + oldy = y; + } + + /* See what's changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ buttons; + for (i = 0; i < 8; i++) { + if (state_changed & (1<<i)) { + if (buttons & (1<<i)) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i + 1, 0, 0); + } + } +} + + +void VGL_PumpEvents(_THIS) +{ + do { + posted = 0; + handle_keyboard(this); + handle_mouse(this); + } while (posted != 0); +} + +void VGL_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the BeOS key translation table */ + for ( i=0; i<SDL_arraysize(keymap); ++i ) + keymap[i] = SDLK_UNKNOWN; + + keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; + keymap[SCANCODE_1] = SDLK_1; + keymap[SCANCODE_2] = SDLK_2; + keymap[SCANCODE_3] = SDLK_3; + keymap[SCANCODE_4] = SDLK_4; + keymap[SCANCODE_5] = SDLK_5; + keymap[SCANCODE_6] = SDLK_6; + keymap[SCANCODE_7] = SDLK_7; + keymap[SCANCODE_8] = SDLK_8; + keymap[SCANCODE_9] = SDLK_9; + keymap[SCANCODE_0] = SDLK_0; + keymap[SCANCODE_MINUS] = SDLK_MINUS; + keymap[SCANCODE_EQUAL] = SDLK_EQUALS; + keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; + keymap[SCANCODE_TAB] = SDLK_TAB; + keymap[SCANCODE_Q] = SDLK_q; + keymap[SCANCODE_W] = SDLK_w; + keymap[SCANCODE_E] = SDLK_e; + keymap[SCANCODE_R] = SDLK_r; + keymap[SCANCODE_T] = SDLK_t; + keymap[SCANCODE_Y] = SDLK_y; + keymap[SCANCODE_U] = SDLK_u; + keymap[SCANCODE_I] = SDLK_i; + keymap[SCANCODE_O] = SDLK_o; + keymap[SCANCODE_P] = SDLK_p; + keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; + keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; + keymap[SCANCODE_ENTER] = SDLK_RETURN; + keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; + keymap[SCANCODE_A] = SDLK_a; + keymap[SCANCODE_S] = SDLK_s; + keymap[SCANCODE_D] = SDLK_d; + keymap[SCANCODE_F] = SDLK_f; + keymap[SCANCODE_G] = SDLK_g; + keymap[SCANCODE_H] = SDLK_h; + keymap[SCANCODE_J] = SDLK_j; + keymap[SCANCODE_K] = SDLK_k; + keymap[SCANCODE_L] = SDLK_l; + keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; + keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; + keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; + keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; + keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; + keymap[SCANCODE_Z] = SDLK_z; + keymap[SCANCODE_X] = SDLK_x; + keymap[SCANCODE_C] = SDLK_c; + keymap[SCANCODE_V] = SDLK_v; + keymap[SCANCODE_B] = SDLK_b; + keymap[SCANCODE_N] = SDLK_n; + keymap[SCANCODE_M] = SDLK_m; + keymap[SCANCODE_COMMA] = SDLK_COMMA; + keymap[SCANCODE_PERIOD] = SDLK_PERIOD; + keymap[SCANCODE_SLASH] = SDLK_SLASH; + keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; + keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; + keymap[SCANCODE_LEFTALT] = SDLK_LALT; + keymap[SCANCODE_SPACE] = SDLK_SPACE; + keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; + keymap[SCANCODE_F1] = SDLK_F1; + keymap[SCANCODE_F2] = SDLK_F2; + keymap[SCANCODE_F3] = SDLK_F3; + keymap[SCANCODE_F4] = SDLK_F4; + keymap[SCANCODE_F5] = SDLK_F5; + keymap[SCANCODE_F6] = SDLK_F6; + keymap[SCANCODE_F7] = SDLK_F7; + keymap[SCANCODE_F8] = SDLK_F8; + keymap[SCANCODE_F9] = SDLK_F9; + keymap[SCANCODE_F10] = SDLK_F10; + keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; + keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; + keymap[SCANCODE_KEYPAD7] = SDLK_KP7; + keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; + keymap[SCANCODE_KEYPAD8] = SDLK_KP8; + keymap[SCANCODE_CURSORUP] = SDLK_KP8; + keymap[SCANCODE_KEYPAD9] = SDLK_KP9; + keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; + keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; + keymap[SCANCODE_KEYPAD4] = SDLK_KP4; + keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; + keymap[SCANCODE_KEYPAD5] = SDLK_KP5; + keymap[SCANCODE_KEYPAD6] = SDLK_KP6; + keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; + keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; + keymap[SCANCODE_KEYPAD1] = SDLK_KP1; + keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; + keymap[SCANCODE_KEYPAD2] = SDLK_KP2; + keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; + keymap[SCANCODE_KEYPAD3] = SDLK_KP3; + keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; + keymap[SCANCODE_KEYPAD0] = SDLK_KP0; + keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; + keymap[SCANCODE_LESS] = SDLK_LESS; + keymap[SCANCODE_F11] = SDLK_F11; + keymap[SCANCODE_F12] = SDLK_F12; + keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; + keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; + keymap[SCANCODE_CONTROL] = SDLK_RCTRL; + keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; + keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; + keymap[SCANCODE_RIGHTALT] = SDLK_RALT; + keymap[SCANCODE_BREAK] = SDLK_BREAK; + keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; + keymap[SCANCODE_HOME] = SDLK_HOME; + keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; + keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; + keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; + keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; + keymap[SCANCODE_END] = SDLK_END; + keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; + keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; + keymap[SCANCODE_INSERT] = SDLK_INSERT; + keymap[SCANCODE_REMOVE] = SDLK_DELETE; + keymap[119] = SDLK_PAUSE; + keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; + keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; + keymap[127] = SDLK_MENU; +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE && vga_keymap ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map += 1; + } + if ( modstate & KMOD_CTRL ) { + map += 2; + } + if ( modstate & KMOD_ALT ) { + map += 4; + } + if ( !(vga_keymap->key[scancode].spcl & (0x80 >> map)) ) { + keysym->unicode = vga_keymap->key[scancode].map[map]; + } + + } + return(keysym); +} + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h b/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h new file mode 100644 index 0000000..614cab5 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglevents_c.h @@ -0,0 +1,155 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_vglvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int VGL_initkeymaps(int fd); +extern int VGL_initmouse(int fd); +extern void VGL_keyboardcallback(int scancode, int pressed); + +extern void VGL_InitOSKeymap(_THIS); +extern void VGL_PumpEvents(_THIS); + +/* Mouse buttons */ +#define MOUSE_LEFTBUTTON 0x01 +#define MOUSE_MIDDLEBUTTON 0x02 +#define MOUSE_RIGHTBUTTON 0x04 + +/* Scancodes */ +#define SCANCODE_ESCAPE 1 +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 +#define SCANCODE_ENTER 28 +#define SCANCODE_LEFTCONTROL 29 +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 +#define SCANCODE_LESS 86 +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 +#define SCANCODE_KEYPADENTER 89 +#define SCANCODE_RIGHTCONTROL 90 +#define SCANCODE_CONTROL 107 +#define SCANCODE_KEYPADDIVIDE 91 +#define SCANCODE_PRINTSCREEN 92 +#define SCANCODE_RIGHTALT 93 +#define SCANCODE_BREAK 104 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 104 /* on some keyboards! */ +#define SCANCODE_HOME 94 +#define SCANCODE_CURSORBLOCKUP 95 /* Cursor key block */ +#define SCANCODE_PAGEUP 96 +#define SCANCODE_CURSORBLOCKLEFT 97 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 98 /* Cursor key block */ +#define SCANCODE_END 99 +#define SCANCODE_CURSORBLOCKDOWN 100 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 101 +#define SCANCODE_INSERT 102 +#define SCANCODE_REMOVE 103 +#define SCANCODE_RIGHTWIN 106 +#define SCANCODE_LEFTWIN 105 diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c b/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c new file mode 100644 index 0000000..466f1c5 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglmouse.c @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; + + +void VGL_FreeWMCursor(_THIS, WMcursor *cursor) +{ + return; +} + +WMcursor *VGL_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + return(NULL); +} + +int VGL_ShowWMCursor(_THIS, WMcursor *cursor) +{ + return(0); +} + +void VGL_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + SDL_PrivateMouseMotion(0, 0, x, y); +} + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h b/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h new file mode 100644 index 0000000..f579d65 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglmouse_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_vglvideo.h" + +/* Functions to be exported */ +extern void VGL_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *VGL_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int VGL_ShowWMCursor(_THIS, WMcursor *cursor); +extern void VGL_WarpWMCursor(_THIS, Uint16 x, Uint16 y); + diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c new file mode 100644 index 0000000..0b61615 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.c @@ -0,0 +1,624 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* libvga based SDL video driver implementation. +*/ + +#include <err.h> +#include <osreldate.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <sys/kbio.h> +#include <vgl.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_vglvideo.h" +#include "SDL_vglevents_c.h" +#include "SDL_vglmouse_c.h" + + +/* Initialization/Query functions */ +static int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int VGL_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void VGL_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface); +static int VGL_LockHWSurface(_THIS, SDL_Surface *surface); +static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface); +static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Misc function */ +static VGLMode ** VGLListModes(int depth, int mem_model); + +/* VGL driver bootstrap functions */ + +static int VGL_Available(void) +{ + /* + * Check to see if we are root and stdin is a + * virtual console. Also try to ensure that + * modes other than 320x200 are available + */ + int console, hires_available, i; + VGLMode **modes; + + console = STDIN_FILENO; + if ( console >= 0 ) { + struct stat sb; + struct vt_mode dummy; + + if ( (fstat(console, &sb) < 0) || + (ioctl(console, VT_GETMODE, &dummy) < 0) ) { + console = -1; + } + } + if (geteuid() != 0 && console == -1) + return 0; + + modes = VGLListModes(8, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + hires_available = 0; + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Xsize > 320) && + (modes[i]->ModeInfo.Ysize > 200) && + ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32))) { + hires_available = 1; + break; + } + } + return hires_available; +} + +static void VGL_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *VGL_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + + /* Set the function pointers */ + device->VideoInit = VGL_VideoInit; + device->ListModes = VGL_ListModes; + device->SetVideoMode = VGL_SetVideoMode; + device->SetColors = VGL_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = VGL_VideoQuit; + device->AllocHWSurface = VGL_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = VGL_LockHWSurface; + device->UnlockHWSurface = VGL_UnlockHWSurface; + device->FlipHWSurface = VGL_FlipHWSurface; + device->FreeHWSurface = VGL_FreeHWSurface; + device->SetIcon = NULL; + device->SetCaption = NULL; + device->GetWMInfo = NULL; + device->FreeWMCursor = VGL_FreeWMCursor; + device->CreateWMCursor = VGL_CreateWMCursor; + device->ShowWMCursor = VGL_ShowWMCursor; + device->WarpWMCursor = VGL_WarpWMCursor; + device->InitOSKeymap = VGL_InitOSKeymap; + device->PumpEvents = VGL_PumpEvents; + + device->free = VGL_DeleteDevice; + + return device; +} + +VideoBootStrap VGL_bootstrap = { + "vgl", "FreeBSD libVGL", + VGL_Available, VGL_CreateDevice +}; + +static int VGL_AddMode(_THIS, VGLMode *inmode) +{ + SDL_Rect *mode; + + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if (inmode->Depth < 8) { /* Not supported */ + return 0; + } + index = ((inmode->Depth + 7) / 8) - 1; + for (i=0; i<SDL_nummodes[index]; ++i) { + mode = SDL_modelist[index][i]; + if ((mode->w == inmode->ModeInfo.Xsize) && + (mode->h == inmode->ModeInfo.Ysize)) + return 0; + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if (mode == NULL) { + SDL_OutOfMemory(); + return -1; + } + mode->x = 0; + mode->y = 0; + mode->w = inmode->ModeInfo.Xsize; + mode->h = inmode->ModeInfo.Ysize; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if (SDL_modelist[index] == NULL) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return -1; + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return 0; +} + +static void VGL_UpdateVideoInfo(_THIS) +{ + this->info.wm_available = 0; + this->info.hw_available = 1; + this->info.video_mem = 0; + if (VGLCurMode == NULL) { + return; + } + if (VGLCurMode->ModeInfo.PixelBytes > 0) { + this->info.video_mem = VGLCurMode->ModeInfo.PixelBytes * + VGLCurMode->ModeInfo.Xsize * + VGLCurMode->ModeInfo.Ysize; + } +} + +int VGL_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + int total_modes; + VGLMode **modes; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + } + + /* Enable mouse and keyboard support */ + if (SDL_getenv("SDL_NO_RAWKBD") == NULL) { + if (VGLKeyboardInit(VGL_CODEKEYS) != 0) { + SDL_SetError("Unable to initialize keyboard"); + return -1; + } + } else { + warnx("Requiest to put keyboard into a raw mode ignored"); + } + if (VGL_initkeymaps(STDIN_FILENO) != 0) { + SDL_SetError("Unable to initialize keymap"); + return -1; + } + if (VGL_initmouse(STDIN_FILENO) != 0) { + SDL_SetError("Unable to initialize mouse"); + return -1; + } + + /* Determine the current screen size */ + if (VGLCurMode != NULL) { + this->info.current_w = VGLCurMode->ModeInfo.Xsize; + this->info.current_h = VGLCurMode->ModeInfo.Ysize; + } + + /* Determine the screen depth */ + if (VGLCurMode != NULL) + vformat->BitsPerPixel = VGLCurMode->Depth; + else + vformat->BitsPerPixel = 16; /* Good default */ + + /* Query for the list of available video modes */ + total_modes = 0; + modes = VGLListModes(-1, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32)) { + VGL_AddMode(this, modes[i]); + total_modes++; + } + } + if (total_modes == 0) { + SDL_SetError("No linear video modes available"); + return -1; + } + + /* Fill in our hardware acceleration capabilities */ + VGL_UpdateVideoInfo(this); + + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if (hw_lock == NULL) { + SDL_SetError("Unable to create lock mutex"); + VGL_VideoQuit(this); + return -1; + } + + /* We're done! */ + return 0; +} + +SDL_Rect **VGL_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return SDL_modelist[((format->BitsPerPixel+7)/8)-1]; +} + +/* Various screen update functions available */ +static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *VGL_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode_found; + int i; + VGLMode **modes; + + modes = VGLListModes(bpp, V_INFO_MM_DIRECT | V_INFO_MM_PACKED); + mode_found = 0; + for (i = 0; modes[i] != NULL; i++) { + if ((modes[i]->ModeInfo.Xsize == width) && + (modes[i]->ModeInfo.Ysize == height) && + ((modes[i]->ModeInfo.Type == VIDBUF8) || + (modes[i]->ModeInfo.Type == VIDBUF16) || + (modes[i]->ModeInfo.Type == VIDBUF32))) { + mode_found = 1; + break; + } + } + if (mode_found == 0) { + SDL_SetError("No matching video mode found"); + return NULL; + } + + /* Shutdown previous videomode (if any) */ + if (VGLCurMode != NULL) + VGLEnd(); + + /* Try to set the requested linear video mode */ + if (VGLInit(modes[i]->ModeId) != 0) { + SDL_SetError("Unable to switch to requested mode"); + return NULL; + } + + VGLCurMode = SDL_realloc(VGLCurMode, sizeof(VGLMode)); + VGLCurMode->ModeInfo = *VGLDisplay; + VGLCurMode->Depth = modes[i]->Depth; + VGLCurMode->ModeId = modes[i]->ModeId; + VGLCurMode->Rmask = modes[i]->Rmask; + VGLCurMode->Gmask = modes[i]->Gmask; + VGLCurMode->Bmask = modes[i]->Bmask; + + /* Workaround a bug in libvgl */ + if (VGLCurMode->ModeInfo.PixelBytes == 0) + (VGLCurMode->ModeInfo.PixelBytes = 1); + + current->w = VGLCurMode->ModeInfo.Xsize; + current->h = VGLCurMode->ModeInfo.Ysize; + current->pixels = VGLCurMode->ModeInfo.Bitmap; + current->pitch = VGLCurMode->ModeInfo.Xsize * + VGLCurMode->ModeInfo.PixelBytes; + current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); + + /* Check if we are in a pseudo-color mode */ + if (VGLCurMode->ModeInfo.Type == VIDBUF8) + current->flags |= SDL_HWPALETTE; + + /* Check if we can do doublebuffering */ + if (flags & SDL_DOUBLEBUF) { + if (VGLCurMode->ModeInfo.Xsize * 2 <= + VGLCurMode->ModeInfo.VYsize) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_address[0] = (byte *)current->pixels; + flip_address[1] = (byte *)current->pixels + + current->h * current->pitch; + VGL_FlipHWSurface(this, current); + } + } + + if (! SDL_ReallocFormat(current, modes[i]->Depth, VGLCurMode->Rmask, + VGLCurMode->Gmask, VGLCurMode->Bmask, 0)) { + return NULL; + } + + /* Update hardware acceleration info */ + VGL_UpdateVideoInfo(this); + + /* Set the blit function */ + this->UpdateRects = VGL_DirectUpdate; + + /* We're done */ + return current; +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int VGL_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} +static void VGL_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +/* We need to wait for vertical retrace on page flipped displays */ +static int VGL_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface == SDL_VideoSurface) { + SDL_mutexP(hw_lock); + } + return 0; +} +static void VGL_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface == SDL_VideoSurface) { + SDL_mutexV(hw_lock); + } +} + +static int VGL_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (VGLPanScreen(VGLDisplay, 0, flip_page * surface->h) < 0) { + SDL_SetError("VGLPanSreen() failed"); + return -1; + } + + flip_page = !flip_page; + surface->pixels = flip_address[flip_page]; + + return 0; +} + +static void VGL_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + return; +} + +int VGL_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + + for(i = 0; i < ncolors; i++) { + VGLSetPaletteIndex(firstcolor + i, + colors[i].r>>2, + colors[i].g>>2, + colors[i].b>>2); + } + return 1; +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void VGL_VideoQuit(_THIS) +{ + int i, j; + + /* Return the keyboard to the normal state */ + VGLKeyboardEnd(); + + /* Reset the console video mode if we actually initialised one */ + if (VGLCurMode != NULL) { + VGLEnd(); + SDL_free(VGLCurMode); + VGLCurMode = NULL; + } + + /* Clear the lock mutex */ + if (hw_lock != NULL) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } + + /* Free video mode lists */ + for (i = 0; i < NUM_MODELISTS; i++) { + if (SDL_modelist[i] != NULL) { + for (j = 0; SDL_modelist[i][j] != NULL; ++j) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, not a memory buffer */ + this->screen->pixels = NULL; + } +} + +#define VGL_RED_INDEX 0 +#define VGL_GREEN_INDEX 1 +#define VGL_BLUE_INDEX 2 + +static VGLMode ** +VGLListModes(int depth, int mem_model) +{ + static VGLMode **modes = NULL; + + VGLBitmap *vminfop; + VGLMode **modesp, *modescp; + video_info_t minfo; + int adptype, i, modenum; + + if (modes == NULL) { + modes = SDL_malloc(sizeof(VGLMode *) * M_VESA_MODE_MAX); + bzero(modes, sizeof(VGLMode *) * M_VESA_MODE_MAX); + } + modesp = modes; + + for (modenum = 0; modenum < M_VESA_MODE_MAX; modenum++) { + minfo.vi_mode = modenum; + if (ioctl(0, CONS_MODEINFO, &minfo) || ioctl(0, CONS_CURRENT, &adptype)) + continue; + if (minfo.vi_mode != modenum) + continue; + if ((minfo.vi_flags & V_INFO_GRAPHICS) == 0) + continue; + if ((mem_model != -1) && ((minfo.vi_mem_model & mem_model) == 0)) + continue; + if ((depth > 1) && (minfo.vi_depth != depth)) + continue; + + /* reallocf can fail */ + if ((*modesp = reallocf(*modesp, sizeof(VGLMode))) == NULL) + return NULL; + modescp = *modesp; + + vminfop = &(modescp->ModeInfo); + bzero(vminfop, sizeof(VGLBitmap)); + + vminfop->Type = NOBUF; + + vminfop->PixelBytes = 1; /* Good default value */ + switch (minfo.vi_mem_model) { + case V_INFO_MM_PLANAR: + /* we can handle EGA/VGA planar modes only */ + if (!(minfo.vi_depth != 4 || minfo.vi_planes != 4 + || (adptype != KD_EGA && adptype != KD_VGA))) + vminfop->Type = VIDBUF4; + break; + case V_INFO_MM_PACKED: + /* we can do only 256 color packed modes */ + if (minfo.vi_depth == 8) + vminfop->Type = VIDBUF8; + break; + case V_INFO_MM_VGAX: + vminfop->Type = VIDBUF8X; + break; +#if defined(__FREEBSD__) && (defined(__DragonFly__) || __FreeBSD_version >= 500000) + case V_INFO_MM_DIRECT: + vminfop->PixelBytes = minfo.vi_pixel_size; + switch (vminfop->PixelBytes) { + case 2: + vminfop->Type = VIDBUF16; + break; +#if notyet + case 3: + vminfop->Type = VIDBUF24; + break; +#endif + case 4: + vminfop->Type = VIDBUF32; + break; + default: + break; + } +#endif + default: + break; + } + if (vminfop->Type == NOBUF) + continue; + + switch (vminfop->Type) { + case VIDBUF16: + case VIDBUF32: + modescp->Rmask = ((1 << minfo.vi_pixel_fsizes[VGL_RED_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_RED_INDEX]; + modescp->Gmask = ((1 << minfo.vi_pixel_fsizes[VGL_GREEN_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_GREEN_INDEX]; + modescp->Bmask = ((1 << minfo.vi_pixel_fsizes[VGL_BLUE_INDEX]) - 1) << + minfo.vi_pixel_fields[VGL_BLUE_INDEX]; + break; + + default: + break; + } + + vminfop->Xsize = minfo.vi_width; + vminfop->Ysize = minfo.vi_height; + modescp->Depth = minfo.vi_depth; + + /* XXX */ + if (minfo.vi_mode >= M_VESA_BASE) + modescp->ModeId = _IO('V', minfo.vi_mode - M_VESA_BASE); + else + modescp->ModeId = _IO('S', minfo.vi_mode); + + /* Sort list */ + for (i = 0; modes + i < modesp ; i++) { + if (modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize > + vminfop->Xsize * modes[i]->ModeInfo.Ysize) + continue; + if ((modes[i]->ModeInfo.Xsize * modes[i]->ModeInfo.Ysize == + vminfop->Xsize * vminfop->Ysize) && + (modes[i]->Depth >= modescp->Depth)) + continue; + *modesp = modes[i]; + modes[i] = modescp; + modescp = *modesp; + vminfop = &(modescp->ModeInfo); + } + + modesp++; + } + + if (*modesp != NULL) { + SDL_free(*modesp); + *modesp = NULL; + } + + return modes; +} diff --git a/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h new file mode 100644 index 0000000..9fc3569 --- /dev/null +++ b/3rdparty/SDL/src/video/vgl/SDL_vglvideo.h @@ -0,0 +1,65 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_vglvideo_h +#define _SDL_vglvideo_h + +#include <sys/fbio.h> +#include <sys/consio.h> +#include <vgl.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +typedef struct { + int ModeId; + int Depth; + int Rmask; + int Gmask; + int Bmask; + VGLBitmap ModeInfo; +} VGLMode; + +/* Private display data */ +struct SDL_PrivateVideoData { +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + SDL_mutex *hw_lock; + VGLMode *VGLCurMode; + int flip_page; + byte *flip_address[2]; +}; +/* Old variable names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define hw_lock (this->hidden->hw_lock) +#define VGLCurMode (this->hidden->VGLCurMode) +#define flip_page (this->hidden->flip_page) +#define flip_address (this->hidden->flip_address) + +#endif /* _SDL_vglvideo_h */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h b/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h new file mode 100644 index 0000000..89d1a88 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_lowvideo.h @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_lowvideo_h +#define _SDL_lowvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#ifndef SetClassLongPtr +#define SetClassLongPtr SetClassLong +#endif +#ifndef GetWindowLongPtr +#define GetWindowLongPtr GetWindowLong +#endif +#ifndef SetWindowLongPtr +#define SetWindowLongPtr SetWindowLong +#endif +#ifndef GWLP_WNDPROC +#define GWLP_WNDPROC GWL_WNDPROC +#endif +#ifndef GWLP_HINSTANCE +#define GWLP_HINSTANCE GWL_HINSTANCE +#endif +#ifndef GCLP_HICON +#define GCLP_HICON GCL_HICON +#endif + +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define FULLSCREEN() \ + ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) + +#define WINDIB_FULLSCREEN() \ +( \ + SDL_VideoSurface && \ + FULLSCREEN() && \ + (((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \ + ((SDL_strcmp(this->name, "windib") == 0) || \ + (SDL_strcmp(this->name, "gapi") == 0))) \ +) +#define DDRAW_FULLSCREEN() \ +( \ + SDL_VideoSurface && \ + FULLSCREEN() && \ + ((SDL_VideoSurface->flags & SDL_OPENGL ) != SDL_OPENGL ) && \ + (SDL_strcmp(this->name, "directx") == 0) \ +) + +#define DINPUT_FULLSCREEN() \ +( \ + FULLSCREEN() && \ + (strcmp(this->name, "directx") == 0) \ +) + +#define DINPUT() (strcmp(this->name, "directx") == 0) + +/* The main window -- and a function to set it for the audio */ +#ifdef _WIN32_WCE +extern LPWSTR SDL_Appname; +#else +extern LPSTR SDL_Appname; +#endif +extern HINSTANCE SDL_Instance; +extern HWND SDL_Window; +extern BOOL SDL_windowid; + +/* Variables and functions exported to other parts of the native video + subsystem (SDL_sysevents.c) +*/ +extern void WIN_FlushMessageQueue(); + +/* Called by windows message loop when application is activated */ +extern void (*WIN_Activate)(_THIS, BOOL active, BOOL minimized); + +/* Called by windows message loop when system palette is available */ +extern void (*WIN_RealizePalette)(_THIS); + +/* Called by windows message loop when the system palette changes */ +extern void (*WIN_PaletteChanged)(_THIS, HWND window); + +/* Called by windows message loop when a portion of the screen needs update */ +extern void (*WIN_WinPAINT)(_THIS, HDC hdc); + +/* Called by windows message loop when the message isn't handled */ +extern LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +/* The window cursor (from SDL_sysmouse.c) */ +extern HCURSOR SDL_hcursor; + +/* The bounds of the window in screen coordinates */ +extern RECT SDL_bounds; + +/* The position of the window in windowed mode */ +extern int SDL_windowX; +extern int SDL_windowY; + +/* Flag -- SDL is performing a resize, rather than the user */ +extern int SDL_resizing; + +/* Flag -- the mouse is in relative motion mode */ +extern int mouse_relative; + +/* The GDI fullscreen mode currently active */ +#ifndef NO_CHANGEDISPLAYSETTINGS +extern DEVMODE SDL_desktop_mode; +extern DEVMODE SDL_fullscreen_mode; +#endif + +/* The system gamma ramp for GDI modes */ +extern WORD *gamma_saved; + +/* This is really from SDL_dx5audio.c */ +extern void DX5_SoundFocus(HWND window); + +/* DJM: This is really from SDL_sysevents.c, we need it in + GDL_CreateWindow as well */ +LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + +#ifdef _WIN64 +#define SDL_ToUnicode ToUnicode +#else +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */ +typedef int (WINAPI *ToUnicodeFN)(UINT, UINT, const BYTE *, LPWSTR, int, UINT); + +extern ToUnicodeFN SDL_ToUnicode; +#endif + +#endif /* SDL_lowvideo_h */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c b/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c new file mode 100644 index 0000000..76c67a1 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysevents.c @@ -0,0 +1,855 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */ +#ifndef WM_XBUTTONDOWN +#define WM_XBUTTONDOWN 0x020B +#endif +#ifndef WM_XBUTTONUP +#define WM_XBUTTONUP 0x020C +#endif +#ifndef GET_XBUTTON_WPARAM +#define GET_XBUTTON_WPARAM(w) (HIWORD(w)) +#endif + +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_lowvideo.h" +#include "SDL_syswm_c.h" +#include "SDL_main.h" +#include "SDL_loadso.h" + +#ifdef WMMSG_DEBUG +#include "wmmsg.h" +#endif + +#include "../windib/SDL_gapidibvideo.h" + +#ifdef SDL_VIDEO_DRIVER_GAPI +#include "../gapi/SDL_gapivideo.h" +#endif + +#ifdef _WIN32_WCE +#define IsZoomed(HWND) 1 +#define NO_GETKEYBOARDSTATE +#if _WIN32_WCE < 420 +#define NO_CHANGEDISPLAYSETTINGS +#endif +#endif + +/* The window we use for everything... */ +#ifdef _WIN32_WCE +LPWSTR SDL_Appname = NULL; +#else +LPSTR SDL_Appname = NULL; +#endif +Uint32 SDL_Appstyle = 0; +HINSTANCE SDL_Instance = NULL; +HWND SDL_Window = NULL; +RECT SDL_bounds = {0, 0, 0, 0}; +int SDL_windowX = 0; +int SDL_windowY = 0; +int SDL_resizing = 0; +int mouse_relative = 0; +int posted = 0; +#ifndef NO_CHANGEDISPLAYSETTINGS +DEVMODE SDL_desktop_mode; +DEVMODE SDL_fullscreen_mode; +#endif +WORD *gamma_saved = NULL; + + +/* Functions called by the message processing function */ +LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL; +void (*WIN_Activate)(_THIS, BOOL active, BOOL iconic); +void (*WIN_RealizePalette)(_THIS); +void (*WIN_PaletteChanged)(_THIS, HWND window); +void (*WIN_WinPAINT)(_THIS, HDC hdc); +extern void DIB_SwapGamma(_THIS); + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 +/* Variables and support functions for SDL_ToUnicode() */ +static int codepage; +static int Is9xME(); +static int GetCodePage(); +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, const BYTE *keystate, LPWSTR wchars, int wsize, UINT flags); + +ToUnicodeFN SDL_ToUnicode = ToUnicode9xME; +#endif +#endif /* !NO_GETKEYBOARDSTATE */ + + +#if defined(_WIN32_WCE) + +//AdjustWindowRect is not available under WinCE 2003 +#define AdjustWindowRect(a,b,c) (AdjustWindowRectEx((a),(b),(c),0)) + +// dynamically load aygshell dll because we want SDL to work on HPC and be300 +HINSTANCE aygshell = NULL; +BOOL (WINAPI *SHFullScreen)(HWND hwndRequester, DWORD dwState) = 0; + +#define SHFS_SHOWTASKBAR 0x0001 +#define SHFS_HIDETASKBAR 0x0002 +#define SHFS_SHOWSIPBUTTON 0x0004 +#define SHFS_HIDESIPBUTTON 0x0008 +#define SHFS_SHOWSTARTICON 0x0010 +#define SHFS_HIDESTARTICON 0x0020 + +static void LoadAygshell(void) +{ + if( !aygshell ) + aygshell = SDL_LoadObject("aygshell.dll"); + if( (aygshell != 0) && (SHFullScreen == 0) ) + { + SHFullScreen = (int (WINAPI *)(struct HWND__ *,unsigned long)) SDL_LoadFunction(aygshell, "SHFullScreen"); + } +} + +#endif + +/* JC 14 Mar 2006 + This is used all over the place, in the windib driver and in the dx5 driver + So we may as well stick it here instead of having multiple copies scattered + about +*/ +void WIN_FlushMessageQueue() +{ + MSG msg; + while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { + if ( msg.message == WM_QUIT ) break; + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } +} + +static void SDL_RestoreGameMode(void) +{ +#ifdef _WIN32_WCE //Under ce we don't minimize, therefore no restore + +#ifdef SDL_VIDEO_DRIVER_GAPI + SDL_VideoDevice *this = current_video; + if(SDL_strcmp(this->name, "gapi") == 0) + { + if( this->hidden->gapiInfo->suspended ) + { + this->hidden->gapiInfo->suspended = 0; + } + } +#endif + +#else + ShowWindow(SDL_Window, SW_RESTORE); +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS +#ifndef _WIN32_WCE + ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN); +#endif +#endif /* NO_CHANGEDISPLAYSETTINGS */ +} +static void SDL_RestoreDesktopMode(void) +{ + +#ifdef _WIN32_WCE + +#ifdef SDL_VIDEO_DRIVER_GAPI + SDL_VideoDevice *this = current_video; + if(SDL_strcmp(this->name, "gapi") == 0) + { + if( !this->hidden->gapiInfo->suspended ) + { + this->hidden->gapiInfo->suspended = 1; + } + } +#endif + +#else + /* WinCE does not have a taskbar, so minimizing is not convenient */ + ShowWindow(SDL_Window, SW_MINIMIZE); +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS +#ifndef _WIN32_WCE + ChangeDisplaySettings(NULL, 0); +#endif +#endif /* NO_CHANGEDISPLAYSETTINGS */ +} + +#ifdef WM_MOUSELEAVE +/* + Special code to handle mouse leave events - this sucks... + http://support.microsoft.com/support/kb/articles/q183/1/07.asp + + TrackMouseEvent() is only available on Win98 and WinNT. + _TrackMouseEvent() is available on Win95, but isn't yet in the mingw32 + development environment, and only works on systems that have had IE 3.0 + or newer installed on them (which is not the case with the base Win95). + Therefore, we implement our own version of _TrackMouseEvent() which + uses our own implementation if TrackMouseEvent() is not available. +*/ +static BOOL (WINAPI *_TrackMouseEvent)(TRACKMOUSEEVENT *ptme) = NULL; + +static VOID CALLBACK +TrackMouseTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime) +{ + union { RECT rect; POINT pt; } rectpt; /* prevent type-punning issue. */ + POINT pt; + + GetClientRect(hWnd, &rectpt.rect); + MapWindowPoints(hWnd, NULL, &rectpt.pt, 2); + GetCursorPos(&pt); + if ( !PtInRect(&rectpt.rect, pt) || (WindowFromPoint(pt) != hWnd) ) { + if ( !KillTimer(hWnd, idEvent) ) { + /* Error killing the timer! */ + } + PostMessage(hWnd, WM_MOUSELEAVE, 0, 0); + } +} +static BOOL WINAPI WIN_TrackMouseEvent(TRACKMOUSEEVENT *ptme) +{ + if ( ptme->dwFlags == TME_LEAVE ) { + return SetTimer(ptme->hwndTrack, ptme->dwFlags, 100, + (TIMERPROC)TrackMouseTimerProc) != 0; + } + return FALSE; +} +#endif /* WM_MOUSELEAVE */ + +int sysevents_mouse_pressed = 0; + +/* The main Win32 event handler +DJM: This is no longer static as (DX5/DIB)_CreateWindow needs it +*/ +LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SDL_VideoDevice *this = current_video; +#ifdef WMMSG_DEBUG + fprintf(stderr, "Received windows message: "); + if ( msg > MAX_WMMSG ) { + fprintf(stderr, "%d", msg); + } else { + fprintf(stderr, "%s", wmtab[msg]); + } + fprintf(stderr, " -- 0x%X, 0x%X\n", wParam, lParam); +#endif + switch (msg) { + + case WM_ACTIVATE: { + SDL_VideoDevice *this = current_video; + BOOL active, minimized; + Uint8 appstate; + + minimized = HIWORD(wParam); + active = (LOWORD(wParam) != WA_INACTIVE) && !minimized; + if ( active ) { + /* Gain the following states */ + appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS; + if ( !(SDL_GetAppState() & SDL_APPINPUTFOCUS) ) { + if ( this->input_grab != SDL_GRAB_OFF ) { + WIN_GrabInput(this, SDL_GRAB_ON); + } + if ( ! DDRAW_FULLSCREEN() ) { + DIB_SwapGamma(this); + } + if ( WINDIB_FULLSCREEN() ) { + SDL_RestoreGameMode(); + } + } +#if defined(_WIN32_WCE) + if ( WINDIB_FULLSCREEN() ) { + LoadAygshell(); + if( SHFullScreen ) + SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON); + else + ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE); + } +#endif + posted = SDL_PrivateAppActive(1, appstate); + } else { + /* Lose the following states */ + appstate = SDL_APPINPUTFOCUS; + if ( minimized ) { + appstate |= SDL_APPACTIVE; + } + + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + if ( this->input_grab != SDL_GRAB_OFF ) { + WIN_GrabInput(this, SDL_GRAB_OFF); + } + if ( ! DDRAW_FULLSCREEN() ) { + DIB_SwapGamma(this); + } + if ( WINDIB_FULLSCREEN() ) { + appstate |= SDL_APPMOUSEFOCUS; + SDL_RestoreDesktopMode(); + /* A fullscreen app gets hidden but will not get a minimize event */ + appstate |= (SDL_APPACTIVE | SDL_APPMOUSEFOCUS); +#if defined(_WIN32_WCE) + LoadAygshell(); + if( SHFullScreen ) + SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON); + else + ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW); +#endif + } + } + posted = SDL_PrivateAppActive(0, appstate); + } + WIN_Activate(this, active, minimized); + return(0); + } + break; + + case WM_MOUSEMOVE: { + +#ifdef WM_MOUSELEAVE + if ( SDL_VideoSurface ) { + /* mouse has entered the window */ + + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + TRACKMOUSEEVENT tme; + + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = SDL_Window; + _TrackMouseEvent(&tme); + } + } +#endif /* WM_MOUSELEAVE */ + + /* Mouse motion is handled in DIB_PumpEvents or + * DX5_PumpEvents, depending on the video driver + * in use */ + + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + return(0); + +#ifdef WM_MOUSELEAVE + case WM_MOUSELEAVE: { + + if ( SDL_VideoSurface ) { + /* mouse has left the window */ + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + return(0); +#endif /* WM_MOUSELEAVE */ + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: { + /* Mouse is handled by DirectInput when fullscreen */ + if ( SDL_VideoSurface && ! DINPUT() ) { + WORD xbuttonval = 0; + Uint8 button, state; + int x, y; + + /* DJM: + We want the SDL window to take focus so that + it acts like a normal windows "component" + (e.g. gains keyboard focus on a mouse click). + */ + SetFocus(SDL_Window); + + /* Figure out which button to use */ + switch (msg) { + case WM_LBUTTONDOWN: + button = SDL_BUTTON_LEFT; + state = SDL_PRESSED; + break; + case WM_LBUTTONUP: + button = SDL_BUTTON_LEFT; + state = SDL_RELEASED; + break; + case WM_MBUTTONDOWN: + button = SDL_BUTTON_MIDDLE; + state = SDL_PRESSED; + break; + case WM_MBUTTONUP: + button = SDL_BUTTON_MIDDLE; + state = SDL_RELEASED; + break; + case WM_RBUTTONDOWN: + button = SDL_BUTTON_RIGHT; + state = SDL_PRESSED; + break; + case WM_RBUTTONUP: + button = SDL_BUTTON_RIGHT; + state = SDL_RELEASED; + break; + case WM_XBUTTONDOWN: + xbuttonval = GET_XBUTTON_WPARAM(wParam); + button = SDL_BUTTON_X1 + xbuttonval - 1; + state = SDL_PRESSED; + break; + case WM_XBUTTONUP: + xbuttonval = GET_XBUTTON_WPARAM(wParam); + button = SDL_BUTTON_X1 + xbuttonval - 1; + state = SDL_RELEASED; + break; + default: + /* Eh? Unknown button? */ + return(0); + } + if ( state == SDL_PRESSED ) { + /* Grab mouse so we get up events */ + if ( ++sysevents_mouse_pressed > 0 ) { + SetCapture(hwnd); + } + } else { + /* Release mouse after all up events */ + if ( --sysevents_mouse_pressed <= 0 ) { + ReleaseCapture(); + sysevents_mouse_pressed = 0; + } + } + if ( mouse_relative ) { + /* RJR: March 28, 2000 + report internal mouse position if in relative mode */ + x = 0; y = 0; + } else { + x = (Sint16)LOWORD(lParam); + y = (Sint16)HIWORD(lParam); +#ifdef _WIN32_WCE + if (SDL_VideoSurface) + GapiTransform(this->hidden->userOrientation, +this->hidden->hiresFix, &x, &y); +#endif + } + posted = SDL_PrivateMouseButton( + state, button, x, y); + + /* + * MSDN says: + * "Unlike the WM_LBUTTONUP, WM_MBUTTONUP, and WM_RBUTTONUP + * messages, an application should return TRUE from [an + * XBUTTON message] if it processes it. Doing so will allow + * software that simulates this message on Microsoft Windows + * systems earlier than Windows 2000 to determine whether + * the window procedure processed the message or called + * DefWindowProc to process it. + */ + if (xbuttonval > 0) + return(TRUE); + } + } + return(0); + + +#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) + case WM_MOUSEWHEEL: + if ( SDL_VideoSurface && ! DINPUT() ) { + int move = (short)HIWORD(wParam); + if ( move ) { + Uint8 button; + if ( move > 0 ) + button = SDL_BUTTON_WHEELUP; + else + button = SDL_BUTTON_WHEELDOWN; + posted = SDL_PrivateMouseButton( + SDL_PRESSED, button, 0, 0); + posted |= SDL_PrivateMouseButton( + SDL_RELEASED, button, 0, 0); + } + } + return(0); +#endif + +#ifdef WM_GETMINMAXINFO + /* This message is sent as a way for us to "check" the values + * of a position change. If we don't like it, we can adjust + * the values before they are changed. + */ + case WM_GETMINMAXINFO: { + MINMAXINFO *info; + RECT size; + int x, y; + int style; + int width; + int height; + + /* We don't want to clobber an internal resize */ + if ( SDL_resizing ) + return(0); + + /* We allow resizing with the SDL_RESIZABLE flag */ + if ( SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + return(0); + } + + /* Get the current position of our window */ + GetWindowRect(SDL_Window, &size); + x = size.left; + y = size.top; + + /* Calculate current width and height of our window */ + size.top = 0; + size.left = 0; + if ( SDL_PublicSurface != NULL ) { + size.bottom = SDL_PublicSurface->h; + size.right = SDL_PublicSurface->w; + } else { + size.bottom = 0; + size.right = 0; + } + + /* DJM - according to the docs for GetMenu(), the + return value is undefined if hwnd is a child window. + Aparently it's too difficult for MS to check + inside their function, so I have to do it here. + */ + style = GetWindowLong(hwnd, GWL_STYLE); + AdjustWindowRect( + &size, + style, + style & WS_CHILDWINDOW ? FALSE + : GetMenu(hwnd) != NULL); + + width = size.right - size.left; + height = size.bottom - size.top; + + /* Fix our size to the current size */ + info = (MINMAXINFO *)lParam; + info->ptMaxSize.x = width; + info->ptMaxSize.y = height; + info->ptMaxPosition.x = x; + info->ptMaxPosition.y = y; + info->ptMinTrackSize.x = width; + info->ptMinTrackSize.y = height; + info->ptMaxTrackSize.x = width; + info->ptMaxTrackSize.y = height; + } + return(0); +#endif /* WM_GETMINMAXINFO */ + + case WM_WINDOWPOSCHANGING: { + WINDOWPOS *windowpos = (WINDOWPOS*)lParam; + + /* When menu is at the side or top, Windows likes + to try to reposition the fullscreen window when + changing video modes. + */ + if ( !SDL_resizing && + SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { + windowpos->x = 0; + windowpos->y = 0; + } + } + return(0); + + case WM_WINDOWPOSCHANGED: { + SDL_VideoDevice *this = current_video; + POINT pt; + int w, h; + + GetClientRect(SDL_Window, &SDL_bounds); + + /* avoiding type-punning here... */ + pt.x = SDL_bounds.left; + pt.y = SDL_bounds.top; + ClientToScreen(SDL_Window, &pt); + SDL_bounds.left = pt.x; + SDL_bounds.top = pt.y; + + pt.x = SDL_bounds.right; + pt.y = SDL_bounds.bottom; + ClientToScreen(SDL_Window, &pt); + SDL_bounds.right = pt.x; + SDL_bounds.bottom = pt.y; + + if ( !SDL_resizing && !IsZoomed(SDL_Window) && + SDL_PublicSurface && + !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + w = SDL_bounds.right-SDL_bounds.left; + h = SDL_bounds.bottom-SDL_bounds.top; + if ( this->input_grab != SDL_GRAB_OFF ) { + ClipCursor(&SDL_bounds); + } + if ( SDL_PublicSurface && + (SDL_PublicSurface->flags & SDL_RESIZABLE) ) { + SDL_PrivateResize(w, h); + } + } + break; + + /* We need to set the cursor */ + case WM_SETCURSOR: { + Uint16 hittest; + + hittest = LOWORD(lParam); + if ( hittest == HTCLIENT ) { + SetCursor(SDL_hcursor); + return(TRUE); + } + } + break; + + /* We are about to get palette focus! */ + case WM_QUERYNEWPALETTE: { + WIN_RealizePalette(current_video); + return(TRUE); + } + break; + + /* Another application changed the palette */ + case WM_PALETTECHANGED: { + WIN_PaletteChanged(current_video, (HWND)wParam); + } + break; + + /* We were occluded, refresh our display */ + case WM_PAINT: { + HDC hdc; + PAINTSTRUCT ps; + + hdc = BeginPaint(SDL_Window, &ps); + if ( current_video->screen && + !(current_video->screen->flags & SDL_OPENGL) ) { + WIN_WinPAINT(current_video, hdc); + } + EndPaint(SDL_Window, &ps); + } + return(0); + + /* DJM: Send an expose event in this case */ + case WM_ERASEBKGND: { + posted = SDL_PrivateExpose(); + } + return(0); + + case WM_CLOSE: { + if ( (posted = SDL_PrivateQuit()) ) + PostQuitMessage(0); + } + return(0); + + case WM_DESTROY: { + PostQuitMessage(0); + } + return(0); + +#ifndef NO_GETKEYBOARDSTATE + case WM_INPUTLANGCHANGE: +#ifndef _WIN64 + codepage = GetCodePage(); +#endif + return(TRUE); +#endif + + default: { + /* Special handling by the video driver */ + if (HandleMessage) { + return(HandleMessage(current_video, + hwnd, msg, wParam, lParam)); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +/* Allow the application handle to be stored and retrieved later */ +static void *SDL_handle = NULL; + +void SDL_SetModuleHandle(void *handle) +{ + SDL_handle = handle; +} +void *SDL_GetModuleHandle(void) +{ + void *handle; + + if ( SDL_handle ) { + handle = SDL_handle; + } else { + handle = GetModuleHandle(NULL); + } + return(handle); +} + +/* This allows the SDL_WINDOWID hack */ +BOOL SDL_windowid = FALSE; + +static int app_registered = 0; + +/* Register the class for this application -- exported for winmain.c */ +int SDL_RegisterApp(char *name, Uint32 style, void *hInst) +{ + WNDCLASS class; +#ifdef WM_MOUSELEAVE + HMODULE handle; +#endif + + /* Only do this once... */ + if ( app_registered ) { + ++app_registered; + return(0); + } + +#ifndef CS_BYTEALIGNCLIENT +#define CS_BYTEALIGNCLIENT 0 +#endif + if ( ! name && ! SDL_Appname ) { + name = "SDL_app"; + SDL_Appstyle = CS_BYTEALIGNCLIENT; + SDL_Instance = hInst ? hInst : SDL_GetModuleHandle(); + } + + if ( name ) { +#ifdef _WIN32_WCE + /* WinCE uses the UNICODE version */ + SDL_Appname = SDL_iconv_utf8_ucs2(name); +#else + SDL_Appname = SDL_iconv_utf8_locale(name); +#endif /* _WIN32_WCE */ + SDL_Appstyle = style; + SDL_Instance = hInst ? hInst : SDL_GetModuleHandle(); + } + + /* Register the application class */ + class.hCursor = NULL; + class.hIcon = LoadImage(SDL_Instance, SDL_Appname, + IMAGE_ICON, + 0, 0, LR_DEFAULTCOLOR); + class.lpszMenuName = NULL; + class.lpszClassName = SDL_Appname; + class.hbrBackground = NULL; + class.hInstance = SDL_Instance; + class.style = SDL_Appstyle; +#if SDL_VIDEO_OPENGL + class.style |= CS_OWNDC; +#endif + class.lpfnWndProc = WinMessage; + class.cbWndExtra = 0; + class.cbClsExtra = 0; + if ( ! RegisterClass(&class) ) { + SDL_SetError("Couldn't register application class"); + return(-1); + } + +#ifdef WM_MOUSELEAVE + /* Get the version of TrackMouseEvent() we use */ + _TrackMouseEvent = NULL; + handle = GetModuleHandle("USER32.DLL"); + if ( handle ) { + _TrackMouseEvent = (BOOL (WINAPI *)(TRACKMOUSEEVENT *))GetProcAddress(handle, "TrackMouseEvent"); + } + if ( _TrackMouseEvent == NULL ) { + _TrackMouseEvent = WIN_TrackMouseEvent; + } +#endif /* WM_MOUSELEAVE */ + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 + /* Initialise variables for SDL_ToUnicode() */ + codepage = GetCodePage(); + + /* Cygwin headers don't match windows.h, so we have to cast around a + const issue here... */ + SDL_ToUnicode = Is9xME() ? ToUnicode9xME : (ToUnicodeFN) ToUnicode; +#endif +#endif /* NO_GETKEYBOARDSTATE */ + + app_registered = 1; + return(0); +} + +/* Unregisters the windowclass registered in SDL_RegisterApp above. */ +void SDL_UnregisterApp() +{ + WNDCLASS class; + + /* SDL_RegisterApp might not have been called before */ + if ( !app_registered ) { + return; + } + --app_registered; + if ( app_registered == 0 ) { + /* Check for any registered window classes. */ + if ( GetClassInfo(SDL_Instance, SDL_Appname, &class) ) { + UnregisterClass(SDL_Appname, SDL_Instance); + } + SDL_free(SDL_Appname); + SDL_Appname = NULL; + } +} + +#ifndef NO_GETKEYBOARDSTATE +#ifndef _WIN64 +/* JFP: Implementation of ToUnicode() that works on 9x/ME/2K/XP */ + +static int Is9xME() +{ + OSVERSIONINFO info; + + SDL_memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + if (!GetVersionEx(&info)) { + return 0; + } + return (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); +} + +static int GetCodePage() +{ + char buff[8]; + int lcid = MAKELCID(LOWORD(GetKeyboardLayout(0)), SORT_DEFAULT); + int cp = GetACP(); + + if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buff, sizeof(buff))) { + cp = SDL_atoi(buff); + } + return cp; +} + +static int WINAPI ToUnicode9xME(UINT vkey, UINT scancode, const BYTE *keystate, LPWSTR wchars, int wsize, UINT flags) +{ + BYTE chars[2]; + + /* arg #3 should be const BYTE *, but cygwin lists it as PBYTE. */ + if (ToAsciiEx(vkey, scancode, (PBYTE) keystate, (WORD*)chars, 0, GetKeyboardLayout(0)) == 1) { + return MultiByteToWideChar(codepage, 0, (LPCSTR) chars, 1, wchars, wsize); + } + return 0; +} +#endif +#endif /* !NO_GETKEYBOARDSTATE */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c new file mode 100644 index 0000000..12d17e0 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse.c @@ -0,0 +1,259 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_sysmouse_c.h" +#include "SDL_lowvideo.h" + +#ifdef _WIN32_WCE +#define USE_STATIC_CURSOR +#endif + +HCURSOR SDL_hcursor = NULL; /* Exported for SDL_eventloop.c */ + +/* The implementation dependent data for the window manager cursor */ +/* For some reason when creating a windows cursor, the ands and xors memory + is not copied, so we need to keep track of it and free it when we are done + with the cursor. If we free the memory prematurely, the app crashes. :-} +*/ +struct WMcursor { + HCURSOR curs; +#ifndef USE_STATIC_CURSOR + Uint8 *ands; + Uint8 *xors; +#endif +}; + +/* Convert bits to padded bytes */ +#define PAD_BITS(bits) ((bits+7)/8) + +#ifdef CURSOR_DEBUG +static void PrintBITMAP(FILE *out, char *bits, int w, int h) +{ + int i; + unsigned char ch; + + while ( h-- > 0 ) { + for ( i=0; i<w; ++i ) { + if ( (i%8) == 0 ) + ch = *bits++; + if ( ch&0x80 ) + fprintf(out, "X"); + else + fprintf(out, " "); + ch <<= 1; + } + fprintf(out, "\n"); + } +} +#endif + +#ifndef USE_STATIC_CURSOR +/* Local functions to convert the SDL cursor mask into Windows format */ +static void memnot(Uint8 *dst, Uint8 *src, int len) +{ + while ( len-- > 0 ) + *dst++ = ~*src++; +} +static void memxor(Uint8 *dst, Uint8 *src1, Uint8 *src2, int len) +{ + while ( len-- > 0 ) + *dst++ = (*src1++)^(*src2++); +} +#endif /* !USE_STATIC_CURSOR */ + +void WIN_FreeWMCursor(_THIS, WMcursor *cursor) +{ +#ifndef USE_STATIC_CURSOR + if ( cursor->curs == GetCursor() ) + SetCursor(NULL); + if ( cursor->curs != NULL ) + DestroyCursor(cursor->curs); + if ( cursor->ands != NULL ) + SDL_free(cursor->ands); + if ( cursor->xors != NULL ) + SDL_free(cursor->xors); +#endif /* !USE_STATIC_CURSOR */ + SDL_free(cursor); +} + +WMcursor *WIN_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ +#ifdef USE_STATIC_CURSOR + WMcursor *cursor; + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor ) { + cursor->curs = LoadCursor(NULL, IDC_ARROW); + } + return(cursor); +#else + WMcursor *cursor; + int allowed_x; + int allowed_y; + int run, pad, i; + Uint8 *aptr, *xptr; + + /* Check to make sure the cursor size is okay */ + allowed_x = GetSystemMetrics(SM_CXCURSOR); + allowed_y = GetSystemMetrics(SM_CYCURSOR); + if ( (w > allowed_x) || (h > allowed_y) ) { + SDL_SetError("Only cursors of dimension (%dx%d) are allowed", + allowed_x, allowed_y); + return(NULL); + } + + /* Allocate the cursor */ + cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); + if ( cursor == NULL ) { + SDL_SetError("Out of memory"); + return(NULL); + } + cursor->curs = NULL; + cursor->ands = NULL; + cursor->xors = NULL; + + /* Pad out to the normal cursor size */ + run = PAD_BITS(w); + pad = PAD_BITS(allowed_x)-run; + aptr = cursor->ands = (Uint8 *)SDL_malloc((run+pad)*allowed_y); + xptr = cursor->xors = (Uint8 *)SDL_malloc((run+pad)*allowed_y); + if ( (aptr == NULL) || (xptr == NULL) ) { + WIN_FreeWMCursor(NULL, cursor); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<h; ++i ) { + memxor(xptr, data, mask, run); + xptr += run; + data += run; + memnot(aptr, mask, run); + mask += run; + aptr += run; + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + pad += run; + for ( ; i<allowed_y; ++i ) { + SDL_memset(xptr, 0, pad); + xptr += pad; + SDL_memset(aptr, ~0, pad); + aptr += pad; + } + + /* Create the cursor */ + cursor->curs = CreateCursor( + (HINSTANCE)GetWindowLongPtr(SDL_Window, GWLP_HINSTANCE), + hot_x, hot_y, allowed_x, allowed_y, + cursor->ands, cursor->xors); + if ( cursor->curs == NULL ) { + WIN_FreeWMCursor(NULL, cursor); + SDL_SetError("Windows couldn't create the requested cursor"); + return(NULL); + } + return(cursor); +#endif /* USE_STATIC_CURSOR */ +} + +int WIN_ShowWMCursor(_THIS, WMcursor *cursor) +{ + POINT mouse_pos; + + if ( !this->screen ) { + return(0); + } + + /* Set the window cursor to our cursor, if applicable */ + if ( cursor != NULL ) { + SDL_hcursor = cursor->curs; + } else { + SDL_hcursor = NULL; + } + GetCursorPos(&mouse_pos); + if ( PtInRect(&SDL_bounds, mouse_pos) ) { + SetCursor(SDL_hcursor); + } + return(1); +} + +void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + if ( mouse_relative) { + /* RJR: March 28, 2000 + leave physical cursor at center of screen if + mouse hidden and grabbed */ + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + POINT pt; + + /* With DirectInput the position doesn't follow + * the cursor, so it is set manually */ + if ( DINPUT() ) { + SDL_PrivateMouseMotion(0, 0, x, y); + } + + pt.x = x; + pt.y = y; + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x, pt.y); + } +} + +/* Update the current mouse state and position */ +void WIN_UpdateMouse(_THIS) +{ + POINT pt; + + /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event + * handler a chance to install a TRACKMOUSEEVENT */ + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + + GetCursorPos(&pt); + ScreenToClient(SDL_Window, &pt); + SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void WIN_CheckMouseMode(_THIS) +{ +#ifndef _WIN32_WCE + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) ) { + mouse_relative = 1; + } else { + mouse_relative = 0; + } +#else + mouse_relative = 0; +#endif +} diff --git a/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h new file mode 100644 index 0000000..5d5fe8d --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_sysmouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Functions to be exported */ +extern void WIN_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *WIN_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int WIN_ShowWMCursor(_THIS, WMcursor *cursor); +extern void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void WIN_UpdateMouse(_THIS); +extern void WIN_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/wincommon/SDL_syswm.c b/3rdparty/SDL/src/video/wincommon/SDL_syswm.c new file mode 100644 index 0000000..504d95d --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_syswm.c @@ -0,0 +1,297 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_version.h" +#include "SDL_video.h" +#include "SDL_loadso.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_syswm_c.h" +#include "SDL_wingl_c.h" + + +#ifdef _WIN32_WCE +#define DISABLE_ICON_SUPPORT +#endif + +/* The screen icon -- needs to be freed on SDL_VideoQuit() */ +HICON screen_icn = NULL; + +/* Win32 icon mask semantics are different from those of SDL: + SDL applies the mask to the icon and copies result to desktop. + Win32 applies the mask to the desktop and XORs the icon on. + This means that the SDL mask needs to be applied to the icon and + then inverted and passed to Win32. +*/ +void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ +#ifdef DISABLE_ICON_SUPPORT + return; +#else + SDL_Palette *pal_256; + SDL_Surface *icon_256; + Uint8 *pdata, *pwin32; + Uint8 *mdata, *mwin32, m = 0; + int icon_len; + int icon_plen; + int icon_mlen; + int icon_pitch; + int mask_pitch; + SDL_Rect bounds; + int i, skip; + int row, col; + struct /* quasi-BMP format */ Win32Icon { + Uint32 biSize; + Sint32 biWidth; + Sint32 biHeight; + Uint16 biPlanes; + Uint16 biBitCount; + Uint32 biCompression; + Uint32 biSizeImage; + Sint32 biXPelsPerMeter; + Sint32 biYPelsPerMeter; + Uint32 biClrUsed; + Uint32 biClrImportant; + struct /* RGBQUAD -- note it's BGR ordered */ { + Uint8 rgbBlue; + Uint8 rgbGreen; + Uint8 rgbRed; + Uint8 rgbReserved; + } biColors[256]; + /* Pixels: + Uint8 pixels[] + */ + /* Mask: + Uint8 mask[] + */ + } *icon_win32; + + /* Allocate the win32 bmp icon and set everything to zero */ + icon_pitch = ((icon->w+3)&~3); + mask_pitch = ((icon->w+7)/8); + icon_plen = icon->h*icon_pitch; + icon_mlen = icon->h*mask_pitch; + icon_len = sizeof(*icon_win32)+icon_plen+icon_mlen; + icon_win32 = (struct Win32Icon *)SDL_stack_alloc(Uint8, icon_len); + if ( icon_win32 == NULL ) { + return; + } + SDL_memset(icon_win32, 0, icon_len); + + /* Set the basic BMP parameters */ + icon_win32->biSize = sizeof(*icon_win32)-sizeof(icon_win32->biColors); + icon_win32->biWidth = icon->w; + icon_win32->biHeight = icon->h*2; + icon_win32->biPlanes = 1; + icon_win32->biBitCount = 8; + icon_win32->biSizeImage = icon_plen+icon_mlen; + + /* Allocate a standard 256 color icon surface */ + icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + icon_win32->biBitCount, 0, 0, 0, 0); + if ( icon_256 == NULL ) { + SDL_stack_free(icon_win32); + return; + } + pal_256 = icon_256->format->palette; + if (icon->format->palette && + (icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)){ + Uint8 black; + SDL_memcpy(pal_256->colors, icon->format->palette->colors, + pal_256->ncolors*sizeof(SDL_Color)); + /* Make sure that 0 is black! */ + black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00); + pal_256->colors[black] = pal_256->colors[0]; + pal_256->colors[0].r = 0x00; + pal_256->colors[0].g = 0x00; + pal_256->colors[0].b = 0x00; + } else { + SDL_DitherColors(pal_256->colors, + icon_256->format->BitsPerPixel); + } + + /* Now copy color data to the icon BMP */ + for ( i=0; i<(1<<icon_win32->biBitCount); ++i ) { + icon_win32->biColors[i].rgbRed = pal_256->colors[i].r; + icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g; + icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b; + } + + /* Convert icon to a standard surface format. This may not always + be necessary, as Windows supports a variety of BMP formats, but + it greatly simplifies our code. + */ + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0 ) { + SDL_stack_free(icon_win32); + SDL_FreeSurface(icon_256); + return; + } + + /* Copy pixels upside-down to icon BMP, masked with the icon mask */ + if ( SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch) ) { + SDL_stack_free(icon_win32); + SDL_FreeSurface(icon_256); + SDL_SetError("Warning: Unexpected icon_256 characteristics"); + return; + } + pdata = (Uint8 *)icon_256->pixels; + mdata = mask; + pwin32 = (Uint8 *)icon_win32+sizeof(*icon_win32)+icon_plen-icon_pitch; + skip = icon_pitch - icon->w; + for ( row=0; row<icon->h; ++row ) { + for ( col=0; col<icon->w; ++col ) { + if ( (col%8) == 0 ) { + m = *mdata++; + } + if ( (m&0x80) != 0x00 ) { + *pwin32 = *pdata; + } + m <<= 1; + ++pdata; + ++pwin32; + } + pdata += skip; + pwin32 += skip; + pwin32 -= 2*icon_pitch; + } + SDL_FreeSurface(icon_256); + + /* Copy mask inverted and upside-down to icon BMP */ + mdata = mask; + mwin32 = (Uint8 *)icon_win32 + +sizeof(*icon_win32)+icon_plen+icon_mlen-mask_pitch; + for ( row=0; row<icon->h; ++row ) { + for ( col=0; col<mask_pitch; ++col ) { + *mwin32++ = ~*mdata++; + } + mwin32 -= 2*mask_pitch; + } + + /* Finally, create the icon handle and set the window icon */ + screen_icn = CreateIconFromResourceEx((Uint8 *)icon_win32, icon_len, + TRUE, 0x00030000, icon->w, icon->h, LR_DEFAULTCOLOR); + if ( screen_icn == NULL ) { + SDL_SetError("Couldn't create Win32 icon handle"); + } else { + SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR)screen_icn); + } + SDL_stack_free(icon_win32); +#endif /* DISABLE_ICON_SUPPORT */ +} + +typedef BOOL (WINAPI *PtrSetWindowTextW)(HWND hWnd, LPCWSTR lpString); + +void WIN_SetWMCaption(_THIS, const char *title, const char *icon) +{ +#ifdef _WIN32_WCE + /* WinCE uses the UNICODE version */ + LPWSTR lpszW = SDL_iconv_utf8_ucs2((char *)title); + SetWindowText(SDL_Window, lpszW); + SDL_free(lpszW); +#else + Uint16 *lpsz = SDL_iconv_utf8_ucs2(title); + size_t len = WideCharToMultiByte(CP_ACP, 0, lpsz, -1, NULL, 0, NULL, NULL); + char *cvt = SDL_stack_alloc(char, len + 1); + WideCharToMultiByte(CP_ACP, 0, lpsz, -1, cvt, len, NULL, NULL); + SetWindowText(SDL_Window, cvt); + SDL_stack_free(cvt); + SDL_free(lpsz); +#endif +} + +int WIN_IconifyWindow(_THIS) +{ + ShowWindow(SDL_Window, SW_MINIMIZE); + return(1); +} + +SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode) +{ + if ( mode == SDL_GRAB_OFF ) { + ClipCursor(NULL); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* RJR: March 28, 2000 + must be leaving relative mode, move mouse from + center of window to where it belongs ... */ + POINT pt; + int x, y; + SDL_GetMouseState(&x,&y); + pt.x = x; + pt.y = y; + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x,pt.y); + } +#ifdef _WIN32_WCE + AllKeys(0); +#endif + } else { + ClipCursor(&SDL_bounds); + if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) { + /* RJR: March 28, 2000 + must be entering relative mode, get ready by + moving mouse to center of window ... */ + POINT pt; + pt.x = (SDL_VideoSurface->w/2); + pt.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, &pt); + SetCursorPos(pt.x, pt.y); + } +#ifdef _WIN32_WCE + AllKeys(1); +#endif + } + return(mode); +} + +/* If 'info' is the right version, this function fills it and returns 1. + Otherwise, in case of a version mismatch, it returns -1. +*/ +int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if ( info->version.major <= SDL_MAJOR_VERSION ) { + info->window = SDL_Window; + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= + SDL_VERSIONNUM(1, 2, 5) ) { +#if SDL_VIDEO_OPENGL + info->hglrc = GL_hrc; +#else + info->hglrc = NULL; +#endif + } + return(1); + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return(-1); + } +} diff --git a/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h b/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h new file mode 100644 index 0000000..a103b43 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_syswm_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_lowvideo.h" + +/* Data that needs to be freed at SDL_SYS_VideoQuit() */ +extern HICON screen_icn; + +/* Functions to be exported */ +extern void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern void WIN_SetWMCaption(_THIS, const char *title, const char *icon); +extern int WIN_IconifyWindow(_THIS); +extern SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode); +extern int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info); + diff --git a/3rdparty/SDL/src/video/wincommon/SDL_wingl.c b/3rdparty/SDL/src/video/wincommon/SDL_wingl.c new file mode 100644 index 0000000..fc4e984 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_wingl.c @@ -0,0 +1,659 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* WGL implementation of SDL OpenGL support */ + +#if SDL_VIDEO_OPENGL +#include "SDL_opengl.h" +#endif +#include "SDL_lowvideo.h" +#include "SDL_wingl_c.h" + +#if SDL_VIDEO_OPENGL +#define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL" +#endif + +/* If setting the HDC fails, we may need to recreate the window (MSDN) */ +static int WIN_GL_ResetWindow(_THIS) +{ + int status = 0; + +#ifndef _WIN32_WCE /* FIXME WinCE needs the UNICODE version of CreateWindow() */ + /* This doesn't work with DirectX code (see CVS comments) */ + /* If we were passed a window, then we can't create a new one */ + if ( !SDL_windowid && SDL_strcmp(this->name, "windib") == 0 ) { + /* Save the existing window attributes */ + LONG style; + RECT rect = { 0, 0, 0, 0 }; + style = GetWindowLong(SDL_Window, GWL_STYLE); + GetWindowRect(SDL_Window, &rect); + DestroyWindow(SDL_Window); + WIN_FlushMessageQueue(); + + SDL_resizing = 1; + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + style, + rect.left, rect.top, + (rect.right-rect.left)+1, + (rect.bottom-rect.top)+1, + NULL, NULL, SDL_Instance, NULL); + WIN_FlushMessageQueue(); + SDL_resizing = 0; + + if ( SDL_Window ) { + this->SetCaption(this, this->wm_title, this->wm_icon); + } else { + SDL_SetError("Couldn't create window"); + status = -1; + } + } else +#endif /* !_WIN32_WCE */ + { + SDL_SetError("Unable to reset window for OpenGL context"); + status = -1; + } + return(status); +} + +#if SDL_VIDEO_OPENGL + +static int ExtensionSupported(const char *extension, const char *extensions) +{ + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = SDL_strchr(extension, ' '); + if ( where || *extension == '\0' ) + return 0; + + if ( ! extensions ) + return 0; + + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, + * etc. */ + + start = extensions; + + for (;;) + { + where = SDL_strstr(start, extension); + if (!where) break; + + terminator = where + SDL_strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + + return 0; +} + +static int ChoosePixelFormatARB(_THIS, const int *iAttribs, const FLOAT *fAttribs) +{ + HWND hwnd; + HDC hdc; + HGLRC hglrc; + const char * (WINAPI *wglGetExtensionsStringARB)(HDC) = 0; + const char *extensions; + int pformat = 0; + UINT matches = 0; + + hwnd = CreateWindow(SDL_Appname, SDL_Appname, WS_POPUP | WS_DISABLED, + 0, 0, 10, 10, + NULL, NULL, SDL_Instance, NULL); + WIN_FlushMessageQueue(); + + hdc = GetDC(hwnd); + + SetPixelFormat(hdc, ChoosePixelFormat(hdc, &GL_pfd), &GL_pfd); + + hglrc = this->gl_data->wglCreateContext(hdc); + if ( hglrc ) { + this->gl_data->wglMakeCurrent(hdc, hglrc); + } + + wglGetExtensionsStringARB = (const char * (WINAPI *)(HDC)) + this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB"); + + if( wglGetExtensionsStringARB ) { + extensions = wglGetExtensionsStringARB(hdc); + } else { + extensions = NULL; + } + + this->gl_data->WGL_ARB_pixel_format = 0; + if( ExtensionSupported("WGL_ARB_pixel_format", extensions) ) { + BOOL (WINAPI *wglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); + wglChoosePixelFormatARB = + (BOOL (WINAPI *)(HDC, const int *, const FLOAT *, UINT, int *, UINT *)) + this->gl_data->wglGetProcAddress("wglChoosePixelFormatARB"); + if( wglChoosePixelFormatARB && + wglChoosePixelFormatARB(hdc, iAttribs, fAttribs, 1, &pformat, &matches) && pformat ) { + this->gl_data->WGL_ARB_pixel_format = 1; + } + } + + if ( hglrc ) { + this->gl_data->wglMakeCurrent(NULL, NULL); + this->gl_data->wglDeleteContext(hglrc); + } + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + WIN_FlushMessageQueue(); + + return pformat; +} + +#endif /* SDL_VIDEO_OPENGL */ + +int WIN_GL_SetupWindow(_THIS) +{ + int retval; +#if SDL_VIDEO_OPENGL + int i; + int iAttribs[64]; + int *iAttr; + int *iAccelAttr = NULL; + float fAttribs[1] = { 0 }; + const GLubyte *(WINAPI *glGetStringFunc)(GLenum); + const char *wglext; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) { + return(-1); + } + } + + /* Set up the pixel format descriptor with our needed format */ + SDL_memset(&GL_pfd, 0, sizeof(GL_pfd)); + GL_pfd.nSize = sizeof(GL_pfd); + GL_pfd.nVersion = 1; + GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL); + if ( this->gl_config.double_buffer ) { + GL_pfd.dwFlags |= PFD_DOUBLEBUFFER; + } + if ( this->gl_config.stereo ) { + GL_pfd.dwFlags |= PFD_STEREO; + } + GL_pfd.iPixelType = PFD_TYPE_RGBA; + GL_pfd.cColorBits = this->gl_config.buffer_size; + GL_pfd.cRedBits = this->gl_config.red_size; + GL_pfd.cGreenBits = this->gl_config.green_size; + GL_pfd.cBlueBits = this->gl_config.blue_size; + GL_pfd.cAlphaBits = this->gl_config.alpha_size; + GL_pfd.cAccumRedBits = this->gl_config.accum_red_size; + GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size; + GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size; + GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size; + GL_pfd.cAccumBits = + (GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits + + GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits); + GL_pfd.cDepthBits = this->gl_config.depth_size; + GL_pfd.cStencilBits = this->gl_config.stencil_size; + + /* setup WGL_ARB_pixel_format attribs */ + iAttr = &iAttribs[0]; + + *iAttr++ = WGL_DRAW_TO_WINDOW_ARB; + *iAttr++ = GL_TRUE; + *iAttr++ = WGL_RED_BITS_ARB; + *iAttr++ = this->gl_config.red_size; + *iAttr++ = WGL_GREEN_BITS_ARB; + *iAttr++ = this->gl_config.green_size; + *iAttr++ = WGL_BLUE_BITS_ARB; + *iAttr++ = this->gl_config.blue_size; + + /* We always choose either FULL or NO accel on Windows, because of flaky + drivers. If the app didn't specify, we use FULL, because that's + probably what they wanted (and if you didn't care and got FULL, that's + a perfectly valid result in any case. */ + *iAttr++ = WGL_ACCELERATION_ARB; + iAccelAttr = iAttr; + if (this->gl_config.accelerated) { + *iAttr++ = WGL_FULL_ACCELERATION_ARB; + } else { + *iAttr++ = WGL_NO_ACCELERATION_ARB; + } + + if ( this->gl_config.alpha_size ) { + *iAttr++ = WGL_ALPHA_BITS_ARB; + *iAttr++ = this->gl_config.alpha_size; + } + + *iAttr++ = WGL_DOUBLE_BUFFER_ARB; + *iAttr++ = this->gl_config.double_buffer; + + *iAttr++ = WGL_DEPTH_BITS_ARB; + *iAttr++ = this->gl_config.depth_size; + + if ( this->gl_config.stencil_size ) { + *iAttr++ = WGL_STENCIL_BITS_ARB; + *iAttr++ = this->gl_config.stencil_size; + } + + if ( this->gl_config.accum_red_size ) { + *iAttr++ = WGL_ACCUM_RED_BITS_ARB; + *iAttr++ = this->gl_config.accum_red_size; + } + + if ( this->gl_config.accum_green_size ) { + *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB; + *iAttr++ = this->gl_config.accum_green_size; + } + + if ( this->gl_config.accum_blue_size ) { + *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB; + *iAttr++ = this->gl_config.accum_blue_size; + } + + if ( this->gl_config.accum_alpha_size ) { + *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB; + *iAttr++ = this->gl_config.accum_alpha_size; + } + + if ( this->gl_config.stereo ) { + *iAttr++ = WGL_STEREO_ARB; + *iAttr++ = GL_TRUE; + } + + if ( this->gl_config.multisamplebuffers ) { + *iAttr++ = WGL_SAMPLE_BUFFERS_ARB; + *iAttr++ = this->gl_config.multisamplebuffers; + } + + if ( this->gl_config.multisamplesamples ) { + *iAttr++ = WGL_SAMPLES_ARB; + *iAttr++ = this->gl_config.multisamplesamples; + } + + *iAttr = 0; + + for ( i=0; ; ++i ) { + /* Get the window device context for our OpenGL drawing */ + GL_hdc = GetDC(SDL_Window); + if ( GL_hdc == NULL ) { + SDL_SetError("Unable to get DC for SDL_Window"); + return(-1); + } + + /* Choose and set the closest available pixel format */ + pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs); + /* App said "don't care about accel" and FULL accel failed. Try NO. */ + if ( ( !pixel_format ) && ( this->gl_config.accelerated < 0 ) ) { + *iAccelAttr = WGL_NO_ACCELERATION_ARB; + pixel_format = ChoosePixelFormatARB(this, iAttribs, fAttribs); + *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */ + } + if ( !pixel_format ) { + pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd); + } + if ( !pixel_format ) { + SDL_SetError("No matching GL pixel format available"); + return(-1); + } + if ( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) { + if ( i == 0 ) { + /* First time through, try resetting the window */ + if ( WIN_GL_ResetWindow(this) < 0 ) { + return(-1); + } + continue; + } + SDL_SetError("Unable to set HDC pixel format"); + return(-1); + } + /* We either succeeded or failed by this point */ + break; + } + DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd); + + GL_hrc = this->gl_data->wglCreateContext(GL_hdc); + if ( GL_hrc == NULL ) { + SDL_SetError("Unable to create GL context"); + return(-1); + } + if ( WIN_GL_MakeCurrent(this) < 0 ) { + return(-1); + } + gl_active = 1; + + /* Get the wglGetPixelFormatAttribivARB pointer for the context */ + if ( this->gl_data->WGL_ARB_pixel_format ) { + this->gl_data->wglGetPixelFormatAttribivARB = + (BOOL (WINAPI *)(HDC, int, int, UINT, const int *, int *)) + this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB"); + } else { + this->gl_data->wglGetPixelFormatAttribivARB = NULL; + } + + /* Vsync control under Windows. Checking glGetString here is + * somewhat a documented and reliable hack - it was originally + * as a feature added by mistake, but since so many people rely + * on it, it will not be removed. strstr should be safe here.*/ + glGetStringFunc = WIN_GL_GetProcAddress(this, "glGetString"); + if ( glGetStringFunc ) { + wglext = (const char *)glGetStringFunc(GL_EXTENSIONS); + } else { + /* Uh oh, something is seriously wrong here... */ + wglext = NULL; + } + if ( wglext && SDL_strstr(wglext, "WGL_EXT_swap_control") ) { + this->gl_data->wglSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglSwapIntervalEXT"); + this->gl_data->wglGetSwapIntervalEXT = WIN_GL_GetProcAddress(this, "wglGetSwapIntervalEXT"); + } else { + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; + } + if ( this->gl_config.swap_control >= 0 ) { + if ( this->gl_data->wglSwapIntervalEXT ) { + this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control); + } + } +#else + SDL_SetError("WIN driver not configured with OpenGL"); +#endif + if ( gl_active ) { + retval = 0; + } else { + retval = -1; + } + return(retval); +} + +void WIN_GL_ShutDown(_THIS) +{ +#if SDL_VIDEO_OPENGL + /* Clean up OpenGL */ + if ( GL_hrc ) { + this->gl_data->wglMakeCurrent(NULL, NULL); + this->gl_data->wglDeleteContext(GL_hrc); + GL_hrc = NULL; + } + if ( GL_hdc ) { + ReleaseDC(SDL_Window, GL_hdc); + GL_hdc = NULL; + } + gl_active = 0; + + WIN_GL_UnloadLibrary(this); +#endif /* SDL_VIDEO_OPENGL */ +} + +#if SDL_VIDEO_OPENGL + +/* Make the current context active */ +int WIN_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + return(retval); +} + +/* Get attribute data from wgl. */ +int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + int retval; + + if (attrib == SDL_GL_SWAP_CONTROL) { + if ( this->gl_data->wglGetSwapIntervalEXT ) { + *value = this->gl_data->wglGetSwapIntervalEXT(); + return 0; + } + return -1; + } + + if ( this->gl_data->wglGetPixelFormatAttribivARB ) { + int wgl_attrib; + + switch(attrib) { + case SDL_GL_RED_SIZE: + wgl_attrib = WGL_RED_BITS_ARB; + break; + case SDL_GL_GREEN_SIZE: + wgl_attrib = WGL_GREEN_BITS_ARB; + break; + case SDL_GL_BLUE_SIZE: + wgl_attrib = WGL_BLUE_BITS_ARB; + break; + case SDL_GL_ALPHA_SIZE: + wgl_attrib = WGL_ALPHA_BITS_ARB; + break; + case SDL_GL_DOUBLEBUFFER: + wgl_attrib = WGL_DOUBLE_BUFFER_ARB; + break; + case SDL_GL_BUFFER_SIZE: + wgl_attrib = WGL_COLOR_BITS_ARB; + break; + case SDL_GL_DEPTH_SIZE: + wgl_attrib = WGL_DEPTH_BITS_ARB; + break; + case SDL_GL_STENCIL_SIZE: + wgl_attrib = WGL_STENCIL_BITS_ARB; + break; + case SDL_GL_ACCUM_RED_SIZE: + wgl_attrib = WGL_ACCUM_RED_BITS_ARB; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB; + break; + case SDL_GL_STEREO: + wgl_attrib = WGL_STEREO_ARB; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + wgl_attrib = WGL_SAMPLE_BUFFERS_ARB; + break; + case SDL_GL_MULTISAMPLESAMPLES: + wgl_attrib = WGL_SAMPLES_ARB; + break; + case SDL_GL_ACCELERATED_VISUAL: + wgl_attrib = WGL_ACCELERATION_ARB; + this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value); + if ( *value == WGL_NO_ACCELERATION_ARB ) { + *value = SDL_FALSE; + } else { + *value = SDL_TRUE; + } + return 0; + default: + return(-1); + } + this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value); + + return 0; + } + + retval = 0; + switch ( attrib ) { + case SDL_GL_RED_SIZE: + *value = GL_pfd.cRedBits; + break; + case SDL_GL_GREEN_SIZE: + *value = GL_pfd.cGreenBits; + break; + case SDL_GL_BLUE_SIZE: + *value = GL_pfd.cBlueBits; + break; + case SDL_GL_ALPHA_SIZE: + *value = GL_pfd.cAlphaBits; + break; + case SDL_GL_DOUBLEBUFFER: + if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) { + *value = 1; + } else { + *value = 0; + } + break; + case SDL_GL_BUFFER_SIZE: + *value = GL_pfd.cColorBits; + break; + case SDL_GL_DEPTH_SIZE: + *value = GL_pfd.cDepthBits; + break; + case SDL_GL_STENCIL_SIZE: + *value = GL_pfd.cStencilBits; + break; + case SDL_GL_ACCUM_RED_SIZE: + *value = GL_pfd.cAccumRedBits; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + *value = GL_pfd.cAccumGreenBits; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + *value = GL_pfd.cAccumBlueBits; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + *value = GL_pfd.cAccumAlphaBits; + break; + case SDL_GL_STEREO: + if ( GL_pfd.dwFlags & PFD_STEREO ) { + *value = 1; + } else { + *value = 0; + } + break; + case SDL_GL_MULTISAMPLEBUFFERS: + *value = 0; + break; + case SDL_GL_MULTISAMPLESAMPLES: + *value = 1; + break; + case SDL_GL_SWAP_CONTROL: + if ( this->gl_data->wglGetSwapIntervalEXT ) { + *value = this->gl_data->wglGetSwapIntervalEXT(); + return 0; + } else { + return -1; + } + break; + default: + retval = -1; + break; + } + return retval; +} + +void WIN_GL_SwapBuffers(_THIS) +{ + SwapBuffers(GL_hdc); +} + +void WIN_GL_UnloadLibrary(_THIS) +{ + if ( this->gl_config.driver_loaded ) { + FreeLibrary((HMODULE)this->gl_config.dll_handle); + + this->gl_data->wglGetProcAddress = NULL; + this->gl_data->wglCreateContext = NULL; + this->gl_data->wglDeleteContext = NULL; + this->gl_data->wglMakeCurrent = NULL; + this->gl_data->wglGetPixelFormatAttribivARB = NULL; + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; + + this->gl_config.dll_handle = NULL; + this->gl_config.driver_loaded = 0; + } +} + +/* Passing a NULL path means load pointers from the application */ +int WIN_GL_LoadLibrary(_THIS, const char* path) +{ + HMODULE handle; + + if ( gl_active ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if ( path == NULL ) { + path = DEFAULT_GL_DRIVER_PATH; + } + handle = LoadLibrary(path); + if ( handle == NULL ) { + SDL_SetError("Could not load OpenGL library"); + return -1; + } + + /* Unload the old driver and reset the pointers */ + WIN_GL_UnloadLibrary(this); + + /* Load new function pointers */ + SDL_memset(this->gl_data, 0, sizeof(*this->gl_data)); + this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *)) + GetProcAddress(handle, "wglGetProcAddress"); + this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC)) + GetProcAddress(handle, "wglCreateContext"); + this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC)) + GetProcAddress(handle, "wglDeleteContext"); + this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC)) + GetProcAddress(handle, "wglMakeCurrent"); + this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int)) + GetProcAddress(handle, "wglSwapIntervalEXT"); + this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void)) + GetProcAddress(handle, "wglGetSwapIntervalEXT"); + + if ( (this->gl_data->wglGetProcAddress == NULL) || + (this->gl_data->wglCreateContext == NULL) || + (this->gl_data->wglDeleteContext == NULL) || + (this->gl_data->wglMakeCurrent == NULL) ) { + SDL_SetError("Could not retrieve OpenGL functions"); + FreeLibrary(handle); + return -1; + } + + this->gl_config.dll_handle = handle; + SDL_strlcpy(this->gl_config.driver_path, path, SDL_arraysize(this->gl_config.driver_path)); + this->gl_config.driver_loaded = 1; + return 0; +} + +void *WIN_GL_GetProcAddress(_THIS, const char* proc) +{ + void *func; + + /* This is to pick up extensions */ + func = this->gl_data->wglGetProcAddress(proc); + if ( ! func ) { + /* This is probably a normal GL function */ + func = GetProcAddress(this->gl_config.dll_handle, proc); + } + return func; +} + +#endif /* SDL_VIDEO_OPENGL */ diff --git a/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h b/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h new file mode 100644 index 0000000..c3f2291 --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/SDL_wingl_c.h @@ -0,0 +1,135 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* WGL implementation of SDL OpenGL support */ + +#include "../SDL_sysvideo.h" + + +struct SDL_PrivateGLData { + int gl_active; /* to stop switching drivers while we have a valid context */ + +#if SDL_VIDEO_OPENGL + PIXELFORMATDESCRIPTOR GL_pfd; + HDC GL_hdc; + HGLRC GL_hrc; + int pixel_format; + int WGL_ARB_pixel_format; + + void * (WINAPI *wglGetProcAddress)(const char *proc); + + HGLRC (WINAPI *wglCreateContext)(HDC hdc); + + BOOL (WINAPI *wglDeleteContext)(HGLRC hglrc); + + BOOL (WINAPI *wglMakeCurrent)(HDC hdc, HGLRC hglrc); + + BOOL (WINAPI *wglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + int *piValues); + void (WINAPI *wglSwapIntervalEXT)(int interval); + int (WINAPI *wglGetSwapIntervalEXT)(void); +#endif /* SDL_VIDEO_OPENGL */ +}; + +/* Old variable names */ +#define gl_active (this->gl_data->gl_active) +#define GL_pfd (this->gl_data->GL_pfd) +#define GL_hdc (this->gl_data->GL_hdc) +#define GL_hrc (this->gl_data->GL_hrc) +#define pixel_format (this->gl_data->pixel_format) + +/* OpenGL functions */ +extern int WIN_GL_SetupWindow(_THIS); +extern void WIN_GL_ShutDown(_THIS); +#if SDL_VIDEO_OPENGL +extern int WIN_GL_MakeCurrent(_THIS); +extern int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void WIN_GL_SwapBuffers(_THIS); +extern void WIN_GL_UnloadLibrary(_THIS); +extern int WIN_GL_LoadLibrary(_THIS, const char* path); +extern void *WIN_GL_GetProcAddress(_THIS, const char* proc); +#endif + +#if SDL_VIDEO_OPENGL + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +#endif diff --git a/3rdparty/SDL/src/video/wincommon/wmmsg.h b/3rdparty/SDL/src/video/wincommon/wmmsg.h new file mode 100644 index 0000000..175a8ce --- /dev/null +++ b/3rdparty/SDL/src/video/wincommon/wmmsg.h @@ -0,0 +1,1030 @@ + +#define MAX_WMMSG (sizeof(wmtab)/sizeof(wmtab[0])) + +char *wmtab[] = { + "WM_NULL", + "WM_CREATE", + "WM_DESTROY", + "WM_MOVE", + "UNKNOWN (4)", + "WM_SIZE", + "WM_ACTIVATE", + "WM_SETFOCUS", + "WM_KILLFOCUS", + "UNKNOWN (9)", + "WM_ENABLE", + "WM_SETREDRAW", + "WM_SETTEXT", + "WM_GETTEXT", + "WM_GETTEXTLENGTH", + "WM_PAINT", + "WM_CLOSE", + "WM_QUERYENDSESSION", + "WM_QUIT", + "WM_QUERYOPEN", + "WM_ERASEBKGND", + "WM_SYSCOLORCHANGE", + "WM_ENDSESSION", + "UNKNOWN (23)", + "WM_SHOWWINDOW", + "UNKNOWN (25)", + "WM_SETTINGCHANGE", + "WM_DEVMODECHANGE", + "WM_ACTIVATEAPP", + "WM_FONTCHANGE", + "WM_TIMECHANGE", + "WM_CANCELMODE", + "WM_SETCURSOR", + "WM_MOUSEACTIVATE", + "WM_CHILDACTIVATE", + "WM_QUEUESYNC", + "WM_GETMINMAXINFO", + "UNKNOWN (37)", + "WM_PAINTICON", + "WM_ICONERASEBKGND", + "WM_NEXTDLGCTL", + "UNKNOWN (41)", + "WM_SPOOLERSTATUS", + "WM_DRAWITEM", + "WM_MEASUREITEM", + "WM_DELETEITEM", + "WM_VKEYTOITEM", + "WM_CHARTOITEM", + "WM_SETFONT", + "WM_GETFONT", + "WM_SETHOTKEY", + "WM_GETHOTKEY", + "UNKNOWN (52)", + "UNKNOWN (53)", + "UNKNOWN (54)", + "WM_QUERYDRAGICON", + "UNKNOWN (56)", + "WM_COMPAREITEM", + "UNKNOWN (58)", + "UNKNOWN (59)", + "UNKNOWN (60)", + "WM_GETOBJECT", + "UNKNOWN (62)", + "UNKNOWN (63)", + "UNKNOWN (64)", + "WM_COMPACTING", + "UNKNOWN (66)", + "UNKNOWN (67)", + "WM_COMMNOTIFY", + "UNKNOWN (69)", + "WM_WINDOWPOSCHANGING", + "WM_WINDOWPOSCHANGED", + "WM_POWER", + "UNKNOWN (73)", + "WM_COPYDATA", + "WM_CANCELJOURNAL", + "UNKNOWN (76)", + "UNKNOWN (77)", + "WM_NOTIFY", + "UNKNOWN (79)", + "WM_INPUTLANGCHANGEREQUEST", + "WM_INPUTLANGCHANGE", + "WM_TCARD", + "WM_HELP", + "WM_USERCHANGED", + "WM_NOTIFYFORMAT", + "UNKNOWN (86)", + "UNKNOWN (87)", + "UNKNOWN (88)", + "UNKNOWN (89)", + "UNKNOWN (90)", + "UNKNOWN (91)", + "UNKNOWN (92)", + "UNKNOWN (93)", + "UNKNOWN (94)", + "UNKNOWN (95)", + "UNKNOWN (96)", + "UNKNOWN (97)", + "UNKNOWN (98)", + "UNKNOWN (99)", + "UNKNOWN (100)", + "UNKNOWN (101)", + "UNKNOWN (102)", + "UNKNOWN (103)", + "UNKNOWN (104)", + "UNKNOWN (105)", + "UNKNOWN (106)", + "UNKNOWN (107)", + "UNKNOWN (108)", + "UNKNOWN (109)", + "UNKNOWN (110)", + "UNKNOWN (111)", + "UNKNOWN (112)", + "UNKNOWN (113)", + "UNKNOWN (114)", + "UNKNOWN (115)", + "UNKNOWN (116)", + "UNKNOWN (117)", + "UNKNOWN (118)", + "UNKNOWN (119)", + "UNKNOWN (120)", + "UNKNOWN (121)", + "UNKNOWN (122)", + "WM_CONTEXTMENU", + "WM_STYLECHANGING", + "WM_STYLECHANGED", + "WM_DISPLAYCHANGE", + "WM_GETICON", + "WM_SETICON", + "WM_NCCREATE", + "WM_NCDESTROY", + "WM_NCCALCSIZE", + "WM_NCHITTEST", + "WM_NCPAINT", + "WM_NCACTIVATE", + "WM_GETDLGCODE", + "WM_SYNCPAINT", + "UNKNOWN (137)", + "UNKNOWN (138)", + "UNKNOWN (139)", + "UNKNOWN (140)", + "UNKNOWN (141)", + "UNKNOWN (142)", + "UNKNOWN (143)", + "UNKNOWN (144)", + "UNKNOWN (145)", + "UNKNOWN (146)", + "UNKNOWN (147)", + "UNKNOWN (148)", + "UNKNOWN (149)", + "UNKNOWN (150)", + "UNKNOWN (151)", + "UNKNOWN (152)", + "UNKNOWN (153)", + "UNKNOWN (154)", + "UNKNOWN (155)", + "UNKNOWN (156)", + "UNKNOWN (157)", + "UNKNOWN (158)", + "UNKNOWN (159)", + "WM_NCMOUSEMOVE", + "WM_NCLBUTTONDOWN", + "WM_NCLBUTTONUP", + "WM_NCLBUTTONDBLCLK", + "WM_NCRBUTTONDOWN", + "WM_NCRBUTTONUP", + "WM_NCRBUTTONDBLCLK", + "WM_NCMBUTTONDOWN", + "WM_NCMBUTTONUP", + "WM_NCMBUTTONDBLCLK", + "UNKNOWN (170)", + "UNKNOWN (171)", + "UNKNOWN (172)", + "UNKNOWN (173)", + "UNKNOWN (174)", + "UNKNOWN (175)", + "UNKNOWN (176)", + "UNKNOWN (177)", + "UNKNOWN (178)", + "UNKNOWN (179)", + "UNKNOWN (180)", + "UNKNOWN (181)", + "UNKNOWN (182)", + "UNKNOWN (183)", + "UNKNOWN (184)", + "UNKNOWN (185)", + "UNKNOWN (186)", + "UNKNOWN (187)", + "UNKNOWN (188)", + "UNKNOWN (189)", + "UNKNOWN (190)", + "UNKNOWN (191)", + "UNKNOWN (192)", + "UNKNOWN (193)", + "UNKNOWN (194)", + "UNKNOWN (195)", + "UNKNOWN (196)", + "UNKNOWN (197)", + "UNKNOWN (198)", + "UNKNOWN (199)", + "UNKNOWN (200)", + "UNKNOWN (201)", + "UNKNOWN (202)", + "UNKNOWN (203)", + "UNKNOWN (204)", + "UNKNOWN (205)", + "UNKNOWN (206)", + "UNKNOWN (207)", + "UNKNOWN (208)", + "UNKNOWN (209)", + "UNKNOWN (210)", + "UNKNOWN (211)", + "UNKNOWN (212)", + "UNKNOWN (213)", + "UNKNOWN (214)", + "UNKNOWN (215)", + "UNKNOWN (216)", + "UNKNOWN (217)", + "UNKNOWN (218)", + "UNKNOWN (219)", + "UNKNOWN (220)", + "UNKNOWN (221)", + "UNKNOWN (222)", + "UNKNOWN (223)", + "UNKNOWN (224)", + "UNKNOWN (225)", + "UNKNOWN (226)", + "UNKNOWN (227)", + "UNKNOWN (228)", + "UNKNOWN (229)", + "UNKNOWN (230)", + "UNKNOWN (231)", + "UNKNOWN (232)", + "UNKNOWN (233)", + "UNKNOWN (234)", + "UNKNOWN (235)", + "UNKNOWN (236)", + "UNKNOWN (237)", + "UNKNOWN (238)", + "UNKNOWN (239)", + "UNKNOWN (240)", + "UNKNOWN (241)", + "UNKNOWN (242)", + "UNKNOWN (243)", + "UNKNOWN (244)", + "UNKNOWN (245)", + "UNKNOWN (246)", + "UNKNOWN (247)", + "UNKNOWN (248)", + "UNKNOWN (249)", + "UNKNOWN (250)", + "UNKNOWN (251)", + "UNKNOWN (252)", + "UNKNOWN (253)", + "UNKNOWN (254)", + "UNKNOWN (255)", + "WM_KEYDOWN", + "WM_KEYUP", + "WM_CHAR", + "WM_DEADCHAR", + "WM_SYSKEYDOWN", + "WM_SYSKEYUP", + "WM_SYSCHAR", + "WM_SYSDEADCHAR", + "WM_KEYLAST", + "UNKNOWN (265)", + "UNKNOWN (266)", + "UNKNOWN (267)", + "UNKNOWN (268)", + "UNKNOWN (269)", + "UNKNOWN (270)", + "UNKNOWN (271)", + "WM_INITDIALOG", + "WM_COMMAND", + "WM_SYSCOMMAND", + "WM_TIMER", + "WM_HSCROLL", + "WM_VSCROLL", + "WM_INITMENU", + "WM_INITMENUPOPUP", + "UNKNOWN (280)", + "UNKNOWN (281)", + "UNKNOWN (282)", + "UNKNOWN (283)", + "UNKNOWN (284)", + "UNKNOWN (285)", + "UNKNOWN (286)", + "WM_MENUSELECT", + "WM_MENUCHAR", + "WM_ENTERIDLE", + "WM_MENURBUTTONUP", + "WM_MENUDRAG", + "WM_MENUGETOBJECT", + "WM_UNINITMENUPOPUP", + "WM_MENUCOMMAND", + "UNKNOWN (295)", + "UNKNOWN (296)", + "UNKNOWN (297)", + "UNKNOWN (298)", + "UNKNOWN (299)", + "UNKNOWN (300)", + "UNKNOWN (301)", + "UNKNOWN (302)", + "UNKNOWN (303)", + "UNKNOWN (304)", + "UNKNOWN (305)", + "WM_CTLCOLORMSGBOX", + "WM_CTLCOLOREDIT", + "WM_CTLCOLORLISTBOX", + "WM_CTLCOLORBTN", + "WM_CTLCOLORDLG", + "WM_CTLCOLORSCROLLBAR", + "WM_CTLCOLORSTATIC", + "UNKNOWN (313)", + "UNKNOWN (314)", + "UNKNOWN (315)", + "UNKNOWN (316)", + "UNKNOWN (317)", + "UNKNOWN (318)", + "UNKNOWN (319)", + "UNKNOWN (320)", + "UNKNOWN (321)", + "UNKNOWN (322)", + "UNKNOWN (323)", + "UNKNOWN (324)", + "UNKNOWN (325)", + "UNKNOWN (326)", + "UNKNOWN (327)", + "UNKNOWN (328)", + "UNKNOWN (329)", + "UNKNOWN (330)", + "UNKNOWN (331)", + "UNKNOWN (332)", + "UNKNOWN (333)", + "UNKNOWN (334)", + "UNKNOWN (335)", + "UNKNOWN (336)", + "UNKNOWN (337)", + "UNKNOWN (338)", + "UNKNOWN (339)", + "UNKNOWN (340)", + "UNKNOWN (341)", + "UNKNOWN (342)", + "UNKNOWN (343)", + "UNKNOWN (344)", + "UNKNOWN (345)", + "UNKNOWN (346)", + "UNKNOWN (347)", + "UNKNOWN (348)", + "UNKNOWN (349)", + "UNKNOWN (350)", + "UNKNOWN (351)", + "UNKNOWN (352)", + "UNKNOWN (353)", + "UNKNOWN (354)", + "UNKNOWN (355)", + "UNKNOWN (356)", + "UNKNOWN (357)", + "UNKNOWN (358)", + "UNKNOWN (359)", + "UNKNOWN (360)", + "UNKNOWN (361)", + "UNKNOWN (362)", + "UNKNOWN (363)", + "UNKNOWN (364)", + "UNKNOWN (365)", + "UNKNOWN (366)", + "UNKNOWN (367)", + "UNKNOWN (368)", + "UNKNOWN (369)", + "UNKNOWN (370)", + "UNKNOWN (371)", + "UNKNOWN (372)", + "UNKNOWN (373)", + "UNKNOWN (374)", + "UNKNOWN (375)", + "UNKNOWN (376)", + "UNKNOWN (377)", + "UNKNOWN (378)", + "UNKNOWN (379)", + "UNKNOWN (380)", + "UNKNOWN (381)", + "UNKNOWN (382)", + "UNKNOWN (383)", + "UNKNOWN (384)", + "UNKNOWN (385)", + "UNKNOWN (386)", + "UNKNOWN (387)", + "UNKNOWN (388)", + "UNKNOWN (389)", + "UNKNOWN (390)", + "UNKNOWN (391)", + "UNKNOWN (392)", + "UNKNOWN (393)", + "UNKNOWN (394)", + "UNKNOWN (395)", + "UNKNOWN (396)", + "UNKNOWN (397)", + "UNKNOWN (398)", + "UNKNOWN (399)", + "UNKNOWN (400)", + "UNKNOWN (401)", + "UNKNOWN (402)", + "UNKNOWN (403)", + "UNKNOWN (404)", + "UNKNOWN (405)", + "UNKNOWN (406)", + "UNKNOWN (407)", + "UNKNOWN (408)", + "UNKNOWN (409)", + "UNKNOWN (410)", + "UNKNOWN (411)", + "UNKNOWN (412)", + "UNKNOWN (413)", + "UNKNOWN (414)", + "UNKNOWN (415)", + "UNKNOWN (416)", + "UNKNOWN (417)", + "UNKNOWN (418)", + "UNKNOWN (419)", + "UNKNOWN (420)", + "UNKNOWN (421)", + "UNKNOWN (422)", + "UNKNOWN (423)", + "UNKNOWN (424)", + "UNKNOWN (425)", + "UNKNOWN (426)", + "UNKNOWN (427)", + "UNKNOWN (428)", + "UNKNOWN (429)", + "UNKNOWN (430)", + "UNKNOWN (431)", + "UNKNOWN (432)", + "UNKNOWN (433)", + "UNKNOWN (434)", + "UNKNOWN (435)", + "UNKNOWN (436)", + "UNKNOWN (437)", + "UNKNOWN (438)", + "UNKNOWN (439)", + "UNKNOWN (440)", + "UNKNOWN (441)", + "UNKNOWN (442)", + "UNKNOWN (443)", + "UNKNOWN (444)", + "UNKNOWN (445)", + "UNKNOWN (446)", + "UNKNOWN (447)", + "UNKNOWN (448)", + "UNKNOWN (449)", + "UNKNOWN (450)", + "UNKNOWN (451)", + "UNKNOWN (452)", + "UNKNOWN (453)", + "UNKNOWN (454)", + "UNKNOWN (455)", + "UNKNOWN (456)", + "UNKNOWN (457)", + "UNKNOWN (458)", + "UNKNOWN (459)", + "UNKNOWN (460)", + "UNKNOWN (461)", + "UNKNOWN (462)", + "UNKNOWN (463)", + "UNKNOWN (464)", + "UNKNOWN (465)", + "UNKNOWN (466)", + "UNKNOWN (467)", + "UNKNOWN (468)", + "UNKNOWN (469)", + "UNKNOWN (470)", + "UNKNOWN (471)", + "UNKNOWN (472)", + "UNKNOWN (473)", + "UNKNOWN (474)", + "UNKNOWN (475)", + "UNKNOWN (476)", + "UNKNOWN (477)", + "UNKNOWN (478)", + "UNKNOWN (479)", + "UNKNOWN (480)", + "UNKNOWN (481)", + "UNKNOWN (482)", + "UNKNOWN (483)", + "UNKNOWN (484)", + "UNKNOWN (485)", + "UNKNOWN (486)", + "UNKNOWN (487)", + "UNKNOWN (488)", + "UNKNOWN (489)", + "UNKNOWN (490)", + "UNKNOWN (491)", + "UNKNOWN (492)", + "UNKNOWN (493)", + "UNKNOWN (494)", + "UNKNOWN (495)", + "UNKNOWN (496)", + "UNKNOWN (497)", + "UNKNOWN (498)", + "UNKNOWN (499)", + "UNKNOWN (500)", + "UNKNOWN (501)", + "UNKNOWN (502)", + "UNKNOWN (503)", + "UNKNOWN (504)", + "UNKNOWN (505)", + "UNKNOWN (506)", + "UNKNOWN (507)", + "UNKNOWN (508)", + "UNKNOWN (509)", + "UNKNOWN (510)", + "UNKNOWN (511)", + "WM_MOUSEMOVE", + "WM_LBUTTONDOWN", + "WM_LBUTTONUP", + "WM_LBUTTONDBLCLK", + "WM_RBUTTONDOWN", + "WM_RBUTTONUP", + "WM_RBUTTONDBLCLK", + "WM_MBUTTONDOWN", + "WM_MBUTTONUP", + "WM_MOUSELAST", + "WM_MOUSEWHEEL", + "WM_XBUTTONDOWN", + "WM_XBUTTONUP", + "UNKNOWN (525)", + "UNKNOWN (526)", + "UNKNOWN (527)", + "WM_PARENTNOTIFY", + "WM_ENTERMENULOOP", + "WM_EXITMENULOOP", + "WM_NEXTMENU", + "WM_SIZING", + "WM_CAPTURECHANGED", + "WM_MOVING", + "UNKNOWN (535)", + "WM_POWERBROADCAST", + "WM_DEVICECHANGE", + "UNKNOWN (538)", + "UNKNOWN (539)", + "UNKNOWN (540)", + "UNKNOWN (541)", + "UNKNOWN (542)", + "UNKNOWN (543)", + "WM_MDICREATE", + "WM_MDIDESTROY", + "WM_MDIACTIVATE", + "WM_MDIRESTORE", + "WM_MDINEXT", + "WM_MDIMAXIMIZE", + "WM_MDITILE", + "WM_MDICASCADE", + "WM_MDIICONARRANGE", + "WM_MDIGETACTIVE", + "UNKNOWN (554)", + "UNKNOWN (555)", + "UNKNOWN (556)", + "UNKNOWN (557)", + "UNKNOWN (558)", + "UNKNOWN (559)", + "WM_MDISETMENU", + "WM_ENTERSIZEMOVE", + "WM_EXITSIZEMOVE", + "WM_DROPFILES", + "WM_MDIREFRESHMENU", + "UNKNOWN (565)", + "UNKNOWN (566)", + "UNKNOWN (567)", + "UNKNOWN (568)", + "UNKNOWN (569)", + "UNKNOWN (570)", + "UNKNOWN (571)", + "UNKNOWN (572)", + "UNKNOWN (573)", + "UNKNOWN (574)", + "UNKNOWN (575)", + "UNKNOWN (576)", + "UNKNOWN (577)", + "UNKNOWN (578)", + "UNKNOWN (579)", + "UNKNOWN (580)", + "UNKNOWN (581)", + "UNKNOWN (582)", + "UNKNOWN (583)", + "UNKNOWN (584)", + "UNKNOWN (585)", + "UNKNOWN (586)", + "UNKNOWN (587)", + "UNKNOWN (588)", + "UNKNOWN (589)", + "UNKNOWN (590)", + "UNKNOWN (591)", + "UNKNOWN (592)", + "UNKNOWN (593)", + "UNKNOWN (594)", + "UNKNOWN (595)", + "UNKNOWN (596)", + "UNKNOWN (597)", + "UNKNOWN (598)", + "UNKNOWN (599)", + "UNKNOWN (600)", + "UNKNOWN (601)", + "UNKNOWN (602)", + "UNKNOWN (603)", + "UNKNOWN (604)", + "UNKNOWN (605)", + "UNKNOWN (606)", + "UNKNOWN (607)", + "UNKNOWN (608)", + "UNKNOWN (609)", + "UNKNOWN (610)", + "UNKNOWN (611)", + "UNKNOWN (612)", + "UNKNOWN (613)", + "UNKNOWN (614)", + "UNKNOWN (615)", + "UNKNOWN (616)", + "UNKNOWN (617)", + "UNKNOWN (618)", + "UNKNOWN (619)", + "UNKNOWN (620)", + "UNKNOWN (621)", + "UNKNOWN (622)", + "UNKNOWN (623)", + "UNKNOWN (624)", + "UNKNOWN (625)", + "UNKNOWN (626)", + "UNKNOWN (627)", + "UNKNOWN (628)", + "UNKNOWN (629)", + "UNKNOWN (630)", + "UNKNOWN (631)", + "UNKNOWN (632)", + "UNKNOWN (633)", + "UNKNOWN (634)", + "UNKNOWN (635)", + "UNKNOWN (636)", + "UNKNOWN (637)", + "UNKNOWN (638)", + "UNKNOWN (639)", + "UNKNOWN (640)", + "UNKNOWN (641)", + "UNKNOWN (642)", + "UNKNOWN (643)", + "UNKNOWN (644)", + "UNKNOWN (645)", + "UNKNOWN (646)", + "UNKNOWN (647)", + "UNKNOWN (648)", + "UNKNOWN (649)", + "UNKNOWN (650)", + "UNKNOWN (651)", + "UNKNOWN (652)", + "UNKNOWN (653)", + "UNKNOWN (654)", + "UNKNOWN (655)", + "UNKNOWN (656)", + "UNKNOWN (657)", + "UNKNOWN (658)", + "UNKNOWN (659)", + "UNKNOWN (660)", + "UNKNOWN (661)", + "UNKNOWN (662)", + "UNKNOWN (663)", + "UNKNOWN (664)", + "UNKNOWN (665)", + "UNKNOWN (666)", + "UNKNOWN (667)", + "UNKNOWN (668)", + "UNKNOWN (669)", + "UNKNOWN (670)", + "UNKNOWN (671)", + "UNKNOWN (672)", + "WM_MOUSEHOVER", + "UNKNOWN (674)", + "WM_MOUSELEAVE", + "UNKNOWN (676)", + "UNKNOWN (677)", + "UNKNOWN (678)", + "UNKNOWN (679)", + "UNKNOWN (680)", + "UNKNOWN (681)", + "UNKNOWN (682)", + "UNKNOWN (683)", + "UNKNOWN (684)", + "UNKNOWN (685)", + "UNKNOWN (686)", + "UNKNOWN (687)", + "UNKNOWN (688)", + "UNKNOWN (689)", + "UNKNOWN (690)", + "UNKNOWN (691)", + "UNKNOWN (692)", + "UNKNOWN (693)", + "UNKNOWN (694)", + "UNKNOWN (695)", + "UNKNOWN (696)", + "UNKNOWN (697)", + "UNKNOWN (698)", + "UNKNOWN (699)", + "UNKNOWN (700)", + "UNKNOWN (701)", + "UNKNOWN (702)", + "UNKNOWN (703)", + "UNKNOWN (704)", + "UNKNOWN (705)", + "UNKNOWN (706)", + "UNKNOWN (707)", + "UNKNOWN (708)", + "UNKNOWN (709)", + "UNKNOWN (710)", + "UNKNOWN (711)", + "UNKNOWN (712)", + "UNKNOWN (713)", + "UNKNOWN (714)", + "UNKNOWN (715)", + "UNKNOWN (716)", + "UNKNOWN (717)", + "UNKNOWN (718)", + "UNKNOWN (719)", + "UNKNOWN (720)", + "UNKNOWN (721)", + "UNKNOWN (722)", + "UNKNOWN (723)", + "UNKNOWN (724)", + "UNKNOWN (725)", + "UNKNOWN (726)", + "UNKNOWN (727)", + "UNKNOWN (728)", + "UNKNOWN (729)", + "UNKNOWN (730)", + "UNKNOWN (731)", + "UNKNOWN (732)", + "UNKNOWN (733)", + "UNKNOWN (734)", + "UNKNOWN (735)", + "UNKNOWN (736)", + "UNKNOWN (737)", + "UNKNOWN (738)", + "UNKNOWN (739)", + "UNKNOWN (740)", + "UNKNOWN (741)", + "UNKNOWN (742)", + "UNKNOWN (743)", + "UNKNOWN (744)", + "UNKNOWN (745)", + "UNKNOWN (746)", + "UNKNOWN (747)", + "UNKNOWN (748)", + "UNKNOWN (749)", + "UNKNOWN (750)", + "UNKNOWN (751)", + "UNKNOWN (752)", + "UNKNOWN (753)", + "UNKNOWN (754)", + "UNKNOWN (755)", + "UNKNOWN (756)", + "UNKNOWN (757)", + "UNKNOWN (758)", + "UNKNOWN (759)", + "UNKNOWN (760)", + "UNKNOWN (761)", + "UNKNOWN (762)", + "UNKNOWN (763)", + "UNKNOWN (764)", + "UNKNOWN (765)", + "UNKNOWN (766)", + "UNKNOWN (767)", + "WM_CUT", + "WM_COPY", + "WM_PASTE", + "WM_CLEAR", + "WM_UNDO", + "WM_RENDERFORMAT", + "WM_RENDERALLFORMATS", + "WM_DESTROYCLIPBOARD", + "WM_DRAWCLIPBOARD", + "WM_PAINTCLIPBOARD", + "WM_VSCROLLCLIPBOARD", + "WM_SIZECLIPBOARD", + "WM_ASKCBFORMATNAME", + "WM_CHANGECBCHAIN", + "WM_HSCROLLCLIPBOARD", + "WM_QUERYNEWPALETTE", + "WM_PALETTEISCHANGING", + "WM_PALETTECHANGED", + "WM_HOTKEY", + "UNKNOWN (787)", + "UNKNOWN (788)", + "UNKNOWN (789)", + "UNKNOWN (790)", + "WM_PRINT", + "WM_PRINTCLIENT", + "UNKNOWN (793)", + "UNKNOWN (794)", + "UNKNOWN (795)", + "UNKNOWN (796)", + "UNKNOWN (797)", + "UNKNOWN (798)", + "UNKNOWN (799)", + "UNKNOWN (800)", + "UNKNOWN (801)", + "UNKNOWN (802)", + "UNKNOWN (803)", + "UNKNOWN (804)", + "UNKNOWN (805)", + "UNKNOWN (806)", + "UNKNOWN (807)", + "UNKNOWN (808)", + "UNKNOWN (809)", + "UNKNOWN (810)", + "UNKNOWN (811)", + "UNKNOWN (812)", + "UNKNOWN (813)", + "UNKNOWN (814)", + "UNKNOWN (815)", + "UNKNOWN (816)", + "UNKNOWN (817)", + "UNKNOWN (818)", + "UNKNOWN (819)", + "UNKNOWN (820)", + "UNKNOWN (821)", + "UNKNOWN (822)", + "UNKNOWN (823)", + "UNKNOWN (824)", + "UNKNOWN (825)", + "UNKNOWN (826)", + "UNKNOWN (827)", + "UNKNOWN (828)", + "UNKNOWN (829)", + "UNKNOWN (830)", + "UNKNOWN (831)", + "UNKNOWN (832)", + "UNKNOWN (833)", + "UNKNOWN (834)", + "UNKNOWN (835)", + "UNKNOWN (836)", + "UNKNOWN (837)", + "UNKNOWN (838)", + "UNKNOWN (839)", + "UNKNOWN (840)", + "UNKNOWN (841)", + "UNKNOWN (842)", + "UNKNOWN (843)", + "UNKNOWN (844)", + "UNKNOWN (845)", + "UNKNOWN (846)", + "UNKNOWN (847)", + "UNKNOWN (848)", + "UNKNOWN (849)", + "UNKNOWN (850)", + "UNKNOWN (851)", + "UNKNOWN (852)", + "UNKNOWN (853)", + "UNKNOWN (854)", + "UNKNOWN (855)", + "WM_HANDHELDFIRST", + "UNKNOWN (857)", + "UNKNOWN (858)", + "UNKNOWN (859)", + "UNKNOWN (860)", + "UNKNOWN (861)", + "UNKNOWN (862)", + "WM_HANDHELDLAST", + "WM_AFXFIRST", + "UNKNOWN (865)", + "UNKNOWN (866)", + "UNKNOWN (867)", + "UNKNOWN (868)", + "UNKNOWN (869)", + "UNKNOWN (870)", + "UNKNOWN (871)", + "UNKNOWN (872)", + "UNKNOWN (873)", + "UNKNOWN (874)", + "UNKNOWN (875)", + "UNKNOWN (876)", + "UNKNOWN (877)", + "UNKNOWN (878)", + "UNKNOWN (879)", + "UNKNOWN (880)", + "UNKNOWN (881)", + "UNKNOWN (882)", + "UNKNOWN (883)", + "UNKNOWN (884)", + "UNKNOWN (885)", + "UNKNOWN (886)", + "UNKNOWN (887)", + "UNKNOWN (888)", + "UNKNOWN (889)", + "UNKNOWN (890)", + "UNKNOWN (891)", + "UNKNOWN (892)", + "UNKNOWN (893)", + "UNKNOWN (894)", + "WM_AFXLAST", + "WM_PENWINFIRST", + "UNKNOWN (897)", + "UNKNOWN (898)", + "UNKNOWN (899)", + "UNKNOWN (900)", + "UNKNOWN (901)", + "UNKNOWN (902)", + "UNKNOWN (903)", + "UNKNOWN (904)", + "UNKNOWN (905)", + "UNKNOWN (906)", + "UNKNOWN (907)", + "UNKNOWN (908)", + "UNKNOWN (909)", + "UNKNOWN (910)", + "WM_PENWINLAST", + "UNKNOWN (912)", + "UNKNOWN (913)", + "UNKNOWN (914)", + "UNKNOWN (915)", + "UNKNOWN (916)", + "UNKNOWN (917)", + "UNKNOWN (918)", + "UNKNOWN (919)", + "UNKNOWN (920)", + "UNKNOWN (921)", + "UNKNOWN (922)", + "UNKNOWN (923)", + "UNKNOWN (924)", + "UNKNOWN (925)", + "UNKNOWN (926)", + "UNKNOWN (927)", + "UNKNOWN (928)", + "UNKNOWN (929)", + "UNKNOWN (930)", + "UNKNOWN (931)", + "UNKNOWN (932)", + "UNKNOWN (933)", + "UNKNOWN (934)", + "UNKNOWN (935)", + "UNKNOWN (936)", + "UNKNOWN (937)", + "UNKNOWN (938)", + "UNKNOWN (939)", + "UNKNOWN (940)", + "UNKNOWN (941)", + "UNKNOWN (942)", + "UNKNOWN (943)", + "UNKNOWN (944)", + "UNKNOWN (945)", + "UNKNOWN (946)", + "UNKNOWN (947)", + "UNKNOWN (948)", + "UNKNOWN (949)", + "UNKNOWN (950)", + "UNKNOWN (951)", + "UNKNOWN (952)", + "UNKNOWN (953)", + "UNKNOWN (954)", + "UNKNOWN (955)", + "UNKNOWN (956)", + "UNKNOWN (957)", + "UNKNOWN (958)", + "UNKNOWN (959)", + "UNKNOWN (960)", + "UNKNOWN (961)", + "UNKNOWN (962)", + "UNKNOWN (963)", + "UNKNOWN (964)", + "UNKNOWN (965)", + "UNKNOWN (966)", + "UNKNOWN (967)", + "UNKNOWN (968)", + "UNKNOWN (969)", + "UNKNOWN (970)", + "UNKNOWN (971)", + "UNKNOWN (972)", + "UNKNOWN (973)", + "UNKNOWN (974)", + "UNKNOWN (975)", + "UNKNOWN (976)", + "UNKNOWN (977)", + "UNKNOWN (978)", + "UNKNOWN (979)", + "UNKNOWN (980)", + "UNKNOWN (981)", + "UNKNOWN (982)", + "UNKNOWN (983)", + "UNKNOWN (984)", + "UNKNOWN (985)", + "UNKNOWN (986)", + "UNKNOWN (987)", + "UNKNOWN (988)", + "UNKNOWN (989)", + "UNKNOWN (990)", + "UNKNOWN (991)", + "UNKNOWN (992)", + "UNKNOWN (993)", + "UNKNOWN (994)", + "UNKNOWN (995)", + "UNKNOWN (996)", + "UNKNOWN (997)", + "UNKNOWN (998)", + "UNKNOWN (999)", + "UNKNOWN (1000)", + "UNKNOWN (1001)", + "UNKNOWN (1002)", + "UNKNOWN (1003)", + "UNKNOWN (1004)", + "UNKNOWN (1005)", + "UNKNOWN (1006)", + "UNKNOWN (1007)", + "UNKNOWN (1008)", + "UNKNOWN (1009)", + "UNKNOWN (1010)", + "UNKNOWN (1011)", + "UNKNOWN (1012)", + "UNKNOWN (1013)", + "UNKNOWN (1014)", + "UNKNOWN (1015)", + "UNKNOWN (1016)", + "UNKNOWN (1017)", + "UNKNOWN (1018)", + "UNKNOWN (1019)", + "UNKNOWN (1020)", + "UNKNOWN (1021)", + "UNKNOWN (1022)", + "UNKNOWN (1023)", + "WM_USER" +}; diff --git a/3rdparty/SDL/src/video/windib/SDL_dibevents.c b/3rdparty/SDL/src/video/windib/SDL_dibevents.c new file mode 100644 index 0000000..6cee54a --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibevents.c @@ -0,0 +1,704 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "SDL_main.h" +#include "SDL_events.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_gapidibvideo.h" +#include "SDL_vkeys.h" + +#ifdef SDL_VIDEO_DRIVER_GAPI +#include "../gapi/SDL_gapivideo.h" +#endif + +#ifdef SDL_VIDEO_DRIVER_WINDIB +#include "SDL_dibvideo.h" +#endif + +#ifndef WM_APP +#define WM_APP 0x8000 +#endif + +#ifdef _WIN32_WCE +#define NO_GETKEYBOARDSTATE +#endif + +/* The translation table from a Microsoft VK keysym to a SDL keysym */ +static SDLKey VK_keymap[SDLK_LAST]; +static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed); +static SDLKey Arrows_keymap[4]; + +/* Masks for processing the windows KEYDOWN and KEYUP messages */ +#define REPEATED_KEYMASK (1<<30) +#define EXTENDED_KEYMASK (1<<24) + +/* DJM: If the user setup the window for us, we want to save his window proc, + and give him a chance to handle some messages. */ +#ifdef STRICT +#define WNDPROCTYPE WNDPROC +#else +#define WNDPROCTYPE FARPROC +#endif +static WNDPROCTYPE userWindowProc = NULL; + + +#ifdef SDL_VIDEO_DRIVER_GAPI + +WPARAM rotateKey(WPARAM key,int direction) +{ + if(direction ==0 ) return key; + + switch (key) { + case 0x26: /* up */ + return Arrows_keymap[(2 + direction) % 4]; + case 0x27: /* right */ + return Arrows_keymap[(1 + direction) % 4]; + case 0x28: /* down */ + return Arrows_keymap[direction % 4]; + case 0x25: /* left */ + return Arrows_keymap[(3 + direction) % 4]; + } + + return key; +} + +static void GapiTransform(GapiInfo *gapiInfo, LONG *x, LONG *y) +{ + if(gapiInfo->hiresFix) + { + *x *= 2; + *y *= 2; + } + + // 0 3 0 + if((!gapiInfo->userOrientation && gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) || + // 3 0 3 + (gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation) || + // 3 0 0 + (gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation)) + { + Sint16 temp = *x; + *x = SDL_VideoSurface->w - *y; + *y = temp; + } + else + // 0 0 0 + if((!gapiInfo->userOrientation && !gapiInfo->systemOrientation && !gapiInfo->gapiOrientation) || + // 0 0 3 + (!gapiInfo->userOrientation && !gapiInfo->systemOrientation && gapiInfo->gapiOrientation)) + { + // without changes + // *x = *x; + // *y = *y; + } + // default + else + { + // without changes + // *x = *x; + // *y = *y; + } +} +#endif + + +/* The main Win32 event handler */ +LRESULT DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + extern int posted; + + switch (msg) { + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + SDL_keysym keysym; + +#ifdef SDL_VIDEO_DRIVER_GAPI + if(this->hidden->gapiInfo) + { + // Drop GAPI artefacts + if (wParam == 0x84 || wParam == 0x5B) + return 0; + + wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform); + } +#endif + /* Ignore repeated keys */ + if ( lParam&REPEATED_KEYMASK ) { + return(0); + } + switch (wParam) { + case VK_CONTROL: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RCONTROL; + else + wParam = VK_LCONTROL; + break; + case VK_SHIFT: + /* EXTENDED trick doesn't work here */ + { + Uint8 *state = SDL_GetKeyState(NULL); + if (state[SDLK_LSHIFT] == SDL_RELEASED && (GetKeyState(VK_LSHIFT) & 0x8000)) { + wParam = VK_LSHIFT; + } else if (state[SDLK_RSHIFT] == SDL_RELEASED && (GetKeyState(VK_RSHIFT) & 0x8000)) { + wParam = VK_RSHIFT; + } else { + /* Win9x */ + int sc = HIWORD(lParam) & 0xFF; + + if (sc == 0x2A) + wParam = VK_LSHIFT; + else + if (sc == 0x36) + wParam = VK_RSHIFT; + else + wParam = VK_LSHIFT; + } + } + break; + case VK_MENU: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RMENU; + else + wParam = VK_LMENU; + break; + } +#ifdef NO_GETKEYBOARDSTATE + /* this is the workaround for the missing ToAscii() and ToUnicode() in CE (not necessary at KEYUP!) */ + if ( SDL_TranslateUNICODE ) { + MSG m; + + m.hwnd = hwnd; + m.message = msg; + m.wParam = wParam; + m.lParam = lParam; + m.time = 0; + if ( TranslateMessage(&m) && PeekMessage(&m, hwnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) { + GetMessage(&m, hwnd, 0, WM_USER); + wParam = m.wParam; + } + } +#endif /* NO_GETKEYBOARDSTATE */ + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(wParam,HIWORD(lParam),&keysym,1)); + } + return(0); + + case WM_SYSKEYUP: + case WM_KEYUP: { + SDL_keysym keysym; + +#ifdef SDL_VIDEO_DRIVER_GAPI + if(this->hidden->gapiInfo) + { + // Drop GAPI artifacts + if (wParam == 0x84 || wParam == 0x5B) + return 0; + + wParam = rotateKey(wParam, this->hidden->gapiInfo->coordinateTransform); + } +#endif + + switch (wParam) { + case VK_CONTROL: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RCONTROL; + else + wParam = VK_LCONTROL; + break; + case VK_SHIFT: + /* EXTENDED trick doesn't work here */ + { + Uint8 *state = SDL_GetKeyState(NULL); + if (state[SDLK_LSHIFT] == SDL_PRESSED && !(GetKeyState(VK_LSHIFT) & 0x8000)) { + wParam = VK_LSHIFT; + } else if (state[SDLK_RSHIFT] == SDL_PRESSED && !(GetKeyState(VK_RSHIFT) & 0x8000)) { + wParam = VK_RSHIFT; + } else { + /* Win9x */ + int sc = HIWORD(lParam) & 0xFF; + + if (sc == 0x2A) + wParam = VK_LSHIFT; + else + if (sc == 0x36) + wParam = VK_RSHIFT; + else + wParam = VK_LSHIFT; + } + } + break; + case VK_MENU: + if ( lParam&EXTENDED_KEYMASK ) + wParam = VK_RMENU; + else + wParam = VK_LMENU; + break; + } + /* Windows only reports keyup for print screen */ + if ( wParam == VK_SNAPSHOT && SDL_GetKeyState(NULL)[SDLK_PRINT] == SDL_RELEASED ) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(wParam,HIWORD(lParam),&keysym,1)); + } + posted = SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(wParam,HIWORD(lParam),&keysym,0)); + } + return(0); +#if defined(SC_SCREENSAVE) && defined(SC_MONITORPOWER) + case WM_SYSCOMMAND: { + const DWORD val = (DWORD) (wParam & 0xFFF0); + if ((val == SC_SCREENSAVE) || (val == SC_MONITORPOWER)) { + if (this->hidden->dibInfo && !allow_screensaver) { + /* Note that this doesn't stop anything on Vista + if the screensaver has a password. */ + return(0); + } + } + } + /* Fall through to default processing */ +#endif /* SC_SCREENSAVE && SC_MONITORPOWER */ + + default: { + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.hwnd = hwnd; + wmmsg.msg = msg; + wmmsg.wParam = wParam; + wmmsg.lParam = lParam; + posted = SDL_PrivateSysWMEvent(&wmmsg); + + /* DJM: If the user isn't watching for private + messages in her SDL event loop, then pass it + along to any win32 specific window proc. + */ + } else if (userWindowProc) { + return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +#ifdef _WIN32_WCE +static BOOL GetLastStylusPos(POINT* ptLast) +{ + BOOL bResult = FALSE; + UINT nRet; + GetMouseMovePoints(ptLast, 1, &nRet); + if ( nRet == 1 ) { + ptLast->x /= 4; + ptLast->y /= 4; + bResult = TRUE; + } + return bResult; +} +#endif + +static void DIB_GenerateMouseMotionEvent(_THIS) +{ + extern int mouse_relative; + extern int posted; + + POINT mouse; +#ifdef _WIN32_WCE + if ( !GetCursorPos(&mouse) && !GetLastStylusPos(&mouse) ) return; +#else + if ( !GetCursorPos(&mouse) ) return; +#endif + + if ( mouse_relative ) { + POINT center; + center.x = (SDL_VideoSurface->w/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + + mouse.x -= center.x; + mouse.y -= center.y; + if ( mouse.x || mouse.y ) { + SetCursorPos(center.x, center.y); + posted = SDL_PrivateMouseMotion(0, 1, (Sint16)mouse.x, (Sint16)mouse.y); + } + } else { + ScreenToClient(SDL_Window, &mouse); +#ifdef SDL_VIDEO_DRIVER_GAPI + if (SDL_VideoSurface && this->hidden->gapiInfo) + GapiTransform(this->hidden->gapiInfo, &mouse.x, &mouse.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, (Sint16)mouse.x, (Sint16)mouse.y); + } +} + +void DIB_PumpEvents(_THIS) +{ + MSG msg; + + while ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } + } + + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + DIB_GenerateMouseMotionEvent( this ); + } +} + +static HKL hLayoutUS = NULL; + +void DIB_InitOSKeymap(_THIS) +{ + int i; +#ifndef _WIN32_WCE + char current_layout[KL_NAMELENGTH]; + + GetKeyboardLayoutName(current_layout); + //printf("Initial Keyboard Layout Name: '%s'\n", current_layout); + + hLayoutUS = LoadKeyboardLayout("00000409", KLF_NOTELLSHELL); + + if (!hLayoutUS) { + //printf("Failed to load US keyboard layout. Using current.\n"); + hLayoutUS = GetKeyboardLayout(0); + } + LoadKeyboardLayout(current_layout, KLF_ACTIVATE); +#else +#if _WIN32_WCE >=420 + TCHAR current_layout[KL_NAMELENGTH]; + + GetKeyboardLayoutName(current_layout); + //printf("Initial Keyboard Layout Name: '%s'\n", current_layout); + + hLayoutUS = LoadKeyboardLayout(L"00000409", 0); + + if (!hLayoutUS) { + //printf("Failed to load US keyboard layout. Using current.\n"); + hLayoutUS = GetKeyboardLayout(0); + } + LoadKeyboardLayout(current_layout, 0); +#endif // _WIN32_WCE >=420 +#endif + /* Map the VK keysyms */ + for ( i=0; i<SDL_arraysize(VK_keymap); ++i ) + VK_keymap[i] = SDLK_UNKNOWN; + + VK_keymap[VK_BACK] = SDLK_BACKSPACE; + VK_keymap[VK_TAB] = SDLK_TAB; + VK_keymap[VK_CLEAR] = SDLK_CLEAR; + VK_keymap[VK_RETURN] = SDLK_RETURN; + VK_keymap[VK_PAUSE] = SDLK_PAUSE; + VK_keymap[VK_ESCAPE] = SDLK_ESCAPE; + VK_keymap[VK_SPACE] = SDLK_SPACE; + VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE; + VK_keymap[VK_COMMA] = SDLK_COMMA; + VK_keymap[VK_MINUS] = SDLK_MINUS; + VK_keymap[VK_PERIOD] = SDLK_PERIOD; + VK_keymap[VK_SLASH] = SDLK_SLASH; + VK_keymap[VK_0] = SDLK_0; + VK_keymap[VK_1] = SDLK_1; + VK_keymap[VK_2] = SDLK_2; + VK_keymap[VK_3] = SDLK_3; + VK_keymap[VK_4] = SDLK_4; + VK_keymap[VK_5] = SDLK_5; + VK_keymap[VK_6] = SDLK_6; + VK_keymap[VK_7] = SDLK_7; + VK_keymap[VK_8] = SDLK_8; + VK_keymap[VK_9] = SDLK_9; + VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON; + VK_keymap[VK_EQUALS] = SDLK_EQUALS; + VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET; + VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH; + VK_keymap[VK_OEM_102] = SDLK_LESS; + VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET; + VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE; + VK_keymap[VK_BACKTICK] = SDLK_BACKQUOTE; + VK_keymap[VK_A] = SDLK_a; + VK_keymap[VK_B] = SDLK_b; + VK_keymap[VK_C] = SDLK_c; + VK_keymap[VK_D] = SDLK_d; + VK_keymap[VK_E] = SDLK_e; + VK_keymap[VK_F] = SDLK_f; + VK_keymap[VK_G] = SDLK_g; + VK_keymap[VK_H] = SDLK_h; + VK_keymap[VK_I] = SDLK_i; + VK_keymap[VK_J] = SDLK_j; + VK_keymap[VK_K] = SDLK_k; + VK_keymap[VK_L] = SDLK_l; + VK_keymap[VK_M] = SDLK_m; + VK_keymap[VK_N] = SDLK_n; + VK_keymap[VK_O] = SDLK_o; + VK_keymap[VK_P] = SDLK_p; + VK_keymap[VK_Q] = SDLK_q; + VK_keymap[VK_R] = SDLK_r; + VK_keymap[VK_S] = SDLK_s; + VK_keymap[VK_T] = SDLK_t; + VK_keymap[VK_U] = SDLK_u; + VK_keymap[VK_V] = SDLK_v; + VK_keymap[VK_W] = SDLK_w; + VK_keymap[VK_X] = SDLK_x; + VK_keymap[VK_Y] = SDLK_y; + VK_keymap[VK_Z] = SDLK_z; + VK_keymap[VK_DELETE] = SDLK_DELETE; + + VK_keymap[VK_NUMPAD0] = SDLK_KP0; + VK_keymap[VK_NUMPAD1] = SDLK_KP1; + VK_keymap[VK_NUMPAD2] = SDLK_KP2; + VK_keymap[VK_NUMPAD3] = SDLK_KP3; + VK_keymap[VK_NUMPAD4] = SDLK_KP4; + VK_keymap[VK_NUMPAD5] = SDLK_KP5; + VK_keymap[VK_NUMPAD6] = SDLK_KP6; + VK_keymap[VK_NUMPAD7] = SDLK_KP7; + VK_keymap[VK_NUMPAD8] = SDLK_KP8; + VK_keymap[VK_NUMPAD9] = SDLK_KP9; + VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD; + VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE; + VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY; + VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS; + VK_keymap[VK_ADD] = SDLK_KP_PLUS; + + VK_keymap[VK_UP] = SDLK_UP; + VK_keymap[VK_DOWN] = SDLK_DOWN; + VK_keymap[VK_RIGHT] = SDLK_RIGHT; + VK_keymap[VK_LEFT] = SDLK_LEFT; + VK_keymap[VK_INSERT] = SDLK_INSERT; + VK_keymap[VK_HOME] = SDLK_HOME; + VK_keymap[VK_END] = SDLK_END; + VK_keymap[VK_PRIOR] = SDLK_PAGEUP; + VK_keymap[VK_NEXT] = SDLK_PAGEDOWN; + + VK_keymap[VK_F1] = SDLK_F1; + VK_keymap[VK_F2] = SDLK_F2; + VK_keymap[VK_F3] = SDLK_F3; + VK_keymap[VK_F4] = SDLK_F4; + VK_keymap[VK_F5] = SDLK_F5; + VK_keymap[VK_F6] = SDLK_F6; + VK_keymap[VK_F7] = SDLK_F7; + VK_keymap[VK_F8] = SDLK_F8; + VK_keymap[VK_F9] = SDLK_F9; + VK_keymap[VK_F10] = SDLK_F10; + VK_keymap[VK_F11] = SDLK_F11; + VK_keymap[VK_F12] = SDLK_F12; + VK_keymap[VK_F13] = SDLK_F13; + VK_keymap[VK_F14] = SDLK_F14; + VK_keymap[VK_F15] = SDLK_F15; + + VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK; + VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK; + VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK; + VK_keymap[VK_RSHIFT] = SDLK_RSHIFT; + VK_keymap[VK_LSHIFT] = SDLK_LSHIFT; + VK_keymap[VK_RCONTROL] = SDLK_RCTRL; + VK_keymap[VK_LCONTROL] = SDLK_LCTRL; + VK_keymap[VK_RMENU] = SDLK_RALT; + VK_keymap[VK_LMENU] = SDLK_LALT; + VK_keymap[VK_RWIN] = SDLK_RSUPER; + VK_keymap[VK_LWIN] = SDLK_LSUPER; + + VK_keymap[VK_HELP] = SDLK_HELP; +#ifdef VK_PRINT + VK_keymap[VK_PRINT] = SDLK_PRINT; +#endif + VK_keymap[VK_SNAPSHOT] = SDLK_PRINT; + VK_keymap[VK_CANCEL] = SDLK_BREAK; + VK_keymap[VK_APPS] = SDLK_MENU; + + Arrows_keymap[3] = 0x25; + Arrows_keymap[2] = 0x26; + Arrows_keymap[1] = 0x27; + Arrows_keymap[0] = 0x28; +} + +#define EXTKEYPAD(keypad) ((scancode & 0x100)?(mvke):(keypad)) + +static int SDL_MapVirtualKey(int scancode, int vkey) +{ +#ifndef _WIN32_WCE + int mvke = MapVirtualKeyEx(scancode & 0xFF, 1, hLayoutUS); +#else + int mvke = MapVirtualKey(scancode & 0xFF, 1); +#endif + + switch(vkey) { + /* These are always correct */ + case VK_DIVIDE: + case VK_MULTIPLY: + case VK_SUBTRACT: + case VK_ADD: + case VK_LWIN: + case VK_RWIN: + case VK_APPS: + /* These are already handled */ + case VK_LCONTROL: + case VK_RCONTROL: + case VK_LSHIFT: + case VK_RSHIFT: + case VK_LMENU: + case VK_RMENU: + case VK_SNAPSHOT: + case VK_PAUSE: + return vkey; + } + switch(mvke) { + /* Distinguish between keypad and extended keys */ + case VK_INSERT: return EXTKEYPAD(VK_NUMPAD0); + case VK_DELETE: return EXTKEYPAD(VK_DECIMAL); + case VK_END: return EXTKEYPAD(VK_NUMPAD1); + case VK_DOWN: return EXTKEYPAD(VK_NUMPAD2); + case VK_NEXT: return EXTKEYPAD(VK_NUMPAD3); + case VK_LEFT: return EXTKEYPAD(VK_NUMPAD4); + case VK_CLEAR: return EXTKEYPAD(VK_NUMPAD5); + case VK_RIGHT: return EXTKEYPAD(VK_NUMPAD6); + case VK_HOME: return EXTKEYPAD(VK_NUMPAD7); + case VK_UP: return EXTKEYPAD(VK_NUMPAD8); + case VK_PRIOR: return EXTKEYPAD(VK_NUMPAD9); + } + return mvke?mvke:vkey; +} + +static SDL_keysym *TranslateKey(WPARAM vkey, UINT scancode, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char) scancode; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + + if ((vkey == VK_RETURN) && (scancode & 0x100)) { + /* No VK_ code for the keypad enter key */ + keysym->sym = SDLK_KP_ENTER; + } + else { + keysym->sym = VK_keymap[SDL_MapVirtualKey(scancode, vkey)]; + } + + if ( pressed && SDL_TranslateUNICODE ) { +#ifdef NO_GETKEYBOARDSTATE + /* Uh oh, better hope the vkey is close enough.. */ + if((keysym->sym == vkey) || (vkey > 0x7f)) + keysym->unicode = vkey; +#else + BYTE keystate[256]; + Uint16 wchars[2]; + + GetKeyboardState(keystate); + /* Numlock isn't taken into account in ToUnicode, + * so we handle it as a special case here */ + if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) + { + keysym->unicode = vkey - VK_NUMPAD0 + '0'; + } + else if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } +#endif /* NO_GETKEYBOARDSTATE */ + } + +#if 0 + { + HKL hLayoutCurrent = GetKeyboardLayout(0); + int sc = scancode & 0xFF; + + printf("SYM:%d, VK:0x%02X, SC:0x%04X, US:(1:0x%02X, 3:0x%02X), " + "Current:(1:0x%02X, 3:0x%02X)\n", + keysym->sym, vkey, scancode, + MapVirtualKeyEx(sc, 1, hLayoutUS), + MapVirtualKeyEx(sc, 3, hLayoutUS), + MapVirtualKeyEx(sc, 1, hLayoutCurrent), + MapVirtualKeyEx(sc, 3, hLayoutCurrent) + ); + } +#endif + return(keysym); +} + +int DIB_CreateWindow(_THIS) +{ + char *windowid; + + SDL_RegisterApp(NULL, 0, 0); + + windowid = SDL_getenv("SDL_WINDOWID"); + SDL_windowid = (windowid != NULL); + if ( SDL_windowid ) { +#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) + /* wince 2.1 does not have strtol */ + wchar_t *windowid_t = SDL_malloc((SDL_strlen(windowid) + 1) * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, windowid, -1, windowid_t, SDL_strlen(windowid) + 1); + SDL_Window = (HWND)wcstol(windowid_t, NULL, 0); + SDL_free(windowid_t); +#else + SDL_Window = (HWND)((size_t)SDL_strtoull(windowid, NULL, 0)); +#endif + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't get user specified window"); + return(-1); + } + + /* DJM: we want all event's for the user specified + window to be handled by SDL. + */ + userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC); + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage); + } else { + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX), + CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't create window"); + return(-1); + } + ShowWindow(SDL_Window, SW_HIDE); + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + return(0); +} + +void DIB_DestroyWindow(_THIS) +{ + if ( SDL_windowid ) { + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc); + } else { + DestroyWindow(SDL_Window); + } + SDL_UnregisterApp(); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); +} diff --git a/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h b/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h new file mode 100644 index 0000000..236aa68 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibevents_c.h @@ -0,0 +1,35 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../wincommon/SDL_lowvideo.h" + +/* Variables and functions exported by SDL_dibevents.c to other parts + of the native video subsystem (SDL_dibvideo.c) +*/ +extern LONG + DIB_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern int DIB_CreateWindow(_THIS); +extern void DIB_DestroyWindow(_THIS); + +extern void DIB_PumpEvents(_THIS); +extern void DIB_InitOSKeymap(_THIS); diff --git a/3rdparty/SDL/src/video/windib/SDL_dibvideo.c b/3rdparty/SDL/src/video/windib/SDL_dibvideo.c new file mode 100644 index 0000000..6187bfc --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibvideo.c @@ -0,0 +1,1323 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Not yet in the mingw32 cross-compile headers */ +#ifndef CDS_FULLSCREEN +#define CDS_FULLSCREEN 4 +#endif + +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_gapidibvideo.h" +#include "SDL_dibvideo.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "SDL_dibevents_c.h" +#include "../wincommon/SDL_wingl_c.h" + +#ifdef _WIN32_WCE + +#ifndef DM_DISPLAYORIENTATION +#define DM_DISPLAYORIENTATION 0x00800000L +#endif +#ifndef DM_DISPLAYQUERYORIENTATION +#define DM_DISPLAYQUERYORIENTATION 0x01000000L +#endif +#ifndef DMDO_0 +#define DMDO_0 0 +#endif +#ifndef DMDO_90 +#define DMDO_90 1 +#endif +#ifndef DMDO_180 +#define DMDO_180 2 +#endif +#ifndef DMDO_270 +#define DMDO_270 4 +#endif + +#define NO_GETDIBITS +#define NO_GAMMA_SUPPORT + #if _WIN32_WCE < 420 + #define NO_CHANGEDISPLAYSETTINGS + #else + #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0) + #endif +#endif +#ifndef WS_MAXIMIZE +#define WS_MAXIMIZE 0 +#endif +#ifndef WS_THICKFRAME +#define WS_THICKFRAME 0 +#endif +#ifndef SWP_NOCOPYBITS +#define SWP_NOCOPYBITS 0 +#endif +#ifndef PC_NOCOLLAPSE +#define PC_NOCOLLAPSE 0 +#endif + +#ifdef _WIN32_WCE +// defined and used in SDL_sysevents.c +extern HINSTANCE aygshell; +#endif + +/* Initialization/Query functions */ +static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DIB_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static void DIB_CheckGamma(_THIS); +void DIB_SwapGamma(_THIS); +void DIB_QuitGamma(_THIS); +int DIB_SetGammaRamp(_THIS, Uint16 *ramp); +int DIB_GetGammaRamp(_THIS, Uint16 *ramp); +static void DIB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DIB_LockHWSurface(_THIS, SDL_Surface *surface); +static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* Windows message handling functions */ +static void DIB_GrabStaticColors(HWND window); +static void DIB_ReleaseStaticColors(HWND window); +static void DIB_Activate(_THIS, BOOL active, BOOL minimized); +static void DIB_RealizePalette(_THIS); +static void DIB_PaletteChanged(_THIS, HWND window); +static void DIB_WinPAINT(_THIS, HDC hdc); + +/* helper fn */ +static int DIB_SussScreenDepth(); + +/* DIB driver bootstrap functions */ + +static int DIB_Available(void) +{ + return(1); +} + +static void DIB_DeleteDevice(SDL_VideoDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + if ( device->hidden->dibInfo ) { + SDL_free( device->hidden->dibInfo ); + } + SDL_free(device->hidden); + } + if ( device->gl_data ) { + SDL_free(device->gl_data); + } + SDL_free(device); + } +} + +static SDL_VideoDevice *DIB_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + if(device->hidden){ + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->dibInfo = (DibInfo *)SDL_malloc((sizeof(DibInfo))); + if(device->hidden->dibInfo == NULL) + { + SDL_free(device->hidden); + device->hidden = NULL; + } + } + + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + DIB_DeleteDevice(device); + return(NULL); + } + SDL_memset(device->hidden->dibInfo, 0, (sizeof *device->hidden->dibInfo)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = DIB_VideoInit; + device->ListModes = DIB_ListModes; + device->SetVideoMode = DIB_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->SetColors = DIB_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DIB_VideoQuit; + device->AllocHWSurface = DIB_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = DIB_LockHWSurface; + device->UnlockHWSurface = DIB_UnlockHWSurface; + device->FlipHWSurface = NULL; + device->FreeHWSurface = DIB_FreeHWSurface; + device->SetGammaRamp = DIB_SetGammaRamp; + device->GetGammaRamp = DIB_GetGammaRamp; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = WIN_GL_LoadLibrary; + device->GL_GetProcAddress = WIN_GL_GetProcAddress; + device->GL_GetAttribute = WIN_GL_GetAttribute; + device->GL_MakeCurrent = WIN_GL_MakeCurrent; + device->GL_SwapBuffers = WIN_GL_SwapBuffers; +#endif + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DIB_InitOSKeymap; + device->PumpEvents = DIB_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = DIB_Activate; + WIN_RealizePalette = DIB_RealizePalette; + WIN_PaletteChanged = DIB_PaletteChanged; + WIN_WinPAINT = DIB_WinPAINT; + HandleMessage = DIB_HandleMessage; + + device->free = DIB_DeleteDevice; + + /* We're finally ready */ + return device; +} + +VideoBootStrap WINDIB_bootstrap = { + "windib", "Win95/98/NT/2000/CE GDI", + DIB_Available, DIB_CreateDevice +}; + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static int DIB_AddMode(_THIS, int bpp, int w, int h) +{ + SDL_Rect *mode; + int i, index; + int next_mode; + + /* Check to see if we already have this mode */ + if ( bpp < 8 || bpp > 32 ) { /* Not supported */ + return(0); + } + index = ((bpp+7)/8)-1; + for ( i=0; i<SDL_nummodes[index]; ++i ) { + mode = SDL_modelist[index][i]; + if ( (mode->w == w) && (mode->h == h) ) { + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +static void DIB_CreatePalette(_THIS, int bpp) +{ +/* RJR: March 28, 2000 + moved palette creation here from "DIB_VideoInit" */ + + LOGPALETTE *palette; + HDC hdc; + int ncolors; + + ncolors = (1 << bpp); + palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+ + ncolors*sizeof(PALETTEENTRY)); + palette->palVersion = 0x300; + palette->palNumEntries = ncolors; + hdc = GetDC(SDL_Window); + GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); + ReleaseDC(SDL_Window, hdc); + screen_pal = CreatePalette(palette); + screen_logpal = palette; +} + +int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env = NULL; +#ifndef NO_CHANGEDISPLAYSETTINGS + int i; + DEVMODE settings; +#endif + + /* Create the window */ + if ( DIB_CreateWindow(this) < 0 ) { + return(-1); + } + +#if !SDL_AUDIO_DISABLED + DX5_SoundFocus(SDL_Window); +#endif + + /* Determine the screen depth */ + vformat->BitsPerPixel = DIB_SussScreenDepth(); + switch (vformat->BitsPerPixel) { + case 15: + vformat->Rmask = 0x00007c00; + vformat->Gmask = 0x000003e0; + vformat->Bmask = 0x0000001f; + vformat->BitsPerPixel = 16; + break; + case 16: + vformat->Rmask = 0x0000f800; + vformat->Gmask = 0x000007e0; + vformat->Bmask = 0x0000001f; + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + vformat->Rmask = 0x00ff0000; + vformat->Gmask = 0x0000ff00; + vformat->Bmask = 0x000000ff; + break; + default: + break; + } + + /* See if gamma is supported on this screen */ + DIB_CheckGamma(this); + +#ifndef NO_CHANGEDISPLAYSETTINGS + + settings.dmSize = sizeof(DEVMODE); + settings.dmDriverExtra = 0; +#ifdef _WIN32_WCE + settings.dmFields = DM_DISPLAYQUERYORIENTATION; + this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL; +#endif + /* Query for the desktop resolution */ + SDL_desktop_mode.dmSize = sizeof(SDL_desktop_mode); + SDL_desktop_mode.dmDriverExtra = 0; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode); + this->info.current_w = SDL_desktop_mode.dmPelsWidth; + this->info.current_h = SDL_desktop_mode.dmPelsHeight; + + /* Query for the list of available video modes */ + for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) { + DIB_AddMode(this, settings.dmBitsPerPel, + settings.dmPelsWidth, settings.dmPelsHeight); +#ifdef _WIN32_WCE + if( this->hidden->supportRotation ) + DIB_AddMode(this, settings.dmBitsPerPel, + settings.dmPelsHeight, settings.dmPelsWidth); +#endif + } + /* Sort the mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } +#else + // WinCE and fullscreen mode: + // We use only vformat->BitsPerPixel that allow SDL to + // emulate other bpp (8, 32) and use triple buffer, + // because SDL surface conversion is much faster than the WinCE one. + // Although it should be tested on devices with graphics accelerator. + + DIB_AddMode(this, vformat->BitsPerPixel, + GetDeviceCaps(GetDC(NULL), HORZRES), + GetDeviceCaps(GetDC(NULL), VERTRES)); + +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + /* Grab an identity palette if we are in a palettized mode */ + if ( vformat->BitsPerPixel <= 8 ) { + /* RJR: March 28, 2000 + moved palette creation to "DIB_CreatePalette" */ + DIB_CreatePalette(this, vformat->BitsPerPixel); + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + +#ifdef _WIN32_WCE + this->hidden->origRotation = -1; +#endif + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* We're done! */ + return(0); +} + +/* We support any format at any dimension */ +SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); + } else { + return((SDL_Rect **)-1); + } +} + + +/* + Helper fn to work out which screen depth windows is currently using. + 15 bit mode is considered 555 format, 16 bit is 565. + returns 0 for unknown mode. + (Derived from code in sept 1999 Windows Developer Journal + http://www.wdj.com/code/archive.html) +*/ +static int DIB_SussScreenDepth() +{ +#ifdef NO_GETDIBITS + int depth; + HDC hdc; + + hdc = GetDC(SDL_Window); + depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC(SDL_Window, hdc); + return(depth); +#else + int depth; + int dib_size; + LPBITMAPINFOHEADER dib_hdr; + HDC hdc; + HBITMAP hbm; + + /* Allocate enough space for a DIB header plus palette (for + * 8-bit modes) or bitfields (for 16- and 32-bit modes) + */ + dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD); + dib_hdr = (LPBITMAPINFOHEADER) SDL_malloc(dib_size); + SDL_memset(dib_hdr, 0, dib_size); + dib_hdr->biSize = sizeof(BITMAPINFOHEADER); + + /* Get a device-dependent bitmap that's compatible with the + screen. + */ + hdc = GetDC(NULL); + hbm = CreateCompatibleBitmap( hdc, 1, 1 ); + + /* Convert the DDB to a DIB. We need to call GetDIBits twice: + * the first call just fills in the BITMAPINFOHEADER; the + * second fills in the bitfields or palette. + */ + GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); + GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS); + DeleteObject(hbm); + ReleaseDC(NULL, hdc); + + depth = 0; + switch( dib_hdr->biBitCount ) + { + case 8: depth = 8; break; + case 24: depth = 24; break; + case 32: depth = 32; break; + case 16: + if( dib_hdr->biCompression == BI_BITFIELDS ) { + /* check the red mask */ + switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) { + case 0xf800: depth = 16; break; /* 565 */ + case 0x7c00: depth = 15; break; /* 555 */ + } + } + } + SDL_free(dib_hdr); + return depth; +#endif /* NO_GETDIBITS */ +} + + +/* Various screen update functions available */ +static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); + +static void DIB_ResizeWindow(_THIS, int width, int height, int prev_width, int prev_height, Uint32 flags) +{ + RECT bounds; + int x, y; + +#ifndef _WIN32_WCE + /* Resize the window */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { +#else + if ( !SDL_windowid ) { +#endif + HWND top; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( width != prev_width || height != prev_height ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW); + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+width; + bounds.bottom = SDL_windowY+height; +#ifndef _WIN32_WCE + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); +#else + // The bMenu parameter must be FALSE; menu bars are not supported + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0); +#endif + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( (flags & SDL_FULLSCREEN) ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + if ( flags & SDL_FULLSCREEN ) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } + SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags); + if ( !(flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + if ( GetParent(SDL_Window) == NULL ) { + SetForegroundWindow(SDL_Window); + } + } +} + +SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + int prev_w, prev_h; + Uint32 prev_flags; + DWORD style; + const DWORD directstyle = + (WS_POPUP); + const DWORD windowstyle = + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX); + const DWORD resizestyle = + (WS_THICKFRAME|WS_MAXIMIZEBOX); + int binfo_size; + BITMAPINFO *binfo; + HDC hdc; + Uint32 Rmask, Gmask, Bmask; + + prev_w = current->w; + prev_h = current->h; + prev_flags = current->flags; + + /* + * Special case for OpenGL windows...since the app needs to call + * SDL_SetVideoMode() in response to resize events to continue to + * function, but WGL handles the GL context details behind the scenes, + * there's no sense in tearing the context down just to rebuild it + * to what it already was...tearing it down sacrifices your GL state + * and uploaded textures. So if we're requesting the same video mode + * attributes just resize the window and return immediately. + */ + if ( SDL_Window && + ((current->flags & ~SDL_ANYFORMAT) == (flags & ~SDL_ANYFORMAT)) && + (current->format->BitsPerPixel == bpp) && + (flags & SDL_OPENGL) && + !(flags & SDL_FULLSCREEN) ) { /* probably not safe for fs */ + current->w = width; + current->h = height; + SDL_resizing = 1; + DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags); + SDL_resizing = 0; + return current; + } + + /* Clean up any GL context that may be hanging around */ + if ( current->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + SDL_resizing = 1; + + /* Recalculate the bitmasks if necessary */ + if ( bpp == current->format->BitsPerPixel ) { + video = current; + } else { + switch (bpp) { + case 15: + case 16: + if ( DIB_SussScreenDepth() == 15 ) { + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } else { + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + break; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, + 0, 0, bpp, Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + /* Fill in part of the video surface */ + video->flags = 0; /* Clear flags */ + video->w = width; + video->h = height; + video->pitch = SDL_CalculatePitch(video); + + /* Small fix for WinCE/Win32 - when activating window + SDL_VideoSurface is equal to zero, so activating code + is not called properly for fullscreen windows because + macros WINDIB_FULLSCREEN uses SDL_VideoSurface + */ + SDL_VideoSurface = video; + +#if defined(_WIN32_WCE) + if ( flags & SDL_FULLSCREEN ) + video->flags |= SDL_FULLSCREEN; +#endif + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Set fullscreen mode if appropriate */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + DEVMODE settings; + BOOL changed; + + SDL_memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + +#ifdef _WIN32_WCE + // try to rotate screen to fit requested resolution + if( this->hidden->supportRotation ) + { + DWORD rotation; + + // ask current mode + settings.dmFields = DM_DISPLAYORIENTATION; + ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL); + rotation = settings.dmDisplayOrientation; + + if( (width > GetDeviceCaps(GetDC(NULL), HORZRES)) + && (height < GetDeviceCaps(GetDC(NULL), VERTRES))) + { + switch( rotation ) + { + case DMDO_0: + settings.dmDisplayOrientation = DMDO_90; + break; + case DMDO_270: + settings.dmDisplayOrientation = DMDO_180; + break; + } + if( settings.dmDisplayOrientation != rotation ) + { + // go to landscape + this->hidden->origRotation = rotation; + ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL); + } + } + if( (width < GetDeviceCaps(GetDC(NULL), HORZRES)) + && (height > GetDeviceCaps(GetDC(NULL), VERTRES))) + { + switch( rotation ) + { + case DMDO_90: + settings.dmDisplayOrientation = DMDO_0; + break; + case DMDO_180: + settings.dmDisplayOrientation = DMDO_270; + break; + } + if( settings.dmDisplayOrientation != rotation ) + { + // go to portrait + this->hidden->origRotation = rotation; + ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL); + } + } + + } +#endif + +#ifndef _WIN32_WCE + settings.dmBitsPerPel = video->format->BitsPerPixel; + settings.dmPelsWidth = width; + settings.dmPelsHeight = height; + settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + if ( width <= (int)SDL_desktop_mode.dmPelsWidth && + height <= (int)SDL_desktop_mode.dmPelsHeight ) { + settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency; + settings.dmFields |= DM_DISPLAYFREQUENCY; + } + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) { + settings.dmFields &= ~DM_DISPLAYFREQUENCY; + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + } +#else + changed = 1; +#endif + if ( changed ) { + video->flags |= SDL_FULLSCREEN; + SDL_fullscreen_mode = settings; + } + + } +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + /* Reset the palette and create a new one if necessary */ + if ( grab_palette ) { + DIB_ReleaseStaticColors(SDL_Window); + grab_palette = FALSE; + } + if ( screen_pal != NULL ) { + /* RJR: March 28, 2000 + delete identity palette if switching from a palettized mode */ + DeleteObject(screen_pal); + screen_pal = NULL; + } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } + + if ( bpp <= 8 ) + { + /* RJR: March 28, 2000 + create identity palette switching to a palettized mode */ + DIB_CreatePalette(this, bpp); + } + + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + ChangeDisplaySettings(NULL, 0); + } +#endif + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + video->flags |= SDL_NOFRAME; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + video->flags |= SDL_RESIZABLE; + } + } +#if WS_MAXIMIZE && !defined(_WIN32_WCE) + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Delete the old bitmap if necessary */ + if ( screen_bmp != NULL ) { + DeleteObject(screen_bmp); + } + if ( ! (flags & SDL_OPENGL) ) { + BOOL is16bitmode = (video->format->BytesPerPixel == 2); + + /* Suss out the bitmap info header */ + binfo_size = sizeof(*binfo); + if( is16bitmode ) { + /* 16bit modes, palette area used for rgb bitmasks */ + binfo_size += 3*sizeof(DWORD); + } else if ( video->format->palette ) { + binfo_size += video->format->palette->ncolors * + sizeof(RGBQUAD); + } + binfo = (BITMAPINFO *)SDL_malloc(binfo_size); + if ( ! binfo ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_OutOfMemory(); + return(NULL); + } + + binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + binfo->bmiHeader.biWidth = video->w; + binfo->bmiHeader.biHeight = -video->h; /* -ve for topdown bitmap */ + binfo->bmiHeader.biPlanes = 1; + binfo->bmiHeader.biSizeImage = video->h * video->pitch; + binfo->bmiHeader.biXPelsPerMeter = 0; + binfo->bmiHeader.biYPelsPerMeter = 0; + binfo->bmiHeader.biClrUsed = 0; + binfo->bmiHeader.biClrImportant = 0; + binfo->bmiHeader.biBitCount = video->format->BitsPerPixel; + + if ( is16bitmode ) { + /* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */ + binfo->bmiHeader.biCompression = BI_BITFIELDS; + ((Uint32*)binfo->bmiColors)[0] = video->format->Rmask; + ((Uint32*)binfo->bmiColors)[1] = video->format->Gmask; + ((Uint32*)binfo->bmiColors)[2] = video->format->Bmask; + } else { + binfo->bmiHeader.biCompression = BI_RGB; /* BI_BITFIELDS for 565 vs 555 */ + if ( video->format->palette ) { + SDL_memset(binfo->bmiColors, 0, + video->format->palette->ncolors*sizeof(RGBQUAD)); + } + } + + /* Create the offscreen bitmap buffer */ + hdc = GetDC(SDL_Window); + screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS, + (void **)(&video->pixels), NULL, 0); + ReleaseDC(SDL_Window, hdc); + SDL_free(binfo); + if ( screen_bmp == NULL ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_SetError("Couldn't create DIB section"); + return(NULL); + } + this->UpdateRects = DIB_NormalUpdate; + + /* Set video surface flags */ + if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) { + grab_palette = TRUE; + } + if ( screen_pal ) { + /* BitBlt() maps colors for us */ + video->flags |= SDL_HWPALETTE; + } + } + DIB_ResizeWindow(this, width, height, prev_w, prev_h, flags); + SDL_resizing = 0; + + /* Set up for OpenGL */ + if ( flags & SDL_OPENGL ) { + if ( WIN_GL_SetupWindow(this) < 0 ) { + return(NULL); + } + video->flags |= SDL_OPENGL; + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* We're live! */ + return(video); +} + +/* We don't actually allow hardware surfaces in the DIB driver */ +static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} +static int DIB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} +static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + HDC hdc, mdc; + int i; + + hdc = GetDC(SDL_Window); + if ( screen_pal ) { + SelectPalette(hdc, screen_pal, FALSE); + } + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + for ( i=0; i<numrects; ++i ) { + BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h, + mdc, rects[i].x, rects[i].y, SRCCOPY); + } + DeleteDC(mdc); + ReleaseDC(SDL_Window, hdc); +} + +static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + int i; + int nentries = pal->palNumEntries; + + for ( i = 0; i < nentries; ++i ) { + entry = &pal->palPalEntry[i]; + if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) { + return i; + } + } + return -1; +} + +static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + BOOL moved = 0; + + entry = &pal->palPalEntry[index]; + if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) { + int found = FindPaletteIndex(pal, r, g, b); + if ( found >= 0 ) { + pal->palPalEntry[found] = *entry; + } + entry->peRed = r; + entry->peGreen = g; + entry->peBlue = b; + moved = 1; + } + entry->peFlags = 0; + + return moved; +} + +int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + HDC hdc, mdc; + RGBQUAD *pal; +#else + HDC hdc; +#endif + int i; + int moved_entries = 0; + + /* Update the display palette */ + hdc = GetDC(SDL_Window); + if ( screen_pal ) { + PALETTEENTRY *entry; + + for ( i=0; i<ncolors; ++i ) { + entry = &screen_logpal->palPalEntry[firstcolor+i]; + entry->peRed = colors[i].r; + entry->peGreen = colors[i].g; + entry->peBlue = colors[i].b; + entry->peFlags = PC_NOCOLLAPSE; + } +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + /* Check to make sure black and white are in position */ + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00); + moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff); + } + /* FIXME: + If we don't have full access to the palette, what we + really want to do is find the 236 most diverse colors + in the desired palette, set those entries (10-245) and + then map everything into the new system palette. + */ +#endif + +#ifndef _WIN32_WCE + /* Copy the entries into the system palette */ + UnrealizeObject(screen_pal); +#endif + SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry); + SelectPalette(hdc, screen_pal, FALSE); + RealizePalette(hdc); + } + +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) + /* Copy palette colors into DIB palette */ + pal = SDL_stack_alloc(RGBQUAD, ncolors); + for ( i=0; i<ncolors; ++i ) { + pal[i].rgbRed = colors[i].r; + pal[i].rgbGreen = colors[i].g; + pal[i].rgbBlue = colors[i].b; + pal[i].rgbReserved = 0; + } + + /* Set the DIB palette and update the display */ + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + SetDIBColorTable(mdc, firstcolor, ncolors, pal); + if ( moved_entries || !grab_palette ) { + BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, + mdc, 0, 0, SRCCOPY); + } + DeleteDC(mdc); + SDL_stack_free(pal); +#endif + ReleaseDC(SDL_Window, hdc); + return(1); +} + + +static void DIB_CheckGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + HDC hdc; + WORD ramp[3*256]; + + /* If we fail to get gamma, disable gamma control */ + hdc = GetDC(SDL_Window); + if ( ! GetDeviceGammaRamp(hdc, ramp) ) { + this->GetGammaRamp = NULL; + this->SetGammaRamp = NULL; + } + ReleaseDC(SDL_Window, hdc); +#endif /* !NO_GAMMA_SUPPORT */ +} +void DIB_SwapGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + HDC hdc; + + if ( gamma_saved ) { + hdc = GetDC(SDL_Window); + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + /* About to leave active state, restore gamma */ + SetDeviceGammaRamp(hdc, gamma_saved); + } else { + /* About to enter active state, set game gamma */ + GetDeviceGammaRamp(hdc, gamma_saved); + SetDeviceGammaRamp(hdc, this->gamma); + } + ReleaseDC(SDL_Window, hdc); + } +#endif /* !NO_GAMMA_SUPPORT */ +} +void DIB_QuitGamma(_THIS) +{ +#ifndef NO_GAMMA_SUPPORT + if ( gamma_saved ) { + /* Restore the original gamma if necessary */ + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + HDC hdc; + + hdc = GetDC(SDL_Window); + SetDeviceGammaRamp(hdc, gamma_saved); + ReleaseDC(SDL_Window, hdc); + } + + /* Free the saved gamma memory */ + SDL_free(gamma_saved); + gamma_saved = 0; + } +#endif /* !NO_GAMMA_SUPPORT */ +} + +int DIB_SetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef NO_GAMMA_SUPPORT + SDL_SetError("SDL compiled without gamma ramp support"); + return -1; +#else + HDC hdc; + BOOL succeeded; + + /* Set the ramp for the display */ + if ( ! gamma_saved ) { + gamma_saved = (WORD *)SDL_malloc(3*256*sizeof(*gamma_saved)); + if ( ! gamma_saved ) { + SDL_OutOfMemory(); + return -1; + } + hdc = GetDC(SDL_Window); + GetDeviceGammaRamp(hdc, gamma_saved); + ReleaseDC(SDL_Window, hdc); + } + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + hdc = GetDC(SDL_Window); + succeeded = SetDeviceGammaRamp(hdc, ramp); + ReleaseDC(SDL_Window, hdc); + } else { + succeeded = TRUE; + } + return succeeded ? 0 : -1; +#endif /* !NO_GAMMA_SUPPORT */ +} + +int DIB_GetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef NO_GAMMA_SUPPORT + SDL_SetError("SDL compiled without gamma ramp support"); + return -1; +#else + HDC hdc; + BOOL succeeded; + + /* Get the ramp from the display */ + hdc = GetDC(SDL_Window); + succeeded = GetDeviceGammaRamp(hdc, ramp); + ReleaseDC(SDL_Window, hdc); + return succeeded ? 0 : -1; +#endif /* !NO_GAMMA_SUPPORT */ +} + +void DIB_VideoQuit(_THIS) +{ + int i, j; + + /* Destroy the window and everything associated with it */ + if ( SDL_Window ) { + /* Delete the screen bitmap (also frees screen->pixels) */ + if ( this->screen ) { + if ( grab_palette ) { + DIB_ReleaseStaticColors(SDL_Window); + } +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( this->screen->flags & SDL_FULLSCREEN ) { + ChangeDisplaySettings(NULL, 0); + ShowWindow(SDL_Window, SW_HIDE); + } +#endif + if ( this->screen->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + this->screen->pixels = NULL; + } + if ( screen_pal != NULL ) { + DeleteObject(screen_pal); + screen_pal = NULL; + } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } + if ( screen_bmp ) { + DeleteObject(screen_bmp); + screen_bmp = NULL; + } + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } + DIB_QuitGamma(this); + DIB_DestroyWindow(this); + + SDL_Window = NULL; + +#if defined(_WIN32_WCE) + +// Unload wince aygshell library to prevent leak + if( aygshell ) + { + FreeLibrary(aygshell); + aygshell = NULL; + } +#endif + } + + for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) { + if ( !SDL_modelist[i] ) { + continue; + } + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + SDL_nummodes[i] = 0; + } +} + +/* Exported for the windows message loop only */ +static void DIB_GrabStaticColors(HWND window) +{ +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256); + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + } + ReleaseDC(window, hdc); +#endif +} +static void DIB_ReleaseStaticColors(HWND window) +{ +#if defined(SYSPAL_NOSTATIC) && !defined(_WIN32_WCE) + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_STATIC); + ReleaseDC(window, hdc); +#endif +} +static void DIB_Activate(_THIS, BOOL active, BOOL minimized) +{ + if ( grab_palette ) { + if ( !active ) { + DIB_ReleaseStaticColors(SDL_Window); + DIB_RealizePalette(this); + } else if ( !minimized ) { + DIB_GrabStaticColors(SDL_Window); + DIB_RealizePalette(this); + } + } +} +static void DIB_RealizePalette(_THIS) +{ + if ( screen_pal != NULL ) { + HDC hdc; + + hdc = GetDC(SDL_Window); +#ifndef _WIN32_WCE + UnrealizeObject(screen_pal); +#endif + SelectPalette(hdc, screen_pal, FALSE); + if ( RealizePalette(hdc) ) { + InvalidateRect(SDL_Window, NULL, FALSE); + } + ReleaseDC(SDL_Window, hdc); + } +} +static void DIB_PaletteChanged(_THIS, HWND window) +{ + if ( window != SDL_Window ) { + DIB_RealizePalette(this); + } +} + +/* Exported for the windows message loop only */ +static void DIB_WinPAINT(_THIS, HDC hdc) +{ + HDC mdc; + + if ( screen_pal ) { + SelectPalette(hdc, screen_pal, FALSE); + } + mdc = CreateCompatibleDC(hdc); + SelectObject(mdc, screen_bmp); + BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h, + mdc, 0, 0, SRCCOPY); + DeleteDC(mdc); +} + +/* Stub in case DirectX isn't available */ +#if !SDL_AUDIO_DRIVER_DSOUND +void DX5_SoundFocus(HWND hwnd) +{ + return; +} +#endif diff --git a/3rdparty/SDL/src/video/windib/SDL_dibvideo.h b/3rdparty/SDL/src/video/windib/SDL_dibvideo.h new file mode 100644 index 0000000..48b1943 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_dibvideo.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dibvideo_h +#define _SDL_dibvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + + +/* Private display data */ +struct DibInfo { + HBITMAP screen_bmp; + HPALETTE screen_pal; + LOGPALETTE *screen_logpal; + BOOL grab_palette; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + +#ifdef _WIN32_WCE + int supportRotation; /* for Pocket PC devices */ + DWORD origRotation; /* for Pocket PC devices */ +#endif + + /* Screensaver settings */ + int allow_screensaver; +}; +/* Old variable names */ +#define screen_bmp (this->hidden->dibInfo->screen_bmp) +#define screen_pal (this->hidden->dibInfo->screen_pal) +#define screen_logpal (this->hidden->dibInfo->screen_logpal) +#define grab_palette (this->hidden->dibInfo->grab_palette) +#define SDL_nummodes (this->hidden->dibInfo->SDL_nummodes) +#define SDL_modelist (this->hidden->dibInfo->SDL_modelist) +#define allow_screensaver (this->hidden->dibInfo->allow_screensaver) + +#endif /* _SDL_dibvideo_h */ diff --git a/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h b/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h new file mode 100644 index 0000000..64743d1 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_gapidibvideo.h @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_gapidibvideo_h +#define _SDL_gapidibvideo_h + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* typedef these to be able to define pointers, but still force everybody who + * wants to access them to include the corresponding header */ +typedef struct GapiInfo GapiInfo; +typedef struct DibInfo DibInfo; + +/* for PDA */ +typedef enum +{ + SDL_ORIENTATION_UP, + SDL_ORIENTATION_DOWN, + SDL_ORIENTATION_LEFT, + SDL_ORIENTATION_RIGHT +} SDL_ScreenOrientation; + +/* Private display data shared by gapi and windib*/ +struct SDL_PrivateVideoData { + int supportRotation; /* for Pocket PC devices */ + DWORD origRotation; /* for Pocket PC devices */ + + GapiInfo* gapiInfo; + DibInfo* dibInfo; +}; + +#endif diff --git a/3rdparty/SDL/src/video/windib/SDL_vkeys.h b/3rdparty/SDL/src/video/windib/SDL_vkeys.h new file mode 100644 index 0000000..53d9246 --- /dev/null +++ b/3rdparty/SDL/src/video/windib/SDL_vkeys.h @@ -0,0 +1,75 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifndef VK_0 +#define VK_0 '0' +#define VK_1 '1' +#define VK_2 '2' +#define VK_3 '3' +#define VK_4 '4' +#define VK_5 '5' +#define VK_6 '6' +#define VK_7 '7' +#define VK_8 '8' +#define VK_9 '9' +#define VK_A 'A' +#define VK_B 'B' +#define VK_C 'C' +#define VK_D 'D' +#define VK_E 'E' +#define VK_F 'F' +#define VK_G 'G' +#define VK_H 'H' +#define VK_I 'I' +#define VK_J 'J' +#define VK_K 'K' +#define VK_L 'L' +#define VK_M 'M' +#define VK_N 'N' +#define VK_O 'O' +#define VK_P 'P' +#define VK_Q 'Q' +#define VK_R 'R' +#define VK_S 'S' +#define VK_T 'T' +#define VK_U 'U' +#define VK_V 'V' +#define VK_W 'W' +#define VK_X 'X' +#define VK_Y 'Y' +#define VK_Z 'Z' +#endif /* VK_0 */ + +/* These keys haven't been defined, but were experimentally determined */ +#define VK_SEMICOLON 0xBA +#define VK_EQUALS 0xBB +#define VK_COMMA 0xBC +#define VK_MINUS 0xBD +#define VK_PERIOD 0xBE +#define VK_SLASH 0xBF +#define VK_GRAVE 0xC0 +#define VK_LBRACKET 0xDB +#define VK_BACKSLASH 0xDC +#define VK_RBRACKET 0xDD +#define VK_APOSTROPHE 0xDE +#define VK_BACKTICK 0xDF +#define VK_OEM_102 0xE2 diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5events.c b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c new file mode 100644 index 0000000..e12092f --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5events.c @@ -0,0 +1,1005 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* CAUTION!!!! If you modify this file, check ../windib/SDL_sysevents.c */ + +#include "directx.h" + +#include "SDL_main.h" +#include "SDL_events.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_dx5video.h" + +#ifndef WM_APP +#define WM_APP 0x8000 +#endif + +#ifdef _WIN32_WCE +#define NO_GETKEYBOARDSTATE +#endif + +/* The keyboard and mouse device input */ +#define MAX_INPUTS 2 +#define INPUT_QSIZE 512 /* Buffer up to 512 input messages */ + +static LPDIRECTINPUT dinput = NULL; +static LPDIRECTINPUTDEVICE2 SDL_DIdev[MAX_INPUTS]; +static HANDLE SDL_DIevt[MAX_INPUTS]; +static void (*SDL_DIfun[MAX_INPUTS])(const int, DIDEVICEOBJECTDATA *); +static int SDL_DIndev = 0; +static int mouse_lost; +static int mouse_pressed; +static int mouse_buttons_swapped = 0; + +/* The translation table from a DirectInput scancode to an SDL keysym */ +static SDLKey DIK_keymap[256]; +static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed); + +/* DJM: If the user setup the window for us, we want to save his window proc, + and give him a chance to handle some messages. */ +#ifdef STRICT +#define WNDPROCTYPE WNDPROC +#else +#define WNDPROCTYPE FARPROC +#endif +static WNDPROCTYPE userWindowProc = NULL; + +static HWND GetTopLevelParent(HWND hWnd) +{ + HWND hParentWnd; + while (1) + { + hParentWnd = GetParent(hWnd); + if (hParentWnd == NULL) + break; + hWnd = hParentWnd; + } + return hWnd; +} + +/* Convert a DirectInput return code to a text message */ +static void SetDIerror(char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case DIERR_GENERIC: + error = "Undefined error!"; + break; + case DIERR_OLDDIRECTINPUTVERSION: + error = "Your version of DirectInput needs upgrading"; + break; + case DIERR_INVALIDPARAM: + error = "Invalid parameters"; + break; + case DIERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DIERR_DEVICENOTREG: + error = "Device not registered"; + break; + case DIERR_NOINTERFACE: + error = "Interface not supported"; + break; + case DIERR_NOTINITIALIZED: + error = "Device not initialized"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectInput error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + +/* Initialize DirectInput + Note: If NONEXCLUSIVE access is requested for the devices, normal + windows input messages will continue to be generated for that + input device, in addition to DirectInput messages. + */ +static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *events); +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *events); +struct { + char *name; + REFGUID guid; + LPCDIDATAFORMAT format; + DWORD win_level; + DWORD raw_level; + void (*fun)(const int numevents, DIDEVICEOBJECTDATA *events); +} inputs[] = { + { "keyboard", + &GUID_SysKeyboard, &c_dfDIKeyboard, + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), + (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard }, + { "mouse", + &GUID_SysMouse, +#if DIRECTINPUT_VERSION >= 0x700 + &c_dfDIMouse2, +#else + &c_dfDIMouse, +#endif + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), + (DISCL_BACKGROUND|DISCL_NONEXCLUSIVE), handle_mouse }, + { NULL, NULL, NULL, 0, 0, NULL } +}; + +static int DX5_DInputInit(_THIS) +{ + int i; + LPDIRECTINPUTDEVICE device; + HRESULT result; + DIPROPDWORD dipdw; + HWND topwnd; + + /* Create the DirectInput object */ + result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, + &dinput, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInputCreate", result); + return(-1); + } + + /* Create all of our registered input devices */ + SDL_DIndev = 0; + for ( i=0; inputs[i].name; ++i ) { + /* Create the DirectInput device */ + result = IDirectInput_CreateDevice(dinput, inputs[i].guid, + &device, NULL); + if ( result != DI_OK ) { + SetDIerror("DirectInput::CreateDevice", result); + return(-1); + } + result = IDirectInputDevice_QueryInterface(device, + &IID_IDirectInputDevice2, (LPVOID *)&SDL_DIdev[i]); + IDirectInputDevice_Release(device); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::QueryInterface", result); + return(-1); + } + topwnd = GetTopLevelParent(SDL_Window); + result = IDirectInputDevice2_SetCooperativeLevel(SDL_DIdev[i], + topwnd, inputs[i].win_level); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetCooperativeLevel", + result); + return(-1); + } + result = IDirectInputDevice2_SetDataFormat(SDL_DIdev[i], + inputs[i].format); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetDataFormat", result); + return(-1); + } + + /* Set buffered input -- we aren't polling */ + SDL_memset(&dipdw, 0, sizeof(dipdw)); + dipdw.diph.dwSize = sizeof(dipdw); + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = INPUT_QSIZE; + result = IDirectInputDevice2_SetProperty(SDL_DIdev[i], + DIPROP_BUFFERSIZE, &dipdw.diph); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetProperty", result); + return(-1); + } + + /* Create an event to be signaled when input is ready */ + SDL_DIevt[i] = CreateEvent(NULL, FALSE, FALSE, NULL); + if ( SDL_DIevt[i] == NULL ) { + SDL_SetError("Couldn't create DirectInput event"); + return(-1); + } + result = IDirectInputDevice2_SetEventNotification(SDL_DIdev[i], + SDL_DIevt[i]); + if ( result != DI_OK ) { + SetDIerror("DirectInputDevice::SetEventNotification", + result); + return(-1); + } + SDL_DIfun[i] = inputs[i].fun; + + /* Acquire the device for input */ + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + + /* Increment the number of devices we have */ + ++SDL_DIndev; + } + mouse_pressed = 0; + mouse_buttons_swapped = GetSystemMetrics(SM_SWAPBUTTON); + + /* DirectInput is ready! */ + return(0); +} + +/* Clean up DirectInput */ +static void DX5_DInputQuit(_THIS) +{ + int i; + + if ( dinput != NULL ) { + /* Close and release all DirectInput devices */ + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + IDirectInputDevice2_Unacquire(SDL_DIdev[i]); + IDirectInputDevice2_SetEventNotification( + SDL_DIdev[i], NULL); + if ( SDL_DIevt[i] != NULL ) { + CloseHandle(SDL_DIevt[i]); + SDL_DIevt[i] = NULL; + } + IDirectInputDevice2_Release(SDL_DIdev[i]); + SDL_DIdev[i] = NULL; + } + } + SDL_DIndev = 0; + + /* Release DirectInput */ + IDirectInput_Release(dinput); + dinput = NULL; + } +} + +/* Flag to tell SDL whether or not we queued an event */ +static int posted = 0; + +/* Input event handler functions */ +static void handle_keyboard(const int numevents, DIDEVICEOBJECTDATA *keybuf) +{ + int i; + SDL_keysym keysym; + + /* Translate keyboard messages */ + for ( i=0; i<numevents; ++i ) { + if ( keybuf[i].dwData & 0x80 ) { + posted = SDL_PrivateKeyboard(SDL_PRESSED, + TranslateKey(keybuf[i].dwOfs, &keysym, 1)); + } else { + posted = SDL_PrivateKeyboard(SDL_RELEASED, + TranslateKey(keybuf[i].dwOfs, &keysym, 0)); + } + } +} + +static void post_mouse_motion(int relative, Sint16 x, Sint16 y) +{ + extern int mouse_relative; + + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + posted = SDL_PrivateMouseMotion( + 0, relative, x, y); + + if ( !mouse_relative ) { + /* As DirectInput reads raw device coordinates, it has no notion of + * cursors or absolute position. We must assume responsibility for + * keeping track of this. */ + int current_x, current_y; + POINT cursor; + RECT trap; + RECT window; + int at_edge; + + /* Get the current cursor position */ + SDL_GetMouseState(¤t_x, ¤t_y); + cursor.x = current_x; + cursor.y = current_y; + ClientToScreen(SDL_Window, &cursor); + + /* Construct a 1 pixel square RECT that is used to confine the cursor + * pointer to a specific pixel using ClipCursor. This is used in + * preference to SetCursorPos as it avoids the cursor jumping around as + * both the OS and SDL attempt to move it simultaneously. */ + trap.left = cursor.x; + trap.top = cursor.y; + trap.right = cursor.x + 1; + trap.bottom = cursor.y + 1; + + GetClientRect(SDL_Window, &window); + window.right -= window.left; window.left = 0; + window.bottom -= window.top; window.top = 0; + + /* As we're assuming control over the cursor, we need to know when to + * relinquish control of it back to the operating system. This is when + * the cursor reaches the edge of the window. */ + at_edge = (current_x == window.left) || + (current_x == (window.right - 1)) || + (current_y == window.top) || + (current_y == (window.bottom - 1)); + + if ( at_edge ) { + ClipCursor(NULL); + } else { + ClipCursor(&trap); + } + } else { + /* When in relative mode, warp the OS's idea of where the cursor is to + * the center of the screen. This isn't really necessary as DirectInput + * reads from the hardware itself, but in case things go wrong, the + * cursor will be left in a sensible place. */ + POINT center; + center.x = (SDL_VideoSurface->w/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + SetCursorPos(center.x, center.y); + } + } +} + +static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf) +{ + int i; + Sint16 xrel, yrel; + Uint8 state; + Uint8 button; + DWORD timestamp = 0; + + /* Sanity check. Mailing list reports this being NULL unexpectedly. */ + if (SDL_PublicSurface == NULL) { + return; + } + + /* If mouse focus has been lost, make sure we release the cursor. */ + if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + mouse_lost = 1; + ClipCursor(NULL); + } else { + /* If the mouse was lost, regain some sense of mouse state */ + if ( mouse_lost ) { + POINT mouse_pos; + Uint8 old_state; + Uint8 new_state; + + /* Set ourselves up with the current cursor position */ + GetCursorPos(&mouse_pos); + ScreenToClient(SDL_Window, &mouse_pos); + post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y); + + /* Check for mouse button changes */ + old_state = SDL_GetMouseState(NULL, NULL); + new_state = 0; + { /* Get the new DirectInput button state for the mouse */ + #if DIRECTINPUT_VERSION >= 0x700 + DIMOUSESTATE2 distate; + #else + DIMOUSESTATE distate; + #endif + HRESULT result; + + result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1], + sizeof(distate), &distate); + if ( result != DI_OK ) { + /* Try again next time */ + SetDIerror( + "IDirectInputDevice2::GetDeviceState", result); + return; + } + for ( i=3; i>=0; --i ) { + if ( (distate.rgbButtons[i]&0x80) == 0x80 ) { + new_state |= 0x01; + } + new_state <<= 1; + } + } + for ( i=0; i<8; ++i ) { + if ( (old_state&0x01) != (new_state&0x01) ) { + button = (Uint8)(i+1); + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( new_state & 0x01 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + } + old_state >>= 1; + new_state >>= 1; + } + mouse_lost = 0; + return; + } + + /* Translate mouse messages */ + xrel = 0; + yrel = 0; + for ( i=0; i<(int)numevents; ++i ) { + switch (ptrbuf[i].dwOfs) { + case DIMOFS_X: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + xrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Y: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = ptrbuf[i].dwTimeStamp; + } + yrel += (Sint16)ptrbuf[i].dwData; + break; + case DIMOFS_Z: + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + if((int)ptrbuf[i].dwData > 0) + button = SDL_BUTTON_WHEELUP; + else + button = SDL_BUTTON_WHEELDOWN; + posted = SDL_PrivateMouseButton( + SDL_PRESSED, button, 0, 0); + posted |= SDL_PrivateMouseButton( + SDL_RELEASED, button, 0, 0); + break; + case DIMOFS_BUTTON0: + case DIMOFS_BUTTON1: + case DIMOFS_BUTTON2: + case DIMOFS_BUTTON3: + #if DIRECTINPUT_VERSION >= 0x700 + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: + #endif + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } + timestamp = 0; + button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1; + /* Map DI button numbers to SDL */ + switch ( button ) { + case 2: button = SDL_BUTTON_RIGHT; break; + case 3: button = SDL_BUTTON_MIDDLE; break; + case 4: button = SDL_BUTTON_X1; break; + case 5: button = SDL_BUTTON_X2; break; + default: break; + } + if ( ptrbuf[i].dwData & 0x80 ) { + /* Grab mouse so we get mouse-up */ + if ( ++mouse_pressed > 0 ) { + SetCapture(SDL_Window); + } + state = SDL_PRESSED; + } else { + /* Release mouse after all mouse-ups */ + if ( --mouse_pressed <= 0 ) { + ReleaseCapture(); + mouse_pressed = 0; + } + state = SDL_RELEASED; + } + if ( mouse_buttons_swapped ) { + if ( button == 1 ) button = 3; + else + if ( button == 3 ) button = 1; + } + posted = SDL_PrivateMouseButton(state, button, + 0, 0); + break; + } + } + if ( xrel || yrel ) { + post_mouse_motion(1, xrel, yrel); + } + } +} + +/* The main Win32 event handler */ +LRESULT DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { +#ifdef WM_ACTIVATEAPP + case WM_ACTIVATEAPP: { + int i, active; + + active = (wParam && (GetForegroundWindow() == hwnd)); + if ( active ) { + for ( i=0; i<MAX_INPUTS; ++i ) { + if (SDL_DIdev[i] != NULL) + IDirectInputDevice2_Acquire( + SDL_DIdev[i]); + } + } else { + for ( i=0; i<MAX_INPUTS; ++i ) { + if (SDL_DIdev[i] != NULL) + IDirectInputDevice2_Unacquire( + SDL_DIdev[i]); + } + mouse_lost = 1; + } + } + break; +#endif /* WM_ACTIVATEAPP */ + +#ifdef WM_DISPLAYCHANGE + case WM_DISPLAYCHANGE: { + WPARAM BitsPerPixel; + WORD SizeX, SizeY; + + /* Ack! The display changed size and/or depth! */ + SizeX = LOWORD(lParam); + SizeY = HIWORD(lParam); + BitsPerPixel = wParam; + /* We cause this message when we go fullscreen */ + } + break; +#endif /* WM_DISPLAYCHANGE */ + + /* The keyboard is handled via DirectInput */ + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_KEYDOWN: { + /* Ignore windows keyboard messages */; + } + return(0); + +#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER) + /* Don't allow screen savers or monitor power downs. + This is because they quietly clear DirectX surfaces. + It would be better to allow the application to + decide whether or not to blow these off, but the + semantics of SDL_PrivateSysWMEvent() don't allow + the application that choice. + */ + case WM_SYSCOMMAND: { + if ((wParam&0xFFF0)==SC_SCREENSAVE || + (wParam&0xFFF0)==SC_MONITORPOWER) + return(0); + } + /* Fall through to default processing */ + +#endif /* SC_SCREENSAVE || SC_MONITORPOWER */ + + default: { + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.hwnd = hwnd; + wmmsg.msg = msg; + wmmsg.wParam = wParam; + wmmsg.lParam = lParam; + posted = SDL_PrivateSysWMEvent(&wmmsg); + + /* DJM: If the user isn't watching for private + messages in her SDL event loop, then pass it + along to any win32 specific window proc. + */ + } else if (userWindowProc) { + return CallWindowProc(userWindowProc, hwnd, msg, wParam, lParam); + } + } + break; + } + return(DefWindowProc(hwnd, msg, wParam, lParam)); +} + +/* This function checks the windows message queue and DirectInput and returns + 1 if there was input, 0 if there was no input, or -1 if the application has + posted a quit message. +*/ +static int DX5_CheckInput(_THIS, int timeout, BOOL processInput) +{ + MSG msg; + int i; + HRESULT result; + DWORD event; + + /* Check the normal windows queue (highest preference) */ + posted = 0; + while ( ! posted && + PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + } + if ( posted ) { + return(1); + } + + /* Pump the DirectInput flow */ + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + result = IDirectInputDevice2_Poll(SDL_DIdev[i]); + if ( (result == DIERR_INPUTLOST) || + (result == DIERR_NOTACQUIRED) ) { + if ( SDL_strcmp(inputs[i].name, "mouse") == 0 ) { + mouse_lost = 1; + } + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + IDirectInputDevice2_Poll(SDL_DIdev[i]); + } + } + } + } + + /* Wait for messages and input events */ + event = MsgWaitForMultipleObjects(SDL_DIndev, SDL_DIevt, FALSE, + timeout, QS_ALLEVENTS); + if ((event >= WAIT_OBJECT_0) && (event < (WAIT_OBJECT_0+SDL_DIndev))) { + DWORD numevents; + static DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; + + event -= WAIT_OBJECT_0; + numevents = INPUT_QSIZE; + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + if ( (result == DIERR_INPUTLOST) || + (result == DIERR_NOTACQUIRED) ) { + if ( SDL_strcmp(inputs[event].name, "mouse") == 0 ) { + mouse_lost = 1; + } + IDirectInputDevice2_Acquire(SDL_DIdev[event]); + result = IDirectInputDevice2_GetDeviceData( + SDL_DIdev[event], sizeof(DIDEVICEOBJECTDATA), + evtbuf, &numevents, 0); + } + /* Handle the events */ + if ( result == DI_OK && processInput ) { + /* Note: This can post multiple events to event queue + */ + (*SDL_DIfun[event])((int)numevents, evtbuf); + return(1); + } + } + if ( event != WAIT_TIMEOUT ) { + /* Maybe there was a windows message? */ + if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ) { + if ( GetMessage(&msg, NULL, 0, 0) > 0 ) { + DispatchMessage(&msg); + } else { + return(-1); + } + return(1); + } + } + return(0); +} + +/* Change cooperative level based on whether or not we are fullscreen */ +void DX5_DInputReset(_THIS, int fullscreen) +{ + DWORD level; + int i; + HRESULT result; + HWND topwnd; + + for ( i=0; i<MAX_INPUTS; ++i ) { + if ( SDL_DIdev[i] != NULL ) { + if ( fullscreen ) { + level = inputs[i].raw_level; + } else { + level = inputs[i].win_level; + } + IDirectInputDevice2_Unacquire(SDL_DIdev[i]); + topwnd = GetTopLevelParent(SDL_Window); + result = IDirectInputDevice2_SetCooperativeLevel( + SDL_DIdev[i], topwnd, level); + IDirectInputDevice2_Acquire(SDL_DIdev[i]); + if ( result != DI_OK ) { + SetDIerror( + "DirectInputDevice::SetCooperativeLevel", result); + } + } + } + mouse_lost = 1; + + /* Flush pending input */ + DX5_CheckInput(this, 0, FALSE); +} + +void DX5_PumpEvents(_THIS) +{ + /* Wait for messages and DirectInput */ + while ( DX5_CheckInput(this, 0, TRUE) > 0 ) { + /* Loop and check again */; + } +} + +void DX5_InitOSKeymap(_THIS) +{ +#ifndef DIK_PAUSE +#define DIK_PAUSE 0xC5 +#endif +#ifndef DIK_OEM_102 +#define DIK_OEM_102 0x56 /* < > | on UK/Germany keyboards */ +#endif + int i; + + /* Map the DIK scancodes to SDL keysyms */ + for ( i=0; i<SDL_arraysize(DIK_keymap); ++i ) + DIK_keymap[i] = 0; + + /* Defined DIK_* constants */ + DIK_keymap[DIK_ESCAPE] = SDLK_ESCAPE; + DIK_keymap[DIK_1] = SDLK_1; + DIK_keymap[DIK_2] = SDLK_2; + DIK_keymap[DIK_3] = SDLK_3; + DIK_keymap[DIK_4] = SDLK_4; + DIK_keymap[DIK_5] = SDLK_5; + DIK_keymap[DIK_6] = SDLK_6; + DIK_keymap[DIK_7] = SDLK_7; + DIK_keymap[DIK_8] = SDLK_8; + DIK_keymap[DIK_9] = SDLK_9; + DIK_keymap[DIK_0] = SDLK_0; + DIK_keymap[DIK_MINUS] = SDLK_MINUS; + DIK_keymap[DIK_EQUALS] = SDLK_EQUALS; + DIK_keymap[DIK_BACK] = SDLK_BACKSPACE; + DIK_keymap[DIK_TAB] = SDLK_TAB; + DIK_keymap[DIK_Q] = SDLK_q; + DIK_keymap[DIK_W] = SDLK_w; + DIK_keymap[DIK_E] = SDLK_e; + DIK_keymap[DIK_R] = SDLK_r; + DIK_keymap[DIK_T] = SDLK_t; + DIK_keymap[DIK_Y] = SDLK_y; + DIK_keymap[DIK_U] = SDLK_u; + DIK_keymap[DIK_I] = SDLK_i; + DIK_keymap[DIK_O] = SDLK_o; + DIK_keymap[DIK_P] = SDLK_p; + DIK_keymap[DIK_LBRACKET] = SDLK_LEFTBRACKET; + DIK_keymap[DIK_RBRACKET] = SDLK_RIGHTBRACKET; + DIK_keymap[DIK_RETURN] = SDLK_RETURN; + DIK_keymap[DIK_LCONTROL] = SDLK_LCTRL; + DIK_keymap[DIK_A] = SDLK_a; + DIK_keymap[DIK_S] = SDLK_s; + DIK_keymap[DIK_D] = SDLK_d; + DIK_keymap[DIK_F] = SDLK_f; + DIK_keymap[DIK_G] = SDLK_g; + DIK_keymap[DIK_H] = SDLK_h; + DIK_keymap[DIK_J] = SDLK_j; + DIK_keymap[DIK_K] = SDLK_k; + DIK_keymap[DIK_L] = SDLK_l; + DIK_keymap[DIK_SEMICOLON] = SDLK_SEMICOLON; + DIK_keymap[DIK_APOSTROPHE] = SDLK_QUOTE; + DIK_keymap[DIK_GRAVE] = SDLK_BACKQUOTE; + DIK_keymap[DIK_LSHIFT] = SDLK_LSHIFT; + DIK_keymap[DIK_BACKSLASH] = SDLK_BACKSLASH; + DIK_keymap[DIK_OEM_102] = SDLK_LESS; + DIK_keymap[DIK_Z] = SDLK_z; + DIK_keymap[DIK_X] = SDLK_x; + DIK_keymap[DIK_C] = SDLK_c; + DIK_keymap[DIK_V] = SDLK_v; + DIK_keymap[DIK_B] = SDLK_b; + DIK_keymap[DIK_N] = SDLK_n; + DIK_keymap[DIK_M] = SDLK_m; + DIK_keymap[DIK_COMMA] = SDLK_COMMA; + DIK_keymap[DIK_PERIOD] = SDLK_PERIOD; + DIK_keymap[DIK_SLASH] = SDLK_SLASH; + DIK_keymap[DIK_RSHIFT] = SDLK_RSHIFT; + DIK_keymap[DIK_MULTIPLY] = SDLK_KP_MULTIPLY; + DIK_keymap[DIK_LMENU] = SDLK_LALT; + DIK_keymap[DIK_SPACE] = SDLK_SPACE; + DIK_keymap[DIK_CAPITAL] = SDLK_CAPSLOCK; + DIK_keymap[DIK_F1] = SDLK_F1; + DIK_keymap[DIK_F2] = SDLK_F2; + DIK_keymap[DIK_F3] = SDLK_F3; + DIK_keymap[DIK_F4] = SDLK_F4; + DIK_keymap[DIK_F5] = SDLK_F5; + DIK_keymap[DIK_F6] = SDLK_F6; + DIK_keymap[DIK_F7] = SDLK_F7; + DIK_keymap[DIK_F8] = SDLK_F8; + DIK_keymap[DIK_F9] = SDLK_F9; + DIK_keymap[DIK_F10] = SDLK_F10; + DIK_keymap[DIK_NUMLOCK] = SDLK_NUMLOCK; + DIK_keymap[DIK_SCROLL] = SDLK_SCROLLOCK; + DIK_keymap[DIK_NUMPAD7] = SDLK_KP7; + DIK_keymap[DIK_NUMPAD8] = SDLK_KP8; + DIK_keymap[DIK_NUMPAD9] = SDLK_KP9; + DIK_keymap[DIK_SUBTRACT] = SDLK_KP_MINUS; + DIK_keymap[DIK_NUMPAD4] = SDLK_KP4; + DIK_keymap[DIK_NUMPAD5] = SDLK_KP5; + DIK_keymap[DIK_NUMPAD6] = SDLK_KP6; + DIK_keymap[DIK_ADD] = SDLK_KP_PLUS; + DIK_keymap[DIK_NUMPAD1] = SDLK_KP1; + DIK_keymap[DIK_NUMPAD2] = SDLK_KP2; + DIK_keymap[DIK_NUMPAD3] = SDLK_KP3; + DIK_keymap[DIK_NUMPAD0] = SDLK_KP0; + DIK_keymap[DIK_DECIMAL] = SDLK_KP_PERIOD; + DIK_keymap[DIK_F11] = SDLK_F11; + DIK_keymap[DIK_F12] = SDLK_F12; + + DIK_keymap[DIK_F13] = SDLK_F13; + DIK_keymap[DIK_F14] = SDLK_F14; + DIK_keymap[DIK_F15] = SDLK_F15; + + DIK_keymap[DIK_NUMPADEQUALS] = SDLK_KP_EQUALS; + DIK_keymap[DIK_NUMPADENTER] = SDLK_KP_ENTER; + DIK_keymap[DIK_RCONTROL] = SDLK_RCTRL; + DIK_keymap[DIK_DIVIDE] = SDLK_KP_DIVIDE; + DIK_keymap[DIK_SYSRQ] = SDLK_PRINT; + DIK_keymap[DIK_RMENU] = SDLK_RALT; + DIK_keymap[DIK_PAUSE] = SDLK_PAUSE; + DIK_keymap[DIK_HOME] = SDLK_HOME; + DIK_keymap[DIK_UP] = SDLK_UP; + DIK_keymap[DIK_PRIOR] = SDLK_PAGEUP; + DIK_keymap[DIK_LEFT] = SDLK_LEFT; + DIK_keymap[DIK_RIGHT] = SDLK_RIGHT; + DIK_keymap[DIK_END] = SDLK_END; + DIK_keymap[DIK_DOWN] = SDLK_DOWN; + DIK_keymap[DIK_NEXT] = SDLK_PAGEDOWN; + DIK_keymap[DIK_INSERT] = SDLK_INSERT; + DIK_keymap[DIK_DELETE] = SDLK_DELETE; + DIK_keymap[DIK_LWIN] = SDLK_LMETA; + DIK_keymap[DIK_RWIN] = SDLK_RMETA; + DIK_keymap[DIK_APPS] = SDLK_MENU; +} + +static SDL_keysym *TranslateKey(UINT scancode, SDL_keysym *keysym, int pressed) +{ + /* Set the keysym information */ + keysym->scancode = (unsigned char)scancode; + keysym->sym = DIK_keymap[scancode]; + keysym->mod = KMOD_NONE; + keysym->unicode = 0; + if ( pressed && SDL_TranslateUNICODE ) { + UINT vkey; +#ifndef NO_GETKEYBOARDSTATE + BYTE keystate[256]; + Uint16 wchars[2]; +#endif + + vkey = MapVirtualKey(scancode, 1); +#ifdef NO_GETKEYBOARDSTATE + /* Uh oh, better hope the vkey is close enough.. */ + keysym->unicode = vkey; +#else + GetKeyboardState(keystate); + /* Numlock isn't taken into account in ToUnicode, + * so we handle it as a special case here */ + if ((keystate[VK_NUMLOCK] & 1) && vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) + { + keysym->unicode = vkey - VK_NUMPAD0 + '0'; + } + else if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } +#endif /* NO_GETKEYBOARDSTATE */ + } + return(keysym); +} + +int DX5_CreateWindow(_THIS) +{ + char *windowid = SDL_getenv("SDL_WINDOWID"); + int i; + + /* Clear out DirectInput variables in case we fail */ + for ( i=0; i<MAX_INPUTS; ++i ) { + SDL_DIdev[i] = NULL; + SDL_DIevt[i] = NULL; + SDL_DIfun[i] = NULL; + } + + SDL_RegisterApp(NULL, 0, 0); + + SDL_windowid = (windowid != NULL); + if ( SDL_windowid ) { + SDL_Window = (HWND)((size_t)SDL_strtoull(windowid, NULL, 0)); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't get user specified window"); + return(-1); + } + + /* DJM: we want all event's for the user specified + window to be handled by SDL. + */ + userWindowProc = (WNDPROCTYPE)GetWindowLongPtr(SDL_Window, GWLP_WNDPROC); + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)WinMessage); + } else { + SDL_Window = CreateWindow(SDL_Appname, SDL_Appname, + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX), + CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, SDL_Instance, NULL); + if ( SDL_Window == NULL ) { + SDL_SetError("Couldn't create window"); + return(-1); + } + ShowWindow(SDL_Window, SW_HIDE); + } + + /* Initialize DirectInput */ + if ( DX5_DInputInit(this) < 0 ) { + return(-1); + } + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* Ready to roll */ + return(0); +} + +void DX5_DestroyWindow(_THIS) +{ + /* Close down DirectInput */ + DX5_DInputQuit(this); + + /* Destroy our window */ + if ( SDL_windowid ) { + SetWindowLongPtr(SDL_Window, GWLP_WNDPROC, (LONG_PTR)userWindowProc); + } else { + DestroyWindow(SDL_Window); + } + SDL_UnregisterApp(); + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); +} diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h b/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h new file mode 100644 index 0000000..28e1b6c --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5events_c.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "../wincommon/SDL_lowvideo.h" + +/* Variables and functions exported by SDL_dx5events.c to other parts + of the native video subsystem (SDL_dx5video.c) +*/ +extern LONG + DX5_HandleMessage(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern int DX5_CreateWindow(_THIS); +extern void DX5_DestroyWindow(_THIS); + +extern void DX5_PumpEvents(_THIS); +extern void DX5_InitOSKeymap(_THIS); +extern void DX5_DInputReset(_THIS, int fullscreen); + diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5video.c b/3rdparty/SDL/src/video/windx5/SDL_dx5video.c new file mode 100644 index 0000000..f80ca97 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5video.c @@ -0,0 +1,2537 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "directx.h" + +/* Not yet in the mingw32 cross-compile headers */ +#ifndef CDS_FULLSCREEN +#define CDS_FULLSCREEN 4 +#endif + +#include "SDL_timer.h" +#include "SDL_events.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../SDL_blit.h" +#include "../SDL_pixels_c.h" +#include "SDL_dx5video.h" +#include "../wincommon/SDL_syswm_c.h" +#include "../wincommon/SDL_sysmouse_c.h" +#include "SDL_dx5events_c.h" +#include "SDL_dx5yuv_c.h" +#include "../wincommon/SDL_wingl_c.h" + +#ifdef _WIN32_WCE +#define NO_CHANGEDISPLAYSETTINGS +#endif +#ifndef WS_MAXIMIZE +#define WS_MAXIMIZE 0 +#endif +#ifndef SWP_NOCOPYBITS +#define SWP_NOCOPYBITS 0 +#endif +#ifndef PC_NOCOLLAPSE +#define PC_NOCOLLAPSE 0 +#endif + + +/* DirectX function pointers for video and events */ +HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); +HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); + +/* This is the rect EnumModes2 uses */ +struct DX5EnumRect { + SDL_Rect r; + int refreshRate; + struct DX5EnumRect* next; +}; +static struct DX5EnumRect *enumlists[NUM_MODELISTS]; + +/* + * Experimentally determined values for c_cfDI* constants used in DirectX 5.0 + */ + +/* Keyboard */ + +static DIOBJECTDATAFORMAT KBD_fmt[] = { + { &GUID_Key, 0, 0x8000000C, 0x00000000 }, + { &GUID_Key, 1, 0x8000010C, 0x00000000 }, + { &GUID_Key, 2, 0x8000020C, 0x00000000 }, + { &GUID_Key, 3, 0x8000030C, 0x00000000 }, + { &GUID_Key, 4, 0x8000040C, 0x00000000 }, + { &GUID_Key, 5, 0x8000050C, 0x00000000 }, + { &GUID_Key, 6, 0x8000060C, 0x00000000 }, + { &GUID_Key, 7, 0x8000070C, 0x00000000 }, + { &GUID_Key, 8, 0x8000080C, 0x00000000 }, + { &GUID_Key, 9, 0x8000090C, 0x00000000 }, + { &GUID_Key, 10, 0x80000A0C, 0x00000000 }, + { &GUID_Key, 11, 0x80000B0C, 0x00000000 }, + { &GUID_Key, 12, 0x80000C0C, 0x00000000 }, + { &GUID_Key, 13, 0x80000D0C, 0x00000000 }, + { &GUID_Key, 14, 0x80000E0C, 0x00000000 }, + { &GUID_Key, 15, 0x80000F0C, 0x00000000 }, + { &GUID_Key, 16, 0x8000100C, 0x00000000 }, + { &GUID_Key, 17, 0x8000110C, 0x00000000 }, + { &GUID_Key, 18, 0x8000120C, 0x00000000 }, + { &GUID_Key, 19, 0x8000130C, 0x00000000 }, + { &GUID_Key, 20, 0x8000140C, 0x00000000 }, + { &GUID_Key, 21, 0x8000150C, 0x00000000 }, + { &GUID_Key, 22, 0x8000160C, 0x00000000 }, + { &GUID_Key, 23, 0x8000170C, 0x00000000 }, + { &GUID_Key, 24, 0x8000180C, 0x00000000 }, + { &GUID_Key, 25, 0x8000190C, 0x00000000 }, + { &GUID_Key, 26, 0x80001A0C, 0x00000000 }, + { &GUID_Key, 27, 0x80001B0C, 0x00000000 }, + { &GUID_Key, 28, 0x80001C0C, 0x00000000 }, + { &GUID_Key, 29, 0x80001D0C, 0x00000000 }, + { &GUID_Key, 30, 0x80001E0C, 0x00000000 }, + { &GUID_Key, 31, 0x80001F0C, 0x00000000 }, + { &GUID_Key, 32, 0x8000200C, 0x00000000 }, + { &GUID_Key, 33, 0x8000210C, 0x00000000 }, + { &GUID_Key, 34, 0x8000220C, 0x00000000 }, + { &GUID_Key, 35, 0x8000230C, 0x00000000 }, + { &GUID_Key, 36, 0x8000240C, 0x00000000 }, + { &GUID_Key, 37, 0x8000250C, 0x00000000 }, + { &GUID_Key, 38, 0x8000260C, 0x00000000 }, + { &GUID_Key, 39, 0x8000270C, 0x00000000 }, + { &GUID_Key, 40, 0x8000280C, 0x00000000 }, + { &GUID_Key, 41, 0x8000290C, 0x00000000 }, + { &GUID_Key, 42, 0x80002A0C, 0x00000000 }, + { &GUID_Key, 43, 0x80002B0C, 0x00000000 }, + { &GUID_Key, 44, 0x80002C0C, 0x00000000 }, + { &GUID_Key, 45, 0x80002D0C, 0x00000000 }, + { &GUID_Key, 46, 0x80002E0C, 0x00000000 }, + { &GUID_Key, 47, 0x80002F0C, 0x00000000 }, + { &GUID_Key, 48, 0x8000300C, 0x00000000 }, + { &GUID_Key, 49, 0x8000310C, 0x00000000 }, + { &GUID_Key, 50, 0x8000320C, 0x00000000 }, + { &GUID_Key, 51, 0x8000330C, 0x00000000 }, + { &GUID_Key, 52, 0x8000340C, 0x00000000 }, + { &GUID_Key, 53, 0x8000350C, 0x00000000 }, + { &GUID_Key, 54, 0x8000360C, 0x00000000 }, + { &GUID_Key, 55, 0x8000370C, 0x00000000 }, + { &GUID_Key, 56, 0x8000380C, 0x00000000 }, + { &GUID_Key, 57, 0x8000390C, 0x00000000 }, + { &GUID_Key, 58, 0x80003A0C, 0x00000000 }, + { &GUID_Key, 59, 0x80003B0C, 0x00000000 }, + { &GUID_Key, 60, 0x80003C0C, 0x00000000 }, + { &GUID_Key, 61, 0x80003D0C, 0x00000000 }, + { &GUID_Key, 62, 0x80003E0C, 0x00000000 }, + { &GUID_Key, 63, 0x80003F0C, 0x00000000 }, + { &GUID_Key, 64, 0x8000400C, 0x00000000 }, + { &GUID_Key, 65, 0x8000410C, 0x00000000 }, + { &GUID_Key, 66, 0x8000420C, 0x00000000 }, + { &GUID_Key, 67, 0x8000430C, 0x00000000 }, + { &GUID_Key, 68, 0x8000440C, 0x00000000 }, + { &GUID_Key, 69, 0x8000450C, 0x00000000 }, + { &GUID_Key, 70, 0x8000460C, 0x00000000 }, + { &GUID_Key, 71, 0x8000470C, 0x00000000 }, + { &GUID_Key, 72, 0x8000480C, 0x00000000 }, + { &GUID_Key, 73, 0x8000490C, 0x00000000 }, + { &GUID_Key, 74, 0x80004A0C, 0x00000000 }, + { &GUID_Key, 75, 0x80004B0C, 0x00000000 }, + { &GUID_Key, 76, 0x80004C0C, 0x00000000 }, + { &GUID_Key, 77, 0x80004D0C, 0x00000000 }, + { &GUID_Key, 78, 0x80004E0C, 0x00000000 }, + { &GUID_Key, 79, 0x80004F0C, 0x00000000 }, + { &GUID_Key, 80, 0x8000500C, 0x00000000 }, + { &GUID_Key, 81, 0x8000510C, 0x00000000 }, + { &GUID_Key, 82, 0x8000520C, 0x00000000 }, + { &GUID_Key, 83, 0x8000530C, 0x00000000 }, + { &GUID_Key, 84, 0x8000540C, 0x00000000 }, + { &GUID_Key, 85, 0x8000550C, 0x00000000 }, + { &GUID_Key, 86, 0x8000560C, 0x00000000 }, + { &GUID_Key, 87, 0x8000570C, 0x00000000 }, + { &GUID_Key, 88, 0x8000580C, 0x00000000 }, + { &GUID_Key, 89, 0x8000590C, 0x00000000 }, + { &GUID_Key, 90, 0x80005A0C, 0x00000000 }, + { &GUID_Key, 91, 0x80005B0C, 0x00000000 }, + { &GUID_Key, 92, 0x80005C0C, 0x00000000 }, + { &GUID_Key, 93, 0x80005D0C, 0x00000000 }, + { &GUID_Key, 94, 0x80005E0C, 0x00000000 }, + { &GUID_Key, 95, 0x80005F0C, 0x00000000 }, + { &GUID_Key, 96, 0x8000600C, 0x00000000 }, + { &GUID_Key, 97, 0x8000610C, 0x00000000 }, + { &GUID_Key, 98, 0x8000620C, 0x00000000 }, + { &GUID_Key, 99, 0x8000630C, 0x00000000 }, + { &GUID_Key, 100, 0x8000640C, 0x00000000 }, + { &GUID_Key, 101, 0x8000650C, 0x00000000 }, + { &GUID_Key, 102, 0x8000660C, 0x00000000 }, + { &GUID_Key, 103, 0x8000670C, 0x00000000 }, + { &GUID_Key, 104, 0x8000680C, 0x00000000 }, + { &GUID_Key, 105, 0x8000690C, 0x00000000 }, + { &GUID_Key, 106, 0x80006A0C, 0x00000000 }, + { &GUID_Key, 107, 0x80006B0C, 0x00000000 }, + { &GUID_Key, 108, 0x80006C0C, 0x00000000 }, + { &GUID_Key, 109, 0x80006D0C, 0x00000000 }, + { &GUID_Key, 110, 0x80006E0C, 0x00000000 }, + { &GUID_Key, 111, 0x80006F0C, 0x00000000 }, + { &GUID_Key, 112, 0x8000700C, 0x00000000 }, + { &GUID_Key, 113, 0x8000710C, 0x00000000 }, + { &GUID_Key, 114, 0x8000720C, 0x00000000 }, + { &GUID_Key, 115, 0x8000730C, 0x00000000 }, + { &GUID_Key, 116, 0x8000740C, 0x00000000 }, + { &GUID_Key, 117, 0x8000750C, 0x00000000 }, + { &GUID_Key, 118, 0x8000760C, 0x00000000 }, + { &GUID_Key, 119, 0x8000770C, 0x00000000 }, + { &GUID_Key, 120, 0x8000780C, 0x00000000 }, + { &GUID_Key, 121, 0x8000790C, 0x00000000 }, + { &GUID_Key, 122, 0x80007A0C, 0x00000000 }, + { &GUID_Key, 123, 0x80007B0C, 0x00000000 }, + { &GUID_Key, 124, 0x80007C0C, 0x00000000 }, + { &GUID_Key, 125, 0x80007D0C, 0x00000000 }, + { &GUID_Key, 126, 0x80007E0C, 0x00000000 }, + { &GUID_Key, 127, 0x80007F0C, 0x00000000 }, + { &GUID_Key, 128, 0x8000800C, 0x00000000 }, + { &GUID_Key, 129, 0x8000810C, 0x00000000 }, + { &GUID_Key, 130, 0x8000820C, 0x00000000 }, + { &GUID_Key, 131, 0x8000830C, 0x00000000 }, + { &GUID_Key, 132, 0x8000840C, 0x00000000 }, + { &GUID_Key, 133, 0x8000850C, 0x00000000 }, + { &GUID_Key, 134, 0x8000860C, 0x00000000 }, + { &GUID_Key, 135, 0x8000870C, 0x00000000 }, + { &GUID_Key, 136, 0x8000880C, 0x00000000 }, + { &GUID_Key, 137, 0x8000890C, 0x00000000 }, + { &GUID_Key, 138, 0x80008A0C, 0x00000000 }, + { &GUID_Key, 139, 0x80008B0C, 0x00000000 }, + { &GUID_Key, 140, 0x80008C0C, 0x00000000 }, + { &GUID_Key, 141, 0x80008D0C, 0x00000000 }, + { &GUID_Key, 142, 0x80008E0C, 0x00000000 }, + { &GUID_Key, 143, 0x80008F0C, 0x00000000 }, + { &GUID_Key, 144, 0x8000900C, 0x00000000 }, + { &GUID_Key, 145, 0x8000910C, 0x00000000 }, + { &GUID_Key, 146, 0x8000920C, 0x00000000 }, + { &GUID_Key, 147, 0x8000930C, 0x00000000 }, + { &GUID_Key, 148, 0x8000940C, 0x00000000 }, + { &GUID_Key, 149, 0x8000950C, 0x00000000 }, + { &GUID_Key, 150, 0x8000960C, 0x00000000 }, + { &GUID_Key, 151, 0x8000970C, 0x00000000 }, + { &GUID_Key, 152, 0x8000980C, 0x00000000 }, + { &GUID_Key, 153, 0x8000990C, 0x00000000 }, + { &GUID_Key, 154, 0x80009A0C, 0x00000000 }, + { &GUID_Key, 155, 0x80009B0C, 0x00000000 }, + { &GUID_Key, 156, 0x80009C0C, 0x00000000 }, + { &GUID_Key, 157, 0x80009D0C, 0x00000000 }, + { &GUID_Key, 158, 0x80009E0C, 0x00000000 }, + { &GUID_Key, 159, 0x80009F0C, 0x00000000 }, + { &GUID_Key, 160, 0x8000A00C, 0x00000000 }, + { &GUID_Key, 161, 0x8000A10C, 0x00000000 }, + { &GUID_Key, 162, 0x8000A20C, 0x00000000 }, + { &GUID_Key, 163, 0x8000A30C, 0x00000000 }, + { &GUID_Key, 164, 0x8000A40C, 0x00000000 }, + { &GUID_Key, 165, 0x8000A50C, 0x00000000 }, + { &GUID_Key, 166, 0x8000A60C, 0x00000000 }, + { &GUID_Key, 167, 0x8000A70C, 0x00000000 }, + { &GUID_Key, 168, 0x8000A80C, 0x00000000 }, + { &GUID_Key, 169, 0x8000A90C, 0x00000000 }, + { &GUID_Key, 170, 0x8000AA0C, 0x00000000 }, + { &GUID_Key, 171, 0x8000AB0C, 0x00000000 }, + { &GUID_Key, 172, 0x8000AC0C, 0x00000000 }, + { &GUID_Key, 173, 0x8000AD0C, 0x00000000 }, + { &GUID_Key, 174, 0x8000AE0C, 0x00000000 }, + { &GUID_Key, 175, 0x8000AF0C, 0x00000000 }, + { &GUID_Key, 176, 0x8000B00C, 0x00000000 }, + { &GUID_Key, 177, 0x8000B10C, 0x00000000 }, + { &GUID_Key, 178, 0x8000B20C, 0x00000000 }, + { &GUID_Key, 179, 0x8000B30C, 0x00000000 }, + { &GUID_Key, 180, 0x8000B40C, 0x00000000 }, + { &GUID_Key, 181, 0x8000B50C, 0x00000000 }, + { &GUID_Key, 182, 0x8000B60C, 0x00000000 }, + { &GUID_Key, 183, 0x8000B70C, 0x00000000 }, + { &GUID_Key, 184, 0x8000B80C, 0x00000000 }, + { &GUID_Key, 185, 0x8000B90C, 0x00000000 }, + { &GUID_Key, 186, 0x8000BA0C, 0x00000000 }, + { &GUID_Key, 187, 0x8000BB0C, 0x00000000 }, + { &GUID_Key, 188, 0x8000BC0C, 0x00000000 }, + { &GUID_Key, 189, 0x8000BD0C, 0x00000000 }, + { &GUID_Key, 190, 0x8000BE0C, 0x00000000 }, + { &GUID_Key, 191, 0x8000BF0C, 0x00000000 }, + { &GUID_Key, 192, 0x8000C00C, 0x00000000 }, + { &GUID_Key, 193, 0x8000C10C, 0x00000000 }, + { &GUID_Key, 194, 0x8000C20C, 0x00000000 }, + { &GUID_Key, 195, 0x8000C30C, 0x00000000 }, + { &GUID_Key, 196, 0x8000C40C, 0x00000000 }, + { &GUID_Key, 197, 0x8000C50C, 0x00000000 }, + { &GUID_Key, 198, 0x8000C60C, 0x00000000 }, + { &GUID_Key, 199, 0x8000C70C, 0x00000000 }, + { &GUID_Key, 200, 0x8000C80C, 0x00000000 }, + { &GUID_Key, 201, 0x8000C90C, 0x00000000 }, + { &GUID_Key, 202, 0x8000CA0C, 0x00000000 }, + { &GUID_Key, 203, 0x8000CB0C, 0x00000000 }, + { &GUID_Key, 204, 0x8000CC0C, 0x00000000 }, + { &GUID_Key, 205, 0x8000CD0C, 0x00000000 }, + { &GUID_Key, 206, 0x8000CE0C, 0x00000000 }, + { &GUID_Key, 207, 0x8000CF0C, 0x00000000 }, + { &GUID_Key, 208, 0x8000D00C, 0x00000000 }, + { &GUID_Key, 209, 0x8000D10C, 0x00000000 }, + { &GUID_Key, 210, 0x8000D20C, 0x00000000 }, + { &GUID_Key, 211, 0x8000D30C, 0x00000000 }, + { &GUID_Key, 212, 0x8000D40C, 0x00000000 }, + { &GUID_Key, 213, 0x8000D50C, 0x00000000 }, + { &GUID_Key, 214, 0x8000D60C, 0x00000000 }, + { &GUID_Key, 215, 0x8000D70C, 0x00000000 }, + { &GUID_Key, 216, 0x8000D80C, 0x00000000 }, + { &GUID_Key, 217, 0x8000D90C, 0x00000000 }, + { &GUID_Key, 218, 0x8000DA0C, 0x00000000 }, + { &GUID_Key, 219, 0x8000DB0C, 0x00000000 }, + { &GUID_Key, 220, 0x8000DC0C, 0x00000000 }, + { &GUID_Key, 221, 0x8000DD0C, 0x00000000 }, + { &GUID_Key, 222, 0x8000DE0C, 0x00000000 }, + { &GUID_Key, 223, 0x8000DF0C, 0x00000000 }, + { &GUID_Key, 224, 0x8000E00C, 0x00000000 }, + { &GUID_Key, 225, 0x8000E10C, 0x00000000 }, + { &GUID_Key, 226, 0x8000E20C, 0x00000000 }, + { &GUID_Key, 227, 0x8000E30C, 0x00000000 }, + { &GUID_Key, 228, 0x8000E40C, 0x00000000 }, + { &GUID_Key, 229, 0x8000E50C, 0x00000000 }, + { &GUID_Key, 230, 0x8000E60C, 0x00000000 }, + { &GUID_Key, 231, 0x8000E70C, 0x00000000 }, + { &GUID_Key, 232, 0x8000E80C, 0x00000000 }, + { &GUID_Key, 233, 0x8000E90C, 0x00000000 }, + { &GUID_Key, 234, 0x8000EA0C, 0x00000000 }, + { &GUID_Key, 235, 0x8000EB0C, 0x00000000 }, + { &GUID_Key, 236, 0x8000EC0C, 0x00000000 }, + { &GUID_Key, 237, 0x8000ED0C, 0x00000000 }, + { &GUID_Key, 238, 0x8000EE0C, 0x00000000 }, + { &GUID_Key, 239, 0x8000EF0C, 0x00000000 }, + { &GUID_Key, 240, 0x8000F00C, 0x00000000 }, + { &GUID_Key, 241, 0x8000F10C, 0x00000000 }, + { &GUID_Key, 242, 0x8000F20C, 0x00000000 }, + { &GUID_Key, 243, 0x8000F30C, 0x00000000 }, + { &GUID_Key, 244, 0x8000F40C, 0x00000000 }, + { &GUID_Key, 245, 0x8000F50C, 0x00000000 }, + { &GUID_Key, 246, 0x8000F60C, 0x00000000 }, + { &GUID_Key, 247, 0x8000F70C, 0x00000000 }, + { &GUID_Key, 248, 0x8000F80C, 0x00000000 }, + { &GUID_Key, 249, 0x8000F90C, 0x00000000 }, + { &GUID_Key, 250, 0x8000FA0C, 0x00000000 }, + { &GUID_Key, 251, 0x8000FB0C, 0x00000000 }, + { &GUID_Key, 252, 0x8000FC0C, 0x00000000 }, + { &GUID_Key, 253, 0x8000FD0C, 0x00000000 }, + { &GUID_Key, 254, 0x8000FE0C, 0x00000000 }, + { &GUID_Key, 255, 0x8000FF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIKeyboard = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 256, 256, KBD_fmt }; + + +/* Mouse */ + +static DIOBJECTDATAFORMAT PTR_fmt[] = { + { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 }, + { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 }, + { NULL, 12, 0x00FFFF0C, 0x00000000 }, + { NULL, 13, 0x00FFFF0C, 0x00000000 }, + { NULL, 14, 0x80FFFF0C, 0x00000000 }, + { NULL, 15, 0x80FFFF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIMouse = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 16, 7, PTR_fmt }; + +static DIOBJECTDATAFORMAT PTR2_fmt[] = { + { &GUID_XAxis, 0, 0x00FFFF03, 0x00000000 }, + { &GUID_YAxis, 4, 0x00FFFF03, 0x00000000 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000000 }, + { NULL, 12, 0x00FFFF0C, 0x00000000 }, + { NULL, 13, 0x00FFFF0C, 0x00000000 }, + { NULL, 14, 0x80FFFF0C, 0x00000000 }, + { NULL, 15, 0x80FFFF0C, 0x00000000 }, + { NULL, 16, 0x80FFFF0C, 0x00000000 }, + { NULL, 17, 0x80FFFF0C, 0x00000000 }, + { NULL, 18, 0x80FFFF0C, 0x00000000 }, + { NULL, 19, 0x80FFFF0C, 0x00000000 } +}; + +const DIDATAFORMAT c_dfDIMouse2 = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000002, 20, 11, PTR2_fmt }; + + +/* Joystick */ + +static DIOBJECTDATAFORMAT JOY_fmt[] = { + { &GUID_XAxis, 0, 0x80FFFF03, 0x00000100 }, + { &GUID_YAxis, 4, 0x80FFFF03, 0x00000100 }, + { &GUID_ZAxis, 8, 0x80FFFF03, 0x00000100 }, + { &GUID_RxAxis, 12, 0x80FFFF03, 0x00000100 }, + { &GUID_RyAxis, 16, 0x80FFFF03, 0x00000100 }, + { &GUID_RzAxis, 20, 0x80FFFF03, 0x00000100 }, + { &GUID_Slider, 24, 0x80FFFF03, 0x00000100 }, + { &GUID_Slider, 28, 0x80FFFF03, 0x00000100 }, + { &GUID_POV, 32, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 36, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 40, 0x80FFFF10, 0x00000000 }, + { &GUID_POV, 44, 0x80FFFF10, 0x00000000 }, + { NULL, 48, 0x80FFFF0C, 0x00000000 }, + { NULL, 49, 0x80FFFF0C, 0x00000000 }, + { NULL, 50, 0x80FFFF0C, 0x00000000 }, + { NULL, 51, 0x80FFFF0C, 0x00000000 }, + { NULL, 52, 0x80FFFF0C, 0x00000000 }, + { NULL, 53, 0x80FFFF0C, 0x00000000 }, + { NULL, 54, 0x80FFFF0C, 0x00000000 }, + { NULL, 55, 0x80FFFF0C, 0x00000000 }, + { NULL, 56, 0x80FFFF0C, 0x00000000 }, + { NULL, 57, 0x80FFFF0C, 0x00000000 }, + { NULL, 58, 0x80FFFF0C, 0x00000000 }, + { NULL, 59, 0x80FFFF0C, 0x00000000 }, + { NULL, 60, 0x80FFFF0C, 0x00000000 }, + { NULL, 61, 0x80FFFF0C, 0x00000000 }, + { NULL, 62, 0x80FFFF0C, 0x00000000 }, + { NULL, 63, 0x80FFFF0C, 0x00000000 }, + { NULL, 64, 0x80FFFF0C, 0x00000000 }, + { NULL, 65, 0x80FFFF0C, 0x00000000 }, + { NULL, 66, 0x80FFFF0C, 0x00000000 }, + { NULL, 67, 0x80FFFF0C, 0x00000000 }, + { NULL, 68, 0x80FFFF0C, 0x00000000 }, + { NULL, 69, 0x80FFFF0C, 0x00000000 }, + { NULL, 70, 0x80FFFF0C, 0x00000000 }, + { NULL, 71, 0x80FFFF0C, 0x00000000 }, + { NULL, 72, 0x80FFFF0C, 0x00000000 }, + { NULL, 73, 0x80FFFF0C, 0x00000000 }, + { NULL, 74, 0x80FFFF0C, 0x00000000 }, + { NULL, 75, 0x80FFFF0C, 0x00000000 }, + { NULL, 76, 0x80FFFF0C, 0x00000000 }, + { NULL, 77, 0x80FFFF0C, 0x00000000 }, + { NULL, 78, 0x80FFFF0C, 0x00000000 }, + { NULL, 79, 0x80FFFF0C, 0x00000000 }, +}; + +const DIDATAFORMAT c_dfDIJoystick = { sizeof(DIDATAFORMAT), sizeof(DIOBJECTDATAFORMAT), 0x00000001, 80, 44, JOY_fmt }; + + +/* Initialization/Query functions */ +static int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int DX5_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp); +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp); +static void DX5_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface); +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface); +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface); +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface); +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface); + +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, + LPDIRECTDRAWSURFACE3 requested, Uint32 flag); + +/* Windows message handling functions */ +static void DX5_Activate(_THIS, BOOL active, BOOL minimized); +static void DX5_RealizePalette(_THIS); +static void DX5_PaletteChanged(_THIS, HWND window); +static void DX5_WinPAINT(_THIS, HDC hdc); + +/* WinDIB driver functions for manipulating gamma ramps */ +extern int DIB_SetGammaRamp(_THIS, Uint16 *ramp); +extern int DIB_GetGammaRamp(_THIS, Uint16 *ramp); +extern void DIB_QuitGamma(_THIS); + +/* DX5 driver bootstrap functions */ + +static int DX5_Available(void) +{ + HINSTANCE DInputDLL; + HINSTANCE DDrawDLL; + int dinput_ok; + int ddraw_ok; + + /* Version check DINPUT.DLL and DDRAW.DLL (Is DirectX okay?) */ + dinput_ok = 0; + DInputDLL = LoadLibrary(TEXT("DINPUT.DLL")); + if ( DInputDLL != NULL ) { + dinput_ok = 1; + FreeLibrary(DInputDLL); + } + ddraw_ok = 0; + DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL")); + if ( DDrawDLL != NULL ) { + HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *); + LPDIRECTDRAW DDraw; + + /* Try to create a valid DirectDraw object */ + DDrawCreate = (void *)GetProcAddress(DDrawDLL, TEXT("DirectDrawCreate")); + if ( (DDrawCreate != NULL) + && !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) { + if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw, + NULL, DDSCL_NORMAL)) ) { + DDSURFACEDESC desc; + LPDIRECTDRAWSURFACE DDrawSurf; + LPDIRECTDRAWSURFACE3 DDrawSurf3; + + /* Try to create a DirectDrawSurface3 object */ + SDL_memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY; + if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc, + &DDrawSurf, NULL)) ) { + if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf, + &IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) { + /* Yay! */ + ddraw_ok = 1; + + /* Clean up.. */ + IDirectDrawSurface3_Release(DDrawSurf3); + } + IDirectDrawSurface_Release(DDrawSurf); + } + } + IDirectDraw_Release(DDraw); + } + FreeLibrary(DDrawDLL); + } + return(dinput_ok && ddraw_ok); +} + +/* Functions for loading the DirectX functions dynamically */ +static HINSTANCE DDrawDLL = NULL; +static HINSTANCE DInputDLL = NULL; + +static void DX5_Unload(void) +{ + if ( DDrawDLL != NULL ) { + FreeLibrary(DDrawDLL); + DDrawCreate = NULL; + DDrawDLL = NULL; + } + if ( DInputDLL != NULL ) { + FreeLibrary(DInputDLL); + DInputCreate = NULL; + DInputDLL = NULL; + } +} +static int DX5_Load(void) +{ + int status; + + DX5_Unload(); + DDrawDLL = LoadLibrary(TEXT("DDRAW.DLL")); + if ( DDrawDLL != NULL ) { + DDrawCreate = (void *)GetProcAddress(DDrawDLL, + TEXT("DirectDrawCreate")); + } + DInputDLL = LoadLibrary(TEXT("DINPUT.DLL")); + if ( DInputDLL != NULL ) { + DInputCreate = (void *)GetProcAddress(DInputDLL, + TEXT("DirectInputCreateA")); + } + if ( DDrawDLL && DDrawCreate && DInputDLL && DInputCreate ) { + status = 0; + } else { + DX5_Unload(); + status = -1; + } + return status; +} + +static void DX5_DeleteDevice(SDL_VideoDevice *this) +{ + /* Free DirectDraw object */ + if ( ddraw2 != NULL ) { + IDirectDraw2_Release(ddraw2); + } + DX5_Unload(); + if ( this ) { + if ( this->hidden ) { + SDL_free(this->hidden); + } + if ( this->gl_data ) { + SDL_free(this->gl_data); + } + SDL_free(this); + } +} + +static SDL_VideoDevice *DX5_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Load DirectX */ + if ( DX5_Load() < 0 ) { + return(NULL); + } + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + DX5_DeleteDevice(device); + return(NULL); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + + /* Set the function pointers */ + device->VideoInit = DX5_VideoInit; + device->ListModes = DX5_ListModes; + device->SetVideoMode = DX5_SetVideoMode; + device->UpdateMouse = WIN_UpdateMouse; + device->CreateYUVOverlay = DX5_CreateYUVOverlay; + device->SetColors = DX5_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = DX5_VideoQuit; + device->AllocHWSurface = DX5_AllocHWSurface; + device->CheckHWBlit = DX5_CheckHWBlit; + device->FillHWRect = DX5_FillHWRect; + device->SetHWColorKey = DX5_SetHWColorKey; + device->SetHWAlpha = DX5_SetHWAlpha; + device->LockHWSurface = DX5_LockHWSurface; + device->UnlockHWSurface = DX5_UnlockHWSurface; + device->FlipHWSurface = DX5_FlipHWSurface; + device->FreeHWSurface = DX5_FreeHWSurface; + device->SetGammaRamp = DX5_SetGammaRamp; + device->GetGammaRamp = DX5_GetGammaRamp; +#if SDL_VIDEO_OPENGL + device->GL_LoadLibrary = WIN_GL_LoadLibrary; + device->GL_GetProcAddress = WIN_GL_GetProcAddress; + device->GL_GetAttribute = WIN_GL_GetAttribute; + device->GL_MakeCurrent = WIN_GL_MakeCurrent; + device->GL_SwapBuffers = WIN_GL_SwapBuffers; +#endif + device->SetCaption = WIN_SetWMCaption; + device->SetIcon = WIN_SetWMIcon; + device->IconifyWindow = WIN_IconifyWindow; + device->GrabInput = WIN_GrabInput; + device->GetWMInfo = WIN_GetWMInfo; + device->FreeWMCursor = WIN_FreeWMCursor; + device->CreateWMCursor = WIN_CreateWMCursor; + device->ShowWMCursor = WIN_ShowWMCursor; + device->WarpWMCursor = WIN_WarpWMCursor; + device->CheckMouseMode = WIN_CheckMouseMode; + device->InitOSKeymap = DX5_InitOSKeymap; + device->PumpEvents = DX5_PumpEvents; + + /* Set up the windows message handling functions */ + WIN_Activate = DX5_Activate; + WIN_RealizePalette = DX5_RealizePalette; + WIN_PaletteChanged = DX5_PaletteChanged; + WIN_WinPAINT = DX5_WinPAINT; + HandleMessage = DX5_HandleMessage; + + device->free = DX5_DeleteDevice; + + /* We're finally ready */ + return device; +} + +VideoBootStrap DIRECTX_bootstrap = { + "directx", "Win95/98/2000 DirectX", + DX5_Available, DX5_CreateDevice +}; + +static int cmpmodes(const void *va, const void *vb) +{ + SDL_Rect *a = *(SDL_Rect **)va; + SDL_Rect *b = *(SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} + +static HRESULT WINAPI EnumModes2(DDSURFACEDESC *desc, VOID *udata) +{ + SDL_VideoDevice *this = (SDL_VideoDevice *)udata; + struct DX5EnumRect *enumrect; +#if defined(NONAMELESSUNION) + int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount; + int refreshRate = desc->u2.dwRefreshRate; +#else + int bpp = desc->ddpfPixelFormat.dwRGBBitCount; + int refreshRate = desc->dwRefreshRate; +#endif + int maxRefreshRate; + + if ( desc->dwWidth <= SDL_desktop_mode.dmPelsWidth && + desc->dwHeight <= SDL_desktop_mode.dmPelsHeight ) { + maxRefreshRate = SDL_desktop_mode.dmDisplayFrequency; + } else { + maxRefreshRate = 85; /* safe value? */ + } + + switch (bpp) { + case 8: + case 16: + case 24: + case 32: + bpp /= 8; --bpp; + if ( enumlists[bpp] && + enumlists[bpp]->r.w == (Uint16)desc->dwWidth && + enumlists[bpp]->r.h == (Uint16)desc->dwHeight ) { + if ( refreshRate > enumlists[bpp]->refreshRate && + refreshRate <= maxRefreshRate ) { + enumlists[bpp]->refreshRate = refreshRate; +#ifdef DDRAW_DEBUG + fprintf(stderr, "New refresh rate for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate); +#endif + } + break; + } + ++SDL_nummodes[bpp]; + enumrect = (struct DX5EnumRect*)SDL_malloc(sizeof(struct DX5EnumRect)); + if ( !enumrect ) { + SDL_OutOfMemory(); + return(DDENUMRET_CANCEL); + } + enumrect->refreshRate = refreshRate; + enumrect->r.x = 0; + enumrect->r.y = 0; + enumrect->r.w = (Uint16)desc->dwWidth; + enumrect->r.h = (Uint16)desc->dwHeight; + enumrect->next = enumlists[bpp]; + enumlists[bpp] = enumrect; +#ifdef DDRAW_DEBUG + fprintf(stderr, "New mode for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate); +#endif + break; + } + + return(DDENUMRET_OK); +} + +void SetDDerror(const char *function, int code) +{ + static char *error; + static char errbuf[1024]; + + errbuf[0] = 0; + switch (code) { + case DDERR_GENERIC: + error = "Undefined error!"; + break; + case DDERR_EXCEPTION: + error = "Exception encountered"; + break; + case DDERR_INVALIDOBJECT: + error = "Invalid object"; + break; + case DDERR_INVALIDPARAMS: + error = "Invalid parameters"; + break; + case DDERR_NOTFOUND: + error = "Object not found"; + break; + case DDERR_INVALIDRECT: + error = "Invalid rectangle"; + break; + case DDERR_INVALIDCAPS: + error = "Invalid caps member"; + break; + case DDERR_INVALIDPIXELFORMAT: + error = "Invalid pixel format"; + break; + case DDERR_OUTOFMEMORY: + error = "Out of memory"; + break; + case DDERR_OUTOFVIDEOMEMORY: + error = "Out of video memory"; + break; + case DDERR_SURFACEBUSY: + error = "Surface busy"; + break; + case DDERR_SURFACELOST: + error = "Surface was lost"; + break; + case DDERR_WASSTILLDRAWING: + error = "DirectDraw is still drawing"; + break; + case DDERR_INVALIDSURFACETYPE: + error = "Invalid surface type"; + break; + case DDERR_NOEXCLUSIVEMODE: + error = "Not in exclusive access mode"; + break; + case DDERR_NOPALETTEATTACHED: + error = "No palette attached"; + break; + case DDERR_NOPALETTEHW: + error = "No palette hardware"; + break; + case DDERR_NOT8BITCOLOR: + error = "Not 8-bit color"; + break; + case DDERR_EXCLUSIVEMODEALREADYSET: + error = "Exclusive mode was already set"; + break; + case DDERR_HWNDALREADYSET: + error = "Window handle already set"; + break; + case DDERR_HWNDSUBCLASSED: + error = "Window handle is subclassed"; + break; + case DDERR_NOBLTHW: + error = "No blit hardware"; + break; + case DDERR_IMPLICITLYCREATED: + error = "Surface was implicitly created"; + break; + case DDERR_INCOMPATIBLEPRIMARY: + error = "Incompatible primary surface"; + break; + case DDERR_NOCOOPERATIVELEVELSET: + error = "No cooperative level set"; + break; + case DDERR_NODIRECTDRAWHW: + error = "No DirectDraw hardware"; + break; + case DDERR_NOEMULATION: + error = "No emulation available"; + break; + case DDERR_NOFLIPHW: + error = "No flip hardware"; + break; + case DDERR_NOTFLIPPABLE: + error = "Surface not flippable"; + break; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + error = "Primary surface already exists"; + break; + case DDERR_UNSUPPORTEDMODE: + error = "Unsupported mode"; + break; + case DDERR_WRONGMODE: + error = "Surface created in different mode"; + break; + case DDERR_UNSUPPORTED: + error = "Operation not supported"; + break; + case E_NOINTERFACE: + error = "Interface not present"; + break; + default: + SDL_snprintf(errbuf, SDL_arraysize(errbuf), + "%s: Unknown DirectDraw error: 0x%x", + function, code); + break; + } + if ( ! errbuf[0] ) { + SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function, error); + } + SDL_SetError("%s", errbuf); + return; +} + + +static int DX5_UpdateVideoInfo(_THIS) +{ + /* This needs to be DDCAPS_DX5 for the DirectDraw2 interface */ +#if DIRECTDRAW_VERSION <= 0x300 +#error Your version of DirectX must be greater than or equal to 5.0 +#endif +#ifndef IDirectDrawGammaControl_SetGammaRamp + /*if gamma is undefined then we really have directx <= 0x500*/ + DDCAPS DDCaps; +#else + DDCAPS_DX5 DDCaps; +#endif + HRESULT result; + + /* Fill in our hardware acceleration capabilities */ + SDL_memset(&DDCaps, 0, sizeof(DDCaps)); + DDCaps.dwSize = sizeof(DDCaps); + result = IDirectDraw2_GetCaps(ddraw2, (DDCAPS *)&DDCaps, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::GetCaps", result); + return(-1); + } + this->info.hw_available = 1; + if ( (DDCaps.dwCaps & DDCAPS_BLT) == DDCAPS_BLT ) { + this->info.blit_hw = 1; + } + if ( ((DDCaps.dwCaps & DDCAPS_COLORKEY) == DDCAPS_COLORKEY) && + ((DDCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) == DDCKEYCAPS_SRCBLT) ) { + this->info.blit_hw_CC = 1; + } + if ( (DDCaps.dwCaps & DDCAPS_ALPHA) == DDCAPS_ALPHA ) { + /* This is only for alpha channel, and DirectX 6 + doesn't support 2D alpha blits yet, so set it 0 + */ + this->info.blit_hw_A = 0; + } + if ( (DDCaps.dwCaps & DDCAPS_CANBLTSYSMEM) == DDCAPS_CANBLTSYSMEM ) { + this->info.blit_sw = 1; + /* This isn't necessarily true, but the HEL will cover us */ + this->info.blit_sw_CC = this->info.blit_hw_CC; + this->info.blit_sw_A = this->info.blit_hw_A; + } + if ( (DDCaps.dwCaps & DDCAPS_BLTCOLORFILL) == DDCAPS_BLTCOLORFILL ) { + this->info.blit_fill = 1; + } + + /* Find out how much video memory is available */ + { DDSCAPS ddsCaps; + DWORD total_mem; + ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; + result = IDirectDraw2_GetAvailableVidMem(ddraw2, + &ddsCaps, &total_mem, NULL); + if ( result != DD_OK ) { + total_mem = DDCaps.dwVidMemTotal; + } + this->info.video_mem = total_mem/1024; + } + return(0); +} + +int DX5_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + HRESULT result; + LPDIRECTDRAW ddraw; + int i, j; + HDC hdc; + + /* Intialize everything */ + ddraw2 = NULL; + SDL_primary = NULL; + SDL_clipper = NULL; + SDL_palette = NULL; + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_modeindex[i] = 0; + } + colorchange_expected = 0; + + /* Create the window */ + if ( DX5_CreateWindow(this) < 0 ) { + return(-1); + } + +#if !SDL_AUDIO_DISABLED + DX5_SoundFocus(SDL_Window); +#endif + + /* Create the DirectDraw object */ + result = DDrawCreate(NULL, &ddraw, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawCreate", result); + return(-1); + } + result = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw2, + (LPVOID *)&ddraw2); + IDirectDraw_Release(ddraw); + if ( result != DD_OK ) { + SetDDerror("DirectDraw::QueryInterface", result); + return(-1); + } + + /* Determine the screen depth */ + hdc = GetDC(SDL_Window); + vformat->BitsPerPixel = GetDeviceCaps(hdc,PLANES) * + GetDeviceCaps(hdc,BITSPIXEL); + ReleaseDC(SDL_Window, hdc); + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Query for the desktop resolution */ + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode); + this->info.current_w = SDL_desktop_mode.dmPelsWidth; + this->info.current_h = SDL_desktop_mode.dmPelsHeight; +#endif + + /* Enumerate the available fullscreen modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) + enumlists[i] = NULL; + + result = IDirectDraw2_EnumDisplayModes(ddraw2,DDEDM_REFRESHRATES,NULL,this,EnumModes2); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::EnumDisplayModes", result); + return(-1); + } + for ( i=0; i<NUM_MODELISTS; ++i ) { + struct DX5EnumRect *rect; + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) { + SDL_modelist[i][j] = &rect->r; + } + SDL_modelist[i][j] = NULL; + + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* Fill in the video hardware capabilities */ + DX5_UpdateVideoInfo(this); + + return(0); +} + +SDL_Rect **DX5_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + int bpp; + + bpp = format->BitsPerPixel; + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* FIXME: No support for 1 bpp or 4 bpp formats */ + switch (bpp) { /* Does windows support other BPP? */ + case 8: + case 16: + case 24: + case 32: + bpp = (bpp/8)-1; + if ( SDL_nummodes[bpp] > 0 ) + return(SDL_modelist[bpp]); + /* Fall through */ + default: + return((SDL_Rect **)0); + } + } else { + if ( this->screen->format->BitsPerPixel == bpp ) { + return((SDL_Rect **)-1); + } else { + return((SDL_Rect **)0); + } + } +} + +/* Various screen update functions available */ +static void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects); +static void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); + +SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + SDL_Surface *video; + int prev_w = -1; + int prev_h = -1; + HRESULT result; + DWORD sharemode; + DWORD style; + const DWORD directstyle = + (WS_POPUP); + const DWORD windowstyle = + (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX); + const DWORD resizestyle = + (WS_THICKFRAME|WS_MAXIMIZEBOX); + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + + SDL_resizing = 1; +#ifdef DDRAW_DEBUG + fprintf(stderr, "Setting %dx%dx%d video mode\n", width, height, bpp); +#endif + /* Clean up any previous DirectDraw surfaces */ + if ( current->hwdata ) { + this->FreeHWSurface(this, current); + current->hwdata = NULL; + } + if ( SDL_primary != NULL ) { + IDirectDrawSurface3_Release(SDL_primary); + SDL_primary = NULL; + } + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Unset any previous OpenGL fullscreen mode */ + if ( (current->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == + (SDL_OPENGL|SDL_FULLSCREEN) ) { + ChangeDisplaySettings(NULL, 0); + } +#endif + + /* Clean up any GL context that may be hanging around */ + if ( current->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + + /* If we are setting a GL mode, use GDI, not DirectX (yuck) */ + if ( flags & SDL_OPENGL ) { + Uint32 Rmask, Gmask, Bmask; + + /* Recalculate the bitmasks if necessary */ + if ( bpp == current->format->BitsPerPixel ) { + video = current; + } else { + switch (bpp) { + case 15: + case 16: + if ( 0 /*DIB_SussScreenDepth() == 15*/ ) { + /* 5-5-5 */ + Rmask = 0x00007c00; + Gmask = 0x000003e0; + Bmask = 0x0000001f; + } else { + /* 5-6-5 */ + Rmask = 0x0000f800; + Gmask = 0x000007e0; + Bmask = 0x0000001f; + } + break; + case 24: + case 32: + /* GDI defined as 8-8-8 */ + Rmask = 0x00ff0000; + Gmask = 0x0000ff00; + Bmask = 0x000000ff; + break; + default: + Rmask = 0x00000000; + Gmask = 0x00000000; + Bmask = 0x00000000; + break; + } + video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, bpp, + Rmask, Gmask, Bmask, 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + } + + /* Fill in part of the video surface */ + prev_w = video->w; + prev_h = video->h; + video->flags = 0; /* Clear flags */ + video->w = width; + video->h = height; + video->pitch = SDL_CalculatePitch(video); + +#ifndef NO_CHANGEDISPLAYSETTINGS + /* Set fullscreen mode if appropriate. + Ugh, since our list of valid video modes comes from + the DirectX driver, we may not actually be able to + change to the desired resolution here. + FIXME: Should we do a closest match? + */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + DEVMODE settings; + BOOL changed; + + SDL_memset(&settings, 0, sizeof(DEVMODE)); + settings.dmSize = sizeof(DEVMODE); + settings.dmBitsPerPel = video->format->BitsPerPixel; + settings.dmPelsWidth = width; + settings.dmPelsHeight = height; + settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; + if ( width <= (int)SDL_desktop_mode.dmPelsWidth && + height <= (int)SDL_desktop_mode.dmPelsHeight ) { + settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency; + settings.dmFields |= DM_DISPLAYFREQUENCY; + } + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) { + settings.dmFields &= ~DM_DISPLAYFREQUENCY; + changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); + } + if ( changed ) { + video->flags |= SDL_FULLSCREEN; + SDL_fullscreen_mode = settings; + } + } +#endif /* !NO_CHANGEDISPLAYSETTINGS */ + + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( video->flags & SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + video->flags |= SDL_NOFRAME; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + video->flags |= SDL_RESIZABLE; + } + } +#if WS_MAXIMIZE + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Resize the window (copied from SDL WinDIB driver) */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { + RECT bounds; + int x, y; + HWND top; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( video->w != prev_w || video->h != prev_h ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW); + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+video->w; + bounds.bottom = SDL_windowY+video->h; + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( (flags & SDL_FULLSCREEN) ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + if ( flags & SDL_FULLSCREEN ) { + top = HWND_TOPMOST; + } else { + top = HWND_NOTOPMOST; + } + SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags); + if ( !(flags & SDL_FULLSCREEN) ) { + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + SetForegroundWindow(SDL_Window); + } + SDL_resizing = 0; + + /* Set up for OpenGL */ + if ( WIN_GL_SetupWindow(this) < 0 ) { + return(NULL); + } + video->flags |= SDL_OPENGL; + return(video); + } + + /* Set the appropriate window style */ + style = GetWindowLong(SDL_Window, GWL_STYLE); + style &= ~(resizestyle|WS_MAXIMIZE); + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + style &= ~windowstyle; + style |= directstyle; + } else { + if ( flags & SDL_NOFRAME ) { + style &= ~windowstyle; + style |= directstyle; + } else { + style &= ~directstyle; + style |= windowstyle; + if ( flags & SDL_RESIZABLE ) { + style |= resizestyle; + } + } +#if WS_MAXIMIZE + if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE; +#endif + } + /* DJM: Don't piss of anyone who has setup his own window */ + if ( !SDL_windowid ) + SetWindowLong(SDL_Window, GWL_STYLE, style); + + /* Set DirectDraw sharing mode.. exclusive when fullscreen */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + sharemode = DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT; + } else { + sharemode = DDSCL_NORMAL; + } + result = IDirectDraw2_SetCooperativeLevel(ddraw2,SDL_Window,sharemode); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::SetCooperativeLevel", result); + return(NULL); + } + + /* Set the display mode, if we are in fullscreen mode */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + RECT bounds; + struct DX5EnumRect *rect; + int maxRefreshRate; + + /* Cover up desktop during mode change */ + bounds.left = 0; + bounds.top = 0; + bounds.right = GetSystemMetrics(SM_CXSCREEN); + bounds.bottom = GetSystemMetrics(SM_CYSCREEN); + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + SetWindowPos(SDL_Window, HWND_TOPMOST, + bounds.left, bounds.top, + bounds.right - bounds.left, + bounds.bottom - bounds.top, SWP_NOCOPYBITS); + ShowWindow(SDL_Window, SW_SHOW); + while ( GetForegroundWindow() != SDL_Window ) { + SetForegroundWindow(SDL_Window); + SDL_Delay(100); + } + + /* find maximum monitor refresh rate for this resolution */ + /* Dmitry Yakimov ftech@tula.net */ + maxRefreshRate = 0; /* system default */ + for ( rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next ) { + if ( (width == rect->r.w) && (height == rect->r.h) ) { + maxRefreshRate = rect->refreshRate; + break; + } + } +#ifdef DDRAW_DEBUG + fprintf(stderr, "refresh rate = %d Hz\n", maxRefreshRate); +#endif + + result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, maxRefreshRate, 0); + if ( result != DD_OK ) { + result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0); + if ( result != DD_OK ) { + /* We couldn't set fullscreen mode, try window */ + return(DX5_SetVideoMode(this, current, width, height, bpp, flags & ~SDL_FULLSCREEN)); + } + } + DX5_DInputReset(this, 1); + } else { + DX5_DInputReset(this, 0); + } + DX5_UpdateVideoInfo(this); + + /* Create a primary DirectDraw surface */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = (DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY); + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* There's no windowed double-buffering */ + flags &= ~SDL_DOUBLEBUF; + } + if ( (flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP); + ddsd.dwBackBufferCount = 1; + } + result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); + if ( (result != DD_OK) && ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) ) { + ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX|DDSCAPS_FLIP); + ddsd.dwBackBufferCount = 0; + result = IDirectDraw2_CreateSurface(ddraw2, + &ddsd, &dd_surface1, NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface(PRIMARY)", result); + return(NULL); + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&SDL_primary); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + return(NULL); + } + IDirectDrawSurface_Release(dd_surface1); + + /* Get the format of the primary DirectDraw surface */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_PIXELFORMAT|DDSD_CAPS; + result = IDirectDrawSurface3_GetSurfaceDesc(SDL_primary, &ddsd); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::GetSurfaceDesc", result); + return(NULL); + } + if ( ! (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) ) { + SDL_SetError("Primary DDRAW surface is not RGB format"); + return(NULL); + } + + /* Free old palette and create a new one if we're in 8-bit mode */ + if ( SDL_palette != NULL ) { + IDirectDrawPalette_Release(SDL_palette); + SDL_palette = NULL; + } +#if defined(NONAMELESSUNION) + if ( ddsd.ddpfPixelFormat.u1.dwRGBBitCount == 8 ) { +#else + if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) { +#endif + int i; + + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* We have access to the entire palette */ + for ( i=0; i<256; ++i ) { + SDL_colors[i].peFlags = + (PC_NOCOLLAPSE|PC_RESERVED); + SDL_colors[i].peRed = 0; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + } else { + /* First 10 colors are reserved by Windows */ + for ( i=0; i<10; ++i ) { + SDL_colors[i].peFlags = PC_EXPLICIT; + SDL_colors[i].peRed = i; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + for ( i=10; i<(10+236); ++i ) { + SDL_colors[i].peFlags = PC_NOCOLLAPSE; + SDL_colors[i].peRed = 0; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + /* Last 10 colors are reserved by Windows */ + for ( i=246; i<256; ++i ) { + SDL_colors[i].peFlags = PC_EXPLICIT; + SDL_colors[i].peRed = i; + SDL_colors[i].peGreen = 0; + SDL_colors[i].peBlue = 0; + } + } + result = IDirectDraw2_CreatePalette(ddraw2, + (DDPCAPS_8BIT|DDPCAPS_ALLOW256), + SDL_colors, &SDL_palette, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreatePalette", result); + return(NULL); + } + result = IDirectDrawSurface3_SetPalette(SDL_primary, + SDL_palette); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::SetPalette", result); + return(NULL); + } + } + + /* Create our video surface using the same pixel format */ + video = current; + if ( (width != video->w) || (height != video->h) + || (video->format->BitsPerPixel != +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount) ) { +#else + ddsd.ddpfPixelFormat.dwRGBBitCount) ) { +#endif + SDL_FreeSurface(video); + video = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount, + ddsd.ddpfPixelFormat.u2.dwRBitMask, + ddsd.ddpfPixelFormat.u3.dwGBitMask, + ddsd.ddpfPixelFormat.u4.dwBBitMask, +#else + ddsd.ddpfPixelFormat.dwRGBBitCount, + ddsd.ddpfPixelFormat.dwRBitMask, + ddsd.ddpfPixelFormat.dwGBitMask, + ddsd.ddpfPixelFormat.dwBBitMask, +#endif + 0); + if ( video == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + prev_w = video->w; + prev_h = video->h; + video->w = width; + video->h = height; + video->pitch = 0; + } + video->flags = 0; /* Clear flags */ + + /* If not fullscreen, locking is possible, but it doesn't do what + the caller really expects -- if the locked surface is written to, + the appropriate portion of the entire screen is modified, not + the application window, as we would like. + Note that it is still possible to write directly to display + memory, but the application must respect the clip list of + the surface. There might be some odd timing interactions + involving clip list updates and background refreshing as + Windows moves other windows across our window. + We currently don't support this, even though it might be a + good idea since BeOS has an implementation of BDirectWindow + that does the same thing. This would be most useful for + applications that do complete screen updates every frame. + -- Fixme? + */ + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* Necessary if we're going from fullscreen to window */ + if ( video->pixels == NULL ) { + video->pitch = (width*video->format->BytesPerPixel); + /* Pitch needs to be QWORD (8-byte) aligned */ + video->pitch = (video->pitch + 7) & ~7; + video->pixels = (void *)SDL_malloc(video->h*video->pitch); + if ( video->pixels == NULL ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SDL_OutOfMemory(); + return(NULL); + } + } + dd_surface3 = NULL; +#if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */ + if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + video->flags |= SDL_HWSURFACE; + } else { + video->flags |= SDL_SWSURFACE; + } +#else + video->flags |= SDL_SWSURFACE; +#endif + if ( (flags & SDL_RESIZABLE) && !(flags & SDL_NOFRAME) ) { + video->flags |= SDL_RESIZABLE; + } + if ( flags & SDL_NOFRAME ) { + video->flags |= SDL_NOFRAME; + } + } else { + /* Necessary if we're going from window to fullscreen */ + if ( video->pixels != NULL ) { + SDL_free(video->pixels); + video->pixels = NULL; + } + dd_surface3 = SDL_primary; + video->flags |= SDL_HWSURFACE; + } + + /* See if the primary surface has double-buffering enabled */ + if ( (ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP) == DDSCAPS_FLIP ) { + video->flags |= SDL_DOUBLEBUF; + } + + /* Allocate the SDL surface associated with the primary surface */ + if ( DX5_AllocDDSurface(this, video, dd_surface3, + video->flags&SDL_HWSURFACE) < 0 ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + return(NULL); + } + + /* Use the appropriate blitting function */ + if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + video->flags |= SDL_FULLSCREEN; + if ( video->format->palette != NULL ) { + video->flags |= SDL_HWPALETTE; + } + this->UpdateRects = DX5_DirectUpdate; + } else { + this->UpdateRects = DX5_WindowUpdate; + } + + /* Make our window the proper size, set the clipper, then show it */ + if ( (flags & SDL_FULLSCREEN) != SDL_FULLSCREEN ) { + /* Create and set a clipper on our primary surface */ + if ( SDL_clipper == NULL ) { + result = IDirectDraw2_CreateClipper(ddraw2, + 0, &SDL_clipper, NULL); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDraw2::CreateClipper",result); + return(NULL); + } + } + result = IDirectDrawClipper_SetHWnd(SDL_clipper, 0, SDL_Window); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDrawClipper::SetHWnd", result); + return(NULL); + } + result = IDirectDrawSurface3_SetClipper(SDL_primary, + SDL_clipper); + if ( result != DD_OK ) { + if ( video != current ) { + SDL_FreeSurface(video); + } + SetDDerror("DirectDrawSurface3::SetClipper", result); + return(NULL); + } + + /* Resize the window (copied from SDL WinDIB driver) */ + if ( !SDL_windowid && !IsZoomed(SDL_Window) ) { + RECT bounds; + int x, y; + UINT swp_flags; + const char *window = NULL; + const char *center = NULL; + + if ( video->w != prev_w || video->h != prev_h ) { + window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) { + SDL_windowX = x; + SDL_windowY = y; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + } + swp_flags = SWP_NOCOPYBITS; + + bounds.left = SDL_windowX; + bounds.top = SDL_windowY; + bounds.right = SDL_windowX+video->w; + bounds.bottom = SDL_windowY+video->h; + AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0); + width = bounds.right-bounds.left; + height = bounds.bottom-bounds.top; + if ( center ) { + x = (GetSystemMetrics(SM_CXSCREEN)-width)/2; + y = (GetSystemMetrics(SM_CYSCREEN)-height)/2; + } else if ( SDL_windowX || SDL_windowY || window ) { + x = bounds.left; + y = bounds.top; + } else { + x = y = -1; + swp_flags |= SWP_NOMOVE; + } + SetWindowPos(SDL_Window, HWND_NOTOPMOST, x, y, width, height, swp_flags); + SDL_windowX = SDL_bounds.left; + SDL_windowY = SDL_bounds.top; + } + + } + ShowWindow(SDL_Window, SW_SHOW); + SetForegroundWindow(SDL_Window); + SDL_resizing = 0; + + /* JC 14 Mar 2006 + Flush the message loop or this can cause big problems later + Especially if the user decides to use dialog boxes or assert()! + */ + WIN_FlushMessageQueue(); + + /* We're live! */ + return(video); +} + +struct private_hwdata { + LPDIRECTDRAWSURFACE3 dd_surface; + LPDIRECTDRAWSURFACE3 dd_writebuf; +}; + +static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, + LPDIRECTDRAWSURFACE3 requested, Uint32 flag) +{ + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + DDSURFACEDESC ddsd; + HRESULT result; + + /* Clear the hardware flag, in case we fail */ + surface->flags &= ~flag; + + /* Allocate the hardware acceleration data */ + surface->hwdata = (struct private_hwdata *) + SDL_malloc(sizeof(*surface->hwdata)); + if ( surface->hwdata == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + dd_surface3 = NULL; + + /* Set up the surface description */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS| + DDSD_PITCH|DDSD_PIXELFORMAT); + ddsd.dwWidth = surface->w; + ddsd.dwHeight= surface->h; +#if defined(NONAMELESSUNION) + ddsd.u1.lPitch = surface->pitch; +#else + ddsd.lPitch = surface->pitch; +#endif + if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) { + ddsd.ddsCaps.dwCaps = + (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); + } else { + ddsd.ddsCaps.dwCaps = + (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY); + } + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; + if ( surface->format->palette ) { + ddsd.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8; + } +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount = surface->format->BitsPerPixel; + ddsd.ddpfPixelFormat.u2.dwRBitMask = surface->format->Rmask; + ddsd.ddpfPixelFormat.u3.dwGBitMask = surface->format->Gmask; + ddsd.ddpfPixelFormat.u4.dwBBitMask = surface->format->Bmask; +#else + ddsd.ddpfPixelFormat.dwRGBBitCount = surface->format->BitsPerPixel; + ddsd.ddpfPixelFormat.dwRBitMask = surface->format->Rmask; + ddsd.ddpfPixelFormat.dwGBitMask = surface->format->Gmask; + ddsd.ddpfPixelFormat.dwBBitMask = surface->format->Bmask; +#endif + + /* Create the DirectDraw video surface */ + if ( requested != NULL ) { + dd_surface3 = requested; + } else { + result = IDirectDraw2_CreateSurface(ddraw2, + &ddsd, &dd_surface1, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface", result); + goto error_end; + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); + IDirectDrawSurface_Release(dd_surface1); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + goto error_end; + } + } + + if ( (flag & SDL_HWSURFACE) == SDL_HWSURFACE ) { + /* Check to see whether the surface actually ended up + in video memory, and fail if not. We expect the + surfaces we create here to actually be in hardware! + */ + result = IDirectDrawSurface3_GetCaps(dd_surface3,&ddsd.ddsCaps); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::GetCaps", result); + goto error_end; + } + if ( (ddsd.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY) != + DDSCAPS_VIDEOMEMORY ) { + SDL_SetError("No room in video memory"); + goto error_end; + } + } else { + /* Try to hook our surface memory */ + ddsd.dwFlags = DDSD_LPSURFACE; + ddsd.lpSurface = surface->pixels; + result = IDirectDrawSurface3_SetSurfaceDesc(dd_surface3, + &ddsd, 0); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::SetSurfaceDesc", result); + goto error_end; + } + + } + + /* Make sure the surface format was set properly */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface3, NULL, + &ddsd, (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + goto error_end; + } + IDirectDrawSurface3_Unlock(dd_surface3, NULL); + + if ( (flag & SDL_HWSURFACE) == SDL_SWSURFACE ) { + if ( ddsd.lpSurface != surface->pixels ) { + SDL_SetError("DDraw didn't use SDL surface memory"); + goto error_end; + } + if ( +#if defined(NONAMELESSUNION) + ddsd.u1.lPitch +#else + ddsd.lPitch +#endif + != (LONG)surface->pitch ) { + SDL_SetError("DDraw created surface with wrong pitch"); + goto error_end; + } + } else { +#if defined(NONAMELESSUNION) + surface->pitch = (Uint16)ddsd.u1.lPitch; +#else + surface->pitch = (Uint16)ddsd.lPitch; +#endif + } +#if defined(NONAMELESSUNION) + if ( (ddsd.ddpfPixelFormat.u1.dwRGBBitCount != + surface->format->BitsPerPixel) || + (ddsd.ddpfPixelFormat.u2.dwRBitMask != surface->format->Rmask) || + (ddsd.ddpfPixelFormat.u3.dwGBitMask != surface->format->Gmask) || + (ddsd.ddpfPixelFormat.u4.dwBBitMask != surface->format->Bmask) ){ +#else + if ( (ddsd.ddpfPixelFormat.dwRGBBitCount != + surface->format->BitsPerPixel) || + (ddsd.ddpfPixelFormat.dwRBitMask != surface->format->Rmask) || + (ddsd.ddpfPixelFormat.dwGBitMask != surface->format->Gmask) || + (ddsd.ddpfPixelFormat.dwBBitMask != surface->format->Bmask) ){ +#endif + SDL_SetError("DDraw didn't use SDL surface description"); + goto error_end; + } + if ( (ddsd.dwWidth != (DWORD)surface->w) || + (ddsd.dwHeight != (DWORD)surface->h) ) { + SDL_SetError("DDraw created surface with wrong size"); + goto error_end; + } + + /* Set the surface private data */ + surface->flags |= flag; + surface->hwdata->dd_surface = dd_surface3; + if ( (surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) { + LPDIRECTDRAWSURFACE3 dd_writebuf; + + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + result = IDirectDrawSurface3_GetAttachedSurface(dd_surface3, + &ddsd.ddsCaps, &dd_writebuf); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::GetAttachedSurface", + result); + } else { + dd_surface3 = dd_writebuf; + } + } + surface->hwdata->dd_writebuf = dd_surface3; + + /* We're ready to go! */ + return(0); + + /* Okay, so goto's are cheesy, but there are so many possible + errors in this function, and the cleanup is the same in + every single case. Is there a better way, other than deeply + nesting the code? + */ +error_end: + if ( (dd_surface3 != NULL) && (dd_surface3 != requested) ) { + IDirectDrawSurface_Release(dd_surface3); + } + SDL_free(surface->hwdata); + surface->hwdata = NULL; + return(-1); +} + +static int DX5_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + /* DDraw limitation -- you need to set cooperative level first */ + if ( SDL_primary == NULL ) { + SDL_SetError("You must set a non-GL video mode first"); + return(-1); + } + return(DX5_AllocDDSurface(this, surface, NULL, SDL_HWSURFACE)); +} + +#ifdef DDRAW_DEBUG +void PrintSurface(char *title, LPDIRECTDRAWSURFACE3 surface, Uint32 flags) +{ + DDSURFACEDESC ddsd; + + /* Lock and load! */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if ( IDirectDrawSurface3_Lock(surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL) != DD_OK ) { + return; + } + IDirectDrawSurface3_Unlock(surface, NULL); + + fprintf(stderr, "%s:\n", title); + fprintf(stderr, "\tSize: %dx%d in %s at %ld bpp (pitch = %ld)\n", + ddsd.dwWidth, ddsd.dwHeight, + (flags & SDL_HWSURFACE) ? "hardware" : "software", +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u1.dwRGBBitCount, ddsd.u1.lPitch); +#else + ddsd.ddpfPixelFormat.dwRGBBitCount, ddsd.lPitch); +#endif + fprintf(stderr, "\tR = 0x%X, G = 0x%X, B = 0x%X\n", +#if defined(NONAMELESSUNION) + ddsd.ddpfPixelFormat.u2.dwRBitMask, + ddsd.ddpfPixelFormat.u3.dwGBitMask, + ddsd.ddpfPixelFormat.u4.dwBBitMask); +#else + ddsd.ddpfPixelFormat.dwRBitMask, + ddsd.ddpfPixelFormat.dwGBitMask, + ddsd.ddpfPixelFormat.dwBBitMask); +#endif +} +#endif /* DDRAW_DEBUG */ + +static int DX5_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + LPDIRECTDRAWSURFACE3 src_surface; + LPDIRECTDRAWSURFACE3 dst_surface; + DWORD flags; + RECT rect; + HRESULT result; + + /* Set it up.. the desination must have a DDRAW surface */ + src_surface = src->hwdata->dd_writebuf; + dst_surface = dst->hwdata->dd_writebuf; + rect.top = (LONG)srcrect->y; + rect.bottom = (LONG)srcrect->y+srcrect->h; + rect.left = (LONG)srcrect->x; + rect.right = (LONG)srcrect->x+srcrect->w; + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) + flags = DDBLTFAST_SRCCOLORKEY; + else + flags = DDBLTFAST_NOCOLORKEY; + /* FIXME: We can remove this flag for _really_ fast blit queuing, + but it will affect the return values of locks and flips. + */ + flags |= DDBLTFAST_WAIT; + + /* Do the blit! */ + result = IDirectDrawSurface3_BltFast(dst_surface, + dstrect->x, dstrect->y, src_surface, &rect, flags); + if ( result != DD_OK ) { + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore(src_surface); + result = IDirectDrawSurface3_Restore(dst_surface); + /* The surfaces need to be reloaded with artwork */ + SDL_SetError("Blit surfaces were lost, reload them"); + return(-2); + } + SetDDerror("IDirectDrawSurface3::BltFast", result); +#ifdef DDRAW_DEBUG + fprintf(stderr, "Original dest rect: %dx%d at %d,%d\n", dstrect->w, dstrect->h, dstrect->x, dstrect->y); + fprintf(stderr, "HW accelerated %sblit to from 0x%p to 0x%p at (%d,%d)\n", + (src->flags & SDL_SRCCOLORKEY) ? "colorkey " : "", src, dst, + dstrect->x, dstrect->y); + PrintSurface("SRC", src_surface, src->flags); + PrintSurface("DST", dst_surface, dst->flags); + fprintf(stderr, "Source rectangle: (%d,%d) - (%d,%d)\n", + rect.left, rect.top, rect.right, rect.bottom); +#endif + /* Unexpected error, fall back to software blit */ + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + return(0); +} + +static int DX5_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* We need to have a DDraw surface for HW blits */ + if ( (src->flags & SDL_HWSURFACE) == SDL_SWSURFACE ) { + /* Allocate a DDraw surface for the blit */ + if ( src->hwdata == NULL ) { + DX5_AllocDDSurface(this, src, NULL, SDL_SWSURFACE); + } + } + if ( src->hwdata == NULL ) { + return(0); + } + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( DX5_SetHWColorKey(this, src, src->format->colorkey) < 0 ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( DX5_SetHWAlpha(this, src, src->format->alpha) < 0 ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { +#ifdef DDRAW_DEBUG + fprintf(stderr, "Setting accelerated blit on 0x%p\n", src); +#endif + src->map->hw_blit = DX5_HWAccelBlit; + } + return(accelerated); +} + +static int DX5_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + LPDIRECTDRAWSURFACE3 dst_surface; + RECT area; + DDBLTFX bltfx; + HRESULT result; + +#ifdef DDRAW_DEBUG + fprintf(stderr, "HW accelerated fill at (%d,%d)\n", dstrect->x, dstrect->y); +#endif + dst_surface = dst->hwdata->dd_writebuf; + area.top = (LONG)dstrect->y; + area.bottom = (LONG)dstrect->y+dstrect->h; + area.left = (LONG)dstrect->x; + area.right = (LONG)dstrect->x+dstrect->w; + bltfx.dwSize = sizeof(bltfx); +#if defined(NONAMELESSUNION) + bltfx.u5.dwFillColor = color; +#else + bltfx.dwFillColor = color; +#endif + result = IDirectDrawSurface3_Blt(dst_surface, + &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx); + if ( result == DDERR_SURFACELOST ) { + IDirectDrawSurface3_Restore(dst_surface); + result = IDirectDrawSurface3_Blt(dst_surface, + &area, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &bltfx); + } + if ( result != DD_OK ) { + SetDDerror("IDirectDrawSurface3::Blt", result); + return(-1); + } + return(0); +} + +static int DX5_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + DDCOLORKEY colorkey; + HRESULT result; + + /* Set the surface colorkey */ + colorkey.dwColorSpaceLowValue = key; + colorkey.dwColorSpaceHighValue = key; + result = IDirectDrawSurface3_SetColorKey( + surface->hwdata->dd_surface, DDCKEY_SRCBLT, &colorkey); + if ( result != DD_OK ) { + SetDDerror("IDirectDrawSurface3::SetColorKey", result); + return(-1); + } + return(0); +} +static int DX5_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + return(-1); +} + +static int DX5_LockHWSurface(_THIS, SDL_Surface *surface) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 dd_surface; + DDSURFACEDESC ddsd; + + /* Lock and load! */ + dd_surface = surface->hwdata->dd_writebuf; + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore( + surface->hwdata->dd_surface); + result = IDirectDrawSurface3_Lock(dd_surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + return(-1); + } + /* Pitch might have changed -- recalculate pitch and offset */ +#if defined(NONAMELESSUNION) + if ( surface->pitch != ddsd.u1.lPitch ) { + surface->pitch = ddsd.u1.lPitch; +#else + if ( surface->pitch != ddsd.lPitch ) { + surface->pitch = (Uint16)ddsd.lPitch; +#endif + surface->offset = + ((ddsd.dwHeight-surface->h)/2)*surface->pitch + + ((ddsd.dwWidth-surface->w)/2)* + surface->format->BytesPerPixel; + } + surface->pixels = ddsd.lpSurface; + return(0); +} + +static void DX5_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + IDirectDrawSurface3_Unlock(surface->hwdata->dd_writebuf, NULL); + surface->pixels = NULL; +} + +static int DX5_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 dd_surface; + + dd_surface = surface->hwdata->dd_surface; + + /* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */ + /* Dmitry Yakimov (ftech@tula.net) */ + while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING); + + result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore( + surface->hwdata->dd_surface); + while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING); + result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Flip", result); + return(-1); + } + return(0); +} + +static void DX5_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface->hwdata ) { + if ( surface->hwdata->dd_surface != SDL_primary ) { + IDirectDrawSurface3_Release(surface->hwdata->dd_surface); + } + SDL_free(surface->hwdata); + surface->hwdata = NULL; + } +} + +void DX5_WindowUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + HRESULT result; + int i; + RECT src, dst; + + for ( i=0; i<numrects; ++i ) { + src.top = (LONG)rects[i].y; + src.bottom = (LONG)rects[i].y+rects[i].h; + src.left = (LONG)rects[i].x; + src.right = (LONG)rects[i].x+rects[i].w; + dst.top = SDL_bounds.top+src.top; + dst.left = SDL_bounds.left+src.left; + dst.bottom = SDL_bounds.top+src.bottom; + dst.right = SDL_bounds.left+src.right; + result = IDirectDrawSurface3_Blt(SDL_primary, &dst, + this->screen->hwdata->dd_surface, &src, + DDBLT_WAIT, NULL); + /* Doh! Check for lost surface and restore it */ + if ( result == DDERR_SURFACELOST ) { + IDirectDrawSurface3_Restore(SDL_primary); + IDirectDrawSurface3_Blt(SDL_primary, &dst, + this->screen->hwdata->dd_surface, &src, + DDBLT_WAIT, NULL); + } + } +} + +void DX5_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ +} + +/* Compress a full palette into the limited number of colors given to us + by windows. + + The "best" way to do this is to sort the colors by diversity and place + the most diverse colors into the limited palette. Unfortunately this + results in widely varying colors being displayed in the interval during + which the windows palette has been set, and the mapping of the shadow + surface to the new palette. This is especially noticeable during fades. + + To deal with this problem, we can copy a predetermined portion of the + full palette, and use that as the limited palette. This allows colors + to fade smoothly as the remapping is very similar on each palette change. + Unfortunately, this breaks applications which partition the palette into + distinct and widely varying areas, expecting all colors to be available. + + I'm making them both available, chosen at compile time. + If you want the chunk-o-palette algorithm, define SIMPLE_COMPRESSION, + otherwise the sort-by-diversity algorithm will be used. +*/ +#define SIMPLE_COMPRESSION +#define CS_CS_DIST(A, B) ({ \ + int r = (A.r - B.r); \ + int g = (A.g - B.g); \ + int b = (A.b - B.b); \ + (r*r + g*g + b*b); \ +}) +static void DX5_CompressPalette(_THIS, SDL_Color *colors, int ncolors, int maxcolors) +{ +#ifdef SIMPLE_COMPRESSION + int i, j; +#else + static SDL_Color zero = { 0, 0, 0, 0 }; + int i, j; + int max, dist; + int prev, next; + int *pool; + int *seen, *order; +#endif + + /* Does this happen? */ + if ( maxcolors > ncolors ) { + maxcolors = ncolors; + } + +#ifdef SIMPLE_COMPRESSION + /* Just copy the first "maxcolors" colors */ + for ( j=10, i=0; i<maxcolors; ++i, ++j ) { + SDL_colors[j].peRed = colors[i].r; + SDL_colors[j].peGreen = colors[i].g; + SDL_colors[j].peBlue = colors[i].b; + } +#else + /* Allocate memory for the arrays we use */ + pool = SDL_stack_alloc(int, 2*ncolors); + if ( pool == NULL ) { + /* No worries, just return */; + return; + } + seen = pool; + SDL_memset(seen, 0, ncolors*sizeof(int)); + order = pool+ncolors; + + /* Start with the brightest color */ + max = 0; + for ( i=0; i<ncolors; ++i ) { + dist = CS_CS_DIST(zero, colors[i]); + if ( dist >= max ) { + max = dist; + next = i; + } + } + j = 0; + order[j++] = next; + seen[next] = 1; + prev = next; + + /* Keep going through all the colors */ + while ( j < maxcolors ) { + max = 0; + for ( i=0; i<ncolors; ++i ) { + if ( seen[i] ) { + continue; + } + dist = CS_CS_DIST(colors[i], colors[prev]); + if ( dist >= max ) { + max = dist; + next = i; + } + } + order[j++] = next; + seen[next] = 1; + prev = next; + } + + /* Compress the colors to the palette */ + for ( j=10, i=0; i<maxcolors; ++i, ++j ) { + SDL_colors[j].peRed = colors[order[i]].r; + SDL_colors[j].peGreen = colors[order[i]].g; + SDL_colors[j].peBlue = colors[order[i]].b; + } + SDL_stack_free(pool); +#endif /* SIMPLE_COMPRESSION */ +} + +/* Set the system colormap in both fullscreen and windowed modes */ +int DX5_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + int alloct_all; + + /* Copy palette colors into display palette */ + alloct_all = 0; + if ( SDL_palette != NULL ) { + if ( (this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { + /* We can set all entries explicitly */ + for ( i=0; i< ncolors; ++i ) { + int j = firstcolor + i; + SDL_colors[j].peRed = colors[i].r; + SDL_colors[j].peGreen = colors[i].g; + SDL_colors[j].peBlue = colors[i].b; + } + /* This sends an WM_PALETTECHANGED message to us */ + colorchange_expected = 1; + IDirectDrawPalette_SetEntries(SDL_palette, 0, + firstcolor, ncolors, &SDL_colors[firstcolor]); + alloct_all = 1; + } else { + /* Grab the 236 most diverse colors in the palette */ + DX5_CompressPalette(this, colors, ncolors, 236); + /* This sends an WM_PALETTECHANGED message to us */ + colorchange_expected = 1; + IDirectDrawPalette_SetEntries(SDL_palette, 0, + 0, 256, SDL_colors); + } + } + return(alloct_all); +} + +/* Gamma code is only available on DirectX 7 and newer */ +static int DX5_SetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef IDirectDrawGammaControl_SetGammaRamp + LPDIRECTDRAWGAMMACONTROL gamma; + DDGAMMARAMP gamma_ramp; + HRESULT result; +#endif + + /* In windowed or OpenGL mode, use windib gamma code */ + if ( ! DDRAW_FULLSCREEN() ) { + return DIB_SetGammaRamp(this, ramp); + } + +#ifndef IDirectDrawGammaControl_SetGammaRamp + SDL_SetError("SDL compiled without DirectX gamma ramp support"); + return -1; +#else + /* Check for a video mode! */ + if ( ! SDL_primary ) { + SDL_SetError("A video mode must be set for gamma correction"); + return(-1); + } + + /* Get the gamma control object */ + result = IDirectDrawSurface3_QueryInterface(SDL_primary, + &IID_IDirectDrawGammaControl, (LPVOID *)&gamma); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result); + return(-1); + } + + /* Set up the gamma ramp */ + SDL_memcpy(gamma_ramp.red, &ramp[0*256], 256*sizeof(*ramp)); + SDL_memcpy(gamma_ramp.green, &ramp[1*256], 256*sizeof(*ramp)); + SDL_memcpy(gamma_ramp.blue, &ramp[2*256], 256*sizeof(*ramp)); + result = IDirectDrawGammaControl_SetGammaRamp(gamma, 0, &gamma_ramp); + if ( result != DD_OK ) { + SetDDerror("DirectDrawGammaControl::SetGammaRamp()", result); + } + + /* Release the interface and return */ + IDirectDrawGammaControl_Release(gamma); + return (result == DD_OK) ? 0 : -1; +#endif /* !IDirectDrawGammaControl_SetGammaRamp */ +} + +static int DX5_GetGammaRamp(_THIS, Uint16 *ramp) +{ +#ifdef IDirectDrawGammaControl_SetGammaRamp + LPDIRECTDRAWGAMMACONTROL gamma; + DDGAMMARAMP gamma_ramp; + HRESULT result; +#endif + + /* In windowed or OpenGL mode, use windib gamma code */ + if ( ! DDRAW_FULLSCREEN() ) { + return DIB_GetGammaRamp(this, ramp); + } + +#ifndef IDirectDrawGammaControl_SetGammaRamp + SDL_SetError("SDL compiled without DirectX gamma ramp support"); + return -1; +#else + /* Check for a video mode! */ + if ( ! SDL_primary ) { + SDL_SetError("A video mode must be set for gamma correction"); + return(-1); + } + + /* Get the gamma control object */ + result = IDirectDrawSurface3_QueryInterface(SDL_primary, + &IID_IDirectDrawGammaControl, (LPVOID *)&gamma); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::QueryInterface(GAMMA)", result); + return(-1); + } + + /* Set up the gamma ramp */ + result = IDirectDrawGammaControl_GetGammaRamp(gamma, 0, &gamma_ramp); + if ( result == DD_OK ) { + SDL_memcpy(&ramp[0*256], gamma_ramp.red, 256*sizeof(*ramp)); + SDL_memcpy(&ramp[1*256], gamma_ramp.green, 256*sizeof(*ramp)); + SDL_memcpy(&ramp[2*256], gamma_ramp.blue, 256*sizeof(*ramp)); + } else { + SetDDerror("DirectDrawGammaControl::GetGammaRamp()", result); + } + + /* Release the interface and return */ + IDirectDrawGammaControl_Release(gamma); + return (result == DD_OK) ? 0 : -1; +#endif /* !IDirectDrawGammaControl_SetGammaRamp */ +} + +void DX5_VideoQuit(_THIS) +{ + int i, j; + + /* If we're fullscreen GL, we need to reset the display */ + if ( this->screen != NULL ) { +#ifndef NO_CHANGEDISPLAYSETTINGS + if ( (this->screen->flags & (SDL_OPENGL|SDL_FULLSCREEN)) == + (SDL_OPENGL|SDL_FULLSCREEN) ) { + ChangeDisplaySettings(NULL, 0); + ShowWindow(SDL_Window, SW_HIDE); + } +#endif + if ( this->screen->flags & SDL_OPENGL ) { + WIN_GL_ShutDown(this); + } + } + + /* Free any palettes we used */ + if ( SDL_palette != NULL ) { + IDirectDrawPalette_Release(SDL_palette); + SDL_palette = NULL; + } + + /* Allow the primary surface to be freed */ + if ( SDL_primary != NULL ) { + SDL_primary = NULL; + } + + /* Free video mode lists */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Free the window */ + DIB_QuitGamma(this); + if ( SDL_Window ) { + DX5_DestroyWindow(this); + } + + /* Free our window icon */ + if ( screen_icn ) { + DestroyIcon(screen_icn); + screen_icn = NULL; + } +} + +/* Exported for the windows message loop only */ +void DX5_Activate(_THIS, BOOL active, BOOL minimized) +{ +} +void DX5_RealizePalette(_THIS) +{ + if ( SDL_palette ) { + IDirectDrawSurface3_SetPalette(SDL_primary, SDL_palette); + } +} +static void DX5_Recolor8Bit(_THIS, SDL_Surface *surface, Uint8 *mapping) +{ + int row, col; + Uint8 *pixels; + + if ( surface->w && surface->h ) { + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + if ( this->LockHWSurface(this, surface) < 0 ) { + return; + } + } + for ( row=0; row<surface->h; ++row ) { + pixels = (Uint8 *)surface->pixels+row*surface->pitch; + for ( col=0; col<surface->w; ++col, ++pixels ) { + *pixels = mapping[*pixels]; + } + } + if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { + this->UnlockHWSurface(this, surface); + } + SDL_UpdateRect(surface, 0, 0, 0, 0); + } +} +void DX5_PaletteChanged(_THIS, HWND window) +{ + SDL_Palette *palette; + SDL_Color *saved = NULL; + HDC hdc; + int i; + PALETTEENTRY *entries; + + /* This is true when the window is closing */ + if ( (SDL_primary == NULL) || (SDL_VideoSurface == NULL) ) + return; + + /* We need to get the colors as they were set */ + palette = this->physpal; + if(!palette) + palette = SDL_VideoSurface->format->palette; + if ( palette == NULL ) { /* Sometimes we don't have a palette */ + return; + } + entries = SDL_stack_alloc(PALETTEENTRY, palette->ncolors); + hdc = GetDC(window); + GetSystemPaletteEntries(hdc, 0, palette->ncolors, entries); + ReleaseDC(window, hdc); + if ( ! colorchange_expected ) { + saved = SDL_stack_alloc(SDL_Color, palette->ncolors); + SDL_memcpy(saved, palette->colors, + palette->ncolors*sizeof(SDL_Color)); + } + for ( i=0; i<palette->ncolors; ++i ) { + palette->colors[i].r = entries[i].peRed; + palette->colors[i].g = entries[i].peGreen; + palette->colors[i].b = entries[i].peBlue; + } + SDL_stack_free(entries); + if ( ! colorchange_expected ) { + Uint8 mapping[256]; + + SDL_memset(mapping, 0, sizeof(mapping)); + for ( i=0; i<palette->ncolors; ++i ) { + mapping[i] = SDL_FindColor(palette, + saved[i].r, saved[i].g, saved[i].b); + } + DX5_Recolor8Bit(this, SDL_VideoSurface, mapping); + SDL_stack_free(saved); + } + colorchange_expected = 0; + + /* Notify all mapped surfaces of the change */ + SDL_FormatChanged(SDL_VideoSurface); +} + +/* Exported for the windows message loop only */ +void DX5_WinPAINT(_THIS, HDC hdc) +{ + SDL_UpdateRect(SDL_PublicSurface, 0, 0, 0, 0); +} diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5video.h b/3rdparty/SDL/src/video/windx5/SDL_dx5video.h new file mode 100644 index 0000000..3d754a0 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5video.h @@ -0,0 +1,61 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_dx5video_h +#define _SDL_dx5video_h + +#include "directx.h" + +/* Private display data */ +struct SDL_PrivateVideoData { + LPDIRECTDRAW2 ddraw2; + LPDIRECTDRAWSURFACE3 SDL_primary; + LPDIRECTDRAWCLIPPER SDL_clipper; + LPDIRECTDRAWPALETTE SDL_palette; + PALETTEENTRY SDL_colors[256]; + int colorchange_expected; + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + int SDL_modeindex[NUM_MODELISTS]; +}; +/* Old variable names */ +#define ddraw2 (this->hidden->ddraw2) +#define SDL_primary (this->hidden->SDL_primary) +#define SDL_clipper (this->hidden->SDL_clipper) +#define SDL_palette (this->hidden->SDL_palette) +#define SDL_colors (this->hidden->SDL_colors) +#define colorchange_expected (this->hidden->colorchange_expected) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_modeindex (this->hidden->SDL_modeindex) + +/* DirectX function pointers for video and events */ +extern HRESULT (WINAPI *DDrawCreate)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); +extern HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); + +/* DirectDraw error reporting function */ +extern void SetDDerror(const char *function, int code); + +#endif /* _SDL_dx5video_h */ diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c new file mode 100644 index 0000000..cb89fdc --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv.c @@ -0,0 +1,296 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectDraw implementation of YUV video overlays */ +#include "directx.h" +#include "SDL_video.h" +#include "SDL_dx5yuv_c.h" +#include "../SDL_yuvfuncs.h" + +//#define USE_DIRECTX_OVERLAY + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs dx5_yuvfuncs = { + DX5_LockYUVOverlay, + DX5_UnlockYUVOverlay, + DX5_DisplayYUVOverlay, + DX5_FreeYUVOverlay +}; + +struct private_yuvhwdata { + LPDIRECTDRAWSURFACE3 surface; + + /* These are just so we don't have to allocate them separately */ + Uint16 pitches[3]; + Uint8 *planes[3]; +}; + + +static LPDIRECTDRAWSURFACE3 CreateYUVSurface(_THIS, + int width, int height, Uint32 format) +{ + HRESULT result; + LPDIRECTDRAWSURFACE dd_surface1; + LPDIRECTDRAWSURFACE3 dd_surface3; + DDSURFACEDESC ddsd; + + /* Set up the surface description */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + ddsd.dwWidth = width; + ddsd.dwHeight= height; +#ifdef USE_DIRECTX_OVERLAY + ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY|DDSCAPS_VIDEOMEMORY); +#else + ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); +#endif + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + ddsd.ddpfPixelFormat.dwFourCC = format; + + /* Create the DirectDraw video surface */ + result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDraw2::CreateSurface", result); + return(NULL); + } + result = IDirectDrawSurface_QueryInterface(dd_surface1, + &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); + IDirectDrawSurface_Release(dd_surface1); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface::QueryInterface", result); + return(NULL); + } + + /* Make sure the surface format was set properly */ + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(dd_surface3, NULL, + &ddsd, DDLOCK_NOSYSLOCK, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + IDirectDrawSurface_Release(dd_surface3); + return(NULL); + } + IDirectDrawSurface3_Unlock(dd_surface3, NULL); + + if ( !(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) || + (ddsd.ddpfPixelFormat.dwFourCC != format) ) { + SDL_SetError("DDraw didn't use requested FourCC format"); + IDirectDrawSurface_Release(dd_surface3); + return(NULL); + } + + /* We're ready to go! */ + return(dd_surface3); +} + +#ifdef DEBUG_YUV +static char *PrintFOURCC(Uint32 code) +{ + static char buf[5]; + + buf[3] = code >> 24; + buf[2] = (code >> 16) & 0xFF; + buf[1] = (code >> 8) & 0xFF; + buf[0] = (code & 0xFF); + return(buf); +} +#endif + +SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + +#ifdef DEBUG_YUV + DWORD numcodes; + DWORD *codes; + + printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format)); + IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL); + if ( numcodes ) { + DWORD i; + codes = SDL_malloc(numcodes*sizeof(*codes)); + if ( codes ) { + IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes); + for ( i=0; i<numcodes; ++i ) { + fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i])); + } + SDL_free(codes); + } + } else { + fprintf(stderr, "No FOURCC codes supported\n"); + } +#endif + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &dx5_yuvfuncs; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->surface = CreateYUVSurface(this, width, height, format); + if ( hwdata->surface == NULL ) { + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + overlay->hw_overlay = 1; + + /* Set up the plane pointers */ + overlay->pitches = hwdata->pitches; + overlay->pixels = hwdata->planes; + switch (format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + overlay->planes = 3; + break; + default: + overlay->planes = 1; + break; + } + + /* We're all done.. */ + return(overlay); +} + +int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 surface; + DDSURFACEDESC ddsd; + + surface = overlay->hwdata->surface; + SDL_memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + result = IDirectDrawSurface3_Lock(surface, NULL, + &ddsd, DDLOCK_NOSYSLOCK, NULL); + if ( result == DDERR_SURFACELOST ) { + result = IDirectDrawSurface3_Restore(surface); + result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, + (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); + } + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Lock", result); + return(-1); + } + + /* Find the pitch and offset values for the overlay */ +#if defined(NONAMELESSUNION) + overlay->pitches[0] = (Uint16)ddsd.u1.lPitch; +#else + overlay->pitches[0] = (Uint16)ddsd.lPitch; +#endif + overlay->pixels[0] = (Uint8 *)ddsd.lpSurface; + switch (overlay->format) { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + /* Add the two extra planes */ + overlay->pitches[1] = overlay->pitches[0] / 2; + overlay->pitches[2] = overlay->pitches[0] / 2; + overlay->pixels[1] = overlay->pixels[0] + + overlay->pitches[0] * overlay->h; + overlay->pixels[2] = overlay->pixels[1] + + overlay->pitches[1] * overlay->h / 2; + break; + default: + /* Only one plane, no worries */ + break; + } + return(0); +} + +void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + LPDIRECTDRAWSURFACE3 surface; + + surface = overlay->hwdata->surface; + IDirectDrawSurface3_Unlock(surface, NULL); +} + +int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + HRESULT result; + LPDIRECTDRAWSURFACE3 surface; + RECT srcrect, dstrect; + + surface = overlay->hwdata->surface; + srcrect.top = src->y; + srcrect.bottom = srcrect.top+src->h; + srcrect.left = src->x; + srcrect.right = srcrect.left+src->w; + dstrect.top = SDL_bounds.top+dst->y; + dstrect.left = SDL_bounds.left+dst->x; + dstrect.bottom = dstrect.top+dst->h; + dstrect.right = dstrect.left+dst->w; +#ifdef USE_DIRECTX_OVERLAY + result = IDirectDrawSurface3_UpdateOverlay(surface, &srcrect, + SDL_primary, &dstrect, DDOVER_SHOW, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::UpdateOverlay", result); + return(-1); + } +#else + result = IDirectDrawSurface3_Blt(SDL_primary, &dstrect, surface, &srcrect, + DDBLT_WAIT, NULL); + if ( result != DD_OK ) { + SetDDerror("DirectDrawSurface3::Blt", result); + return(-1); + } +#endif + return(0); +} + +void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + if ( hwdata->surface ) { + IDirectDrawSurface_Release(hwdata->surface); + } + SDL_free(hwdata); + overlay->hwdata = NULL; + } +} + diff --git a/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h new file mode 100644 index 0000000..dfceaf9 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/SDL_dx5yuv_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the DirectDraw implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "../wincommon/SDL_lowvideo.h" +#include "SDL_dx5video.h" + +extern SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); diff --git a/3rdparty/SDL/src/video/windx5/directx.h b/3rdparty/SDL/src/video/windx5/directx.h new file mode 100644 index 0000000..c7f5365 --- /dev/null +++ b/3rdparty/SDL/src/video/windx5/directx.h @@ -0,0 +1,97 @@ + +#ifndef _directx_h +#define _directx_h + +/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <mmsystem.h> +#ifndef WIN32 +#define WIN32 +#endif +#undef WINNT + +/* Far pointers don't exist in 32-bit code */ +#ifndef FAR +#define FAR +#endif + +/* Error codes not yet included in Win32 API header files */ +#ifndef MAKE_HRESULT +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code)))) +#endif + +#ifndef S_OK +#define S_OK (HRESULT)0x00000000L +#endif + +#ifndef SUCCEEDED +#define SUCCEEDED(x) ((HRESULT)(x) >= 0) +#endif +#ifndef FAILED +#define FAILED(x) ((HRESULT)(x)<0) +#endif + +#ifndef E_FAIL +#define E_FAIL (HRESULT)0x80000008L +#endif +#ifndef E_NOINTERFACE +#define E_NOINTERFACE (HRESULT)0x80004002L +#endif +#ifndef E_OUTOFMEMORY +#define E_OUTOFMEMORY (HRESULT)0x8007000EL +#endif +#ifndef E_INVALIDARG +#define E_INVALIDARG (HRESULT)0x80070057L +#endif +#ifndef E_NOTIMPL +#define E_NOTIMPL (HRESULT)0x80004001L +#endif +#ifndef REGDB_E_CLASSNOTREG +#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L +#endif + +/* Severity codes */ +#ifndef SEVERITY_ERROR +#define SEVERITY_ERROR 1 +#endif + +/* Error facility codes */ +#ifndef FACILITY_WIN32 +#define FACILITY_WIN32 7 +#endif + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field)) +#endif + +/* DirectX headers (if it isn't included, I haven't tested it yet) + */ +/* We need these defines to mark what version of DirectX API we use */ +#define DIRECTDRAW_VERSION 0x0700 +#define DIRECTSOUND_VERSION 0x0500 +#define DIRECTINPUT_VERSION 0x0700 + +#include <ddraw.h> +#include <dsound.h> +#include <dinput.h> + +#if DIRECTINPUT_VERSION >= 0x0700 && !defined(DIMOFS_BUTTON4) +typedef struct _DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2, *LPDIMOUSESTATE2; + +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) + +extern const DIDATAFORMAT c_dfDIMouse2; +#endif + +#endif /* _directx_h */ diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c new file mode 100644 index 0000000..635b972 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents.c @@ -0,0 +1,233 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/types.h> +#include <dev/wscons/wsdisplay_usl_io.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <errno.h> +#include <string.h> + +#include "SDL.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_wsconsvideo.h" +#include "SDL_wsconsevents_c.h" + +static int posted = 0; + +int WSCONS_InitKeyboard(_THIS) +{ + struct termios tty; + + if (ioctl(private->fd, WSKBDIO_GTYPE, &private->kbdType) == -1) { + WSCONS_ReportError("cannot get keyboard type: %s", strerror(errno)); + return -1; + } + + if (tcgetattr(private->fd, &private->saved_tty) == -1) { + WSCONS_ReportError("cannot get terminal attributes: %s", strerror(errno)); + return -1; + } + private->did_save_tty = 1; + tty = private->saved_tty; + tty.c_iflag = IGNPAR | IGNBRK; + tty.c_oflag = 0; + tty.c_cflag = CREAD | CS8; + tty.c_lflag = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + cfsetispeed(&tty, 9600); + cfsetospeed(&tty, 9600); + if (tcsetattr(private->fd, TCSANOW, &tty) < 0) { + WSCONS_ReportError("cannot set terminal attributes: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, KDSKBMODE, K_RAW) == -1) { + WSCONS_ReportError("cannot set raw keyboard mode: %s", strerror(errno)); + return -1; + } + + return 0; +} + +void WSCONS_ReleaseKeyboard(_THIS) +{ + if (private->fd != -1) { + if (ioctl(private->fd, KDSKBMODE, K_XLATE) == -1) { + WSCONS_ReportError("cannot restore keyboard to translated mode: %s", + strerror(errno)); + } + if (private->did_save_tty) { + if (tcsetattr(private->fd, TCSANOW, &private->saved_tty) < 0) { + WSCONS_ReportError("cannot restore keynoard attributes: %s", + strerror(errno)); + } + } + } +} + +static void updateMouse() +{ +} + +static SDLKey keymap[128]; + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + keysym->scancode = scancode; + keysym->sym = SDLK_UNKNOWN; + keysym->mod = KMOD_NONE; + + if (scancode < SDL_arraysize(keymap)) + keysym->sym = keymap[scancode]; + + if (keysym->sym == SDLK_UNKNOWN) + printf("Unknown mapping for scancode %d\n", scancode); + + return keysym; +} + +static void updateKeyboard(_THIS) +{ + unsigned char buf[100]; + SDL_keysym keysym; + int n, i; + + if ((n = read(private->fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < n; i++) { + unsigned char c = buf[i] & 0x7f; + if (c == 224) // special key prefix -- what should we do with it? + continue; + posted += SDL_PrivateKeyboard((buf[i] & 0x80) ? SDL_RELEASED : SDL_PRESSED, + TranslateKey(c, &keysym)); + } + } +} + +void WSCONS_PumpEvents(_THIS) +{ + do { + posted = 0; + updateMouse(); + updateKeyboard(this); + } while (posted); +} + +void WSCONS_InitOSKeymap(_THIS) +{ + int i; + + /* Make sure unknown keys are mapped correctly */ + for (i=0; i < SDL_arraysize(keymap); i++) { + keymap[i] = SDLK_UNKNOWN; + } + + switch (private->kbdType) { +#ifdef WSKBD_TYPE_ZAURUS + case WSKBD_TYPE_ZAURUS: + /* top row */ + keymap[2] = SDLK_1; + keymap[3] = SDLK_2; + keymap[4] = SDLK_3; + keymap[5] = SDLK_4; + keymap[6] = SDLK_5; + keymap[7] = SDLK_6; + keymap[8] = SDLK_7; + keymap[9] = SDLK_8; + keymap[10] = SDLK_9; + keymap[11] = SDLK_0; + keymap[14] = SDLK_BACKSPACE; + + /* second row */ + keymap[16] = SDLK_q; + keymap[17] = SDLK_w; + keymap[18] = SDLK_e; + keymap[19] = SDLK_r; + keymap[20] = SDLK_t; + keymap[21] = SDLK_y; + keymap[22] = SDLK_u; + keymap[23] = SDLK_i; + keymap[24] = SDLK_o; + keymap[25] = SDLK_p; + + /* third row */ + keymap[15] = SDLK_TAB; + keymap[30] = SDLK_a; + keymap[31] = SDLK_s; + keymap[32] = SDLK_d; + keymap[33] = SDLK_f; + keymap[34] = SDLK_g; + keymap[35] = SDLK_h; + keymap[36] = SDLK_j; + keymap[37] = SDLK_k; + keymap[38] = SDLK_l; + + /* fourth row */ + keymap[42] = SDLK_LSHIFT; + keymap[44] = SDLK_z; + keymap[45] = SDLK_x; + keymap[46] = SDLK_c; + keymap[47] = SDLK_v; + keymap[48] = SDLK_b; + keymap[49] = SDLK_n; + keymap[50] = SDLK_m; + keymap[54] = SDLK_RSHIFT; + keymap[28] = SDLK_RETURN; + + /* fifth row */ + keymap[56] = SDLK_LALT; + keymap[29] = SDLK_LCTRL; + /* keymap[56] = ; */ + keymap[0] = SDLK_LSUPER; + keymap[12] = SDLK_MINUS; + keymap[57] = SDLK_SPACE; + keymap[51] = SDLK_COMMA; + keymap[52] = SDLK_PERIOD; + + /* misc */ + keymap[59] = SDLK_F1; + keymap[60] = SDLK_F2; + keymap[61] = SDLK_F3; + keymap[62] = SDLK_F4; + keymap[63] = SDLK_F5; + keymap[1] = SDLK_ESCAPE; + /* keymap[28] = SDLK_KP_ENTER; */ + keymap[72] = SDLK_UP; + keymap[75] = SDLK_LEFT; + keymap[77] = SDLK_RIGHT; + keymap[80] = SDLK_DOWN; + break; +#endif /* WSKBD_TYPE_ZAURUS */ + + default: + WSCONS_ReportError("Unable to map keys for keyboard type %u", + private->kbdType); + break; + } +} + +/* end of SDL_wsconsevents.c ... */ + diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h new file mode 100644 index 0000000..f68ee6e --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsevents_c.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_wsconsvideo.h" + +int WSCONS_InitKeyboard(_THIS); +void WSCONS_ReleaseKeyboard(_THIS); + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern void WSCONS_InitOSKeymap(_THIS); +extern void WSCONS_PumpEvents(_THIS); + +/* end of SDL_wsconsevents_c.h ... */ + diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c new file mode 100644 index 0000000..b69e0c5 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_wsconsmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h new file mode 100644 index 0000000..875437b --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_wsconsvideo.h" + +/* Functions to be exported */ diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c new file mode 100644 index 0000000..0e850d1 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.c @@ -0,0 +1,609 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <sys/time.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <dev/wscons/wsdisplay_usl_io.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_wsconsvideo.h" +#include "SDL_wsconsevents_c.h" +#include "SDL_wsconsmouse_c.h" + +#define WSCONSVID_DRIVER_NAME "wscons" +enum { + WSCONS_ROTATE_NONE = 0, + WSCONS_ROTATE_CCW = 90, + WSCONS_ROTATE_UD = 180, + WSCONS_ROTATE_CW = 270 +}; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* Initialization/Query functions */ +static int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void WSCONS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface); +static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface); + +/* etc. */ +static WSCONS_bitBlit WSCONS_blit16; +static WSCONS_bitBlit WSCONS_blit16blocked; +static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +void WSCONS_ReportError(char *fmt, ...) +{ + char message[200]; + va_list vaArgs; + + message[199] = '\0'; + + va_start(vaArgs, fmt); + vsnprintf(message, 199, fmt, vaArgs); + va_end(vaArgs); + + SDL_SetError(message); + fprintf(stderr, "WSCONS error: %s\n", message); +} + +/* WSCONS driver bootstrap functions */ + +static int WSCONS_Available(void) +{ + return 1; +} + +static void WSCONS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *WSCONS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(device, 0, (sizeof *device)); + device->hidden = + (struct SDL_PrivateVideoData *)SDL_malloc((sizeof *device->hidden)); + if (device->hidden == NULL) { + SDL_OutOfMemory(); + SDL_free(device); + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + device->hidden->fd = -1; + + /* Set the function pointers */ + device->VideoInit = WSCONS_VideoInit; + device->ListModes = WSCONS_ListModes; + device->SetVideoMode = WSCONS_SetVideoMode; + device->SetColors = WSCONS_SetColors; + device->UpdateRects = WSCONS_UpdateRects; + device->VideoQuit = WSCONS_VideoQuit; + device->AllocHWSurface = WSCONS_AllocHWSurface; + device->LockHWSurface = WSCONS_LockHWSurface; + device->UnlockHWSurface = WSCONS_UnlockHWSurface; + device->FreeHWSurface = WSCONS_FreeHWSurface; + device->InitOSKeymap = WSCONS_InitOSKeymap; + device->PumpEvents = WSCONS_PumpEvents; + device->free = WSCONS_DeleteDevice; + + return device; +} + +VideoBootStrap WSCONS_bootstrap = { + WSCONSVID_DRIVER_NAME, + "SDL wscons video driver", + WSCONS_Available, + WSCONS_CreateDevice +}; + +#define WSCONSDEV_FORMAT "/dev/ttyC%01x" + +int WSCONS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + char devnamebuf[30]; + char *devname; + char *rotation; + int wstype; + int wsmode = WSDISPLAYIO_MODE_DUMBFB; + size_t len, mapsize; + int pagemask; + int width, height; + + devname = SDL_getenv("SDL_WSCONSDEV"); + if (devname == NULL) { + int activeVT; + if (ioctl(STDIN_FILENO, VT_GETACTIVE, &activeVT) == -1) { + WSCONS_ReportError("Unable to determine active terminal: %s", + strerror(errno)); + return -1; + } + SDL_snprintf(devnamebuf, sizeof(devnamebuf), WSCONSDEV_FORMAT, activeVT - 1); + devname = devnamebuf; + } + + private->fd = open(devname, O_RDWR | O_NONBLOCK, 0); + if (private->fd == -1) { + WSCONS_ReportError("open %s: %s", devname, strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_GINFO, &private->info) == -1) { + WSCONS_ReportError("ioctl WSDISPLAY_GINFO: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { + WSCONS_ReportError("ioctl WSDISPLAY_GTYPE: %s", strerror(errno)); + return -1; + } + if (ioctl(private->fd, WSDISPLAYIO_LINEBYTES, &private->physlinebytes) == -1) { + WSCONS_ReportError("ioctl WSDISPLAYIO_LINEBYTES: %s", strerror(errno)); + return -1; + } + if (private->info.depth > 8) { + if (wstype == WSDISPLAY_TYPE_SUN24 || + wstype == WSDISPLAY_TYPE_SUNCG12 || + wstype == WSDISPLAY_TYPE_SUNCG14 || + wstype == WSDISPLAY_TYPE_SUNTCX || + wstype == WSDISPLAY_TYPE_SUNFFB) { + private->redMask = 0x0000ff; + private->greenMask = 0x00ff00; + private->blueMask = 0xff0000; +#ifdef WSDISPLAY_TYPE_PXALCD + } else if (wstype == WSDISPLAY_TYPE_PXALCD) { + private->redMask = 0x1f << 11; + private->greenMask = 0x3f << 5; + private->blueMask = 0x1f; +#endif + } else { + WSCONS_ReportError("Unknown video hardware"); + return -1; + } + } else { + WSCONS_ReportError("Displays with 8 bpp or less are not supported"); + return -1; + } + + private->rotate = WSCONS_ROTATE_NONE; + rotation = SDL_getenv("SDL_VIDEO_WSCONS_ROTATION"); + if (rotation != NULL) { + if (SDL_strlen(rotation) == 0) { + private->shadowFB = 0; + private->rotate = WSCONS_ROTATE_NONE; + printf("Not rotating, no shadow\n"); + } else if (!SDL_strcmp(rotation, "NONE")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_NONE; + printf("Not rotating, but still using shadow\n"); + } else if (!SDL_strcmp(rotation, "CW")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_CW; + printf("Rotating screen clockwise\n"); + } else if (!SDL_strcmp(rotation, "CCW")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_CCW; + printf("Rotating screen counter clockwise\n"); + } else if (!SDL_strcmp(rotation, "UD")) { + private->shadowFB = 1; + private->rotate = WSCONS_ROTATE_UD; + printf("Rotating screen upside down\n"); + } else { + WSCONS_ReportError("\"%s\" is not a valid value for " + "SDL_VIDEO_WSCONS_ROTATION", rotation); + return -1; + } + } + + switch (private->info.depth) { + case 1: + case 4: + case 8: + len = private->physlinebytes * private->info.height; + break; + case 16: + if (private->physlinebytes == private->info.width) { + len = private->info.width * private->info.height * sizeof(short); + } else { + len = private->physlinebytes * private->info.height; + } + if (private->rotate == WSCONS_ROTATE_NONE || + private->rotate == WSCONS_ROTATE_UD) { + private->blitFunc = WSCONS_blit16; + } else { + private->blitFunc = WSCONS_blit16blocked; + } + break; + case 32: + if (private->physlinebytes == private->info.width) { + len = private->info.width * private->info.height * sizeof(int); + } else { + len = private->physlinebytes * private->info.height; + } + break; + default: + WSCONS_ReportError("unsupported depth %d", private->info.depth); + return -1; + } + + if (private->shadowFB && private->blitFunc == NULL) { + WSCONS_ReportError("Using software buffer, but no blitter function is " + "available for this %d bpp.", private->info.depth); + return -1; + } + + if (ioctl(private->fd, WSDISPLAYIO_SMODE, &wsmode) == -1) { + WSCONS_ReportError("ioctl SMODE"); + return -1; + } + + pagemask = getpagesize() - 1; + mapsize = ((int)len + pagemask) & ~pagemask; + private->physmem = (Uint8 *)mmap(NULL, mapsize, + PROT_READ | PROT_WRITE, MAP_SHARED, + private->fd, (off_t)0); + if (private->physmem == (Uint8 *)MAP_FAILED) { + private->physmem = NULL; + WSCONS_ReportError("mmap: %s", strerror(errno)); + return -1; + } + private->fbmem_len = len; + + if (private->rotate == WSCONS_ROTATE_CW || + private->rotate == WSCONS_ROTATE_CCW) { + width = private->info.height; + height = private->info.width; + } else { + width = private->info.width; + height = private->info.height; + } + + this->info.current_w = width; + this->info.current_h = height; + + if (private->shadowFB) { + private->shadowmem = (Uint8 *)SDL_malloc(len); + if (private->shadowmem == NULL) { + WSCONS_ReportError("No memory for shadow"); + return -1; + } + private->fbstart = private->shadowmem; + private->fblinebytes = width * ((private->info.depth + 7) / 8); + } else { + private->fbstart = private->physmem; + private->fblinebytes = private->physlinebytes; + } + + private->SDL_modelist[0] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + private->SDL_modelist[0]->w = width; + private->SDL_modelist[0]->h = height; + + vformat->BitsPerPixel = private->info.depth; + vformat->BytesPerPixel = private->info.depth / 8; + + if (WSCONS_InitKeyboard(this) == -1) { + return -1; + } + + return 0; +} + +SDL_Rect **WSCONS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if (format->BitsPerPixel == private->info.depth) { + return private->SDL_modelist; + } else { + return NULL; + } +} + +SDL_Surface *WSCONS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + if (width != private->SDL_modelist[0]->w || + height != private->SDL_modelist[0]->h) { + WSCONS_ReportError("Requested video mode %dx%d not supported.", + width, height); + return NULL; + } + if (bpp != private->info.depth) { + WSCONS_ReportError("Requested video depth %d bpp not supported.", bpp); + return NULL; + } + + if (!SDL_ReallocFormat(current, + bpp, + private->redMask, + private->greenMask, + private->blueMask, + 0)) { + WSCONS_ReportError("Couldn't allocate new pixel format"); + return NULL; + } + + current->flags &= SDL_FULLSCREEN; + if (private->shadowFB) { + current->flags |= SDL_SWSURFACE; + } else { + current->flags |= SDL_HWSURFACE; + } + current->w = width; + current->h = height; + current->pitch = private->fblinebytes; + current->pixels = private->fbstart; + + SDL_memset(private->fbstart, 0, private->fbmem_len); + + return current; +} + +static int WSCONS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return -1; +} +static void WSCONS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static int WSCONS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return 0; +} + +static void WSCONS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ +} + +static void WSCONS_blit16(Uint8 *byte_src_pos, + int srcRightDelta, + int srcDownDelta, + Uint8 *byte_dst_pos, + int dst_linebytes, + int width, + int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w != 0; w--) { + *dst = *src; + src += srcRightDelta; + dst++; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes); + src_pos += srcDownDelta; + height--; + } +} + +#define BLOCKSIZE_W 32 +#define BLOCKSIZE_H 32 + +static void WSCONS_blit16blocked(Uint8 *byte_src_pos, + int srcRightDelta, + int srcDownDelta, + Uint8 *byte_dst_pos, + int dst_linebytes, + int width, + int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height > 0) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w > 0; w -= BLOCKSIZE_W) { + WSCONS_blit16((Uint8 *)src, + srcRightDelta, + srcDownDelta, + (Uint8 *)dst, + dst_linebytes, + min(w, BLOCKSIZE_W), + min(height, BLOCKSIZE_H)); + src += srcRightDelta * BLOCKSIZE_W; + dst += BLOCKSIZE_W; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H); + src_pos += srcDownDelta * BLOCKSIZE_H; + height -= BLOCKSIZE_H; + } +} + +static void WSCONS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + int width = private->SDL_modelist[0]->w; + int height = private->SDL_modelist[0]->h; + int bytesPerPixel = (private->info.depth + 7) / 8; + int i; + + if (!private->shadowFB) { + return; + } + + if (private->info.depth != 16) { + WSCONS_ReportError("Shadow copy only implemented for 16 bpp"); + return; + } + + for (i = 0; i < numrects; i++) { + int x1, y1, x2, y2; + int scr_x1, scr_y1, scr_x2, scr_y2; + int sha_x1, sha_y1; + int shadowRightDelta; /* Address change when moving right in dest */ + int shadowDownDelta; /* Address change when moving down in dest */ + Uint8 *src_start; + Uint8 *dst_start; + + x1 = rects[i].x; + y1 = rects[i].y; + x2 = x1 + rects[i].w; + y2 = y1 + rects[i].h; + + if (x1 < 0) { + x1 = 0; + } else if (x1 > width) { + x1 = width; + } + if (x2 < 0) { + x2 = 0; + } else if (x2 > width) { + x2 = width; + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > height) { + y1 = height; + } + if (y2 < 0) { + y2 = 0; + } else if (y2 > height) { + y2 = height; + } + if (x2 <= x1 || y2 <= y1) { + continue; + } + + switch (private->rotate) { + case WSCONS_ROTATE_NONE: + sha_x1 = scr_x1 = x1; + sha_y1 = scr_y1 = y1; + scr_x2 = x2; + scr_y2 = y2; + shadowRightDelta = 1; + shadowDownDelta = width; + break; + case WSCONS_ROTATE_CCW: + scr_x1 = y1; + scr_y1 = width - x2; + scr_x2 = y2; + scr_y2 = width - x1; + sha_x1 = x2 - 1; + sha_y1 = y1; + shadowRightDelta = width; + shadowDownDelta = -1; + break; + case WSCONS_ROTATE_UD: + scr_x1 = width - x2; + scr_y1 = height - y2; + scr_x2 = width - x1; + scr_y2 = height - y1; + sha_x1 = x2 - 1; + sha_y1 = y2 - 1; + shadowRightDelta = -1; + shadowDownDelta = -width; + break; + case WSCONS_ROTATE_CW: + scr_x1 = height - y2; + scr_y1 = x1; + scr_x2 = height - y1; + scr_y2 = x2; + sha_x1 = x1; + sha_y1 = y2 - 1; + shadowRightDelta = -width; + shadowDownDelta = 1; + break; + default: + WSCONS_ReportError("Unknown rotation"); + return; + } + + src_start = private->shadowmem + (sha_y1 * width + sha_x1) * bytesPerPixel; + dst_start = private->physmem + scr_y1 * private->physlinebytes + + scr_x1 * bytesPerPixel; + + private->blitFunc(src_start, + shadowRightDelta, + shadowDownDelta, + dst_start, + private->physlinebytes, + scr_x2 - scr_x1, + scr_y2 - scr_y1); + } +} + +int WSCONS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + return 0; +} + +/* + * Note: If we are terminated, this could be called in the middle of + * another SDL video routine -- notably UpdateRects. + */ +void WSCONS_VideoQuit(_THIS) +{ + int mode = WSDISPLAYIO_MODE_EMUL; + + if (private->shadowmem != NULL) { + SDL_free(private->shadowmem); + private->shadowmem = NULL; + } + private->fbstart = NULL; + if (this->screen != NULL) { + this->screen->pixels = NULL; + } + + if (private->SDL_modelist[0] != NULL) { + SDL_free(private->SDL_modelist[0]); + private->SDL_modelist[0] = NULL; + } + + if (ioctl(private->fd, WSDISPLAYIO_SMODE, &mode) == -1) { + WSCONS_ReportError("ioctl SMODE"); + } + + WSCONS_ReleaseKeyboard(this); + + if (private->fd != -1) { + close(private->fd); + private->fd = -1; + } +} diff --git a/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h new file mode 100644 index 0000000..9d75c17 --- /dev/null +++ b/3rdparty/SDL/src/video/wscons/SDL_wsconsvideo.h @@ -0,0 +1,76 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_wsconsvideo_h +#define _SDL_wsconsvideo_h + +#include <sys/time.h> +#include <termios.h> +#include <dev/wscons/wsconsio.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" + +void WSCONS_ReportError(char *fmt, ...); + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this +#define private (this->hidden) + +/* Private display data */ + +typedef void WSCONS_bitBlit(Uint8 *src_pos, + int srcRightDelta, // pixels, not bytes + int srcDownDelta, // pixels, not bytes + Uint8 *dst_pos, + int dst_linebytes, + int width, + int height); + +struct SDL_PrivateVideoData { + int fd; /* file descriptor of open device */ + struct wsdisplay_fbinfo info; /* frame buffer characteristics */ + int physlinebytes; /* number of bytes per row */ + int redMask, greenMask, blueMask; + + Uint8 *fbstart; /* These refer to the surface used, */ + int fblinebytes; /* physical frame buffer or shadow. */ + + size_t fbmem_len; + Uint8 *physmem; + Uint8 *shadowmem; + int rotate; + int shadowFB; /* Tells whether a shadow is being used. */ + + WSCONS_bitBlit *blitFunc; + + SDL_Rect *SDL_modelist[2]; + + unsigned int kbdType; + int did_save_tty; + struct termios saved_tty; +}; + + +#endif /* _SDL_wsconsvideo_h */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dga.c b/3rdparty/SDL/src/video/x11/SDL_x11dga.c new file mode 100644 index 0000000..e1c0c2e --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dga.c @@ -0,0 +1,90 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is currently only used to enable DGA mouse. + There is a completely separate DGA driver that is fullscreen-only. +*/ + +#include "SDL_video.h" +#include "../SDL_cursor_c.h" +#include "SDL_x11dga_c.h" + +/* Global for the error handler */ +int dga_event, dga_error = -1; + +void X11_EnableDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + static int use_dgamouse = -1; + + /* Check configuration to see if we should use DGA mouse */ + if ( use_dgamouse < 0 ) { + int dga_major, dga_minor; + int dga_flags; + const char *env_use_dgamouse; + + use_dgamouse = 1; + env_use_dgamouse = SDL_getenv("SDL_VIDEO_X11_DGAMOUSE"); + if ( env_use_dgamouse ) { + use_dgamouse = SDL_atoi(env_use_dgamouse); + } + /* Check for buggy X servers */ + if ( use_dgamouse && BUGGY_XFREE86(==, 4000) ) { + use_dgamouse = 0; + } + if ( !use_dgamouse || !local_X11 || + !SDL_NAME(XF86DGAQueryExtension)(SDL_Display, &dga_event, &dga_error) || + !SDL_NAME(XF86DGAQueryVersion)(SDL_Display, &dga_major, &dga_minor) || + !SDL_NAME(XF86DGAQueryDirectVideo)(SDL_Display, SDL_Screen, &dga_flags) || + !(dga_flags & XF86DGADirectPresent) ) { + use_dgamouse = 0; + } + } + + if ( use_dgamouse && !(using_dga & DGA_MOUSE) ) { + if ( SDL_NAME(XF86DGADirectVideo)(SDL_Display, SDL_Screen, XF86DGADirectMouse) ) { + using_dga |= DGA_MOUSE; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ +} + +/* Argh. Glide resets DGA mouse mode when it makes the context current! */ +void X11_CheckDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + if ( using_dga & DGA_MOUSE ) { + SDL_NAME(XF86DGADirectVideo)(SDL_Display,SDL_Screen,XF86DGADirectMouse); + } +#endif +} + +void X11_DisableDGAMouse(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + if ( using_dga & DGA_MOUSE ) { + SDL_NAME(XF86DGADirectVideo)(SDL_Display, SDL_Screen, 0); + using_dga &= ~DGA_MOUSE; + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h b/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h new file mode 100644 index 0000000..a57511c --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dga_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Different DGA access states */ +#define DGA_GRAPHICS 0x01 +#define DGA_KEYBOARD 0x02 +#define DGA_MOUSE 0x04 + +extern void X11_EnableDGAMouse(_THIS); +extern void X11_CheckDGAMouse(_THIS); +extern void X11_DisableDGAMouse(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dyn.c b/3rdparty/SDL/src/video/x11/SDL_x11dyn.c new file mode 100644 index 0000000..7058add --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dyn.c @@ -0,0 +1,222 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#define DEBUG_DYNAMIC_X11 0 + +#include "SDL_x11dyn.h" + +#if DEBUG_DYNAMIC_X11 +#include <stdio.h> +#endif + +#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + +#include "SDL_name.h" +#include "SDL_loadso.h" + +typedef struct +{ + void *lib; + const char *libname; +} x11dynlib; + +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC +#define SDL_VIDEO_DRIVER_X11_DYNAMIC NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER NULL +#endif +#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR +#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL +#endif + +static x11dynlib x11libs[] = +{ + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER }, + { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR }, +}; + +static void *X11_GetSym(const char *fnname, int *rc) +{ + void *fn = NULL; + int i; + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].lib != NULL) + { + fn = SDL_LoadFunction(x11libs[i].lib, fnname); + if (fn != NULL) + break; + } + } + + #if DEBUG_DYNAMIC_X11 + if (fn != NULL) + printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, *fn); + else + printf("X11: Symbol '%s' NOT FOUND!\n", fnname); + #endif + + if (fn == NULL) + *rc = 0; /* kill this module. */ + + return fn; +} + + +/* Define all the function pointers and wrappers... */ +#define SDL_X11_MODULE(modname) +#define SDL_X11_SYM(rc,fn,params,args,ret) \ + static rc (*p##fn) params = NULL; \ + rc fn params { ret p##fn args ; } +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM +#endif /* SDL_VIDEO_DRIVER_X11_DYNAMIC */ + +/* Annoying varargs entry point... */ +#ifdef X_HAVE_UTF8_STRING +XIC (*pXCreateIC)(XIM,...) = NULL; +char *(*pXGetICValues)(XIC, ...) = NULL; +#endif + +/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */ +#define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 1; +#define SDL_X11_SYM(rc,fn,params,args,ret) +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM + + +static void *SDL_XGetRequest_workaround(Display* dpy, CARD8 type, size_t len) +{ + xReq *req; + WORD64ALIGN + if (dpy->bufptr + len > dpy->bufmax) + _XFlush(dpy); + dpy->last_req = dpy->bufptr; + req = (xReq*)dpy->bufptr; + req->reqType = type; + req->length = len / 4; + dpy->bufptr += len; + dpy->request++; + return req; +} + +static int x11_load_refcount = 0; + +void SDL_X11_UnloadSymbols(void) +{ + #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + /* Don't actually unload if more than one module is using the libs... */ + if (x11_load_refcount > 0) { + if (--x11_load_refcount == 0) { + int i; + + /* set all the function pointers to NULL. */ + #define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; + #define SDL_X11_SYM(rc,fn,params,args,ret) p##fn = NULL; + #include "SDL_x11sym.h" + #undef SDL_X11_MODULE + #undef SDL_X11_SYM + + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = NULL; + pXGetICValues = NULL; + #endif + + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].lib != NULL) { + SDL_UnloadObject(x11libs[i].lib); + x11libs[i].lib = NULL; + } + } + } + } + #endif +} + +/* returns non-zero if all needed symbols were loaded. */ +int SDL_X11_LoadSymbols(void) +{ + int rc = 1; /* always succeed if not using Dynamic X11 stuff. */ + + #ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC + /* deal with multiple modules (dga, x11, etc) needing these symbols... */ + if (x11_load_refcount++ == 0) { + int i; + int *thismod = NULL; + for (i = 0; i < SDL_TABLESIZE(x11libs); i++) { + if (x11libs[i].libname != NULL) { + x11libs[i].lib = SDL_LoadObject(x11libs[i].libname); + } + } + #define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname; + #define SDL_X11_SYM(rc,fn,params,args,ret) \ + p##fn = (rc(*)params) X11_GetSym(#fn, thismod); + #include "SDL_x11sym.h" + #undef SDL_X11_MODULE + #undef SDL_X11_SYM + + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = (XIC(*)(XIM,...)) X11_GetSym("XCreateIC", + &SDL_X11_HAVE_UTF8); + pXGetICValues = (char * (*)(XIC,...)) X11_GetSym("XGetICValues", + &SDL_X11_HAVE_UTF8); + #endif + + /* + * In case we're built with newer Xlib headers, we need to make sure + * that _XGetRequest() is available, even on older systems. + * Otherwise, various Xlib macros we use will call a NULL pointer. + */ + if (!SDL_X11_HAVE_XGETREQUEST) { + p_XGetRequest = SDL_XGetRequest_workaround; + } + + if (SDL_X11_HAVE_BASEXLIB) { /* all required symbols loaded. */ + SDL_ClearError(); + } else { + SDL_X11_UnloadSymbols(); /* in case something got loaded... */ + rc = 0; + } + } + #else + #if DEBUG_DYNAMIC_X11 + printf("X11: No dynamic X11 support in this build of SDL.\n"); + #endif + #ifdef X_HAVE_UTF8_STRING + pXCreateIC = XCreateIC; + pXGetICValues = XGetICValues; + #endif + #endif + + return rc; +} + +/* end of SDL_x11dyn.c ... */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11dyn.h b/3rdparty/SDL/src/video/x11/SDL_x11dyn.h new file mode 100644 index 0000000..c2ff82a --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11dyn.h @@ -0,0 +1,93 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11dyn_h +#define _SDL_x11dyn_h + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +/* Apparently some X11 systems can't include this multiple times... */ +#ifndef SDL_INCLUDED_XLIBINT_H +#define SDL_INCLUDED_XLIBINT_H 1 +#include <X11/Xlibint.h> +#endif + +#include <X11/Xproto.h> + +#include "../Xext/extensions/Xext.h" +#include "../Xext/extensions/extutil.h" + +#ifndef NO_SHARED_MEMORY +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#endif + +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include <X11/extensions/Xrandr.h> +#endif + +/* + * When using the "dynamic X11" functionality, we duplicate all the Xlib + * symbols that would be referenced by SDL inside of SDL itself. + * These duplicated symbols just serve as passthroughs to the functions + * in Xlib, that was dynamically loaded. + * + * This allows us to use Xlib as-is when linking against it directly, but + * also handles all the strange cases where there was code in the Xlib + * headers that may or may not exist or vary on a given platform. + */ +#ifdef __cplusplus +extern "C" { +#endif + +/* evil function signatures... */ +typedef Bool (*SDL_X11_XESetWireToEventRetType)(Display*,XEvent*,xEvent*); +typedef int (*SDL_X11_XSynchronizeRetType)(Display*); +typedef Status (*SDL_X11_XESetEventToWireRetType)(Display*,XEvent*,xEvent*); + +int SDL_X11_LoadSymbols(void); +void SDL_X11_UnloadSymbols(void); + +/* That's really annoying...make this a function pointer no matter what. */ +#ifdef X_HAVE_UTF8_STRING +extern XIC (*pXCreateIC)(XIM,...); +extern char *(*pXGetICValues)(XIC, ...); +#endif + +/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */ +#define SDL_X11_MODULE(modname) extern int SDL_X11_HAVE_##modname; +#define SDL_X11_SYM(rc,fn,params,args,ret) +#include "SDL_x11sym.h" +#undef SDL_X11_MODULE +#undef SDL_X11_SYM + + +#ifdef __cplusplus +} +#endif + +#endif /* !defined _SDL_x11dyn_h */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11events.c b/3rdparty/SDL/src/video/x11/SDL_x11events.c new file mode 100644 index 0000000..559a001 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11events.c @@ -0,0 +1,1414 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting X11 events into SDL events */ + +#include <setjmp.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#ifdef __SVR4 +#include <X11/Sunkeysym.h> +#endif +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> + +#include "SDL_timer.h" +#include "SDL_syswm.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" +#include "SDL_x11gamma_c.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11mouse_c.h" +#include "SDL_x11events_c.h" + + +/* Define this if you want to debug X11 events */ +/*#define DEBUG_XEVENTS*/ + +/* The translation tables from an X11 keysym to a SDL keysym */ +static SDLKey ODD_keymap[256]; +static SDLKey MISC_keymap[256]; +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc); + +/* + Pending resize target for ConfigureNotify (so outdated events don't + cause inappropriate resize events) +*/ +int X11_PendingConfigureNotifyWidth = -1; +int X11_PendingConfigureNotifyHeight = -1; + +#ifdef X_HAVE_UTF8_STRING +Uint32 Utf8ToUcs4(const Uint8 *utf8) +{ + Uint32 c; + int i = 1; + int noOctets = 0; + int firstOctetMask = 0; + unsigned char firstOctet = utf8[0]; + if (firstOctet < 0x80) { + /* + Characters in the range: + 00000000 to 01111111 (ASCII Range) + are stored in one octet: + 0xxxxxxx (The same as its ASCII representation) + The least 6 significant bits of the first octet is the most 6 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 1; + firstOctetMask = 0x7F; /* 0(1111111) - The most significant bit is ignored */ + } else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */ + == 0xC0 ) { /* see if those 3 bits are 110. If so, the char is in this range */ + /* + Characters in the range: + 00000000 10000000 to 00000111 11111111 + are stored in two octets: + 110xxxxx 10xxxxxx + The least 5 significant bits of the first octet is the most 5 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 2; + firstOctetMask = 0x1F; /* 000(11111) - The most 3 significant bits are ignored */ + } else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */ + == 0xE0) { /* see if those 4 bits are 1110. If so, the char is in this range */ + /* + Characters in the range: + 00001000 00000000 to 11111111 11111111 + are stored in three octets: + 1110xxxx 10xxxxxx 10xxxxxx + The least 4 significant bits of the first octet is the most 4 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 3; + firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */ + } else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */ + == 0xF0) { /* see if those 5 bits are 11110. If so, the char is in this range */ + /* + Characters in the range: + 00000001 00000000 00000000 to 00011111 11111111 11111111 + are stored in four octets: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + The least 3 significant bits of the first octet is the most 3 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 4; + firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */ + } else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */ + == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */ + /* + Characters in the range: + 00000000 00100000 00000000 00000000 to + 00000011 11111111 11111111 11111111 + are stored in five octets: + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + The least 2 significant bits of the first octet is the most 2 significant nonzero bits + of the UCS4 representation. + */ + noOctets = 5; + firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */ + } else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */ + == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */ + /* + Characters in the range: + 00000100 00000000 00000000 00000000 to + 01111111 11111111 11111111 11111111 + are stored in six octets: + 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + The least significant bit of the first octet is the most significant nonzero bit + of the UCS4 representation. + */ + noOctets = 6; + firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */ + } else + return 0; /* The given chunk is not a valid UTF-8 encoded Unicode character */ + + /* + The least noOctets significant bits of the first octet is the most 2 significant nonzero bits + of the UCS4 representation. + The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of + firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet. + This done by AND'ing firstOctet with its mask to trim the bits used for identifying the + number of continuing octets (if any) and leave only the free bits (the x's) + Sample: + 1-octet: 0xxxxxxx & 01111111 = 0xxxxxxx + 2-octets: 110xxxxx & 00011111 = 000xxxxx + */ + c = firstOctet & firstOctetMask; + + /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */ + for (i = 1; i < noOctets; i++) { + /* A valid continuing octet is of the form 10xxxxxx */ + if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */ + != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */ + /*The given chunk is a partial sequence at the end of a string that could + begin a valid character */ + return 0; + + /* Make room for the next 6-bits */ + c <<= 6; + + /* + Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room + of c.ucs4 with them. + This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4. + */ + c |= utf8[i] & 0x3F; + } + return c; +} + +/* Given a UTF-8 encoded string pointed to by utf8 of length length in + bytes, returns the corresponding UTF-16 encoded string in the + buffer pointed to by utf16. The maximum number of UTF-16 encoding + units (i.e., Unit16s) allowed in the buffer is specified in + utf16_max_length. The return value is the number of UTF-16 + encoding units placed in the output buffer pointed to by utf16. + + In case of an error, -1 is returned, leaving some unusable partial + results in the output buffer. + + The caller must estimate the size of utf16 buffer by itself before + calling this function. Insufficient output buffer is considered as + an error, and once an error occured, this function doesn't give any + clue how large the result will be. + + The error cases include following: + + - Invalid byte sequences were in the input UTF-8 bytes. The caller + has no way to know what point in the input buffer was the + errornous byte. + + - The input contained a character (a valid UTF-8 byte sequence) + whose scalar value exceeded the range that UTF-16 can represent + (i.e., characters whose Unicode scalar value above 0x110000). + + - The output buffer has no enough space to hold entire utf16 data. + + Please note: + + - '\0'-termination is not assumed both on the input UTF-8 string + and on the output UTF-16 string; any legal zero byte in the input + UTF-8 string will be converted to a 16-bit zero in output. As a + side effect, the last UTF-16 encoding unit stored in the output + buffer will have a non-zero value if the input UTF-8 was not + '\0'-terminated. + + - UTF-8 aliases are *not* considered as an error. They are + converted to UTF-16. For example, 0xC0 0xA0, 0xE0 0x80 0xA0, + and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16 + encoding unit 0x0020. + + - Three byte UTF-8 sequences whose value corresponds to a surrogate + code or other reserved scalar value are not considered as an + error either. They may cause an invalid UTF-16 data (e.g., those + containing unpaired surrogates). + +*/ + +static int Utf8ToUtf16(const Uint8 *utf8, const int utf8_length, Uint16 *utf16, const int utf16_max_length) { + + /* p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. */ + Uint16 *p = utf16; + Uint16 const *const max_ptr = utf16 + utf16_max_length; + + /* end_of_input points to the last byte of input as opposed to the next to the last byte. */ + Uint8 const *const end_of_input = utf8 + utf8_length - 1; + + while (utf8 <= end_of_input) { + Uint8 const c = *utf8; + if (p >= max_ptr) { + /* No more output space. */ + return -1; + } + if (c < 0x80) { + /* One byte ASCII. */ + *p++ = c; + utf8 += 1; + } else if (c < 0xC0) { + /* Follower byte without preceeding leader bytes. */ + return -1; + } else if (c < 0xE0) { + /* Two byte sequence. We need one follower byte. */ + if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) { + return -1; + } + *p++ = (Uint16)(0xCF80 + (c << 6) + utf8[1]); + utf8 += 2; + } else if (c < 0xF0) { + /* Three byte sequence. We need two follower byte. */ + if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) { + return -1; + } + *p++ = (Uint16)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]); + utf8 += 3; + } else if (c < 0xF8) { + int plane; + /* Four byte sequence. We need three follower bytes. */ + if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) { + return -1; + } + plane = (-0xC8 + (c << 2) + (utf8[1] >> 4)); + if (plane == 0) { + /* This four byte sequence is an alias that + corresponds to a Unicode scalar value in BMP. + It fits in an UTF-16 encoding unit. */ + *p++ = (Uint16)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]); + } else if (plane <= 16) { + /* This is a legal four byte sequence that corresponds to a surrogate pair. */ + if (p + 1 >= max_ptr) { + /* No enough space on the output buffer for the pair. */ + return -1; + } + *p++ = (Uint16)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4)); + *p++ = (Uint16)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]); + } else { + /* This four byte sequence is out of UTF-16 code space. */ + return -1; + } + utf8 += 4; + } else { + /* Longer sequence or unused byte. */ + return -1; + } + } + return p - utf16; +} + +#endif + +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) + */ +static int X11_KeyRepeat(Display *display, XEvent *event) +{ + XEvent peekevent; + int repeated; + + repeated = 0; + if ( XPending(display) ) { + XPeekEvent(display, &peekevent); + if ( (peekevent.type == KeyPress) && + (peekevent.xkey.keycode == event->xkey.keycode) && + ((peekevent.xkey.time-event->xkey.time) < 2) ) { + repeated = 1; + XNextEvent(display, &peekevent); + } + } + return(repeated); +} + +/* Note: The X server buffers and accumulates mouse motion events, so + the motion event generated by the warp may not appear exactly as we + expect it to. We work around this (and improve performance) by only + warping the pointer when it reaches the edge, and then wait for it. +*/ +#define MOUSE_FUDGE_FACTOR 8 + +static __inline__ int X11_WarpedMotion(_THIS, XEvent *xevent) +{ + int w, h, i; + int deltax, deltay; + int posted; + + w = SDL_VideoSurface->w; + h = SDL_VideoSurface->h; + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Warped mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay); + + if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) || + (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) || + (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) { + /* Get the events that have accumulated */ + while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) { + deltax = xevent->xmotion.x - mouse_last.x; + deltay = xevent->xmotion.y - mouse_last.y; +#ifdef DEBUG_MOTION + printf("Extra mouse motion: %d,%d\n", deltax, deltay); +#endif + mouse_last.x = xevent->xmotion.x; + mouse_last.y = xevent->xmotion.y; + posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay); + } + mouse_last.x = w/2; + mouse_last.y = h/2; + XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, + mouse_last.x, mouse_last.y); + for ( i=0; i<10; ++i ) { + XMaskEvent(SDL_Display, PointerMotionMask, xevent); + if ( (xevent->xmotion.x > + (mouse_last.x-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.x < + (mouse_last.x+MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y > + (mouse_last.y-MOUSE_FUDGE_FACTOR)) && + (xevent->xmotion.y < + (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) { + break; + } +#ifdef DEBUG_XEVENTS + printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y); +#endif + } +#ifdef DEBUG_XEVENTS + if ( i == 10 ) { + printf("Warning: didn't detect mouse warp motion\n"); + } +#endif + } + return(posted); +} + +static int X11_DispatchEvent(_THIS) +{ + int posted; + XEvent xevent; + + SDL_memset(&xevent, '\0', sizeof (XEvent)); /* valgrind fix. --ryan. */ + XNextEvent(SDL_Display, &xevent); + + /* Discard KeyRelease and KeyPress events generated by auto-repeat. + We need to do it before passing event to XFilterEvent. Otherwise, + KeyRelease aware IMs are confused... */ + if ( xevent.type == KeyRelease + && X11_KeyRepeat(SDL_Display, &xevent) ) { + return 0; + } + +#ifdef X_HAVE_UTF8_STRING + /* If we are translating with IM, we need to pass all events + to XFilterEvent, and discard those filtered events immediately. */ + if ( SDL_TranslateUNICODE + && SDL_IM != NULL + && XFilterEvent(&xevent, None) ) { + return 0; + } +#endif + + posted = 0; + switch (xevent.type) { + + /* Gaining mouse coverage? */ + case EnterNotify: { +#ifdef DEBUG_XEVENTS +printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y); +if ( xevent.xcrossing.mode == NotifyGrab ) +printf("Mode: NotifyGrab\n"); +if ( xevent.xcrossing.mode == NotifyUngrab ) +printf("Mode: NotifyUngrab\n"); +#endif + if ( this->input_grab == SDL_GRAB_OFF ) { + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xcrossing.x, + xevent.xcrossing.y); + } + break; + + /* Losing mouse coverage? */ + case LeaveNotify: { +#ifdef DEBUG_XEVENTS +printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y); +if ( xevent.xcrossing.mode == NotifyGrab ) +printf("Mode: NotifyGrab\n"); +if ( xevent.xcrossing.mode == NotifyUngrab ) +printf("Mode: NotifyUngrab\n"); +#endif + if ( (xevent.xcrossing.mode != NotifyGrab) && + (xevent.xcrossing.mode != NotifyUngrab) && + (xevent.xcrossing.detail != NotifyInferior) ) { + if ( this->input_grab == SDL_GRAB_OFF ) { + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } else { + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xcrossing.x, + xevent.xcrossing.y); + } + } + } + break; + + /* Gaining input focus? */ + case FocusIn: { +#ifdef DEBUG_XEVENTS +printf("FocusIn!\n"); +#endif + posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + XSetICFocus(SDL_IC); + } +#endif + /* Queue entry into fullscreen mode */ + switch_waiting = 0x01 | SDL_FULLSCREEN; + switch_time = SDL_GetTicks() + 1500; + } + break; + + /* Losing input focus? */ + case FocusOut: { +#ifdef DEBUG_XEVENTS +printf("FocusOut!\n"); +#endif + posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS); + +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + XUnsetICFocus(SDL_IC); + } +#endif + /* Queue leaving fullscreen mode */ + switch_waiting = 0x01; + switch_time = SDL_GetTicks() + 200; + } + break; + +#ifdef X_HAVE_UTF8_STRING + /* Some IM requires MappingNotify to be passed to + XRefreshKeyboardMapping by the app. */ + case MappingNotify: { + XRefreshKeyboardMapping(&xevent.xmapping); + } + break; +#endif /* X_HAVE_UTF8_STRING */ + + /* Generated upon EnterWindow and FocusIn */ + case KeymapNotify: { +#ifdef DEBUG_XEVENTS +printf("KeymapNotify!\n"); +#endif + X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); + } + break; + + /* Mouse motion? */ + case MotionNotify: { + if ( SDL_VideoSurface ) { + if ( mouse_relative ) { + if ( using_dga & DGA_MOUSE ) { +#ifdef DEBUG_MOTION + printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root); +#endif + posted = SDL_PrivateMouseMotion(0, 1, + xevent.xmotion.x_root, + xevent.xmotion.y_root); + } else { + posted = X11_WarpedMotion(this,&xevent); + } + } else { +#ifdef DEBUG_MOTION + printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, + xevent.xmotion.x, + xevent.xmotion.y); + } + } + } + break; + + /* Mouse button press? */ + case ButtonPress: { + posted = SDL_PrivateMouseButton(SDL_PRESSED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Mouse button release? */ + case ButtonRelease: { + posted = SDL_PrivateMouseButton(SDL_RELEASED, + xevent.xbutton.button, 0, 0); + } + break; + + /* Key press? */ + case KeyPress: { + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + +#ifdef DEBUG_XEVENTS +printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + /* If we're not doing translation, we're done! */ + if ( !SDL_TranslateUNICODE ) { + /* Get the translated SDL virtual keysym and put it on the queue.*/ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + break; + } + + /* Look up the translated value for the key event */ +#ifdef X_HAVE_UTF8_STRING + if ( SDL_IC != NULL ) { + Status status; + KeySym xkeysym; + int i; + /* A UTF-8 character can be at most 6 bytes */ + /* ... It's true, but Xutf8LookupString can + return more than one characters. Moreover, + the spec. put no upper bound, so we should + be ready for longer strings. */ + char keybuf[32]; + char *keydata = keybuf; + int count; + Uint16 utf16buf[32]; + Uint16 *utf16data = utf16buf; + int utf16size; + int utf16length; + + count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status); + if (XBufferOverflow == status) { + /* The IM has just generated somewhat long + string. We need a longer buffer in this + case. */ + keydata = SDL_malloc(count); + if ( keydata == NULL ) { + SDL_OutOfMemory(); + break; + } + count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status); + } + + switch (status) { + + case XBufferOverflow: { + /* Oops! We have allocated the bytes as + requested by Xutf8LookupString, so the + length of the buffer must be + sufficient. This case should never + happen! */ + SDL_SetError("Xutf8LookupString indicated a double buffer overflow!"); + break; + } + + case XLookupChars: + case XLookupBoth: { + if (0 == count) { + break; + } + + /* We got a converted string from IM. Make + sure to deliver all characters to the + application as SDL events. Note that + an SDL event can only carry one UTF-16 + encoding unit, and a surrogate pair is + delivered as two SDL events. I guess + this behaviour is probably _imported_ + from Windows or MacOS. To do so, we need + to convert the UTF-8 data into UTF-16 + data (not UCS4/UTF-32!). We need an + estimate of the number of UTF-16 encoding + units here. The worst case is pure ASCII + string. Assume so. */ + /* In 1.3 SDL may have a text event instead, that + carries the whole UTF-8 string with it. */ + utf16size = count * sizeof(Uint16); + if (utf16size > sizeof(utf16buf)) { + utf16data = (Uint16 *) SDL_malloc(utf16size); + if (utf16data == NULL) { + SDL_OutOfMemory(); + break; + } + } + utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size); + if (utf16length < 0) { + /* The keydata contained an invalid byte + sequence. It should be a bug of the IM + or Xlib... */ + SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!"); + break; + } + + /* Deliver all UTF-16 encoding units. At + this moment, SDL event queue has a + fixed size (128 events), and an SDL + event can hold just one UTF-16 encoding + unit. So, if we receive more than 128 + UTF-16 encoding units from a commit, + exceeded characters will be lost. */ + for (i = 0; i < utf16length - 1; i++) { + keysym.scancode = 0; + keysym.sym = SDLK_UNKNOWN; + keysym.mod = KMOD_NONE; + keysym.unicode = utf16data[i]; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + /* The keysym for the last character carries the + scancode and symbol that corresponds to the X11 + keycode. */ + if (utf16length > 0) { + keysym.scancode = keycode; + keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0); + keysym.mod = KMOD_NONE; + keysym.unicode = utf16data[utf16length - 1]; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case XLookupKeySym: { + /* I'm not sure whether it is possible that + a zero keycode makes XLookupKeySym + status. What I'm sure is that a + combination of a zero scan code and a non + zero sym makes SDL_PrivateKeyboard + strange state... So, just discard it. + If this doesn't work, I'm receiving bug + reports, and I can know under what + condition this case happens. */ + if (keycode) { + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case XLookupNone: { + /* IM has eaten the event. */ + break; + } + + default: + /* An unknown status from Xutf8LookupString. */ + SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status"); + } + + /* Release dynamic buffers if allocated. */ + if (keydata != NULL && keybuf != keydata) { + SDL_free(keydata); + } + if (utf16data != NULL && utf16buf != utf16data) { + SDL_free(utf16data); + } + } + else +#endif + { + static XComposeStatus state; + char keybuf[32]; + + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if ( XLookupString(&xevent.xkey, + keybuf, sizeof(keybuf), + NULL, &state) ) { + /* + * FIXME: XLookupString() may yield more than one + * character, so we need a mechanism to allow for + * this (perhaps null keypress events with a + * unicode value) + */ + keysym.unicode = (Uint8)keybuf[0]; + } + + posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + } + break; + + /* Key release? */ + case KeyRelease: { + SDL_keysym keysym; + KeyCode keycode = xevent.xkey.keycode; + + if (keycode == 0) { + /* There should be no KeyRelease for keycode == 0, + since it is a notification from IM but a real + keystroke. */ + /* We need to emit some diagnostic message here. */ + break; + } + +#ifdef DEBUG_XEVENTS +printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); +#endif + + /* Get the translated SDL virtual keysym */ + keysym.scancode = keycode; + keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + + posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + + /* Have we been iconified? */ + case UnmapNotify: { +#ifdef DEBUG_XEVENTS +printf("UnmapNotify!\n"); +#endif + /* If we're active, make ourselves inactive */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + /* Swap out the gamma before we go inactive */ + X11_SwapVidModeGamma(this); + + /* Send an internal deactivate event */ + posted = SDL_PrivateAppActive(0, + SDL_APPACTIVE|SDL_APPINPUTFOCUS); + } + } + break; + + /* Have we been restored? */ + case MapNotify: { +#ifdef DEBUG_XEVENTS +printf("MapNotify!\n"); +#endif + /* If we're not active, make ourselves active */ + if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) { + /* Send an internal activate event */ + posted = SDL_PrivateAppActive(1, SDL_APPACTIVE); + + /* Now that we're active, swap the gamma back */ + X11_SwapVidModeGamma(this); + } + + if ( SDL_VideoSurface && + (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) { + X11_EnterFullScreen(this); + } else { + X11_GrabInputNoLock(this, this->input_grab); + } + X11_CheckMouseModeNoLock(this); + + if ( SDL_VideoSurface ) { + X11_RefreshDisplay(this); + } + } + break; + + /* Have we been resized or moved? */ + case ConfigureNotify: { +#ifdef DEBUG_XEVENTS +printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); +#endif + if ((X11_PendingConfigureNotifyWidth != -1) && + (X11_PendingConfigureNotifyHeight != -1)) { + if ((xevent.xconfigure.width != X11_PendingConfigureNotifyWidth) && + (xevent.xconfigure.height != X11_PendingConfigureNotifyHeight)) { + /* Event is from before the resize, so ignore. */ + break; + } + X11_PendingConfigureNotifyWidth = -1; + X11_PendingConfigureNotifyHeight = -1; + } + if ( SDL_VideoSurface ) { + if ((xevent.xconfigure.width != SDL_VideoSurface->w) || + (xevent.xconfigure.height != SDL_VideoSurface->h)) { + /* FIXME: Find a better fix for the bug with KDE 1.2 */ + if ( ! ((xevent.xconfigure.width == 32) && + (xevent.xconfigure.height == 32)) ) { + SDL_PrivateResize(xevent.xconfigure.width, + xevent.xconfigure.height); + } + } else { + /* OpenGL windows need to know about the change */ + if ( SDL_VideoSurface->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } + } + } + } + break; + + /* Have we been requested to quit (or another client message?) */ + case ClientMessage: { + if ( (xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) ) + { + posted = SDL_PrivateQuit(); + } else + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.subsystem = SDL_SYSWM_X11; + wmmsg.event.xevent = xevent; + posted = SDL_PrivateSysWMEvent(&wmmsg); + } + } + break; + + /* Do we need to refresh ourselves? */ + case Expose: { +#ifdef DEBUG_XEVENTS +printf("Expose (count = %d)\n", xevent.xexpose.count); +#endif + if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) { + X11_RefreshDisplay(this); + } + } + break; + + default: { +#ifdef DEBUG_XEVENTS +printf("Unhandled event %d\n", xevent.type); +#endif + /* Only post the event if we're watching for it */ + if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { + SDL_SysWMmsg wmmsg; + + SDL_VERSION(&wmmsg.version); + wmmsg.subsystem = SDL_SYSWM_X11; + wmmsg.event.xevent = xevent; + posted = SDL_PrivateSysWMEvent(&wmmsg); + } + } + break; + } + return(posted); +} + +/* Ack! XPending() actually performs a blocking read if no events available */ +int X11_Pending(Display *display) +{ + /* Flush the display connection and look to see if events are queued */ + XFlush(display); + if ( XEventsQueued(display, QueuedAlready) ) { + return(1); + } + + /* More drastic measures are required -- see if X is ready to talk */ + { + static struct timeval zero_time; /* static == 0 */ + int x11_fd; + fd_set fdset; + + x11_fd = ConnectionNumber(display); + FD_ZERO(&fdset); + FD_SET(x11_fd, &fdset); + if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) { + return(XPending(display)); + } + } + + /* Oh well, nothing is ready .. */ + return(0); +} + +void X11_PumpEvents(_THIS) +{ + int pending; + + /* Update activity every five seconds to prevent screensaver. --ryan. */ + if (!allow_screensaver) { + static Uint32 screensaverTicks; + Uint32 nowTicks = SDL_GetTicks(); + if ((nowTicks - screensaverTicks) > 5000) { + XResetScreenSaver(SDL_Display); + screensaverTicks = nowTicks; + } + } + + /* Keep processing pending events */ + pending = 0; + while ( X11_Pending(SDL_Display) ) { + X11_DispatchEvent(this); + ++pending; + } + if ( switch_waiting ) { + Uint32 now; + + now = SDL_GetTicks(); + if ( pending || !SDL_VideoSurface ) { + /* Try again later... */ + if ( switch_waiting & SDL_FULLSCREEN ) { + switch_time = now + 1500; + } else { + switch_time = now + 200; + } + } else if ( (int)(switch_time-now) <= 0 ) { + Uint32 go_fullscreen; + + go_fullscreen = switch_waiting & SDL_FULLSCREEN; + switch_waiting = 0; + if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) { + if ( go_fullscreen ) { + X11_EnterFullScreen(this); + } else { + X11_LeaveFullScreen(this); + } + } + /* Handle focus in/out when grabbed */ + if ( go_fullscreen ) { + X11_GrabInputNoLock(this, this->input_grab); + } else { + X11_GrabInputNoLock(this, SDL_GRAB_OFF); + } + X11_CheckMouseModeNoLock(this); + } + } +} + +void X11_InitKeymap(void) +{ + int i; + + /* Odd keys used in international keyboards */ + for ( i=0; i<SDL_arraysize(ODD_keymap); ++i ) + ODD_keymap[i] = SDLK_UNKNOWN; + + /* Some of these might be mappable to an existing SDLK_ code */ + ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE; + ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE; +#ifdef XK_dead_hook + ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE; +#endif +#ifdef XK_dead_horn + ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE; +#endif + +#ifdef XK_dead_circumflex + /* These X keysyms have 0xFE as the high byte */ + ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET; +#endif +#ifdef XK_ISO_Level3_Shift + ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */ +#endif + + /* Map the miscellaneous keys */ + for ( i=0; i<SDL_arraysize(MISC_keymap); ++i ) + MISC_keymap[i] = SDLK_UNKNOWN; + + /* These X keysyms have 0xFF as the high byte */ + MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE; + MISC_keymap[XK_Tab&0xFF] = SDLK_TAB; + MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR; + MISC_keymap[XK_Return&0xFF] = SDLK_RETURN; + MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE; + MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE; + MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE; + + MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0; /* Keypad 0-9 */ + MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1; + MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2; + MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3; + MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4; + MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5; + MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6; + MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7; + MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8; + MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9; + MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0; + MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1; + MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2; + MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3; + MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4; + MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5; + MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6; + MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7; + MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8; + MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9; + MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD; + MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE; + MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY; + MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS; + MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS; + MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER; + MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS; + + MISC_keymap[XK_Up&0xFF] = SDLK_UP; + MISC_keymap[XK_Down&0xFF] = SDLK_DOWN; + MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT; + MISC_keymap[XK_Left&0xFF] = SDLK_LEFT; + MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT; + MISC_keymap[XK_Home&0xFF] = SDLK_HOME; + MISC_keymap[XK_End&0xFF] = SDLK_END; + MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP; + MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN; + + MISC_keymap[XK_F1&0xFF] = SDLK_F1; + MISC_keymap[XK_F2&0xFF] = SDLK_F2; + MISC_keymap[XK_F3&0xFF] = SDLK_F3; + MISC_keymap[XK_F4&0xFF] = SDLK_F4; + MISC_keymap[XK_F5&0xFF] = SDLK_F5; + MISC_keymap[XK_F6&0xFF] = SDLK_F6; + MISC_keymap[XK_F7&0xFF] = SDLK_F7; + MISC_keymap[XK_F8&0xFF] = SDLK_F8; + MISC_keymap[XK_F9&0xFF] = SDLK_F9; + MISC_keymap[XK_F10&0xFF] = SDLK_F10; + MISC_keymap[XK_F11&0xFF] = SDLK_F11; + MISC_keymap[XK_F12&0xFF] = SDLK_F12; + MISC_keymap[XK_F13&0xFF] = SDLK_F13; + MISC_keymap[XK_F14&0xFF] = SDLK_F14; + MISC_keymap[XK_F15&0xFF] = SDLK_F15; + + MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK; + MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK; + MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK; + MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT; + MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT; + MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL; + MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL; + MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT; + MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT; + MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA; + MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA; + MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */ + MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */ + MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */ + MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */ + + MISC_keymap[XK_Help&0xFF] = SDLK_HELP; + MISC_keymap[XK_Print&0xFF] = SDLK_PRINT; + MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ; + MISC_keymap[XK_Break&0xFF] = SDLK_BREAK; + MISC_keymap[XK_Menu&0xFF] = SDLK_MENU; + MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */ +} + +/* Get the translated SDL virtual keysym */ +SDLKey X11_TranslateKeycode(Display *display, KeyCode kc) +{ + KeySym xsym; + SDLKey key; + + xsym = XKeycodeToKeysym(display, kc, 0); +#ifdef DEBUG_KEYS + fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym); +#endif + key = SDLK_UNKNOWN; + if ( xsym ) { + switch (xsym>>8) { + case 0x1005FF: +#ifdef SunXK_F36 + if ( xsym == SunXK_F36 ) + key = SDLK_F11; +#endif +#ifdef SunXK_F37 + if ( xsym == SunXK_F37 ) + key = SDLK_F12; +#endif + break; + case 0x00: /* Latin 1 */ + key = (SDLKey)(xsym & 0xFF); + break; + case 0x01: /* Latin 2 */ + case 0x02: /* Latin 3 */ + case 0x03: /* Latin 4 */ + case 0x04: /* Katakana */ + case 0x05: /* Arabic */ + case 0x06: /* Cyrillic */ + case 0x07: /* Greek */ + case 0x08: /* Technical */ + case 0x0A: /* Publishing */ + case 0x0C: /* Hebrew */ + case 0x0D: /* Thai */ + /* These are wrong, but it's better than nothing */ + key = (SDLKey)(xsym & 0xFF); + break; + case 0xFE: + key = ODD_keymap[xsym&0xFF]; + break; + case 0xFF: + key = MISC_keymap[xsym&0xFF]; + break; + default: + /* + fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n", + (unsigned int)xsym); + */ + break; + } + } else { + /* X11 doesn't know how to translate the key! */ + switch (kc) { + /* Caution: + These keycodes are from the Microsoft Keyboard + */ + case 115: + key = SDLK_LSUPER; + break; + case 116: + key = SDLK_RSUPER; + break; + case 117: + key = SDLK_MENU; + break; + default: + /* + * no point in an error message; happens for + * several keys when we get a keymap notify + */ + break; + } + } + return key; +} + +/* X11 modifier masks for various keys */ +static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask; +static unsigned num_mask, mode_switch_mask; + +static void get_modifier_masks(Display *display) +{ + static unsigned got_masks; + int i, j; + XModifierKeymap *xmods; + unsigned n; + + if(got_masks) + return; + + xmods = XGetModifierMapping(display); + n = xmods->max_keypermod; + for(i = 3; i < 8; i++) { + for(j = 0; j < n; j++) { + KeyCode kc = xmods->modifiermap[i * n + j]; + KeySym ks = XKeycodeToKeysym(display, kc, 0); + unsigned mask = 1 << i; + switch(ks) { + case XK_Num_Lock: + num_mask = mask; break; + case XK_Alt_L: + alt_l_mask = mask; break; + case XK_Alt_R: + alt_r_mask = mask; break; + case XK_Meta_L: + meta_l_mask = mask; break; + case XK_Meta_R: + meta_r_mask = mask; break; + case XK_Mode_switch: + mode_switch_mask = mask; break; + } + } + } + XFreeModifiermap(xmods); + got_masks = 1; +} + + +/* + * This function is semi-official; it is not officially exported and should + * not be considered part of the SDL API, but may be used by client code + * that *really* needs it (including legacy code). + * It is slow, though, and should be avoided if possible. + * + * Note that it isn't completely accurate either; in particular, multi-key + * sequences (dead accents, compose key sequences) will not work since the + * state has been irrevocably lost. + */ +Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers) +{ + struct SDL_VideoDevice *this = current_video; + char keybuf[32]; + int i; + KeySym xsym = 0; + XKeyEvent xkey; + Uint16 unicode; + + if ( !this || !SDL_Display ) { + return 0; + } + + SDL_memset(&xkey, 0, sizeof(xkey)); + xkey.display = SDL_Display; + + xsym = keysym; /* last resort if not found */ + for (i = 0; i < 256; ++i) { + if ( MISC_keymap[i] == keysym ) { + xsym = 0xFF00 | i; + break; + } else if ( ODD_keymap[i] == keysym ) { + xsym = 0xFE00 | i; + break; + } + } + + xkey.keycode = XKeysymToKeycode(xkey.display, xsym); + + get_modifier_masks(SDL_Display); + if(modifiers & KMOD_SHIFT) + xkey.state |= ShiftMask; + if(modifiers & KMOD_CAPS) + xkey.state |= LockMask; + if(modifiers & KMOD_CTRL) + xkey.state |= ControlMask; + if(modifiers & KMOD_MODE) + xkey.state |= mode_switch_mask; + if(modifiers & KMOD_LALT) + xkey.state |= alt_l_mask; + if(modifiers & KMOD_RALT) + xkey.state |= alt_r_mask; + if(modifiers & KMOD_LMETA) + xkey.state |= meta_l_mask; + if(modifiers & KMOD_RMETA) + xkey.state |= meta_r_mask; + if(modifiers & KMOD_NUM) + xkey.state |= num_mask; + + unicode = 0; + if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) ) + unicode = (unsigned char)keybuf[0]; + return(unicode); +} + + +/* + * Called when focus is regained, to read the keyboard state and generate + * synthetic keypress/release events. + * key_vec is a bit vector of keycodes (256 bits) + */ +void X11_SetKeyboardState(Display *display, const char *key_vec) +{ + char keys_return[32]; + int i; + Uint8 *kstate = SDL_GetKeyState(NULL); + SDLMod modstate; + Window junk_window; + int x, y; + unsigned int mask; + + /* The first time the window is mapped, we initialize key state */ + if ( ! key_vec ) { + XQueryKeymap(display, keys_return); + key_vec = keys_return; + } + + /* Get the keyboard modifier state */ + modstate = 0; + get_modifier_masks(display); + if ( XQueryPointer(display, DefaultRootWindow(display), + &junk_window, &junk_window, &x, &y, &x, &y, &mask) ) { + if ( mask & LockMask ) { + modstate |= KMOD_CAPS; + } + if ( mask & mode_switch_mask ) { + modstate |= KMOD_MODE; + } + if ( mask & num_mask ) { + modstate |= KMOD_NUM; + } + } + + /* Zero the new keyboard state and generate it */ + SDL_memset(kstate, 0, SDLK_LAST); + /* + * An obvious optimisation is to check entire longwords at a time in + * both loops, but we can't be sure the arrays are aligned so it's not + * worth the extra complexity + */ + for ( i = 0; i < 32; i++ ) { + int j; + if ( !key_vec[i] ) + continue; + for ( j = 0; j < 8; j++ ) { + if ( key_vec[i] & (1 << j) ) { + SDLKey key; + KeyCode kc = (i << 3 | j); + key = X11_TranslateKeycode(display, kc); + if ( key == SDLK_UNKNOWN ) { + continue; + } + kstate[key] = SDL_PRESSED; + switch (key) { + case SDLK_LSHIFT: + modstate |= KMOD_LSHIFT; + break; + case SDLK_RSHIFT: + modstate |= KMOD_RSHIFT; + break; + case SDLK_LCTRL: + modstate |= KMOD_LCTRL; + break; + case SDLK_RCTRL: + modstate |= KMOD_RCTRL; + break; + case SDLK_LALT: + modstate |= KMOD_LALT; + break; + case SDLK_RALT: + modstate |= KMOD_RALT; + break; + case SDLK_LMETA: + modstate |= KMOD_LMETA; + break; + case SDLK_RMETA: + modstate |= KMOD_RMETA; + break; + default: + break; + } + } + } + } + + /* Hack - set toggle key state */ + if ( modstate & KMOD_CAPS ) { + kstate[SDLK_CAPSLOCK] = SDL_PRESSED; + } else { + kstate[SDLK_CAPSLOCK] = SDL_RELEASED; + } + if ( modstate & KMOD_NUM ) { + kstate[SDLK_NUMLOCK] = SDL_PRESSED; + } else { + kstate[SDLK_NUMLOCK] = SDL_RELEASED; + } + + /* Set the final modifier state */ + SDL_SetModState(modstate); +} + +void X11_InitOSKeymap(_THIS) +{ + X11_InitKeymap(); +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11events_c.h b/3rdparty/SDL/src/video/x11/SDL_x11events_c.h new file mode 100644 index 0000000..fe26d9c --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11events_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_InitOSKeymap(_THIS); +extern void X11_PumpEvents(_THIS); +extern void X11_SetKeyboardState(Display *display, const char *key_vec); + +/* Variables to be exported */ +extern int X11_PendingConfigureNotifyWidth; +extern int X11_PendingConfigureNotifyHeight; + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gamma.c b/3rdparty/SDL/src/video/x11/SDL_x11gamma.c new file mode 100644 index 0000000..c6afbda --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gamma.c @@ -0,0 +1,142 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL.h" +#include "SDL_events.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" + +/* From the X server sources... */ +#define MAX_GAMMA 10.0 +#define MIN_GAMMA (1.0/MAX_GAMMA) + +static int X11_SetGammaNoLock(_THIS, float red, float green, float blue) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200) { + SDL_NAME(XF86VidModeGamma) gamma; + Bool succeeded; + + /* Clamp the gamma values */ + if ( red < MIN_GAMMA ) { + gamma.red = MIN_GAMMA; + } else + if ( red > MAX_GAMMA ) { + gamma.red = MAX_GAMMA; + } else { + gamma.red = red; + } + if ( green < MIN_GAMMA ) { + gamma.green = MIN_GAMMA; + } else + if ( green > MAX_GAMMA ) { + gamma.green = MAX_GAMMA; + } else { + gamma.green = green; + } + if ( blue < MIN_GAMMA ) { + gamma.blue = MIN_GAMMA; + } else + if ( blue > MAX_GAMMA ) { + gamma.blue = MAX_GAMMA; + } else { + gamma.blue = blue; + } + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + succeeded = SDL_NAME(XF86VidModeSetGamma)(SDL_Display, SDL_Screen, &gamma); + XSync(SDL_Display, False); + } else { + gamma_saved[0] = gamma.red; + gamma_saved[1] = gamma.green; + gamma_saved[2] = gamma.blue; + succeeded = True; + } + if ( succeeded ) { + ++gamma_changed; + } + return succeeded ? 0 : -1; + } +#endif + SDL_SetError("Gamma correction not supported"); + return -1; +} +int X11_SetVidModeGamma(_THIS, float red, float green, float blue) +{ + int result; + + SDL_Lock_EventThread(); + result = X11_SetGammaNoLock(this, red, green, blue); + SDL_Unlock_EventThread(); + + return(result); +} + +static int X11_GetGammaNoLock(_THIS, float *red, float *green, float *blue) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200) { + SDL_NAME(XF86VidModeGamma) gamma; + if (SDL_NAME(XF86VidModeGetGamma)(SDL_Display, SDL_Screen, &gamma)) { + *red = gamma.red; + *green = gamma.green; + *blue = gamma.blue; + return 0; + } + return -1; + } +#endif + return -1; +} +int X11_GetVidModeGamma(_THIS, float *red, float *green, float *blue) +{ + int result; + + SDL_Lock_EventThread(); + result = X11_GetGammaNoLock(this, red, green, blue); + SDL_Unlock_EventThread(); + + return(result); +} + +void X11_SaveVidModeGamma(_THIS) +{ + /* Try to save the current gamma, otherwise disable gamma control */ + if ( X11_GetGammaNoLock(this, + &gamma_saved[0], &gamma_saved[1], &gamma_saved[2]) < 0 ) { + this->SetGamma = 0; + this->GetGamma = 0; + } + gamma_changed = 0; +} +void X11_SwapVidModeGamma(_THIS) +{ + float new_gamma[3]; + + if ( gamma_changed ) { + new_gamma[0] = gamma_saved[0]; + new_gamma[1] = gamma_saved[1]; + new_gamma[2] = gamma_saved[2]; + X11_GetGammaNoLock(this, &gamma_saved[0], &gamma_saved[1], &gamma_saved[2]); + X11_SetGammaNoLock(this, new_gamma[0], new_gamma[1], new_gamma[2]); + } +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h b/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h new file mode 100644 index 0000000..c46350f --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gamma_c.h @@ -0,0 +1,32 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11gamma_h +#define _SDL_x11gamma_h + +extern int X11_SetVidModeGamma(_THIS, float red, float green, float blue); +extern int X11_GetVidModeGamma(_THIS, float *red, float *green, float *blue); +extern void X11_SaveVidModeGamma(_THIS); +extern void X11_SwapVidModeGamma(_THIS); + +#endif diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gl.c b/3rdparty/SDL/src/video/x11/SDL_x11gl.c new file mode 100644 index 0000000..aa5297b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gl.c @@ -0,0 +1,577 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11gl_c.h" + +#if defined(__IRIX__) +/* IRIX doesn't have a GL library versioning system */ +#define DEFAULT_OPENGL "libGL.so" +#elif defined(__MACOSX__) +#define DEFAULT_OPENGL "/usr/X11R6/lib/libGL.1.dylib" +#elif defined(__QNXNTO__) +#define DEFAULT_OPENGL "libGL.so.3" +#elif defined(__OpenBSD__) +#define DEFAULT_OPENGL "libGL.so.4.0" +#else +#define DEFAULT_OPENGL "libGL.so.1" +#endif + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + +/* GLX_EXT_visual_rating stuff that might not be in the system headers... */ +#ifndef GLX_VISUAL_CAVEAT_EXT +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#endif +#ifndef GLX_NONE_EXT +#define GLX_NONE_EXT 0x8000 +#endif +#ifndef GLX_SLOW_VISUAL_EXT +#define GLX_SLOW_VISUAL_EXT 0x8001 +#endif +#ifndef GLX_NON_CONFORMANT_VISUAL_EXT +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +#endif + + +#if SDL_VIDEO_OPENGL_GLX +static int glXExtensionSupported(_THIS, const char *extension) +{ + const char *extensions; + const char *start; + const char *where, *terminator; + + /* Extension names should not have spaces. */ + where = SDL_strchr(extension, ' '); + if ( where || *extension == '\0' ) { + return 0; + } + + extensions = this->gl_data->glXQueryExtensionsString(GFX_Display,SDL_Screen); + /* It takes a bit of care to be fool-proof about parsing the + * OpenGL extensions string. Don't be fooled by sub-strings, etc. + */ + + /* http://bugs.debian.org/537487 */ + if (extensions == NULL) { + return 0; + } + + start = extensions; + + for (;;) { + where = SDL_strstr(start, extension); + if (!where) break; + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') return 1; + + start = terminator; + } + return 0; +} +#endif /* SDL_VIDEO_OPENGL_GLX */ + +XVisualInfo *X11_GL_GetVisual(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + /* 64 seems nice. */ + int attribs[64]; + int i; + + /* load the gl driver from a default path */ + if ( ! this->gl_config.driver_loaded ) { + /* no driver has been loaded, use default (ourselves) */ + if ( X11_GL_LoadLibrary(this, NULL) < 0 ) { + return NULL; + } + } + + /* See if we already have a window which we must use */ + if ( SDL_windowid ) { + XWindowAttributes a; + XVisualInfo vi_in; + int out_count; + + XGetWindowAttributes(SDL_Display, SDL_Window, &a); + vi_in.screen = SDL_Screen; + vi_in.visualid = XVisualIDFromVisual(a.visual); + glx_visualinfo = XGetVisualInfo(SDL_Display, + VisualScreenMask|VisualIDMask, &vi_in, &out_count); + return glx_visualinfo; + } + + /* Setup our GLX attributes according to the gl_config. */ + i = 0; + attribs[i++] = GLX_RGBA; + attribs[i++] = GLX_RED_SIZE; + attribs[i++] = this->gl_config.red_size; + attribs[i++] = GLX_GREEN_SIZE; + attribs[i++] = this->gl_config.green_size; + attribs[i++] = GLX_BLUE_SIZE; + attribs[i++] = this->gl_config.blue_size; + + if( this->gl_config.alpha_size ) { + attribs[i++] = GLX_ALPHA_SIZE; + attribs[i++] = this->gl_config.alpha_size; + } + + if( this->gl_config.double_buffer ) { + attribs[i++] = GLX_DOUBLEBUFFER; + } + + attribs[i++] = GLX_DEPTH_SIZE; + attribs[i++] = this->gl_config.depth_size; + + if( this->gl_config.stencil_size ) { + attribs[i++] = GLX_STENCIL_SIZE; + attribs[i++] = this->gl_config.stencil_size; + } + + if( this->gl_config.accum_red_size ) { + attribs[i++] = GLX_ACCUM_RED_SIZE; + attribs[i++] = this->gl_config.accum_red_size; + } + + if( this->gl_config.accum_green_size ) { + attribs[i++] = GLX_ACCUM_GREEN_SIZE; + attribs[i++] = this->gl_config.accum_green_size; + } + + if( this->gl_config.accum_blue_size ) { + attribs[i++] = GLX_ACCUM_BLUE_SIZE; + attribs[i++] = this->gl_config.accum_blue_size; + } + + if( this->gl_config.accum_alpha_size ) { + attribs[i++] = GLX_ACCUM_ALPHA_SIZE; + attribs[i++] = this->gl_config.accum_alpha_size; + } + + if( this->gl_config.stereo ) { + attribs[i++] = GLX_STEREO; + } + + if( this->gl_config.multisamplebuffers ) { + attribs[i++] = GLX_SAMPLE_BUFFERS_ARB; + attribs[i++] = this->gl_config.multisamplebuffers; + } + + if( this->gl_config.multisamplesamples ) { + attribs[i++] = GLX_SAMPLES_ARB; + attribs[i++] = this->gl_config.multisamplesamples; + } + + if( this->gl_config.accelerated >= 0 && + glXExtensionSupported(this, "GLX_EXT_visual_rating") ) { + attribs[i++] = GLX_VISUAL_CAVEAT_EXT; + attribs[i++] = GLX_NONE_EXT; + } + +#ifdef GLX_DIRECT_COLOR /* Try for a DirectColor visual for gamma support */ + if ( !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { + attribs[i++] = GLX_X_VISUAL_TYPE; + attribs[i++] = GLX_DIRECT_COLOR; + } +#endif + attribs[i++] = None; + + glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, + SDL_Screen, attribs); +#ifdef GLX_DIRECT_COLOR + if( !glx_visualinfo && !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { /* No DirectColor visual? Try again.. */ + attribs[i-3] = None; + glx_visualinfo = this->gl_data->glXChooseVisual(GFX_Display, + SDL_Screen, attribs); + } +#endif + if( !glx_visualinfo ) { + SDL_SetError( "Couldn't find matching GLX visual"); + return NULL; + } +/* + printf("Found GLX visual 0x%x\n", glx_visualinfo->visualid); +*/ + return glx_visualinfo; +#else + SDL_SetError("X11 driver not configured with OpenGL"); + return NULL; +#endif +} + +int X11_GL_CreateWindow(_THIS, int w, int h) +{ + int retval; +#if SDL_VIDEO_OPENGL_GLX + XSetWindowAttributes attributes; + unsigned long mask; + unsigned long black; + + black = (glx_visualinfo->visual == DefaultVisual(SDL_Display, + SDL_Screen)) + ? BlackPixel(SDL_Display, SDL_Screen) : 0; + attributes.background_pixel = black; + attributes.border_pixel = black; + attributes.colormap = SDL_XColorMap; + mask = CWBackPixel | CWBorderPixel | CWColormap; + + SDL_Window = XCreateWindow(SDL_Display, WMwindow, + 0, 0, w, h, 0, glx_visualinfo->depth, + InputOutput, glx_visualinfo->visual, + mask, &attributes); + if ( !SDL_Window ) { + SDL_SetError("Could not create window"); + return -1; + } + retval = 0; +#else + SDL_SetError("X11 driver not configured with OpenGL"); + retval = -1; +#endif + return(retval); +} + +int X11_GL_CreateContext(_THIS) +{ + int retval; +#if SDL_VIDEO_OPENGL_GLX + + /* We do this to create a clean separation between X and GLX errors. */ + XSync( SDL_Display, False ); + glx_context = this->gl_data->glXCreateContext(GFX_Display, + glx_visualinfo, NULL, True); + XSync( GFX_Display, False ); + + if ( glx_context == NULL ) { + SDL_SetError("Could not create GL context"); + return(-1); + } + if ( X11_GL_MakeCurrent(this) < 0 ) { + return(-1); + } + gl_active = 1; + + if ( !glXExtensionSupported(this, "GLX_SGI_swap_control") ) { + this->gl_data->glXSwapIntervalSGI = NULL; + } + if ( !glXExtensionSupported(this, "GLX_MESA_swap_control") ) { + this->gl_data->glXSwapIntervalMESA = NULL; + } + if ( !glXExtensionSupported(this, "GLX_EXT_swap_control") ) { + this->gl_data->glXSwapIntervalEXT = NULL; + } + + if ( this->gl_config.swap_control >= 0 ) { + int rc = -1; + if ( this->gl_data->glXSwapIntervalEXT ) { + rc = this->gl_data->glXSwapIntervalEXT(GFX_Display, SDL_Window, + this->gl_config.swap_control); + } else if ( this->gl_data->glXSwapIntervalMESA ) { + rc = this->gl_data->glXSwapIntervalMESA(this->gl_config.swap_control); + } else if ( this->gl_data->glXSwapIntervalSGI ) { + rc = this->gl_data->glXSwapIntervalSGI(this->gl_config.swap_control); + } + if (rc == 0) { + this->gl_data->swap_interval = this->gl_config.swap_control; + } + } +#else + SDL_SetError("X11 driver not configured with OpenGL"); +#endif + if ( gl_active ) { + retval = 0; + } else { + retval = -1; + } + return(retval); +} + +void X11_GL_Shutdown(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + /* Clean up OpenGL */ + if( glx_context ) { + this->gl_data->glXMakeCurrent(GFX_Display, None, NULL); + + if (glx_context != NULL) + this->gl_data->glXDestroyContext(GFX_Display, glx_context); + + glx_context = NULL; + } + gl_active = 0; +#endif /* SDL_VIDEO_OPENGL_GLX */ +} + +#if SDL_VIDEO_OPENGL_GLX + +/* Make the current context active */ +int X11_GL_MakeCurrent(_THIS) +{ + int retval; + + retval = 0; + if ( ! this->gl_data->glXMakeCurrent(GFX_Display, + SDL_Window, glx_context) ) { + SDL_SetError("Unable to make GL context current"); + retval = -1; + } + XSync( GFX_Display, False ); + + /* More Voodoo X server workarounds... Grr... */ + SDL_Lock_EventThread(); + X11_CheckDGAMouse(this); + SDL_Unlock_EventThread(); + + return(retval); +} + +/* Get attribute data from glX. */ +int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) +{ + int retval = -1; + int unsupported = 0; + int glx_attrib = None; + + switch( attrib ) { + case SDL_GL_RED_SIZE: + glx_attrib = GLX_RED_SIZE; + break; + case SDL_GL_GREEN_SIZE: + glx_attrib = GLX_GREEN_SIZE; + break; + case SDL_GL_BLUE_SIZE: + glx_attrib = GLX_BLUE_SIZE; + break; + case SDL_GL_ALPHA_SIZE: + glx_attrib = GLX_ALPHA_SIZE; + break; + case SDL_GL_DOUBLEBUFFER: + glx_attrib = GLX_DOUBLEBUFFER; + break; + case SDL_GL_BUFFER_SIZE: + glx_attrib = GLX_BUFFER_SIZE; + break; + case SDL_GL_DEPTH_SIZE: + glx_attrib = GLX_DEPTH_SIZE; + break; + case SDL_GL_STENCIL_SIZE: + glx_attrib = GLX_STENCIL_SIZE; + break; + case SDL_GL_ACCUM_RED_SIZE: + glx_attrib = GLX_ACCUM_RED_SIZE; + break; + case SDL_GL_ACCUM_GREEN_SIZE: + glx_attrib = GLX_ACCUM_GREEN_SIZE; + break; + case SDL_GL_ACCUM_BLUE_SIZE: + glx_attrib = GLX_ACCUM_BLUE_SIZE; + break; + case SDL_GL_ACCUM_ALPHA_SIZE: + glx_attrib = GLX_ACCUM_ALPHA_SIZE; + break; + case SDL_GL_STEREO: + glx_attrib = GLX_STEREO; + break; + case SDL_GL_MULTISAMPLEBUFFERS: + glx_attrib = GLX_SAMPLE_BUFFERS_ARB; + break; + case SDL_GL_MULTISAMPLESAMPLES: + glx_attrib = GLX_SAMPLES_ARB; + break; + case SDL_GL_ACCELERATED_VISUAL: + if ( glXExtensionSupported(this, "GLX_EXT_visual_rating") ) { + glx_attrib = GLX_VISUAL_CAVEAT_EXT; + retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value); + if ( *value == GLX_SLOW_VISUAL_EXT ) { + *value = SDL_FALSE; + } else { + *value = SDL_TRUE; + } + return retval; + } else { + unsupported = 1; + } + break; + case SDL_GL_SWAP_CONTROL: + if ( ( this->gl_data->glXSwapIntervalEXT ) || + ( this->gl_data->glXSwapIntervalMESA ) || + ( this->gl_data->glXSwapIntervalSGI ) ) { + *value = this->gl_data->swap_interval; + return 0; + } else { + unsupported = 1; + } + break; + default: + unsupported = 1; + break; + } + + if (unsupported) { + SDL_SetError("OpenGL attribute is unsupported on this system"); + } else { + retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value); + } + return retval; +} + +void X11_GL_SwapBuffers(_THIS) +{ + this->gl_data->glXSwapBuffers(GFX_Display, SDL_Window); +} + +#endif /* SDL_VIDEO_OPENGL_GLX */ + +#define OPENGL_REQUIRS_DLOPEN +#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN) +#include <dlfcn.h> +#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL)) +#define GL_LoadFunction dlsym +#define GL_UnloadObject dlclose +#else +#define GL_LoadObject SDL_LoadObject +#define GL_LoadFunction SDL_LoadFunction +#define GL_UnloadObject SDL_UnloadObject +#endif + +void X11_GL_UnloadLibrary(_THIS) +{ +#if SDL_VIDEO_OPENGL_GLX + if ( this->gl_config.driver_loaded ) { + + GL_UnloadObject(this->gl_config.dll_handle); + + this->gl_data->glXGetProcAddress = NULL; + this->gl_data->glXChooseVisual = NULL; + this->gl_data->glXCreateContext = NULL; + this->gl_data->glXDestroyContext = NULL; + this->gl_data->glXMakeCurrent = NULL; + this->gl_data->glXSwapBuffers = NULL; + this->gl_data->glXSwapIntervalSGI = NULL; + this->gl_data->glXSwapIntervalMESA = NULL; + this->gl_data->glXSwapIntervalEXT = NULL; + + this->gl_config.dll_handle = NULL; + this->gl_config.driver_loaded = 0; + } +#endif +} + +#if SDL_VIDEO_OPENGL_GLX + +/* Passing a NULL path means load pointers from the application */ +int X11_GL_LoadLibrary(_THIS, const char* path) +{ + void* handle = NULL; + + if ( gl_active ) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + if ( path == NULL ) { + path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); + if ( path == NULL ) { + path = DEFAULT_OPENGL; + } + } + + handle = GL_LoadObject(path); + if ( handle == NULL ) { +#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN) + SDL_SetError("Failed loading %s", path); +#else + /* SDL_LoadObject() will call SDL_SetError() for us. */ +#endif + return -1; + } + + /* Unload the old driver and reset the pointers */ + X11_GL_UnloadLibrary(this); + + /* Save the handle for X11_GL_GetProcAddress() */ + this->gl_config.dll_handle = handle; + + /* Load new function pointers */ + this->gl_data->glXGetProcAddress = + (void *(*)(const GLubyte *)) GL_LoadFunction(handle, "glXGetProcAddressARB"); + this->gl_data->glXChooseVisual = + (XVisualInfo *(*)(Display *, int, int *)) X11_GL_GetProcAddress(this, "glXChooseVisual"); + this->gl_data->glXCreateContext = + (GLXContext (*)(Display *, XVisualInfo *, GLXContext, int)) X11_GL_GetProcAddress(this, "glXCreateContext"); + this->gl_data->glXDestroyContext = + (void (*)(Display *, GLXContext)) X11_GL_GetProcAddress(this, "glXDestroyContext"); + this->gl_data->glXMakeCurrent = + (int (*)(Display *, GLXDrawable, GLXContext)) X11_GL_GetProcAddress(this, "glXMakeCurrent"); + this->gl_data->glXSwapBuffers = + (void (*)(Display *, GLXDrawable)) X11_GL_GetProcAddress(this, "glXSwapBuffers"); + this->gl_data->glXGetConfig = + (int (*)(Display *, XVisualInfo *, int, int *)) X11_GL_GetProcAddress(this, "glXGetConfig"); + this->gl_data->glXQueryExtensionsString = + (const char *(*)(Display *, int)) X11_GL_GetProcAddress(this, "glXQueryExtensionsString"); + this->gl_data->glXSwapIntervalSGI = + (int (*)(int)) X11_GL_GetProcAddress(this, "glXSwapIntervalSGI"); + this->gl_data->glXSwapIntervalMESA = + (GLint (*)(unsigned)) X11_GL_GetProcAddress(this, "glXSwapIntervalMESA"); + this->gl_data->glXSwapIntervalEXT = + (int (*)(Display*,GLXDrawable,int)) X11_GL_GetProcAddress(this, "glXSwapIntervalEXT"); + + if ( (this->gl_data->glXChooseVisual == NULL) || + (this->gl_data->glXCreateContext == NULL) || + (this->gl_data->glXDestroyContext == NULL) || + (this->gl_data->glXMakeCurrent == NULL) || + (this->gl_data->glXSwapBuffers == NULL) || + (this->gl_data->glXGetConfig == NULL) || + (this->gl_data->glXQueryExtensionsString == NULL)) { + GL_UnloadObject(this->gl_config.dll_handle); + this->gl_config.dll_handle = NULL; + SDL_SetError("Could not retrieve OpenGL functions"); + return -1; + } + + this->gl_config.driver_loaded = 1; + if ( path ) { + SDL_strlcpy(this->gl_config.driver_path, path, + SDL_arraysize(this->gl_config.driver_path)); + } else { + *this->gl_config.driver_path = '\0'; + } + return 0; +} + +void *X11_GL_GetProcAddress(_THIS, const char* proc) +{ + if ( this->gl_data->glXGetProcAddress ) { + return this->gl_data->glXGetProcAddress((const GLubyte *)proc); + } + return GL_LoadFunction(this->gl_config.dll_handle, proc); +} + +#endif /* SDL_VIDEO_OPENGL_GLX */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h b/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h new file mode 100644 index 0000000..b4822cb --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11gl_c.h @@ -0,0 +1,99 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_OPENGL_GLX +#include <GL/glx.h> +#include "SDL_loadso.h" +#endif + +#include "../SDL_sysvideo.h" + +struct SDL_PrivateGLData { + int gl_active; /* to stop switching drivers while we have a valid context */ + +#if SDL_VIDEO_OPENGL_GLX + GLXContext glx_context; /* Current GL context */ + XVisualInfo* glx_visualinfo; /* XVisualInfo* returned by glXChooseVisual */ + + void * (*glXGetProcAddress)(const GLubyte *procName); + + XVisualInfo* (*glXChooseVisual) + ( Display* dpy, + int screen, + int* attribList ); + + GLXContext (*glXCreateContext) + ( Display* dpy, + XVisualInfo* vis, + GLXContext shareList, + Bool direct ); + + void (*glXDestroyContext) + ( Display* dpy, + GLXContext ctx ); + + Bool (*glXMakeCurrent) + ( Display* dpy, + GLXDrawable drawable, + GLXContext ctx ); + + void (*glXSwapBuffers) + ( Display* dpy, + GLXDrawable drawable ); + + int (*glXGetConfig) + ( Display* dpy, + XVisualInfo* visual_info, + int attrib, + int* value ); + + const char *(*glXQueryExtensionsString) + ( Display* dpy, + int screen ); + + int (*glXSwapIntervalSGI) ( int interval ); + GLint (*glXSwapIntervalMESA) ( unsigned interval ); + int (*glXSwapIntervalEXT)( Display *dpy, GLXDrawable drw, int interval); + int swap_interval; +#endif /* SDL_VIDEO_OPENGL_GLX */ +}; + +/* Old variable names */ +#define gl_active (this->gl_data->gl_active) +#define glx_context (this->gl_data->glx_context) +#define glx_visualinfo (this->gl_data->glx_visualinfo) + +/* OpenGL functions */ +extern XVisualInfo *X11_GL_GetVisual(_THIS); +extern int X11_GL_CreateWindow(_THIS, int w, int h); +extern int X11_GL_CreateContext(_THIS); +extern void X11_GL_Shutdown(_THIS); +#if SDL_VIDEO_OPENGL_GLX +extern int X11_GL_MakeCurrent(_THIS); +extern int X11_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); +extern void X11_GL_SwapBuffers(_THIS); +extern int X11_GL_LoadLibrary(_THIS, const char* path); +extern void *X11_GL_GetProcAddress(_THIS, const char* proc); +#endif +extern void X11_GL_UnloadLibrary(_THIS); + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11image.c b/3rdparty/SDL/src/video/x11/SDL_x11image.c new file mode 100644 index 0000000..464bc37 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11image.c @@ -0,0 +1,316 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <stdio.h> +#include <unistd.h> + +#include "SDL_endian.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11image_c.h" + +#ifndef NO_SHARED_MEMORY + +/* Shared memory error handler routine */ +static int shm_error; +static int (*X_handler)(Display *, XErrorEvent *) = NULL; +static int shm_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAccess ) { + shm_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +static void try_mitshm(_THIS, SDL_Surface *screen) +{ + /* Dynamic X11 may not have SHM entry points on this box. */ + if ((use_mitshm) && (!SDL_X11_HAVE_SHM)) + use_mitshm = 0; + + if(!use_mitshm) + return; + shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, + IPC_CREAT | 0777); + if ( shminfo.shmid >= 0 ) { + shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); + shminfo.readOnly = False; + if ( shminfo.shmaddr != (char *)-1 ) { + shm_error = False; + X_handler = XSetErrorHandler(shm_errhandler); + XShmAttach(SDL_Display, &shminfo); + XSync(SDL_Display, True); + XSetErrorHandler(X_handler); + if ( shm_error ) + shmdt(shminfo.shmaddr); + } else { + shm_error = True; + } + shmctl(shminfo.shmid, IPC_RMID, NULL); + } else { + shm_error = True; + } + if ( shm_error ) + use_mitshm = 0; + if ( use_mitshm ) + screen->pixels = shminfo.shmaddr; +} +#endif /* ! NO_SHARED_MEMORY */ + +/* Various screen update functions available */ +static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); +static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); + +int X11_SetupImage(_THIS, SDL_Surface *screen) +{ +#ifndef NO_SHARED_MEMORY + try_mitshm(this, screen); + if(use_mitshm) { + SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, + this->hidden->depth, ZPixmap, + shminfo.shmaddr, &shminfo, + screen->w, screen->h); + if(!SDL_Ximage) { + XShmDetach(SDL_Display, &shminfo); + XSync(SDL_Display, False); + shmdt(shminfo.shmaddr); + screen->pixels = NULL; + goto error; + } + this->UpdateRects = X11_MITSHMUpdate; + } + if(!use_mitshm) +#endif /* not NO_SHARED_MEMORY */ + { + screen->pixels = SDL_malloc(screen->h*screen->pitch); + if ( screen->pixels == NULL ) { + SDL_OutOfMemory(); + return -1; + } + SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, + this->hidden->depth, ZPixmap, 0, + (char *)screen->pixels, + screen->w, screen->h, + 32, 0); + if ( SDL_Ximage == NULL ) + goto error; + /* XPutImage will convert byte sex automatically */ + SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) + ? MSBFirst : LSBFirst; + this->UpdateRects = X11_NormalUpdate; + } + screen->pitch = SDL_Ximage->bytes_per_line; + return(0); + +error: + SDL_SetError("Couldn't create XImage"); + return 1; +} + +void X11_DestroyImage(_THIS, SDL_Surface *screen) +{ + if ( SDL_Ximage ) { + XDestroyImage(SDL_Ximage); +#ifndef NO_SHARED_MEMORY + if ( use_mitshm ) { + XShmDetach(SDL_Display, &shminfo); + XSync(SDL_Display, False); + shmdt(shminfo.shmaddr); + } +#endif /* ! NO_SHARED_MEMORY */ + SDL_Ximage = NULL; + } + if ( screen ) { + screen->pixels = NULL; + } +} + +/* Determine the number of CPUs in the system */ +static int num_CPU(void) +{ + static int num_cpus = 0; + + if(!num_cpus) { +#if defined(__LINUX__) + char line[BUFSIZ]; + FILE *pstat = fopen("/proc/stat", "r"); + if ( pstat ) { + while ( fgets(line, sizeof(line), pstat) ) { + if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') { + ++num_cpus; + } + } + fclose(pstat); + } +#elif defined(__IRIX__) + num_cpus = sysconf(_SC_NPROC_ONLN); +#elif defined(_SC_NPROCESSORS_ONLN) + /* number of processors online (SVR4.0MP compliant machines) */ + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(_SC_NPROCESSORS_CONF) + /* number of processors configured (SVR4.0MP compliant machines) */ + num_cpus = sysconf(_SC_NPROCESSORS_CONF); +#endif + if ( num_cpus <= 0 ) { + num_cpus = 1; + } + } + return num_cpus; +} + +int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) +{ + int retval; + + X11_DestroyImage(this, screen); + if ( flags & SDL_OPENGL ) { /* No image when using GL */ + retval = 0; + } else { + retval = X11_SetupImage(this, screen); + /* We support asynchronous blitting on the display */ + if ( flags & SDL_ASYNCBLIT ) { + /* This is actually slower on single-CPU systems, + probably because of CPU contention between the + X server and the application. + Note: Is this still true with XFree86 4.0? + */ + if ( num_CPU() > 1 ) { + screen->flags |= SDL_ASYNCBLIT; + } + } + } + return(retval); +} + +/* We don't actually allow hardware surfaces other than the main one */ +int X11_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} +void X11_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +int X11_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( (surface == SDL_VideoSurface) && blit_queued ) { + XSync(GFX_Display, False); + blit_queued = 0; + } + return(0); +} +void X11_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +int X11_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int i; + + for (i = 0; i < numrects; ++i) { + if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ + continue; + } + XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, + rects[i].x, rects[i].y, + rects[i].x, rects[i].y, rects[i].w, rects[i].h); + } + if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { + XFlush(GFX_Display); + blit_queued = 1; + } else { + XSync(GFX_Display, False); + } +} + +static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects) +{ +#ifndef NO_SHARED_MEMORY + int i; + + for ( i=0; i<numrects; ++i ) { + if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ + continue; + } + XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, + rects[i].x, rects[i].y, + rects[i].x, rects[i].y, rects[i].w, rects[i].h, + False); + } + if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { + XFlush(GFX_Display); + blit_queued = 1; + } else { + XSync(GFX_Display, False); + } +#endif /* ! NO_SHARED_MEMORY */ +} + +/* There's a problem with the automatic refreshing of the display. + Even though the XVideo code uses the GFX_Display to update the + video memory, it appears that updating the window asynchronously + from a different thread will cause "blackouts" of the window. + This is a sort of a hacked workaround for the problem. +*/ +static int enable_autorefresh = 1; + +void X11_DisableAutoRefresh(_THIS) +{ + --enable_autorefresh; +} + +void X11_EnableAutoRefresh(_THIS) +{ + ++enable_autorefresh; +} + +void X11_RefreshDisplay(_THIS) +{ + /* Don't refresh a display that doesn't have an image (like GL) + Instead, post an expose event so the application can refresh. + */ + if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) { + SDL_PrivateExpose(); + return; + } +#ifndef NO_SHARED_MEMORY + if ( this->UpdateRects == X11_MITSHMUpdate ) { + XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, + 0, 0, 0, 0, this->screen->w, this->screen->h, + False); + } else +#endif /* ! NO_SHARED_MEMORY */ + { + XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, + 0, 0, 0, 0, this->screen->w, this->screen->h); + } + XSync(SDL_Display, False); +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11image_c.h b/3rdparty/SDL/src/video/x11/SDL_x11image_c.h new file mode 100644 index 0000000..2de1571 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11image_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +extern int X11_SetupImage(_THIS, SDL_Surface *screen); +extern void X11_DestroyImage(_THIS, SDL_Surface *screen); +extern int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags); + +extern int X11_AllocHWSurface(_THIS, SDL_Surface *surface); +extern void X11_FreeHWSurface(_THIS, SDL_Surface *surface); +extern int X11_LockHWSurface(_THIS, SDL_Surface *surface); +extern void X11_UnlockHWSurface(_THIS, SDL_Surface *surface); +extern int X11_FlipHWSurface(_THIS, SDL_Surface *surface); + +extern void X11_DisableAutoRefresh(_THIS); +extern void X11_EnableAutoRefresh(_THIS); +extern void X11_RefreshDisplay(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11modes.c b/3rdparty/SDL/src/video/x11/SDL_x11modes.c new file mode 100644 index 0000000..c232e6a --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11modes.c @@ -0,0 +1,1143 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Utilities for getting and setting the X display mode */ + +#include <stdio.h> + +#include "SDL_timer.h" +#include "SDL_events.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" + +/*#define X11MODES_DEBUG*/ + +#define MAX(a, b) (a > b ? a : b) + +#if SDL_VIDEO_DRIVER_X11_XRANDR +static int cmpmodelist(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect **)va; + const SDL_Rect *b = *(const SDL_Rect **)vb; + if ( a->w == b->w ) + return b->h - a->h; + else + return b->w - a->w; +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +Bool SDL_NAME(XF86VidModeGetModeInfo)(Display *dpy, int scr, SDL_NAME(XF86VidModeModeInfo) *info) +{ + Bool retval; + int dotclock; + SDL_NAME(XF86VidModeModeLine) l; + SDL_memset(&l, 0, sizeof(l)); + retval = SDL_NAME(XF86VidModeGetModeLine)(dpy, scr, &dotclock, &l); + info->dotclock = dotclock; + info->hdisplay = l.hdisplay; + info->hsyncstart = l.hsyncstart; + info->hsyncend = l.hsyncend; + info->htotal = l.htotal; + info->hskew = l.hskew; + info->vdisplay = l.vdisplay; + info->vsyncstart = l.vsyncstart; + info->vsyncend = l.vsyncend; + info->vtotal = l.vtotal; + info->flags = l.flags; + info->privsize = l.privsize; + info->private = l.private; + return retval; +} +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static void save_mode(_THIS) +{ + SDL_memset(&saved_mode, 0, sizeof(saved_mode)); + SDL_NAME(XF86VidModeGetModeInfo)(SDL_Display,SDL_Screen,&saved_mode); + SDL_NAME(XF86VidModeGetViewPort)(SDL_Display,SDL_Screen,&saved_view.x,&saved_view.y); +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static void restore_mode(_THIS) +{ + SDL_NAME(XF86VidModeModeLine) mode; + int unused; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { + if ( (saved_mode.hdisplay != mode.hdisplay) || + (saved_mode.vdisplay != mode.vdisplay) ) { + SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, &saved_mode); + } + } + if ( (saved_view.x != 0) || (saved_view.y != 0) ) { + SDL_NAME(XF86VidModeSetViewPort)(SDL_Display, SDL_Screen, saved_view.x, saved_view.y); + } +} +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_NAME(XF86VidModeModeInfo) *a = *(const SDL_NAME(XF86VidModeModeInfo)**)va; + const SDL_NAME(XF86VidModeModeInfo) *b = *(const SDL_NAME(XF86VidModeModeInfo)**)vb; + if ( a->hdisplay == b->hdisplay ) + return b->vdisplay - a->vdisplay; + else + return b->hdisplay - a->hdisplay; +} +#endif + +static void get_real_resolution(_THIS, int* w, int* h); + +static void set_best_resolution(_THIS, int width, int height) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + SDL_NAME(XF86VidModeModeLine) mode; + SDL_NAME(XF86VidModeModeInfo) **modes; + int i; + int nmodes; + int best = -1; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &i, &mode) && + SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display,SDL_Screen,&nmodes,&modes) ) { + for ( i = 0; i < nmodes ; i++ ) { + if ( (modes[i]->hdisplay == width) && + (modes[i]->vdisplay == height) ) { + best = i; + break; + } + if ( modes[i]->hdisplay >= width && + modes[i]->vdisplay >= height ) { + if ( best < 0 || + (modes[i]->hdisplay < modes[best]->hdisplay && + modes[i]->vdisplay <= modes[best]->vdisplay) || + (modes[i]->vdisplay < modes[best]->vdisplay && + modes[i]->hdisplay <= modes[best]->hdisplay) ) { + best = i; + } + } + } + if ( best >= 0 && + ((modes[best]->hdisplay != mode.hdisplay) || + (modes[best]->vdisplay != mode.vdisplay)) ) { +#ifdef X11MODES_DEBUG + printf("Best Mode %d: %d x %d @ %d\n", best, + modes[best]->hdisplay, modes[best]->vdisplay, + (modes[best]->htotal && modes[best]->vtotal) ? (1000 * modes[best]->dotclock / (modes[best]->htotal * modes[best]->vtotal)) : 0 ); +#endif + SDL_NAME(XF86VidModeSwitchToMode)(SDL_Display, SDL_Screen, modes[best]); + } + XFree(modes); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + + /* XiG */ +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme && SDL_modelist ) { + int i; + +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: set_best_resolution(): w = %d, h = %d\n", + width, height); +#endif + for ( i=0; SDL_modelist[i]; ++i ) { + if ( (SDL_modelist[i]->w >= width) && + (SDL_modelist[i]->h >= height) ) { + break; + } + } + + if ( SDL_modelist[i] ) { /* found one, lets try it */ + int w, h; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &w, &h); + + if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: set_best_resolution: " + "XiGMiscChangeResolution: %d %d\n", + SDL_modelist[i]->w, SDL_modelist[i]->h); +#endif + XiGMiscChangeResolution(SDL_Display, + SDL_Screen, + 0, /* view */ + SDL_modelist[i]->w, + SDL_modelist[i]->h, + 0); + XSync(SDL_Display, False); + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr && SDL_modelist ) { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n", + width, height); +#endif + int i, nsizes; + XRRScreenSize *sizes; + + /* find the smallest resolution that is at least as big as the user requested */ + sizes = XRRConfigSizes(screen_config, &nsizes); + for ( i = (nsizes-1); i >= 0; i-- ) { + if ( (SDL_modelist[i]->w >= width) && + (SDL_modelist[i]->h >= height) ) { + break; + } + } + + if ( i >= 0 && SDL_modelist[i] ) { /* found one, lets try it */ + int w, h; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &w, &h); + + if ( (SDL_modelist[i]->w != w) || (SDL_modelist[i]->h != h) ) { + int size_id; + +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: set_best_resolution: " + "XXRSetScreenConfig: %d %d\n", + SDL_modelist[i]->w, SDL_modelist[i]->h); +#endif + + /* find the matching size entry index */ + for ( size_id = 0; size_id < nsizes; ++size_id ) { + if ( (sizes[size_id].width == SDL_modelist[i]->w) && + (sizes[size_id].height == SDL_modelist[i]->h) ) + break; + } + + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + size_id, saved_rotation, CurrentTime); + } + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ +} + +static void get_real_resolution(_THIS, int* w, int* h) +{ +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme ) { + int ractive; + XiGMiscResolutionInfo *modelist; + + XiGMiscQueryResolutions(SDL_Display, SDL_Screen, + 0, /* view */ + &ractive, &modelist); + *w = modelist[ractive].width; + *h = modelist[ractive].height; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: get_real_resolution: w = %d h = %d\n", *w, *h); +#endif + XFree(modelist); + return; + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + SDL_NAME(XF86VidModeModeLine) mode; + int unused; + + if ( SDL_NAME(XF86VidModeGetModeLine)(SDL_Display, SDL_Screen, &unused, &mode) ) { + *w = mode.hdisplay; + *h = mode.vdisplay; + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + int nsizes; + XRRScreenSize* sizes; + + sizes = XRRConfigSizes(screen_config, &nsizes); + if ( nsizes > 0 ) { + int cur_size; + Rotation cur_rotation; + + cur_size = XRRConfigCurrentConfiguration(screen_config, &cur_rotation); + if ( cur_size >= 0 && cur_size < nsizes ) { + *w = sizes[cur_size].width; + *h = sizes[cur_size].height; + } +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: get_real_resolution: w = %d h = %d\n", *w, *h); +#endif + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama ) { + *w = xinerama_info.width; + *h = xinerama_info.height; + return; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + *w = DisplayWidth(SDL_Display, SDL_Screen); + *h = DisplayHeight(SDL_Display, SDL_Screen); +} + +/* Called after mapping a window - waits until the window is mapped */ +void X11_WaitMapped(_THIS, Window win) +{ + XEvent event; + do { + XMaskEvent(SDL_Display, StructureNotifyMask, &event); + } while ( (event.type != MapNotify) || (event.xmap.event != win) ); +} + +/* Called after unmapping a window - waits until the window is unmapped */ +void X11_WaitUnmapped(_THIS, Window win) +{ + XEvent event; + do { + XMaskEvent(SDL_Display, StructureNotifyMask, &event); + } while ( (event.type != UnmapNotify) || (event.xunmap.event != win) ); +} + +static void move_cursor_to(_THIS, int x, int y) +{ + XWarpPointer(SDL_Display, None, SDL_Root, 0, 0, 0, 0, x, y); +} + +static int add_default_visual(_THIS) +{ + int i; + int n = this->hidden->nvisuals; + for (i=0; i<n; i++) { + if (this->hidden->visuals[i].visual == DefaultVisual(SDL_Display, SDL_Screen)) return n; + } + this->hidden->visuals[n].depth = DefaultDepth(SDL_Display, SDL_Screen);; + this->hidden->visuals[n].visual = DefaultVisual(SDL_Display, SDL_Screen);; + this->hidden->nvisuals++; + return(this->hidden->nvisuals); +} +static int add_visual(_THIS, int depth, int class) +{ + XVisualInfo vi; + if(XMatchVisualInfo(SDL_Display, SDL_Screen, depth, class, &vi)) { + int n = this->hidden->nvisuals; + this->hidden->visuals[n].depth = vi.depth; + this->hidden->visuals[n].visual = vi.visual; + this->hidden->nvisuals++; + } + return(this->hidden->nvisuals); +} +static int add_visual_byid(_THIS, const char *visual_id) +{ + XVisualInfo *vi, template; + int nvis; + + if ( visual_id ) { + SDL_memset(&template, 0, (sizeof template)); + template.visualid = SDL_strtol(visual_id, NULL, 0); + vi = XGetVisualInfo(SDL_Display, VisualIDMask, &template, &nvis); + if ( vi ) { + int n = this->hidden->nvisuals; + this->hidden->visuals[n].depth = vi->depth; + this->hidden->visuals[n].visual = vi->visual; + this->hidden->nvisuals++; + XFree(vi); + } + } + return(this->hidden->nvisuals); +} + +/* Global for the error handler */ +int vm_event, vm_error = -1; + +#if SDL_VIDEO_DRIVER_X11_XINERAMA +static int CheckXinerama(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_XINERAMA"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Query the extension version */ + if ( !SDL_NAME(XineramaQueryExtension)(SDL_Display, major, minor) || + !SDL_NAME(XineramaIsActive)(SDL_Display) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR +static int CheckXRandR(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_XRANDR"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* This defaults off now, due to KDE window maximize problems */ + if ( !env ) { + return 0; + } + + if ( !SDL_X11_HAVE_XRANDR ) { + return 0; + } + + /* Query the extension version */ + if ( !XRRQueryVersion(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE +static int CheckVidMode(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_VIDMODE"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Metro-X 4.3.0 and earlier has a broken implementation of + XF86VidModeGetAllModeLines() - it hangs the client. + */ + if ( SDL_strcmp(ServerVendor(SDL_Display), "Metro Link Incorporated") == 0 ) { + FILE *metro_fp; + + metro_fp = fopen("/usr/X11R6/lib/X11/Metro/.version", "r"); + if ( metro_fp != NULL ) { + int major, minor, patch, version, scannum; + major = 0; minor = 0; patch = 0; + scannum = fscanf(metro_fp, "%d.%d.%d", &major, &minor, &patch); + fclose(metro_fp); + if ( (scannum < 0) || (scannum > 3) ) { + return 0; /* we need _something_ useful from fscanf(). */ + } + version = major*100+minor*10+patch; + if ( version < 431 ) { + return 0; + } + } + } + + /* Query the extension version */ + vm_error = -1; + if ( !SDL_NAME(XF86VidModeQueryExtension)(SDL_Display, &vm_event, &vm_error) || + !SDL_NAME(XF86VidModeQueryVersion)(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XME +static int CheckXME(_THIS, int *major, int *minor) +{ + const char *env; + + /* Default the extension not available */ + *major = *minor = 0; + + /* Allow environment override */ + env = getenv("SDL_VIDEO_X11_VIDMODE"); + if ( env && !SDL_atoi(env) ) { + return 0; + } + + /* Query the extension version */ + if ( !XiGMiscQueryVersion(SDL_Display, major, minor) ) { + return 0; + } + return 1; +} +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + +int X11_GetVideoModes(_THIS) +{ +#if SDL_VIDEO_DRIVER_X11_XINERAMA + int xinerama_major, xinerama_minor; +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + int xrandr_major, xrandr_minor; + int nsizes; + XRRScreenSize *sizes; +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE + int vm_major, vm_minor; + int nmodes; + SDL_NAME(XF86VidModeModeInfo) **modes; +#endif +#if SDL_VIDEO_DRIVER_X11_XME + int xme_major, xme_minor; + int ractive, nummodes; + XiGMiscResolutionInfo *modelist; +#endif + int i, n; + int screen_w; + int screen_h; + + use_xinerama = 0; + use_xrandr = 0; + use_vidmode = 0; + use_xme = 0; + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + /* Query Xinerama extention */ + if ( CheckXinerama(this, &xinerama_major, &xinerama_minor) ) { + /* Find out which screen is the desired one */ + int desired = -1; + int screens; + int w, h; + SDL_NAME(XineramaScreenInfo) *xinerama; + + const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); + if ( !variable ) { + variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD"); + } + if ( variable ) { + desired = SDL_atoi(variable); + } +#ifdef X11MODES_DEBUG + printf("X11 detected Xinerama:\n"); +#endif + xinerama = SDL_NAME(XineramaQueryScreens)(SDL_Display, &screens); + for ( i = 0; i < screens; i++ ) { +#ifdef X11MODES_DEBUG + printf("xinerama %d: %dx%d+%d+%d\n", + xinerama[i].screen_number, + xinerama[i].width, xinerama[i].height, + xinerama[i].x_org, xinerama[i].y_org); +#endif + if ( xinerama[i].screen_number == desired ) { + use_xinerama = 1; + xinerama_info = xinerama[i]; + } + } + XFree(xinerama); + + if ( use_xinerama ) { + SDL_modelist = (SDL_Rect **)SDL_malloc(3*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + + /* Add the full xinerama mode */ + n = 0; + w = xinerama_info.width; + h = xinerama_info.height; + if ( screen_w > w || screen_h > h) { + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + } + + /* Add the head xinerama mode */ + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = w; + SDL_modelist[n]->h = h; + ++n; + } + SDL_modelist[n] = NULL; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* XRandR */ + /* require at least XRandR v1.0 (arbitrary) */ + if ( CheckXRandR(this, &xrandr_major, &xrandr_minor) && (xrandr_major >= 1) ) + { +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n", + xrandr_major, xrandr_minor); +#endif + + /* save the screen configuration since we must reference it + each time we toggle modes. + */ + screen_config = XRRGetScreenInfo(SDL_Display, SDL_Root); + + /* retrieve the list of resolution */ + sizes = XRRConfigSizes(screen_config, &nsizes); + if (nsizes > 0) { + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)malloc((nsizes+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + for ( i=0; i < nsizes; i++ ) { + if ((SDL_modelist[i] = + (SDL_Rect *)malloc(sizeof(SDL_Rect))) == NULL) + break; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XRANDR: mode = %4d, w = %4d, h = %4d\n", + i, sizes[i].width, sizes[i].height); +#endif + + SDL_modelist[i]->x = 0; + SDL_modelist[i]->y = 0; + SDL_modelist[i]->w = sizes[i].width; + SDL_modelist[i]->h = sizes[i].height; + + } + /* sort the mode list descending as SDL expects */ + SDL_qsort(SDL_modelist, nsizes, sizeof *SDL_modelist, cmpmodelist); + SDL_modelist[i] = NULL; /* terminator */ + + use_xrandr = xrandr_major * 100 + xrandr_minor; + saved_size_id = XRRConfigCurrentConfiguration(screen_config, &saved_rotation); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* XVidMode */ + if ( !use_xrandr && +#if SDL_VIDEO_DRIVER_X11_XINERAMA + (!use_xinerama || xinerama_info.screen_number == -1) && +#endif + CheckVidMode(this, &vm_major, &vm_minor) && + SDL_NAME(XF86VidModeGetAllModeLines)(SDL_Display, SDL_Screen,&nmodes,&modes) ) + { +#ifdef X11MODES_DEBUG + printf("VidMode modes: (unsorted)\n"); + for ( i = 0; i < nmodes; ++i ) { + printf("Mode %d: %d x %d @ %d\n", i, + modes[i]->hdisplay, modes[i]->vdisplay, + (modes[i]->htotal && modes[i]->vtotal) ? (1000 * modes[i]->dotclock / (modes[i]->htotal * modes[i]->vtotal)) : 0 ); + } +#endif + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)SDL_malloc((nmodes+2)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + SDL_qsort(modes, nmodes, sizeof *modes, cmpmodes); + n = 0; + for ( i=0; i<nmodes; ++i ) { + int w, h; + + /* Eliminate duplicate modes with different refresh rates */ + if ( i > 0 && + modes[i]->hdisplay == modes[i-1]->hdisplay && + modes[i]->vdisplay == modes[i-1]->vdisplay ) { + continue; + } + + /* Check to see if we should add the screen size (Xinerama) */ + w = modes[i]->hdisplay; + h = modes[i]->vdisplay; + if ( (screen_w * screen_h) >= (w * h) ) { + if ( (screen_w != w) || (screen_h != h) ) { + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + } + screen_w = 0; + screen_h = 0; + } + + /* Add the size from the video mode list */ + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] == NULL ) { + break; + } + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = w; + SDL_modelist[n]->h = h; + ++n; + } + SDL_modelist[n] = NULL; + XFree(modes); + + use_vidmode = vm_major * 100 + vm_minor; + save_mode(this); + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_XME + /* XiG */ + modelist = NULL; + /* first lets make sure we have the extension, and it's at least v2.0 */ + if ( CheckXME(this, &xme_major, &xme_minor) && xme_major >= 2 && + (nummodes = XiGMiscQueryResolutions(SDL_Display, SDL_Screen, + 0, /* view */ + &ractive, &modelist)) > 1 ) + { /* then we actually have some */ + int j; + + /* We get the list already sorted in descending order. + We'll copy it in reverse order so SDL is happy */ +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: nummodes = %d, active mode = %d\n", + nummodes, ractive); +#endif + if ( SDL_modelist ) { + for ( i = 0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + } + SDL_modelist = (SDL_Rect **)SDL_malloc((nummodes+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + for ( i=0, j=nummodes-1; j>=0; i++, j-- ) { + if ((SDL_modelist[i] = + (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect))) == NULL) + break; +#ifdef X11MODES_DEBUG + fprintf(stderr, "XME: mode = %4d, w = %4d, h = %4d\n", + i, modelist[i].width, modelist[i].height); +#endif + + SDL_modelist[i]->x = 0; + SDL_modelist[i]->y = 0; + SDL_modelist[i]->w = modelist[j].width; + SDL_modelist[i]->h = modelist[j].height; + + } + SDL_modelist[i] = NULL; /* terminator */ + + use_xme = xme_major * 100 + xme_minor; + saved_res = modelist[ractive]; /* save the current resolution */ + } + if ( modelist ) { + XFree(modelist); + } +#endif /* SDL_VIDEO_DRIVER_X11_XME */ + + { + /* It's interesting to note that if we allow 32 bit depths, + we get a visual with an alpha mask on composite servers. + static int depth_list[] = { 32, 24, 16, 15, 8 }; + */ + static int depth_list[] = { 24, 16, 15, 8 }; + int j, np; + int use_directcolor = 1; + XPixmapFormatValues *pf; + + /* Search for the visuals in deepest-first order, so that the first + will be the richest one */ + if ( SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) { + use_directcolor = 0; + } + this->hidden->nvisuals = 0; + if ( ! add_visual_byid(this, SDL_getenv("SDL_VIDEO_X11_VISUALID")) ) { + for ( i=0; i<SDL_arraysize(depth_list); ++i ) { + if ( depth_list[i] > 8 ) { + if ( use_directcolor ) { + add_visual(this, depth_list[i], DirectColor); + } + add_visual(this, depth_list[i], TrueColor); + } else { + add_visual(this, depth_list[i], PseudoColor); + add_visual(this, depth_list[i], StaticColor); + } + } + add_default_visual(this); + } + if ( this->hidden->nvisuals == 0 ) { + SDL_SetError("Found no sufficiently capable X11 visuals"); + return -1; + } + + /* look up the pixel quantum for each depth */ + pf = XListPixmapFormats(SDL_Display, &np); + for(i = 0; i < this->hidden->nvisuals; i++) { + int d = this->hidden->visuals[i].depth; + for(j = 0; j < np; j++) + if(pf[j].depth == d) + break; + this->hidden->visuals[i].bpp = j < np ? pf[j].bits_per_pixel : d; + } + + XFree(pf); + } + + if ( SDL_modelist == NULL ) { + SDL_modelist = (SDL_Rect **)SDL_malloc((1+1)*sizeof(SDL_Rect *)); + if ( !SDL_modelist ) { + SDL_OutOfMemory(); + return -1; + } + n = 0; + SDL_modelist[n] = (SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[n] ) { + SDL_modelist[n]->x = 0; + SDL_modelist[n]->y = 0; + SDL_modelist[n]->w = screen_w; + SDL_modelist[n]->h = screen_h; + ++n; + } + SDL_modelist[n] = NULL; + } + +#ifdef X11MODES_DEBUG + if ( use_xinerama ) { + printf("Xinerama is enabled\n"); + } + + if ( use_xrandr ) { + printf("XRandR is enabled\n"); + } + + if ( use_vidmode ) { + printf("VidMode is enabled\n"); + } + + if ( use_xme ) { + printf("Xi Graphics XME fullscreen is enabled\n"); + } + + if ( SDL_modelist ) { + printf("X11 video mode list:\n"); + for ( i=0; SDL_modelist[i]; ++i ) { + printf("\t%dx%d\n", SDL_modelist[i]->w, SDL_modelist[i]->h); + } + } +#endif /* X11MODES_DEBUG */ + + return 0; +} + +int X11_SupportedVisual(_THIS, SDL_PixelFormat *format) +{ + int i; + for(i = 0; i < this->hidden->nvisuals; i++) + if(this->hidden->visuals[i].bpp == format->BitsPerPixel) + return 1; + return 0; +} + +SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + if ( X11_SupportedVisual(this, format) ) { + if ( flags & SDL_FULLSCREEN ) { + return(SDL_modelist); + } else { + return((SDL_Rect **)-1); + } + } else { + return((SDL_Rect **)0); + } +} + +void X11_FreeVideoModes(_THIS) +{ + int i; + + if ( SDL_modelist ) { + for ( i=0; SDL_modelist[i]; ++i ) { + SDL_free(SDL_modelist[i]); + } + SDL_free(SDL_modelist); + SDL_modelist = NULL; + } + +#if SDL_VIDEO_DRIVER_X11_XRANDR + /* Free the Xrandr screen configuration */ + if ( screen_config ) { + XRRFreeScreenConfigInfo(screen_config); + screen_config = NULL; + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ +} + +int X11_ResizeFullScreen(_THIS) +{ + int x = 0, y = 0; + int real_w, real_h; + int screen_w; + int screen_h; + + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama && + window_w <= xinerama_info.width && + window_h <= xinerama_info.height ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + if ( currently_fullscreen ) { + /* Switch resolution and cover it with the FSwindow */ + move_cursor_to(this, x, y); + set_best_resolution(this, window_w, window_h); + move_cursor_to(this, x, y); + get_real_resolution(this, &real_w, &real_h); + if ( window_w > real_w ) { + real_w = MAX(real_w, screen_w); + } + if ( window_h > real_h ) { + real_h = MAX(real_h, screen_h); + } + XMoveResizeWindow(SDL_Display, FSwindow, x, y, real_w, real_h); + move_cursor_to(this, real_w/2, real_h/2); + + /* Center and reparent the drawing window */ + x = (real_w - window_w)/2; + y = (real_h - window_h)/2; + XReparentWindow(SDL_Display, SDL_Window, FSwindow, x, y); + /* FIXME: move the mouse to the old relative location */ + XSync(SDL_Display, True); /* Flush spurious mode change events */ + } + return(1); +} + +void X11_QueueEnterFullScreen(_THIS) +{ + switch_waiting = 0x01 | SDL_FULLSCREEN; + switch_time = SDL_GetTicks() + 1500; +#if 0 /* This causes a BadMatch error if the window is iconified (not needed) */ + XSetInputFocus(SDL_Display, WMwindow, RevertToNone, CurrentTime); +#endif +} + +int X11_EnterFullScreen(_THIS) +{ + int okay; +#if 0 + Window tmpwin, *windows; + int i, nwindows; +#endif + int x = 0, y = 0; + int real_w, real_h; + int screen_w; + int screen_h; + + okay = 1; + if ( currently_fullscreen ) { + return(okay); + } + + /* Ungrab the input so that we can move the mouse around */ + X11_GrabInputNoLock(this, SDL_GRAB_OFF); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama && + window_w <= xinerama_info.width && + window_h <= xinerama_info.height ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */ + + /* Map the fullscreen window to blank the screen */ + screen_w = DisplayWidth(SDL_Display, SDL_Screen); + screen_h = DisplayHeight(SDL_Display, SDL_Screen); + get_real_resolution(this, &real_w, &real_h); + real_w = MAX(window_w, MAX(real_w, screen_w)); + real_h = MAX(window_h, MAX(real_h, screen_h)); + XMoveResizeWindow(SDL_Display, FSwindow, + x, y, real_w, real_h); + XMapRaised(SDL_Display, FSwindow); + X11_WaitMapped(this, FSwindow); + +#if 0 /* This seems to break WindowMaker in focus-follows-mouse mode */ + /* Make sure we got to the top of the window stack */ + if ( XQueryTree(SDL_Display, SDL_Root, &tmpwin, &tmpwin, + &windows, &nwindows) && windows ) { + /* If not, try to put us there - if fail... oh well */ + if ( windows[nwindows-1] != FSwindow ) { + tmpwin = windows[nwindows-1]; + for ( i=0; i<nwindows; ++i ) { + if ( windows[i] == FSwindow ) { + SDL_memcpy(&windows[i], &windows[i+1], + (nwindows-i-1)*sizeof(windows[i])); + break; + } + } + windows[nwindows-1] = FSwindow; + XRestackWindows(SDL_Display, windows, nwindows); + XSync(SDL_Display, False); + } + XFree(windows); + } +#else + XRaiseWindow(SDL_Display, FSwindow); +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* Save the current video mode */ + if ( use_vidmode ) { + SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, True); + save_mode(this); + } +#endif + currently_fullscreen = 1; + + /* Set the new resolution */ + okay = X11_ResizeFullScreen(this); + if ( ! okay ) { + X11_LeaveFullScreen(this); + } + /* Set the colormap */ + if ( SDL_XColorMap ) { + XInstallColormap(SDL_Display, SDL_XColorMap); + } + if ( okay ) { + X11_GrabInputNoLock(this, this->input_grab | SDL_GRAB_FULLSCREEN); + } + + /* We may need to refresh the screen at this point (no backing store) + We also don't get an event, which is why we explicitly refresh. */ + if ( this->screen ) { + if ( this->screen->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } else { + X11_RefreshDisplay(this); + } + } + + return(okay); +} + +int X11_LeaveFullScreen(_THIS) +{ + if ( currently_fullscreen ) { + XReparentWindow(SDL_Display, SDL_Window, WMwindow, 0, 0); +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if ( use_vidmode ) { + restore_mode(this); + SDL_NAME(XF86VidModeLockModeSwitch)(SDL_Display, SDL_Screen, False); + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XME + if ( use_xme ) { + int rw, rh; + + /* check current mode so we can avoid uneccessary mode changes */ + get_real_resolution(this, &rw, &rh); + + if (rw != saved_res.width || rh != saved_res.height) { + XiGMiscChangeResolution(SDL_Display, + SDL_Screen, + 0, /* view */ + saved_res.width, + saved_res.height, + 0); + XSync(SDL_Display, False); + } + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if ( use_xrandr ) { + XRRSetScreenConfig(SDL_Display, screen_config, SDL_Root, + saved_size_id, saved_rotation, CurrentTime); + } +#endif + + XUnmapWindow(SDL_Display, FSwindow); + X11_WaitUnmapped(this, FSwindow); + XSync(SDL_Display, True); /* Flush spurious mode change events */ + currently_fullscreen = 0; + } + /* If we get popped out of fullscreen mode for some reason, input_grab + will still have the SDL_GRAB_FULLSCREEN flag set, since this is only + temporary. In this case, release the grab unless the input has been + explicitly grabbed. + */ + X11_GrabInputNoLock(this, this->input_grab & ~SDL_GRAB_FULLSCREEN); + + /* We may need to refresh the screen at this point (no backing store) + We also don't get an event, which is why we explicitly refresh. */ + if ( this->screen ) { + if ( this->screen->flags & SDL_OPENGL ) { + SDL_PrivateExpose(); + } else { + X11_RefreshDisplay(this); + } + } + + return(0); +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h b/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h new file mode 100644 index 0000000..f7780bf --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11modes_c.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Utilities for getting and setting the X display mode */ + +#include "SDL_x11video.h" + +/* Define this if you want to grab the keyboard in fullscreen mode. + If you do not define this, SDL will return from SDL_SetVideoMode() + immediately, but will not actually go fullscreen until the window + manager is idle. +*/ +#define GRAB_FULLSCREEN + +extern int X11_GetVideoModes(_THIS); +extern SDL_Rect **X11_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +extern void X11_FreeVideoModes(_THIS); +extern int X11_ResizeFullScreen(_THIS); +extern void X11_WaitMapped(_THIS, Window win); +extern void X11_WaitUnmapped(_THIS, Window win); +extern void X11_QueueEnterFullScreen(_THIS); +extern int X11_EnterFullScreen(_THIS); +extern int X11_LeaveFullScreen(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11mouse.c b/3rdparty/SDL/src/video/x11/SDL_x11mouse.c new file mode 100644 index 0000000..16ad739 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11mouse.c @@ -0,0 +1,288 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "../SDL_cursor_c.h" +#include "SDL_x11dga_c.h" +#include "SDL_x11mouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + Cursor x_cursor; +}; + + +void X11_FreeWMCursor(_THIS, WMcursor *cursor) +{ + if ( SDL_Display != NULL ) { + SDL_Lock_EventThread(); + XFreeCursor(SDL_Display, cursor->x_cursor); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } + SDL_free(cursor); +} + +WMcursor *X11_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y) +{ + WMcursor *cursor; + XGCValues GCvalues; + GC GCcursor; + XImage *data_image, *mask_image; + Pixmap data_pixmap, mask_pixmap; + int clen, i; + char *x_data, *x_mask; + static XColor black = { 0, 0, 0, 0 }; + static XColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + /* Allocate the cursor memory */ + cursor = (WMcursor *)SDL_malloc(sizeof(WMcursor)); + if ( cursor == NULL ) { + SDL_OutOfMemory(); + return(NULL); + } + + /* Mix the mask and the data */ + clen = (w/8)*h; + x_data = (char *)SDL_malloc(clen); + if ( x_data == NULL ) { + SDL_free(cursor); + SDL_OutOfMemory(); + return(NULL); + } + x_mask = (char *)SDL_malloc(clen); + if ( x_mask == NULL ) { + SDL_free(cursor); + SDL_free(x_data); + SDL_OutOfMemory(); + return(NULL); + } + for ( i=0; i<clen; ++i ) { + /* The mask is OR'd with the data to turn inverted color + pixels black since inverted color cursors aren't supported + under X11. + */ + x_mask[i] = data[i] | mask[i]; + x_data[i] = data[i]; + } + + /* Prevent the event thread from running while we use the X server */ + SDL_Lock_EventThread(); + + /* Create the data image */ + data_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + 1, XYBitmap, 0, x_data, w, h, 8, w/8); + data_image->byte_order = MSBFirst; + data_image->bitmap_bit_order = MSBFirst; + data_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); + + /* Create the data mask */ + mask_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + 1, XYBitmap, 0, x_mask, w, h, 8, w/8); + mask_image->byte_order = MSBFirst; + mask_image->bitmap_bit_order = MSBFirst; + mask_pixmap = XCreatePixmap(SDL_Display, SDL_Root, w, h, 1); + + /* Create the graphics context */ + GCvalues.function = GXcopy; + GCvalues.foreground = ~0; + GCvalues.background = 0; + GCvalues.plane_mask = AllPlanes; + GCcursor = XCreateGC(SDL_Display, data_pixmap, + (GCFunction|GCForeground|GCBackground|GCPlaneMask), + &GCvalues); + + /* Blit the images to the pixmaps */ + XPutImage(SDL_Display, data_pixmap, GCcursor, data_image, + 0, 0, 0, 0, w, h); + XPutImage(SDL_Display, mask_pixmap, GCcursor, mask_image, + 0, 0, 0, 0, w, h); + XFreeGC(SDL_Display, GCcursor); + /* These free the x_data and x_mask memory pointers */ + XDestroyImage(data_image); + XDestroyImage(mask_image); + + /* Create the cursor */ + cursor->x_cursor = XCreatePixmapCursor(SDL_Display, data_pixmap, + mask_pixmap, &black, &white, hot_x, hot_y); + XFreePixmap(SDL_Display, data_pixmap); + XFreePixmap(SDL_Display, mask_pixmap); + + /* Release the event thread */ + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + + return(cursor); +} + +int X11_ShowWMCursor(_THIS, WMcursor *cursor) +{ + /* Don't do anything if the display is gone */ + if ( SDL_Display == NULL ) { + return(0); + } + + /* Set the X11 cursor cursor, or blank if cursor is NULL */ + if ( SDL_Window ) { + SDL_Lock_EventThread(); + if ( cursor == NULL ) { + if ( SDL_BlankCursor != NULL ) { + XDefineCursor(SDL_Display, SDL_Window, + SDL_BlankCursor->x_cursor); + } + } else { + XDefineCursor(SDL_Display, SDL_Window, cursor->x_cursor); + } + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } + return(1); +} + +void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y) +{ + if ( using_dga & DGA_MOUSE ) { + SDL_PrivateMouseMotion(0, 0, x, y); + } else if ( mouse_relative) { + /* RJR: March 28, 2000 + leave physical cursor at center of screen if + mouse hidden and grabbed */ + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + SDL_Lock_EventThread(); + XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0, x, y); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + } +} + +/* Sets the mouse acceleration from a string of the form: + 2/1/0 + The first number is the numerator, followed by the acceleration + denumenator and threshold. +*/ +static void SetMouseAccel(_THIS, const char *accel_param) +{ + int i; + size_t len; + int accel_value[3]; + char *mouse_param, *mouse_param_buf, *pin; + + len = SDL_strlen(accel_param)+1; + mouse_param_buf = SDL_stack_alloc(char, len); + if ( ! mouse_param_buf ) { + return; + } + SDL_strlcpy(mouse_param_buf, accel_param, len); + mouse_param = mouse_param_buf; + + for ( i=0; (i < 3) && mouse_param; ++i ) { + pin = SDL_strchr(mouse_param, '/'); + if ( pin ) { + *pin = '\0'; + } + accel_value[i] = atoi(mouse_param); + if ( pin ) { + mouse_param = pin+1; + } else { + mouse_param = NULL; + } + } + if ( i == 3 ) { + XChangePointerControl(SDL_Display, True, True, + accel_value[0], accel_value[1], accel_value[2]); + } + SDL_stack_free(mouse_param_buf); +} + +/* Check to see if we need to enter or leave mouse relative mode */ +void X11_CheckMouseModeNoLock(_THIS) +{ + const Uint8 full_focus = (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); + char *env_override; + int enable_relative = 1; + + /* This happens when quiting after an xio error */ + if ( SDL_Display == NULL ) + return; + + /* Allow the user to override the relative mouse mode. + They almost never want to do this, as it seriously affects + applications that rely on continuous relative mouse motion. + */ + env_override = SDL_getenv("SDL_MOUSE_RELATIVE"); + if ( env_override ) { + enable_relative = atoi(env_override); + } + + /* If the mouse is hidden and input is grabbed, we use relative mode */ + if ( enable_relative && + !(SDL_cursorstate & CURSOR_VISIBLE) && + (this->input_grab != SDL_GRAB_OFF) && + (SDL_GetAppState() & full_focus) == full_focus ) { + if ( ! mouse_relative ) { + X11_EnableDGAMouse(this); + if ( ! (using_dga & DGA_MOUSE) ) { + char *xmouse_accel; + + SDL_GetMouseState(&mouse_last.x, &mouse_last.y); + /* Use as raw mouse mickeys as possible */ + XGetPointerControl(SDL_Display, + &mouse_accel.numerator, + &mouse_accel.denominator, + &mouse_accel.threshold); + xmouse_accel=SDL_getenv("SDL_VIDEO_X11_MOUSEACCEL"); + if ( xmouse_accel ) { + SetMouseAccel(this, xmouse_accel); + } + } + mouse_relative = 1; + } + } else { + if ( mouse_relative ) { + if ( using_dga & DGA_MOUSE ) { + X11_DisableDGAMouse(this); + } else { + XChangePointerControl(SDL_Display, True, True, + mouse_accel.numerator, + mouse_accel.denominator, + mouse_accel.threshold); + } + mouse_relative = 0; + } + } +} +void X11_CheckMouseMode(_THIS) +{ + SDL_Lock_EventThread(); + X11_CheckMouseModeNoLock(this); + SDL_Unlock_EventThread(); +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h b/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h new file mode 100644 index 0000000..03d97d8 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11mouse_c.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_FreeWMCursor(_THIS, WMcursor *cursor); +extern WMcursor *X11_CreateWMCursor(_THIS, + Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y); +extern int X11_ShowWMCursor(_THIS, WMcursor *cursor); +extern void X11_WarpWMCursor(_THIS, Uint16 x, Uint16 y); +extern void X11_CheckMouseModeNoLock(_THIS); +extern void X11_CheckMouseMode(_THIS); diff --git a/3rdparty/SDL/src/video/x11/SDL_x11sym.h b/3rdparty/SDL/src/video/x11/SDL_x11sym.h new file mode 100644 index 0000000..4875b98 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11sym.h @@ -0,0 +1,201 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +SDL_X11_MODULE(BASEXLIB) +SDL_X11_SYM(XClassHint*,XAllocClassHint,(void),(),return) +SDL_X11_SYM(Status,XAllocColor,(Display* a,Colormap b,XColor* c),(a,b,c),return) +SDL_X11_SYM(XSizeHints*,XAllocSizeHints,(void),(),return) +SDL_X11_SYM(XWMHints*,XAllocWMHints,(void),(),return) +SDL_X11_SYM(int,XChangePointerControl,(Display* a,Bool b,Bool c,int d,int e,int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XChangeProperty,(Display* a,Window b,Atom c,Atom d,int e,int f,_Xconst unsigned char* g,int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(int,XChangeWindowAttributes,(Display* a,Window b,unsigned long c,XSetWindowAttributes* d),(a,b,c,d),return) +SDL_X11_SYM(Bool,XCheckTypedEvent,(Display* a,int b,XEvent* c),(a,b,c),return) +SDL_X11_SYM(int,XClearWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XCloseDisplay,(Display* a),(a),return) +SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return) +SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) +SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return) +SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(Pixmap,XCreatePixmap,(Display* a,Drawable b,unsigned int c,unsigned int d,unsigned int e),(a,b,c,d,e),return) +SDL_X11_SYM(Pixmap,XCreatePixmapFromBitmapData,(Display* a,Drawable b,char* c,unsigned int d,unsigned int e,unsigned long f,unsigned long g,unsigned int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(Window,XCreateSimpleWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,unsigned long h,unsigned long i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return) +SDL_X11_SYM(int,XDefineCursor,(Display* a,Window b,Cursor c),(a,b,c),return) +SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return) +SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return) +SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event, Window w),(event,w),return) +SDL_X11_SYM(int,XFlush,(Display* a),(a),return) +SDL_X11_SYM(int,XFree,(void*a),(a),return) +SDL_X11_SYM(int,XFreeColormap,(Display* a,Colormap b),(a,b),return) +SDL_X11_SYM(int,XFreeColors,(Display* a,Colormap b,unsigned long* c,int d,unsigned long e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) +SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) +SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) +SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) +SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return) +SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return) +SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return) +SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return) +SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(Status,XIconifyWindow,(Display* a,Window b,int c),(a,b,c),return) +SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) +SDL_X11_SYM(KeyCode,XKeysymToKeycode,(Display* a,KeySym b),(a,b),return) +SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) +SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) +SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XMapWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XMaskEvent,(Display* a,long b,XEvent* c),(a,b,c),return) +SDL_X11_SYM(Status,XMatchVisualInfo,(Display* a,int b,int c,int d,XVisualInfo* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XMissingExtension,(Display* a,_Xconst char* b),(a,b),return) +SDL_X11_SYM(int,XMoveResizeWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f),(a,b,c,d,e,f),return) +SDL_X11_SYM(int,XMoveWindow,(Display* a,Window b,int c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XNextEvent,(Display* a,XEvent* b),(a,b),return) +SDL_X11_SYM(Display*,XOpenDisplay,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return) +SDL_X11_SYM(int,XPending,(Display* a),(a),return) +SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(int,XQueryColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return) +SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XReparentWindow,(Display* a,Window b,Window c,int d,int e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XResetScreenSaver,(Display* a),(a),return) +SDL_X11_SYM(int,XResizeWindow,(Display* a,Window b,unsigned int c,unsigned int d),(a,b,c,d),return) +SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return) +SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XSetClassHint,(Display* a,Window b,XClassHint* c),(a,b,c),return) +SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return) +SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return) +SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return) +SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return) +SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),) +SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) +SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return) +SDL_X11_SYM(int,XSetWindowBackgroundPixmap,(Display* a,Window b,Pixmap c),(a,b,c),return) +SDL_X11_SYM(int,XSetWindowColormap,(Display* a,Window b,Colormap c),(a,b,c),return) +SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) +SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return) +SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return) +SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return) +SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return) +SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return) +SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h, int i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) +SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return) +SDL_X11_SYM(XExtensionInfo*,XextCreateExtension,(void),(),return) +SDL_X11_SYM(void,XextDestroyExtension,(XExtensionInfo* a),(a),) +SDL_X11_SYM(XExtDisplayInfo*,XextFindDisplay,(XExtensionInfo* a,Display* b),(a,b),return) +SDL_X11_SYM(int,XextRemoveDisplay,(XExtensionInfo* a,Display* b),(a,b),return) +SDL_X11_SYM(Bool,XQueryExtension,(Display* a,_Xconst char* b,int* c,int* d,int* e),(a,b,c,d,e),return) +SDL_X11_SYM(char *,XDisplayString,(Display* a),(a),return) +SDL_X11_SYM(int,XGetErrorText,(Display* a,int b,char* c,int d),(a,b,c,d),return) +SDL_X11_SYM(void,_XEatData,(Display* a,unsigned long b),(a,b),) +SDL_X11_SYM(void,_XFlush,(Display* a),(a),) +SDL_X11_SYM(void,_XFlushGCCache,(Display* a,GC b),(a,b),) +SDL_X11_SYM(int,_XRead,(Display* a,char* b,long c),(a,b,c),return) +SDL_X11_SYM(void,_XReadPad,(Display* a,char* b,long c),(a,b,c),) +SDL_X11_SYM(void,_XSend,(Display* a,_Xconst char* b,long c),(a,b,c),) +SDL_X11_SYM(Status,_XReply,(Display* a,xReply* b,int c,Bool d),(a,b,c,d),return) +SDL_X11_SYM(unsigned long,_XSetLastRequestRead,(Display* a,xGenericReply* b),(a,b),return) +SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),return) +SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return) +SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return) +SDL_X11_SYM(XExtensionErrorHandler,XSetExtensionErrorHandler,(XExtensionErrorHandler a),(a),return) + +#if NeedWidePrototypes +SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return) +#else +SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return) +#endif + +#ifdef X_HAVE_UTF8_STRING +SDL_X11_MODULE(UTF8) +SDL_X11_SYM(int,Xutf8TextListToTextProperty,(Display* a,char** b,int c,XICCEncodingStyle d,XTextProperty* e),(a,b,c,d,e),return) +SDL_X11_SYM(int,Xutf8LookupString,(XIC a,XKeyPressedEvent* b,char* c,int d,KeySym* e,Status* f),(a,b,c,d,e,f),return) +/*SDL_X11_SYM(XIC,XCreateIC,(XIM, ...),return) !!! ARGH! */ +SDL_X11_SYM(void,XDestroyIC,(XIC a),(a),) +SDL_X11_SYM(void,XSetICFocus,(XIC a),(a),) +SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),) +/*SDL_X11_SYM(char*,XGetICValues,(XIC a, ...),return)*/ +SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return) +SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return) +SDL_X11_SYM(char*,XSetLocaleModifiers,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XRefreshKeyboardMapping,(XMappingEvent* a),(a),return) +SDL_X11_SYM(Display*,XDisplayOfIM,(XIM a),(a),return) +#endif + +#ifndef NO_SHARED_MEMORY +SDL_X11_MODULE(SHM) +SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return) +SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return) +SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return) +SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return) +SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return) +#endif + +/* + * Not required...these only exist in code in headers on some 64-bit platforms, + * and are removed via macros elsewhere, so it's safe for them to be missing. + */ +#ifdef LONG64 +SDL_X11_MODULE(IO_32BIT) +SDL_X11_SYM(int,_XData32,(Display *dpy,register long *data,unsigned len),(dpy,data,len),return) +SDL_X11_SYM(void,_XRead32,(Display *dpy,register long *data,long len),(dpy,data,len),) +#endif + +/* + * libX11 1.4.99.1 added _XGetRequest, and macros use it behind the scenes. + */ +SDL_X11_MODULE(XGETREQUEST) +SDL_X11_SYM(void *,_XGetRequest,(Display* a,CARD8 b,size_t c),(a,b,c),return) + +/* + * These only show up on some variants of Unix. + */ +#if defined(__osf__) +SDL_X11_MODULE(OSF_ENTRY_POINTS) +SDL_X11_SYM(void,_SmtBufferOverflow,(Display *dpy,register smtDisplayPtr p),(dpy,p),) +SDL_X11_SYM(void,_SmtIpError,(Display *dpy,register smtDisplayPtr p, int i),(dpy,p,i),) +SDL_X11_SYM(int,ipAllocateData,(ChannelPtr a, IPCard b, IPDataPtr * c),(a,b,c),return) +SDL_X11_SYM(int,ipUnallocateAndSendData,(ChannelPtr a, IPCard b),(a,b),return) +#endif + +/* Xrandr support. */ +#if SDL_VIDEO_DRIVER_X11_XRANDR +SDL_X11_MODULE(XRANDR) +SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return) +SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return) +SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return) +SDL_X11_SYM(XRRScreenSize *,XRRConfigSizes,(XRRScreenConfiguration *config, int *nsizes),(config,nsizes),return) +SDL_X11_SYM(Status,XRRSetScreenConfig,(Display *dpy, XRRScreenConfiguration *config, Drawable draw, int size_index, Rotation rotation, Time timestamp),(dpy,config,draw,size_index,rotation,timestamp),return) +SDL_X11_SYM(void,XRRFreeScreenConfigInfo,(XRRScreenConfiguration *config),(config),) +#endif + +/* end of SDL_x11sym.h ... */ + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11video.c b/3rdparty/SDL/src/video/x11/SDL_x11video.c new file mode 100644 index 0000000..f7d8073 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11video.c @@ -0,0 +1,1571 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* X11 based SDL video driver implementation. + Note: This implementation does not currently need X11 thread locking, + since the event thread uses a separate X connection and any + additional locking necessary is handled internally. However, + if full locking is neccessary, take a look at XInitThreads(). +*/ + +#include <unistd.h> +#include <sys/ioctl.h> +#ifdef MTRR_SUPPORT +#include <asm/mtrr.h> +#include <sys/fcntl.h> +#endif + +#include "SDL_endian.h" +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11video.h" +#include "SDL_x11wm_c.h" +#include "SDL_x11mouse_c.h" +#include "SDL_x11events_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11image_c.h" +#include "SDL_x11yuv_c.h" +#include "SDL_x11gl_c.h" +#include "SDL_x11gamma_c.h" +#include "../blank_cursor.h" + +#ifdef X_HAVE_UTF8_STRING +#include <locale.h> +#endif + +/* Initialization/Query functions */ +static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int X11_ToggleFullScreen(_THIS, int on); +static void X11_UpdateMouse(_THIS); +static int X11_SetColors(_THIS, int firstcolor, int ncolors, + SDL_Color *colors); +static int X11_SetGammaRamp(_THIS, Uint16 *ramp); +static void X11_VideoQuit(_THIS); + + +/* X11 driver bootstrap functions */ + +static int X11_Available(void) +{ + Display *display = NULL; + if ( SDL_X11_LoadSymbols() ) { + display = XOpenDisplay(NULL); + if ( display != NULL ) { + XCloseDisplay(display); + } + SDL_X11_UnloadSymbols(); + } + return(display != NULL); +} + +static void X11_DeleteDevice(SDL_VideoDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + SDL_free(device->hidden); + } + if ( device->gl_data ) { + SDL_free(device->gl_data); + } + SDL_free(device); + SDL_X11_UnloadSymbols(); + } +} + +static SDL_VideoDevice *X11_CreateDevice(int devindex) +{ + SDL_VideoDevice *device = NULL; + + if ( SDL_X11_LoadSymbols() ) { + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) || + (device->gl_data == NULL) ) { + SDL_OutOfMemory(); + X11_DeleteDevice(device); /* calls SDL_X11_UnloadSymbols(). */ + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, (sizeof *device->gl_data)); + +#if SDL_VIDEO_OPENGL_GLX + device->gl_data->swap_interval = -1; +#endif + + /* Set the driver flags */ + device->handles_any_size = 1; + + /* Set the function pointers */ + device->VideoInit = X11_VideoInit; + device->ListModes = X11_ListModes; + device->SetVideoMode = X11_SetVideoMode; + device->ToggleFullScreen = X11_ToggleFullScreen; + device->UpdateMouse = X11_UpdateMouse; +#if SDL_VIDEO_DRIVER_X11_XV + device->CreateYUVOverlay = X11_CreateYUVOverlay; +#endif + device->SetColors = X11_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = X11_VideoQuit; + device->AllocHWSurface = X11_AllocHWSurface; + device->CheckHWBlit = NULL; + device->FillHWRect = NULL; + device->SetHWColorKey = NULL; + device->SetHWAlpha = NULL; + device->LockHWSurface = X11_LockHWSurface; + device->UnlockHWSurface = X11_UnlockHWSurface; + device->FlipHWSurface = X11_FlipHWSurface; + device->FreeHWSurface = X11_FreeHWSurface; + device->SetGamma = X11_SetVidModeGamma; + device->GetGamma = X11_GetVidModeGamma; + device->SetGammaRamp = X11_SetGammaRamp; + device->GetGammaRamp = NULL; +#if SDL_VIDEO_OPENGL_GLX + device->GL_LoadLibrary = X11_GL_LoadLibrary; + device->GL_GetProcAddress = X11_GL_GetProcAddress; + device->GL_GetAttribute = X11_GL_GetAttribute; + device->GL_MakeCurrent = X11_GL_MakeCurrent; + device->GL_SwapBuffers = X11_GL_SwapBuffers; +#endif + device->SetCaption = X11_SetCaption; + device->SetIcon = X11_SetIcon; + device->IconifyWindow = X11_IconifyWindow; + device->GrabInput = X11_GrabInput; + device->GetWMInfo = X11_GetWMInfo; + device->FreeWMCursor = X11_FreeWMCursor; + device->CreateWMCursor = X11_CreateWMCursor; + device->ShowWMCursor = X11_ShowWMCursor; + device->WarpWMCursor = X11_WarpWMCursor; + device->CheckMouseMode = X11_CheckMouseMode; + device->InitOSKeymap = X11_InitOSKeymap; + device->PumpEvents = X11_PumpEvents; + + device->free = X11_DeleteDevice; + } + + return device; +} + +VideoBootStrap X11_bootstrap = { + "x11", "X Window System", + X11_Available, X11_CreateDevice +}; + +/* Normal X11 error handler routine */ +static int (*X_handler)(Display *, XErrorEvent *) = NULL; +static int x_errhandler(Display *d, XErrorEvent *e) +{ +#if SDL_VIDEO_DRIVER_X11_VIDMODE + extern int vm_error; +#endif +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + extern int dga_error; +#endif + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + /* VidMode errors are non-fatal. :) */ + /* Are the errors offset by one from the error base? + e.g. the error base is 143, the code is 148, and the + actual error is XF86VidModeExtensionDisabled (4) ? + */ + if ( (vm_error >= 0) && + (((e->error_code == BadRequest)&&(e->request_code == vm_error)) || + ((e->error_code > vm_error) && + (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) { +#ifdef X11_DEBUG +{ char errmsg[1024]; + XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); +printf("VidMode error: %s\n", errmsg); +} +#endif + return(0); + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE + /* DGA errors can be non-fatal. :) */ + if ( (dga_error >= 0) && + ((e->error_code > dga_error) && + (e->error_code <= (dga_error+XF86DGANumberErrors))) ) { +#ifdef X11_DEBUG +{ char errmsg[1024]; + XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg)); +printf("DGA error: %s\n", errmsg); +} +#endif + return(0); + } +#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */ + + return(X_handler(d,e)); +} + +/* X11 I/O error handler routine */ +static int (*XIO_handler)(Display *) = NULL; +static int xio_errhandler(Display *d) +{ + /* Ack! Lost X11 connection! */ + + /* We will crash if we try to clean up our display */ + if ( SDL_VideoSurface && current_video->hidden->Ximage ) { + SDL_VideoSurface->pixels = NULL; + } + current_video->hidden->X11_Display = NULL; + + /* Continue with the standard X11 error handler */ + return(XIO_handler(d)); +} + +static int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL; +static int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason) +{ +#ifdef X11_DEBUG + printf("Xext error inside SDL (may be harmless):\n"); + printf(" Extension \"%s\" %s on display \"%s\".\n", + ext, reason, XDisplayString(d)); +#endif + + if (SDL_strcmp(reason, "missing") == 0) { + /* + * Since the query itself, elsewhere, can handle a missing extension + * and the default behaviour in Xlib is to write to stderr, which + * generates unnecessary bug reports, we just ignore these. + */ + return 0; + } + + /* Everything else goes to the default handler... */ + return Xext_handler(d, ext, reason); +} + +/* Find out what class name we should use */ +static char *get_classname(char *classname, int maxlen) +{ + char *spot; +#if defined(__LINUX__) || defined(__FREEBSD__) + char procfile[1024]; + char linkfile[1024]; + int linksize; +#endif + + /* First allow environment variable override */ + spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS"); + if ( spot ) { + SDL_strlcpy(classname, spot, maxlen); + return classname; + } + + /* Next look at the application's executable name */ +#if defined(__LINUX__) || defined(__FREEBSD__) +#if defined(__LINUX__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid()); +#elif defined(__FREEBSD__) + SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid()); +#else +#error Where can we find the executable name? +#endif + linksize = readlink(procfile, linkfile, sizeof(linkfile)-1); + if ( linksize > 0 ) { + linkfile[linksize] = '\0'; + spot = SDL_strrchr(linkfile, '/'); + if ( spot ) { + SDL_strlcpy(classname, spot+1, maxlen); + } else { + SDL_strlcpy(classname, linkfile, maxlen); + } + return classname; + } +#endif /* __LINUX__ */ + + /* Finally use the default we've used forever */ + SDL_strlcpy(classname, "SDL_App", maxlen); + return classname; +} + +/* Create auxiliary (toplevel) windows with the current visual */ +static void create_aux_windows(_THIS) +{ + int x = 0, y = 0; + char classname[1024]; + XSetWindowAttributes xattr; + XWMHints *hints; + unsigned long app_event_mask; + int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen)); + + /* Look up some useful Atoms */ + WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False); + + /* Don't create any extra windows if we are being managed */ + if ( SDL_windowid ) { + FSwindow = 0; + WMwindow = SDL_strtol(SDL_windowid, NULL, 0); + return; + } + + if(FSwindow) + XDestroyWindow(SDL_Display, FSwindow); + +#if SDL_VIDEO_DRIVER_X11_XINERAMA + if ( use_xinerama ) { + x = xinerama_info.x_org; + y = xinerama_info.y_org; + } +#endif + xattr.override_redirect = True; + xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0; + xattr.border_pixel = 0; + xattr.colormap = SDL_XColorMap; + + FSwindow = XCreateWindow(SDL_Display, SDL_Root, + x, y, 32, 32, 0, + this->hidden->depth, InputOutput, SDL_Visual, + CWOverrideRedirect | CWBackPixel | CWBorderPixel + | CWColormap, + &xattr); + + XSelectInput(SDL_Display, FSwindow, StructureNotifyMask); + + /* Tell KDE to keep the fullscreen window on top */ + { + XEvent ev; + long mask; + + SDL_memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = SDL_Root; + ev.xclient.message_type = XInternAtom(SDL_Display, + "KWM_KEEP_ON_TOP", False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = FSwindow; + ev.xclient.data.l[1] = CurrentTime; + mask = SubstructureRedirectMask; + XSendEvent(SDL_Display, SDL_Root, False, mask, &ev); + } + + hints = NULL; + if(WMwindow) { + /* All window attributes must survive the recreation */ + hints = XGetWMHints(SDL_Display, WMwindow); + XDestroyWindow(SDL_Display, WMwindow); + } + + /* Create the window for windowed management */ + /* (reusing the xattr structure above) */ + WMwindow = XCreateWindow(SDL_Display, SDL_Root, + x, y, 32, 32, 0, + this->hidden->depth, InputOutput, SDL_Visual, + CWBackPixel | CWBorderPixel | CWColormap, + &xattr); + + /* Set the input hints so we get keyboard input */ + if(!hints) { + hints = XAllocWMHints(); + hints->input = True; + hints->flags = InputHint; + } + XSetWMHints(SDL_Display, WMwindow, hints); + XFree(hints); + X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon); + + app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | PropertyChangeMask | StructureNotifyMask | KeymapStateMask; + XSelectInput(SDL_Display, WMwindow, app_event_mask); + + /* Set the class hints so we can get an icon (AfterStep) */ + get_classname(classname, sizeof(classname)); + { + XClassHint *classhints; + classhints = XAllocClassHint(); + if(classhints != NULL) { + classhints->res_name = classname; + classhints->res_class = classname; + XSetClassHint(SDL_Display, WMwindow, classhints); + XFree(classhints); + } + } + + { + pid_t pid = getpid(); + char hostname[256]; + + if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) { + Atom _NET_WM_PID = XInternAtom(SDL_Display, "_NET_WM_PID", False); + Atom WM_CLIENT_MACHINE = XInternAtom(SDL_Display, "WM_CLIENT_MACHINE", False); + + hostname[sizeof(hostname)-1] = '\0'; + XChangeProperty(SDL_Display, WMwindow, _NET_WM_PID, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&pid, 1); + XChangeProperty(SDL_Display, WMwindow, WM_CLIENT_MACHINE, XA_STRING, 8, + PropModeReplace, (unsigned char *)hostname, SDL_strlen(hostname)); + } + } + + /* Setup the communication with the IM server */ + /* create_aux_windows may be called several times against the same + Display. We should reuse the SDL_IM if one has been opened for + the Display, so we should not simply reset SDL_IM here. */ + + #ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + /* Discard obsolete resources if any. */ + if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) { + /* Just a double check. I don't think this + code is ever executed. */ + SDL_SetError("display has changed while an IM is kept"); + if (SDL_IC) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + } + XCloseIM(SDL_IM); + SDL_IM = NULL; + } + + /* Open an input method. */ + if (SDL_IM == NULL) { + char *old_locale = NULL, *old_modifiers = NULL; + const char *p; + size_t n; + /* I'm not comfortable to do locale setup + here. However, we need C library locale + (and xlib modifiers) to be set based on the + user's preference to use XIM, and many + existing game programs doesn't take care of + users' locale preferences, so someone other + than the game program should do it. + Moreover, ones say that some game programs + heavily rely on the C locale behaviour, + e.g., strcol()'s, and we can't change the C + library locale. Given the situation, I + couldn't find better place to do the + job... */ + + /* Save the current (application program's) + locale settings. */ + p = setlocale(LC_ALL, NULL); + if ( p ) { + n = SDL_strlen(p)+1; + old_locale = SDL_stack_alloc(char, n); + if ( old_locale ) { + SDL_strlcpy(old_locale, p, n); + } + } + p = XSetLocaleModifiers(NULL); + if ( p ) { + n = SDL_strlen(p)+1; + old_modifiers = SDL_stack_alloc(char, n); + if ( old_modifiers ) { + SDL_strlcpy(old_modifiers, p, n); + } + } + + /* Fetch the user's preferences and open the + input method with them. */ + setlocale(LC_ALL, ""); + XSetLocaleModifiers(""); + SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname); + + /* Restore the application's locale settings + so that we don't break the application's + expected behaviour. */ + if ( old_locale ) { + /* We need to restore the C library + locale first, since the + interpretation of the X modifier + may depend on it. */ + setlocale(LC_ALL, old_locale); + SDL_stack_free(old_locale); + } + if ( old_modifiers ) { + XSetLocaleModifiers(old_modifiers); + SDL_stack_free(old_modifiers); + } + } + + /* Create a new input context for the new window just created. */ + if (SDL_IM == NULL) { + SDL_SetError("no input method could be opened"); + } else { + if (SDL_IC != NULL) { + /* Discard the old IC before creating new one. */ + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + } + /* Theoretically we should check the current IM supports + PreeditNothing+StatusNothing style (i.e., root window method) + before creating the IC. However, it is the bottom line method, + and we supports any other options. If the IM didn't support + root window method, the following call fails, and SDL falls + back to pre-XIM keyboard handling. */ + SDL_IC = pXCreateIC(SDL_IM, + XNClientWindow, WMwindow, + XNFocusWindow, WMwindow, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNResourceName, classname, + XNResourceClass, classname, + NULL); + + if (SDL_IC == NULL) { + SDL_SetError("no input context could be created"); + XCloseIM(SDL_IM); + SDL_IM = NULL; + } else { + /* We need to receive X events that an IM wants and to pass + them to the IM through XFilterEvent. The set of events may + vary depending on the IM implementation and the options + specified through various routes. Although unlikely, the + xlib specification allows IM to change the event requirement + with its own circumstances, it is safe to call SelectInput + whenever we re-create an IC. */ + unsigned long mask = 0; + char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL); + if (ret != NULL) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + SDL_SetError("no input context could be created"); + XCloseIM(SDL_IM); + SDL_IM = NULL; + } else { + XSelectInput(SDL_Display, WMwindow, app_event_mask | mask); + XSetICFocus(SDL_IC); + } + } + } + } + #endif + + /* Allow the window to be deleted by the window manager */ + XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1); +} + +static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const char *env; + char *display; + int i; + + /* Open the X11 display */ + display = NULL; /* Get it from DISPLAY environment variable */ + + if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) || + (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) { + local_X11 = 1; + } else { + local_X11 = 0; + } + SDL_Display = XOpenDisplay(display); +#if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC) + /* On Tru64 if linking without -lX11, it fails and you get following message. + * Xlib: connection to ":0.0" refused by server + * Xlib: XDM authorization key matches an existing client! + * + * It succeeds if retrying 1 second later + * or if running xhost +localhost on shell. + * + */ + if ( SDL_Display == NULL ) { + SDL_Delay(1000); + SDL_Display = XOpenDisplay(display); + } +#endif + if ( SDL_Display == NULL ) { + SDL_SetError("Couldn't open X11 display"); + return(-1); + } +#ifdef X11_DEBUG + XSynchronize(SDL_Display, True); +#endif + + /* Create an alternate X display for graphics updates -- allows us + to do graphics updates in a separate thread from event handling. + Thread-safe X11 doesn't seem to exist. + */ + GFX_Display = XOpenDisplay(display); + if ( GFX_Display == NULL ) { + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + SDL_SetError("Couldn't open X11 display"); + return(-1); + } + + /* Set the normal X error handler */ + X_handler = XSetErrorHandler(x_errhandler); + + /* Set the error handler if we lose the X display */ + XIO_handler = XSetIOErrorHandler(xio_errhandler); + + /* Set the X extension error handler */ + Xext_handler = XSetExtensionErrorHandler(xext_errhandler); + + /* use default screen (from $DISPLAY) */ + SDL_Screen = DefaultScreen(SDL_Display); + +#ifndef NO_SHARED_MEMORY + /* Check for MIT shared memory extension */ + use_mitshm = 0; + if ( local_X11 ) { + use_mitshm = XShmQueryExtension(SDL_Display); + } +#endif /* NO_SHARED_MEMORY */ + + /* Get the available video modes */ + if(X11_GetVideoModes(this) < 0) { + XCloseDisplay(GFX_Display); + GFX_Display = NULL; + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + return -1; + } + + /* Determine the current screen size */ + this->info.current_w = DisplayWidth(SDL_Display, SDL_Screen); + this->info.current_h = DisplayHeight(SDL_Display, SDL_Screen); + + /* Determine the default screen depth: + Use the default visual (or at least one with the same depth) */ + SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen); + for(i = 0; i < this->hidden->nvisuals; i++) + if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display, + SDL_Screen)) + break; + if(i == this->hidden->nvisuals) { + /* default visual was useless, take the deepest one instead */ + i = 0; + } + SDL_Visual = this->hidden->visuals[i].visual; + if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) { + SDL_XColorMap = SDL_DisplayColormap; + } else { + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocNone); + } + this->hidden->depth = this->hidden->visuals[i].depth; + vformat->BitsPerPixel = this->hidden->visuals[i].bpp; + if ( vformat->BitsPerPixel > 8 ) { + vformat->Rmask = SDL_Visual->red_mask; + vformat->Gmask = SDL_Visual->green_mask; + vformat->Bmask = SDL_Visual->blue_mask; + } + if ( this->hidden->depth == 32 ) { + vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask)); + } + X11_SaveVidModeGamma(this); + + /* Allow environment override of screensaver disable. */ + env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); + if ( env ) { + allow_screensaver = SDL_atoi(env); + } else { +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + allow_screensaver = 0; +#else + allow_screensaver = 1; +#endif + } + + /* See if we have been passed a window to use */ + SDL_windowid = SDL_getenv("SDL_WINDOWID"); + + /* Create the fullscreen and managed windows */ + create_aux_windows(this); + + /* Create the blank cursor */ + SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask, + BLANK_CWIDTH, BLANK_CHEIGHT, + BLANK_CHOTX, BLANK_CHOTY); + + /* Fill in some window manager capabilities */ + this->info.wm_available = 1; + + /* We're done! */ + XFlush(SDL_Display); + return(0); +} + +static void X11_DestroyWindow(_THIS, SDL_Surface *screen) +{ + /* Clean up OpenGL */ + if ( screen ) { + screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT); + } + X11_GL_Shutdown(this); + + if ( ! SDL_windowid ) { + /* Hide the managed window */ + if ( WMwindow ) { + XUnmapWindow(SDL_Display, WMwindow); + } + if ( screen && (screen->flags & SDL_FULLSCREEN) ) { + screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + + /* Destroy the output window */ + if ( SDL_Window ) { + XDestroyWindow(SDL_Display, SDL_Window); + } + + /* Free the colormap entries */ + if ( SDL_XPixels ) { + int numcolors; + unsigned long pixel; + numcolors = SDL_Visual->map_entries; + for ( pixel=0; pixel<numcolors; ++pixel ) { + while ( SDL_XPixels[pixel] > 0 ) { + XFreeColors(GFX_Display, + SDL_DisplayColormap,&pixel,1,0); + --SDL_XPixels[pixel]; + } + } + SDL_free(SDL_XPixels); + SDL_XPixels = NULL; + } + + /* Free the graphics context */ + if ( SDL_GC ) { + XFreeGC(SDL_Display, SDL_GC); + SDL_GC = 0; + } + } +} + +static SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h) +{ + const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); + const char *center = SDL_getenv("SDL_VIDEO_CENTERED"); + if ( window ) { + if ( SDL_sscanf(window, "%d,%d", x, y) == 2 ) { + return SDL_TRUE; + } + if ( SDL_strcmp(window, "center") == 0 ) { + center = window; + } + } + if ( center ) { + *x = (DisplayWidth(SDL_Display, SDL_Screen) - w)/2; + *y = (DisplayHeight(SDL_Display, SDL_Screen) - h)/2; + return SDL_TRUE; + } + return SDL_FALSE; +} + +static void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags) +{ + XSizeHints *hints; + + hints = XAllocSizeHints(); + if ( hints ) { + if (!(flags & SDL_RESIZABLE)) { + hints->min_width = hints->max_width = w; + hints->min_height = hints->max_height = h; + hints->flags = PMaxSize | PMinSize; + } + if ( flags & SDL_FULLSCREEN ) { + hints->x = 0; + hints->y = 0; + hints->flags |= USPosition; + } else + /* Center it, if desired */ + if ( X11_WindowPosition(this, &hints->x, &hints->y, w, h) ) { + hints->flags |= USPosition; + + /* Hints must be set before moving the window, otherwise an + unwanted ConfigureNotify event will be issued */ + XSetWMNormalHints(SDL_Display, WMwindow, hints); + + XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y); + + /* Flush the resize event so we don't catch it later */ + XSync(SDL_Display, True); + } + XSetWMNormalHints(SDL_Display, WMwindow, hints); + XFree(hints); + } + + /* Respect the window caption style */ + if ( flags & SDL_NOFRAME ) { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to set MWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); + if ( WM_HINTS != None ) { + /* Hints used by Motif compliant window managers */ + struct { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; + } MWMHints = { (1L << 1), 0, 0, 0, 0 }; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&MWMHints, + sizeof(MWMHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set KWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); + if ( WM_HINTS != None ) { + long KWMHints = 0; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&KWMHints, + sizeof(KWMHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Now try to set GNOME hints */ + WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); + if ( WM_HINTS != None ) { + long GNOMEHints = 0; + + XChangeProperty(SDL_Display, WMwindow, + WM_HINTS, WM_HINTS, 32, + PropModeReplace, + (unsigned char *)&GNOMEHints, + sizeof(GNOMEHints)/sizeof(long)); + set = SDL_TRUE; + } + /* Finally set the transient hints if necessary */ + if ( ! set ) { + XSetTransientForHint(SDL_Display, WMwindow, SDL_Root); + } + } else { + SDL_bool set; + Atom WM_HINTS; + + /* We haven't modified the window manager hints yet */ + set = SDL_FALSE; + + /* First try to unset MWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset KWM hints */ + WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Now try to unset GNOME hints */ + WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True); + if ( WM_HINTS != None ) { + XDeleteProperty(SDL_Display, WMwindow, WM_HINTS); + set = SDL_TRUE; + } + /* Finally unset the transient hints if necessary */ + if ( ! set ) { + XDeleteProperty(SDL_Display, WMwindow, XA_WM_TRANSIENT_FOR); + } + } +} + +static int X11_CreateWindow(_THIS, SDL_Surface *screen, + int w, int h, int bpp, Uint32 flags) +{ + int i, depth; + Visual *vis; + int vis_change; + Uint32 Amask; + + /* If a window is already present, destroy it and start fresh */ + if ( SDL_Window ) { + X11_DestroyWindow(this, screen); + switch_waiting = 0; /* Prevent jump back to now-meaningless state. */ + } + + /* See if we have been given a window id */ + if ( SDL_windowid ) { + SDL_Window = SDL_strtol(SDL_windowid, NULL, 0); + } else { + SDL_Window = 0; + } + + /* find out which visual we are going to use */ + if ( flags & SDL_OPENGL ) { + XVisualInfo *vi; + + vi = X11_GL_GetVisual(this); + if( !vi ) { + return -1; + } + vis = vi->visual; + depth = vi->depth; + } else if ( SDL_windowid ) { + XWindowAttributes a; + + XGetWindowAttributes(SDL_Display, SDL_Window, &a); + vis = a.visual; + depth = a.depth; + } else { + for ( i = 0; i < this->hidden->nvisuals; i++ ) { + if ( this->hidden->visuals[i].bpp == bpp ) + break; + } + if ( i == this->hidden->nvisuals ) { + SDL_SetError("No matching visual for requested depth"); + return -1; /* should never happen */ + } + vis = this->hidden->visuals[i].visual; + depth = this->hidden->visuals[i].depth; + } +#ifdef X11_DEBUG + printf("Choosing %s visual at %d bpp - %d colormap entries\n", vis->class == PseudoColor ? "PseudoColor" : (vis->class == TrueColor ? "TrueColor" : (vis->class == DirectColor ? "DirectColor" : "Unknown")), depth, vis->map_entries); +#endif + vis_change = (vis != SDL_Visual); + SDL_Visual = vis; + this->hidden->depth = depth; + + /* Allocate the new pixel format for this video mode */ + if ( this->hidden->depth == 32 ) { + Amask = (0xFFFFFFFF & ~(vis->red_mask|vis->green_mask|vis->blue_mask)); + } else { + Amask = 0; + } + if ( ! SDL_ReallocFormat(screen, bpp, + vis->red_mask, vis->green_mask, vis->blue_mask, Amask) ) { + return -1; + } + + /* Create the appropriate colormap */ + if ( SDL_XColorMap != SDL_DisplayColormap ) { + XFreeColormap(SDL_Display, SDL_XColorMap); + } + if ( SDL_Visual->class == PseudoColor ) { + int ncolors; + + /* Allocate the pixel flags */ + ncolors = SDL_Visual->map_entries; + SDL_XPixels = SDL_malloc(ncolors * sizeof(int)); + if(SDL_XPixels == NULL) { + SDL_OutOfMemory(); + return -1; + } + SDL_memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels)); + + /* always allocate a private colormap on non-default visuals */ + if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) { + flags |= SDL_HWPALETTE; + } + if ( flags & SDL_HWPALETTE ) { + screen->flags |= SDL_HWPALETTE; + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocAll); + } else { + SDL_XColorMap = SDL_DisplayColormap; + } + } else if ( SDL_Visual->class == DirectColor ) { + + /* Create a colormap which we can manipulate for gamma */ + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocAll); + XSync(SDL_Display, False); + + /* Initialize the colormap to the identity mapping */ + SDL_GetGammaRamp(0, 0, 0); + this->screen = screen; + X11_SetGammaRamp(this, this->gamma); + this->screen = NULL; + } else { + /* Create a read-only colormap for our window */ + SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, + SDL_Visual, AllocNone); + } + + /* Recreate the auxiliary windows, if needed (required for GL) */ + if ( vis_change ) + create_aux_windows(this); + + if(screen->flags & SDL_HWPALETTE) { + /* Since the full-screen window might have got a nonzero background + colour (0 is white on some displays), we should reset the + background to 0 here since that is what the user expects + with a private colormap */ + XSetWindowBackground(SDL_Display, FSwindow, 0); + XClearWindow(SDL_Display, FSwindow); + } + + /* resize the (possibly new) window manager window */ + if( !SDL_windowid ) { + X11_SetSizeHints(this, w, h, flags); + window_w = w; + window_h = h; + XResizeWindow(SDL_Display, WMwindow, w, h); + } + + /* Create (or use) the X11 display window */ + if ( !SDL_windowid ) { + if ( flags & SDL_OPENGL ) { + if ( X11_GL_CreateWindow(this, w, h) < 0 ) { + return(-1); + } + } else { + XSetWindowAttributes swa; + + swa.background_pixel = 0; + swa.border_pixel = 0; + swa.colormap = SDL_XColorMap; + SDL_Window = XCreateWindow(SDL_Display, WMwindow, + 0, 0, w, h, 0, depth, + InputOutput, SDL_Visual, + CWBackPixel | CWBorderPixel + | CWColormap, &swa); + } + /* Only manage our input if we own the window */ + XSelectInput(SDL_Display, SDL_Window, + ( EnterWindowMask | LeaveWindowMask + | ButtonPressMask | ButtonReleaseMask + | PointerMotionMask | ExposureMask )); + } + /* Create the graphics context here, once we have a window */ + if ( flags & SDL_OPENGL ) { + if ( X11_GL_CreateContext(this) < 0 ) { + return(-1); + } else { + screen->flags |= SDL_OPENGL; + } + } else { + XGCValues gcv; + + gcv.graphics_exposures = False; + SDL_GC = XCreateGC(SDL_Display, SDL_Window, + GCGraphicsExposures, &gcv); + if ( ! SDL_GC ) { + SDL_SetError("Couldn't create graphics context"); + return(-1); + } + } + + /* Set our colormaps when not setting a GL mode */ + if ( ! (flags & SDL_OPENGL) ) { + XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); + if( !SDL_windowid ) { + XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap); + XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap); + } + } + +#if 0 /* This is an experiment - are the graphics faster now? - nope. */ + if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") ) +#endif + /* Cache the window in the server, when possible */ + { + Screen *xscreen; + XSetWindowAttributes a; + + xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen); + a.backing_store = DoesBackingStore(xscreen); + if ( a.backing_store != NotUseful ) { + XChangeWindowAttributes(SDL_Display, SDL_Window, + CWBackingStore, &a); + } + } + + /* Map them both and go fullscreen, if requested */ + if ( ! SDL_windowid ) { + XMapWindow(SDL_Display, SDL_Window); + XMapWindow(SDL_Display, WMwindow); + X11_WaitMapped(this, WMwindow); + if ( flags & SDL_FULLSCREEN ) { + screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } else { + screen->flags &= ~SDL_FULLSCREEN; + } + } + + return(0); +} + +static int X11_ResizeWindow(_THIS, + SDL_Surface *screen, int w, int h, Uint32 flags) +{ + if ( ! SDL_windowid ) { + /* Resize the window manager window */ + X11_SetSizeHints(this, w, h, flags); + window_w = w; + window_h = h; + XResizeWindow(SDL_Display, WMwindow, w, h); + + /* Resize the fullscreen and display windows */ + if ( flags & SDL_FULLSCREEN ) { + if ( screen->flags & SDL_FULLSCREEN ) { + X11_ResizeFullScreen(this); + } else { + screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } + } else { + if ( screen->flags & SDL_FULLSCREEN ) { + screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + } + XResizeWindow(SDL_Display, SDL_Window, w, h); + } + return(0); +} + +SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 saved_flags; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + + /* Check the combination of flags we were passed */ + if ( flags & SDL_FULLSCREEN ) { + /* Clear fullscreen flag if not supported */ + if ( SDL_windowid ) { + flags &= ~SDL_FULLSCREEN; + } + } + + /* Flush any delayed updates */ + XSync(GFX_Display, False); + + /* Set up the X11 window */ + saved_flags = current->flags; + if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL)) + && (bpp == current->format->BitsPerPixel) + && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) { + if (X11_ResizeWindow(this, current, width, height, flags) < 0) { + current = NULL; + goto done; + } + X11_PendingConfigureNotifyWidth = width; + X11_PendingConfigureNotifyHeight = height; + } else { + if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) { + current = NULL; + goto done; + } + } + + /* Update the internal keyboard state */ + X11_SetKeyboardState(SDL_Display, NULL); + + /* When the window is first mapped, ignore non-modifier keys */ + if ( !current->w && !current->h ) { + Uint8 *keys = SDL_GetKeyState(NULL); + int i; + for ( i = 0; i < SDLK_LAST; ++i ) { + switch (i) { + case SDLK_NUMLOCK: + case SDLK_CAPSLOCK: + case SDLK_LCTRL: + case SDLK_RCTRL: + case SDLK_LSHIFT: + case SDLK_RSHIFT: + case SDLK_LALT: + case SDLK_RALT: + case SDLK_LMETA: + case SDLK_RMETA: + case SDLK_MODE: + break; + default: + keys[i] = SDL_RELEASED; + break; + } + } + } + + /* Set up the new mode framebuffer */ + if ( ((current->w != width) || (current->h != height)) || + ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { + current->w = width; + current->h = height; + current->pitch = SDL_CalculatePitch(current); + if (X11_ResizeImage(this, current, flags) < 0) { + current = NULL; + goto done; + } + } + + /* Clear these flags and set them only if they are in the new set. */ + current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); + current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME)); + + done: + /* Release the event thread */ + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + + /* We're done! */ + return(current); +} + +static int X11_ToggleFullScreen(_THIS, int on) +{ + Uint32 event_thread; + + /* Don't switch if we don't own the window */ + if ( SDL_windowid ) { + return(0); + } + + /* Don't lock if we are the event thread */ + event_thread = SDL_EventThreadID(); + if ( event_thread && (SDL_ThreadID() == event_thread) ) { + event_thread = 0; + } + if ( event_thread ) { + SDL_Lock_EventThread(); + } + if ( on ) { + this->screen->flags |= SDL_FULLSCREEN; + X11_EnterFullScreen(this); + } else { + this->screen->flags &= ~SDL_FULLSCREEN; + X11_LeaveFullScreen(this); + } + X11_RefreshDisplay(this); + if ( event_thread ) { + SDL_Unlock_EventThread(); + } + SDL_ResetKeyboard(); + return(1); +} + +/* Update the current mouse state and position */ +static void X11_UpdateMouse(_THIS) +{ + Window u1; int u2; + Window current_win; + int x, y; + unsigned int mask; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + if ( XQueryPointer(SDL_Display, SDL_Window, &u1, ¤t_win, + &u2, &u2, &x, &y, &mask) ) { + if ( (x >= 0) && (x < SDL_VideoSurface->w) && + (y >= 0) && (y < SDL_VideoSurface->h) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } + } + SDL_Unlock_EventThread(); +} + +/* simple colour distance metric. Supposed to be better than a plain + Euclidian distance anyway. */ +#define COLOUR_FACTOR 3 +#define LIGHT_FACTOR 1 +#define COLOUR_DIST(r1, g1, b1, r2, g2, b2) \ + (COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)) \ + + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2))) + +static void allocate_nearest(_THIS, SDL_Color *colors, + SDL_Color *want, int nwant) +{ + /* + * There is no way to know which ones to choose from, so we retrieve + * the entire colormap and try the nearest possible, until we find one + * that is shared. + */ + XColor all[256]; + int i; + for(i = 0; i < 256; i++) + all[i].pixel = i; + /* + * XQueryColors sets the flags in the XColor struct, so we use + * that to keep track of which colours are available + */ + XQueryColors(GFX_Display, SDL_XColorMap, all, 256); + + for(i = 0; i < nwant; i++) { + XColor *c; + int j; + int best = 0; + int mindist = 0x7fffffff; + int ri = want[i].r; + int gi = want[i].g; + int bi = want[i].b; + for(j = 0; j < 256; j++) { + int rj, gj, bj, d2; + if(!all[j].flags) + continue; /* unavailable colour cell */ + rj = all[j].red >> 8; + gj = all[j].green >> 8; + bj = all[j].blue >> 8; + d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj); + if(d2 < mindist) { + mindist = d2; + best = j; + } + } + if(SDL_XPixels[best]) + continue; /* already allocated, waste no more time */ + c = all + best; + if(XAllocColor(GFX_Display, SDL_XColorMap, c)) { + /* got it */ + colors[c->pixel].r = c->red >> 8; + colors[c->pixel].g = c->green >> 8; + colors[c->pixel].b = c->blue >> 8; + ++SDL_XPixels[c->pixel]; + } else { + /* + * The colour couldn't be allocated, probably being + * owned as a r/w cell by another client. Flag it as + * unavailable and try again. The termination of the + * loop is guaranteed since at least black and white + * are always there. + */ + c->flags = 0; + i--; + } + } +} + +int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int nrej = 0; + + /* Check to make sure we have a colormap allocated */ + if ( SDL_XPixels == NULL ) { + return(0); + } + if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { + /* private writable colormap: just set the colours we need */ + XColor *xcmap; + int i; + xcmap = SDL_stack_alloc(XColor, ncolors); + if(xcmap == NULL) + return 0; + for ( i=0; i<ncolors; ++i ) { + xcmap[i].pixel = i + firstcolor; + xcmap[i].red = (colors[i].r<<8)|colors[i].r; + xcmap[i].green = (colors[i].g<<8)|colors[i].g; + xcmap[i].blue = (colors[i].b<<8)|colors[i].b; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); + XSync(GFX_Display, False); + SDL_stack_free(xcmap); + } else { + /* + * Shared colormap: We only allocate read-only cells, which + * increases the likelyhood of colour sharing with other + * clients. The pixel values will almost certainly be + * different from the requested ones, so the user has to + * walk the colormap and see which index got what colour. + * + * We can work directly with the logical palette since it + * has already been set when we get here. + */ + SDL_Color *want, *reject; + unsigned long *freelist; + int i; + int nfree = 0; + int nc = this->screen->format->palette->ncolors; + colors = this->screen->format->palette->colors; + freelist = SDL_stack_alloc(unsigned long, nc); + /* make sure multiple allocations of the same cell are freed */ + for(i = 0; i < ncolors; i++) { + int pixel = firstcolor + i; + while(SDL_XPixels[pixel]) { + freelist[nfree++] = pixel; + --SDL_XPixels[pixel]; + } + } + XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0); + SDL_stack_free(freelist); + + want = SDL_stack_alloc(SDL_Color, ncolors); + reject = SDL_stack_alloc(SDL_Color, ncolors); + SDL_memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color)); + /* make sure the user isn't fooled by her own wishes + (black is safe, always available in the default colormap) */ + SDL_memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color)); + + /* now try to allocate the colours */ + for(i = 0; i < ncolors; i++) { + XColor col; + col.red = want[i].r << 8; + col.green = want[i].g << 8; + col.blue = want[i].b << 8; + col.flags = DoRed | DoGreen | DoBlue; + if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) { + /* We got the colour, or at least the nearest + the hardware could get. */ + colors[col.pixel].r = col.red >> 8; + colors[col.pixel].g = col.green >> 8; + colors[col.pixel].b = col.blue >> 8; + ++SDL_XPixels[col.pixel]; + } else { + /* + * no more free cells, add it to the list + * of rejected colours + */ + reject[nrej++] = want[i]; + } + } + if(nrej) + allocate_nearest(this, colors, reject, nrej); + SDL_stack_free(reject); + SDL_stack_free(want); + } + return nrej == 0; +} + +int X11_SetGammaRamp(_THIS, Uint16 *ramp) +{ + int i, ncolors; + XColor xcmap[256]; + + /* See if actually setting the gamma is supported */ + if ( SDL_Visual->class != DirectColor ) { + SDL_SetError("Gamma correction not supported on this visual"); + return(-1); + } + + /* Calculate the appropriate palette for the given gamma ramp */ + ncolors = SDL_Visual->map_entries; + for ( i=0; i<ncolors; ++i ) { + Uint8 c = (256 * i / ncolors); + xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); + xcmap[i].red = ramp[0*256+c]; + xcmap[i].green = ramp[1*256+c]; + xcmap[i].blue = ramp[2*256+c]; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); + XSync(GFX_Display, False); + return(0); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +void X11_VideoQuit(_THIS) +{ + /* Shutdown everything that's still up */ + /* The event thread should be done, so we can touch SDL_Display */ + if ( SDL_Display != NULL ) { + /* Flush any delayed updates */ + XSync(GFX_Display, False); + + /* Close the connection with the IM server */ + #ifdef X_HAVE_UTF8_STRING + if (SDL_IC != NULL) { + XUnsetICFocus(SDL_IC); + XDestroyIC(SDL_IC); + SDL_IC = NULL; + } + if (SDL_IM != NULL) { + XCloseIM(SDL_IM); + SDL_IM = NULL; + } + #endif + + /* Start shutting down the windows */ + X11_DestroyImage(this, this->screen); + X11_DestroyWindow(this, this->screen); + X11_FreeVideoModes(this); + if ( SDL_XColorMap != SDL_DisplayColormap ) { + XFreeColormap(SDL_Display, SDL_XColorMap); + } + if ( SDL_iconcolors ) { + unsigned long pixel; + Colormap dcmap = DefaultColormap(SDL_Display, + SDL_Screen); + for(pixel = 0; pixel < 256; ++pixel) { + while(SDL_iconcolors[pixel] > 0) { + XFreeColors(GFX_Display, + dcmap, &pixel, 1, 0); + --SDL_iconcolors[pixel]; + } + } + SDL_free(SDL_iconcolors); + SDL_iconcolors = NULL; + } + + /* Restore gamma settings if they've changed */ + if ( SDL_GetAppState() & SDL_APPACTIVE ) { + X11_SwapVidModeGamma(this); + } + + /* Free that blank cursor */ + if ( SDL_BlankCursor != NULL ) { + this->FreeWMCursor(this, SDL_BlankCursor); + SDL_BlankCursor = NULL; + } + + /* Close the X11 graphics connection */ + if ( GFX_Display != NULL ) { + XCloseDisplay(GFX_Display); + GFX_Display = NULL; + } + + /* Close the X11 display connection */ + XCloseDisplay(SDL_Display); + SDL_Display = NULL; + + /* Reset the X11 error handlers */ + if ( XIO_handler ) { + XSetIOErrorHandler(XIO_handler); + } + if ( X_handler ) { + XSetErrorHandler(X_handler); + } + + /* Unload GL library after X11 shuts down */ + X11_GL_UnloadLibrary(this); + } + if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { + /* Direct screen access, no memory buffer */ + this->screen->pixels = NULL; + } + +#if SDL_VIDEO_DRIVER_X11_XME + XiGMiscDestroy(); +#endif +} + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11video.h b/3rdparty/SDL/src/video/x11/SDL_x11video.h new file mode 100644 index 0000000..f347560 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11video.h @@ -0,0 +1,214 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11video_h +#define _SDL_x11video_h + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#if SDL_VIDEO_DRIVER_X11_DGAMOUSE +#include "../Xext/extensions/xf86dga.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XINERAMA +#include "../Xext/extensions/Xinerama.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR +#include <X11/extensions/Xrandr.h> +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE +#include "../Xext/extensions/xf86vmode.h" +#endif +#if SDL_VIDEO_DRIVER_X11_XME +#include "../Xext/extensions/xme.h" +#endif + +#include "SDL_x11dyn.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +/* Private display data */ +struct SDL_PrivateVideoData { + int local_X11; /* Flag: true if local display */ + Display *X11_Display; /* Used for events and window management */ + Display *GFX_Display; /* Used for graphics and colormap stuff */ + Visual *SDL_Visual; /* The visual used by our window */ + Window WMwindow; /* Input window, managed by window manager */ + Window FSwindow; /* Fullscreen window, completely unmanaged */ + Window SDL_Window; /* Shared by both displays (no X security?) */ + Atom WM_DELETE_WINDOW; /* "close-window" protocol atom */ + WMcursor *BlankCursor; /* The invisible cursor */ + XIM X11_IM; /* Used to communicate with the input method (IM) server */ + XIC X11_IC; /* Used for retaining the state, properties, and semantics of communication with the input method (IM) server */ + + char *SDL_windowid; /* Flag: true if we have been passed a window */ + + /* Direct Graphics Access extension information */ + int using_dga; + +#ifndef NO_SHARED_MEMORY + /* MIT shared memory extension information */ + int use_mitshm; + XShmSegmentInfo shminfo; +#endif + + /* The variables used for displaying graphics */ + XImage *Ximage; /* The X image for our window */ + GC gc; /* The graphic context for drawing */ + + /* The current width and height of the fullscreen mode */ + int window_w; + int window_h; + + /* Support for internal mouse warping */ + struct { + int x; + int y; + } mouse_last; + struct { + int numerator; + int denominator; + int threshold; + } mouse_accel; + int mouse_relative; + + /* The current list of available video modes */ + SDL_Rect **modelist; + + /* available visuals of interest to us, sorted deepest first */ + struct { + Visual *visual; + int depth; /* number of significant bits/pixel */ + int bpp; /* pixel quantum in bits */ + } visuals[2*5]; /* at most 2 entries for 8, 15, 16, 24, 32 */ + int nvisuals; + + Visual *vis; /* current visual in use */ + int depth; /* current visual depth (not bpp) */ + + /* Variables used by the X11 video mode code */ +#if SDL_VIDEO_DRIVER_X11_XINERAMA + SDL_NAME(XineramaScreenInfo) xinerama_info; +#endif +#if SDL_VIDEO_DRIVER_X11_XRANDR + XRRScreenConfiguration* screen_config; + int saved_size_id; + Rotation saved_rotation; +#endif +#if SDL_VIDEO_DRIVER_X11_VIDMODE + SDL_NAME(XF86VidModeModeInfo) saved_mode; + struct { + int x, y; + } saved_view; +#endif +#if SDL_VIDEO_DRIVER_X11_XME /* XiG XME fullscreen */ + XiGMiscResolutionInfo saved_res; +#endif + + int use_xinerama; + int use_xrandr; + int use_vidmode; + int use_xme; + int currently_fullscreen; + + /* Automatic mode switching support (entering/leaving fullscreen) */ + Uint32 switch_waiting; + Uint32 switch_time; + + /* Prevent too many XSync() calls */ + int blit_queued; + + /* Colormap handling */ + Colormap DisplayColormap; /* The default display colormap */ + Colormap XColorMap; /* The current window colormap */ + int *XPixels; /* pixels value allocation counts */ + float gamma_saved[3]; /* Saved gamma values for VidMode gamma */ + int gamma_changed; /* flag: has VidMode gamma been modified? */ + + short *iconcolors; /* List of colors used by the icon */ + + /* Screensaver settings */ + int allow_screensaver; +}; + +/* Old variable names */ +#define local_X11 (this->hidden->local_X11) +#define SDL_Display (this->hidden->X11_Display) +#define GFX_Display (this->hidden->GFX_Display) +#define SDL_Screen DefaultScreen(this->hidden->X11_Display) +#define SDL_Visual (this->hidden->vis) +#define SDL_Root RootWindow(SDL_Display, SDL_Screen) +#define WMwindow (this->hidden->WMwindow) +#define FSwindow (this->hidden->FSwindow) +#define SDL_Window (this->hidden->SDL_Window) +#define WM_DELETE_WINDOW (this->hidden->WM_DELETE_WINDOW) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define SDL_IM (this->hidden->X11_IM) +#define SDL_IC (this->hidden->X11_IC) +#define SDL_windowid (this->hidden->SDL_windowid) +#define using_dga (this->hidden->using_dga) +#define use_mitshm (this->hidden->use_mitshm) +#define shminfo (this->hidden->shminfo) +#define SDL_Ximage (this->hidden->Ximage) +#define SDL_GC (this->hidden->gc) +#define window_w (this->hidden->window_w) +#define window_h (this->hidden->window_h) +#define mouse_last (this->hidden->mouse_last) +#define mouse_accel (this->hidden->mouse_accel) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_modelist (this->hidden->modelist) +#define xinerama_info (this->hidden->xinerama_info) +#define saved_mode (this->hidden->saved_mode) +#define saved_view (this->hidden->saved_view) +#define saved_res (this->hidden->saved_res) +#define screen_config (this->hidden->screen_config) +#define saved_size_id (this->hidden->saved_size_id) +#define saved_rotation (this->hidden->saved_rotation) +#define use_xinerama (this->hidden->use_xinerama) +#define use_vidmode (this->hidden->use_vidmode) +#define use_xrandr (this->hidden->use_xrandr) +#define use_xme (this->hidden->use_xme) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define switch_waiting (this->hidden->switch_waiting) +#define switch_time (this->hidden->switch_time) +#define blit_queued (this->hidden->blit_queued) +#define SDL_DisplayColormap (this->hidden->DisplayColormap) +#define SDL_PrivateColormap (this->hidden->PrivateColormap) +#define SDL_XColorMap (this->hidden->XColorMap) +#define SDL_XPixels (this->hidden->XPixels) +#define gamma_saved (this->hidden->gamma_saved) +#define gamma_changed (this->hidden->gamma_changed) +#define SDL_iconcolors (this->hidden->iconcolors) +#define allow_screensaver (this->hidden->allow_screensaver) + +/* Some versions of XFree86 have bugs - detect if this is one of them */ +#define BUGGY_XFREE86(condition, buggy_version) \ +((SDL_strcmp(ServerVendor(SDL_Display), "The XFree86 Project, Inc") == 0) && \ + (VendorRelease(SDL_Display) condition buggy_version)) + +#endif /* _SDL_x11video_h */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11wm.c b/3rdparty/SDL/src/video/x11/SDL_x11wm.c new file mode 100644 index 0000000..14c816b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11wm.c @@ -0,0 +1,434 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#include "SDL_version.h" +#include "SDL_timer.h" +#include "SDL_video.h" +#include "SDL_syswm.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_x11modes_c.h" +#include "SDL_x11wm_c.h" + +static Uint8 reverse_byte(Uint8 x) +{ + x = (x & 0xaa) >> 1 | (x & 0x55) << 1; + x = (x & 0xcc) >> 2 | (x & 0x33) << 2; + x = (x & 0xf0) >> 4 | (x & 0x0f) << 4; + return x; +} + +void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask) +{ + SDL_Surface *sicon; + XWMHints *wmhints; + XImage *icon_image; + Pixmap icon_pixmap; + Pixmap mask_pixmap; + Window icon_window = None; + GC gc; + XGCValues GCvalues; + int i, dbpp; + SDL_Rect bounds; + Uint8 *LSBmask; + Visual *dvis; + char *p; + int masksize; + + SDL_Lock_EventThread(); + + /* The icon must use the default visual, depth and colormap of the + screen, so it might need a conversion */ + dvis = DefaultVisual(SDL_Display, SDL_Screen); + dbpp = DefaultDepth(SDL_Display, SDL_Screen); + for(i = 0; i < this->hidden->nvisuals; i++) { + if(this->hidden->visuals[i].visual == dvis) { + dbpp = this->hidden->visuals[i].bpp; + break; + } + } + + /* The Visual struct is supposed to be opaque but we cheat a little */ + sicon = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h, + dbpp, + dvis->red_mask, dvis->green_mask, + dvis->blue_mask, 0); + if ( sicon == NULL ) + goto done; + + if(dbpp == 8) { + /* Default visual is 8bit; we need to allocate colours from + the default colormap */ + SDL_Color want[256], got[256]; + int nwant; + Colormap dcmap; + int missing; + dcmap = DefaultColormap(SDL_Display, SDL_Screen); + if(icon->format->palette) { + /* The icon has a palette as well - we just have to + find those colours */ + nwant = icon->format->palette->ncolors; + SDL_memcpy(want, icon->format->palette->colors, + nwant * sizeof want[0]); + } else { + /* try the standard 6x6x6 cube for lack of better + ideas */ + int r, g, b, i; + for(r = i = 0; r < 256; r += 0x33) + for(g = 0; g < 256; g += 0x33) + for(b = 0; b < 256; b += 0x33, i++) { + want[i].r = r; + want[i].g = g; + want[i].b = b; + } + nwant = 216; + } + if(SDL_iconcolors) { + /* free already allocated colours first */ + unsigned long freelist[512]; + int nfree = 0; + for(i = 0; i < 256; i++) { + while(SDL_iconcolors[i]) { + freelist[nfree++] = i; + SDL_iconcolors[i]--; + } + } + XFreeColors(GFX_Display, dcmap, freelist, nfree, 0); + } + if(!SDL_iconcolors) + SDL_iconcolors = SDL_malloc(256 * sizeof *SDL_iconcolors); + SDL_memset(SDL_iconcolors, 0, 256 * sizeof *SDL_iconcolors); + + /* try to allocate the colours */ + SDL_memset(got, 0, sizeof got); + missing = 0; + for(i = 0; i < nwant; i++) { + XColor c; + c.red = want[i].r << 8; + c.green = want[i].g << 8; + c.blue = want[i].b << 8; + c.flags = DoRed | DoGreen | DoBlue; + if(XAllocColor(GFX_Display, dcmap, &c)) { + /* got the colour */ + SDL_iconcolors[c.pixel]++; + got[c.pixel] = want[i]; + } else { + missing = 1; + } + } + if(missing) { + /* Some colours were apparently missing, so we just + allocate all the rest as well */ + XColor cols[256]; + for(i = 0; i < 256; i++) + cols[i].pixel = i; + XQueryColors(GFX_Display, dcmap, cols, 256); + for(i = 0; i < 256; i++) { + got[i].r = cols[i].red >> 8; + got[i].g = cols[i].green >> 8; + got[i].b = cols[i].blue >> 8; + if(!SDL_iconcolors[i]) { + if(XAllocColor(GFX_Display, dcmap, + cols + i)) { + SDL_iconcolors[i] = 1; + } else { + /* index not available */ + got[i].r = 0; + got[i].g = 0; + got[i].b = 0; + } + } + } + } + + SDL_SetColors(sicon, got, 0, 256); + } + + bounds.x = 0; + bounds.y = 0; + bounds.w = icon->w; + bounds.h = icon->h; + if ( SDL_LowerBlit(icon, &bounds, sicon, &bounds) < 0 ) + goto done; + + /* We need the mask as given, except in LSBfirst format instead of + MSBfirst. Reverse the bits in each byte. */ + masksize = ((sicon->w + 7) >> 3) * sicon->h; + LSBmask = SDL_malloc(masksize); + if ( LSBmask == NULL ) { + goto done; + } + SDL_memset(LSBmask, 0, masksize); + for(i = 0; i < masksize; i++) + LSBmask[i] = reverse_byte(mask[i]); + mask_pixmap = XCreatePixmapFromBitmapData(SDL_Display, WMwindow, + (char *)LSBmask, + sicon->w, sicon->h, + 1L, 0L, 1); + + /* Transfer the image to an X11 pixmap */ + icon_image = XCreateImage(SDL_Display, + DefaultVisual(SDL_Display, SDL_Screen), + DefaultDepth(SDL_Display, SDL_Screen), + ZPixmap, 0, sicon->pixels, + sicon->w, sicon->h, + 32, 0); + icon_image->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) + ? MSBFirst : LSBFirst; + icon_pixmap = XCreatePixmap(SDL_Display, SDL_Root, sicon->w, sicon->h, + DefaultDepth(SDL_Display, SDL_Screen)); + gc = XCreateGC(SDL_Display, icon_pixmap, 0, &GCvalues); + XPutImage(SDL_Display, icon_pixmap, gc, icon_image, + 0, 0, 0, 0, sicon->w, sicon->h); + XFreeGC(SDL_Display, gc); + XDestroyImage(icon_image); + SDL_free(LSBmask); + sicon->pixels = NULL; + + /* Some buggy window managers (some versions of Enlightenment, it + seems) need an icon window *and* icon pixmap to work properly, while + it screws up others. The default is only to use a pixmap. */ + p = SDL_getenv("SDL_VIDEO_X11_ICONWIN"); + if(p && *p) { + icon_window = XCreateSimpleWindow(SDL_Display, SDL_Root, + 0, 0, sicon->w, sicon->h, 0, + CopyFromParent, + CopyFromParent); + XSetWindowBackgroundPixmap(SDL_Display, icon_window, + icon_pixmap); + XClearWindow(SDL_Display, icon_window); + } + + /* Set the window icon to the icon pixmap (and icon window) */ + wmhints = XAllocWMHints(); + wmhints->flags = (IconPixmapHint | IconMaskHint | InputHint); + wmhints->icon_pixmap = icon_pixmap; + wmhints->icon_mask = mask_pixmap; + wmhints->input = True; + if(icon_window != None) { + wmhints->flags |= IconWindowHint; + wmhints->icon_window = icon_window; + } + XSetWMHints(SDL_Display, WMwindow, wmhints); + XFree(wmhints); + XSync(SDL_Display, False); + + done: + SDL_Unlock_EventThread(); + SDL_FreeSurface(sicon); +} + +void X11_SetCaptionNoLock(_THIS, const char *title, const char *icon) +{ + XTextProperty titleprop, iconprop; + Status status; + +#ifdef X_HAVE_UTF8_STRING + Atom _NET_WM_NAME = 0; + Atom _NET_WM_ICON_NAME = 0; + + /* Look up some useful Atoms */ + if (SDL_X11_HAVE_UTF8) { + _NET_WM_NAME = XInternAtom(SDL_Display, "_NET_WM_NAME", False); + _NET_WM_ICON_NAME = XInternAtom(SDL_Display, "_NET_WM_ICON_NAME", False); + } +#endif + + if ( title != NULL ) { + char *title_locale = SDL_iconv_utf8_locale(title); + if ( !title_locale ) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&title_locale, 1, &titleprop); + SDL_free(title_locale); + if ( status ) { + XSetTextProperty(SDL_Display, WMwindow, &titleprop, XA_WM_NAME); + XFree(titleprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = Xutf8TextListToTextProperty(SDL_Display, + (char **)&title, 1, XUTF8StringStyle, &titleprop); + if ( status == Success ) { + XSetTextProperty(SDL_Display, WMwindow, &titleprop, _NET_WM_NAME); + XFree(titleprop.value); + } + } +#endif + } + if ( icon != NULL ) { + char *icon_locale = SDL_iconv_utf8_locale(icon); + if ( !icon_locale ) { + SDL_OutOfMemory(); + return; + } + status = XStringListToTextProperty(&icon_locale, 1, &iconprop); + SDL_free(icon_locale); + if ( status ) { + XSetTextProperty(SDL_Display, WMwindow, &iconprop, XA_WM_ICON_NAME); + XFree(iconprop.value); + } +#ifdef X_HAVE_UTF8_STRING + if (SDL_X11_HAVE_UTF8) { + status = Xutf8TextListToTextProperty(SDL_Display, + (char **)&icon, 1, XUTF8StringStyle, &iconprop); + if ( status == Success ) { + XSetTextProperty(SDL_Display, WMwindow, &iconprop, _NET_WM_ICON_NAME); + XFree(iconprop.value); + } + } +#endif + } + XSync(SDL_Display, False); +} + +void X11_SetCaption(_THIS, const char *title, const char *icon) +{ + SDL_Lock_EventThread(); + X11_SetCaptionNoLock(this, title, icon); + SDL_Unlock_EventThread(); +} + +/* Iconify the window */ +int X11_IconifyWindow(_THIS) +{ + int result; + + SDL_Lock_EventThread(); + result = XIconifyWindow(SDL_Display, WMwindow, SDL_Screen); + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); + return(result); +} + +SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode) +{ + int result; + + if ( this->screen == NULL || SDL_Display == NULL ) { + return(SDL_GRAB_OFF); + } + if ( ! SDL_Window ) { + return(mode); /* Will be set later on mode switch */ + } + if ( mode == SDL_GRAB_OFF ) { + XUngrabPointer(SDL_Display, CurrentTime); + XUngrabKeyboard(SDL_Display, CurrentTime); + } else { + if ( this->screen->flags & SDL_FULLSCREEN ) { + /* Unbind the mouse from the fullscreen window */ + XUngrabPointer(SDL_Display, CurrentTime); + } + /* Try to grab the mouse */ +#if 0 /* We'll wait here until we actually grab, otherwise behavior undefined */ + for ( numtries = 0; numtries < 10; ++numtries ) { +#else + for ( ; ; ) { +#endif + result = XGrabPointer(SDL_Display, SDL_Window, True, 0, + GrabModeAsync, GrabModeAsync, + SDL_Window, None, CurrentTime); + if ( result == GrabSuccess ) { + break; + } + SDL_Delay(100); + } + if ( result != GrabSuccess ) { + /* Uh, oh, what do we do here? */ ; + } + /* Now grab the keyboard */ + XGrabKeyboard(SDL_Display, WMwindow, True, + GrabModeAsync, GrabModeAsync, CurrentTime); + + /* Raise the window if we grab the mouse */ + if ( !(this->screen->flags & SDL_FULLSCREEN) ) + XRaiseWindow(SDL_Display, WMwindow); + + /* Make sure we register input focus */ + SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); + /* Since we grabbed the pointer, we have mouse focus, too. */ + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + } + XSync(SDL_Display, False); + + return(mode); +} + +SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode) +{ + SDL_Lock_EventThread(); + mode = X11_GrabInputNoLock(this, mode); + SDL_Unlock_EventThread(); + + return(mode); +} + +/* If 'info' is the right version, this function fills it and returns 1. + Otherwise, in case of a version mismatch, it returns -1. +*/ +static void lock_display(void) +{ + SDL_Lock_EventThread(); +} +static void unlock_display(void) +{ + /* Make sure any X11 transactions are completed */ + SDL_VideoDevice *this = current_video; + XSync(SDL_Display, False); + SDL_Unlock_EventThread(); +} + +#include <stdio.h> +int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info) +{ + if ( info->version.major <= SDL_MAJOR_VERSION ) { + info->subsystem = SDL_SYSWM_X11; + info->info.x11.display = SDL_Display; + info->info.x11.window = SDL_Window; + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= 1002 ) { + info->info.x11.fswindow = FSwindow; + info->info.x11.wmwindow = WMwindow; + } + + + if ( SDL_VERSIONNUM(info->version.major, + info->version.minor, + info->version.patch) >= 1212 ) { + info->info.x11.gfxdisplay = GFX_Display; + } + + info->info.x11.lock_func = lock_display; + info->info.x11.unlock_func = unlock_display; + return(1); + } else { + SDL_SetError("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return(-1); + } +} diff --git a/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h b/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h new file mode 100644 index 0000000..f85477b --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11wm_c.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_x11video.h" + +/* Functions to be exported */ +extern void X11_SetCaptionNoLock(_THIS, const char *title, const char *icon); +extern void X11_SetCaption(_THIS, const char *title, const char *icon); +extern void X11_SetIcon(_THIS, SDL_Surface *icon, Uint8 *mask); +extern int X11_IconifyWindow(_THIS); +extern SDL_GrabMode X11_GrabInputNoLock(_THIS, SDL_GrabMode mode); +extern SDL_GrabMode X11_GrabInput(_THIS, SDL_GrabMode mode); +extern int X11_GetWMInfo(_THIS, SDL_SysWMinfo *info); + diff --git a/3rdparty/SDL/src/video/x11/SDL_x11yuv.c b/3rdparty/SDL/src/video/x11/SDL_x11yuv.c new file mode 100644 index 0000000..62698df --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11yuv.c @@ -0,0 +1,538 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the XFree86 Xv extension implementation of YUV video overlays */ + +#if SDL_VIDEO_DRIVER_X11_XV + +#include <X11/Xlib.h> +#ifndef NO_SHARED_MEMORY +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> +#endif +#include "../Xext/extensions/Xvlib.h" + +#include "SDL_x11yuv_c.h" +#include "../SDL_yuvfuncs.h" + +#define XFREE86_REFRESH_HACK +#ifdef XFREE86_REFRESH_HACK +#include "SDL_x11image_c.h" +#endif + +/* Workaround when pitch != width */ +#define PITCH_WORKAROUND + +/* Workaround intel i810 video overlay waiting with failing until the + first Xv[Shm]PutImage call <sigh> */ +#define INTEL_XV_BADALLOC_WORKAROUND + +/* Fix for the NVidia GeForce 2 - use the last available adaptor */ +/*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ + +/* The functions used to manipulate software video overlays */ +static struct private_yuvhwfuncs x11_yuvfuncs = { + X11_LockYUVOverlay, + X11_UnlockYUVOverlay, + X11_DisplayYUVOverlay, + X11_FreeYUVOverlay +}; + +struct private_yuvhwdata { + int port; +#ifndef NO_SHARED_MEMORY + int yuv_use_mitshm; + XShmSegmentInfo yuvshm; +#endif + SDL_NAME(XvImage) *image; +}; + + +static int (*X_handler)(Display *, XErrorEvent *) = NULL; + +#ifndef NO_SHARED_MEMORY +/* Shared memory error handler routine */ +static int shm_error; +static int shm_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAccess ) { + shm_error = True; + return(0); + } else + return(X_handler(d,e)); +} +#endif /* !NO_SHARED_MEMORY */ + +static int xv_error; +static int xv_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadMatch ) { + xv_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +#ifdef INTEL_XV_BADALLOC_WORKAROUND +static int intel_errhandler(Display *d, XErrorEvent *e) +{ + if ( e->error_code == BadAlloc ) { + xv_error = True; + return(0); + } else + return(X_handler(d,e)); +} + +static void X11_ClearYUVOverlay(SDL_Overlay *overlay) +{ + int x,y; + + switch (overlay->format) + { + case SDL_YV12_OVERLAY: + case SDL_IYUV_OVERLAY: + for (y = 0; y < overlay->h; y++) + memset(overlay->pixels[0] + y * overlay->pitches[0], + 0, overlay->w); + + for (y = 0; y < (overlay->h / 2); y++) + { + memset(overlay->pixels[1] + y * overlay->pitches[1], + -128, overlay->w / 2); + memset(overlay->pixels[2] + y * overlay->pitches[2], + -128, overlay->w / 2); + } + break; + case SDL_YUY2_OVERLAY: + case SDL_YVYU_OVERLAY: + for (y = 0; y < overlay->h; y++) + { + for (x = 0; x < overlay->w; x += 2) + { + Uint8 *pixel_pair = overlay->pixels[0] + + y * overlay->pitches[0] + x * 2; + pixel_pair[0] = 0; + pixel_pair[1] = -128; + pixel_pair[2] = 0; + pixel_pair[3] = -128; + } + } + break; + case SDL_UYVY_OVERLAY: + for (y = 0; y < overlay->h; y++) + { + for (x = 0; x < overlay->w; x += 2) + { + Uint8 *pixel_pair = overlay->pixels[0] + + y * overlay->pitches[0] + x * 2; + pixel_pair[0] = -128; + pixel_pair[1] = 0; + pixel_pair[2] = -128; + pixel_pair[3] = 0; + } + } + break; + } +} +#endif + +SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) +{ + SDL_Overlay *overlay; + struct private_yuvhwdata *hwdata; + int xv_port; + unsigned int i, j, k; + unsigned int adaptors; + SDL_NAME(XvAdaptorInfo) *ainfo; + int bpp; +#ifndef NO_SHARED_MEMORY + XShmSegmentInfo *yuvshm; +#endif +#ifdef INTEL_XV_BADALLOC_WORKAROUND + int intel_adapter = False; +#endif + + /* Look for the XVideo extension with a valid port for this format */ + xv_port = -1; + if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && + (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, + RootWindow(GFX_Display, SDL_Screen), + &adaptors, &ainfo)) ) { +#ifdef USE_LAST_ADAPTOR + for ( i=0; i < adaptors; ++i ) +#else + for ( i=0; (i < adaptors) && (xv_port == -1); ++i ) +#endif /* USE_LAST_ADAPTOR */ + { + /* Check to see if the visual can be used */ + if ( BUGGY_XFREE86(<=, 4001) ) { + int visual_ok = 0; + for ( j=0; j<ainfo[i].num_formats; ++j ) { + if ( ainfo[i].formats[j].visual_id == + SDL_Visual->visualid ) { + visual_ok = 1; + break; + } + } + if ( ! visual_ok ) { + continue; + } + } +#ifdef INTEL_XV_BADALLOC_WORKAROUND + if ( !strcmp(ainfo[i].name, "Intel(R) Video Overla")) + intel_adapter = True; + else + intel_adapter = False; +#endif + if ( (ainfo[i].type & XvInputMask) && + (ainfo[i].type & XvImageMask) ) { + int num_formats; + SDL_NAME(XvImageFormatValues) *formats; + formats = SDL_NAME(XvListImageFormats)(GFX_Display, + ainfo[i].base_id, &num_formats); +#ifdef USE_LAST_ADAPTOR + for ( j=0; j < num_formats; ++j ) +#else + for ( j=0; (j < num_formats) && (xv_port == -1); ++j ) +#endif /* USE_LAST_ADAPTOR */ + { + if ( (Uint32)formats[j].id == format ) { + for ( k=0; k < ainfo[i].num_ports; ++k ) { + if ( Success == SDL_NAME(XvGrabPort)(GFX_Display, ainfo[i].base_id+k, CurrentTime) ) { + xv_port = ainfo[i].base_id+k; + break; + } + } + } + } + if ( formats ) { + XFree(formats); + } + } + } + SDL_NAME(XvFreeAdaptorInfo)(ainfo); + } + + /* Precalculate the bpp for the pitch workaround below */ + switch (format) { + /* Add any other cases we need to support... */ + case SDL_YUY2_OVERLAY: + case SDL_UYVY_OVERLAY: + case SDL_YVYU_OVERLAY: + bpp = 2; + break; + default: + bpp = 1; + break; + } + +#if 0 + /* + * !!! FIXME: + * "Here are some diffs for X11 and yuv. Note that the last part 2nd + * diff should probably be a new call to XvQueryAdaptorFree with ainfo + * and the number of adaptors, instead of the loop through like I did." + * + * ACHTUNG: This is broken! It looks like XvFreeAdaptorInfo does this + * for you, so we end up with a double-free. I need to look at this + * more closely... --ryan. + */ + for ( i=0; i < adaptors; ++i ) { + if (ainfo[i].name != NULL) Xfree(ainfo[i].name); + if (ainfo[i].formats != NULL) Xfree(ainfo[i].formats); + } + Xfree(ainfo); +#endif + + if ( xv_port == -1 ) { + SDL_SetError("No available video ports for requested format"); + return(NULL); + } + + /* Enable auto-painting of the overlay colorkey */ + { + static const char *attr[] = { "XV_AUTOPAINT_COLORKEY", "XV_AUTOPAINT_COLOURKEY" }; + unsigned int i; + + SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, True); + X_handler = XSetErrorHandler(xv_errhandler); + for ( i=0; i < sizeof(attr)/(sizeof attr[0]); ++i ) { + Atom a; + + xv_error = False; + a = XInternAtom(GFX_Display, attr[i], True); + if ( a != None ) { + SDL_NAME(XvSetPortAttribute)(GFX_Display, xv_port, a, 1); + XSync(GFX_Display, True); + if ( ! xv_error ) { + break; + } + } + } + XSetErrorHandler(X_handler); + SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, False); + } + + /* Create the overlay structure */ + overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); + if ( overlay == NULL ) { + SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); + SDL_OutOfMemory(); + return(NULL); + } + SDL_memset(overlay, 0, (sizeof *overlay)); + + /* Fill in the basic members */ + overlay->format = format; + overlay->w = width; + overlay->h = height; + + /* Set up the YUV surface function structure */ + overlay->hwfuncs = &x11_yuvfuncs; + overlay->hw_overlay = 1; + + /* Create the pixel data and lookup tables */ + hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); + overlay->hwdata = hwdata; + if ( hwdata == NULL ) { + SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->port = xv_port; +#ifndef NO_SHARED_MEMORY + yuvshm = &hwdata->yuvshm; + SDL_memset(yuvshm, 0, sizeof(*yuvshm)); + hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, + 0, width, height, yuvshm); +#ifdef PITCH_WORKAROUND + if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { + /* Ajust overlay width according to pitch */ + width = hwdata->image->pitches[0] / bpp; + XFree(hwdata->image); + hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, + 0, width, height, yuvshm); + } +#endif /* PITCH_WORKAROUND */ + hwdata->yuv_use_mitshm = (hwdata->image != NULL); + if ( hwdata->yuv_use_mitshm ) { + yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, + IPC_CREAT | 0777); + if ( yuvshm->shmid >= 0 ) { + yuvshm->shmaddr = (char *)shmat(yuvshm->shmid, 0, 0); + yuvshm->readOnly = False; + if ( yuvshm->shmaddr != (char *)-1 ) { + shm_error = False; + X_handler = XSetErrorHandler(shm_errhandler); + XShmAttach(GFX_Display, yuvshm); + XSync(GFX_Display, True); + XSetErrorHandler(X_handler); + if ( shm_error ) + shmdt(yuvshm->shmaddr); + } else { + shm_error = True; + } + shmctl(yuvshm->shmid, IPC_RMID, NULL); + } else { + shm_error = True; + } + if ( shm_error ) { + XFree(hwdata->image); + hwdata->yuv_use_mitshm = 0; + } else { + hwdata->image->data = yuvshm->shmaddr; + } + } + if ( !hwdata->yuv_use_mitshm ) +#endif /* NO_SHARED_MEMORY */ + { + hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, + 0, width, height); + +#ifdef PITCH_WORKAROUND + if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { + /* Ajust overlay width according to pitch */ + XFree(hwdata->image); + width = hwdata->image->pitches[0] / bpp; + hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, + 0, width, height); + } +#endif /* PITCH_WORKAROUND */ + if ( hwdata->image == NULL ) { + SDL_SetError("Couldn't create XVideo image"); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + hwdata->image->data = SDL_malloc(hwdata->image->data_size); + if ( hwdata->image->data == NULL ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + } + + /* Find the pitch and offset values for the overlay */ + overlay->planes = hwdata->image->num_planes; + overlay->pitches = (Uint16 *)SDL_malloc(overlay->planes * sizeof(Uint16)); + overlay->pixels = (Uint8 **)SDL_malloc(overlay->planes * sizeof(Uint8 *)); + if ( !overlay->pitches || !overlay->pixels ) { + SDL_OutOfMemory(); + SDL_FreeYUVOverlay(overlay); + return(NULL); + } + for ( i=0; i<overlay->planes; ++i ) { + overlay->pitches[i] = hwdata->image->pitches[i]; + overlay->pixels[i] = (Uint8 *)hwdata->image->data + + hwdata->image->offsets[i]; + } + +#ifdef XFREE86_REFRESH_HACK + /* Work around an XFree86 X server bug (?) + We can't perform normal updates in windows that have video + being output to them. See SDL_x11image.c for more details. + */ + X11_DisableAutoRefresh(this); +#endif + +#ifdef INTEL_XV_BADALLOC_WORKAROUND + /* HACK, GRRR sometimes (i810) creating the overlay succeeds, but the + first call to XvShm[Put]Image to a mapped window fails with: + "BadAlloc (insufficient resources for operation)". This happens with + certain formats when the XvImage is too large to the i810's liking. + + We work around this by doing a test XvShm[Put]Image with a black + Xv image, this may cause some flashing, so only do this check if we + are running on an intel Xv-adapter. */ + if (intel_adapter) + { + xv_error = False; + X_handler = XSetErrorHandler(intel_errhandler); + + X11_ClearYUVOverlay(overlay); + + /* We set the destination height and width to 1 pixel to avoid + putting a large black rectangle over the screen, thus + strongly reducing possible flashing. */ +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, + SDL_Window, SDL_GC, + hwdata->image, + 0, 0, overlay->w, overlay->h, + 0, 0, 1, 1, False); + } + else +#endif + { + SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, + SDL_Window, SDL_GC, + hwdata->image, + 0, 0, overlay->w, overlay->h, + 0, 0, 1, 1); + } + XSync(GFX_Display, False); + XSetErrorHandler(X_handler); + + if (xv_error) + { + X11_FreeYUVOverlay(this, overlay); + return NULL; + } + /* Repair the (1 pixel worth of) damage we've just done */ + X11_RefreshDisplay(this); + } +#endif + + /* We're all done.. */ + return(overlay); +} + +int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return(0); +} + +void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + return; +} + +int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, + hwdata->image, + src->x, src->y, src->w, src->h, + dst->x, dst->y, dst->w, dst->h, False); + } + else +#endif + { + SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, + hwdata->image, + src->x, src->y, src->w, src->h, + dst->x, dst->y, dst->w, dst->h); + } + XSync(GFX_Display, False); + return(0); +} + +void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) +{ + struct private_yuvhwdata *hwdata; + + hwdata = overlay->hwdata; + if ( hwdata ) { + SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); +#ifndef NO_SHARED_MEMORY + if ( hwdata->yuv_use_mitshm ) { + XShmDetach(GFX_Display, &hwdata->yuvshm); + shmdt(hwdata->yuvshm.shmaddr); + } +#endif + if ( hwdata->image ) { + XFree(hwdata->image); + } + SDL_free(hwdata); + } + if ( overlay->pitches ) { + SDL_free(overlay->pitches); + overlay->pitches = NULL; + } + if ( overlay->pixels ) { + SDL_free(overlay->pixels); + overlay->pixels = NULL; + } +#ifdef XFREE86_REFRESH_HACK + X11_EnableAutoRefresh(this); +#endif +} + +#endif /* SDL_VIDEO_DRIVER_X11_XV */ diff --git a/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h b/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h new file mode 100644 index 0000000..d297683 --- /dev/null +++ b/3rdparty/SDL/src/video/x11/SDL_x11yuv_c.h @@ -0,0 +1,41 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* This is the XFree86 Xv extension implementation of YUV video overlays */ + +#include "SDL_video.h" +#include "SDL_x11video.h" + +#if SDL_VIDEO_DRIVER_X11_XV + +extern SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + +#endif /* SDL_VIDEO_DRIVER_X11_XV */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios.c b/3rdparty/SDL/src/video/xbios/SDL_xbios.c new file mode 100644 index 0000000..56bf6ab --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios.c @@ -0,0 +1,1116 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + * Xbios SDL video driver + * + * Patrice Mandin + */ + +#include <sys/stat.h> +#include <unistd.h> + +/* Mint includes */ +#include <mint/cookie.h> +#include <mint/osbind.h> +#include <mint/falcon.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "../ataricommon/SDL_ataric2p_s.h" +#include "../ataricommon/SDL_atarievents_c.h" +#include "../ataricommon/SDL_atarimxalloc_c.h" +#include "../ataricommon/SDL_atarigl_c.h" +#include "SDL_xbios.h" +#include "SDL_xbios_blowup.h" +#include "SDL_xbios_centscreen.h" +#include "SDL_xbios_sb3.h" +#include "SDL_xbios_tveille.h" +#include "SDL_xbios_milan.h" + +#define XBIOS_VID_DRIVER_NAME "xbios" + +#ifndef C_fVDI +#define C_fVDI 0x66564449L +#endif + +/* Debug print info */ +#if 0 +#define DEBUG_PRINT(what) \ + { \ + printf what; \ + } +#define DEBUG_VIDEO_XBIOS 1 +#else +#define DEBUG_PRINT(what) +#undef DEBUG_VIDEO_XBIOS +#endif + +/* Initialization/Query functions */ +static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void XBIOS_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface); +static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface); +static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface); +static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); + +#if SDL_VIDEO_OPENGL +/* OpenGL functions */ +static void XBIOS_GL_SwapBuffers(_THIS); +#endif + +/* To setup palette */ + +static unsigned short TT_palette[256]; +static unsigned long F30_palette[256]; + +/* Default list of video modes */ + +static const xbiosmode_t stmodes[1]={ + {ST_LOW>>8,320,200,4, XBIOSMODE_C2P} +}; + +static const xbiosmode_t ttmodes[2]={ + {TT_LOW,320,480,8, XBIOSMODE_C2P}, + {TT_LOW,320,240,8, XBIOSMODE_C2P|XBIOSMODE_DOUBLELINE} +}; + +static const xbiosmode_t falconrgbmodes[16]={ + {BPS16|COL80|OVERSCAN|VERTFLAG,768,480,16,0}, + {BPS16|COL80|OVERSCAN,768,240,16,0}, + {BPS16|COL80|VERTFLAG,640,400,16,0}, + {BPS16|COL80,640,200,16,0}, + {BPS16|OVERSCAN|VERTFLAG,384,480,16,0}, + {BPS16|OVERSCAN,384,240,16,0}, + {BPS16|VERTFLAG,320,400,16,0}, + {BPS16,320,200,16,0}, + {BPS8|COL80|OVERSCAN|VERTFLAG,768,480,8,XBIOSMODE_C2P}, + {BPS8|COL80|OVERSCAN,768,240,8,XBIOSMODE_C2P}, + {BPS8|COL80|VERTFLAG,640,400,8,XBIOSMODE_C2P}, + {BPS8|COL80,640,200,8,XBIOSMODE_C2P}, + {BPS8|OVERSCAN|VERTFLAG,384,480,8,XBIOSMODE_C2P}, + {BPS8|OVERSCAN,384,240,8,XBIOSMODE_C2P}, + {BPS8|VERTFLAG,320,400,8,XBIOSMODE_C2P}, + {BPS8,320,200,8,XBIOSMODE_C2P} +}; + +static const xbiosmode_t falconvgamodes[6]={ + {BPS16,320,480,16,0}, + {BPS16|VERTFLAG,320,240,16,0}, + {BPS8|COL80,640,480,8,XBIOSMODE_C2P}, + {BPS8|COL80|VERTFLAG,640,240,8,XBIOSMODE_C2P}, + {BPS8,320,480,8,XBIOSMODE_C2P}, + {BPS8|VERTFLAG,320,240,8,XBIOSMODE_C2P} +}; + +/* Xbios driver bootstrap functions */ + +static int XBIOS_Available(void) +{ + long cookie_vdo, /*cookie_mil,*/ cookie_hade, cookie_scpn; + long cookie_fvdi; + const char *envr = SDL_getenv("SDL_VIDEODRIVER"); + + /* Milan/Hades Atari clones do not have an Atari video chip */ + if ( /*(Getcookie(C__MIL, &cookie_mil) == C_FOUND) ||*/ + (Getcookie(C_hade, &cookie_hade) == C_FOUND) ) { + return 0; + } + + /* fVDI means graphic card, so no Xbios with it */ + if (Getcookie(C_fVDI, &cookie_fvdi) == C_FOUND) { + if (!envr) { + return 0; + } + if (SDL_strcmp(envr, XBIOS_VID_DRIVER_NAME)!=0) { + return 0; + } + /* Except if we force Xbios usage, through env var */ + } + + /* Cookie _VDO present ? if not, assume ST machine */ + if (Getcookie(C__VDO, &cookie_vdo) != C_FOUND) { + cookie_vdo = VDO_ST << 16; + } + + /* Test if we have a monochrome monitor plugged in */ + switch( cookie_vdo >>16) { + case VDO_ST: + case VDO_STE: + if ( Getrez() == (ST_HIGH>>8) ) + return 0; + break; + case VDO_TT: + if ( (EgetShift() & ES_MODE) == TT_HIGH) + return 0; + break; + case VDO_F30: + if ( VgetMonitor() == MONITOR_MONO) + return 0; + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + if (!SDL_XBIOS_SB3Usable((scpn_cookie_t *)cookie_scpn)) { + return 0; + } + } + break; + case VDO_MILAN: + break; + default: + return 0; + } + + return 1; +} + +static void XBIOS_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *XBIOS_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( device ) { + SDL_memset(device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *device->hidden)); + device->gl_data = (struct SDL_PrivateGLData *) + SDL_malloc((sizeof *device->gl_data)); + } + if ( (device == NULL) || (device->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( device ) { + SDL_free(device); + } + return(0); + } + SDL_memset(device->hidden, 0, (sizeof *device->hidden)); + SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); + + /* Video functions */ + device->VideoInit = XBIOS_VideoInit; + device->ListModes = XBIOS_ListModes; + device->SetVideoMode = XBIOS_SetVideoMode; + device->SetColors = XBIOS_SetColors; + device->UpdateRects = NULL; + device->VideoQuit = XBIOS_VideoQuit; + device->AllocHWSurface = XBIOS_AllocHWSurface; + device->LockHWSurface = XBIOS_LockHWSurface; + device->UnlockHWSurface = XBIOS_UnlockHWSurface; + device->FlipHWSurface = XBIOS_FlipHWSurface; + device->FreeHWSurface = XBIOS_FreeHWSurface; + +#if SDL_VIDEO_OPENGL + /* OpenGL functions */ + device->GL_LoadLibrary = SDL_AtariGL_LoadLibrary; + device->GL_GetProcAddress = SDL_AtariGL_GetProcAddress; + device->GL_GetAttribute = SDL_AtariGL_GetAttribute; + device->GL_MakeCurrent = SDL_AtariGL_MakeCurrent; + device->GL_SwapBuffers = XBIOS_GL_SwapBuffers; +#endif + + /* Events */ + device->InitOSKeymap = Atari_InitOSKeymap; + device->PumpEvents = Atari_PumpEvents; + + device->free = XBIOS_DeleteDevice; + + return device; +} + +VideoBootStrap XBIOS_bootstrap = { + XBIOS_VID_DRIVER_NAME, "Atari Xbios driver", + XBIOS_Available, XBIOS_CreateDevice +}; + +void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo) +{ + int i = 0; + + switch(modeinfo->depth) { + case 15: + case 16: + i = 1; + break; + case 24: + i = 2; + break; + case 32: + i = 3; + break; + } + + if ( actually_add ) { + SDL_Rect saved_rect[2]; + xbiosmode_t saved_mode[2]; + int b, j; + + /* Add the mode, sorted largest to smallest */ + b = 0; + j = 0; + while ( (SDL_modelist[i][j]->w > modeinfo->width) || + (SDL_modelist[i][j]->h > modeinfo->height) ) { + ++j; + } + /* Skip modes that are already in our list */ + if ( (SDL_modelist[i][j]->w == modeinfo->width) && + (SDL_modelist[i][j]->h == modeinfo->height) ) { + return; + } + /* Insert the new mode */ + saved_rect[b] = *SDL_modelist[i][j]; + SDL_memcpy(&saved_mode[b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); + SDL_modelist[i][j]->w = modeinfo->width; + SDL_modelist[i][j]->h = modeinfo->height; + SDL_memcpy(SDL_xbiosmode[i][j], modeinfo, sizeof(xbiosmode_t)); + /* Everybody scoot down! */ + if ( saved_rect[b].w && saved_rect[b].h ) { + for ( ++j; SDL_modelist[i][j]->w; ++j ) { + saved_rect[!b] = *SDL_modelist[i][j]; + memcpy(&saved_mode[!b], SDL_xbiosmode[i][j], sizeof(xbiosmode_t)); + *SDL_modelist[i][j] = saved_rect[b]; + SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); + b = !b; + } + *SDL_modelist[i][j] = saved_rect[b]; + SDL_memcpy(SDL_xbiosmode[i][j], &saved_mode[b], sizeof(xbiosmode_t)); + } + } else { + ++SDL_nummodes[i]; + } +} + +static void XBIOS_ListSTModes(_THIS, int actually_add) +{ + SDL_XBIOS_AddMode(this, actually_add, &stmodes[0]); +} + +static void XBIOS_ListTTModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<2; i++) { + SDL_XBIOS_AddMode(this, actually_add, &ttmodes[i]); + } +} + +static void XBIOS_ListFalconRgbModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<16; i++) { + xbiosmode_t modeinfo; + + SDL_memcpy(&modeinfo, &falconrgbmodes[i], sizeof(xbiosmode_t)); + modeinfo.number &= ~(VGA|PAL); + modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } +} + +static void XBIOS_ListFalconVgaModes(_THIS, int actually_add) +{ + int i; + + for (i=0; i<6; i++) { + xbiosmode_t modeinfo; + + SDL_memcpy(&modeinfo, &falconvgamodes[i], sizeof(xbiosmode_t)); + modeinfo.number &= ~(VGA|PAL); + modeinfo.number |= XBIOS_oldvmode & (VGA|PAL); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } +} + +static int XBIOS_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + long cookie_blow, cookie_scpn, cookie_cnts; + + /* Initialize all variables that we clean on shutdown */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + SDL_xbiosmode[i] = NULL; + } + + /* Cookie _VDO present ? if not, assume ST machine */ + if (Getcookie(C__VDO, &XBIOS_cvdo) != C_FOUND) { + XBIOS_cvdo = VDO_ST << 16; + } + + /* Allocate memory for old palette */ + XBIOS_oldpalette = (void *)SDL_malloc(256*sizeof(long)); + if ( !XBIOS_oldpalette ) { + SDL_SetError("Unable to allocate memory for old palette\n"); + return(-1); + } + + /* Initialize video mode list */ + /* and save current screen status (palette, screen address, video mode) */ + XBIOS_centscreen = SDL_FALSE; + XBIOS_oldvbase = Physbase(); + + /* Determine the current screen size */ + this->info.current_w = 0; + this->info.current_h = 0; + + /* Determine the screen depth (use default 8-bit depth) */ + vformat->BitsPerPixel = 8; + + /* First allocate room for needed video modes */ + switch (XBIOS_cvdo >>16) { + case VDO_ST: + case VDO_STE: + { + short *oldpalette; + + XBIOS_oldvmode=Getrez(); + switch(XBIOS_oldvmode << 8) { + case ST_LOW: + XBIOS_oldnumcol=16; + break; + case ST_MED: + XBIOS_oldnumcol=4; + break; + case ST_HIGH: + XBIOS_oldnumcol=2; + break; + } + + oldpalette= (short *) XBIOS_oldpalette; + for (i=0;i<XBIOS_oldnumcol;i++) { + *oldpalette++=Setcolor(i,-1); + } + + XBIOS_ListSTModes(this, 0); + } + break; + case VDO_TT: + XBIOS_oldvmode=EgetShift(); + + switch(XBIOS_oldvmode & ES_MODE) { + case TT_LOW: + XBIOS_oldnumcol=256; + break; + case ST_LOW: + case TT_MED: + XBIOS_oldnumcol=16; + break; + case ST_MED: + XBIOS_oldnumcol=4; + break; + case ST_HIGH: + case TT_HIGH: + XBIOS_oldnumcol=2; + break; + } + if (XBIOS_oldnumcol) { + EgetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + XBIOS_ListTTModes(this, 0); + break; + case VDO_F30: + XBIOS_oldvmode=VsetMode(-1); + + XBIOS_oldnumcol= 1<< (1 << (XBIOS_oldvmode & NUMCOLS)); + if (XBIOS_oldnumcol > 256) { + XBIOS_oldnumcol = 0; + } + if (XBIOS_oldnumcol) { + VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + vformat->BitsPerPixel = 16; + + /* ScreenBlaster 3 ? */ + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + SDL_XBIOS_ListSB3Modes(this, 0, (scpn_cookie_t *)cookie_scpn); + } else + /* Centscreen ? */ + if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { + XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 0); + XBIOS_centscreen = SDL_TRUE; + } else + /* Standard, with or without Blowup */ + { + switch (VgetMonitor()) + { + case MONITOR_RGB: + case MONITOR_TV: + XBIOS_ListFalconRgbModes(this, 0); + break; + case MONITOR_VGA: + XBIOS_ListFalconVgaModes(this, 0); + break; + } + + if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { + SDL_XBIOS_ListBlowupModes(this, 0, (blow_cookie_t *)cookie_blow); + } + } + break; + case VDO_MILAN: + { + SCREENINFO si; + + /* Read infos about current mode */ + VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_GETMODE); + + si.size = sizeof(SCREENINFO); + si.devID = XBIOS_oldvmode; + si.scrFlags = 0; + VsetScreen(-1, &si, MI_MAGIC, CMD_GETINFO); + + this->info.current_w = si.scrWidth; + this->info.current_h = si.scrHeight; + + XBIOS_oldnumcol = 0; + if (si.scrFlags & SCRINFO_OK) { + if (si.scrPlanes <= 8) { + XBIOS_oldnumcol = 1<<si.scrPlanes; + } + } + if (XBIOS_oldnumcol) { + VgetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + + SDL_XBIOS_ListMilanModes(this, 0); + } + break; + } + + for ( i=0; i<NUM_MODELISTS; ++i ) { + int j; + + SDL_xbiosmode[i] = (xbiosmode_t **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(xbiosmode_t *)); + if ( SDL_xbiosmode[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_xbiosmode[i][j]=(xbiosmode_t *)SDL_malloc(sizeof(xbiosmode_t)); + if ( SDL_xbiosmode[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_xbiosmode[i][j], 0, sizeof(xbiosmode_t)); + } + SDL_xbiosmode[i][j] = NULL; + + SDL_modelist[i] = (SDL_Rect **) + SDL_malloc((SDL_nummodes[i]+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[i] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + for ( j=0; j<SDL_nummodes[i]; ++j ) { + SDL_modelist[i][j]=(SDL_Rect *)SDL_malloc(sizeof(SDL_Rect)); + if ( SDL_modelist[i][j] == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + SDL_memset(SDL_modelist[i][j], 0, sizeof(SDL_Rect)); + } + SDL_modelist[i][j] = NULL; + } + + /* Now fill the mode list */ + switch (XBIOS_cvdo >>16) { + case VDO_ST: + case VDO_STE: + XBIOS_ListSTModes(this, 1); + break; + case VDO_TT: + XBIOS_ListTTModes(this, 1); + break; + case VDO_F30: + /* ScreenBlaster 3 ? */ + if (Getcookie(C_SCPN, &cookie_scpn) == C_FOUND) { + SDL_XBIOS_ListSB3Modes(this, 1, (scpn_cookie_t *)cookie_scpn); + } else + /* Centscreen ? */ + if (Getcookie(C_CNTS, &cookie_cnts) == C_FOUND) { + XBIOS_oldvmode = SDL_XBIOS_ListCentscreenModes(this, 1); + XBIOS_centscreen = SDL_TRUE; + } else + /* Standard, with or without Blowup */ + { + switch (VgetMonitor()) + { + case MONITOR_RGB: + case MONITOR_TV: + XBIOS_ListFalconRgbModes(this, 1); + break; + case MONITOR_VGA: + XBIOS_ListFalconVgaModes(this, 1); + break; + } + + if (Getcookie(C_BLOW, &cookie_blow) == C_FOUND) { + SDL_XBIOS_ListBlowupModes(this, 1, (blow_cookie_t *)cookie_blow); + } + } + break; + case VDO_MILAN: + SDL_XBIOS_ListMilanModes(this, 1); + break; + } + + XBIOS_screens[0]=NULL; + XBIOS_screens[1]=NULL; + XBIOS_shadowscreen=NULL; + + /* Update hardware info */ + this->info.hw_available = 1; + this->info.video_mem = (Uint32) Atari_SysMalloc(-1L, MX_STRAM); + + /* Init chunky to planar routine */ + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + +#if SDL_VIDEO_OPENGL + SDL_AtariGL_InitPointers(this); +#endif + + /* Disable screensavers */ + if (SDL_XBIOS_TveillePresent(this)) { + SDL_XBIOS_TveilleDisable(this); + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **XBIOS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +static void XBIOS_FreeBuffers(_THIS) +{ + int i; + + for (i=0;i<2;i++) { + if (XBIOS_screensmem[i]!=NULL) { + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + if (i==1) { + VsetScreen(-1, -1, MI_MAGIC, CMD_FREEPAGE); + } + } else { + Mfree(XBIOS_screensmem[i]); + } + XBIOS_screensmem[i]=NULL; + } + } + + if (XBIOS_shadowscreen!=NULL) { + Mfree(XBIOS_shadowscreen); + XBIOS_shadowscreen=NULL; + } +} + +static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + int mode, new_depth; + int i, num_buffers; + xbiosmode_t *new_video_mode; + Uint32 new_screen_size; + Uint32 modeflags; + + /* Free current buffers */ + XBIOS_FreeBuffers(this); + + /* Try to set the requested linear video mode */ + bpp = (bpp+7)/8-1; + for ( mode=0; SDL_modelist[bpp][mode]; ++mode ) { + if ( (SDL_modelist[bpp][mode]->w == width) && + (SDL_modelist[bpp][mode]->h == height) ) { + break; + } + } + if ( SDL_modelist[bpp][mode] == NULL ) { + SDL_SetError("Couldn't find requested mode in list"); + return(NULL); + } + new_video_mode = SDL_xbiosmode[bpp][mode]; + + modeflags = SDL_FULLSCREEN | SDL_PREALLOC; + + /* Allocate needed buffers: simple/double buffer and shadow surface */ + new_depth = new_video_mode->depth; + if (new_depth == 4) { + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert4; + new_depth=8; + modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; + } else if (new_depth == 8) { + SDL_Atari_C2pConvert = SDL_Atari_C2pConvert8; + modeflags |= SDL_SWSURFACE|SDL_HWPALETTE; + } else { + modeflags |= SDL_HWSURFACE; + } + + new_screen_size = width * height * ((new_depth)>>3); + new_screen_size += 256; /* To align on a 256 byte adress */ + + if (new_video_mode->flags & XBIOSMODE_C2P) { + XBIOS_shadowscreen = Atari_SysMalloc(new_screen_size, MX_PREFTTRAM); + + if (XBIOS_shadowscreen == NULL) { + SDL_SetError("Can not allocate %d KB for shadow buffer", new_screen_size>>10); + return (NULL); + } + SDL_memset(XBIOS_shadowscreen, 0, new_screen_size); + } + + /* Output buffer needs to be twice in size for the software double-line mode */ + if (new_video_mode->flags & XBIOSMODE_DOUBLELINE) { + new_screen_size <<= 1; + } + + /* Double buffer ? */ + num_buffers = 1; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (this->gl_config.double_buffer) { + flags |= SDL_DOUBLEBUF; + } + } +#endif + if ((flags & SDL_DOUBLEBUF) && ((XBIOS_cvdo>>16) != VDO_MILAN)) { + num_buffers = 2; + modeflags |= SDL_DOUBLEBUF; + } + + /* Allocate buffers */ + for (i=0; i<num_buffers; i++) { + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + if (i==0) { + XBIOS_screensmem[i] = XBIOS_oldvbase; + } else { + VsetScreen(-1, &XBIOS_screensmem[i], MI_MAGIC, CMD_ALLOCPAGE); + } + } else { + XBIOS_screensmem[i] = Atari_SysMalloc(new_screen_size, MX_STRAM); + } + + if (XBIOS_screensmem[i]==NULL) { + XBIOS_FreeBuffers(this); + SDL_SetError("Can not allocate %d KB for buffer %d", new_screen_size>>10, i); + return (NULL); + } + SDL_memset(XBIOS_screensmem[i], 0, new_screen_size); + + XBIOS_screens[i]=(void *) (( (long) XBIOS_screensmem[i]+256) & 0xFFFFFF00UL); + } + + /* Allocate the new pixel format for the screen */ + if ( ! SDL_ReallocFormat(current, new_depth, 0, 0, 0, 0) ) { + XBIOS_FreeBuffers(this); + SDL_SetError("Couldn't allocate new pixel format for requested mode"); + return(NULL); + } + + XBIOS_current = new_video_mode; + current->w = width; + current->h = height; + current->pitch = (width * new_depth)>>3; + + /* this is for C2P conversion */ + XBIOS_pitch = (new_video_mode->width * new_video_mode->depth)>>3; + + if (new_video_mode->flags & XBIOSMODE_C2P) + current->pixels = XBIOS_shadowscreen; + else + current->pixels = XBIOS_screens[0]; + + XBIOS_fbnum = 0; + +#if SDL_VIDEO_OPENGL + if (flags & SDL_OPENGL) { + if (!SDL_AtariGL_Init(this, current)) { + XBIOS_FreeBuffers(this); + SDL_SetError("Can not create OpenGL context"); + return NULL; + } + + modeflags |= SDL_OPENGL; + } +#endif + + current->flags = modeflags; + +#ifndef DEBUG_VIDEO_XBIOS + /* Now set the video mode */ + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[0], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[0],-1); + } + + switch(XBIOS_cvdo >> 16) { + case VDO_ST: + Setscreen(-1,-1,new_video_mode->number); + + /* Reset palette */ + for (i=0;i<16;i++) { + TT_palette[i]= ((i>>1)<<8) | (((i*8)/17)<<4) | (i>>1); + } + Setpalette(TT_palette); + break; + case VDO_STE: + Setscreen(-1,-1,new_video_mode->number); + + /* Reset palette */ + for (i=0;i<16;i++) + { + int c; + + c=((i&1)<<3)|((i>>1)&7); + TT_palette[i]=(c<<8)|(c<<4)|c; + } + Setpalette(TT_palette); + break; + case VDO_TT: + EsetShift(new_video_mode->number); + break; + case VDO_F30: + if (XBIOS_centscreen) { + SDL_XBIOS_CentscreenSetmode(this, width, height, new_depth); + } else { + VsetMode(new_video_mode->number); + } + + /* Set hardware palette to black in True Colour */ + if (new_depth > 8) { + SDL_memset(F30_palette, 0, sizeof(F30_palette)); + VsetRGB(0,256,F30_palette); + } + break; + case VDO_MILAN: + VsetScreen(-1, new_video_mode->number, MI_MAGIC, CMD_SETMODE); + + /* Set hardware palette to black in True Colour */ + if (new_depth > 8) { + SDL_memset(F30_palette, 0, sizeof(F30_palette)); + VsetRGB(0,256,F30_palette); + } + break; + } + + Vsync(); +#endif + + this->UpdateRects = XBIOS_UpdateRects; + + return (current); +} + +/* We don't actually allow hardware surfaces other than the main one */ +static int XBIOS_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + return(-1); +} + +static void XBIOS_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static int XBIOS_LockHWSurface(_THIS, SDL_Surface *surface) +{ + return(0); +} + +static void XBIOS_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + return; +} + +static void XBIOS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *surface; + + surface = this->screen; + + if (XBIOS_current->flags & XBIOSMODE_C2P) { + int i; + int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); + + for (i=0;i<numrects;i++) { + void *source,*destination; + int x1,x2; + + x1 = rects[i].x & ~15; + x2 = rects[i].x+rects[i].w; + if (x2 & 15) { + x2 = (x2 | 15) +1; + } + + source = surface->pixels; + source += surface->pitch * rects[i].y; + source += x1; + + destination = XBIOS_screens[XBIOS_fbnum]; + destination += XBIOS_pitch * rects[i].y; + destination += x1; + + /* Convert chunky to planar screen */ + SDL_Atari_C2pConvert( + source, + destination, + x2-x1, + rects[i].h, + doubleline, + surface->pitch, + XBIOS_pitch + ); + } + } + +#ifndef DEBUG_VIDEO_XBIOS + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); + } + + Vsync(); +#endif + + if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { + XBIOS_fbnum ^= 1; + if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { + surface->pixels=XBIOS_screens[XBIOS_fbnum]; + } + } +} + +static int XBIOS_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (XBIOS_current->flags & XBIOSMODE_C2P) { + void *destscr; + int destx; + int doubleline = (XBIOS_current->flags & XBIOSMODE_DOUBLELINE ? 1 : 0); + + /* Center on destination screen */ + destscr = XBIOS_screens[XBIOS_fbnum]; + destscr += XBIOS_pitch * ((XBIOS_current->height - surface->h) >> 1); + destx = (XBIOS_current->width - surface->w) >> 1; + destx &= ~15; + destscr += destx; + + /* Convert chunky to planar screen */ + SDL_Atari_C2pConvert( + surface->pixels, + destscr, + surface->w, + surface->h, + doubleline, + surface->pitch, + XBIOS_pitch + ); + } + +#ifndef DEBUG_VIDEO_XBIOS + if ((XBIOS_cvdo>>16) == VDO_MILAN) { + VsetScreen(-1, XBIOS_screens[XBIOS_fbnum], MI_MAGIC, CMD_SETADR); + } else { + Setscreen(-1,XBIOS_screens[XBIOS_fbnum],-1); + } + + Vsync(); +#endif + + if ((surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { + XBIOS_fbnum ^= 1; + if ((XBIOS_current->flags & XBIOSMODE_C2P) == 0) { + surface->pixels=XBIOS_screens[XBIOS_fbnum]; + } + } + + return(0); +} + +static int XBIOS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ +#ifndef DEBUG_VIDEO_XBIOS + int i; + int r,v,b; + + switch( XBIOS_cvdo >> 16) { + case VDO_ST: + case VDO_STE: + for (i=0;i<ncolors;i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + TT_palette[firstcolor+i]=((r*30)+(v*59)+(b*11))/100; + } + SDL_Atari_C2pConvert4_pal(TT_palette); /* convert the lighting */ + break; + case VDO_TT: + for(i = 0; i < ncolors; i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + TT_palette[i]=((r>>4)<<8)|((v>>4)<<4)|(b>>4); + } + EsetPalette(firstcolor,ncolors,TT_palette); + break; + case VDO_F30: + case VDO_MILAN: + for(i = 0; i < ncolors; i++) + { + r = colors[i].r; + v = colors[i].g; + b = colors[i].b; + + F30_palette[i]=(r<<16)|(v<<8)|b; + } + VsetRGB(firstcolor,ncolors,F30_palette); + break; + } +#endif + + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void XBIOS_VideoQuit(_THIS) +{ + int i,j; + + Atari_ShutdownEvents(); + + /* Restore video mode and palette */ +#ifndef DEBUG_VIDEO_XBIOS + switch(XBIOS_cvdo >> 16) { + case VDO_ST: + case VDO_STE: + Setscreen(-1,XBIOS_oldvbase,XBIOS_oldvmode); + if (XBIOS_oldnumcol) { + Setpalette(XBIOS_oldpalette); + } + break; + case VDO_TT: + Setscreen(-1,XBIOS_oldvbase,-1); + EsetShift(XBIOS_oldvmode); + if (XBIOS_oldnumcol) { + EsetPalette(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + case VDO_F30: + Setscreen(-1, XBIOS_oldvbase, -1); + if (XBIOS_centscreen) { + SDL_XBIOS_CentscreenRestore(this, XBIOS_oldvmode); + } else { + VsetMode(XBIOS_oldvmode); + } + if (XBIOS_oldnumcol) { + VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + case VDO_MILAN: + VsetScreen(-1, &XBIOS_oldvbase, MI_MAGIC, CMD_SETADR); + VsetScreen(-1, &XBIOS_oldvmode, MI_MAGIC, CMD_SETMODE); + if (XBIOS_oldnumcol) { + VsetRGB(0, XBIOS_oldnumcol, XBIOS_oldpalette); + } + break; + } + Vsync(); +#endif + +#if SDL_VIDEO_OPENGL + if (gl_active) { + SDL_AtariGL_Quit(this, SDL_TRUE); + } +#endif + + if (XBIOS_oldpalette) { + SDL_free(XBIOS_oldpalette); + XBIOS_oldpalette=NULL; + } + XBIOS_FreeBuffers(this); + + /* Free mode list */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) + SDL_free(SDL_modelist[i][j]); + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + if ( SDL_xbiosmode[i] != NULL ) { + for ( j=0; SDL_xbiosmode[i][j]; ++j ) + SDL_free(SDL_xbiosmode[i][j]); + SDL_free(SDL_xbiosmode[i]); + SDL_xbiosmode[i] = NULL; + } + } + + this->screen->pixels = NULL; + + /* Restore screensavers */ + if (SDL_XBIOS_TveillePresent(this)) { + SDL_XBIOS_TveilleEnable(this); + } +} + +#if SDL_VIDEO_OPENGL + +static void XBIOS_GL_SwapBuffers(_THIS) +{ + SDL_AtariGL_SwapBuffers(this); + XBIOS_FlipHWSurface(this, this->screen); + SDL_AtariGL_MakeCurrent(this); +} + +#endif diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios.h b/3rdparty/SDL/src/video/xbios/SDL_xbios.h new file mode 100644 index 0000000..3ad6827 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios.h @@ -0,0 +1,111 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_xbios_h +#define _SDL_xbios_h + +#include "SDL_stdinc.h" +#include "../SDL_sysvideo.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +#define XBIOSMODE_DOUBLELINE (1<<0) +#define XBIOSMODE_C2P (1<<1) + +typedef struct +{ + Uint16 number; /* Video mode number */ + Uint16 width; /* Size */ + Uint16 height; + Uint16 depth; /* bits per plane */ + Uint16 flags; +} xbiosmode_t; + +/* Private display data */ +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + +struct SDL_PrivateVideoData { + long cookie_vdo; + long old_video_mode; /* Old video mode before entering SDL */ + void *old_video_base; /* Old pointer to screen buffer */ + void *old_palette; /* Old palette */ + Uint32 old_num_colors; /* Nb of colors in saved palette */ + + void *screens[2]; /* Pointers to aligned screen buffer */ + void *screensmem[2]; /* Pointers to screen buffer */ + void *shadowscreen; /* Shadow screen for c2p conversion */ + int frame_number; /* Number of frame for double buffer */ + int pitch; /* Destination line width for C2P */ + + SDL_bool centscreen; /* Centscreen extension present ? */ + + xbiosmode_t *current; /* Current set mode */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + xbiosmode_t **SDL_xbiosmode[NUM_MODELISTS]; +}; + +/* _VDO cookie values */ +enum { + VDO_ST=0, + VDO_STE, + VDO_TT, + VDO_F30, + VDO_MILAN +}; + +/* Monitor types */ +enum { + MONITOR_MONO=0, + MONITOR_TV, + MONITOR_VGA, + MONITOR_RGB +}; + +/* EgetShift masks */ +#define ES_MODE 0x0700 + +/* Hidden structure -> variables names */ +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define SDL_xbiosmode (this->hidden->SDL_xbiosmode) +#define XBIOS_mutex (this->hidden->mutex) +#define XBIOS_cvdo (this->hidden->cookie_vdo) +#define XBIOS_oldpalette (this->hidden->old_palette) +#define XBIOS_oldnumcol (this->hidden->old_num_colors) +#define XBIOS_oldvbase (this->hidden->old_video_base) +#define XBIOS_oldvmode (this->hidden->old_video_mode) +#define XBIOS_screens (this->hidden->screens) +#define XBIOS_screensmem (this->hidden->screensmem) +#define XBIOS_shadowscreen (this->hidden->shadowscreen) +#define XBIOS_fbnum (this->hidden->frame_number) +#define XBIOS_pitch (this->hidden->pitch) +#define XBIOS_centscreen (this->hidden->centscreen) +#define XBIOS_current (this->hidden->current) + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_AddMode(_THIS, int actually_add, const xbiosmode_t *modeinfo); + +#endif /* _SDL_xbios_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c new file mode 100644 index 0000000..2950b84 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.c @@ -0,0 +1,77 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Blowup extension definitions + + Patrice Mandin +*/ + +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_blowup.h" + +void SDL_XBIOS_ListBlowupModes(_THIS, int actually_add, blow_cookie_t *cookie_blow) +{ + int i, j, num_mode, bank; + blow_mode_t *blow_mode; + xbiosmode_t modeinfo; + + if (actually_add) { + /* Set bit 15 for old modes */ + for (i=0;i<NUM_MODELISTS;i++) { + if ( SDL_xbiosmode[i] != NULL ) { + for ( j=0; SDL_xbiosmode[i][j]; ++j ) { + SDL_xbiosmode[i][j]->number |= 1<<15; + } + } + } + } + + /* Add Blowup modes for 8 and 16 bpp */ + for (num_mode=3; num_mode<5; num_mode++) { + bank = cookie_blow->num_mode[num_mode]; + blow_mode = &(cookie_blow->blowup_modes[num_mode+(bank*5)]); + + /* Check extended mode enabled */ + if (blow_mode->enabled == 0) { + /* Check monitor needed for this mode */ + if ((blow_mode->monitor == cookie_blow->montype) + || ((blow_mode->monitor == MONITOR_TV) + && (cookie_blow->montype == MONITOR_RGB)) + || ((blow_mode->monitor == MONITOR_RGB) + && (cookie_blow->montype == MONITOR_TV))) + { + /* we can use this extended mode */ + modeinfo.number = (num_mode == 3 ? BPS8 : BPS16); + modeinfo.width = blow_mode->width + 1; + modeinfo.height = blow_mode->height + 1; + modeinfo.depth = (num_mode == 3 ? 8 : 16); + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + } +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h new file mode 100644 index 0000000..09a3651 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_blowup.h @@ -0,0 +1,86 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Blowup extension definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_blowup_h +#define _SDL_xbios_blowup_h + +#include "SDL_xbios.h" + +/*--- Types ---*/ + +typedef struct { + /* 64 bytes */ + unsigned short enabled; /* Extended mode enabled ? 0=yes, <>0=no */ + unsigned short dummy10[6]; + unsigned short registers_0E; /* value for register 0xffff820e */ + unsigned short registers_10; /* value for register 0xffff8210 */ + unsigned short dummy11[23]; + + /* 64 bytes */ + unsigned short width; /* width-1 */ + unsigned short height; /* height-1 */ + unsigned short dummy20; + unsigned long screensize; /* screensize in bytes */ + unsigned short dummy21[8]; + unsigned short virtual; /* Virtual screen ? */ + unsigned short virwidth; /* Virtual screen width */ + unsigned short virheight; /* Virtual screen height */ + + unsigned short dummy22; + unsigned short monitor; /* Monitor defined for this mode */ + unsigned short extension; /* Extended mode defined ? 0=yes, 1=no */ + unsigned short dummy23[13]; + + /* 64 bytes */ + unsigned short dummy30; + unsigned short registers_82[6]; /* values for registers 0xffff8282-8c */ + unsigned short dummy31[9]; + + unsigned short dummy32; + unsigned short registers_A2[6]; /* values for registers 0xffff82a2-ac */ + unsigned short dummy33[9]; + + /* 64 bytes */ + unsigned short registers_C0; /* value for register 0xffff82c0 */ + unsigned short registers_C2; /* value for register 0xffff82c2 */ + unsigned short dummy40[30]; +} blow_mode_t; + +typedef struct { + blow_mode_t blowup_modes[10]; + unsigned char num_mode[6]; + unsigned long dummy; + unsigned short montype; +} blow_cookie_t; + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_ListBlowupModes(_THIS, int actually_add, blow_cookie_t *cookie_blow); + +#endif /* _SDL_xbios_blowup_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c new file mode 100644 index 0000000..6daade2 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.c @@ -0,0 +1,104 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Centscreen extension definitions + + Patrice Mandin +*/ + +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_centscreen.h" + +int SDL_XBIOS_ListCentscreenModes(_THIS, int actually_add) +{ + centscreen_mode_t curmode, listedmode; + unsigned long result; + int cur_handle; /* Current Centscreen mode handle */ + + /* Add Centscreen modes */ + Vread(&curmode); + cur_handle = curmode.handle; + curmode.mode = curmode.physx = curmode.physy = curmode.plan = + curmode.logx = curmode.logy = -1; + + result = Vfirst(&curmode, &listedmode); + if (result==0) { + while (result==0) { + /* Don't add modes with virtual screen */ + if ((listedmode.mode & CSCREEN_VIRTUAL)==0) { + /* Don't add modes with bpp<8 */ + if (listedmode.plan>=8) { + xbiosmode_t modeinfo; + + modeinfo.number = listedmode.mode; + modeinfo.width = listedmode.physx; + modeinfo.height = listedmode.physy; + modeinfo.depth = listedmode.plan; + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + SDL_memcpy(&curmode, &listedmode, sizeof(centscreen_mode_t)); + curmode.mode = curmode.physx = curmode.physy = curmode.plan = + curmode.logx = curmode.logy = -1; + result = Vnext(&curmode, &listedmode); + } + } else { + fprintf(stderr, "No suitable Centscreen modes\n"); + } + + return cur_handle; +} + +void SDL_XBIOS_CentscreenSetmode(_THIS, int width, int height, int planes) +{ + centscreen_mode_t newmode, curmode; + + newmode.handle = newmode.mode = newmode.logx = newmode.logy = -1; + newmode.physx = width; + newmode.physy = height; + newmode.plan = planes; + Vwrite(0, &newmode, &curmode); + +#ifdef SDL_VIDEO_DISABLE_SCREENSAVER + /* Disable screensaver */ + Vread(&newmode); + newmode.mode &= ~(CSCREEN_SAVER|CSCREEN_ENERGYSTAR); + Vwrite(0, &newmode, &curmode); +#endif /* SDL_VIDEO_DISABLE_SCREENSAVER */ +} + +void SDL_XBIOS_CentscreenRestore(_THIS, int prev_handle) +{ + centscreen_mode_t newmode, curmode; + + /* Restore old video mode */ + newmode.handle = prev_handle; + newmode.mode = newmode.physx = newmode.physy = newmode.plan = + newmode.logx = newmode.logy = -1; + Vwrite(0, &newmode, &curmode); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h new file mode 100644 index 0000000..dfe88d9 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_centscreen.h @@ -0,0 +1,114 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Centscreen extension definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_centscreen_h +#define _SDL_xbios_centscreen_h + +#include <mint/falcon.h> /* for trap_14_xxx macros */ + +#include "SDL_xbios.h" + +/*--- Defines ---*/ + +#define CSCREEN_ENERGYSTAR (1<<9) +#define CSCREEN_SAVER (1<<10) +#define CSCREEN_VIRTUAL (1<<11) +#define CSCREEN_EXTCLOCK_CT2 (1<<12) +#define CSCREEN_EXTCLOCK (1<<13) +#define CSCREEN_STANDARD (1<<14) +#define CSCREEN_DEFAULT (1<<15) + +/*--- Structures ---*/ + +typedef struct { + unsigned short handle; /* videomode handle */ + unsigned short mode; /* Falcon videomode code */ + unsigned short physx; /* visible width */ + unsigned short physy; /* visible height */ + unsigned short plan; /* bitplanes */ + unsigned short logx; /* virtual width */ + unsigned short logy; /* virtual height */ + unsigned short eco; /* screen saver delay */ + unsigned short eco2; /* energy star screen saver delay */ + unsigned short wsize; /* screen width (mm) */ + unsigned short hsize; /* screen height (mm) */ + unsigned short dummy[21]; + unsigned char name[32]; /* videomode name */ +} centscreen_mode_t; + +/*--- Functions prototypes ---*/ + +#define Vread(current_mode) \ + (void)trap_14_wl((short)0x41,(long)(current_mode)) +#define Vwrite(init_vdi, inparam, outparam) \ + (long)trap_14_wwll((short)0x42,(short)(init_vdi),(long)(inparam),(long)(outparam)) +#define Vattrib(inparam, outparam) \ + (void)trap_14_wll((short)0x43,(long)(inparam),(long)(outparam)) +#define Vcreate(inparam, outparam) \ + (void)trap_14_wll((short)0x44,(long)(inparam),(long)(outparam)) +#define Vdelete(handle) \ + (long)trap_14_ww((short)0x45,(short)(handle)) +#define Vfirst(mask,mode) \ + (long)trap_14_wll((short)0x46,(long)(mask),(long)(mode)) +#define Vnext(mask,mode) \ + (long)trap_14_wll((short)0x47,(long)(mask),(long)(mode)) +#define Vvalid(handle) \ + (long)trap_14_ww((short)0x48,(short)(handle)) +#define Vload() \ + (long)trap_14_w((short)0x49) +#define Vsave() \ + (long)trap_14_w((short)0x4a) +#define Vopen() \ + (long)trap_14_w((short)0x4b) +#define Vclose() \ + (long)trap_14_w((short)0x4c) +#define Vscroll(scrollmode) \ + (long)trap_14_ww((short)0x4d,(short)(scrollmode)) +#define Voffset() \ + (long)trap_14_w((short)0x4e) +#define Vseek() \ + (long)trap_14_w((short)0x4f) +#define Vlock(cmd) \ + (long)trap_14_ww((short)0x50,(short)(cmd)) +#define SetMon(montype) \ + (long)trap_14_ww((short)0x51,(short)(montype)) +#define MultiMon(cmd) \ + (long)trap_14_ww((short)0x52,(short)(cmd)) +#define VSizeComp() \ + (long)trap_14_w((short)0x53) +#define Vsize(mode) \ + (long)trap_14_wl((short)0x54,(long)(mode)) + +/*--- Functions prototypes ---*/ + +int SDL_XBIOS_ListCentscreenModes(_THIS, int actually_add); +void SDL_XBIOS_CentscreenSetmode(_THIS, int width, int height, int planes); +void SDL_XBIOS_CentscreenRestore(_THIS, int prev_handle); + +#endif /* _SDL_xbios_centscreen_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c new file mode 100644 index 0000000..a99ee18 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.c @@ -0,0 +1,106 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Milan Xbios video functions + + Patrice Mandin +*/ + +#include <mint/cookie.h> +#include <mint/falcon.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_milan.h" + +#define NUM_PREDEFINED_MODES 7 + +typedef struct { + Uint16 width, height; +} predefined_mode_t; + +static const predefined_mode_t mode_list[NUM_PREDEFINED_MODES]={ + {640,400}, + {640,480}, + {800,608}, + {1024,768}, + {1152,864}, + {1280,1024}, + {1600,1200} +}; + +static const Uint8 mode_bpp[4]={ + 8, 15, 16, 32 +}; + +/*--- Variables ---*/ + +static int enum_actually_add; +static SDL_VideoDevice *enum_this; + +/*--- Functions ---*/ + +static unsigned long /*cdecl*/ enumfunc(SCREENINFO *inf, unsigned long flag) +{ + xbiosmode_t modeinfo; + + modeinfo.number = inf->devID; + modeinfo.width = inf->scrWidth; + modeinfo.height = inf->scrHeight; + modeinfo.depth = inf->scrPlanes; + modeinfo.flags = 0; + + SDL_XBIOS_AddMode(enum_this, enum_actually_add, &modeinfo); + + return ENUMMODE_CONT; +} + +void SDL_XBIOS_ListMilanModes(_THIS, int actually_add) +{ + int i; + + /* Read validated predefined modes */ + for (i=0; i<NUM_PREDEFINED_MODES; i++) { + int j; + Uint16 deviceid = 0x1000 + (i<<4); + + for (j=1; j<4; j++) { + if (Validmode(deviceid + j)) { + xbiosmode_t modeinfo; + + modeinfo.number = deviceid + j; + modeinfo.width = mode_list[i].width; + modeinfo.height = mode_list[i].height; + modeinfo.depth = mode_bpp[j-1]; + modeinfo.flags = 0; + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); + } + } + } + + /* Read custom created modes */ + enum_this = this; + enum_actually_add = actually_add; + VsetScreen(-1, &enumfunc, MI_MAGIC, CMD_ENUMMODES); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h new file mode 100644 index 0000000..bcf5c8a --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_milan.h @@ -0,0 +1,129 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Milan Xbios video functions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_milan_h +#define _SDL_xbios_milan_h + +#include "SDL_xbios.h" + +/*--- Defines ---*/ + +/* Vsetscreen() parameters */ +#define MI_MAGIC 0x4D49 + +enum { + CMD_GETMODE=0, + CMD_SETMODE, + CMD_GETINFO, + CMD_ALLOCPAGE, + CMD_FREEPAGE, + CMD_FLIPPAGE, + CMD_ALLOCMEM, + CMD_FREEMEM, + CMD_SETADR, + CMD_ENUMMODES +}; + +enum { + ENUMMODE_EXIT=0, + ENUMMODE_CONT +}; + +enum { + BLK_ERR=0, + BLK_OK, + BLK_CLEARED +}; + +/* scrFlags */ +#define SCRINFO_OK 1 + +/* scrClut */ +#define NO_CLUT 0 +#define HARD_CLUT 1 +#define SOFT_CLUT 2 + +/* scrFormat */ +#define INTERLEAVE_PLANES 0 +#define STANDARD_PLANES 1 +#define PACKEDPIX_PLANES 2 + +/* bitFlags */ +#define STANDARD_BITS 1 +#define FALCON_BITS 2 +#define INTEL_BITS 8 + +/*--- Structures ---*/ + +typedef struct _scrblk { + unsigned long size; /* size of strukture */ + unsigned long blk_status; /* status bits of blk */ + unsigned long blk_start; /* Start Adress */ + unsigned long blk_len; /* length of memblk */ + unsigned long blk_x; /* x pos in total screen*/ + unsigned long blk_y; /* y pos in total screen */ + unsigned long blk_w; /* width */ + unsigned long blk_h; /* height */ + unsigned long blk_wrap; /* width in bytes */ +} SCRMEMBLK; + +typedef struct screeninfo { + unsigned long size; /* Size of structure */ + unsigned long devID; /* device id number */ + unsigned char name[64]; /* Friendly name of Screen */ + unsigned long scrFlags; /* some Flags */ + unsigned long frameadr; /* Adress of framebuffer */ + unsigned long scrHeight; /* visible X res */ + unsigned long scrWidth; /* visible Y res */ + unsigned long virtHeight; /* virtual X res */ + unsigned long virtWidth; /* virtual Y res */ + unsigned long scrPlanes; /* color Planes */ + unsigned long scrColors; /* # of colors */ + unsigned long lineWrap; /* # of Bytes to next line */ + unsigned long planeWarp; /* # of Bytes to next plane */ + unsigned long scrFormat; /* screen Format */ + unsigned long scrClut; /* type of clut */ + unsigned long redBits; /* Mask of Red Bits */ + unsigned long greenBits; /* Mask of Green Bits */ + unsigned long blueBits; /* Mask of Blue Bits */ + unsigned long alphaBits; /* Mask of Alpha Bits */ + unsigned long genlockBits;/* Mask of Genlock Bits */ + unsigned long unusedBits; /* Mask of unused Bits */ + unsigned long bitFlags; /* Bits organisation flags */ + unsigned long maxmem; /* max. memory in this mode */ + unsigned long pagemem; /* needed memory for one page */ + unsigned long max_x; /* max. possible width */ + unsigned long max_y; /* max. possible heigth */ +} SCREENINFO; + +/*--- Functions prototypes ---*/ + +void SDL_XBIOS_ListMilanModes(_THIS, int actually_add); + +#endif /* _SDL_xbios_milan_h */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c new file mode 100644 index 0000000..8b0ed2c --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.c @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + ScreenBlaster 3 functions + + Patrice Mandin +*/ + +/*--- Includes ---*/ + +#include "SDL_stdinc.h" +#include "SDL_xbios.h" +#include "SDL_xbios_sb3.h" + +/*--- Defines ---*/ + +const int SDL_XBIOS_scpn_planes_device[]={ + SCPN_DEV_1BPP, + SCPN_DEV_4BPP, + SCPN_DEV_8BPP, + SCPN_DEV_16BPP, + SCPN_DEV_2BPP, + SCPN_DEV_4BPP, + SCPN_DEV_1BPP +}; + +/*--- Functions ---*/ + +int SDL_XBIOS_SB3Usable(scpn_cookie_t *cookie_scpn) +{ + scpn_screeninfo_t *scrinfo; + int bpp; + + /* Check if current SB3 mode is usable, i.e. 8 or 16bpp */ + scrinfo = cookie_scpn->screen_info; + bpp = 1<<(SDL_XBIOS_scpn_planes_device[scrinfo->device]); + + if ((bpp==8) || (bpp==16)) { + return 1; + } + + return 0; +} + +void SDL_XBIOS_ListSB3Modes(_THIS, int actually_add, scpn_cookie_t *cookie_scpn) +{ + scpn_screeninfo_t *scrinfo; + xbiosmode_t modeinfo; + + scrinfo = cookie_scpn->screen_info; + if (actually_add) { + scrinfo->h_pos = scrinfo->v_pos = 0; + } + + modeinfo.number = -1; + modeinfo.width = scrinfo->virtual_width; + modeinfo.height = scrinfo->virtual_height; + modeinfo.depth = 1<<(SDL_XBIOS_scpn_planes_device[scrinfo->device]); + modeinfo.flags = (modeinfo.depth == 8 ? XBIOSMODE_C2P : 0); + + SDL_XBIOS_AddMode(this, actually_add, &modeinfo); +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h new file mode 100644 index 0000000..3272c31 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_sb3.h @@ -0,0 +1,82 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + ScreenBlaster 3 definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_sb3_h_ +#define _SDL_xbios_sb3_h_ + +/*--- Defines ---*/ + +#ifndef C_SCPN +#define C_SCPN 0x5343504EL +#endif + +#define SCPN_DEV_1BPP 0 +#define SCPN_DEV_2BPP 1 +#define SCPN_DEV_4BPP 2 +#define SCPN_DEV_8BPP 3 +#define SCPN_DEV_16BPP 4 + +extern const int SDL_XBIOS_scpn_planes_device[]; + +/*--- Types ---*/ + +typedef struct { + unsigned short virtual_width; /* Virtual screen width */ + unsigned short virtual_height; /* Virtual screen height */ + unsigned short visible_width; /* Visible width */ + unsigned short visible_height; /* Visible height */ + unsigned short h_pos; /* Horizontal position in virtual screen */ + unsigned short v_pos; /* Vertical position in virtual screen */ + unsigned short dummy; + unsigned long size; /* Size of screen in bytes */ + unsigned short device; /* Device number to find planes = getRez() */ + /* = Index in scpn_planes_device[] */ +} scpn_screeninfo_t; + +typedef struct { + unsigned long magic; /* just a BRA assembler jump */ + unsigned short version; + void *dummy1; + unsigned short ptsout0_1; + unsigned short ptsout0_2; + unsigned short dummy3; + unsigned char date[8]; /* Date of program build */ + unsigned char asm_string[30]; /* 10 times the 'ASM' string */ + unsigned short dummy4; + scpn_screeninfo_t *screen_info; + unsigned short dummy6; +} scpn_cookie_t; + +/*--- Function prototypes ---*/ + +int SDL_XBIOS_SB3Usable(scpn_cookie_t *cookie_scpn); + +void SDL_XBIOS_ListSB3Modes(_THIS, int actually_add, scpn_cookie_t *cookie_scpn); + +#endif /* _SDL_xbios_sb3_h_ */ diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c new file mode 100644 index 0000000..b0f8499 --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.c @@ -0,0 +1,63 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Turbo veille screensaver + + Patrice Mandin +*/ + +#include <mint/cookie.h> + +#include "SDL_xbios.h" +#include "SDL_xbios_tveille.h" + +static tveille_t *cookie_veil = NULL; +static int status; + +int SDL_XBIOS_TveillePresent(_THIS) +{ + long dummy; + + cookie_veil = NULL; + if (Getcookie(C_VeiL, &dummy) == C_FOUND) { + cookie_veil = (tveille_t *) dummy; + } + + return (cookie_veil != NULL); +} + +void SDL_XBIOS_TveilleDisable(_THIS) +{ + if (cookie_veil) { + status = cookie_veil->enabled; + cookie_veil->enabled = 0xff; + } +} + +void SDL_XBIOS_TveilleEnable(_THIS) +{ + if (cookie_veil) { + cookie_veil->enabled = status; + } +} diff --git a/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h new file mode 100644 index 0000000..8a9cd7d --- /dev/null +++ b/3rdparty/SDL/src/video/xbios/SDL_xbios_tveille.h @@ -0,0 +1,64 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* + Turbo veille screensaver + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_tveille_h +#define _SDL_xbios_tveille_h + +#include "SDL_xbios.h" + +/*--- Structures ---*/ + +typedef struct { + unsigned long version; + void (*prg_ptr)(); + void (*kbd_ptr)(); + void (*vbl_ptr)(); + unsigned long vbl_count; + void (*oldkbd_ptr)(); + unsigned long off_count; + unsigned long prg_size; + unsigned long dummy1[4]; + unsigned char dummy2; + unsigned char status; + unsigned short freq; + unsigned short dummy3; + unsigned char clear_first; + unsigned char enabled; /* 0=enabled, 0xff=disabled */ + unsigned char serial_redir; + unsigned char dummy4; + void (*oldserial_ptr)(); +} tveille_t; + +/*--- Functions prototypes ---*/ + +int SDL_XBIOS_TveillePresent(_THIS); +void SDL_XBIOS_TveilleDisable(_THIS); +void SDL_XBIOS_TveilleEnable(_THIS); + +#endif /* _SDL_xbios_tveille_h */ |