diff --git a/CMakeLists.txt b/CMakeLists.txt index 358f32f3afd98..95400595bf954 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,6 +131,9 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*") message_error("BeOS support has been removed as of SDL 2.0.2.") elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*") set(HAIKU TRUE) +elseif(CMAKE_SYSTEM_NAME MATCHES "Amiga.*") + set(AMIGA TRUE) + message("*** AmigaOS 4 build ***") endif() # Don't mistake osx for unix @@ -153,12 +156,15 @@ endif() # for the time being. This default with change to ON once this becomes # commonly supported in browsers or the Emscripten teams makes a single # binary work everywhere. -if (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN) +if (AMIGA OR (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN)) set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON) else() set(SDL_PTHREADS_ENABLED_BY_DEFAULT OFF) endif() +if(UNIX OR MINGW OR MSYS OR AMIGA) + set(OPT_DEF_LIBC ON) +endif() # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers, # so we'll just use libusb when it's available. libusb does not support iOS, # so we default to yes on iOS. @@ -297,6 +303,7 @@ if(EMSCRIPTEN) set(OPT_DEF_ASM FALSE) set(SDL_SHARED_ENABLED_BY_DEFAULT OFF) set(SDL_ATOMIC_ENABLED_BY_DEFAULT OFF) + set(SDL_THREADS_ENABLED_BY_DEFAULT OFF) set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF) set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF) set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF) @@ -552,6 +559,12 @@ if(USE_GCC OR USE_CLANG) endif() endif() +if(AMIGA) + # Disable Altivec for now. It gives problem for people without it. + message("Disabling Altivec...") + set(ALTIVEC FALSE) +endif() + if(ASSEMBLY) if(USE_GCC OR USE_CLANG) set(SDL_ASSEMBLY_ROUTINES 1) @@ -864,13 +877,15 @@ if(LIBC) endif() endif() - check_library_exists(iconv iconv_open "" HAVE_LIBICONV) - check_library_exists(c iconv_open "" HAVE_BUILTIN_ICONV) - if(HAVE_BUILTIN_ICONV) - set(HAVE_ICONV 1) - elseif(HAVE_LIBICONV) - list(APPEND EXTRA_LIBS iconv) - set(HAVE_ICONV 1) + if(NOT AMIGA) # we don't have libiconv + check_library_exists(iconv iconv_open "" HAVE_LIBICONV) + check_library_exists(c iconv_open "" HAVE_BUILTIN_ICONV) + if(HAVE_BUILTIN_ICONV) + set(HAVE_ICONV 1) + elseif(HAVE_LIBICONV) + list(APPEND EXTRA_LIBS iconv) + set(HAVE_ICONV 1) + endif() endif() if(NOT APPLE) @@ -2029,141 +2044,84 @@ elseif(HAIKU) CheckPTHREAD() -elseif(RISCOS) - file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${MISC_SOURCES}) - set(HAVE_SDL_MISC TRUE) +elseif(AMIGA) + message("AmigaOS 4 specific stuff") - if(SDL_TIMERS) - set(SDL_TIMER_UNIX 1) - file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES}) - set(HAVE_SDL_TIMERS TRUE) + if(SDL_VIDEO) + set(SDL_VIDEO_DRIVER_AMIGAOS4 1) + file(GLOB AMIGAOS4VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/amigaos4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${AMIGAOS4VIDEO_SOURCES}) + set(HAVE_SDL_VIDEO TRUE) - if(CLOCK_GETTIME) - set(HAVE_CLOCK_GETTIME 1) + set(SDL_VIDEO_RENDER_AMIGAOS4 1) + + if(VIDEO_OPENGL) + set(SDL_VIDEO_RENDER_OGL 1) # MiniGL should be there + set(SDL_VIDEO_OPENGL 1) + set(HAVE_VIDEO_OPENGL TRUE) endif() - endif() - CheckPTHREAD() + CheckOpenGLES2() + endif() if(SDL_AUDIO) - CheckOSS() - endif() -elseif(VITA) - # SDL_spinlock.c Needs to be compiled in ARM mode. - check_c_compiler_flag(-marm HAVE_ARM_MODE) - if(HAVE_ARM_MODE) - set_source_files_properties(${SDL2_SOURCE_DIR}/src/atomic/SDL_spinlock.c PROPERTIES COMPILE_FLAGS -marm) + set(SDL_AUDIO_DRIVER_AMIGAOS4 1) + file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/amigaos4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${AUDIO_SOURCES}) + set(HAVE_SDL_AUDIO TRUE) endif() - file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${MISC_SOURCES}) - set(HAVE_SDL_MISC TRUE) + if(SDL_TIMERS) + set(SDL_TIMER_UNIX 1) + file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES}) + set(HAVE_SDL_TIMERS TRUE) + endif(SDL_TIMERS) - if(SDL_AUDIO) - set(SDL_AUDIO_DRIVER_VITA 1) - file(GLOB VITA_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_AUDIO_SOURCES}) - set(HAVE_SDL_AUDIO TRUE) + if(SDL_LOADSO) + set(SDL_LOADSO_AMIGAOS4 1) + file(GLOB LOADSO_SOURCES ${SDL2_SOURCE_DIR}/src/loadso/amigaos4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${LOADSO_SOURCES}) + set(HAVE_SDL_LOADSO TRUE) endif() + if(SDL_FILESYSTEM) - set(SDL_FILESYSTEM_VITA 1) - file(GLOB VITA_FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_FILESYSTEM_SOURCES}) + set(SDL_FILESYSTEM_AMIGAOS4 1) + file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/amigaos4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${FILESYSTEM_SOURCES}) set(HAVE_SDL_FILESYSTEM TRUE) endif() + if(SDL_JOYSTICK) - set(SDL_JOYSTICK_VITA 1) - file(GLOB VITA_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_JOYSTICK_SOURCES}) + set(SDL_JOYSTICK_AMIGAINPUT 1) # TODO: rename? + file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/amigaos4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES}) set(HAVE_SDL_JOYSTICK TRUE) endif() - if(SDL_POWER) - set(SDL_POWER_VITA 1) - file(GLOB VITA_POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_POWER_SOURCES}) - set(HAVE_SDL_POWER TRUE) - endif() - if(SDL_THREADS) - set(SDL_THREAD_VITA 1) - set(SOURCE_FILES ${SOURCE_FILES} - ${SDL2_SOURCE_DIR}/src/thread/vita/SDL_sysmutex.c - ${SDL2_SOURCE_DIR}/src/thread/vita/SDL_syssem.c - ${SDL2_SOURCE_DIR}/src/thread/vita/SDL_systhread.c - ${SDL2_SOURCE_DIR}/src/thread/vita/SDL_syscond.c - ${SDL2_SOURCE_DIR}/src/thread/generic/SDL_systls.c) - set(HAVE_SDL_THREADS TRUE) - endif() - if(SDL_TIMERS) - set(SDL_TIMER_VITA 1) - file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES}) - set(HAVE_SDL_TIMERS TRUE) - endif() - if(SDL_SENSOR) - set(SDL_SENSOR_VITA 1) - set(HAVE_SDL_SENSORS TRUE) - file(GLOB VITA_SENSOR_SOURCES ${SDL2_SOURCE_DIR}/src/sensor/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_SENSOR_SOURCES}) - endif() - if(SDL_VIDEO) - set(SDL_VIDEO_DRIVER_VITA 1) - file(GLOB VITA_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/vita/*.c) - set(SOURCE_FILES ${SOURCE_FILES} ${VITA_VIDEO_SOURCES}) - set(HAVE_SDL_VIDEO TRUE) - check_include_file(pib.h HAVE_PIGS_IN_BLANKET_H) + CheckPTHREAD() +elseif(RISCOS) + file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${MISC_SOURCES}) + set(HAVE_SDL_MISC TRUE) - if(HAVE_PIGS_IN_BLANKET_H) - set(SDL_VIDEO_OPENGL_ES2 1) - list(APPEND EXTRA_LIBS - pib - ) + if(SDL_TIMERS) + set(SDL_TIMER_UNIX 1) + file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES}) + set(HAVE_SDL_TIMERS TRUE) + if(CLOCK_GETTIME) + set(HAVE_CLOCK_GETTIME 1) endif() - set(SDL_VIDEO_RENDER_VITA_GXM 1) - - list(APPEND EXTRA_LIBS - SceGxm_stub - SceDisplay_stub - SceCtrl_stub - SceAppMgr_stub - SceAudio_stub - SceSysmodule_stub - SceDisplay_stub - SceCtrl_stub - SceIofilemgr_stub - SceCommonDialog_stub - SceTouch_stub - SceHid_stub - SceMotion_stub - m - ) endif() - set(HAVE_ARMSIMD TRUE) - set(SDL_ARM_SIMD_BLITTERS 1) - file(GLOB ARMSIMD_SOURCES ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-simd*.S) - set(SOURCE_FILES ${SOURCE_FILES} ${ARMSIMD_SOURCES}) - - set(HAVE_ARMNEON TRUE) - set(SDL_ARM_NEON_BLITTERS 1) - file(GLOB ARMNEON_SOURCES ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-neon*.S) - set(SOURCE_FILES ${SOURCE_FILES} ${ARMNEON_SOURCES}) - - set_property(SOURCE ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-simd-asm.S PROPERTY LANGUAGE C) - set_property(SOURCE ${SDL2_SOURCE_DIR}/src/video/arm/pixman-arm-neon-asm.S PROPERTY LANGUAGE C) - - add_definitions("-D__VITA__") - add_definitions("-Dmemcpy=sceClibMemcpy") - add_definitions("-Dmemset=sceClibMemset") - add_definitions("-Dmemmove=sceClibMemmove") - add_definitions("-Dmemcmp=sceClibMemcmp") - -# CheckPTHREAD() + CheckPTHREAD() + if(SDL_AUDIO) + CheckOSS() + endif() endif() if(VIDEO_VULKAN) @@ -2263,9 +2221,7 @@ if(NOT CMAKE_HOST_WIN32) WORKING_DIRECTORY ${SDL2_BINARY_DIR}) endif() if(NOT WINDOWS OR CYGWIN) - set(prefix ${CMAKE_INSTALL_PREFIX}) - set(exec_prefix "\${prefix}") set(libdir "\${exec_prefix}/lib${LIB_SUFFIX}") set(bindir "\${exec_prefix}/bin") @@ -2278,12 +2234,12 @@ if(NOT WINDOWS OR CYGWIN) set(ENABLE_STATIC_FALSE "") endif() if(SDL_SHARED) - set(PKGCONFIG_LIBS_PRIV " + set(PKG_CONFIG_LIBS_PRIV " Libs.private:") set(ENABLE_SHARED_TRUE "") set(ENABLE_SHARED_FALSE "#") else() - set(PKGCONFIG_LIBS_PRIV "") + set(PKG_CONFIG_LIBS_PRIV "") set(ENABLE_SHARED_TRUE "#") set(ENABLE_SHARED_FALSE "") endif() diff --git a/Makefile.amigaos4 b/Makefile.amigaos4 new file mode 100644 index 0000000000000..754d92ffc8d6f --- /dev/null +++ b/Makefile.amigaos4 @@ -0,0 +1,85 @@ +# Makefile to build the AmigaOS4 SDL library + +AR = ppc-amigaos-ar +RANLIB = ppc-amigaos-ranlib +CC = ppc-amigaos-gcc +CXX = ppc-amigaos-g++ +STRIP = ppc-amigaos-strip + +AMIGADATE = $(shell date +"%-d.%-m.%Y") + +CFLAGS = -gstabs -O2 -Wall -fPIC -fcommon -I./include -D__AMIGADATE__=\"$(AMIGADATE)\" + +TARGET_STATIC = libSDL2.a +TARGET_SHARED = libSDL2-2.0.so +TESTLIB_STATIC = libSDL2_test.a + +SOURCES = \ + ./src/*.c \ + ./src/atomic/*.c \ + ./src/audio/*.c \ + ./src/audio/amigaos4/*.c \ + ./src/audio/dummy/*.c \ + ./src/cpuinfo/*.c \ + ./src/events/*.c \ + ./src/file/*.c \ + ./src/filesystem/amigaos4/*.c \ + ./src/haptic/*.c \ + ./src/haptic/dummy/*.c \ + ./src/joystick/*.c \ + ./src/joystick/amigaos4/*.c \ + ./src/loadso/amigaos4/*.c \ + ./src/misc/*.c \ + ./src/misc/amigaos4/*.c \ + ./src/render/*.c \ + ./src/power/*.c \ + ./src/render/amigaos4/*.c \ + ./src/render/opengl/*.c \ + ./src/render/opengles2/*.c \ + ./src/render/software/*.c \ + ./src/sensor/*.c \ + ./src/sensor/dummy/*.c \ + ./src/stdlib/*.c \ + ./src/thread/*.c \ + ./src/thread/amigaos4/*.c \ + ./src/thread/generic/SDL_syscond.c \ + ./src/thread/generic/SDL_systls.c \ + ./src/timer/*.c \ + ./src/timer/amigaos4/*.c \ + ./src/video/*.c \ + ./src/video/dummy/*.c \ + ./src/video/amigaos4/*.c \ + ./src/video/yuv2rgb/*.c \ + +TESTLIB_SOURCES =./src/test/*.c + +OBJECTS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g') +TESTLIB_OBJECTS = $(shell echo $(TESTLIB_SOURCES) | sed -e 's,\.c,\.o,g') +VERSION_OBJECT = src/main/amigaos4/SDL_os4version.o + +all: config_copy $(TARGET_STATIC) $(TARGET_SHARED) $(TESTLIB_STATIC) + +$(TESTLIB_STATIC): $(TESTLIB_OBJECTS) + $(AR) crv $@ $^ + $(RANLIB) $@ + +$(TARGET_STATIC): $(OBJECTS) + $(AR) crv $@ $^ + $(RANLIB) $@ + +$(TARGET_SHARED): $(OBJECTS) $(VERSION_OBJECT) + $(CC) -shared -Wl,-soname,$(TARGET_SHARED) -o $(TARGET_SHARED) $(OBJECTS) $(VERSION_OBJECT) + +config_copy: + cp include/SDL_config_amigaos4.h include/SDL_config.h + +clean: + rm -f $(TARGET_STATIC) $(TARGET_SHARED)* $(TESTLIB_STATIC) $(OBJECTS) + +install: + mkdir -p /SDK/local/newlib/lib + mkdir -p /SDK/local/newlib/include/SDL2 + cp -f $(TARGET_STATIC) /SDK/local/newlib/lib + cp -f $(TARGET_SHARED) /SDK/local/newlib/lib + cp -f $(TESTLIB_STATIC) /SDK/local/newlib/lib + cp -f include/*.h /SDK/local/newlib/include/SDL2/ diff --git a/amiga-extra/Install b/amiga-extra/Install new file mode 100755 index 0000000000000..f946b97397523 --- /dev/null +++ b/amiga-extra/Install @@ -0,0 +1,28 @@ +failat 21 + +echo Copying shared object ... +copy SDK/local/newlib/lib/libSDL2-2.0.so SObjs: +copy SDK/local/newlib/lib/libSDL2-2.0_debug.so SObjs: + +set option `RequestChoice "One more question..." "Would you like to install the SDK?" "Yes, please" "No, thanks"` + +If $option eq 1 + echo Copying SDK files ... + copy SDK/#? SDK: all + + protect SDK:local/newlib/bin/sdl2-config +rweds + + cd SDK:local/newlib/lib + makelink from=libSDL2.so to=libSDL2-2.0.so soft +Else + echo Skipped SDK installation ... +EndIf + +echo Setting up link ... + +cd SObjs: +makelink >NIL: from=libSDL2.so to=libSDL2-2.0.so soft + +echo SDL2 is installed :) + +Wait 5 diff --git a/amiga-extra/Install.info b/amiga-extra/Install.info new file mode 100644 index 0000000000000..32b78ba62b48c Binary files /dev/null and b/amiga-extra/Install.info differ diff --git a/configure b/configure index 80a528f94a4c8..37a5a42dca669 100755 --- a/configure +++ b/configure @@ -21791,6 +21791,20 @@ $as_echo "#define SDL_VIDEO_DRIVER_HAIKU 1" >>confdefs.h fi } +CheckAmigaOS4Video() +{ + if test x$enable_video = xyes; then + +$as_echo "#define SDL_VIDEO_DRIVER_AMIGAOS4 1" >>confdefs.h +$as_echo "#define SDL_VIDEO_RENDER_AMIGAOS4 1" >> confdefs.h + + SOURCES="$SOURCES $srcdir/src/video/amigaos4/*.c" + + have_video=yes + SUMMARY_video="${SUMMARY_video} amigaos4" + fi +} + CheckCOCOA() { # Check whether --enable-video-cocoa was given. @@ -22633,6 +22647,66 @@ $as_echo "#define SDL_VIDEO_RENDER_OGL 1" >>confdefs.h fi } +CheckAmigaOS4GL() +{ + if test x$enable_video = xyes -a x$enable_video_opengl = xyes; then + +$as_echo "#define SDL_VIDEO_OPENGL 1" >>confdefs.h + + +$as_echo "#define SDL_VIDEO_OPENGL_AMIGAOS4 1" >>confdefs.h + + +$as_echo "#define SDL_VIDEO_RENDER_OGL 1" >>confdefs.h + +# EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lGL -lGLU" + + SUMMARY_video="${SUMMARY_video} opengl" + fi +} + +CheckAmigaOS4GLES2() +{ + if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenGL ES v2 headers" >&5 +$as_echo_n "checking for OpenGL ES v2 headers... " >&6; } + video_opengles_v2=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #include + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + video_opengles_v2=yes + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_opengles_v2" >&5 +$as_echo "$video_opengles_v2" >&6; } + if test x$video_opengles_v2 = xyes; then + +$as_echo "#define SDL_VIDEO_OPENGL_ES2 1" >>confdefs.h + + +$as_echo "#define SDL_VIDEO_RENDER_OGL_ES2 1" >>confdefs.h + + SUMMARY_video="${SUMMARY_video} opengl_es2" + fi + fi +} + CheckMacGL() { if test x$enable_video = xyes -a x$enable_video_opengl = xyes; then @@ -25444,6 +25518,82 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h SOURCES="$srcdir/src/main/haiku/*.cc $SOURCES" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lroot -lbe -lmedia -lgame -ldevice -ltextencoding" ;; + + *-*-amigaos*) + ARCH=amigaos4 + ac_default_prefix=/progdir + CheckDummyVideo + CheckDummyAudio + CheckAmigaOS4Video + CheckAmigaOS4GL + CheckAmigaOS4GLES2 + #CheckDLOPEN + CheckPTHREAD + + # Set up files for the thread library +# if test x$enable_threads = xyes; then +# +#$as_echo "#define SDL_THREAD_AMIGAOS4 1" >>confdefs.h +# +# SOURCES="$SOURCES $srcdir/src/thread/amigaos4/*.c" +# have_threads=yes +# fi + # Set up files for the audio library + if test x$enable_audio = xyes; then + SUMMARY_audio="${SUMMARY_audio} amigaos4" +$as_echo "#define SDL_AUDIO_DRIVER_AMIGAOS4 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/audio/amigaos4/*.c" + have_audio=yes + fi + # Set up files for the joystick library + if test x$enable_joystick = xyes; then + +$as_echo "#define SDL_JOYSTICK_AMIGAINPUT 1" >>confdefs.h + SUMMARY_input="${SUMMARY_input} amigainput" + SOURCES="$SOURCES $srcdir/src/joystick/amigaos4/*.c" + have_joystick=yes + fi + # Set up files for the timer library +# if test x$enable_timers = xyes; then +# +#$as_echo "#define SDL_TIMER_AMIGAOS4 1" >>confdefs.h +# +# SOURCES="$SOURCES $srcdir/src/timer/amigaos4/*.c" +# have_timers=yes +# fi + if test x$enable_timers = xyes; then + +$as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/timer/unix/*.c" + have_timers=yes + fi + # Set up files for the system filesystem library + if test x$enable_filesystem = xyes; then + +$as_echo "#define SDL_FILESYSTEM_AMIGAOS4 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/filesystem/amigaos4/*.c" + have_filesystem=yes + fi + + # Set up files for the shared object loading library + if test x$enable_loadso = xyes; then + +$as_echo "#define SDL_LOADSO_AMIGAOS4 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/loadso/amigaos4/*.c" + have_loadso=yes + fi + + # The AmigaOS4 platform requires special setup. + SOURCES="$srcdir/src/main/amigaos4/*.c $SOURCES" + #EXTRA_LDFLAGS="-use-dynld -Wl,-export-dynamic -Wl,-no-undefined $EXTRA_LDFLAGS -ldl" + EXTRA_LDFLAGS="-lpthread" + + EXTRA_CFLAGS="$EXTRA_CFLAGS -mstrict-align" + ;; *-ios-*) ARCH=ios @@ -25984,9 +26134,8 @@ fi SDL_STATIC_LIBS="$EXTRA_LDFLAGS" - - - +# AmigaOS4 hack! This is only to pass "-use-dynld" for sdl2-config +SDL_LIBS="-use-dynld $SDL_LIBS $EXTRA_LDFLAGS" if test x$enable_shared = xyes; then PKGCONFIG_LIBS_PRIV=" diff --git a/configure.ac b/configure.ac index 6ec90c4a87557..3722f355ac12c 100644 --- a/configure.ac +++ b/configure.ac @@ -2075,6 +2075,18 @@ CheckHaikuVideo() fi } +dnl Set up the AmigaOS video driver if enabled +CheckAmigaOS4Video() +{ + if test x$enable_video = xyes; then + AC_DEFINE(SDL_VIDEO_DRIVER_AMIGAOS4, 1, [ ]) + AC_DEFINE(SDL_VIDEO_RENDER_AMIGAOS4, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/video/amigaos4/*.c" + have_video=yes + SUMMARY_video="${SUMMARY_video} amigaos4" + fi +} + dnl Set up the Cocoa video driver for Mac OS X (but not Darwin) CheckCOCOA() { @@ -2447,6 +2459,40 @@ CheckHaikuGL() fi } +dnl Check for AmigaOS4 OpenGL +CheckAmigaOS4GL() +{ + if test x$enable_video = xyes -a x$enable_video_opengl = xyes; then + AC_DEFINE(SDL_VIDEO_OPENGL, 1, [ ]) + AC_DEFINE(SDL_VIDEO_OPENGL_AMIGAOS4, 1, [ ]) + AC_DEFINE(SDL_VIDEO_RENDER_OGL, 1, [ ]) + #EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lGL -lGLU" + SUMMARY_video="${SUMMARY_video} opengl" + fi +} + +CheckAmigaOS4GLES() +{ + if test x$enable_video = xyes -a x$enable_video_opengles = xyes; then + AC_MSG_CHECKING(for OpenGL ES v2 headers) + video_opengles_v2=no + AC_TRY_COMPILE([ + #include + #include + #include + ],[ + ],[ + video_opengles_v2=yes + ]) + AC_MSG_RESULT($video_opengles_v2) + if test x$video_opengles_v2 = xyes; then + AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ]) + AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ]) + SUMMARY_video="${SUMMARY_video} opengl_es2" + fi + fi +} + dnl Check for MacOS OpenGL CheckMacGL() { @@ -3948,6 +3994,66 @@ case "$host" in SOURCES="$srcdir/src/main/haiku/*.cc $SOURCES" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lroot -lbe -lmedia -lgame -ldevice -ltextencoding" ;; + *-*-amigaos*) + ARCH=amigaos4 + ac_default_prefix=/progdir + CheckDummyVideo + CheckDummyAudio + CheckAmigaOS4Video + CheckAmigaOS4GL + CheckAmigaOS4GLES + #CheckDLOPEN + CheckPTHREAD + + # Set up files for the thread library +# if test x$enable_threads = xyes; then +# AC_DEFINE(SDL_THREAD_AMIGAOS4, 1, [ ]) +# SOURCES="$SOURCES $srcdir/src/thread/amigaos4/*.c" +# have_threads=yes +# fi + # Set up files for the audio library + if test x$enable_audio = xyes; then + SUMMARY_audio="${SUMMARY_audio} amigaos4" + AC_DEFINE(SDL_AUDIO_DRIVER_AMIGAOS4, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/audio/amigaos4/*.c" + have_audio=yes + fi + # Set up files for the joystick library + if test x$enable_joystick = xyes; then + SUMMARY_input="${SUMMARY_input} amigainput" + AC_DEFINE(SDL_JOYSTICK_AMIGAINPUT, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/joystick/amigaos4/*.c" + have_joystick=yes + fi + # Set up files for the timer library +# if test x$enable_timers = xyes; then +# AC_DEFINE(SDL_TIMER_AMIGAOS4, 1, [ ]) +# SOURCES="$SOURCES $srcdir/src/timer/amigaos4/*.c" +# have_timers=yes +# fi + if test x$enable_timers = xyes; then + AC_DEFINE(SDL_TIMER_UNIX, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/timer/unix/*.c" + have_timers=yes + fi + # Set up files for the system filesystem library + if test x$enable_filesystem = xyes; then + AC_DEFINE(SDL_FILESYSTEM_AMIGAOS4, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/filesystem/amigaos4/*.c" + have_filesystem=yes + fi + # Set up files for the shared object loading library + if test x$enable_loadso = xyes; then + AC_DEFINE(SDL_LOADSO_AMIGAOS4, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/loadso/amigaos4/*.c" + have_loadso=yes + fi + # The AmigaOS4 platform requires special setup. + SOURCES="$srcdir/src/main/amigaos4/*.c $SOURCES" + #EXTRA_LDFLAGS="-use-dynld -Wl,-export-dynamic -Wl,-no-undefined $EXTRA_LDFLAGS -ldl" + EXTRA_LDFLAGS="" + EXTRA_CFLAGS="$EXTRA_CFLAGS -mstrict-align" + ;; *-ios-*) ARCH=ios @@ -4398,6 +4504,9 @@ fi SDL_STATIC_LIBS="$EXTRA_LDFLAGS" +# AmigaOS4 hack! This is only to pass "-use-dynld" for sdl2-config +SDL_LIBS="-use-dynld $SDL_LIBS" + dnl Expand the cflags and libraries needed by apps using SDL AC_SUBST(SDL_CFLAGS) AC_SUBST(SDL_LIBS) diff --git a/docs/README-amigaos4.md b/docs/README-amigaos4.md new file mode 100755 index 0000000000000..d39d668433880 --- /dev/null +++ b/docs/README-amigaos4.md @@ -0,0 +1,174 @@ +================================================================================ +SDL 2.0 requirements +================================================================================ + +AmigaOS 4.1 Final Edition +MiniGL (optional from SDL2 point of view, but OpenGL context might still be + required by the SDL2 application) +OpenGL ES 2.0 (optional) + +================================================================================ +Building SDL 2.0 library +================================================================================ + + gmake -f Makefile.amigaos4 + + At the moment configure script and CMake are not supported. + +================================================================================ +Using SDL 2.0 in your projects +================================================================================ + + #include "SDL2/SDL.h" + ...do magical SDL2 things... + + + gcc helloworld.c -use-dynld -lSDL2 + +================================================================================ +About SDL_Renderers +================================================================================ + +A renderer is a subsystem that can do 2D drawing. There are 4 renderers: +software, OpenGL, OpenGL ES 2.0 and compositing. + +Software renderer is always available. Pixels are plotted by the CPU so this is +usually a slow option. + +OpenGL renderer uses MiniGL (and Warp3D) for accelerated drawing. Drawing is +done in immediate mode. This should be fairly fast if textures are static. + +OpenGL ES 2.0 renderer uses ogles2.library (and Warp3D Nova). + +Compositing renderer uses AmigaOS 4 graphics.library for accelerated drawing. +However, blended lines and points are not accelerated since compositing doesn't +support them. Compositing renderer supports only 32-bit bitmaps. If (Workbench) +screen mode is 16-bit, color format conversion can slow things down. + +It's possible to select the preferred renderer before its creation, like this: + + SDL_SetHint(SDL_HINT_RENDER_DRIVER, name); + +where name is "software", "opengl" or "compositing". + +It's possible to enable VSYNC with: + + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); + +There is a benchmark tool called sdl2benchmark which was written to test +available renderers. + +================================================================================ +About ENV variables +================================================================================ + +Advanced users may use ENV variables to control some things in SDL2. +Some variables supported by the SDL_Renderer subsystem: + +Batch drawing: + +setenv SDL_RENDER_BATCHING 1 # Enable +setenv SDL_RENDER_BATCHING 0 # Disable + +Driver selection: + +setenv SDL_RENDER_DRIVER "software" +setenv SDL_RENDER_DRIVER "compositing" +setenv SDL_RENDER_DRIVER "opengl" + +VSYNC: + +setenv SDL_RENDER_VSYNC 1 # Enable +setenv SDL_RENDER_VSYNC 0 # Disable + +It must be noted that these variables apply only to those applications that +actually use the SDL_Renderer subsystem, and not 3D games. + +================================================================================ +About OpenGL +================================================================================ + +If you want to draw accelerated 3D graphics or use explicitly OpenGL functions, +you have to create an OpenGL context, instead of an SDL_Renderer. + +If you would like to create an OpenGL ES 2.0 context, you need to specify the +version before window creation, for example: + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + +MiniGL context can be created using major version 1 and minor version 3. This is +also the default setup. + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + +================================================================================ +About Joysticks +================================================================================ + +Joysticks that are compatible with AmigaInput can be used with SDL2. In addition +to legacy joystick API, SDL supports new game controller API which uses a +predefined database to map joystick axes and buttons. At the moment +game controller database contains the following entries: + +- Speedlink Competition Pro +- Ewent Joypad EW3170 +- PS2 Joystick (USB adaptor) +- SHARK 91230 Joystick +- MAGIC-NS +- Wireless Controller +- 8Bitdo SN30 Pro +- Thrustmaster dual analog 3.2 +- XEOX Gamepad SL-6556-BK +- Strike2 Joystick +- GeeekPi_A gamepad +- Logitech Cordless RumblePad 2 +- Logitech RumblePad 2 USB +- Logitech(R) Precision(TM) Gamepad + +Joysticks can be tested using testjoystick tool. New game controller mappings +can be generated using controllermap tool. New mappings can be then added to +the game controller database. + +================================================================================ +WinUAE +================================================================================ + +Because WinUAE doesn't support hardware-accelerated compositing or 3D, you need +to install the following software: + +- http://os4depot.net/index.php?function=showfile&file=graphics/misc/patchcompositetags.lha +- http://os4depot.net/index.php?function=showfile&file=library/graphics/wazp3d.lha + +================================================================================ +Tips +================================================================================ + +If you are already familiar with SDL 1.2, or porting SDL 1.2 code, it's worth +checking the migration guide at: + +https://wiki.libsdl.org/MigrationGuide + +Always check the return values of functions and in error case you can get more +information using SDL_GetError() function! + +================================================================================ +Limitations +================================================================================ + +Altivec support is disabled. It should be possible to enable in private builds +but it hasn't been tested so far. + +Unsupported subsystems include Haptic and Power. There is no Vulkan backend for +AmigaOS either. + +OpenGL renderer doesn't support render targets and blend modes "ADD" or "MOD". +This is due to missing features in MiniGL. + +================================================================================ +Project page and bug tracker +================================================================================ + +https://github.com/AmigaPorts/SDL diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 0446547e0e497..f097f8e17e447 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -268,6 +268,7 @@ #cmakedefine SDL_AUDIO_DRIVER_AAUDIO @SDL_AUDIO_DRIVER_AAUDIO@ #cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@ #cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@ +#cmakedefine SDL_AUDIO_DRIVER_AMIGAOS4 @SDL_AUDIO_DRIVER_AMIGAOS4@ #cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@ #cmakedefine SDL_AUDIO_DRIVER_DISK @SDL_AUDIO_DRIVER_DISK@ #cmakedefine SDL_AUDIO_DRIVER_DSOUND @SDL_AUDIO_DRIVER_DSOUND@ @@ -304,6 +305,7 @@ #cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@ #cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@ #cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@ +#cmakedefine SDL_JOYSTICK_AMIGAINPUT @SDL_JOYSTICK_AMIGAINPUT@ #cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@ #cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@ #cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@ @@ -338,6 +340,7 @@ #cmakedefine SDL_LOADSO_DUMMY @SDL_LOADSO_DUMMY@ #cmakedefine SDL_LOADSO_LDG @SDL_LOADSO_LDG@ #cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@ +#cmakedefine SDL_LOADSO_AMIGAOS4 @SDL_LOADSO_AMIGAOS4@ #cmakedefine SDL_LOADSO_OS2 @SDL_LOADSO_OS2@ /* Enable various threading systems */ @@ -346,6 +349,7 @@ #cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@ #cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@ #cmakedefine SDL_THREAD_WINDOWS @SDL_THREAD_WINDOWS@ +#cmakedefine SDL_THREAD_AMIGAOS4 @SDL_THREAD_AMIGAOS4@ #cmakedefine SDL_THREAD_OS2 @SDL_THREAD_OS2@ #cmakedefine SDL_THREAD_VITA @SDL_THREAD_VITA@ @@ -354,6 +358,7 @@ #cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@ #cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@ #cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@ +#cmakedefine SDL_TIMER_AMIGAOS4 @SDL_TIMER_AMIGAOS4@ #cmakedefine SDL_TIMER_OS2 @SDL_TIMER_OS2@ #cmakedefine SDL_TIMER_VITA @SDL_TIMER_VITA@ @@ -361,6 +366,7 @@ #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@ #cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@ #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@ +#cmakedefine SDL_VIDEO_DRIVER_AMIGAOS4 @SDL_VIDEO_DRIVER_AMIGAOS4@ #cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@ #cmakedefine SDL_VIDEO_DRIVER_UIKIT @SDL_VIDEO_DRIVER_UIKIT@ #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@ @@ -417,6 +423,7 @@ #cmakedefine SDL_VIDEO_RENDER_DIRECTFB @SDL_VIDEO_RENDER_DIRECTFB@ #cmakedefine SDL_VIDEO_RENDER_METAL @SDL_VIDEO_RENDER_METAL@ #cmakedefine SDL_VIDEO_RENDER_VITA_GXM @SDL_VIDEO_RENDER_VITA_GXM@ +#cmakedefine SDL_VIDEO_RENDER_AMIGAOS4 @SDL_VIDEO_RENDER_AMIGAOS4@ /* Enable OpenGL support */ #cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@ @@ -455,6 +462,7 @@ #cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@ #cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@ #cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@ +#cmakedefine SDL_FILESYSTEM_AMIGAOS4 @SDL_FILESYSTEM_AMIGAOS4@ #cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@ #cmakedefine SDL_FILESYSTEM_OS2 @SDL_FILESYSTEM_OS2@ #cmakedefine SDL_FILESYSTEM_VITA @SDL_FILESYSTEM_VITA@ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 9ddd932e3779f..b2d3c92107fcb 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -265,6 +265,7 @@ #undef SDL_AUDIO_DRIVER_ANDROID #undef SDL_AUDIO_DRIVER_ARTS #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC +#undef SDL_AUDIO_DRIVER_AMIGAOS4 #undef SDL_AUDIO_DRIVER_COREAUDIO #undef SDL_AUDIO_DRIVER_DISK #undef SDL_AUDIO_DRIVER_DSOUND @@ -302,6 +303,7 @@ #undef SDL_INPUT_LINUXKD #undef SDL_INPUT_WSCONS #undef SDL_JOYSTICK_HAIKU +#undef SDL_JOYSTICK_AMIGAINPUT #undef SDL_JOYSTICK_DINPUT #undef SDL_JOYSTICK_XINPUT #undef SDL_JOYSTICK_DUMMY @@ -335,6 +337,7 @@ #undef SDL_LOADSO_DUMMY #undef SDL_LOADSO_LDG #undef SDL_LOADSO_WINDOWS +#undef SDL_LOADSO_AMIGAOS4 #undef SDL_LOADSO_OS2 /* Enable various threading systems */ @@ -343,10 +346,12 @@ #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP #undef SDL_THREAD_WINDOWS +#undef SDL_THREAD_AMIGAOS4 #undef SDL_THREAD_OS2 /* Enable various timer systems */ #undef SDL_TIMER_HAIKU +#undef SDL_TIMER_AMIGAOS4 #undef SDL_TIMER_DUMMY #undef SDL_TIMER_UNIX #undef SDL_TIMER_WINDOWS @@ -354,6 +359,7 @@ /* Enable various video drivers */ #undef SDL_VIDEO_DRIVER_HAIKU +#undef SDL_VIDEO_DRIVER_AMIGAOS4 #undef SDL_VIDEO_DRIVER_COCOA #undef SDL_VIDEO_DRIVER_DIRECTFB #undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @@ -405,6 +411,7 @@ #undef SDL_VIDEO_RENDER_OGL_ES2 #undef SDL_VIDEO_RENDER_DIRECTFB #undef SDL_VIDEO_RENDER_METAL +#undef SDL_VIDEO_RENDER_AMIGAOS4 /* Enable OpenGL support */ #undef SDL_VIDEO_OPENGL @@ -439,6 +446,7 @@ #undef SDL_FILESYSTEM_DUMMY #undef SDL_FILESYSTEM_UNIX #undef SDL_FILESYSTEM_WINDOWS +#undef SDL_FILESYSTEM_AMIGAOS4 #undef SDL_FILESYSTEM_NACL #undef SDL_FILESYSTEM_ANDROID #undef SDL_FILESYSTEM_EMSCRIPTEN diff --git a/include/SDL_config_amigaos4.h b/include/SDL_config_amigaos4.h new file mode 100644 index 0000000000000..7ca9681cd6298 --- /dev/null +++ b/include/SDL_config_amigaos4.h @@ -0,0 +1,403 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_amigaos4_h_ +#define SDL_config_amigaos4_h_ +#define SDL_config_h_ + +/* This is a set of defines to configure the SDL features */ + +/* General platform specific identifiers */ +#include "SDL_platform.h" + +/* C datatypes */ +#ifdef __LP64__ +#define SIZEOF_VOIDP 8 +#else +#define SIZEOF_VOIDP 4 +#endif +#define HAVE_GCC_ATOMICS 1 +/* #undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET */ + +/* Useful headers */ +#define STDC_HEADERS 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_FLOAT_H 1 +#define HAVE_ICONV_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MATH_H 1 +/* #undef HAVE_MEMORY_H */ +#define HAVE_SIGNAL_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDIO_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_WCHAR_H 1 +/* #undef HAVE_PTHREAD_NP_H */ +/* #undef HAVE_LIBUNWIND_H */ + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */ +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +/* #undef HAVE_UNSETENV */ +#endif +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +/* #undef HAVE_MEMCMP */ +#define HAVE_WCSLEN 1 +/* #undef HAVE_WCSLCPY */ +/* #undef HAVE_WCSLCAT */ +#define HAVE_WCSCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +/* #undef HAVE__STRREV */ +/* #undef HAVE__STRUPR */ +/* #undef HAVE__STRLWR */ +/* #undef HAVE_INDEX */ +/* #undef HAVE_RINDEX */ +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +/* #undef HAVE_ITOA */ +/* #undef HAVE__LTOA */ +/* #undef HAVE__UITOA */ +/* #undef HAVE__ULTOA */ +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +/* #undef HAVE__I64TOA */ +/* #undef HAVE__UI64TOA */ +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +/* #undef HAVE_STRTOD */ +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +/* #undef HAVE__STRICMP */ +#define HAVE_STRCASECMP 1 +/* #undef HAVE__STRNICMP */ +#define HAVE_STRNCASECMP 1 +/* #undef HAVE_SSCANF */ +#define HAVE_VSSCANF 1 +/* #undef HAVE_SNPRINTF */ +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI /**/ +#define HAVE_ACOS 1 +#define HAVE_ACOSF 1 +#define HAVE_ASIN 1 +#define HAVE_ASINF 1 +#define HAVE_ATAN 1 +#define HAVE_ATANF 1 +#define HAVE_ATAN2 1 +#define HAVE_ATAN2F 1 +#define HAVE_CEIL 1 +#define HAVE_CEILF 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COPYSIGNF 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_EXP 1 +#define HAVE_EXPF 1 +#define HAVE_FABS 1 +#define HAVE_FABSF 1 +#define HAVE_FLOOR 1 +#define HAVE_FLOORF 1 +#define HAVE_FMOD 1 +#define HAVE_FMODF 1 +#define HAVE_LOG 1 +#define HAVE_LOGF 1 +#define HAVE_LOG10 1 +#define HAVE_LOG10F 1 +#define HAVE_POW 1 +#define HAVE_POWF 1 +#define HAVE_SCALBN 1 +#define HAVE_SCALBNF 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_FOPEN64 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSEEKO64 1 +/* #undef HAVE_SIGACTION */ +/* #undef HAVE_SA_SIGACTION */ +#define HAVE_SETJMP 1 +/* #undef HAVE_NANOSLEEP */ +/* #undef HAVE_SYSCONF */ +/* #undef HAVE_SYSCTLBYNAME */ +/* #undef HAVE_CLOCK_GETTIME */ +/* #undef HAVE_GETPAGESIZE */ +/* #undef HAVE_MPROTECT */ +#define HAVE_ICONV 1 +/* #undef HAVE_PTHREAD_SETNAME_NP */ +/* #undef HAVE_PTHREAD_SET_NAME_NP */ +/* #undef HAVE_SEM_TIMEDWAIT */ +/* #undef HAVE_GETAUXVAL */ +/* #undef HAVE_POLL */ + + +/*#define HAVE_ALTIVEC_H 1*/ +/* #undef HAVE_DBUS_DBUS_H */ +/* #undef HAVE_FCITX_FRONTEND_H */ +/* #undef HAVE_IBUS_IBUS_H */ +/* #undef HAVE_IMMINTRIN_H */ +/* #undef HAVE_LIBSAMPLERATE_H */ +/* #undef HAVE_LIBUDEV_H */ + +/* #undef HAVE_DDRAW_H */ +/* #undef HAVE_DINPUT_H */ +/* #undef HAVE_DSOUND_H */ +/* #undef HAVE_DXGI_H */ +/* #undef HAVE_XINPUT_H */ +/* #undef HAVE_ENDPOINTVOLUME_H */ +/* #undef HAVE_MMDEVICEAPI_H */ +/* #undef HAVE_AUDIOCLIENT_H */ +/* #undef HAVE_XINPUT_GAMEPAD_EX */ +/* #undef HAVE_XINPUT_STATE_EX */ + +/* SDL internal assertion support */ +/* #undef SDL_DEFAULT_ASSERT_LEVEL */ + +/* Allow disabling of core subsystems */ +/* #undef SDL_ATOMIC_DISABLED */ +/* #undef SDL_AUDIO_DISABLED */ +/* #undef SDL_CPUINFO_DISABLED */ +/* #undef SDL_EVENTS_DISABLED */ +/* #undef SDL_FILE_DISABLED */ +/* #undef SDL_JOYSTICK_DISABLED */ +/* #undef SDL_HAPTIC_DISABLED */ +/* #undef SDL_SENSOR_DISABLED */ +/* #undef SDL_LOADSO_DISABLED */ +/* #undef SDL_RENDER_DISABLED */ +/* #undef SDL_THREADS_DISABLED */ +/* #undef SDL_TIMERS_DISABLED */ +/* #undef SDL_VIDEO_DISABLED */ +/* #undef SDL_POWER_DISABLED */ +/* #undef SDL_FILESYSTEM_DISABLED */ + +/* Enable various audio drivers */ +/* #undef SDL_AUDIO_DRIVER_ALSA */ +/* #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_ANDROID */ +/* #undef SDL_AUDIO_DRIVER_ARTS */ +/* #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC */ +#define SDL_AUDIO_DRIVER_AMIGAOS4 1 +/* #undef SDL_AUDIO_DRIVER_COREAUDIO */ +/* #undef SDL_AUDIO_DRIVER_DISK */ +/* #undef SDL_AUDIO_DRIVER_DSOUND */ +#define SDL_AUDIO_DRIVER_DUMMY 1 +/* #undef SDL_AUDIO_DRIVER_EMSCRIPTEN */ +/* #undef SDL_AUDIO_DRIVER_ESD */ +/* #undef SDL_AUDIO_DRIVER_ESD_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_FUSIONSOUND */ +/* #undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_HAIKU */ +/* #undef SDL_AUDIO_DRIVER_JACK */ +/* #undef SDL_AUDIO_DRIVER_JACK_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_NACL */ +/* #undef SDL_AUDIO_DRIVER_NAS */ +/* #undef SDL_AUDIO_DRIVER_NAS_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_NETBSD */ +/* #undef SDL_AUDIO_DRIVER_OSS */ +/* #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H */ +/* #undef SDL_AUDIO_DRIVER_PAUDIO */ +/* #undef SDL_AUDIO_DRIVER_PULSEAUDIO */ +/* #undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_QSA */ +/* #undef SDL_AUDIO_DRIVER_SNDIO */ +/* #undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC */ +/* #undef SDL_AUDIO_DRIVER_SUNAUDIO */ +/* #undef SDL_AUDIO_DRIVER_WASAPI */ +/* #undef SDL_AUDIO_DRIVER_WINMM */ + +/* Enable various input drivers */ +/* #undef SDL_INPUT_LINUXEV */ +/* #undef SDL_INPUT_LINUXKD */ +/* #undef SDL_INPUT_TSLIB */ +/* #undef SDL_JOYSTICK_HAIKU */ +#define SDL_JOYSTICK_AMIGAINPUT 1 +/* #undef SDL_JOYSTICK_DINPUT */ +/* #undef SDL_JOYSTICK_XINPUT */ +/* #undef SDL_JOYSTICK_DUMMY */ +/* #undef SDL_JOYSTICK_IOKIT */ +/* #undef SDL_JOYSTICK_LINUX */ +/* #undef SDL_JOYSTICK_ANDROID */ +/* #undef SDL_JOYSTICK_WINMM */ +/* #undef SDL_JOYSTICK_USBHID */ +/* #undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */ +/* #undef SDL_JOYSTICK_HIDAPI */ +/* #undef SDL_JOYSTICK_EMSCRIPTEN */ +#define SDL_HAPTIC_DUMMY 1 +/* #undef SDL_HAPTIC_ANDROID */ +/* #undef SDL_HAPTIC_LINUX */ +/* #undef SDL_HAPTIC_IOKIT */ +/* #undef SDL_HAPTIC_DINPUT */ +/* #undef SDL_HAPTIC_XINPUT */ + +/* Enable various sensor drivers */ +/* #undef SDL_SENSOR_ANDROID */ +#define SDL_SENSOR_DUMMY 1 + +/* Enable various shared object loading systems */ +/* #undef SDL_LOADSO_DLOPEN */ +/* #undef SDL_LOADSO_DUMMY */ +/* #undef SDL_LOADSO_LDG */ +/* #undef SDL_LOADSO_WINDOWS */ +#define SDL_LOADSO_AMIGAOS4 1 + +/* Enable various threading systems */ +/* #undef SDL_THREAD_PTHREAD */ +/* #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX */ +/* #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP */ +/* #undef SDL_THREAD_WINDOWS */ +#define SDL_THREAD_AMIGAOS4 1 + +/* Enable various timer systems */ +/* #undef SDL_TIMER_HAIKU */ +#define SDL_TIMER_AMIGAOS4 1 +/* #undef SDL_TIMER_DUMMY */ +/* #undef SDL_TIMER_UNIX */ +/* #undef SDL_TIMER_WINDOWS */ + +/* Enable various video drivers */ +/* #undef SDL_VIDEO_DRIVER_HAIKU */ +#define SDL_VIDEO_DRIVER_AMIGAOS4 1 +/* #undef SDL_VIDEO_DRIVER_COCOA */ +/* #undef SDL_VIDEO_DRIVER_DIRECTFB */ +/* #undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC */ +#define SDL_VIDEO_DRIVER_DUMMY 1 +/* #undef SDL_VIDEO_DRIVER_WINDOWS */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR */ +/* #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON */ +/* #undef SDL_VIDEO_DRIVER_X11 */ +/* #undef SDL_VIDEO_DRIVER_RPI */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM */ +/* #undef SDL_VIDEO_DRIVER_ANDROID */ +/* #undef SDL_VIDEO_DRIVER_EMSCRIPTEN */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS */ +/* #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE */ +/* #undef SDL_VIDEO_DRIVER_X11_XCURSOR */ +/* #undef SDL_VIDEO_DRIVER_X11_XDBE */ +/* #undef SDL_VIDEO_DRIVER_X11_XINERAMA */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2 */ +/* #undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */ +/* #undef SDL_VIDEO_DRIVER_X11_XRANDR */ +/* #undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER */ +/* #undef SDL_VIDEO_DRIVER_X11_XSHAPE */ +/* #undef SDL_VIDEO_DRIVER_X11_XVIDMODE */ +/* #undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */ +/* #undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY */ +/* #undef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM */ +/* #undef SDL_VIDEO_DRIVER_NACL */ +/* #undef SDL_VIDEO_DRIVER_VIVANTE */ +/* #undef SDL_VIDEO_DRIVER_VIVANTE_VDK */ +/* #undef SDL_VIDEO_DRIVER_QNX */ + +/* #undef SDL_VIDEO_RENDER_D3D */ +/* #undef SDL_VIDEO_RENDER_D3D11 */ +#define SDL_VIDEO_RENDER_OGL 1 +/* #undef SDL_VIDEO_RENDER_OGL_ES */ +#define SDL_VIDEO_RENDER_OGL_ES2 1 +/* #undef SDL_VIDEO_RENDER_DIRECTFB */ +/* #undef SDL_VIDEO_RENDER_METAL */ +#define SDL_VIDEO_RENDER_AMIGAOS4 1 + +/* Enable OpenGL support */ +#define SDL_VIDEO_OPENGL 1 +/* #undef SDL_VIDEO_OPENGL_ES */ +#define SDL_VIDEO_OPENGL_ES2 1 +/* #undef SDL_VIDEO_OPENGL_BGL */ +/* #undef SDL_VIDEO_OPENGL_CGL */ +/* #undef SDL_VIDEO_OPENGL_EGL */ +/* #undef SDL_VIDEO_OPENGL_GLX */ +/* #undef SDL_VIDEO_OPENGL_WGL */ +/* #undef SDL_VIDEO_OPENGL_OSMESA */ +/* #undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC */ + +/* Enable Vulkan support */ +/* #undef SDL_VIDEO_VULKAN */ + +/* Enable system power support */ +/* #undef SDL_POWER_LINUX */ +/* #undef SDL_POWER_WINDOWS */ +/* #undef SDL_POWER_MACOSX */ +/* #undef SDL_POWER_HAIKU */ +/* #undef SDL_POWER_ANDROID */ +/* #undef SDL_POWER_EMSCRIPTEN */ +/* #undef SDL_POWER_HARDWIRED */ + +/* Enable system filesystem support */ +/* #undef SDL_FILESYSTEM_HAIKU */ +/* #undef SDL_FILESYSTEM_COCOA */ +/* #undef SDL_FILESYSTEM_DUMMY */ +/* #undef SDL_FILESYSTEM_UNIX */ +/* #undef SDL_FILESYSTEM_WINDOWS */ +#define SDL_FILESYSTEM_AMIGAOS4 1 +/* #undef SDL_FILESYSTEM_NACL */ +/* #undef SDL_FILESYSTEM_ANDROID */ +/* #undef SDL_FILESYSTEM_EMSCRIPTEN */ + +/* Enable assembly routines */ +#define SDL_ASSEMBLY_ROUTINES 1 +/*#define SDL_ALTIVEC_BLITTERS 1*/ + +/* Enable ime support */ +/* #undef SDL_USE_IME */ + +/* Enable dynamic udev support */ +/* #undef SDL_UDEV_DYNAMIC */ + +/* Enable dynamic libsamplerate support */ +/* #undef SDL_LIBSAMPLERATE_DYNAMIC */ + +#endif /* SDL_config_amigaos4_h_ */ diff --git a/include/SDL_endian.h b/include/SDL_endian.h index 0a8e204a4824e..47780a892baad 100644 --- a/include/SDL_endian.h +++ b/include/SDL_endian.h @@ -72,7 +72,7 @@ _m_prefetch(void *__P) #if defined(__hppa__) || \ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ (defined(__MIPS__) && defined(__MIPSEB__)) || \ - defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ + defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(_M_PPC) || \ defined(__sparc__) #define SDL_BYTEORDER SDL_BIG_ENDIAN #else diff --git a/include/SDL_opengl.h b/include/SDL_opengl.h index 95b51ae45c23c..a3234a868e399 100644 --- a/include/SDL_opengl.h +++ b/include/SDL_opengl.h @@ -37,6 +37,15 @@ #include "SDL_config.h" +#ifdef __AMIGAOS4__ +/* We really need the system headers for MiniGL */ + +#include + +#include "SDL_opengl_glext.h" + +#else + #ifndef __IPHONEOS__ /* No OpenGL on iOS. */ /* @@ -2178,6 +2187,8 @@ typedef void (APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum t #endif /* !__IPHONEOS__ */ +#endif /* __AMIGAOS4__ */ + #endif /* SDL_opengl_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/include/SDL_platform.h b/include/SDL_platform.h index ebaa25242fde0..0a10ae066824b 100644 --- a/include/SDL_platform.h +++ b/include/SDL_platform.h @@ -159,6 +159,11 @@ #define __PSP__ 1 #endif +#if defined(__amigaos4__) +#undef __AMIGAOS4__ +#define __AMIGAOS4__ 1 +#endif + /* The NACL compiler defines __native_client__ and __pnacl__ * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi */ diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index 12e86a17cc4c9..b90a73056b7aa 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -139,6 +139,7 @@ typedef enum SDL_SYSWM_WAYLAND, SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ SDL_SYSWM_WINRT, + SDL_SYSWM_OS4, SDL_SYSWM_ANDROID, SDL_SYSWM_VIVANTE, SDL_SYSWM_OS2, @@ -308,6 +309,12 @@ struct SDL_SysWMinfo EGLSurface surface; } android; #endif +#if defined(SDL_VIDEO_DRIVER_AMIGAOS4) + struct + { + struct Window *window; /**< The AmigaOS 4 window */ + } os4; +#endif #if defined(SDL_VIDEO_DRIVER_OS2) struct diff --git a/include/SDL_test.h b/include/SDL_test.h index 66fde839fa3fe..8cf35e571bc69 100644 --- a/include/SDL_test.h +++ b/include/SDL_test.h @@ -51,7 +51,33 @@ extern "C" { #endif /* Global definitions */ +#ifdef __amigaos4__ +# ifndef __LONG_MAX__ +# define __LONG_MAX__ 2147483647L +# endif +# undef LONG_MIN +# define LONG_MIN (-LONG_MAX-1) +# undef LONG_MAX +# define LONG_MAX __LONG_MAX__ +/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */ +# undef ULONG_MAX +# define ULONG_MAX (LONG_MAX * 2UL + 1) + +# ifndef __LONG_LONG_MAX__ +# define __LONG_LONG_MAX__ 9223372036854775807LL +# endif + +/* Minimum and maximum values a `signed long long int' can hold. */ +# undef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX-1) +# undef LLONG_MAX +# define LLONG_MAX __LONG_LONG_MAX__ + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */ +# undef ULLONG_MAX +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1) +#endif /* * Note: Maximum size of SDLTest log message is less than SDL's limit * to ensure we can fit additional information such as the timestamp. diff --git a/src/SDL.c b/src/SDL.c index 73f1cd7f0bd6c..5993bb2f27e74 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -52,6 +52,10 @@ #include "joystick/SDL_joystick_c.h" #include "sensor/SDL_sensor_c.h" +#if SDL_THREAD_AMIGAOS4 +#include "thread/amigaos4/SDL_systhread_c.h" +#endif + /* Initialization/Cleanup routines */ #if !SDL_TIMERS_DISABLED # include "timer/SDL_timer_c.h" @@ -158,6 +162,10 @@ SDL_InitSubSystem(Uint32 flags) /* Clear the error message */ SDL_ClearError(); +#if SDL_THREAD_AMIGAOS4 + OS4_InitThreadSubSystem(); +#endif + #if SDL_USE_LIBDBUS SDL_DBus_Init(); #endif @@ -445,6 +453,10 @@ SDL_Quit(void) SDL_TicksQuit(); #endif +#if SDL_THREAD_AMIGAOS4 + OS4_QuitThreadSubSystem(); +#endif + SDL_ClearHints(); SDL_AssertionsQuit(); SDL_LogResetPriorities(); @@ -538,6 +550,8 @@ SDL_GetPlatform() return "iOS"; #elif __PSP__ return "PlayStation Portable"; +#elif __AMIGAOS4__ + return "AmigaOS 4"; #elif __VITA__ return "PlayStation Vita"; #else diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 5ce94d1fffcc9..81e4838e07c77 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -101,6 +101,9 @@ static const AudioBootStrap *const bootstrap[] = { #if SDL_AUDIO_DRIVER_PSP &PSPAUDIO_bootstrap, #endif +#if SDL_AUDIO_DRIVER_AMIGAOS4 + &AMIGAOS4AUDIO_bootstrap, +#endif #if SDL_AUDIO_DRIVER_VITA &VITAAUD_bootstrap, #endif diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 17b9e70583581..daa455d70fab2 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -211,6 +211,7 @@ extern AudioBootStrap ANDROIDAUDIO_bootstrap; extern AudioBootStrap PSPAUDIO_bootstrap; extern AudioBootStrap VITAAUD_bootstrap; extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap; +extern AudioBootStrap AMIGAOS4AUDIO_bootstrap; extern AudioBootStrap OS2AUDIO_bootstrap; #endif /* SDL_sysaudio_h_ */ diff --git a/src/audio/amigaos4/SDL_os4audio.c b/src/audio/amigaos4/SDL_os4audio.c new file mode 100644 index 0000000000000..efef0f51dd1df --- /dev/null +++ b/src/audio/amigaos4/SDL_os4audio.c @@ -0,0 +1,474 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_AUDIO_DRIVER_AMIGAOS4 + +// This optimisation assumes that allocated audio buffers +// are sufficiently aligned to treat as arrays of longwords. +// Which they should be, as far as I can tell. +#define POSSIBLY_DANGEROUS_OPTIMISATION 1 + +#include "SDL_audio.h" +#include "SDL_timer.h" +#include "../SDL_audio_c.h" +#include "../SDL_sysaudio.h" +#include "SDL_os4audio.h" + +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +/* The tag name used by the AmigaOS4 audio driver */ +#define DRIVER_NAME "amigaos4" + +static SDL_bool +OS4_OpenAhiDevice(OS4AudioData * os4data) +{ + if (os4data->deviceOpen) { + dprintf("Device already open\n"); + } + + os4data->deviceOpen = SDL_FALSE; + + os4data->ahiReplyPort = (struct MsgPort *)IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE); + + if (os4data->ahiReplyPort) { + + /* create a iorequest for the device */ + os4data->ahiRequest[0] = (struct AHIRequest *) + IExec->AllocSysObjectTags( + ASOT_IOREQUEST, + ASOIOR_ReplyPort, os4data->ahiReplyPort, + ASOIOR_Size, sizeof(struct AHIRequest), + TAG_DONE); + + if (os4data->ahiRequest[0]) { + + if (!IExec->OpenDevice(AHINAME, 0, (struct IORequest *)os4data->ahiRequest[0], 0)) { + + dprintf("%s opened\n", AHINAME); + + /* Create a copy */ + os4data->ahiRequest[1] = (struct AHIRequest *) + IExec->AllocSysObjectTags( + ASOT_IOREQUEST, + ASOIOR_Duplicate, os4data->ahiRequest[0], + TAG_DONE); + + if (os4data->ahiRequest[1]) { + + dprintf("IO requests created\n"); + + os4data->deviceOpen = SDL_TRUE; + os4data->currentBuffer = 0; + os4data->link = NULL; + } else { + dprintf("Failed to duplicate IO request\n"); + } + } else { + dprintf("Failed to open %s\n", AHINAME); + } + } else { + dprintf("Failed to create IO request\n"); + } + } else { + dprintf("Failed to create reply port\n"); + } + + dprintf("deviceOpen = %d\n", os4data->deviceOpen); + return os4data->deviceOpen; +} + +static void +OS4_CloseAhiDevice(OS4AudioData * os4data) +{ + if (os4data->ahiRequest[0]) { + if (os4data->link) { + dprintf("Aborting I/O...\n"); + + IExec->AbortIO((struct IORequest *)os4data->link); + IExec->WaitIO((struct IORequest *)os4data->link); + } + + dprintf("Closing device\n"); + IExec->CloseDevice((struct IORequest *)os4data->ahiRequest[0]); + + dprintf("Freeing I/O requests\n"); + IExec->FreeSysObject(ASOT_IOREQUEST, os4data->ahiRequest[0]); + os4data->ahiRequest[0] = NULL; + + if (os4data->ahiRequest[1]) { + IExec->FreeSysObject(ASOT_IOREQUEST, os4data->ahiRequest[1]); + os4data->ahiRequest[1] = NULL; + } + } + + if (os4data->ahiReplyPort) { + dprintf("Deleting message port\n"); + IExec->FreeSysObject(ASOT_PORT, os4data->ahiReplyPort); + os4data->ahiReplyPort = NULL; + } + + os4data->deviceOpen = SDL_FALSE; + + dprintf("Device closed\n"); +} + +static SDL_bool +OS4_AudioAvailable(void) +{ + SDL_bool isAvailable = SDL_FALSE; + + OS4AudioData *tempData = SDL_calloc(1, sizeof(OS4AudioData)); + + if (!tempData) { + dprintf("Failed to allocate temp data\n"); + } else { + isAvailable = OS4_OpenAhiDevice(tempData); + + OS4_CloseAhiDevice(tempData); + + SDL_free(tempData); + } + + dprintf("AHI is %savailable\n", isAvailable ? "" : "not "); + return isAvailable; +} + +static int +OS4_SwapBuffer(int current) +{ + return (1 - current); +} + +static void +OS4_FillCaptureRequest(struct AHIRequest * request, void * buffer, int length, int frequency, int type) +{ + request->ahir_Std.io_Message.mn_Node.ln_Pri = 60; + request->ahir_Std.io_Data = buffer, + request->ahir_Std.io_Length = length; + request->ahir_Std.io_Command = CMD_READ; + request->ahir_Volume = 0x10000; + request->ahir_Position = 0x8000; + request->ahir_Link = NULL; + request->ahir_Frequency = frequency; + request->ahir_Type = type; +} + +/* ---------------------------------------------- */ +/* Audio driver exported functions implementation */ +/* ---------------------------------------------- */ +static void +OS4_CloseDevice(_THIS) +{ + OS4AudioData *os4data = _this->hidden; + + dprintf("Called\n"); + + OS4_CloseAhiDevice(os4data); + + if (os4data->audioBuffer[0]) { + SDL_free(os4data->audioBuffer[0]); + os4data->audioBuffer[0] = NULL; + } + + if (os4data->audioBuffer[1]) { + SDL_free(os4data->audioBuffer[1]); + os4data->audioBuffer[1] = NULL; + } + + SDL_free(os4data); +} + +static int +OS4_OpenDevice(_THIS, void * handle, const char * devname, int iscapture) +{ + int result = 0; + OS4AudioData *os4data = NULL; + + dprintf("handle %p, devname %s, iscapture %d\n", handle, devname, iscapture); + + _this->hidden = (OS4AudioData *) SDL_malloc(sizeof(OS4AudioData)); + + if (!_this->hidden) { + dprintf("Failed to allocate private data\n"); + return SDL_OutOfMemory(); + } + + SDL_memset(_this->hidden, 0, sizeof(OS4AudioData)); + os4data = _this->hidden; + + if ((_this->spec.format & 0xff) != 8) { + _this->spec.format = AUDIO_S16MSB; + } + + dprintf("New format = 0x%x\n", _this->spec.format); + dprintf("Buffer size = %d\n", _this->spec.size); + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(&_this->spec); + + os4data->audioBufferSize = _this->spec.size; + os4data->audioBuffer[0] = (Uint8 *) SDL_malloc(_this->spec.size); + os4data->audioBuffer[1] = (Uint8 *) SDL_malloc(_this->spec.size); + + if (os4data->audioBuffer[0] == NULL || os4data->audioBuffer[1] == NULL) { + OS4_CloseDevice(_this); + dprintf("No memory for audio buffer\n"); + SDL_SetError("No memory for audio buffer"); + return -1; + } + + SDL_memset(os4data->audioBuffer[0], _this->spec.silence, _this->spec.size); + SDL_memset(os4data->audioBuffer[1], _this->spec.silence, _this->spec.size); + + switch(_this->spec.format) { + case AUDIO_S8: + case AUDIO_U8: + os4data->ahiType = (_this->spec.channels < 2) ? AHIST_M8S : AHIST_S8S; + break; + + default: + os4data->ahiType = (_this->spec.channels < 2) ? AHIST_M16S : AHIST_S16S; + break; + } + + return result; +} + +static void +OS4_ThreadInit(_THIS) +{ + OS4AudioData *os4data = _this->hidden; + + dprintf("Called\n"); + + /* Signal must be opened in the task which is using it (player) */ + if (!OS4_OpenAhiDevice(os4data)) { + // FIXME: this is bad. We have failed and SDL core doesn't know about that. + dprintf("Failed to open AHI\n"); + } + + /* This will cause a lot of problems.. and should be removed. + + One possibility: create a configuration GUI or ENV variable that allows + user to select priority, if there is no silver bullet value */ + IExec->SetTaskPri(IExec->FindTask(NULL), 5); +} + +static void +OS4_WaitDevice(_THIS) +{ + /* Dummy - OS4_PlayDevice handles the waiting */ + //dprintf("Called\n"); +} + +static void +OS4_PlayDevice(_THIS) +{ + struct AHIRequest *ahiRequest; + SDL_AudioSpec *spec = &_this->spec; + OS4AudioData *os4data = _this->hidden; + int current = os4data->currentBuffer; + + //dprintf("Called\n"); + + if (!os4data->deviceOpen) { + dprintf("Device is not open\n"); + return; + } + + ahiRequest = os4data->ahiRequest[current]; + + ahiRequest->ahir_Std.io_Message.mn_Node.ln_Pri = 60; + ahiRequest->ahir_Std.io_Data = os4data->audioBuffer[current]; + ahiRequest->ahir_Std.io_Length = os4data->audioBufferSize; + ahiRequest->ahir_Std.io_Offset = 0; + ahiRequest->ahir_Std.io_Command = CMD_WRITE; + ahiRequest->ahir_Volume = 0x10000; + ahiRequest->ahir_Position = 0x8000; + ahiRequest->ahir_Link = os4data->link; + ahiRequest->ahir_Frequency = spec->freq; + ahiRequest->ahir_Type = os4data->ahiType; + + // Convert to signed? + if (spec->format == AUDIO_U8) { +#if POSSIBLY_DANGEROUS_OPTIMISATION + int i, n; + uint32 *mixbuf = (uint32 *)os4data->audioBuffer[current]; + n = os4data->audioBufferSize / 4; // let the gcc optimiser decide the best way to divide by 4 + for (i = 0; i < n; i++) { + *(mixbuf++) ^= 0x80808080; + } + + if (0 != (n = os4data->audioBufferSize & 3)) { + uint8 *mixbuf8 = (uint8 *)mixbuf; + for (i = 0; i < n; i++) { + *(mixbuf8++) -= 128; + } + } +#else + int i; + for (i = 0; i < os4data->audioBufferSize; i++) { + os4data->audioBuffer[current][i] -= 128; + } +#endif + } + + IExec->SendIO((struct IORequest *)ahiRequest); + + if (os4data->link) { + IExec->WaitIO((struct IORequest *)os4data->link); + } + + os4data->link = ahiRequest; + os4data->currentBuffer = OS4_SwapBuffer(current); +} + +static Uint8 * +OS4_GetDeviceBuf(_THIS) +{ + //dprintf("Called\n"); + + return _this->hidden->audioBuffer[_this->hidden->currentBuffer]; +} + +#ifndef MIN +#define MIN(a, b) (a) < (b) ? (a) : (b) +#endif + +#define RESTART_CAPTURE_THRESHOLD 500 + +static int +OS4_CaptureFromDevice(_THIS, void * buffer, int buflen) +{ + struct AHIRequest *request; + SDL_AudioSpec *spec = &_this->spec; + OS4AudioData *os4data = _this->hidden; + Uint32 now; + size_t copyLen; + void *completedBuffer; + int current; + + //dprintf("Called %p, %d\n", buffer, buflen); + + if (!os4data->deviceOpen) { + dprintf("Device is not open\n"); + return 0; + } + + now = SDL_GetTicks(); + current = os4data->currentBuffer; + + request = os4data->ahiRequest[0]; + + if ((now - os4data->lastCaptureTicks) > RESTART_CAPTURE_THRESHOLD) { + + if (os4data->requestSent) { + IExec->WaitIO((struct IORequest *)request); + } + + /* Assume that we have to (re)start recording */ + OS4_FillCaptureRequest( + request, + os4data->audioBuffer[current], + os4data->audioBufferSize, + spec->freq, + os4data->ahiType); + + request->ahir_Std.io_Offset = 0; + + dprintf("Start recording\n"); + + IExec->DoIO((struct IORequest *)request); + os4data->requestSent = SDL_FALSE; + + current = OS4_SwapBuffer(current); + } else { + /* Wait for the previous request completion */ + IExec->WaitIO((struct IORequest *)request); + } + + OS4_FillCaptureRequest( + request, + os4data->audioBuffer[current], + os4data->audioBufferSize, + spec->freq, + os4data->ahiType); + + IExec->SendIO((struct IORequest *)request); + os4data->requestSent = SDL_TRUE; + + current = OS4_SwapBuffer(current); + + completedBuffer = os4data->audioBuffer[current]; + + copyLen = MIN(buflen, os4data->audioBufferSize); + + SDL_memcpy(buffer, completedBuffer, copyLen); + + os4data->lastCaptureTicks = now; + os4data->currentBuffer = current; + + //dprintf("%d bytes copied\n", copyLen); + + return copyLen; +} + +/* ------------------------------------------ */ +/* Audio driver init functions implementation */ +/* ------------------------------------------ */ +static int +OS4_Init(SDL_AudioDriverImpl * impl) +{ + if (!OS4_AudioAvailable()) { + SDL_SetError("Failed to open AHI device"); + return 0; + } + + // impl->DetectDevices? + impl->OpenDevice = OS4_OpenDevice; + impl->ThreadInit = OS4_ThreadInit; + impl->WaitDevice = OS4_WaitDevice; + impl->PlayDevice = OS4_PlayDevice; + // impl->GetPendingBytes? + impl->GetDeviceBuf = OS4_GetDeviceBuf; + impl->CaptureFromDevice = OS4_CaptureFromDevice; + // impl->FlushCapture + // impl->PrepareToClose() + impl->CloseDevice = OS4_CloseDevice; + // impl->Lock+UnlockDevice + // impl->FreeDeviceHandle + // impl->Deinitialize + + impl->HasCaptureSupport = 1; + impl->OnlyHasDefaultOutputDevice = 1; + impl->OnlyHasDefaultCaptureDevice = 1; + + return 1; +} + +AudioBootStrap AMIGAOS4AUDIO_bootstrap = { + DRIVER_NAME, "AmigaOS4 AHI audio", OS4_Init, 0 +}; +#endif diff --git a/src/audio/amigaos4/SDL_os4audio.h b/src/audio/amigaos4/SDL_os4audio.h new file mode 100644 index 0000000000000..53074716414c7 --- /dev/null +++ b/src/audio/amigaos4/SDL_os4audio.h @@ -0,0 +1,53 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef _SDL_os4audio_h +#define _SDL_os4audio_h + +#include +#include +#include + +#include "SDL_types.h" + +#include "../SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *_this + +struct SDL_PrivateAudioData +{ + struct MsgPort *ahiReplyPort; + struct AHIRequest *ahiRequest[2]; + uint32 ahiType; + int currentBuffer; // buffer number to fill + struct AHIRequest *link; // point to previous I/O request sent + + SDL_bool deviceOpen; + Uint32 audioBufferSize; + Uint8 *audioBuffer[2]; + + Uint32 lastCaptureTicks; + SDL_bool requestSent; // Keeps book of IO done with SendIO(), to avoid issues with WaitIO() +}; + +typedef struct SDL_PrivateAudioData OS4AudioData; + +#endif diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 1668e701cd099..bdd59a7f783b4 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -59,6 +59,11 @@ #include #endif +#ifdef __AMIGAOS4__ +#include +#include +#endif + #if defined(__QNXNTO__) #include #endif @@ -327,6 +332,13 @@ CPU_haveAltiVec(void) int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); if (0 == error) altivec = (hasVectorUnit != 0); +#elif defined __amigaos4__ + { + uint32 vec_unit; + + IExec->GetCPUInfoTags(GCIT_VectorUnit, &vec_unit, TAG_DONE); + altivec = (vec_unit == VECTORTYPE_ALTIVEC); + } #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP void (*handler) (int sig); handler = signal(SIGILL, illegal_instruction); @@ -809,8 +821,15 @@ SDL_GetCPUCacheLineSize(void) cpuid(0x80000005, a, b, c, d); return (c & 0xff); } else { +#ifdef __AMIGAOS4__ + uint32 size; + + IExec->GetCPUInfoTags(GCIT_CacheLineSize, &size, TAG_DONE); + return size; +#else /* Just make a guess here... */ return SDL_CACHELINE_SIZE; +#endif } } @@ -1009,6 +1028,11 @@ SDL_GetSystemRAM(void) } } #endif +#ifdef __AMIGAOS4__ + if (SDL_SystemRAM <= 0) { + SDL_SystemRAM = IExec->AvailMem(MEMF_TOTAL) / (1024 * 1024); + } +#endif #ifdef __OS2__ if (SDL_SystemRAM <= 0) { Uint32 sysram = 0; diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 2619ff7612363..115f55ab9b6c3 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -53,6 +53,8 @@ #define SDL_DYNAMIC_API 0 #elif defined(__PSP__) && __PSP__ #define SDL_DYNAMIC_API 0 +#elif defined(__amigaos4__) /* It seems we cannot load .so from a statically linked binary */ +#define SDL_DYNAMIC_API 0 #elif defined(__riscos__) && __riscos__ /* probably not useful on RISC OS, since dlopen() can't be used when using static linking. */ #define SDL_DYNAMIC_API 0 #elif defined(__clang_analyzer__) diff --git a/src/events/scancodes_amiga.h b/src/events/scancodes_amiga.h new file mode 100644 index 0000000000000..5ae622e753a5c --- /dev/null +++ b/src/events/scancodes_amiga.h @@ -0,0 +1,144 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../include/SDL_scancode.h" + +/* Amiga virtual key code to SDL_Keycode mapping table + Sources: + - AmigaOS wiki +*/ +/* *INDENT-OFF* */ +static SDL_Scancode const amiga_scancode_table[] = { + /* 0 */ SDL_SCANCODE_GRAVE, + /* 1 */ SDL_SCANCODE_1, + /* 2 */ SDL_SCANCODE_2, + /* 3 */ SDL_SCANCODE_3, + /* 4 */ SDL_SCANCODE_4, + /* 5 */ SDL_SCANCODE_5, + /* 6 */ SDL_SCANCODE_6, + /* 7 */ SDL_SCANCODE_7, + /* 8 */ SDL_SCANCODE_8, + /* 9 */ SDL_SCANCODE_9, + /* 10 */ SDL_SCANCODE_0, + /* 11 */ SDL_SCANCODE_MINUS, + /* 12 */ SDL_SCANCODE_EQUALS, + /* 13 */ SDL_SCANCODE_BACKSLASH, + /* 14 */ SDL_SCANCODE_INTERNATIONAL3, + /* 15 */ SDL_SCANCODE_KP_0, + /* 16 */ SDL_SCANCODE_Q, + /* 17 */ SDL_SCANCODE_W, + /* 18 */ SDL_SCANCODE_E, + /* 19 */ SDL_SCANCODE_R, + /* 20 */ SDL_SCANCODE_T, + /* 21 */ SDL_SCANCODE_Y, + /* 22 */ SDL_SCANCODE_U, + /* 23 */ SDL_SCANCODE_I, + /* 24 */ SDL_SCANCODE_O, + /* 25 */ SDL_SCANCODE_P, + /* 26 */ SDL_SCANCODE_LEFTBRACKET, + /* 27 */ SDL_SCANCODE_RIGHTBRACKET, + /* 28 */ SDL_SCANCODE_UNKNOWN, + /* 29 */ SDL_SCANCODE_KP_1, + /* 30 */ SDL_SCANCODE_KP_2, + /* 31 */ SDL_SCANCODE_KP_3, + /* 32 */ SDL_SCANCODE_A, + /* 33 */ SDL_SCANCODE_S, + /* 34 */ SDL_SCANCODE_D, + /* 35 */ SDL_SCANCODE_F, + /* 36 */ SDL_SCANCODE_G, + /* 37 */ SDL_SCANCODE_H, + /* 38 */ SDL_SCANCODE_J, + /* 39 */ SDL_SCANCODE_K, + /* 40 */ SDL_SCANCODE_L, + /* 41 */ SDL_SCANCODE_SEMICOLON, + /* 42 */ SDL_SCANCODE_APOSTROPHE, + /* 43 */ SDL_SCANCODE_INTERNATIONAL1, + /* 44 */ SDL_SCANCODE_UNKNOWN, + /* 45 */ SDL_SCANCODE_KP_4, + /* 46 */ SDL_SCANCODE_KP_5, + /* 47 */ SDL_SCANCODE_KP_6, + /* 48 */ SDL_SCANCODE_INTERNATIONAL2, + /* 49 */ SDL_SCANCODE_Z, + /* 50 */ SDL_SCANCODE_X, + /* 51 */ SDL_SCANCODE_C, + /* 52 */ SDL_SCANCODE_V, + /* 53 */ SDL_SCANCODE_B, + /* 54 */ SDL_SCANCODE_N, + /* 55 */ SDL_SCANCODE_M, + /* 56 */ SDL_SCANCODE_COMMA, + /* 57 */ SDL_SCANCODE_PERIOD, + /* 58 */ SDL_SCANCODE_SLASH, + /* 59 */ SDL_SCANCODE_UNKNOWN, // or SDL_SCANCODE_INTERNATIONAL1, + /* 60 */ SDL_SCANCODE_KP_PERIOD, + /* 61 */ SDL_SCANCODE_KP_7, + /* 62 */ SDL_SCANCODE_KP_8, + /* 63 */ SDL_SCANCODE_KP_9, + /* 64 */ SDL_SCANCODE_SPACE, + /* 65 */ SDL_SCANCODE_BACKSPACE, + /* 66 */ SDL_SCANCODE_TAB, + /* 67 */ SDL_SCANCODE_KP_ENTER, + /* 68 */ SDL_SCANCODE_RETURN, + /* 69 */ SDL_SCANCODE_ESCAPE, + /* 70 */ SDL_SCANCODE_DELETE, + /* 71 */ SDL_SCANCODE_INSERT, + /* 72 */ SDL_SCANCODE_PAGEUP, + /* 73 */ SDL_SCANCODE_PAGEDOWN, + /* 74 */ SDL_SCANCODE_KP_MINUS, + /* 75 */ SDL_SCANCODE_F11, + /* 76 */ SDL_SCANCODE_UP, + /* 77 */ SDL_SCANCODE_DOWN, + /* 78 */ SDL_SCANCODE_RIGHT, + /* 79 */ SDL_SCANCODE_LEFT, + /* 80 */ SDL_SCANCODE_F1, + /* 81 */ SDL_SCANCODE_F2, + /* 82 */ SDL_SCANCODE_F3, + /* 83 */ SDL_SCANCODE_F4, + /* 84 */ SDL_SCANCODE_F5, + /* 85 */ SDL_SCANCODE_F6, + /* 86 */ SDL_SCANCODE_F7, + /* 87 */ SDL_SCANCODE_F8, + /* 88 */ SDL_SCANCODE_F9, + /* 89 */ SDL_SCANCODE_F10, + /* 90 */ SDL_SCANCODE_KP_LEFTPAREN, + /* 91 */ SDL_SCANCODE_KP_RIGHTPAREN, + /* 92 */ SDL_SCANCODE_KP_DIVIDE, + /* 93 */ SDL_SCANCODE_KP_MULTIPLY, + /* 94 */ SDL_SCANCODE_KP_PLUS, + /* 95 */ SDL_SCANCODE_SCROLLLOCK, // or SDL_SCANCODE_HELP, + /* 96 */ SDL_SCANCODE_LSHIFT, + /* 97 */ SDL_SCANCODE_RSHIFT, + /* 98 */ SDL_SCANCODE_CAPSLOCK, + /* 99 */ SDL_SCANCODE_LCTRL, + /* 100 */ SDL_SCANCODE_LALT, + /* 101 */ SDL_SCANCODE_RALT, + /* 102 */ SDL_SCANCODE_LGUI, + /* 103 */ SDL_SCANCODE_RGUI, + /* 104 */ SDL_SCANCODE_UNKNOWN, + /* 105 */ SDL_SCANCODE_UNKNOWN, + /* 106 */ SDL_SCANCODE_UNKNOWN, + /* 107 */ SDL_SCANCODE_MENU, + /* 108 */ SDL_SCANCODE_KP_PERIOD, + /* 109 */ SDL_SCANCODE_PRINTSCREEN, + /* 110 */ SDL_SCANCODE_PAUSE, + /* 111 */ SDL_SCANCODE_F12, + /* 112 */ SDL_SCANCODE_HOME, + /* 113 */ SDL_SCANCODE_END, +}; +/* *INDENT-ON* */ diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 9552b3d03ab0f..ace07a53f4797 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -34,6 +34,10 @@ #include "../core/windows/SDL_windows.h" #endif +#ifdef __AMIGAOS4__ +#define off64_t _off64_t +#endif + #ifdef HAVE_STDIO_H #include #endif @@ -615,6 +619,12 @@ stdio_seek(SDL_RWops * context, Sint64 offset, int whence) } #endif +#ifdef __AMIGAOS4__ + if ((context->hidden.stdio.fp->_flags & __SL64) == 0) { + return SDL_SetError("File wasn't opened with fopen64"); + } +#endif + if (fseek(context->hidden.stdio.fp, (fseek_off_t)offset, stdiowhence) == 0) { Sint64 pos = ftell(context->hidden.stdio.fp); if (pos < 0) { diff --git a/src/filesystem/amigaos4/SDL_sysfilesystem.c b/src/filesystem/amigaos4/SDL_sysfilesystem.c new file mode 100644 index 0000000000000..700c0c01f9db5 --- /dev/null +++ b/src/filesystem/amigaos4/SDL_sysfilesystem.c @@ -0,0 +1,162 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_FILESYSTEM_AMIGAOS4 + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent filesystem routines */ + +#include "SDL_error.h" +#include "SDL_filesystem.h" +#include "../../video/amigaos4/SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include + +static struct DOSIFace* iDos; +static struct DOSBase* dosBase; + +static BOOL +OS4_OpenDosLibrary() +{ + dosBase = (struct DOSBase *)OS4_OpenLibrary("dos.library", 50); + iDos = (struct DOSIFace *)OS4_GetInterface((struct Library *)dosBase); + return iDos != NULL; +} + +static void +OS4_CloseDosLibrary() +{ + OS4_DropInterface((struct Interface **)&iDos); + OS4_CloseLibrary((struct Library **)&dosBase); +} + +char * +SDL_GetBasePath(void) +{ + char* buffer = NULL; + const char* const basePath = "PROGDIR:"; + + size_t len = SDL_strlen(basePath) + 1; + + buffer = (char *) SDL_malloc(len); + if (!buffer) { + SDL_OutOfMemory(); + return NULL; + } + + SDL_memset(buffer, 0, len); + SDL_snprintf(buffer, len, "%s", basePath); + + return buffer; +} + +static BOOL +OS4_CreateDirTree(const char* path) +{ + BOOL success = FALSE; + + char* temp = SDL_strdup(path); + + if (!temp) { + dprintf("Failed to create temporary path\n"); + return FALSE; + } + + const size_t len = SDL_strlen(temp); + + if (len < 1) { + dprintf("Empty string\n"); + return FALSE; + } + + if (temp[len - 1] == '/') { + temp[len - 1] = '\0'; + } + + if (OS4_OpenDosLibrary()) { + BPTR lock = iDos->CreateDirTree(temp); + if (lock) { + success = TRUE; + iDos->UnLock(lock); + } else { + const int32 err = iDos->IoErr(); + dprintf("Failed to create dir tree '%s' (err %d)\n", temp, err); + if (err == ERROR_OBJECT_EXISTS) { + dprintf("Object already exists -> success\n"); + success = TRUE; + } + } + + OS4_CloseDosLibrary(); + } + + SDL_free(temp); + + return success; +} + +char * +SDL_GetPrefPath(const char *org, const char *app) +{ + const char* const envPath = "ENVARC:"; + size_t len = SDL_strlen(envPath) + 1; + char* buffer = NULL; + + if (org) { + len += SDL_strlen(org) + 1; + } + + if (app) { + len += SDL_strlen(app) + 1; + } + + buffer = (char *) SDL_malloc(len); + if (!buffer) { + SDL_OutOfMemory(); + return NULL; + } + + SDL_memset(buffer, 0, len); + SDL_snprintf(buffer, len, envPath); + + if (org) { + SDL_snprintf(buffer + SDL_strlen(buffer), len - SDL_strlen(buffer), "%s/", org); + } + + if (app) { + SDL_snprintf(buffer + SDL_strlen(buffer), len - SDL_strlen(buffer), "%s/", app); + } + + if (OS4_CreateDirTree(buffer)) { + return buffer; + } + + SDL_free(buffer); + return NULL; +} + +#endif /* SDL_FILESYSTEM_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index 2d54b63a19056..d353161064e17 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -862,6 +862,22 @@ static const char *s_ControllerMappings [] = #if defined(SDL_JOYSTICK_EMSCRIPTEN) "default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", #endif +#if defined(__AMIGAOS4__) + "53504545442d4c494e4b20436f6d7065,SPEED-LINK Competition Pro,platform:AmigaOS 4,a:b0,b:b1,x:b3,y:b2,leftx:a0,lefty:a1,", + "47656e6572696320202055534220204a,Ewent Joypad EW3170,platform:AmigaOS 4,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", + "555342204a6f79737469636b20202020,PS2 Joystick (USB adaptor),platform:AmigaOS 4,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,", + "555342204a6f79737469636b20202020,SHARK 91230 Joystick,platform:AmigaOS 4,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,", + "4d414749432d4e530000000000000000,MAGIC-NS,platform:AmigaOS4,a:b2,b:b1,x:b3,y:b0,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdwn:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "576972656c65737320436f6e74726f6c,Wireless Controller,platform:AmigaOS 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "38426974646f20534e33302050726f20,8Bitdo SN30 Pro,platform:AmigaOS 4,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,", + "5468727573746d617374657220647561,Thrustmaster dual analog 3.2,platform:AmigaOS 4,a:b0,b:b2,x:b1,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,", + "58454f582047616d6570616420534c2d,XEOX Gamepad SL-6556-BK,platform:AmigaOS 4,a:b0,b:b1,x:b2,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:+a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "202055534220204a6f79737469636b20,Strike2 Joystick,platform:AmigaOS 4,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "7573622067616d657061642020202020,GeeekPi_A gamepad,platform:AmigaOS 4,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,", + "4c6f67697465636820436f72646c6573,Logitech Cordless RumblePad 2,platform:AmigaOS 4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b9,leftstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,", + "4c6f6769746563682052756d626c6550,Logitech RumblePad 2 USB,platform:AmigaOS 4,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "4c6f6769746563682852292050726563,Logitech(R) Precision(TM) Gamepad,platform:AmigaOS 4,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,lefttrigger:b6,righttrigger:b7,", +#endif #if defined(SDL_JOYSTICK_VITA) "50535669746120436f6e74726f6c6c65,PSVita Controller,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", #endif diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 5a46f0c8629d6..a1a19a2932409 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -95,6 +95,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { #ifdef SDL_JOYSTICK_VIRTUAL &SDL_VIRTUAL_JoystickDriver, #endif +#if defined(SDL_JOYSTICK_AMIGAINPUT) + &SDL_AMIGAINPUT_JoystickDriver, +#endif #ifdef SDL_JOYSTICK_VITA &SDL_VITA_JoystickDriver #endif diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 749c6efd2963c..301f01794270f 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -193,6 +193,7 @@ typedef struct _SDL_JoystickDriver #define SDL_LED_MIN_REPEAT_MS 5000 /* The available joystick drivers */ +extern SDL_JoystickDriver SDL_AMIGAINPUT_JoystickDriver; extern SDL_JoystickDriver SDL_ANDROID_JoystickDriver; extern SDL_JoystickDriver SDL_BSD_JoystickDriver; extern SDL_JoystickDriver SDL_DARWIN_JoystickDriver; diff --git a/src/joystick/amigaos4/SDL_sysjoystick.c b/src/joystick/amigaos4/SDL_sysjoystick.c new file mode 100644 index 0000000000000..9e4a4560ec49a --- /dev/null +++ b/src/joystick/amigaos4/SDL_sysjoystick.c @@ -0,0 +1,650 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if defined(SDL_JOYSTICK_AMIGAINPUT) || defined(SDL_JOYSTICK_DISABLED) + +#define OLDSDK 1 + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" +#include "../../video/amigaos4/SDL_os4library.h" + +#include "SDL_events.h" + +#include +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#define MAX_JOYSTICKS 32 + +#define MAX_AXES 8 +#define MAX_BUTTONS 16 +#define MAX_HATS 8 + +#define BUFFER_OFFSET(buffer, offset) (((int32 *)buffer)[offset]) + +struct joystick +{ + AIN_DeviceID id; + const char *name; +}; + +/* Per-joystick data private to driver */ +struct joystick_hwdata +{ + AIN_DeviceHandle *handle; + APTR context; + + uint32 axisBufferOffset[MAX_AXES]; + int32 axisData[MAX_AXES]; + TEXT axisName[MAX_AXES][32]; + + uint32 buttonBufferOffset[MAX_BUTTONS]; + int32 buttonData[MAX_BUTTONS]; + + uint32 hatBufferOffset[MAX_HATS]; + int32 hatData[MAX_HATS]; +}; + +// TODO: get rid of static data +static uint32 joystickCount; +static struct joystick joystickList [MAX_JOYSTICKS]; +static APTR joystickContext; + +/* A handy container to encapsulate the information we + * need when enumerating joysticks on the system. + */ +struct enumPacket +{ + APTR context; + uint32 *count; + struct joystick *joyList; +}; + +static struct Library *SDL_AIN_Base; +static struct AIN_IFace *SDL_IAIN; + +/* + * Convert AmigaInput hat data to SDL hat data. + */ +static inline Uint8 +AMIGAINPUT_MapHatData(int hat_data) +{ + switch (hat_data) { + case 1: return SDL_HAT_UP; + case 2: return SDL_HAT_UP | SDL_HAT_RIGHT; + case 3: return SDL_HAT_RIGHT; + case 4: return SDL_HAT_DOWN | SDL_HAT_RIGHT; + case 5: return SDL_HAT_DOWN; + case 6: return SDL_HAT_DOWN | SDL_HAT_LEFT; + case 7: return SDL_HAT_LEFT; + case 8: return SDL_HAT_UP | SDL_HAT_LEFT; + default: return SDL_HAT_CENTERED; + } +} + +/* + * Callback to enumerate joysticks + */ +static BOOL +AMIGAINPUT_EnumerateJoysticks(AIN_Device *device, void *UserData) +{ + APTR context = ((struct enumPacket *)UserData)->context; + uint32 *count = ((struct enumPacket *)UserData)->count; + struct joystick *joy = &((struct enumPacket *)UserData)->joyList[*count]; + + BOOL result = FALSE; + + if (*count < MAX_JOYSTICKS) { + dprintf("ENUMJOY: id=%ld, type=%ld, axes=%ld, buttons=%ld\n", + count, + (int32)device->Type, + (int32)device->NumAxes, + (int32)device->NumButtons); + + if (device->Type == AINDT_JOYSTICK) { + /* AmigaInput can report devices even when there's no + * physical stick present. We take some steps to try and + * ignore such bogus devices. + * + * First, check whether we have a useful number of axes and buttons + */ + if ((device->NumAxes > 0) && (device->NumButtons > 0)) { + /* Then, check whether we can actually obtain the device + */ +#if OLDSDK + AIN_DeviceHandle *handle = SDL_IAIN->AIN_ObtainDevice (context, device->DeviceID); +#else + AIN_DeviceHandle *handle = SDL_IAIN->ObtainDevice (context, device->DeviceID); +#endif + + if (handle) { + /* Okay. This appears to be a valid device. We'll report it to SDL. + */ + joy->id = device->DeviceID; + joy->name = SDL_strdup(device->DeviceName); + + dprintf("Found joystick #%d (AI ID=%d) '%s'\n", *count, joy->id, joy->name); + + (*count)++; + +#if OLDSDK + SDL_IAIN->AIN_ReleaseDevice (context, handle); +#else + SDL_IAIN->ReleaseDevice (context, handle); +#endif + + result = TRUE; + } + else + dprintf("Failed to obtain joystick '%s' (AI ID=%d) - ignoring.\n", device->DeviceName, device->DeviceID); + } + else + dprintf("Joystick '%s' (AI ID=%d) has no axes/buttons - ignoring.\n", device->DeviceName, device->DeviceID); + } + } + return result; +} + +static BOOL +AMIGAINPUT_OpenLibrary(void) +{ + dprintf("Called\n"); + + SDL_AIN_Base = OS4_OpenLibrary("AmigaInput.library", 51); + + if (SDL_AIN_Base) { + SDL_IAIN = (struct AIN_IFace *) OS4_GetInterface(SDL_AIN_Base); + + if (!SDL_IAIN) { + OS4_CloseLibrary(&SDL_AIN_Base); + } + } else { + dprintf("Failed to open AmigaInput.library\n"); + } + + return SDL_AIN_Base != NULL; +} + +static void +AMIGAINPUT_CloseLibrary(void) +{ + dprintf("Called\n"); + + OS4_DropInterface((void *) &SDL_IAIN); + OS4_CloseLibrary(&SDL_AIN_Base); +} + +/* Function to scan the system for joysticks. + * It should return 0, or -1 on an unrecoverable fatal error. + */ +static int +AMIGAINPUT_Init(void) +{ + if (AMIGAINPUT_OpenLibrary()) { +#if OLDSDK + joystickContext = SDL_IAIN->AIN_CreateContext(1, NULL); +#else + joystickContext = SDL_IAIN->CreateContext(1, NULL); +#endif + + if (joystickContext) { + struct enumPacket packet = { + joystickContext, + &joystickCount, + &joystickList[0] + }; + +#if OLDSDK + BOOL result = SDL_IAIN->AIN_EnumDevices(joystickContext, AMIGAINPUT_EnumerateJoysticks, &packet); +#else + BOOL result = SDL_IAIN->EnumDevices(joystickContext, AMIGAINPUT_EnumerateJoysticks, &packet); +#endif + dprintf("EnumDevices returned %d\n", result); + dprintf("Found %d joysticks\n", joystickCount); + + if (result) { + /* + + NOTE: AI doesn't seem to handle hotplugged/removed joysticks very well. + Report only devices detected at startup to SDL. + + */ + int i; + + for (i = 0; i < joystickCount; i++) { + dprintf("Add joystick %d\n", i); + SDL_PrivateJoystickAdded(i); + } + } + } + + return 0; + } else { + dprintf("Failed to create context\n"); + } + + return -1; +} + +static int +AMIGAINPUT_GetCount() +{ + return joystickCount; +} + +static void +AMIGAINPUT_Detect() +{ + //dprintf("Called\n"); +} + +/* Function to get the device-dependent name of a joystick */ +static const char * +AMIGAINPUT_GetDeviceName(int device_index) +{ + return joystickList[device_index].name; +} + +static int +AMIGAINPUT_GetDevicePlayerIndex(int device_index) +{ + return device_index; +} + +static void +AMIGAINPUT_SetDevicePlayerIndex(int device_index, int player_index) +{ + dprintf("Not implemented\n"); +} + +static SDL_JoystickID +AMIGAINPUT_GetDeviceInstanceID(int device_index) +{ + return device_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. + */ +static int +AMIGAINPUT_Open(SDL_Joystick * joystick, int device_index) +{ + AIN_DeviceHandle *handle; + AIN_DeviceID id = joystickList[joystick->instance_id].id; + +#if OLDSDK + handle = SDL_IAIN->AIN_ObtainDevice(joystickContext, id); +#else + handle = SDL_IAIN->ObtainDevice(joystickContext, id); +#endif + + dprintf("Opening joystick #%d (AI ID=%d)\n", joystick->instance_id, id); + + if (handle) { + joystick->hwdata = SDL_calloc(1, sizeof(struct joystick_hwdata)); + + if (joystick->hwdata) { + struct joystick_hwdata *hwdata = joystick->hwdata; + unsigned int num_axes = 0; + unsigned int num_buttons = 0; + unsigned int num_hats = 0; + TEXT tmpstr[32]; + uint32 tmpoffset; + + int i; + BOOL result = TRUE; + + hwdata->handle = handle; + hwdata->context = joystickContext; + + joystick->name = (char *) joystickList[joystick->instance_id].name; + + /* Query number of axes, buttons and hats the device has */ +#if OLDSDK + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_NUMAXES, 0, &num_axes, 4); + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_NUMBUTTONS, 0, &num_buttons, 4); + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_NUMHATS, 0, &num_hats, 4); +#else + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_NUMAXES, 0, &num_axes, 4); + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_NUMBUTTONS, 0, &num_buttons, 4); + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_NUMHATS, 0, &num_hats, 4); +#endif + +// dprintf ("Found %d axes, %d buttons, %d hats\n", num_axes, num_buttons, num_hats); + + joystick->naxes = num_axes < MAX_AXES ? num_axes : MAX_AXES; + joystick->nbuttons = num_buttons < MAX_BUTTONS ? num_buttons : MAX_BUTTONS; + joystick->nhats = num_hats < MAX_HATS ? num_hats : MAX_HATS; + + // Ensure all axis names are null terminated + for (i = 0; i < MAX_AXES; i++) + hwdata->axisName[i][0] = 0; + + /* Query offsets in ReadDevice buffer for axes' data */ + for (i = 0; i < joystick->naxes; i++) { +#if OLDSDK + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_AXIS_OFFSET, i, &(hwdata->axisBufferOffset[i]), 4); + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_AXISNAME, i, &(hwdata->axisName[i][0]), 32 ); +#else + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_AXIS_OFFSET, i, &(hwdata->axisBufferOffset[i]), 4); + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_AXISNAME, i, &(hwdata->axisName[i][0]), 32 ); +#endif + } + + // Sort the axes so that X and Y come first + for (i = 0; i < joystick->naxes; i++) { + if ( ( strcasecmp( &hwdata->axisName[i][0], "X-Axis" ) == 0 ) && ( i != 0 ) ) { + // Back up the zero position axis data + tmpoffset = hwdata->axisBufferOffset[0]; + strlcpy( tmpstr, hwdata->axisName[0], 32 ); + + // Move this one to zero + hwdata->axisBufferOffset[0] = hwdata->axisBufferOffset[i]; + strlcpy( hwdata->axisName[0], hwdata->axisName[i], 32 ); + + // Put the old 0 here + hwdata->axisBufferOffset[i] = tmpoffset; + strlcpy( hwdata->axisName[i], tmpstr, 32 ); + + continue; + } + + if ( ( strcasecmp( &hwdata->axisName[i][0], "Y-Axis" ) == 0 ) && ( i != 1 ) ) { + // Back up the position 1 axis data + tmpoffset = hwdata->axisBufferOffset[1]; + strlcpy( tmpstr, hwdata->axisName[1], 32 ); + + // Move this one to position 1 + hwdata->axisBufferOffset[1] = hwdata->axisBufferOffset[i]; + strlcpy( hwdata->axisName[1], hwdata->axisName[i], 32 ); + + // Put the old 1 here + hwdata->axisBufferOffset[i] = tmpoffset; + strlcpy( hwdata->axisName[i], tmpstr, 32 ); + + continue; + } + } + + /* Query offsets in ReadDevice buffer for buttons' data */ + for (i = 0; i < joystick->nbuttons; i++) { +#if OLDSDK + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_BUTTON_OFFSET, i, &(hwdata->buttonBufferOffset[i]), 4); +#else + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_BUTTON_OFFSET, i, &(hwdata->buttonBufferOffset[i]), 4); +#endif + } + + /* Query offsets in ReadDevice buffer for hats' data */ + for (i = 0; i < joystick->nhats; i++) { +#if OLDSDK + result = result && SDL_IAIN->AIN_Query(hwdata->context, id, AINQ_HAT_OFFSET, i, &(hwdata->hatBufferOffset[i]), 4); +#else + result = result && SDL_IAIN->Query(hwdata->context, id, AINQ_HAT_OFFSET, i, &(hwdata->hatBufferOffset[i]), 4); +#endif + } + + if (result) { + dprintf("Successful\n"); + return 0; + } + } + +#if OLDSDK + SDL_IAIN->AIN_ReleaseDevice (joystickContext, handle); +#else + SDL_IAIN->ReleaseDevice (joystickContext, handle); +#endif + } + + SDL_SetError("Failed to open device\n"); + + dprintf("Failed\n"); + + 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. + */ +static void +AMIGAINPUT_Update(SDL_Joystick * joystick) +{ + struct joystick_hwdata *hwdata = joystick->hwdata; + void *buffer; + + //dprintf("Called %p\n", hwdata); + + /* + * Poll device for data + */ +#if OLDSDK + if (hwdata && SDL_IAIN->AIN_ReadDevice(hwdata->context, hwdata->handle, &buffer)) +#else + if (hwdata && SDL_IAIN->ReadDevice(hwdata->context, hwdata->handle, &buffer)) +#endif + { + int i; + + /* Extract axis data from buffer and notify SDL of any changes + * in axis state + */ + for (i = 0; i < joystick->naxes; i++) { + int axisdata = BUFFER_OFFSET(buffer, hwdata->axisBufferOffset[i]); + + /* Clamp axis data to 16-bits to work around possible AI driver bugs */ + if (axisdata > 32767) axisdata = 32767; + if (axisdata < -32768) axisdata = -32768; + + if (axisdata != hwdata->axisData[i]) { + SDL_PrivateJoystickAxis(joystick, i, (Sint16)axisdata); + hwdata->axisData[i] = axisdata; + } + } + + /* Extract button data from buffer and notify SDL of any changes + * in button state + * + * Note: SDL doesn't support analog buttons. + */ + for (i = 0; i < joystick->nbuttons; i++) { + int buttondata = BUFFER_OFFSET(buffer, hwdata->buttonBufferOffset[i]); + + if (buttondata != hwdata->buttonData[i]) { + SDL_PrivateJoystickButton(joystick, i, buttondata ? SDL_PRESSED : SDL_RELEASED); + hwdata->buttonData[i] = buttondata; + } + } + + /* Extract hat data from buffer and notify SDL of any changes + * in hat state + */ + for (i = 0; i < joystick->nhats; i++) { + int hatdata = BUFFER_OFFSET(buffer, hwdata->hatBufferOffset[i]); + + if (hatdata != hwdata->hatData[i]) { + SDL_PrivateJoystickHat(joystick, i, AMIGAINPUT_MapHatData(hatdata)); + hwdata->hatData[i] = hatdata; + } + } + } +} + +/* Function to close a joystick after use */ +static void +AMIGAINPUT_Close(SDL_Joystick * joystick) +{ + dprintf("Closing joystick #%d (AI ID=%d)\n", joystick->instance_id, joystickList[joystick->instance_id].id); + +#if OLDSDK + SDL_IAIN->AIN_ReleaseDevice(joystick->hwdata->context, joystick->hwdata->handle); +#else + SDL_IAIN->ReleaseDevice(joystick->hwdata->context, joystick->hwdata->handle); +#endif + + SDL_free(joystick->hwdata); + joystick->hwdata = NULL; +} + +/* Function to perform any system-specific joystick related cleanup */ +static void +AMIGAINPUT_Quit(void) +{ + uint32 i; + +#if 0 + + // TODO: check whether this kind of work around makes sense anymore. Anyway, + // SDL_Joysticks declaration has changed so code needs work in case of still necessary. + + // PG + // Close any open joysticks before quitting. + // This stops a hang on exit for bad SDL software that doesn't + // explicitly close all their joysticks. + if (SDL_joysticks) { + for (i=0; SDL_joysticks[i]; ++i) { + SDL_SYS_JoystickClose( SDL_joysticks[i] ); + + /* Free the data associated with this joystick */ + if ( SDL_joysticks[i]->axes ) { + SDL_free(SDL_joysticks[i]->axes); + } + if ( SDL_joysticks[i]->hats ) { + SDL_free(SDL_joysticks[i]->hats); + } + if ( SDL_joysticks[i]->balls ) { + SDL_free(SDL_joysticks[i]->balls); + } + if ( SDL_joysticks[i]->buttons ) { + SDL_free(SDL_joysticks[i]->buttons); + } + + SDL_free(SDL_joysticks[i]); + SDL_joysticks[i] = NULL; + } + } + +#endif + + for (i = 0; i < joystickCount; i++) + SDL_free((char *)joystickList[i].name); + + joystickCount = 0; + + if (joystickContext) { +#if OLDSDK + SDL_IAIN->AIN_DeleteContext(joystickContext); +#else + SDL_IAIN->DeleteContext(joystickContext); +#endif + joystickContext = NULL; + } + + AMIGAINPUT_CloseLibrary(); +} + +static SDL_JoystickGUID +AMIGAINPUT_GetDeviceGUID(int device_index) +{ + SDL_JoystickGUID guid; + /* the GUID is just the first 16 chars of the name for now */ + const char *name = AMIGAINPUT_GetDeviceName(device_index); + SDL_zero( guid ); + SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + return guid; +} + +static int +AMIGAINPUT_Rumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) +{ + dprintf("Called\n"); + return SDL_Unsupported(); +} + +static int +AMIGAINPUT_RumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble) +{ + dprintf("Called\n"); + return SDL_Unsupported(); +} + +static SDL_bool +AMIGAINPUT_HasLED(SDL_Joystick * joystick) +{ + dprintf("Called\n"); + return SDL_FALSE; +} + +static int +AMIGAINPUT_SetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue) +{ + dprintf("Called\n"); + return SDL_Unsupported(); +} + +static int +AMIGAINPUT_SetSensorsEnabled(SDL_Joystick * joystick, SDL_bool enabled) +{ + dprintf("Called\n"); + return SDL_Unsupported(); +} + +static SDL_bool +AMIGAINPUT_GetGamepadMapping(int device_index, SDL_GamepadMapping * out) +{ + dprintf("Called\n"); + return SDL_FALSE; +} + +SDL_JoystickDriver SDL_AMIGAINPUT_JoystickDriver = +{ + AMIGAINPUT_Init, + AMIGAINPUT_GetCount, + AMIGAINPUT_Detect, + AMIGAINPUT_GetDeviceName, + AMIGAINPUT_GetDevicePlayerIndex, + AMIGAINPUT_SetDevicePlayerIndex, + AMIGAINPUT_GetDeviceGUID, + AMIGAINPUT_GetDeviceInstanceID, + AMIGAINPUT_Open, + AMIGAINPUT_Rumble, + AMIGAINPUT_RumbleTriggers, + AMIGAINPUT_HasLED, + AMIGAINPUT_SetLED, + AMIGAINPUT_SetSensorsEnabled, + AMIGAINPUT_Update, + AMIGAINPUT_Close, + AMIGAINPUT_Quit, + AMIGAINPUT_GetGamepadMapping +}; + +#endif /* SDL_JOYSTICK_AMIGAINPUT || SDL_JOYSTICK_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/loadso/amigaos4/SDL_sysloadso.c b/src/loadso/amigaos4/SDL_sysloadso.c new file mode 100644 index 0000000000000..3006420b779f7 --- /dev/null +++ b/src/loadso/amigaos4/SDL_sysloadso.c @@ -0,0 +1,187 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_LOADSO_AMIGAOS4 + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* System dependent library loading routines */ + +#include +#include + +static struct Library *elfBase; +static struct Library *dosBase; + +static struct ElfIFace *iElf; +static struct DOSIFace *iDOS; + +#include "SDL_loadso.h" +#include "../../video/amigaos4/SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +typedef struct { + Elf32_Handle elf_handle; + APTR shared_object; +} OS4_ObjectHandle; + +static void +OS4_CloseLibs() +{ + OS4_DropInterface((void *)&iElf); + OS4_DropInterface((void *)&iDOS); + + iElf = NULL; + iDOS = NULL; + + OS4_CloseLibrary(&elfBase); + OS4_CloseLibrary(&dosBase); + + elfBase = NULL; + dosBase = NULL; +} + +static BOOL +OS4_OpenLibs() +{ + BOOL result = FALSE; + + if (!elfBase) { + elfBase = OS4_OpenLibrary("elf.library", 52); + + if (elfBase) { + iElf = (struct ElfIFace *) OS4_GetInterface(elfBase); + } + } + + if (!dosBase) { + dosBase = OS4_OpenLibrary("dos.library", 51); + + if (dosBase) { + iDOS = (struct DOSIFace *) OS4_GetInterface(dosBase); + } + } + + if (iElf && iDOS) + { + result = TRUE; + } else { + OS4_CloseLibs(); + } + + return result; +} + +void * +SDL_LoadObject(const char *sofile) +{ + if (OS4_OpenLibs()) { + OS4_ObjectHandle *handle = SDL_malloc(sizeof(OS4_ObjectHandle)); + + if (handle) { + BPTR seglist = iDOS->GetProcSegList(NULL, GPSLF_RUN); + + if (seglist) { + Elf32_Handle eh = NULL; + + iDOS->GetSegListInfoTags(seglist, GSLI_ElfHandle, &eh, TAG_DONE); + + dprintf("Elf handle %p\n", eh); + + if (eh) { + APTR so = iElf->DLOpen(eh, sofile, 0); + + if (so) { + dprintf("'%s' loaded\n", sofile); + + handle->elf_handle = eh; + handle->shared_object = so; + + return handle; + } else { + dprintf("DLOpen failed for '%s'\n", sofile); + SDL_SetError("DLOpen failed for '%s'", sofile); + } + } else { + dprintf("Failed to get elf handle of running task\n"); + SDL_SetError("Failed to get elf handle"); + } + } else { + dprintf("Failed to get seglist\n"); + SDL_SetError("Failed to get seglist"); + } + + SDL_free(handle); + } + } + + return NULL; +} + +void * +SDL_LoadFunction(void *handle, const char *name) +{ + void *symbol = NULL; + + if (OS4_OpenLibs() && handle) { + APTR address = NULL; + OS4_ObjectHandle *oh = handle; + + Elf32_Error result = iElf->DLSym(oh->elf_handle, oh->shared_object, name, &address); + + if (result == ELF32_NO_ERROR) { + symbol = address; + dprintf("Symbol '%s' found at %p\n", name, address); + } else { + dprintf("Symbol '%s' not found\n", name); + SDL_SetError("Symbol '%s' not found", name); + } + } + + return symbol; +} + +void +SDL_UnloadObject(void *handle) +{ + if (OS4_OpenLibs() && handle) { + OS4_ObjectHandle *oh = handle; + + Elf32_Error result = iElf->DLClose(oh->elf_handle, oh->shared_object); + + dprintf("DLClose %s\n", (result == ELF32_NO_ERROR) ? "OK" : "failed" ); + +/* BUG: testloadso crashes on Final Edition...removed this block for now, until a solution is found. + IElf->CloseElfTags( + oh->elf_handle, + TAG_DONE); +*/ + SDL_free(handle); + } + + OS4_CloseLibs(); +} + +#endif /* SDL_LOADSO_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/main/amigaos4/SDL_dummy_main.c b/src/main/amigaos4/SDL_dummy_main.c new file mode 100644 index 0000000000000..0174136b2211d --- /dev/null +++ b/src/main/amigaos4/SDL_dummy_main.c @@ -0,0 +1,28 @@ +/* + SDL_dummy_main.c, placed in the public domain by Sam Lantinga 3/13/14 +*/ +#include "../../SDL_internal.h" + +/* 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 */ +int +SDL_main_stub_symbol(void); + +int +SDL_main_stub_symbol(void) +{ + return 0; +} +#endif + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/main/amigaos4/SDL_os4debug.h b/src/main/amigaos4/SDL_os4debug.h new file mode 100644 index 0000000000000..6133af3a877a5 --- /dev/null +++ b/src/main/amigaos4/SDL_os4debug.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef SDL_OS4DEBUG_H +#define SDL_OS4DEBUG_H + +#include + +#ifndef DEBUG +# define dprintf(format, args...) +# define kprintf(format, args...) +#else /* DEBUG */ +# define dprintf(format, args...) IExec->DebugPrintF("[%s] " format, __PRETTY_FUNCTION__ , ## args) +//# define dprintf(format, args...)((struct ExecIFace *)((*(struct ExecBase **)4)->MainInterface))->DebugPrintF("[%s] " format, __PRETTY_FUNCTION__ , ## args) +# define kprintf(format, args...)((struct ExecIFace *)((*(struct ExecBase **)4)->MainInterface))->DebugPrintF(format, ## args) +#endif /* DEBUG */ + +#endif /* SDL_OS4DEBUG_H */ diff --git a/src/main/amigaos4/SDL_os4version.c b/src/main/amigaos4/SDL_os4version.c new file mode 100644 index 0000000000000..d8da95fa91826 --- /dev/null +++ b/src/main/amigaos4/SDL_os4version.c @@ -0,0 +1,25 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifdef __AMIGADATE__ +static const char* const version __attribute__ ((used)) = "\0$VER: libSDL2.so 0.14 (" __AMIGADATE__ ")\0"; +#endif + diff --git a/src/misc/amigaos4/SDL_sysurl.c b/src/misc/amigaos4/SDL_sysurl.c new file mode 100644 index 0000000000000..b3f3498c93a97 --- /dev/null +++ b/src/misc/amigaos4/SDL_sysurl.c @@ -0,0 +1,65 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../SDL_sysurl.h" + +#include "../../video/amigaos4/SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include + +int +SDL_SYS_OpenURL(const char *url) +{ + int result = -1; + + struct Library* dosBase = OS4_OpenLibrary(DOSNAME, 50); + + if (dosBase) { + struct DOSIFace* iDOS = (struct DOSIFace *)OS4_GetInterface(dosBase); + + if (iDOS) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "URL:%s", url); + + BPTR handle = iDOS->Open(buffer, MODE_OLDFILE); + + if (handle) { + iDOS->Close(handle); + dprintf("URL '%s' opened\n", url); + result = 0; + } else { + dprintf("Failed to open URL '%s'\n", url); + } + + OS4_DropInterface((void *)&iDOS); + } + + OS4_CloseLibrary(&dosBase); + } + + return result; +} + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 8288b0f3ccc00..20699734381ad 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -92,6 +92,9 @@ this should probably be removed at some point in the future. --ryan. */ #if !SDL_RENDER_DISABLED static const SDL_RenderDriver *render_drivers[] = { +#if SDL_VIDEO_RENDER_AMIGAOS4 + &OS4_RenderDriver, +#endif #if SDL_VIDEO_RENDER_D3D &D3D_RenderDriver, #endif diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 84411082bc030..9cd1c4cc22aae 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -249,6 +249,7 @@ extern SDL_RenderDriver GLES_RenderDriver; extern SDL_RenderDriver DirectFB_RenderDriver; extern SDL_RenderDriver METAL_RenderDriver; extern SDL_RenderDriver PSP_RenderDriver; +extern SDL_RenderDriver OS4_RenderDriver; extern SDL_RenderDriver SW_RenderDriver; extern SDL_RenderDriver VITA_GLES2_RenderDriver; extern SDL_RenderDriver VITA_GXM_RenderDriver; diff --git a/src/render/amigaos4/SDL_rc_draw.c b/src/render/amigaos4/SDL_rc_draw.c new file mode 100644 index 0000000000000..ee3a2fc72234a --- /dev/null +++ b/src/render/amigaos4/SDL_rc_draw.c @@ -0,0 +1,619 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_AMIGAOS4 && !SDL_RENDER_DISABLED + +#include "SDL_render_compositing.h" +#include "SDL_rc_draw.h" + +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +typedef struct { + int x1, y1, x2, y2; + Uint32 (*blendfp)(Uint32, Uint8, Uint8, Uint8, Uint8); + Uint32 *baseaddress; + Uint32 width; + SDL_bool last; + Uint8 sr; + Uint8 sg; + Uint8 sb; + Uint8 sa; +} OS4_LineData; + +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#define ROUNDF(a) (int)((a) + 0.5f) + +static inline Uint32* +OS4_GetMemoryAddress(Uint32 * memory, Uint32 width, Uint16 x, Uint16 y) +{ + return memory + x + y * width; +} + +static inline Uint32 +OS4_GetPixel(Uint32 * memory, Uint32 width, Uint16 x, Uint16 y) +{ + return *(memory + x + y * width); +} + +static inline void +OS4_SetPixel(Uint32 * memory, Uint32 width, Uint16 x, Uint16 y, Uint32 color) +{ + *(memory + x + y * width) = color; +} + +static inline Uint8 +ALPHA(Uint32 c) +{ + return (c >> 24); +} + +static inline Uint8 +RED(Uint32 c) +{ + return (c >> 16); +} + +static inline Uint8 +GREEN(Uint32 c) +{ + return (c >> 8); +} + +static inline Uint8 +BLUE(Uint32 c) +{ + return c; +} + +static inline Uint8 +MUL(Uint8 a, Uint8 b) +{ + Uint32 u = (a * b) / 255; + return u; +} + +static inline Uint8 +ADD(Uint8 a, Uint8 b) +{ + Uint32 c = a + b; + + if (c > 255) c = 255; + + return c; +} + +static Uint32 +BlendPoint(Uint32 old, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa) +{ + Uint8 dr, dg, db, da, one_minus_alpha; + + one_minus_alpha = 255 - sa; + + dr = sr + MUL(one_minus_alpha, RED(old)); + dg = sg + MUL(one_minus_alpha, GREEN(old)); + db = sb + MUL(one_minus_alpha, BLUE(old)); + da = sa + MUL(one_minus_alpha, ALPHA(old)); + + return da << 24 | dr << 16 | dg << 8 | db; +} + +static Uint32 +AddPoint(Uint32 old, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa) +{ + Uint8 dr, dg, db, da; + + dr = ADD(sr, RED(old)); + dg = ADD(sg, GREEN(old)); + db = ADD(sb, BLUE(old)); + da = ALPHA(old); + + return da << 24 | dr << 16 | dg << 8 | db; +} + +static Uint32 +ModPoint(Uint32 old, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa) +{ + Uint8 dr, dg, db, da; + + dr = MUL(sr, RED(old)); + dg = MUL(sg, GREEN(old)); + db = MUL(sb, BLUE(old)); + da = ALPHA(old); + + return da << 24 | dr << 16 | dg << 8 | db; +} + +static Uint32 +NopPoint(Uint32 old, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa) +{ + return old; +} + +int +OS4_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, + int count, SDL_BlendMode mode, Uint8 a, Uint8 r, Uint8 g, Uint8 b) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + struct BitMap *bitmap = OS4_ActivateRenderer(renderer); + int i, status; + + int minx, miny, maxx, maxy; + + if (!bitmap) { + return -1; + } + + minx = data->cliprect.x; + miny = data->cliprect.y; + maxx = data->cliprect.x + data->cliprect.w - 1; + maxy = data->cliprect.y + data->cliprect.h - 1; + + if (mode == SDL_BLENDMODE_NONE) { + + int32 ret = 0; + + const Uint32 color = a << 24 | r << 16 | g << 8 | b; + + for (i = 0; i < count; ++i) { + + int x, y; + + x = points[i].x; + y = points[i].y; + + /* Clipping - is it possible clip with RastPort? */ + if (x < minx || x > maxx || y < miny || y > maxy) { + continue; + } + + ret |= data->iGraphics->WritePixelColor( + &data->rastport, + x, + y, + color); + } + + status = ret ? -1 : 0; + + } else { + + APTR baseaddress; + uint32 bytesperrow; + + APTR lock = data->iGraphics->LockBitMapTags( + bitmap, + LBM_BaseAddress, &baseaddress, + LBM_BytesPerRow, &bytesperrow, + TAG_DONE); + + if (lock) { + + Uint32 (*blendfp)(Uint32, Uint8, Uint8, Uint8, Uint8); + + const Uint32 width = bytesperrow / 4; + Uint8 sr, sg, sb, sa; + + switch (mode) { + case SDL_BLENDMODE_BLEND: + sr = MUL(a, r); + sg = MUL(a, g); + sb = MUL(a, b); + sa = a; + blendfp = BlendPoint; + break; + case SDL_BLENDMODE_ADD: + sr = MUL(a, r); + sg = MUL(a, g); + sb = MUL(a, b); + sa = 0; + blendfp = AddPoint; + break; + case SDL_BLENDMODE_MOD: + sr = r; + sg = g; + sb = b; + sa = 0; + blendfp = ModPoint; + break; + default: + dprintf("Unknown blend mode %d\n", mode); + sr = r; + sg = g; + sb = b; + sa = a; + blendfp = NopPoint; + break; + } + + for (i = 0; i < count; ++i) { + Uint32 newcolor, oldcolor; + int x, y; + + x = points[i].x; + y = points[i].y; + + /* Clipping */ + if (x < minx || x > maxx || y < miny || y > maxy) { + continue; + } + + oldcolor = OS4_GetPixel(baseaddress, width, x, y); + + newcolor = blendfp(oldcolor, sr, sg, sb, sa); + + OS4_SetPixel(baseaddress, width, x, y, newcolor); + } + + data->iGraphics->UnlockBitMap(lock); + + status = 0; + } else { + dprintf("Lock failed\n"); + status = -1; + } + } + + return status; +} + +static void +OS4_HLine(OS4_LineData * data) +{ + int x, minx, maxx; + Uint32 *memory; + + if (data->x1 < data->x2) { + minx = data->x1; + maxx = data->x2; + + if (!data->last) { + --maxx; + } + } else { + minx = data->x2; + maxx = data->x1; + + if (!data->last) { + ++minx; + } + } + + memory = OS4_GetMemoryAddress(data->baseaddress, data->width, minx, data->y1); + + for (x = minx; x <= maxx; ++x) { + Uint32 oldcolor, newcolor; + + oldcolor = *memory; + newcolor = data->blendfp(oldcolor, data->sr, data->sg, data->sb, data->sa); + *memory++ = newcolor; + } +} + +static void +OS4_VLine(OS4_LineData * data) +{ + int y, miny, maxy; + Uint32 *memory; + + if (data->y1 < data->y2) { + miny = data->y1; + maxy = data->y2; + + if (!data->last) { + --maxy; + } + } else { + miny = data->y2; + maxy = data->y1; + + if (!data->last) { + ++miny; + } + } + + memory = OS4_GetMemoryAddress(data->baseaddress, data->width, data->x1, miny); + + for (y = miny; y <= maxy; ++y) { + Uint32 oldcolor, newcolor; + + oldcolor = *memory; + newcolor = data->blendfp(oldcolor, data->sr, data->sg, data->sb, data->sa); + *memory = newcolor; + memory += data->width; + } +} + +static void +OS4_DLine(OS4_LineData * data) +{ + int x, y, startx, starty, endx, endy, ystep, width; + Uint32 *memory; + + if (data->x1 < data->x2) { + startx = data->x1; + starty = data->y1; + + endx = data->x2; + endy = data->y2; + + if (!data->last) { + //--endx; + } + } else { + startx = data->x2; + starty = data->y2; + + endx = data->x1; + endy = data->y1; + + if (!data->last) { + //++startx; + } + } + + if (endy < starty) { + ystep = -1; + width = -data->width; + } else { + ystep = 1; + width = data->width; + } + + memory = OS4_GetMemoryAddress(data->baseaddress, data->width, startx, starty); + + //dprintf("%d, %d -> %d, %d, ystep %d\n", data->x1, data->y1, data->x2, data->y2, ystep); + + for (x = startx, y = starty; x <= endx; ++x, y += ystep) { + Uint32 oldcolor, newcolor; + + oldcolor = *memory; + newcolor = data->blendfp(oldcolor, data->sr, data->sg, data->sb, data->sa); + *memory++ = newcolor; + memory += width; + } +} + +static void +OS4_Line(OS4_LineData *data) +{ + float ystep; + int x, y, startx, starty, endx, endy; + Uint32 *memory; + + if (data->x1 < data->x2) { + startx = data->x1; + starty = data->y1; + + endx = data->x2; + endy = data->y2; + } else { + startx = data->x2; + starty = data->y2; + + endx = data->x1; + endy = data->y1; + } + + // TODO: last + ystep = (float)(endy - starty) / (float)(endx - startx); + + //dprintf("%d, %d -> %d, %d, ystep %d\n", data->x1, data->y1, data->x2, data->y2, (int)(10 * ystep)); + + memory = OS4_GetMemoryAddress(data->baseaddress, data->width, startx, starty); + + if (ystep > 0.5f || ystep < -0.5f) { + + float xstep = 1.0f / ystep; + float fx = startx; + + int lastx = startx; + + for (y = starty ; y <= endy; fx += xstep, ++y) { + + Uint32 oldcolor, newcolor; + + x = ROUNDF(fx); + + oldcolor = *memory; + newcolor = data->blendfp(oldcolor, data->sr, data->sg, data->sb, data->sa); + *memory = newcolor; + memory += data->width; + + memory += (x - lastx); + lastx = x; + } + + } else { + float fy = starty; + + int lasty = starty; + + for (x = startx ; x <= endx; ++x, fy += ystep ) { + Uint32 oldcolor, newcolor; + int diff; + + y = ROUNDF(fy); + + oldcolor = *memory; + newcolor = data->blendfp(oldcolor, data->sr, data->sg, data->sb, data->sa); + *memory++ = newcolor; + + diff = y - lasty; + if (diff < 0) { + memory -= data->width; + lasty = y; + } else if (diff > 0) { + memory += data->width; + lasty = y; + } + } + } +} + +static void +OS4_BlendLine(OS4_LineData * data) +{ + if (data->y1 == data->y2) { + OS4_HLine(data); + } else if (data->x1 == data->x2) { + OS4_VLine(data); + } else if (ABS(data->x1 - data->x2) == ABS(data->y1 - data->y2)) { + OS4_DLine(data); + } else { + OS4_Line(data); + } +} + +int +OS4_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, + int count, SDL_BlendMode mode, Uint8 a, Uint8 r, Uint8 g, Uint8 b) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + struct BitMap *bitmap = OS4_ActivateRenderer(renderer); + + int i, status; + + if (!bitmap) { + return -1; + } + + if (mode == SDL_BLENDMODE_NONE) { + + const Uint32 color = a << 24 | r << 16 | g << 8 | b; + + data->iGraphics->SetRPAttrs(&data->rastport, RPTAG_APenColor, color, TAG_DONE); + + for (i = 0; i < count - 1; ++i) { + + int x1, y1, x2, y2; + + x1 = points[i].x; + y1 = points[i].y; + x2 = points[i + 1].x; + y2 = points[i + 1].y; + + /* Clipping - is it possible to do with RastPort? */ + if (!SDL_IntersectRectAndLine(&data->cliprect, &x1, &y1, &x2, &y2)) { + continue; + } + + data->iGraphics->Move( + &data->rastport, + x1, + y1); + + data->iGraphics->Draw( + &data->rastport, + x2, + y2); + } + + status = 0; + } else { + + APTR baseaddress; + uint32 bytesperrow; + + APTR lock = data->iGraphics->LockBitMapTags( + bitmap, + LBM_BaseAddress, &baseaddress, + LBM_BytesPerRow, &bytesperrow, + TAG_DONE); + + if (lock) { + + OS4_LineData ld; + ld.baseaddress = baseaddress; + ld.width = bytesperrow / 4; + ld.last = SDL_FALSE; + + switch (mode) { + case SDL_BLENDMODE_BLEND: + ld.sr = MUL(a, r); + ld.sg = MUL(a, g); + ld.sb = MUL(a, b); + ld.sa = a; + ld.blendfp = BlendPoint; + break; + case SDL_BLENDMODE_ADD: + ld.sr = MUL(a, r); + ld.sg = MUL(a, g); + ld.sb = MUL(a, b); + ld.sa = 0; + ld.blendfp = AddPoint; + break; + case SDL_BLENDMODE_MOD: + ld.sr = r; + ld.sg = g; + ld.sb = b; + ld.sa = a; + ld.blendfp = ModPoint; + break; + default: + dprintf("Unknown blend mode %d\n", mode); + ld.sr = r; + ld.sg = g; + ld.sb = b; + ld.sa = a; + ld.blendfp = NopPoint; + break; + } + + for (i = 0; i < count - 1; ++i) { + + ld.x1 = points[i].x; + ld.y1 = points[i].y; + ld.x2 = points[i + 1].x; + ld.y2 = points[i + 1].y; + + /* Clipping */ + if (!SDL_IntersectRectAndLine(&data->cliprect, &ld.x1, &ld.y1, &ld.x2, &ld.y2)) { + continue; + } + + if (i == count - 2) { + ld.last = SDL_TRUE; + } + + OS4_BlendLine(&ld); + } + + data->iGraphics->UnlockBitMap(lock); + + status = 0; + } else { + dprintf("Lock failed\n"); + status = -1; + } + + } + + return status; +} + +#endif /* !SDL_RENDER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/amigaos4/SDL_rc_draw.h b/src/render/amigaos4/SDL_rc_draw.h new file mode 100644 index 0000000000000..1998ecded15da --- /dev/null +++ b/src/render/amigaos4/SDL_rc_draw.h @@ -0,0 +1,37 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_rc_draw_h +#define _SDL_rc_draw_h + +#include "../SDL_sysrender.h" + +extern int OS4_RenderDrawPoints(SDL_Renderer * renderer, + const SDL_Point * points, int count, SDL_BlendMode mode, Uint8 a, Uint8 r, Uint8 g, Uint8 b); + +extern int OS4_RenderDrawLines(SDL_Renderer * renderer, + const SDL_Point * points, int count, SDL_BlendMode mode, Uint8 a, Uint8 r, Uint8 g, Uint8 b); + +#endif + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/amigaos4/SDL_rc_texture.c b/src/render/amigaos4/SDL_rc_texture.c new file mode 100644 index 0000000000000..b5af26fb1a4be --- /dev/null +++ b/src/render/amigaos4/SDL_rc_texture.c @@ -0,0 +1,355 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_AMIGAOS4 && !SDL_RENDER_DISABLED + +#include "SDL_render_compositing.h" +#include "SDL_rc_texture.h" + +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static SDL_bool +OS4_IsBlendModeSupported(SDL_BlendMode mode) +{ + switch (mode) { + case SDL_BLENDMODE_NONE: + case SDL_BLENDMODE_BLEND: + case SDL_BLENDMODE_ADD: + //dprintf("Texture blend mode: %d\n", mode); + return SDL_TRUE; + default: + dprintf("Not supported blend mode %d\n", mode); + return SDL_FALSE; + } +} + +int +OS4_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + OS4_TextureData *texturedata; + + if (texture->format != SDL_PIXELFORMAT_ARGB8888) { + return SDL_SetError("Not supported texture format"); + } + + if (!SDL_PixelFormatEnumToMasks + (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + return SDL_SetError("Unknown texture format"); + } + + //dprintf("Allocation VRAM bitmap %d*%d*%d for texture\n", texture->w, texture->h, bpp); + + texturedata = SDL_calloc(1, sizeof(*texturedata)); + if (!texturedata) + { + dprintf("Failed to allocate driver data\n"); + return SDL_OutOfMemory(); + } + + texturedata->bitmap = OS4_AllocBitMap(renderer, texture->w, texture->h, bpp); + + if (!texturedata->bitmap) { + dprintf("Failed to allocate bitmap\n"); + SDL_free(texturedata); + return SDL_SetError("Failed to allocate bitmap"); + } + + /* Check texture parameters just for debug */ + //OS4_IsColorModEnabled(texture); + OS4_IsBlendModeSupported(texture->blendMode); + + texture->driverdata = texturedata; + + return 0; +} + +static SDL_bool +OS4_ModulateRGB(SDL_Renderer * renderer, SDL_Texture * texture, Uint8 * src, int pitch) +{ + SDL_bool result = SDL_FALSE; + + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + if (texturedata->finalbitmap) { + APTR baseaddress; + uint32 bytesperrow; + + APTR lock = data->iGraphics->LockBitMapTags( + texturedata->finalbitmap, + LBM_BaseAddress, &baseaddress, + LBM_BytesPerRow, &bytesperrow, + TAG_DONE); + + if (lock) { + int y; + + for (y = 0; y < texture->h; y++) { + + Uint32 *readaddress = (Uint32 *)(src + y * pitch); + Uint32 *writeaddress = (Uint32 *)(baseaddress + y * bytesperrow); + + int x; + + for (x = 0; x < texture->w; x++) { + + Uint32 oldcolor = readaddress[x]; + Uint32 newcolor = (oldcolor & 0xFF000000); + + Uint8 r = (oldcolor & 0x00FF0000) >> 16; + Uint8 g = (oldcolor & 0x0000FF00) >> 8; + Uint8 b = (oldcolor & 0x000000FF); + + newcolor |= ((r * texture->r) / 255) << 16; + newcolor |= ((g * texture->g) / 255) << 8; + newcolor |= ((b * texture->b) / 255); + + writeaddress[x] = newcolor; + } + } + + data->iGraphics->UnlockBitMap(texturedata->finalbitmap); + + result = SDL_TRUE; + } else { + dprintf("Lock failed\n"); + } + } + + return result; +} + +static SDL_bool +OS4_NeedRemodulation(SDL_Texture * texture) +{ + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + if (texture->r != texturedata->r || + texture->g != texturedata->g || + texture->b != texturedata->b || + texturedata->finalbitmap == NULL) { + + return SDL_TRUE; + } + + return SDL_FALSE; +} + +int +OS4_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + /* Modulate only when needed, it's CPU heavy */ + if (OS4_IsColorModEnabled(texture) && OS4_NeedRemodulation(texture)) { + + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + if (!texturedata->rambuf) { + struct BitMap *oldRastPortBM; + + if (!(texturedata->rambuf = SDL_malloc(texture->w * texture->h * sizeof(Uint32)))) { + dprintf("Failed to allocate ram buffer\n"); + return SDL_OutOfMemory(); + } + + /* Copy texture from VRAM to RAM buffer for faster color modulation. We also + temporarily borrow rastport from renderer */ + oldRastPortBM = data->rastport.BitMap; + + data->rastport.BitMap = texturedata->bitmap; + + data->iGraphics->ReadPixelArray( + &data->rastport, + 0, + 0, + texturedata->rambuf, + 0, + 0, + texture->w * sizeof(Uint32), + PIXF_A8R8G8B8, + texture->w, + texture->h); + + data->rastport.BitMap = oldRastPortBM; + } + + if (!texturedata->finalbitmap) { + if (!(texturedata->finalbitmap = OS4_AllocBitMap(renderer, texture->w, texture->h, 32))) { + dprintf("Failed to allocate final bitmap\n"); + return SDL_OutOfMemory(); + } + } + + if (!OS4_ModulateRGB(renderer, texture, texturedata->rambuf, texture->w * sizeof(Uint32))) { + return SDL_SetError("RGB modulation failed"); + } + + /* Remember last values so that we can avoid re-modulation with same parameters */ + texturedata->r = texture->r; + texturedata->g = texture->g; + texturedata->b = texture->b; + } + + return 0; +} + +int +OS4_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, int pitch) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + int32 ret = data->iGraphics->BltBitMapTags( + BLITA_Source, pixels, + BLITA_SrcType, BLITT_ARGB32, + BLITA_SrcBytesPerRow, pitch, + BLITA_Dest, texturedata->bitmap, + BLITA_DestX, rect->x, + BLITA_DestY, rect->y, + BLITA_Width, rect->w, + BLITA_Height, rect->h, + TAG_DONE); + + if (ret != -1) { + dprintf("BltBitMapTags(): %d\n", ret); + return SDL_SetError("BltBitMapTags failed"); + } + + if (OS4_IsColorModEnabled(texture)) { + + if (!texturedata->finalbitmap) { + if (!(texturedata->finalbitmap = OS4_AllocBitMap(renderer, texture->w, texture->h, 32))) { + dprintf("Failed to allocate final bitmap\n"); + return SDL_OutOfMemory(); + } + } + + // This can be really slow, if done per frame + if (!OS4_ModulateRGB(renderer, texture, (Uint8 *)pixels, pitch)) { + return SDL_SetError("RGB modulation failed"); + } + } + + return 0; +} + +int +OS4_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, void **pixels, int *pitch) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + APTR baseaddress; + uint32 bytesperrow; + + //dprintf("Called\n"); + + texturedata->lock = data->iGraphics->LockBitMapTags( + texturedata->bitmap, + LBM_BaseAddress, &baseaddress, + LBM_BytesPerRow, &bytesperrow, + TAG_DONE); + + if (texturedata->lock) { + *pixels = + (void *) ((Uint8 *) baseaddress + rect->y * bytesperrow + + rect->x * 4); + + *pitch = bytesperrow; + + return 0; + } else { + dprintf("Lock failed\n"); + return SDL_SetError("Lock failed"); + } +} + +void +OS4_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + //dprintf("Called\n"); + + if (texturedata->lock) { + data->iGraphics->UnlockBitMap(texturedata->lock); + texturedata->lock = NULL; + } +} + +int +OS4_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + if (texture) { + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + data->target = texturedata->bitmap; + + //dprintf("Render target texture %p (bitmap %p)\n", texture, data->target); + } else { + data->target = data->bitmap; + //dprintf("Render target window\n"); + } + return 0; +} + +void +OS4_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + if (texturedata) { + if (texturedata->bitmap) { + //dprintf("Freeing texture bitmap %p\n", texturedata->bitmap); + + data->iGraphics->FreeBitMap(texturedata->bitmap); + texturedata->bitmap = NULL; + } + + if (texturedata->finalbitmap) { + data->iGraphics->FreeBitMap(texturedata->finalbitmap); + texturedata->finalbitmap = NULL; + } + + if (texturedata->rambuf) { + SDL_free(texturedata->rambuf); + texturedata->rambuf = NULL; + } + + SDL_free(texturedata); + } +} + +#endif /* !SDL_RENDER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/amigaos4/SDL_rc_texture.h b/src/render/amigaos4/SDL_rc_texture.h new file mode 100644 index 0000000000000..20e2ce013867d --- /dev/null +++ b/src/render/amigaos4/SDL_rc_texture.h @@ -0,0 +1,58 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_rc_texture_h +#define _SDL_rc_texture_h + +#include "../SDL_sysrender.h" + +typedef struct +{ + struct BitMap *bitmap; + struct BitMap *finalbitmap; /* Contains color modulated version of bitmap */ + APTR lock; + Uint8 r, g, b; /* Last known color modulation parameters */ + Uint8 *rambuf; /* Work buffer for color modulation */ +} OS4_TextureData; + +extern int OS4_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); + +extern int OS4_SetTextureColorMod(SDL_Renderer * renderer, + SDL_Texture * texture); + +extern int OS4_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, + int pitch); + +extern int OS4_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); + +extern int OS4_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, void **pixels, int *pitch); + +extern void OS4_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); + +extern void OS4_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); + +#endif + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/amigaos4/SDL_render_compositing.c b/src/render/amigaos4/SDL_render_compositing.c new file mode 100644 index 0000000000000..0d5d236dec182 --- /dev/null +++ b/src/render/amigaos4/SDL_render_compositing.c @@ -0,0 +1,969 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_AMIGAOS4 && !SDL_RENDER_DISABLED + +#include "SDL_render_compositing.h" +#include "SDL_rc_texture.h" +#include "SDL_rc_draw.h" + +#include "../SDL_sysrender.h" + +#include "../../video/SDL_sysvideo.h" +#include "../../video/amigaos4/SDL_os4window.h" +#include "../../video/amigaos4/SDL_os4video.h" + +#include +#include +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +/* AmigaOS4 (compositing) renderer implementation + +TODO: + +- SDL_BlendMode_Mod: is it impossible to accelerate? +- Blended line drawing could probably be optimized +- Batching RenderCopy(Ex) should be now possible. + +NOTE: + +- compositing is used for blended rectangles and texture blitting +- blended lines and points are drawn with the CPU as compositing doesn't support these primitives + (could try small triangles to plot a point?) +- texture color modulation is implemented by CPU + +*/ + +typedef struct { + float x, y; + float s, t, w; +} OS4_Vertex; + +static const uint16 OS4_QuadIndices[] = { + 0, 1, 2, 2, 3, 0 +}; + +typedef struct { + float srcAlpha; + float destAlpha; + uint32 flags; +} OS4_CompositingParams; + +SDL_bool +OS4_IsColorModEnabled(SDL_Texture * texture) +{ + if ((texture->r & texture->g & texture->b) != 255) { + //dprintf("Color mod enabled (%d, %d, %d)\n", texture->r, texture->g, texture->b); + return SDL_TRUE; + } + + return SDL_FALSE; +} + +struct BitMap * +OS4_AllocBitMap(SDL_Renderer * renderer, int width, int height, int depth) { + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + return data->iGraphics->AllocBitMapTags( + width, + height, + depth, + BMATags_Displayable, TRUE, + BMATags_PixelFormat, PIXF_A8R8G8B8, + //BMATags_Clear, TRUE, + TAG_DONE); +} + +struct BitMap * +OS4_ActivateRenderer(SDL_Renderer * renderer) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + if (!data->target) { + data->target = data->bitmap; + } + + if (!data->target && renderer->window) { + + int width = renderer->window->w; + int height = renderer->window->h; + int depth = 32; + + dprintf("Allocating VRAM bitmap %d*%d*%d for renderer\n", width, height, depth); + + data->target = data->bitmap = OS4_AllocBitMap(renderer, width, height, depth); + + if (!data->bitmap) { + dprintf("Allocation failed\n"); + } + } + + if (!data->solidcolor) { + int width = 1; + int height = 1; + int depth = 32; + + data->solidcolor = OS4_AllocBitMap(renderer, width, height, depth); + + if (!data->solidcolor) { + dprintf("Failed to allocate solid color bitmap\n"); + } + } + + data->rastport.BitMap = data->target; + + return data->target; +} + +static void +OS4_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + dprintf("Called with event %d\n", event->event); + + if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) { + + /* Next time ActivateRenderer() is called, new bitmap will be created */ + if (data->bitmap) { + + dprintf("Freeing renderer bitmap %p\n", data->bitmap); + + data->iGraphics->FreeBitMap(data->bitmap); + data->bitmap = NULL; + data->target = NULL; + } + } +} + +static int +OS4_GetBitMapSize(SDL_Renderer * renderer, struct BitMap * bitmap, int * w, int * h) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + if (bitmap) { + if (w) { + *w = data->iGraphics->GetBitMapAttr(bitmap, BMA_ACTUALWIDTH); + //dprintf("w=%d\n", *w); + } + if (h) { + *h = data->iGraphics->GetBitMapAttr(bitmap, BMA_HEIGHT); + //dprintf("h=%d\n", *h); + } + + return 0; + } else { + SDL_SetError("NULL bitmap"); + return -1; + } +} + +static int +OS4_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) +{ + struct BitMap * bitmap = OS4_ActivateRenderer(renderer); + + if (!bitmap) { + SDL_SetError("OS4 renderer doesn't have an output bitmap"); + return -1; + } + + return OS4_GetBitMapSize(renderer, bitmap, w, h); +} + +/* Special function to set our 1 * 1 * 32 bitmap */ +static SDL_bool +OS4_SetSolidColor(SDL_Renderer * renderer, Uint32 color) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + if (data->solidcolor) { + APTR baseaddress; + + APTR lock = data->iGraphics->LockBitMapTags( + data->solidcolor, + LBM_BaseAddress, &baseaddress, + TAG_DONE); + + if (lock) { + *(Uint32 *)baseaddress = color; + + data->iGraphics->UnlockBitMap(data->solidcolor); + + return SDL_TRUE; + } else { + dprintf("Lock failed\n"); + } + } + + return SDL_FALSE; +} + +static uint32 +OS4_ConvertBlendMode(SDL_BlendMode mode) +{ + switch (mode) { + case SDL_BLENDMODE_NONE: + return COMPOSITE_Src; + case SDL_BLENDMODE_BLEND: + return COMPOSITE_Src_Over_Dest; + case SDL_BLENDMODE_ADD: + return COMPOSITE_Plus; + case SDL_BLENDMODE_MOD: + // This is not correct, but we can't do modulation at the moment + return COMPOSITE_Src_Over_Dest; + default: + dprintf("Unknown blend mode %d\n", mode); + return COMPOSITE_Src_Over_Dest; + } +} + +static uint32 +OS4_GetCompositeFlags(SDL_BlendMode mode) +{ + uint32 flags = COMPFLAG_IgnoreDestAlpha | COMPFLAG_HardwareOnly; + + if (mode == SDL_BLENDMODE_NONE) { + flags |= COMPFLAG_SrcAlphaOverride; + } + + return flags; +} + +static void +OS4_SetupCompositing(SDL_Texture * dst, OS4_CompositingParams * params, SDL_ScaleMode scaleMode, SDL_BlendMode blendMode, Uint8 alpha) +{ + params->flags = COMPFLAG_HardwareOnly; + + if (scaleMode != SDL_ScaleModeNearest) { + params->flags |= COMPFLAG_SrcFilter; + } + + if (blendMode == SDL_BLENDMODE_NONE) { + if (!dst) { + params->flags |= COMPFLAG_SrcAlphaOverride; + } + params->srcAlpha = 1.0f; + } else { + params->srcAlpha = alpha / 255.0f; + } + + params->destAlpha = 1.0f; +} + +static void +OS4_RotateVertices(OS4_Vertex vertices[4], const double angle, const SDL_FPoint * center) +{ + int i; + + float rads = angle * M_PI / 180.0f; + + float sina = SDL_sinf(rads); + float cosa = SDL_cosf(rads); + + for (i = 0; i < 4; ++i) { + float x = vertices[i].x - center->x; + float y = vertices[i].y - center->y; + + vertices[i].x = x * cosa - y * sina + center->x; + vertices[i].y = x * sina + y * cosa + center->y; + } +} + +static void +OS4_FillVertexData(OS4_Vertex vertices[4], const SDL_Rect * srcrect, const SDL_Rect * dstrect, + const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) +{ + /* Flip texture coordinates if needed */ + + Uint16 left, right, top, bottom, tmp; + + left = srcrect->x; + right = left + srcrect->w; + top = srcrect->y; + bottom = top + srcrect->h; + + if (flip & SDL_FLIP_HORIZONTAL) { + tmp = left; + left = right; + right = tmp; + } + + if (flip & SDL_FLIP_VERTICAL) { + tmp = bottom; + bottom = top; + top = tmp; + } + + /* + + Plan is to draw quad with two triangles: + + v0-v3 + | \ | + v1-v2 + + */ + + vertices[0].x = dstrect->x; + vertices[0].y = dstrect->y; + vertices[0].s = left; + vertices[0].t = top; + vertices[0].w = 1.0f; + + vertices[1].x = dstrect->x; + vertices[1].y = dstrect->y + dstrect->h; + vertices[1].s = left; + vertices[1].t = bottom; + vertices[1].w = 1.0f; + + vertices[2].x = dstrect->x + dstrect->w; + vertices[2].y = dstrect->y + dstrect->h; + vertices[2].s = right; + vertices[2].t = bottom; + vertices[2].w = 1.0f; + + vertices[3].x = dstrect->x + dstrect->w; + vertices[3].y = dstrect->y; + vertices[3].s = right; + vertices[3].t = top; + vertices[3].w = 1.0f; + + if (angle != 0.0) { + OS4_RotateVertices(vertices, angle, center); + } +} + +static int +OS4_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * points, int count, SDL_BlendMode mode, + Uint8 a, Uint8 r, Uint8 g, Uint8 b) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + struct BitMap *bitmap = OS4_ActivateRenderer(renderer); + int i, status; + + //dprintf("Called for %d rects\n", count); + //Sint32 s = SDL_GetTicks(); + + if (!bitmap) { + return -1; + } + + if (mode == SDL_BLENDMODE_NONE) { + + const Uint32 color = a << 24 | r << 16 | g << 8 | b; + + for (i = 0; i < count; ++i) { + + SDL_Rect clipped; + + /* Perform clipping - is it possible to use RastPort? */ + if (!SDL_IntersectRect(&points[i], &data->cliprect, &clipped)) { + continue; + } + + data->iGraphics->RectFillColor( + &data->rastport, + clipped.x, + clipped.y, + clipped.x + clipped.w - 1, + clipped.y + clipped.h - 1, + color); // graphics.lib v54! + } + + status = 0; + } else { + + Uint32 colormod; + + if (!data->solidcolor) { + return -1; + } + + colormod = a << 24 | r << 16 | g << 8 | b; + + // Color modulation is implemented through fill texture manipulation + if (!OS4_SetSolidColor(renderer, colormod)) { + return -1; + } + + /* TODO: batch */ + for (i = 0; i < count; ++i) { + + const SDL_Rect srcrect = { 0, 0, 1, 1 }; + + OS4_Vertex vertices[4]; + + uint32 ret_code; + + OS4_FillVertexData(vertices, &srcrect, &points[i], 0.0, NULL, SDL_FLIP_NONE); + + ret_code = data->iGraphics->CompositeTags( + OS4_ConvertBlendMode(mode), + data->solidcolor, + bitmap, + COMPTAG_DestX, data->cliprect.x, + COMPTAG_DestY, data->cliprect.y, + COMPTAG_DestWidth, data->cliprect.w, + COMPTAG_DestHeight, data->cliprect.h, + COMPTAG_Flags, OS4_GetCompositeFlags(mode), + COMPTAG_VertexArray, vertices, + COMPTAG_VertexFormat, COMPVF_STW0_Present, + COMPTAG_NumTriangles, 2, + COMPTAG_IndexArray, OS4_QuadIndices, + TAG_END); + + if (ret_code) { + static Uint32 counter; + + if ((counter++ % 100) == 0) { + dprintf("CompositeTags: %d (fails: %u)\n", ret_code, counter); + } + } + } + + status = 0; + } + + //dprintf("Took %d\n", SDL_GetTicks() - s); + + return status; +} + +static int +OS4_RenderCopyEx(SDL_Renderer * renderer, SDL_RenderCommand * cmd, const OS4_Vertex * vertices, + struct BitMap * dst) +{ + SDL_Texture * texture = cmd->data.draw.texture; + const SDL_BlendMode mode = cmd->data.draw.blend; + + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + OS4_TextureData *texturedata = (OS4_TextureData *) texture->driverdata; + + struct BitMap *src = OS4_IsColorModEnabled(texture) ? + texturedata->finalbitmap : texturedata->bitmap; + + OS4_CompositingParams params; + uint32 ret_code; + + if (!dst) { + return -1; + } + + OS4_SetupCompositing(renderer->target, ¶ms, texture->scaleMode, mode, cmd->data.draw.a); + + ret_code = data->iGraphics->CompositeTags( + OS4_ConvertBlendMode(mode), + src, + dst, + COMPTAG_SrcAlpha, COMP_FLOAT_TO_FIX(params.srcAlpha), + COMPTAG_DestAlpha, COMP_FLOAT_TO_FIX(params.destAlpha), + COMPTAG_DestX, data->cliprect.x, + COMPTAG_DestY, data->cliprect.y, + COMPTAG_DestWidth, data->cliprect.w, + COMPTAG_DestHeight, data->cliprect.h, + COMPTAG_Flags, params.flags, + COMPTAG_VertexArray, vertices, + COMPTAG_VertexFormat, COMPVF_STW0_Present, + COMPTAG_NumTriangles, 2, + COMPTAG_IndexArray, OS4_QuadIndices, + TAG_END); + + if (ret_code) { + static Uint32 counter; + + if ((counter++ % 100) == 0) { + dprintf("CompositeTags: %d (fails: %u)\n", ret_code, counter); + } + + return SDL_SetError("CompositeTags failed"); + } + + return 0; +} + +static int +OS4_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, void * pixels, int pitch) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + SDL_Rect final_rect; + + struct BitMap *bitmap = OS4_ActivateRenderer(renderer); + + //dprintf("Called\n"); + + if (!bitmap) { + return -1; + } + + if (renderer->viewport.x || renderer->viewport.y) { + final_rect.x = renderer->viewport.x + rect->x; + final_rect.y = renderer->viewport.y + rect->y; + final_rect.w = rect->w; + final_rect.h = rect->h; + rect = &final_rect; + } + + if (rect->x < 0 || rect->x+rect->w > renderer->window->w || + rect->y < 0 || rect->y+rect->h > renderer->window->h) { + return SDL_SetError("Tried to read outside of surface bounds"); + } + + if (format != SDL_PIXELFORMAT_ARGB8888) { + return SDL_SetError("Unsupported pixel format"); + } + + data->iGraphics->ReadPixelArray( + &data->rastport, + rect->x, + rect->y, + pixels, + 0, + 0, + pitch, + PIXF_A8R8G8B8, + rect->w, + rect->h); + + return 0; +} + +static int min(int a, int b) +{ + return (a < b) ? a : b; +} + +static void +OS4_RenderPresent(SDL_Renderer * renderer) +{ + SDL_Window *window = renderer->window; + struct BitMap *source = OS4_ActivateRenderer(renderer); + + //dprintf("Called\n"); + //Uint32 s = SDL_GetTicks(); + + if (window && source) { + OS4_RenderData *data = (OS4_RenderData *)renderer->driverdata; + + // TODO: should we take viewport into account? + + SDL_WindowData *windowdata = (SDL_WindowData *)window->driverdata; + + struct Window *syswin = windowdata->syswin; + + if (syswin) { + + int32 ret; + int width; + int height; + + //dprintf("target %p\n", data->target); + + if (data->vsyncEnabled) { + data->iGraphics->WaitTOF(); + } + + data->iLayers->LockLayer(0, syswin->WLayer); + + width = min(window->w, syswin->Width - (syswin->BorderLeft + syswin->BorderRight)); + height = min(window->h, syswin->Height - (syswin->BorderTop + syswin->BorderBottom)); + + ret = data->iGraphics->BltBitMapTags( + BLITA_Source, source, + BLITA_DestType, BLITT_RASTPORT, + BLITA_Dest, syswin->RPort, + BLITA_DestX, syswin->BorderLeft, + BLITA_DestY, syswin->BorderTop, + BLITA_Width, width, + BLITA_Height, height, + TAG_DONE); + + data->iLayers->UnlockLayer(syswin->WLayer); + + if (ret != -1) { + dprintf("BltBitMapTags(): %d\n", ret); + } + } + } + //dprintf("Took %d\n", SDL_GetTicks() - s); +} + +static void +OS4_RenderClear(SDL_Renderer * renderer, Uint8 a, Uint8 r, Uint8 g, Uint8 b, struct BitMap * bitmap) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + const Uint32 color = (a << 24) | (r << 16) | (g << 8) | b; + + int width = 0; + int height = 0; + + OS4_GetBitMapSize(renderer, bitmap, &width, &height); + + data->iGraphics->RectFillColor( + &data->rastport, + 0, + 0, + width - 1, + height - 1, + color); // graphics.lib v54! +} + +static void +OS4_DestroyRenderer(SDL_Renderer * renderer) +{ + OS4_RenderData *data = (OS4_RenderData *) renderer->driverdata; + + if (data->bitmap) { + dprintf("Freeing renderer bitmap %p\n", data->bitmap); + + data->iGraphics->FreeBitMap(data->bitmap); + data->bitmap = NULL; + } + + if (data->solidcolor) { + data->iGraphics->FreeBitMap(data->solidcolor); + data->solidcolor = NULL; + } + + SDL_free(data); + SDL_free(renderer); +} + +static int +OS4_QueueNop(SDL_Renderer * renderer, SDL_RenderCommand *cmd) +{ + return 0; +} + +static int +OS4_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) +{ + SDL_Point *verts = (SDL_Point *) SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Point), 0, &cmd->data.draw.first); + size_t i; + + if (!verts) { + return -1; + } + + cmd->data.draw.count = count; + + if (renderer->viewport.x || renderer->viewport.y) { + const int x = renderer->viewport.x; + const int y = renderer->viewport.y; + for (i = 0; i < count; i++, verts++, points++) { + verts->x = (int)(x + points->x); + verts->y = (int)(y + points->y); + } + } else { + for (i = 0; i < count; i++, verts++, points++) { + verts->x = (int)points->x; + verts->y = (int)points->y; + } + } + + return 0; +} + +static int +OS4_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) +{ + return OS4_QueueDrawPoints(renderer, cmd, points, count); +} + +static int +OS4_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) +{ + SDL_Rect *verts = (SDL_Rect *) SDL_AllocateRenderVertices(renderer, count * sizeof(SDL_Rect), 0, &cmd->data.draw.first); + size_t i; + + if (!verts) { + return -1; + } + + cmd->data.draw.count = count; + + if (renderer->viewport.x || renderer->viewport.y) { + const int x = renderer->viewport.x; + const int y = renderer->viewport.y; + + for (i = 0; i < count; i++, verts++, rects++) { + verts->x = (int)(x + rects->x); + verts->y = (int)(y + rects->y); + verts->w = SDL_max((int)rects->w, 1); + verts->h = SDL_max((int)rects->h, 1); + } + } else { + for (i = 0; i < count; i++, verts++, rects++) { + verts->x = (int)rects->x; + verts->y = (int)rects->y; + verts->w = SDL_max((int)rects->w, 1); + verts->h = SDL_max((int)rects->h, 1); + } + } + + return 0; +} + +static int +OS4_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect, + const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) +{ + SDL_Rect final_rect; + SDL_FPoint final_center; + + OS4_Vertex *verts = (OS4_Vertex *) SDL_AllocateRenderVertices(renderer, + 4 * sizeof(OS4_Vertex), 0, &cmd->data.draw.first); + + if (!verts) { + return -1; + } + + cmd->data.draw.count = 1; + + if (renderer->viewport.x || renderer->viewport.y) { + final_rect.x = (int)(renderer->viewport.x + dstrect->x); + final_rect.y = (int)(renderer->viewport.y + dstrect->y); + } else { + final_rect.x = (int)dstrect->x; + final_rect.y = (int)dstrect->y; + } + + final_rect.w = (int)dstrect->w; + final_rect.h = (int)dstrect->h; + + final_center.x = dstrect->x + center->x; + final_center.y = dstrect->y + center->y; + + OS4_FillVertexData(verts, srcrect, &final_rect, angle, &final_center, flip); + + return OS4_SetTextureColorMod(renderer, texture); +} + +static int +OS4_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand * cmd, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect *dstrect) +{ + const SDL_FPoint center = { 0.0, 0.0 }; + return OS4_QueueCopyEx(renderer, cmd, texture, srcrect, dstrect, 0.0, ¢er, SDL_FLIP_NONE); +} + +static int +OS4_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand * cmd, void * vertices, size_t vertsize) +{ + OS4_RenderData *data = (OS4_RenderData *)renderer->driverdata; + + struct BitMap *bitmap = OS4_ActivateRenderer(renderer); + + if (!bitmap) { + dprintf("NULL bitmap\n"); + return -1; + } + + while (cmd) { + switch (cmd->command) { + case SDL_RENDERCMD_SETDRAWCOLOR: + // Nothing to do + break; + + case SDL_RENDERCMD_SETVIEWPORT: { + SDL_Rect *viewport = &data->viewport; + if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(SDL_Rect)) != 0) { + SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof(SDL_Rect)); + + //dprintf("viewport %d, %d\n", viewport->w, viewport->h); + + if (!data->cliprect_enabled) { + // CompositeTags uses cliprect: with clipping disabled, maximize it + SDL_memcpy(&data->cliprect, viewport, sizeof(SDL_Rect)); + } + } + break; + } + + case SDL_RENDERCMD_SETCLIPRECT: { + const SDL_Rect *rect = &cmd->data.cliprect.rect; + if (data->cliprect_enabled != cmd->data.cliprect.enabled) { + data->cliprect_enabled = cmd->data.cliprect.enabled; + + //dprintf("cliprect enabled %d\n", data->cliprect_enabled); + } + + if (SDL_memcmp(&data->cliprect, rect, sizeof(SDL_Rect)) != 0) { + SDL_memcpy(&data->cliprect, rect, sizeof(SDL_Rect)); + + //dprintf("cliprect %d, %d\n", data->cliprect.w, data->cliprect.h); + } + + if (!data->cliprect_enabled) { + // CompositeTags uses cliprect: with clipping disabled, maximize it + SDL_memcpy(&data->cliprect, &data->viewport, sizeof(SDL_Rect)); + } + break; + } + + case SDL_RENDERCMD_CLEAR: { + const Uint8 r = cmd->data.color.r; + const Uint8 g = cmd->data.color.g; + const Uint8 b = cmd->data.color.b; + const Uint8 a = cmd->data.color.a; + OS4_RenderClear(renderer, a, r, g, b, bitmap); + break; + } + + case SDL_RENDERCMD_DRAW_POINTS: { + const Uint8 r = cmd->data.draw.r; + const Uint8 g = cmd->data.draw.g; + const Uint8 b = cmd->data.draw.b; + const Uint8 a = cmd->data.draw.a; + const size_t count = cmd->data.draw.count; + const SDL_Point *verts = (SDL_Point *)(((Uint8 *) vertices) + cmd->data.draw.first); + const SDL_BlendMode blend = cmd->data.draw.blend; + OS4_RenderDrawPoints(renderer, verts, count, blend, a, r, g, b); + break; + } + + case SDL_RENDERCMD_DRAW_LINES: { + const Uint8 r = cmd->data.draw.r; + const Uint8 g = cmd->data.draw.g; + const Uint8 b = cmd->data.draw.b; + const Uint8 a = cmd->data.draw.a; + const size_t count = cmd->data.draw.count; + const SDL_Point *verts = (SDL_Point *)(((Uint8 *) vertices) + cmd->data.draw.first); + const SDL_BlendMode blend = cmd->data.draw.blend; + OS4_RenderDrawLines(renderer, verts, count, blend, a, r, g, b); + break; + } + + case SDL_RENDERCMD_FILL_RECTS: { + const Uint8 r = cmd->data.draw.r; + const Uint8 g = cmd->data.draw.g; + const Uint8 b = cmd->data.draw.b; + const Uint8 a = cmd->data.draw.a; + const size_t count = cmd->data.draw.count; + const SDL_Rect *verts = (SDL_Rect *)(((Uint8 *) vertices) + cmd->data.draw.first); + const SDL_BlendMode blend = cmd->data.draw.blend; + OS4_RenderFillRects(renderer, verts, count, blend, a, r, g, b); + break; + } + + case SDL_RENDERCMD_COPY: { + const OS4_Vertex *verts = (OS4_Vertex *)(((Uint8 *) vertices) + cmd->data.draw.first); + OS4_RenderCopyEx(renderer, cmd, verts, bitmap); + break; + } + + case SDL_RENDERCMD_COPY_EX: { + const OS4_Vertex *verts = (OS4_Vertex *)(((Uint8 *) vertices) + cmd->data.draw.first); + OS4_RenderCopyEx(renderer, cmd, verts, bitmap); + break; + } + + case SDL_RENDERCMD_NO_OP: + break; + } + + cmd = cmd->next; + } + + return 0; +} + +SDL_Renderer * +OS4_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + SDL_VideoData *videodata = (SDL_VideoData *)SDL_GetVideoDevice()->driverdata; + SDL_Renderer *renderer; + OS4_RenderData *data; + + dprintf("Creating renderer for '%s' (flags 0x%x)\n", window->title, flags); + + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + + data = (OS4_RenderData *) SDL_calloc(1, sizeof(*data)); + if (!data) { + OS4_DestroyRenderer(renderer); + SDL_OutOfMemory(); + return NULL; + } + + renderer->WindowEvent = OS4_WindowEvent; + renderer->GetOutputSize = OS4_GetOutputSize; + renderer->CreateTexture = OS4_CreateTexture; + renderer->UpdateTexture = OS4_UpdateTexture; + renderer->LockTexture = OS4_LockTexture; + renderer->UnlockTexture = OS4_UnlockTexture; + renderer->SetRenderTarget = OS4_SetRenderTarget; + renderer->QueueSetViewport = OS4_QueueNop; + renderer->QueueSetDrawColor = OS4_QueueNop; + renderer->QueueDrawPoints = OS4_QueueDrawPoints; + renderer->QueueDrawLines = OS4_QueueDrawLines; + renderer->QueueFillRects = OS4_QueueFillRects; + renderer->QueueCopy = OS4_QueueCopy; + renderer->QueueCopyEx = OS4_QueueCopyEx; + renderer->RunCommandQueue = OS4_RunCommandQueue; + renderer->RenderReadPixels = OS4_RenderReadPixels; + renderer->RenderPresent = OS4_RenderPresent; + renderer->DestroyTexture = OS4_DestroyTexture; + renderer->DestroyRenderer = OS4_DestroyRenderer; + renderer->info = OS4_RenderDriver.info; + + renderer->driverdata = data; + + data->iGraphics = videodata->iGraphics; + data->iLayers = videodata->iLayers; + + data->iGraphics->InitRastPort(&data->rastport); + + data->vsyncEnabled = flags & SDL_RENDERER_PRESENTVSYNC; + + dprintf("VSYNC: %s\n", data->vsyncEnabled ? "on" : "off"); + + return renderer; +} + +SDL_RenderDriver OS4_RenderDriver = { + OS4_CreateRenderer, + { + "compositing", + SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC, + 1, + { + SDL_PIXELFORMAT_ARGB8888, + }, + 0, + 0 + } +}; + +#endif /* !SDL_RENDER_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/amigaos4/SDL_render_compositing.h b/src/render/amigaos4/SDL_render_compositing.h new file mode 100644 index 0000000000000..d440518ed8b05 --- /dev/null +++ b/src/render/amigaos4/SDL_render_compositing.h @@ -0,0 +1,54 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_render_compositing_h +#define _SDL_render_compositing_h + +#include "../SDL_sysrender.h" + +#include "graphics/rastport.h" + +typedef struct +{ + struct GraphicsIFace *iGraphics; + struct LayersIFace * iLayers; + struct BitMap *bitmap; + struct BitMap *target; + struct BitMap *solidcolor; + struct RastPort rastport; + + SDL_Rect cliprect; + SDL_bool cliprect_enabled; + + SDL_Rect viewport; + + SDL_bool vsyncEnabled; +} OS4_RenderData; + +extern struct BitMap * OS4_ActivateRenderer(SDL_Renderer * renderer); +extern struct BitMap * OS4_AllocBitMap(SDL_Renderer * renderer, int width, int height, int depth); +extern SDL_bool OS4_IsColorModEnabled(SDL_Texture * texture); + +#endif + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/render/opengl/SDL_glfuncs.h b/src/render/opengl/SDL_glfuncs.h index 498dd10861518..c8e43079cc1d0 100644 --- a/src/render/opengl/SDL_glfuncs.h +++ b/src/render/opengl/SDL_glfuncs.h @@ -36,7 +36,11 @@ SDL_PROC_UNUSED(void, glBitmap, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, const GLubyte *)) SDL_PROC(void, glBlendEquation, (GLenum)) +#ifdef __AMIGAOS4__ +SDL_PROC(void, glBlendFunc, (GLenum, GLenum)) +#else SDL_PROC_UNUSED(void, glBlendFunc, (GLenum, GLenum)) +#endif SDL_PROC(void, glBlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum)) SDL_PROC_UNUSED(void, glCallList, (GLuint)) SDL_PROC_UNUSED(void, glCallLists, (GLsizei, GLenum, const GLvoid *)) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 514ca27e502ea..a122b50af64db 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -35,8 +35,13 @@ * these should match the defaults selected in SDL_GL_ResetAttributes */ +#ifdef __AMIGAOS4__ +#define RENDERER_CONTEXT_MAJOR 1 +#define RENDERER_CONTEXT_MINOR 3 +#else #define RENDERER_CONTEXT_MAJOR 2 #define RENDERER_CONTEXT_MINOR 1 +#endif /* OpenGL renderer implementation */ @@ -235,6 +240,12 @@ GL_LoadFunctions(GL_RenderData * data) #define SDL_PROC(ret,func,params) data->func=func; #else int retval = 0; +#ifdef __AMIGAOS4__ +#define SDL_PROC(ret,func,params) \ + do { \ + data->func = SDL_GL_GetProcAddress(#func); \ + } while ( 0 ); +#else #define SDL_PROC(ret,func,params) \ do { \ data->func = SDL_GL_GetProcAddress(#func); \ @@ -242,6 +253,7 @@ GL_LoadFunctions(GL_RenderData * data) retval = SDL_SetError("Couldn't load GL function %s: %s", #func, SDL_GetError()); \ } \ } while ( 0 ); +#endif #endif /* __SDL_NOGETPROCADDR__ */ #include "SDL_glfuncs.h" @@ -1052,6 +1064,29 @@ GL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * te return 0; } +static void +GlBlendModeHack(GL_RenderData * data, const SDL_BlendMode mode) +{ + switch (mode) { + case SDL_BLENDMODE_NONE: + data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + data->glDisable(GL_BLEND); + break; + + case SDL_BLENDMODE_ADD: + data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + data->glEnable(GL_BLEND); + data->glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR); + break; + + default: + data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + data->glEnable(GL_BLEND); + data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + } +} + static void SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader) { @@ -1094,16 +1129,22 @@ SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader } if (blend != data->drawstate.blend) { - if (blend == SDL_BLENDMODE_NONE) { - data->glDisable(GL_BLEND); + + if (data->glBlendFuncSeparate && data->glBlendEquation) { + if (blend == SDL_BLENDMODE_NONE) { + data->glDisable(GL_BLEND); + } else { + data->glEnable(GL_BLEND); + data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)), + GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)), + GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)), + GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend))); + data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend))); + } } else { - data->glEnable(GL_BLEND); - data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)), - GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)), - GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)), - GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend))); - data->glBlendEquation(GetBlendEquation(SDL_GetBlendModeColorOperation(blend))); + GlBlendModeHack(data, blend); } + data->drawstate.blend = blend; } diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index f36b34f906176..bbd2e3eeab10c 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -145,7 +145,9 @@ typedef struct GLES2_RenderData SDL_bool debug_enabled; -#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; +/* AmigaOS 4 workaround: add "my" prefix to function pointer names because glCall gets extended to IOGLES2->glCall + which doesn't compile in cases of data->glCall */ +#define SDL_PROC(ret,func,params) ret (APIENTRY *my##func) params; #include "SDL_gles2funcs.h" #undef SDL_PROC GLES2_FBOList *framebuffers; @@ -191,7 +193,7 @@ GL_ClearErrors(SDL_Renderer *renderer) if (!data->debug_enabled) { return; } - while (data->glGetError() != GL_NO_ERROR) { + while (data->myglGetError() != GL_NO_ERROR) { /* continue; */ } } @@ -207,7 +209,7 @@ GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, } /* check gl errors (can return multiple errors) */ for (;;) { - GLenum error = data->glGetError(); + GLenum error = data->myglGetError(); if (error != GL_NO_ERROR) { if (prefix == NULL || prefix[0] == '\0') { prefix = "generic"; @@ -243,12 +245,12 @@ static int GLES2_LoadFunctions(GLES2_RenderData * data) #endif #if defined __SDL_NOGETPROCADDR__ -#define SDL_PROC(ret,func,params) data->func=func; +#define SDL_PROC(ret,func,params) data->my##func=func; #else #define SDL_PROC(ret,func,params) \ do { \ - data->func = SDL_GL_GetProcAddress(#func); \ - if ( ! data->func ) { \ + data->my##func = SDL_GL_GetProcAddress(#func); \ + if ( ! data->my##func ) { \ return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \ } \ } while ( 0 ); @@ -270,7 +272,7 @@ GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h) result = SDL_malloc(sizeof(GLES2_FBOList)); result->w = w; result->h = h; - data->glGenFramebuffers(1, &result->FBO); + data->myglGenFramebuffers(1, &result->FBO); result->next = data->framebuffers; data->framebuffers = result; } @@ -303,7 +305,7 @@ GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) if (event->event == SDL_WINDOWEVENT_MINIMIZED) { /* According to Apple documentation, we need to finish drawing NOW! */ - data->glFinish(); + data->myglFinish(); } } @@ -418,17 +420,17 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment) entry->fragment_shader = fragment; /* Create the program and link it */ - entry->id = data->glCreateProgram(); - data->glAttachShader(entry->id, vertex); - data->glAttachShader(entry->id, fragment); - data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position"); - data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord"); - data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle"); - data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center"); - data->glLinkProgram(entry->id); - data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); + entry->id = data->myglCreateProgram(); + data->myglAttachShader(entry->id, vertex); + data->myglAttachShader(entry->id, fragment); + data->myglBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position"); + data->myglBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord"); + data->myglBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle"); + data->myglBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center"); + data->myglLinkProgram(entry->id); + data->myglGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); if (!linkSuccessful) { - data->glDeleteProgram(entry->id); + data->myglDeleteProgram(entry->id); SDL_free(entry); SDL_SetError("Failed to link shader program"); return NULL; @@ -436,33 +438,33 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment) /* Predetermine locations of uniform variables */ entry->uniform_locations[GLES2_UNIFORM_PROJECTION] = - data->glGetUniformLocation(entry->id, "u_projection"); + data->myglGetUniformLocation(entry->id, "u_projection"); entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] = - data->glGetUniformLocation(entry->id, "u_texture_v"); + data->myglGetUniformLocation(entry->id, "u_texture_v"); entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] = - data->glGetUniformLocation(entry->id, "u_texture_u"); + data->myglGetUniformLocation(entry->id, "u_texture_u"); entry->uniform_locations[GLES2_UNIFORM_TEXTURE] = - data->glGetUniformLocation(entry->id, "u_texture"); + data->myglGetUniformLocation(entry->id, "u_texture"); entry->uniform_locations[GLES2_UNIFORM_COLOR] = - data->glGetUniformLocation(entry->id, "u_color"); + data->myglGetUniformLocation(entry->id, "u_color"); entry->color = 0; - data->glUseProgram(entry->id); + data->myglUseProgram(entry->id); if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) { - data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */ + data->myglUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */ } if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] != -1) { - data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */ + data->myglUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */ } if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE] != -1) { - data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */ + data->myglUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */ } if (entry->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) { - data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection); + data->myglUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection); } if (entry->uniform_locations[GLES2_UNIFORM_COLOR] != -1) { - data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f); + data->myglUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f); } /* Cache the linked program */ @@ -477,7 +479,7 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment) /* Evict the last entry from the cache if we exceed the limit */ if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) { - data->glDeleteProgram(data->program_cache.tail->id); + data->myglDeleteProgram(data->program_cache.tail->id); data->program_cache.tail = data->program_cache.tail->prev; if (data->program_cache.tail != NULL) { SDL_free(data->program_cache.tail->next); @@ -501,21 +503,21 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t } /* Compile */ - id = data->glCreateShader(shader_type); - data->glShaderSource(id, 1, (const char**)&shader_src, NULL); - data->glCompileShader(id); - data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful); + id = data->myglCreateShader(shader_type); + data->myglShaderSource(id, 1, (const char**)&shader_src, NULL); + data->myglCompileShader(id); + data->myglGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful); if (!compileSuccessful) { SDL_bool isstack = SDL_FALSE; char *info = NULL; int length = 0; - data->glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); + data->myglGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); if (length > 0) { info = SDL_small_alloc(char, length, &isstack); if (info) { - data->glGetShaderInfoLog(id, length, &length, info); + data->myglGetShaderInfoLog(id, length, &length, info); } } if (info) { @@ -524,7 +526,7 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t } else { SDL_SetError("Failed to load the shader"); } - data->glDeleteShader(id); + data->myglDeleteShader(id); return 0; } @@ -646,7 +648,7 @@ GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int } /* Select that program in OpenGL */ - data->glUseProgram(program->id); + data->myglUseProgram(program->id); /* Set the current program */ data->drawstate.program = program; @@ -896,7 +898,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I if (data->drawstate.viewport_dirty) { const SDL_Rect *viewport = &data->drawstate.viewport; - data->glViewport(viewport->x, + data->myglViewport(viewport->x, data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h), viewport->w, viewport->h); if (viewport->w && viewport->h) { @@ -909,9 +911,9 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I if (data->drawstate.cliprect_enabled_dirty) { if (!data->drawstate.cliprect_enabled) { - data->glDisable(GL_SCISSOR_TEST); + data->myglDisable(GL_SCISSOR_TEST); } else { - data->glEnable(GL_SCISSOR_TEST); + data->myglEnable(GL_SCISSOR_TEST); } data->drawstate.cliprect_enabled_dirty = SDL_FALSE; } @@ -919,7 +921,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { const SDL_Rect *viewport = &data->drawstate.viewport; const SDL_Rect *rect = &data->drawstate.cliprect; - data->glScissor(viewport->x + rect->x, + data->myglScissor(viewport->x + rect->x, data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h, rect->w, rect->h); data->drawstate.cliprect_dirty = SDL_FALSE; @@ -928,10 +930,10 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I if (texture != data->drawstate.texture) { if ((texture != NULL) != data->drawstate.texturing) { if (texture == NULL) { - data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD); + data->myglDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD); data->drawstate.texturing = SDL_FALSE; } else { - data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD); + data->myglEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD); data->drawstate.texturing = SDL_TRUE; } } @@ -940,28 +942,28 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata; #if SDL_HAVE_YUV if (tdata->yuv) { - data->glActiveTexture(GL_TEXTURE2); - data->glBindTexture(tdata->texture_type, tdata->texture_v); + data->myglActiveTexture(GL_TEXTURE2); + data->myglBindTexture(tdata->texture_type, tdata->texture_v); - data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglActiveTexture(GL_TEXTURE1); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); - data->glActiveTexture(GL_TEXTURE0); + data->myglActiveTexture(GL_TEXTURE0); } else if (tdata->nv12) { - data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglActiveTexture(GL_TEXTURE1); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); - data->glActiveTexture(GL_TEXTURE0); + data->myglActiveTexture(GL_TEXTURE0); } #endif - data->glBindTexture(tdata->texture_type, tdata->texture); + data->myglBindTexture(tdata->texture_type, tdata->texture); } data->drawstate.texture = texture; } if (texture) { - data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8))); + data->myglVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8))); } if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) { @@ -972,7 +974,7 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) { if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) { - data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection); + data->myglUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection); SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)); } } @@ -983,43 +985,43 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I const Uint8 g = (data->drawstate.color >> 8) & 0xFF; const Uint8 b = (data->drawstate.color >> 0) & 0xFF; const Uint8 a = (data->drawstate.color >> 24) & 0xFF; - data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f); + data->myglUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f); program->color = data->drawstate.color; } } if (blend != data->drawstate.blend) { if (blend == SDL_BLENDMODE_NONE) { - data->glDisable(GL_BLEND); + data->myglDisable(GL_BLEND); } else { - data->glEnable(GL_BLEND); - data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)), + data->myglEnable(GL_BLEND); + data->myglBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)), GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)), GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)), GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend))); - data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)), + data->myglBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)), GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend))); } data->drawstate.blend = blend; } /* all drawing commands use this */ - data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first); + data->myglVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first); if (is_copy_ex != was_copy_ex) { if (is_copy_ex) { - data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE); - data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER); + data->myglEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE); + data->myglEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER); } else { - data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE); - data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER); + data->myglDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE); + data->myglDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER); } data->drawstate.is_copy_ex = is_copy_ex; } if (is_copy_ex) { - data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16))); - data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24))); + data->myglVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16))); + data->myglVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24))); } return 0; @@ -1158,12 +1160,12 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver } /* upload the new VBO data for this set of commands. */ - data->glBindBuffer(GL_ARRAY_BUFFER, vbo); + data->myglBindBuffer(GL_ARRAY_BUFFER, vbo); if (data->vertex_buffer_size[vboidx] < vertsize) { - data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW); + data->myglBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW); data->vertex_buffer_size[vboidx] = vertsize; } else { - data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices); + data->myglBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices); } /* cycle through a few VBOs so the GL has some time with the data before we replace it. */ @@ -1217,22 +1219,22 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver const GLfloat fg = ((GLfloat) g) * inv255f; const GLfloat fb = ((GLfloat) b) * inv255f; const GLfloat fa = ((GLfloat) a) * inv255f; - data->glClearColor(fr, fg, fb, fa); + data->myglClearColor(fr, fg, fb, fa); data->drawstate.clear_color = color; } if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) { - data->glDisable(GL_SCISSOR_TEST); + data->myglDisable(GL_SCISSOR_TEST); data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled; } - data->glClear(GL_COLOR_BUFFER_BIT); + data->myglClear(GL_COLOR_BUFFER_BIT); break; } case SDL_RENDERCMD_DRAW_POINTS: { if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) { - data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count); + data->myglDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count); } break; } @@ -1241,7 +1243,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver const size_t count = cmd->data.draw.count; SDL_assert(count >= 2); if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) { - data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count); + data->myglDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count); } break; } @@ -1251,7 +1253,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver size_t offset = 0; if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) { for (i = 0; i < count; ++i, offset += 4) { - data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4); + data->myglDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4); } } break; @@ -1260,7 +1262,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver case SDL_RENDERCMD_COPY: case SDL_RENDERCMD_COPY_EX: { if (SetCopyState(renderer, cmd) == 0) { - data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + data->myglDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } break; } @@ -1289,7 +1291,7 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer) for (i = 0; i < GLES2_SHADER_COUNT; i++) { GLuint id = data->shader_id_cache[i]; if (id) { - data->glDeleteShader(id); + data->myglDeleteShader(id); } } } @@ -1298,7 +1300,7 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer) GLES2_ProgramCacheEntry *next; entry = data->program_cache.head; while (entry) { - data->glDeleteProgram(entry->id); + data->myglDeleteProgram(entry->id); next = entry->next; SDL_free(entry); entry = next; @@ -1308,13 +1310,13 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer) if (data->context) { while (data->framebuffers) { GLES2_FBOList *nextnode = data->framebuffers->next; - data->glDeleteFramebuffers(1, &data->framebuffers->FBO); + data->myglDeleteFramebuffers(1, &data->framebuffers->FBO); GL_CheckError("", renderer); SDL_free(data->framebuffers); data->framebuffers = nextnode; } - data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); + data->myglDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); GL_CheckError("", renderer); SDL_GL_DeleteContext(data->context); @@ -1417,63 +1419,63 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glGenTextures(1, &data->texture_v); + renderdata->myglGenTextures(1, &data->texture_v); if (GL_CheckError("glGenTexures()", renderer) < 0) { return -1; } - renderdata->glActiveTexture(GL_TEXTURE2); - renderdata->glBindTexture(data->texture_type, data->texture_v); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); - - renderdata->glGenTextures(1, &data->texture_u); + renderdata->myglActiveTexture(GL_TEXTURE2); + renderdata->myglBindTexture(data->texture_type, data->texture_v); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + renderdata->myglTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); + + renderdata->myglGenTextures(1, &data->texture_u); if (GL_CheckError("glGenTexures()", renderer) < 0) { return -1; } - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); + renderdata->myglActiveTexture(GL_TEXTURE1); + renderdata->myglBindTexture(data->texture_type, data->texture_u); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + renderdata->myglTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } } else if (data->nv12) { - renderdata->glGenTextures(1, &data->texture_u); + renderdata->myglGenTextures(1, &data->texture_u); if (GL_CheckError("glGenTexures()", renderer) < 0) { return -1; } - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); + renderdata->myglActiveTexture(GL_TEXTURE1); + renderdata->myglBindTexture(data->texture_type, data->texture_u); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + renderdata->myglTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } } #endif - renderdata->glGenTextures(1, &data->texture); + renderdata->myglGenTextures(1, &data->texture); if (GL_CheckError("glGenTexures()", renderer) < 0) { return -1; } texture->driverdata = data; - renderdata->glActiveTexture(GL_TEXTURE0); - renderdata->glBindTexture(data->texture_type, data->texture); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + renderdata->myglActiveTexture(GL_TEXTURE0); + renderdata->myglBindTexture(data->texture_type, data->texture); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { - renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); + renderdata->myglTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); if (GL_CheckError("glTexImage2D()", renderer) < 0) { return -1; } @@ -1500,6 +1502,44 @@ GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint return 0; /* nothing to do */ } +#ifdef SDL_BIG_ENDIAN + /* HACK: do endian conversion. Then shaders and target texture should be compatible. + Alpha channel must be in correct place for blending */ + + src_pitch = width * bpp; + + blob = (Uint8 *)SDL_malloc(src_pitch * height); + if (!blob) { + return SDL_OutOfMemory(); + } + src = blob; + for (y = 0; y < height; ++y) + { + int x; + + if (bpp == 4) { + Uint32* to = (Uint32 *)src; + Uint32* from = (Uint32 *)pixels; + + for (x = 0; x < width; x++) { + to[x] = SDL_SwapLE32(from[x]); + } + } else { + Uint8* to = src; + Uint8* from = (Uint8 *)pixels; + + for (x = 0; x < src_pitch; x += 3) { + to[x + 0] = from[x + 2]; + to[x + 1] = from[x + 1]; + to[x + 2] = from[x + 0]; + } + } + + src += src_pitch; + pixels = (Uint8 *)pixels + pitch; + } + src = blob; +#else /* Reformat the texture data into a tightly packed array */ src_pitch = width * bpp; src = (Uint8 *)pixels; @@ -1517,8 +1557,9 @@ GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint } src = blob; } +#endif - data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src); + data->myglTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src); if (blob) { SDL_free(blob); } @@ -1542,7 +1583,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect data->drawstate.texture = NULL; /* we trash this state. */ /* Create a texture subimage with the supplied data */ - data->glBindTexture(tdata->texture_type, tdata->texture); + data->myglBindTexture(tdata->texture_type, tdata->texture); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x, rect->y, @@ -1557,9 +1598,9 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect /* Skip to the correct offset into the next texture */ pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); if (texture->format == SDL_PIXELFORMAT_YV12) { - data->glBindTexture(tdata->texture_type, tdata->texture_v); + data->myglBindTexture(tdata->texture_type, tdata->texture_v); } else { - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); } GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, @@ -1574,9 +1615,9 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect /* Skip to the correct offset into the next texture */ pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2)); if (texture->format == SDL_PIXELFORMAT_YV12) { - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); } else { - data->glBindTexture(tdata->texture_type, tdata->texture_v); + data->myglBindTexture(tdata->texture_type, tdata->texture_v); } GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, @@ -1589,7 +1630,7 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect } else if (tdata->nv12) { /* Skip to the correct offset into the next texture */ pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, rect->y / 2, @@ -1624,7 +1665,7 @@ GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, data->drawstate.texture = NULL; /* we trash this state. */ - data->glBindTexture(tdata->texture_type, tdata->texture_v); + data->myglBindTexture(tdata->texture_type, tdata->texture_v); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, rect->y / 2, @@ -1634,7 +1675,7 @@ GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, tdata->pixel_type, Vplane, Vpitch, 1); - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, rect->y / 2, @@ -1644,7 +1685,7 @@ GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, tdata->pixel_type, Uplane, Upitch, 1); - data->glBindTexture(tdata->texture_type, tdata->texture); + data->myglBindTexture(tdata->texture_type, tdata->texture); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x, rect->y, @@ -1675,7 +1716,7 @@ GLES2_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture, data->drawstate.texture = NULL; /* we trash this state. */ - data->glBindTexture(tdata->texture_type, tdata->texture_u); + data->myglBindTexture(tdata->texture_type, tdata->texture_u); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x / 2, rect->y / 2, @@ -1685,7 +1726,7 @@ GLES2_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture, GL_UNSIGNED_BYTE, UVplane, UVpitch, 2); - data->glBindTexture(tdata->texture_type, tdata->texture); + data->myglBindTexture(tdata->texture_type, tdata->texture); GLES2_TexSubImage2D(data, tdata->texture_type, rect->x, rect->y, @@ -1737,27 +1778,27 @@ GLES2_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Sc #if SDL_HAVE_YUV if (data->yuv) { - renderdata->glActiveTexture(GL_TEXTURE2); - renderdata->glBindTexture(data->texture_type, data->texture_v); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); - - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); + renderdata->myglActiveTexture(GL_TEXTURE2); + renderdata->myglBindTexture(data->texture_type, data->texture_v); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); + + renderdata->myglActiveTexture(GL_TEXTURE1); + renderdata->myglBindTexture(data->texture_type, data->texture_u); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); } else if (data->nv12) { - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); + renderdata->myglActiveTexture(GL_TEXTURE1); + renderdata->myglBindTexture(data->texture_type, data->texture_u); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); } #endif - renderdata->glActiveTexture(GL_TEXTURE0); - renderdata->glBindTexture(data->texture_type, data->texture); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); + renderdata->myglActiveTexture(GL_TEXTURE0); + renderdata->myglBindTexture(data->texture_type, data->texture); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->myglTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); } static int @@ -1770,14 +1811,14 @@ GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) data->drawstate.viewport_dirty = SDL_TRUE; if (texture == NULL) { - data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer); + data->myglBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer); } else { texturedata = (GLES2_TextureData *) texture->driverdata; - data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO); + data->myglBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO); /* TODO: check if texture pixel format allows this operation */ - data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0); + data->myglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0); /* Check FBO status */ - status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER); + status = data->myglCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { return SDL_SetError("glFramebufferTexture2D() failed"); } @@ -1802,13 +1843,13 @@ GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) /* Destroy the texture */ if (tdata) { - data->glDeleteTextures(1, &tdata->texture); + data->myglDeleteTextures(1, &tdata->texture); #if SDL_HAVE_YUV if (tdata->texture_v) { - data->glDeleteTextures(1, &tdata->texture_v); + data->myglDeleteTextures(1, &tdata->texture_v); } if (tdata->texture_u) { - data->glDeleteTextures(1, &tdata->texture_u); + data->myglDeleteTextures(1, &tdata->texture_u); } #endif SDL_free(tdata->pixel_data); @@ -1843,7 +1884,7 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, SDL_GetRendererOutputSize(renderer, &w, &h); - data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, + data->myglReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels); if (GL_CheckError("glReadPixels()", renderer) < 0) { return -1; @@ -1895,7 +1936,7 @@ static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, flo GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; GLES2_ActivateRenderer(renderer); - data->glBindTexture(texturedata->texture_type, texturedata->texture); + data->myglBindTexture(texturedata->texture_type, texturedata->texture); data->drawstate.texture = texture; if (texw) { @@ -1914,7 +1955,7 @@ static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; GLES2_ActivateRenderer(renderer); - data->glBindTexture(texturedata->texture_type, 0); + data->myglBindTexture(texturedata->texture_type, 0); data->drawstate.texture = NULL; return 0; @@ -2025,17 +2066,17 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) } value = 0; - data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); + data->myglGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_width = value; value = 0; - data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); + data->myglGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); renderer->info.max_texture_height = value; /* we keep a few of these and cycle through them, so data can live for a few frames. */ - data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); + data->myglGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); data->framebuffers = NULL; - data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer); + data->myglGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer); data->window_framebuffer = (GLuint)window_framebuffer; /* Populate the function pointers for the module */ @@ -2076,14 +2117,14 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) #endif /* Set up parameters for rendering */ - data->glActiveTexture(GL_TEXTURE0); - data->glPixelStorei(GL_PACK_ALIGNMENT, 1); - data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + data->myglActiveTexture(GL_TEXTURE0); + data->myglPixelStorei(GL_PACK_ALIGNMENT, 1); + data->myglPixelStorei(GL_UNPACK_ALIGNMENT, 1); - data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION); - data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); + data->myglEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION); + data->myglDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); - data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + data->myglClearColor(1.0f, 1.0f, 1.0f, 1.0f); data->drawstate.blend = SDL_BLENDMODE_INVALID; data->drawstate.color = 0xFFFFFFFF; diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c index 004e7741c7a1f..9109fa087cb46 100644 --- a/src/stdlib/SDL_iconv.c +++ b/src/stdlib/SDL_iconv.c @@ -30,6 +30,12 @@ #include "SDL_stdinc.h" #include "SDL_endian.h" +#ifdef __AMIGAOS4__ +/* HACK: AmigaOS 4 iconv implementation doesn't support all conversions, making testiconv fail. +As a workaround, fallback to custom implementation. */ +#undef HAVE_ICONV +#endif + #if defined(HAVE_ICONV) && defined(HAVE_ICONV_H) #ifdef __FreeBSD__ /* Define LIBICONV_PLUG to use iconv from the base instead of ports and avoid linker errors. */ diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h index 0ff4502cae834..e2cc5bd3765d5 100644 --- a/src/thread/SDL_thread_c.h +++ b/src/thread/SDL_thread_c.h @@ -38,6 +38,8 @@ #include "vita/SDL_systhread_c.h" #elif SDL_THREAD_STDCPP #include "stdcpp/SDL_systhread_c.h" +#elif SDL_THREAD_AMIGAOS4 +#include "amigaos4/SDL_systhread_c.h" #elif SDL_THREAD_OS2 #include "os2/SDL_systhread_c.h" #else diff --git a/src/thread/amigaos4/SDL_sysmutex.c b/src/thread/amigaos4/SDL_sysmutex.c new file mode 100644 index 0000000000000..a0961ee272b0a --- /dev/null +++ b/src/thread/amigaos4/SDL_sysmutex.c @@ -0,0 +1,128 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_AMIGAOS4 + +/* Mutex functions using the AmigaOS 4 API */ + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include "SDL_mutex.h" + +#include + +struct SDL_mutex +{ + APTR mtx; +}; + +SDL_mutex * +SDL_CreateMutex(void) +{ + SDL_mutex* mutex; + + /* Allocate mutex memory */ + mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex)); + + if (mutex) { + mutex->mtx = IExec->AllocSysObjectTags(ASOT_MUTEX, + ASOMUTEX_Recursive, TRUE, + TAG_DONE); + + if (!mutex->mtx) { + dprintf("Failed to allocate mutex\n"); + SDL_free(mutex); + SDL_OutOfMemory(); + return NULL; + } + + dprintf("Created mutex %p\n", mutex->mtx); + } else { + SDL_OutOfMemory(); + } + + return mutex; +} + +void +SDL_DestroyMutex(SDL_mutex * mutex) +{ + if (mutex) { + dprintf("Destroying mutex %p\n", mutex->mtx); + IExec->FreeSysObject(ASOT_MUTEX, mutex->mtx); + mutex->mtx = NULL; + SDL_free(mutex); + } +} + +int +SDL_LockMutex(SDL_mutex * mutex) +{ + if (mutex == NULL) { + return SDL_SetError("Passed a NULL mutex"); + } + + //dprintf("Called\n"); + + IExec->MutexObtain(mutex->mtx); + + //dprintf("Locked mutex %p\n", mutex); + + return 0; +} + +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ + int retval = 0; + if (mutex == NULL) { + return SDL_SetError("Passed a NULL mutex"); + } + + //dprintf("Called\n"); + + if (!IExec->MutexAttempt(mutex->mtx)) { + retval = SDL_MUTEX_TIMEDOUT; + } + return retval; +} + +/* Unlock the mutex */ +int +SDL_UnlockMutex(SDL_mutex * mutex) +{ + if (mutex == NULL) { + return SDL_SetError("Passed a NULL mutex"); + } + + //dprintf("Unlocking mutex %p\n", mutex); + + IExec->MutexRelease(mutex->mtx); + + return 0; +} + +#endif /* SDL_THREAD_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/thread/amigaos4/SDL_syssem.c b/src/thread/amigaos4/SDL_syssem.c new file mode 100644 index 0000000000000..169fe704526b8 --- /dev/null +++ b/src/thread/amigaos4/SDL_syssem.c @@ -0,0 +1,239 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_AMIGAOS4 + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include "SDL_thread.h" +#include "../../timer/amigaos4/SDL_os4timer_c.h" +#include "../../thread/amigaos4/SDL_systhread_c.h" + +#include +#include + +#define MUTEX_SIGNAL SIGBREAKF_CTRL_F +#define BREAK_SIGNAL SIGBREAKF_CTRL_C + +struct SDL_semaphore +{ + APTR mutex; // Protects the control block + Uint32 count; // Current value + struct MinList waiters; // Task waiting on this semaphore +}; + +typedef struct OS4_WaiterNode +{ + struct MinNode node; + struct Task* task; +} OS4_WaiterNode; + +SDL_sem * +SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem* sem = (SDL_sem *) SDL_malloc(sizeof(*sem)); + if (sem) { + sem->mutex = IExec->AllocSysObjectTags(ASOT_MUTEX, + ASOMUTEX_Recursive, TRUE, + TAG_DONE); + + if (!sem->mutex) { + dprintf("Failed to allocate mutex\n"); + SDL_SetError("Failed to allocate mutex"); + SDL_free(sem); + return NULL; + } + + IExec->NewMinList(&sem->waiters); + + sem->count = initial_value; + + dprintf("Created semaphore %p with count %d\n", sem, sem->count); + } else { + SDL_OutOfMemory(); + } + return (sem); +} + +void +SDL_DestroySemaphore(SDL_sem * sem) +{ + if (sem) { + dprintf("Destroying semaphore %p\n", sem); + + if (sem->mutex) { + IExec->MutexObtain(sem->mutex); + + if (!IsMinListEmpty(&sem->waiters)) { + dprintf("Semaphore %p has waiters\n"); + + OS4_WaiterNode* node; + + while ((node = (OS4_WaiterNode *)IExec->RemHead((struct List *)&sem->waiters))) { + dprintf("Interrupting waiting task %p\n", node->task); + + IExec->Signal(node->task, BREAK_SIGNAL); + + /* Reschedule tasks */ + IExec->MutexRelease(sem->mutex); + IExec->MutexObtain(sem->mutex); + } + } + + IExec->MutexRelease(sem->mutex); + + IExec->FreeSysObject(ASOT_MUTEX, sem->mutex); + sem->mutex = NULL; + } + SDL_free(sem); + } +} + +int +SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) +{ + if (!sem) { + return SDL_SetError("Passed a NULL sem"); + } + + BOOL wait = TRUE; + + struct Task* task = IExec->FindTask(NULL); + + ULONG alarmSignal = 0; + + if (timeout > 0) { + alarmSignal = OS4_TimerSetAlarm(OS4_ThreadGetTimer(), timeout); + } + + while (wait) { + OS4_WaiterNode node; + + IExec->MutexObtain(sem->mutex); + + if (sem->count > 0) { + sem->count--; + wait = FALSE; + } else { + if (timeout == 0) { + //dprintf("Semaphore %p trying timed out\n", sem); + IExec->MutexRelease(sem->mutex); + return SDL_MUTEX_TIMEDOUT; + } + + node.task = task; + IExec->AddTail((struct List *)&sem->waiters, (struct Node *)&node); + } + + IExec->MutexRelease(sem->mutex); + + if (wait) { + //dprintf("Semaphore %p signals before wait 0x%X, count %u\n", sem, IExec->SetSignal(0L, 0L), sem->count); + + const ULONG signals = IExec->Wait(MUTEX_SIGNAL | BREAK_SIGNAL | alarmSignal); + + IExec->MutexObtain(sem->mutex); + IExec->Remove((struct Node *)&node); + IExec->MutexRelease(sem->mutex); + + if (signals & BREAK_SIGNAL) { + dprintf("Semaphore %p interrupted\n", sem); + return SDL_MUTEX_TIMEDOUT; + } + + if (signals & alarmSignal) { + //dprintf("Semaphore %p timer triggered\n"); + return SDL_MUTEX_TIMEDOUT; + } + + if (signals & MUTEX_SIGNAL) { + dprintf("Semaphore %p got signal 0x%X\n", sem, signals); + } + } + } + + if (timeout) { + OS4_TimerClearAlarm(OS4_ThreadGetTimer()); + } + + //dprintf("Semaphore %p obtained\n", sem); + + return 0; +} + +int +SDL_SemTryWait(SDL_sem * sem) +{ + return SDL_SemWaitTimeout(sem, 0); +} + +int +SDL_SemWait(SDL_sem * sem) +{ + //dprintf("Called\n"); + + 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) { + return SDL_SetError("Passed a NULL sem"); + } + + //dprintf("Called\n"); + + IExec->MutexObtain(sem->mutex); + + if (++sem->count == 1) { + OS4_WaiterNode* node = (OS4_WaiterNode *)IExec->RemHead((struct List *)&sem->waiters); + + if (node) { + dprintf("Signalling task %p for semaphore %p\n", node->task, sem); + IExec->Signal(node->task, MUTEX_SIGNAL); + } + } + + IExec->MutexRelease(sem->mutex); + + dprintf("Semaphore %p value %u\n", sem, sem->count); + + return 0; +} + +#endif /* SDL_THREAD_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/thread/amigaos4/SDL_systhread.c b/src/thread/amigaos4/SDL_systhread.c new file mode 100644 index 0000000000000..eb1fb04a24d46 --- /dev/null +++ b/src/thread/amigaos4/SDL_systhread.c @@ -0,0 +1,428 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_AMIGAOS4 + +/* AmigaOS 4 thread management routines for SDL */ + +#include "SDL_thread.h" +#include "../SDL_thread_c.h" +#include "../SDL_systhread.h" +#include "SDL_systhread_c.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" +#include "../../video/amigaos4/SDL_os4library.h" + +#include +#include + +#define CHILD_SIGNAL SIGBREAKF_CTRL_D +#define BREAK_SIGNAL SIGBREAKF_CTRL_C + +static struct DOSIFace* iDOS; // TODO: try to make centralized interface storage for SDL2 - now it's a mess with too many symbols all over the place +static struct DOSBase* dosBase; + +typedef struct OS4_SafeList +{ + APTR mutex; + struct MinList list; +} OS4_SafeList; + +typedef struct OS4_ThreadNode +{ + struct MinNode node; + struct Task* task; + SDL_Thread* thread; + OS4_TimerInstance timer; +} OS4_ThreadNode; + +typedef struct OS4_ThreadControl +{ + OS4_ThreadNode primary; + OS4_SafeList children; + OS4_SafeList waiters; +} OS4_ThreadControl; + +static OS4_ThreadControl control; + +static BOOL initialized = FALSE; + +// NOTE: Init and Quit are called from SDL.c at the moment. +void OS4_InitThreadSubSystem(void) +{ + if (initialized) { + dprintf("Already initialized\n"); + return; + } + + control.primary.task = IExec->FindTask(NULL); + + dprintf("Main task %p\n", control.primary.task); + + control.children.mutex = IExec->AllocSysObjectTags(ASOT_MUTEX, TAG_DONE); + control.waiters.mutex = IExec->AllocSysObjectTags(ASOT_MUTEX, TAG_DONE); + + dprintf("Children mutex %p, waiters mutex %p\n", control.children.mutex, control.waiters.mutex); + + IExec->NewMinList((struct MinList *)&control.children.list); + IExec->NewMinList((struct MinList *)&control.waiters.list); + + dosBase = (struct DOSBase *)OS4_OpenLibrary(DOSNAME, 50); + iDOS = (struct DOSIFace *)OS4_GetInterface((struct Library *)dosBase); + + dprintf("dosBase %p, iDos %p\n", dosBase, iDOS); + + OS4_InitTimerSubSystem(); + OS4_TimerCreate(&control.primary.timer); + + control.primary.task->tc_UserData = &control.primary; // Timer lookup requires this + + initialized = TRUE; +} + +void OS4_QuitThreadSubSystem(void) +{ + struct MinNode* iter; + + if (!initialized) { + dprintf("Not initialized\n"); + return; + } + + dprintf("Called from task %p\n", IExec->FindTask(NULL)); + + do { + IExec->MutexObtain(control.children.mutex); + + if (IsMinListEmpty(&control.children.list)) { + dprintf("No child threads left - proceed with SDL2 shutdown\n"); + IExec->MutexRelease(control.children.mutex); + break; + } else { + for (iter = control.children.list.mlh_Head; iter->mln_Succ; iter = iter->mln_Succ) { + IExec->Signal(((OS4_ThreadNode *)iter)->task, SIGBREAKF_CTRL_C); + } + } + + IExec->MutexRelease(control.children.mutex); + } while (TRUE); + + OS4_TimerDestroy(&control.primary.timer); + + OS4_QuitTimerSubSystem(); + + dprintf("Freeing mutexes\n"); + + IExec->FreeSysObject(ASOT_MUTEX, control.children.mutex); + IExec->FreeSysObject(ASOT_MUTEX, control.waiters.mutex); + + control.children.mutex = NULL; + control.waiters.mutex = NULL; + + dprintf("Dropping iDOS\n"); + + OS4_DropInterface((struct Interface **)&iDOS); + OS4_CloseLibrary((struct Library **)&dosBase); + + initialized = FALSE; + + dprintf("All done\n"); +} + +static LONG +OS4_RunThread(STRPTR args, int32 length, APTR execbase) +{ + struct Task* thisTask = IExec->FindTask(NULL); + + OS4_ThreadNode* node = thisTask->tc_UserData; + + node->task = thisTask; + + dprintf("This task %p, node %p, SDL_Thread %p\n", thisTask, node, node->thread); + + OS4_TimerCreate(&node->timer); + + IExec->MutexObtain(control.children.mutex); + IExec->AddTail((struct List *)&control.children.list, (struct Node *)node); + IExec->MutexRelease(control.children.mutex); + + SDL_RunThread(node->thread); + + return RETURN_OK; +} + +static void +OS4_ExitThread(int32 returnCode, int32 finalData) +{ + struct Task* thisTask = IExec->FindTask(NULL); + + OS4_ThreadNode *node = (OS4_ThreadNode *)finalData; // TODO: cannot use thisTask->tc_UserData if this is sometimes called from other process' context + + dprintf("Called from task %p, finalData %p\n", thisTask, finalData); + + IExec->MutexObtain(control.children.mutex); + + dprintf("Removing node %p from children list\n", node); + + IExec->Remove((struct Node *)node); + + dprintf("Signalling waiters\n"); + + IExec->MutexObtain(control.waiters.mutex); + + if (IsMinListEmpty(&control.waiters.list)) { + dprintf("Waiters list is empty\n"); + } else { + struct MinNode* iter; + + for (iter = control.waiters.list.mlh_Head; iter->mln_Succ; iter = iter->mln_Succ) { + //dprintf("iter %p, sending CHILD_SIGNAL\n", iter); + IExec->Signal(((OS4_ThreadNode *)iter)->task, CHILD_SIGNAL); + } + } + + IExec->MutexRelease(control.waiters.mutex); + + OS4_TimerDestroy(&node->timer); + + IExec->FreeVec(node); + + dprintf("Exiting\n"); + + // Hold the mutex until end, to prevent parent task shutting down the thread subsystem + IExec->MutexRelease(control.children.mutex); +} + +int +SDL_SYS_CreateThread(SDL_Thread * thread) +{ + char nameBuffer[128]; + struct Task* thisTask = IExec->FindTask(NULL); + + OS4_ThreadNode* node = IExec->AllocVecTags(sizeof(OS4_ThreadNode), + AVT_ClearWithValue, 0, + TAG_DONE); + + if (!node) { + dprintf("Failed to allocated thread node\n"); + return SDL_SetError("Not enough resources to create thread"); + } + + dprintf("Node %p\n", node); + + node->thread = thread; + + BPTR inputStream = iDOS->DupFileHandle(iDOS->Input()); + BPTR outputStream = iDOS->DupFileHandle(iDOS->Output()); + BPTR errorStream = iDOS->DupFileHandle(iDOS->ErrorOutput()); + + snprintf(nameBuffer, sizeof(nameBuffer), "SDL thread %s (%p)", thread->name, thread); + + struct Process* child = iDOS->CreateNewProcTags( + NP_Child, TRUE, + NP_Entry, OS4_RunThread, + NP_FinalCode, OS4_ExitThread, + // HACK: when running testthread, sometimes child process is calling exit() and SDL cleanup fails + // because ExitThread() is called from other context. By passing the node pointer, it can be removed + // from the list and quit doesn't hang. + NP_FinalData, (int32)node, + NP_Input, inputStream, + NP_CloseInput, inputStream != ZERO, + NP_Output, outputStream, + NP_CloseOutput, outputStream != ZERO, + NP_Error, errorStream, + NP_CloseError, errorStream != ZERO, + NP_Name, nameBuffer, + NP_Priority, thisTask->tc_Node.ln_Pri, + NP_StackSize, thread->stacksize, + NP_UserData, (APTR)node, + TAG_DONE); + + if (!child) { + dprintf("Failed to create a new thread '%s'\n", thread->name); + return SDL_SetError("Not enough resources to create thread"); + } + + dprintf("Created new thread '%s' (task %p)\n", thread->name, child); + + return 0; +} + +void +SDL_SYS_SetupThread(const char * name) +{ + //dprintf("Called for '%s'\n", name); +} + +SDL_threadID +SDL_ThreadID(void) +{ + return (SDL_threadID) IExec->FindTask(NULL); +} + +int +SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) +{ + int value; + + switch (priority) { + case SDL_THREAD_PRIORITY_LOW: + value = -5; + break; + case SDL_THREAD_PRIORITY_HIGH: + value = 5; + break; + case SDL_THREAD_PRIORITY_TIME_CRITICAL: + value = 10; + break; + default: + value = 0; + break; + } + + struct Task* task = IExec->FindTask(NULL); + const BYTE old = IExec->SetTaskPri(task, value); + + dprintf("Changed task %p priority from %d to %d\n", task, old, value); + + return 0; +} + +static BOOL +OS4_StartJoining(OS4_ThreadNode * waiterNode, SDL_Thread * thread) +{ + BOOL found = FALSE; + + struct MinNode* iter; + + //dprintf("Start\n"); + + IExec->MutexObtain(control.children.mutex); + + if (IsMinListEmpty(&control.children.list)) { + dprintf("Children list is empty\n"); + } else { + for (iter = control.children.list.mlh_Head; iter->mln_Succ; iter = iter->mln_Succ) { + if (((OS4_ThreadNode *)iter)->thread == thread) { + found = TRUE; + IExec->MutexObtain(control.waiters.mutex); + IExec->AddTail((struct List *)&control.waiters.list, (struct Node *)waiterNode); + IExec->MutexRelease(control.waiters.mutex); + break; + } + } + } + + IExec->MutexRelease(control.children.mutex); + + //dprintf("End\n"); + + return found; +} + +static void +OS4_StopJoining(OS4_ThreadNode * node) +{ + //dprintf("Start\n"); + IExec->MutexObtain(control.waiters.mutex); + IExec->Remove((struct Node *)node); + IExec->MutexRelease(control.waiters.mutex); + //dprintf("End\n"); +} + +void +SDL_SYS_WaitThread(SDL_Thread * thread) +{ + dprintf("Waiting for '%s'\n", thread->name); + + OS4_ThreadNode node; + node.task = IExec->FindTask(NULL); + node.thread = ((OS4_ThreadNode *)node.task->tc_UserData)->thread; + + do { + const BOOL found = OS4_StartJoining(&node, thread); + + if (found) { + const ULONG signals = IExec->Wait(CHILD_SIGNAL | BREAK_SIGNAL); + + OS4_StopJoining(&node); + + if (signals & BREAK_SIGNAL) { + dprintf("Break signal\n"); + return; + } + + dprintf("Some child thread terminated\n"); + } else { + dprintf("Thread '%s' doesn't exist\n", thread->name); + return; + } + } while (TRUE); + + dprintf("Waiting over\n"); +} + +void +SDL_SYS_DetachThread(SDL_Thread * thread) +{ + dprintf("Called for '%s'\n", thread->name); + + // NOTE: not removing from child thread list because child tasks should exit + // before their parent (NP_Child, TRUE) + +#if 0 + IExec->MutexObtain(control.children.mutex); + + if (IsMinListEmpty(&control.children.list)) { + dprintf("Children list is empty\n"); + } else { + struct MinNode* iter; + + for (iter = control.children.list.mlh_Head; iter->mln_Succ; iter = iter->mln_Succ) { + if (((OS4_ThreadNode *)iter)->thread == thread) { + IExec->Remove((struct Node *)iter); + IExec->FreeVec(iter); + break; + } + } + } + + IExec->MutexRelease(control.children.mutex); +#endif +} + +OS4_TimerInstance* +OS4_ThreadGetTimer(void) +{ + struct Task* task = IExec->FindTask(NULL); + OS4_ThreadNode* node = task->tc_UserData; + + //dprintf("Task %p, timer %p\n", task, &node->timer); + + return &node->timer; +} + +#endif /* SDL_THREAD_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/thread/amigaos4/SDL_systhread_c.h b/src/thread/amigaos4/SDL_systhread_c.h new file mode 100644 index 0000000000000..2ce70d6b7c352 --- /dev/null +++ b/src/thread/amigaos4/SDL_systhread_c.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_SYSTHREAD_C_H +#define SDL_SYSTHREAD_C_H + +#include "../../timer/amigaos4/SDL_os4timer_c.h" + +typedef struct Task* SYS_ThreadHandle; + +void OS4_InitThreadSubSystem(void); +void OS4_QuitThreadSubSystem(void); + +OS4_TimerInstance* OS4_ThreadGetTimer(void); + +#endif + diff --git a/src/thread/pthread/SDL_syscond.c b/src/thread/pthread/SDL_syscond.c index 674351e328515..48ec6a6006dad 100644 --- a/src/thread/pthread/SDL_syscond.c +++ b/src/thread/pthread/SDL_syscond.c @@ -29,6 +29,19 @@ #include "SDL_thread.h" #include "SDL_sysmutex_c.h" +#ifdef __amigaos4__ +#ifndef timespec + +/* FIXME: hack to get compile working. At least my SDK defines timespec only for CLIB2 */ +struct timespec +{ + unsigned int tv_sec; + unsigned int tv_nsec; +}; + +#endif +#endif + struct SDL_cond { pthread_cond_t cond; diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index 6902dbc1ab618..ec8e0f5639305 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -48,6 +48,7 @@ #endif #endif +#include "SDL_platform.h" #include "SDL_thread.h" #include "../SDL_thread_c.h" #include "../SDL_systhread.h" @@ -59,6 +60,9 @@ #include #endif +#ifdef __amigaos4__ +#include +#endif #ifndef __NACL__ /* List of signals to mask in the subthreads */ @@ -125,7 +129,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread) void SDL_SYS_SetupThread(const char *name) { -#if !defined(__NACL__) +#if !defined(__NACL__) && !defined(__AMIGAOS4__) int i; sigset_t mask; #endif /* !__NACL__ */ @@ -158,7 +162,7 @@ SDL_SYS_SetupThread(const char *name) } /* NativeClient does not yet support signals.*/ -#if !defined(__NACL__) +#if !defined(__NACL__) && !defined(__AMIGAOS4__) /* Mask asynchronous signals for this thread */ sigemptyset(&mask); for (i = 0; sig_list[i]; ++i) { diff --git a/src/timer/amigaos4/SDL_os4timer.c b/src/timer/amigaos4/SDL_os4timer.c new file mode 100644 index 0000000000000..440c5ea50105f --- /dev/null +++ b/src/timer/amigaos4/SDL_os4timer.c @@ -0,0 +1,245 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if defined(SDL_TIMER_AMIGAOS4) || defined(SDL_TIMERS_DISABLED) + +#include "SDL_types.h" + +#include +#include +#include +#include +#include + +#include "SDL_os4timer_c.h" + +#include "../../thread/amigaos4/SDL_systhread_c.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static struct TimeVal OS4_StartTime; + +static struct TimerIFace* SDL2_ITimer; + +static ULONG OS4_TimerFrequency; + +typedef struct OS4_ClockVal { + union { + struct EClockVal cv; + Uint64 ticks; + } u; +} OS4_ClockVal; + +// Initialized with the thread sub system +void OS4_InitTimerSubSystem(void) +{ + dprintf("Called\n"); + + struct ExecBase* sysbase = (struct ExecBase *)IExec->Data.LibBase; + struct Library* timerBase = (struct Library *)IExec->FindName(&sysbase->DeviceList, "timer.device"); + + SDL2_ITimer = (struct TimerIFace *)IExec->GetInterface(timerBase, "main", 1, NULL); + + dprintf("ITimer %p\n", SDL2_ITimer); + + if (!SDL2_ITimer) { + dprintf("Failed to get ITimer\n"); + return; + } + + SDL2_ITimer->GetSysTime(&OS4_StartTime); + + struct EClockVal cv; + OS4_TimerFrequency = SDL2_ITimer->ReadEClock(&cv); + + dprintf("Timer frequency %u Hz\n", OS4_TimerFrequency); +} + +void OS4_QuitTimerSubSystem(void) +{ + dprintf("Called\n"); + + IExec->DropInterface((struct Interface *)SDL2_ITimer); + SDL2_ITimer = NULL; +} + +static void +OS4_TimerCleanup(OS4_TimerInstance * timer) +{ + if (timer) { + if (timer->timerRequest) { + dprintf("Freeing timer request %p\n", timer->timerRequest); + IExec->FreeSysObject(ASOT_IOREQUEST, timer->timerRequest); + timer->timerRequest = NULL; + } + + if (timer->timerPort) { + dprintf("Freeing timer port %p\n", timer->timerPort); + IExec->FreeSysObject(ASOT_PORT, timer->timerPort); + timer->timerPort = NULL; + } + } +} + +BOOL +OS4_TimerCreate(OS4_TimerInstance * timer) +{ + BOOL success = FALSE; + + dprintf("Creating timer %p for task %p\n", timer, IExec->FindTask(NULL)); + + if (!timer) { + return FALSE; + } + + timer->timerPort = IExec->AllocSysObject(ASOT_PORT, NULL); + + if (timer->timerPort) { + timer->timerRequest = IExec->AllocSysObjectTags(ASOT_IOREQUEST, + ASOIOR_ReplyPort, timer->timerPort, + ASOIOR_Size, sizeof(struct TimeRequest), + TAG_DONE); + + if (timer->timerRequest) { + if (!(IExec->OpenDevice("timer.device", UNIT_WAITUNTIL, (struct IORequest *)timer->timerRequest, 0))) { + success = TRUE; + } else { + dprintf("Failed to open timer.device\n"); + } + } else { + dprintf("Failed to allocate timer request\n"); + } + } else { + dprintf("Failed to allocate timer port\n"); + } + + if (!success) { + OS4_TimerCleanup(timer); + } + + return success; +} + +void +OS4_TimerDestroy(OS4_TimerInstance * timer) +{ + dprintf("Destroying timer %p for task %p\n", timer, IExec->FindTask(NULL)); + + if (timer && timer->timerRequest) { + if (!IExec->CheckIO((struct IORequest *)timer->timerRequest)) { + IExec->AbortIO((struct IORequest *)timer->timerRequest); + IExec->WaitIO((struct IORequest *)timer->timerRequest); + } + } + + OS4_TimerCleanup(timer); +} + +ULONG +OS4_TimerSetAlarm(OS4_TimerInstance * timer, Uint32 alarmTicks) +{ + const ULONG seconds = alarmTicks / 1000; + struct TimeVal now; + + if (!SDL2_ITimer) { + dprintf("Timer subsystem not initialized\n"); + return 0; + } + + //dprintf("Called for timer %p, ticks %u\n", timer, alarmTicks); + + timer->timerRequest->Request.io_Command = TR_ADDREQUEST; + timer->timerRequest->Time.Seconds = seconds; + timer->timerRequest->Time.Microseconds = (alarmTicks - (seconds * 1000)) * 1000; + + SDL2_ITimer->GetSysTime(&now); + SDL2_ITimer->AddTime(&timer->timerRequest->Time, &now); + + IExec->SetSignal(0, 1L << timer->timerPort->mp_SigBit); + IExec->SendIO((struct IORequest *)timer->timerRequest); + + // Return the alarm signal for Wait() use + return 1L << timer->timerPort->mp_SigBit; +} + +void +OS4_TimerClearAlarm(OS4_TimerInstance * timer) +{ + if (!IExec->CheckIO((struct IORequest *)timer->timerRequest)) { + IExec->AbortIO((struct IORequest *)timer->timerRequest); + } + + IExec->WaitIO((struct IORequest *)timer->timerRequest); +} + +BOOL +OS4_TimerDelay(Uint32 ticks) +{ + OS4_TimerInstance* timer = OS4_ThreadGetTimer(); + + const ULONG alarmSig = OS4_TimerSetAlarm(timer, ticks); + const ULONG sigsReceived = IExec->Wait(alarmSig | SIGBREAKF_CTRL_C); + + OS4_TimerClearAlarm(timer); + + return (sigsReceived & alarmSig) == alarmSig; +} + +void +OS4_TimerGetTime(struct TimeVal * timeval) +{ + if (!SDL2_ITimer) { + dprintf("Timer subsystem not initialized\n"); + timeval->Seconds = 0; + timeval->Microseconds = 0; + return; + } + + SDL2_ITimer->GetSysTime(timeval); + SDL2_ITimer->SubTime(timeval, &OS4_StartTime); +} + +Uint64 +OS4_TimerGetCounter(void) +{ + OS4_ClockVal value; + + if (!SDL2_ITimer) { + dprintf("Timer subsystem not initialized\n"); + return 0; + } + + SDL2_ITimer->ReadEClock(&value.u.cv); + + return value.u.ticks; +} + +Uint64 +OS4_TimerGetFrequency(void) +{ + return OS4_TimerFrequency; +} + +#endif /* (SDL_TIMER_AMIGAOS4) || defined(SDL_TIMERS_DISABLED) */ + diff --git a/src/timer/amigaos4/SDL_os4timer_c.h b/src/timer/amigaos4/SDL_os4timer_c.h new file mode 100644 index 0000000000000..3df2dc2a1ed6d --- /dev/null +++ b/src/timer/amigaos4/SDL_os4timer_c.h @@ -0,0 +1,50 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_OS4TIMER_C_H +#define SDL_OS4TIMER_C_H + +#include + +struct MsgPort; +struct TimeRequest; +struct TimeVal; + +typedef struct OS4_TimerInstance +{ + struct MsgPort* timerPort; + struct TimeRequest* timerRequest; +} OS4_TimerInstance; + +void OS4_InitTimerSubSystem(void); +void OS4_QuitTimerSubSystem(void); + +BOOL OS4_TimerCreate(OS4_TimerInstance * timer); +void OS4_TimerDestroy(OS4_TimerInstance * timer); +ULONG OS4_TimerSetAlarm(OS4_TimerInstance * timer, Uint32 alarmTicks); +void OS4_TimerClearAlarm(OS4_TimerInstance * timer); +BOOL OS4_TimerDelay(Uint32 ticks); +void OS4_TimerGetTime(struct TimeVal * timeval); +Uint64 OS4_TimerGetCounter(void); +Uint64 OS4_TimerGetFrequency(void); + +#endif /* SDL_OS4TIMER_C_H */ + diff --git a/src/timer/amigaos4/SDL_systimer.c b/src/timer/amigaos4/SDL_systimer.c new file mode 100644 index 0000000000000..eafbe8e098356 --- /dev/null +++ b/src/timer/amigaos4/SDL_systimer.c @@ -0,0 +1,83 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if defined(SDL_TIMER_AMIGAOS4) || defined(SDL_TIMERS_DISABLED) + +#include + +#include "SDL_timer.h" +#include "SDL_os4timer_c.h" + +#undef DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static SDL_bool started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (started) { + return; + } + started = SDL_TRUE; +} + +void +SDL_TicksQuit(void) +{ + started = SDL_FALSE; +} + +Uint32 +SDL_GetTicks(void) +{ + if (!started) { + SDL_TicksInit(); + } + + struct TimeVal cur; + OS4_TimerGetTime(&cur); + + return cur.Seconds * 1000 + cur.Microseconds / 1000; +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + return OS4_TimerGetCounter(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return OS4_TimerGetFrequency(); +} + +void +SDL_Delay(Uint32 ms) +{ + OS4_TimerDelay(ms); +} + +#endif /* SDL_TIMER_AMIGAOS4 || SDL_TIMERS_DISABLED */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/timer/unix/SDL_systimer.c b/src/timer/unix/SDL_systimer.c index 05db3a9f7af53..9a6ede9be93f6 100644 --- a/src/timer/unix/SDL_systimer.c +++ b/src/timer/unix/SDL_systimer.c @@ -202,7 +202,11 @@ SDL_Delay(Uint32 ms) #if HAVE_NANOSLEEP struct timespec elapsed, tv; #else + +#ifndef __amigaos4__ struct timeval tv; +#endif + Uint32 then, now, elapsed; #endif @@ -229,10 +233,14 @@ SDL_Delay(Uint32 ms) break; } ms -= elapsed; +#ifdef __amigaos4__ + was_error = usleep(ms * 1000); +#else tv.tv_sec = ms / 1000; tv.tv_usec = (ms % 1000) * 1000; was_error = select(0, NULL, NULL, NULL, &tv); +#endif #endif /* HAVE_NANOSLEEP */ } while (was_error && (errno == EINTR)); } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 682e52592921b..265409583b81a 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -435,6 +435,7 @@ extern VideoBootStrap KMSDRM_bootstrap; extern VideoBootStrap KMSDRM_LEGACY_bootstrap; extern VideoBootStrap DUMMY_bootstrap; extern VideoBootStrap Wayland_bootstrap; +extern VideoBootStrap OS4_bootstrap; extern VideoBootStrap NACL_bootstrap; extern VideoBootStrap VIVANTE_bootstrap; extern VideoBootStrap Emscripten_bootstrap; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index a5cbe69629e41..288f2e21bb39f 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -109,6 +109,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_EMSCRIPTEN &Emscripten_bootstrap, #endif +#if SDL_VIDEO_DRIVER_AMIGAOS4 + &OS4_bootstrap, +#endif #if SDL_VIDEO_DRIVER_QNX &QNX_bootstrap, #endif @@ -151,7 +154,12 @@ static SDL_VideoDevice *_this = NULL; return retval; \ } +#ifdef __AMIGAOS4__ +/* Let's have only one kind of full screen */ +#define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN) +#else #define FULLSCREEN_MASK (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN) +#endif #ifdef __MACOSX__ /* Support for Mac OS X fullscreen spaces */ @@ -1154,6 +1162,10 @@ SDL_SetWindowDisplayMode(SDL_Window * window, const SDL_DisplayMode * mode) SDL_DisplayMode fullscreen_mode; if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) { SDL_SetDisplayModeForDisplay(SDL_GetDisplayForWindow(window), &fullscreen_mode); +#ifdef __AMIGAOS4__ + // Force window on new screen + _this->SetWindowFullscreen(_this, window, SDL_GetDisplayForWindow(window), SDL_TRUE); +#endif } } return 0; @@ -1387,8 +1399,15 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) return 0; } -#define CREATE_FLAGS \ - (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL) +#ifdef __AMIGAOS4__ + /* Without this hack, SDL would trigger us to open a window before screen which causes unnecessary + work, because then we would have to close the window first and re-open it on the custom screen */ + #define CREATE_FLAGS \ + (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_FULLSCREEN) +#else + #define CREATE_FLAGS \ + (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL) +#endif static SDL_INLINE SDL_bool IsAcceptingDragAndDrop(void) @@ -1561,6 +1580,11 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) window->y = y; window->w = w; window->h = h; + +#ifndef __AMIGAOS4__ +/* On AmigaOS4 we have to open the screen first, therefore this centering +logic fails if screen is of different size. We center the window later +on the backend side, after we know the screen size. */ if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); @@ -1576,6 +1600,8 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) window->y = bounds.y + (bounds.h - h) / 2; } } +#endif + window->windowed.x = window->x; window->windowed.y = window->y; window->windowed.w = window->w; @@ -1725,6 +1751,15 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags) _this->DestroyWindow(_this, window); } +#ifdef __AMIGAOS4__ + if (window->flags & SDL_WINDOW_OPENGL) { + /* We have to unload the old library in case we have to switch + between MiniGL and OGLES2. Otherwise function pointers will be messed up. */ + SDL_GL_UnloadLibrary(); + window->flags &= ~SDL_WINDOW_OPENGL; + } +#endif + if ((window->flags & SDL_WINDOW_OPENGL) != (flags & SDL_WINDOW_OPENGL)) { if (flags & SDL_WINDOW_OPENGL) { need_gl_load = SDL_TRUE; @@ -3307,8 +3342,13 @@ SDL_GL_ResetAttributes() _this->gl_config.accelerated = -1; /* accelerated or not, both are fine */ #if SDL_VIDEO_OPENGL +#ifdef __AMIGAOS4__ + _this->gl_config.major_version = 1; /* MiniGL */ + _this->gl_config.minor_version = 3; +#else _this->gl_config.major_version = 2; _this->gl_config.minor_version = 1; +#endif _this->gl_config.profile_mask = 0; #elif SDL_VIDEO_OPENGL_ES2 _this->gl_config.major_version = 2; @@ -4061,6 +4101,9 @@ SDL_IsScreenKeyboardShown(SDL_Window *window) #if SDL_VIDEO_DRIVER_X11 #include "x11/SDL_x11messagebox.h" #endif +#if SDL_VIDEO_DRIVER_AMIGAOS4 +#include "amigaos4/SDL_os4messagebox.h" +#endif #if SDL_VIDEO_DRIVER_WAYLAND #include "wayland/SDL_waylandmessagebox.h" #endif @@ -4074,7 +4117,7 @@ SDL_IsScreenKeyboardShown(SDL_Window *window) #include "vita/SDL_vitamessagebox.h" #endif -#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_HAIKU || SDL_VIDEO_DRIVER_OS2 +#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT || SDL_VIDEO_DRIVER_COCOA || SDL_VIDEO_DRIVER_UIKIT || SDL_VIDEO_DRIVER_X11 || SDL_VIDEO_DRIVER_AMIGAOS4 || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_HAIKU || SDL_VIDEO_DRIVER_OS2 static SDL_bool SDL_MessageboxValidForDriver(const SDL_MessageBoxData *messageboxdata, SDL_SYSWM_TYPE drivertype) { SDL_SysWMinfo info; @@ -4173,6 +4216,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) retval = 0; } #endif +#if SDL_VIDEO_DRIVER_AMIGAOS4 + if (retval == -1 && + SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_OS4) && + OS4_ShowMessageBox(messageboxdata, buttonid) == 0) { + retval = 0; + } +#endif #if SDL_VIDEO_DRIVER_WAYLAND if (retval == -1 && SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) && diff --git a/src/video/amigaos4/SDL_os4_notimplemented_funcs.t b/src/video/amigaos4/SDL_os4_notimplemented_funcs.t new file mode 100644 index 0000000000000..6f96e52a4d018 --- /dev/null +++ b/src/video/amigaos4/SDL_os4_notimplemented_funcs.t @@ -0,0 +1,1280 @@ +#define FUNC_NOT_IMPLEMENTED printf("function (%s) not implemented on file (%s),%d\n",__FUNCTION__, __FILE__, __LINE__); + +static void AmiglClearIndex( GLfloat c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glClearIndex(c); +#endif +} + +static void AmiglIndexMask( GLuint mask ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexMask(mask); +#endif +} + +static void AmiglGetPolygonStipple( GLubyte *mask ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPolygonStipple(mask); +#endif +} + +static void AmiglEdgeFlagv( const GLboolean *flag ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glEdgeFlagv(flag); +#endif +} + +static void AmiglClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glClearAccum(red, green, blue, alpha); +#endif +} + +static void AmiglAccum( GLenum op, GLfloat value ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glAccum(op, value); +#endif +} + +static void AmiglIndexd( GLdouble c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexd(c); +#endif +} + +static void AmiglIndexf( GLfloat c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexf(c); +#endif +} + +static void AmiglIndexi( GLint c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexi(c); +#endif +} + +static void AmiglIndexs( GLshort c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexs(c); +#endif +} + +static void AmiglIndexub( GLubyte c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexub(c); +#endif +} + +static void AmiglIndexdv( const GLdouble *c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexdv(c); +#endif +} + +static void AmiglIndexfv( const GLfloat *c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexfv(c); +#endif +} + +static void AmiglIndexiv( const GLint *c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexiv(c); +#endif +} + +static void AmiglIndexsv( const GLshort *c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexsv(c); +#endif +} + +static void AmiglIndexubv( const GLubyte *c ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexubv(c); +#endif +} + +static void AmiglTexCoord1s( GLshort s ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord1s(s); +#endif +} + +static void AmiglTexCoord2s( GLshort s, GLshort t ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord2s(s, t); +#endif +} + +static void AmiglTexCoord3d( GLdouble s, GLdouble t, GLdouble r ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3d(s, t, r); +#endif +} + +static void AmiglTexCoord3i( GLint s, GLint t, GLint r ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3i(s, t, r); +#endif + } + +static void AmiglTexCoord3s( GLshort s, GLshort t, GLshort r ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3s(s, t, r); +#endif + } + +static void AmiglTexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4d(s, t, r, q); +#endif +} + +static void AmiglTexCoord4i( GLint s, GLint t, GLint r, GLint q ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4i(s, t, r, q); +#endif +} + +static void AmiglTexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4s(s, t, r, q); +#endif +} + +static void AmiglTexCoord1dv( const GLdouble *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord1dv(v); +#endif +} + +static void AmiglTexCoord1fv( const GLfloat *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord1fv(v); +#endif +} + +static void AmiglTexCoord1iv( const GLint *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord1iv(v); +#endif +} + +static void AmiglTexCoord1sv( const GLshort *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord1sv(v); +#endif +} + +static void AmiglTexCoord2dv( const GLdouble *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord2dv(v); +#endif +} + +static void AmiglTexCoord2sv( const GLshort *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord2sv(v); +#endif +} + +static void AmiglTexCoord3dv( const GLdouble *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3dv(v); +#endif +} + +static void AmiglTexCoord3iv( const GLint *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3iv(v); +#endif +} + +static void AmiglTexCoord3sv( const GLshort *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord3sv(v); +#endif +} + +static void AmiglTexCoord4dv( const GLdouble *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4dv(v); +#endif +} + +static void AmiglTexCoord4iv( const GLint *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4iv(v); +#endif +} + +static void AmiglTexCoord4sv( const GLshort *v ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoord4sv(v); +#endif +} + +static void AmiglIndexPointer( GLenum type, GLsizei stride, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexPointer(type, stride, ptr); +#endif +} + +static void AmiglEdgeFlagPointer( GLsizei stride, const GLboolean *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glEdgeFlagPointer(stride, ptr); +#endif +} + +static void AmiglGetPointerv( GLenum pname, void **params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPointerv(pname, params); +#endif +} + +static void AmiglPixelMapfv( GLenum map, GLint mapsize, const GLfloat *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPixelMapfv(map, mapsize, values); +#endif +} + +static void AmiglPixelMapuiv( GLenum map, GLint mapsize, const GLuint *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPixelMapuiv(map, mapsize, values); +#endif +} + +static void AmiglPixelMapusv( GLenum map, GLint mapsize, const GLushort *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPixelMapusv(map, mapsize, values); +#endif +} + +static void AmiglGetPixelMapfv( GLenum map, GLfloat *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPixelMapfv(map, values); +#endif +} + +static void AmiglGetPixelMapuiv( GLenum map, GLuint *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPixelMapuiv(map, values); +#endif +} + +static void AmiglGetPixelMapusv( GLenum map, GLushort *values ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPixelMapusv(map, values); +#endif +} + +static void AmiglTexGend( GLenum coord, GLenum pname, GLdouble param ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexGend(coord, pname, param); +#endif +} + +static void AmiglTexGenf( GLenum coord, GLenum pname, GLfloat param ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexGenf(coord, pname, param); +#endif +} + +static void AmiglTexGendv( GLenum coord, GLenum pname, const GLdouble *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexGendv(coord, pname, params); +#endif +} + +static void AmiglTexGeniv( GLenum coord, GLenum pname, const GLint *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexGeniv(coord, pname, params); +#endif +} + +static void AmiglGetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetTexGendv(coord, pname, params); +#endif +} + +static void AmiglGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetTexGenfv(coord, pname, params); +#endif +} + +static void AmiglGetTexGeniv( GLenum coord, GLenum pname, GLint *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetTexGeniv(coord, pname, params); +#endif +} + +static void AmiglGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetTexEnvfv(target, pname, params); +#endif +} + +static void AmiglFogiv( GLenum pname, const GLint *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glFogiv(pname, params); +#endif + } + +static void AmiglFeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glFeedbackBuffer(size, type, buffer); +#endif +} + +static void AmiglPassThrough( GLfloat token ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPassThrough(token); +#endif +} + +static void AmiglBlendEquationEXT( GLenum mode ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glBlendEquationEXT(mode); +#endif +} + +static void AmiglBlendColorEXT( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glBlendColorEXT(red, green, blue, alpha); +#endif +} + +static void AmiglPolygonOffsetEXT( GLfloat factor, GLfloat bias ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPolygonOffsetEXT(factor, bias); +#endif +} + +static void AmiglVertexPointerEXT( GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glVertexPointerEXT(size, type, stride, count, ptr); +#endif +} + +static void AmiglNormalPointerEXT( GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glNormalPointerEXT(type, stride, count, ptr); +#endif +} + +static void AmiglColorPointerEXT( GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glColorPointerEXT(size, type, stride, count, ptr); +#endif +} + +static void AmiglIndexPointerEXT( GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIndexPointerEXT(type, stride, count, ptr); +#endif +} + +static void AmiglTexCoordPointerEXT( GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexCoordPointerEXT(size, type, stride, count, ptr); +#endif +} + +static void AmiglEdgeFlagPointerEXT( GLsizei stride, GLsizei count, const GLboolean *ptr ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glEdgeFlagPointerEXT(stride, count, ptr); +#endif +} + +static void AmiglGetPointervEXT( GLenum pname, void **params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetPointervEXT(pname, params); +#endif + } + +static void AmiglArrayElementEXT( GLint i ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glArrayElementEXT(i); +#endif +} + +static void AmiglDrawArraysEXT( GLenum mode, GLint first, GLsizei count ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glDrawArraysEXT(mode, first, count); +#endif +} + +static void AmiglGenTexturesEXT( GLsizei n, GLuint *textures ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGenTexturesEXT(n, textures); +#endif +} + +static void AmiglDeleteTexturesEXT( GLsizei n, const GLuint *textures) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glDeleteTexturesEXT(n, textures); +#endif +} + +static void AmiglBindTextureEXT( GLenum target, GLuint texture ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glBindTextureEXT(target, texture); +#endif +} + +static void AmiglPrioritizeTexturesEXT( GLsizei n, const GLuint *textures, const GLclampf *priorities ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPrioritizeTexturesEXT(n, textures, priorities); +#endif +} + +static GLboolean AmiglAreTexturesResidentEXT( GLsizei n, const GLuint *textures, GLboolean *residences ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glAreTexturesResidentEXT(n, textures, residences); +#else + return 0; +#endif +} + +static GLboolean AmiglIsTextureEXT( GLuint texture ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glIsTextureEXT(texture); +#else + return 0; +#endif +} + +static void AmiglTexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexImage3DEXT(target, level, internalFormat, width, height, depth, border, format, type, pixels); +#endif +} + +static void AmiglTexSubImage3DEXT( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +#endif +} + +static void AmiglCopyTexSubImage3DEXT( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glCopyTexSubImage3DEXT(target, level, xoffset, yoffset, zoffset, x, y, width, height); +#endif +} + +static void AmiglColorSubTableEXT( GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glColorSubTableEXT(target, start, count, format, type, data); +#endif +} + +static void AmiglGetColorTableEXT( GLenum target, GLenum format, GLenum type, GLvoid *table ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetColorTableEXT(target, format, type, table); +#endif +} + +static void AmiglGetColorTableParameterfvEXT( GLenum target, GLenum pname, GLfloat *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetColorTableParameterfvEXT(target, pname, params); +#endif +} + +static void AmiglGetColorTableParameterivEXT( GLenum target, GLenum pname, GLint *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glGetColorTableParameterivEXT(target, pname, params); +#endif +} + +static void AmiglMultiTexCoord1dSGIS(GLenum target, GLdouble s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1dSGIS(target, s); +#endif +} + +static void AmiglMultiTexCoord1dvSGIS(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1dvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord1fSGIS(GLenum target, GLfloat s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1fSGIS(target, s); +#endif +} +static void AmiglMultiTexCoord1fvSGIS(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1fvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord1iSGIS(GLenum target, GLint s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1iSGIS(target, s); +#endif +} + +static void AmiglMultiTexCoord1ivSGIS(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1ivSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord1sSGIS(GLenum target, GLshort s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1sSGIS(target, s); +#endif +} + +static void AmiglMultiTexCoord1svSGIS(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1svSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord2dSGIS(GLenum target, GLdouble s, GLdouble t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2dSGIS(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2dvSGIS(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2dvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord2fSGIS(GLenum target, GLfloat s, GLfloat t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2fSGIS(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2fvSGIS(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2fvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord2iSGIS(GLenum target, GLint s, GLint t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2iSGIS(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2ivSGIS(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2ivSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord2sSGIS(GLenum target, GLshort s, GLshort t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2sSGIS(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2svSGIS(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2svSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord3dSGIS(GLenum target, GLdouble s, GLdouble t, GLdouble r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3dSGIS(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3dvSGIS(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3dvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord3fSGIS(GLenum target, GLfloat s, GLfloat t, GLfloat r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3fSGIS(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3fvSGIS(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3fvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord3iSGIS(GLenum target, GLint s, GLint t, GLint r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3iSGIS(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3ivSGIS(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3ivSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord3sSGIS(GLenum target, GLshort s, GLshort t, GLshort r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3sSGIS(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3svSGIS(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3svSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord4dSGIS(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4dSGIS(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4dvSGIS(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4dvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord4fSGIS(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4fSGIS(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4fvSGIS(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4fvSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord4iSGIS(GLenum target, GLint s, GLint t, GLint r, GLint q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4iSGIS(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4ivSGIS(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4ivSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoord4sSGIS(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4sSGIS(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4svSGIS(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4svSGIS(target, v); +#endif +} + +static void AmiglMultiTexCoordPointerSGIS(GLenum target, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoordPointerSGIS(target, size, type, stride, pointer); +#endif +} + +static void AmiglSelectTextureSGIS(GLenum target) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glSelectTextureSGIS(target); +#endif +} + +static void AmiglSelectTextureCoordSetSGIS(GLenum target) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glSelectTextureCoordSetSGIS(target); +#endif +} + +static void AmiglMultiTexCoord1dEXT(GLenum target, GLdouble s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1dEXT(target, s); +#endif +} + +static void AmiglMultiTexCoord1dvEXT(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1dvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord1fEXT(GLenum target, GLfloat s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1fEXT(target, s); +#endif +} + +static void AmiglMultiTexCoord1fvEXT(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1fvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord1iEXT(GLenum target, GLint s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1iEXT(target, s); +#endif +} + +static void AmiglMultiTexCoord1ivEXT(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1ivEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord1sEXT(GLenum target, GLshort s) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1sEXT(target, s); +#endif +} + +static void AmiglMultiTexCoord1svEXT(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord1svEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord2dEXT(GLenum target, GLdouble s, GLdouble t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2dEXT(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2dvEXT(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2dvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord2fEXT(GLenum target, GLfloat s, GLfloat t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2fEXT(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2fvEXT(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2fvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord2iEXT(GLenum target, GLint s, GLint t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2iEXT(target, s, t); +#endif +} + +static void AmiglMultiTexCoord2ivEXT(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2ivEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord2sEXT(GLenum target, GLshort s, GLshort t) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2sEXT(target, s, t); +#endif +} +static void AmiglMultiTexCoord2svEXT(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord2svEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord3dEXT(GLenum target, GLdouble s, GLdouble t, GLdouble r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3dEXT(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3dvEXT(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3dvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord3fEXT(GLenum target, GLfloat s, GLfloat t, GLfloat r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3fEXT(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3fvEXT(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3fvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord3iEXT(GLenum target, GLint s, GLint t, GLint r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3iEXT(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3ivEXT(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3ivEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord3sEXT(GLenum target, GLshort s, GLshort t, GLshort r) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3sEXT(target, s, t, r); +#endif +} + +static void AmiglMultiTexCoord3svEXT(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord3svEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord4dEXT(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4dEXT(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4dvEXT(GLenum target, const GLdouble *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4dvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord4fEXT(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4fEXT(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4fvEXT(GLenum target, const GLfloat *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4fvEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord4iEXT(GLenum target, GLint s, GLint t, GLint r, GLint q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4iEXT(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4ivEXT(GLenum target, const GLint *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4ivEXT(target, v); +#endif +} + +static void AmiglMultiTexCoord4sEXT(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4sEXT(target, s, t, r, q); +#endif +} + +static void AmiglMultiTexCoord4svEXT(GLenum target, const GLshort *v) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glMultiTexCoord4svEXT(target, v); +#endif +} + +static void AmiglInterleavedTextureCoordSetsEXT( GLint factor ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glInterleavedTextureCoordSetsEXT(factor); +#endif +} + +static void AmiglSelectTextureEXT( GLenum target ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glSelectTextureEXT(target); +#endif +} + +static void AmiglSelectTextureCoordSetEXT( GLenum target ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glSelectTextureCoordSetEXT(target); +#endif +} + +static void AmiglSelectTextureTransformEXT( GLenum target ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glSelectTextureTransformEXT(target); +#endif +} + +static void AmiglPointParameterfEXT( GLenum pname, GLfloat param ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPointParameterfEXT(pname, param); +#endif +} + +static void AmiglPointParameterfvEXT( GLenum pname, GLfloat *params ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glPointParameterfvEXT(pname, params); +#endif +} + +static void AmiglWindowPos2iMESA( GLint x, GLint y ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2iMESA(x, y); +#endif +} + +static void AmiglWindowPos2sMESA( GLshort x, GLshort y ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2sMESA(x, y); +#endif +} + +static void AmiglWindowPos2fMESA( GLfloat x, GLfloat y ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2fMESA(x, y); +#endif +} + +static void AmiglWindowPos2dMESA( GLdouble x, GLdouble y ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2dMESA(x, y); +#endif +} + +static void AmiglWindowPos2ivMESA( const GLint *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2ivMESA(p); +#endif +} + +static void AmiglWindowPos2svMESA( const GLshort *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2svMESA(p); +#endif +} + +static void AmiglWindowPos2fvMESA( const GLfloat *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2fvMESA(p); +#endif +} + +static void AmiglWindowPos2dvMESA( const GLdouble *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos2dvMESA(p); +#endif +} + +static void AmiglWindowPos3iMESA( GLint x, GLint y, GLint z ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3iMESA(x, y, z); +#endif +} + +static void AmiglWindowPos3sMESA( GLshort x, GLshort y, GLshort z ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3sMESA(x, y, z); +#endif +} + +static void AmiglWindowPos3fMESA( GLfloat x, GLfloat y, GLfloat z ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3fMESA(x, y, z); +#endif +} + +static void AmiglWindowPos3dMESA( GLdouble x, GLdouble y, GLdouble z ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3dMESA(x, y, z); +#endif +} + +static void AmiglWindowPos3ivMESA( const GLint *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3ivMESA(p); +#endif +} + +static void AmiglWindowPos3svMESA( const GLshort *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3svMESA(p); +#endif +} + +static void AmiglWindowPos3fvMESA( const GLfloat *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3fvMESA(p); +#endif +} + +static void AmiglWindowPos3dvMESA( const GLdouble *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos3dvMESA(p); +#endif +} + +static void AmiglWindowPos4iMESA( GLint x, GLint y, GLint z, GLint w ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4iMESA(x, y, z, w); +#endif +} + +static void AmiglWindowPos4sMESA( GLshort x, GLshort y, GLshort z, GLshort w ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4sMESA(x, y, z, w); +#endif +} + +static void AmiglWindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4fMESA(x, y, z, w); +#endif +} + +static void AmiglWindowPos4dMESA( GLdouble x, GLdouble y, GLdouble z, GLdouble w) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4dMESA(x, y, z, w); +#endif +} + +static void AmiglWindowPos4ivMESA( const GLint *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4ivMESA(p); +#endif +} + +static void AmiglWindowPos4svMESA( const GLshort *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4svMESA(p); +#endif +} + +static void AmiglWindowPos4fvMESA( const GLfloat *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4fvMESA(p); +#endif +} + +static void AmiglWindowPos4dvMESA( const GLdouble *p ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glWindowPos4dvMESA(p); +#endif +} + +static void AmiglResizeBuffersMESA( void ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glResizeBuffersMESA(); +#endif +} + +static void AmiglTexImage3D( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); +#endif +} + +static void AmiglTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +#endif +} + +static void AmiglCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { +FUNC_NOT_IMPLEMENTED +#ifndef __amigaos4__ + return glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); +#endif +} + + + diff --git a/src/video/amigaos4/SDL_os4_notimplemented_table.t b/src/video/amigaos4/SDL_os4_notimplemented_table.t new file mode 100644 index 0000000000000..30991e573a239 --- /dev/null +++ b/src/video/amigaos4/SDL_os4_notimplemented_table.t @@ -0,0 +1,182 @@ +{ "glClearIndex", AmiglClearIndex }, +{ "glIndexMask", AmiglIndexMask }, +{ "glGetPolygonStipple", AmiglGetPolygonStipple }, +{ "glEdgeFlagv", AmiglEdgeFlagv }, +{ "glClearAccum", AmiglClearAccum }, +{ "glAccum", AmiglAccum }, +{ "glIndexd", AmiglIndexd }, +{ "glIndexf", AmiglIndexf }, +{ "glIndexi", AmiglIndexi }, +{ "glIndexs", AmiglIndexs }, +{ "glIndexub", AmiglIndexub }, +{ "glIndexdv", AmiglIndexdv }, +{ "glIndexfv", AmiglIndexfv }, +{ "glIndexiv", AmiglIndexiv }, +{ "glIndexsv", AmiglIndexsv }, +{ "glIndexubv", AmiglIndexubv }, +{ "glTexCoord1s", AmiglTexCoord1s }, +{ "glTexCoord2s", AmiglTexCoord2s }, +{ "glTexCoord3d", AmiglTexCoord3d }, +{ "glTexCoord3i", AmiglTexCoord3i }, +{ "glTexCoord3s", AmiglTexCoord3s }, +{ "glTexCoord4d", AmiglTexCoord4d }, +{ "glTexCoord4i", AmiglTexCoord4i }, +{ "glTexCoord4s", AmiglTexCoord4s }, +{ "glTexCoord1dv", AmiglTexCoord1dv }, +{ "glTexCoord1fv", AmiglTexCoord1fv }, +{ "glTexCoord1iv", AmiglTexCoord1iv }, +{ "glTexCoord1sv", AmiglTexCoord1sv }, +{ "glTexCoord2dv", AmiglTexCoord2dv }, +{ "glTexCoord2sv", AmiglTexCoord2sv }, +{ "glTexCoord3dv", AmiglTexCoord3dv }, +{ "glTexCoord3iv", AmiglTexCoord3iv }, +{ "glTexCoord3sv", AmiglTexCoord3sv }, +{ "glTexCoord4dv", AmiglTexCoord4dv }, +{ "glTexCoord4iv", AmiglTexCoord4iv }, +{ "glTexCoord4sv", AmiglTexCoord4sv }, +{ "glIndexPointer", AmiglIndexPointer }, +{ "glEdgeFlagPointer", AmiglEdgeFlagPointer }, +{ "glGetPointerv", AmiglGetPointerv }, +{ "glPixelMapfv", AmiglPixelMapfv }, +{ "glPixelMapuiv", AmiglPixelMapuiv }, +{ "glPixelMapusv", AmiglPixelMapusv }, +{ "glGetPixelMapfv", AmiglGetPixelMapfv }, +{ "glGetPixelMapuiv", AmiglGetPixelMapuiv }, +{ "glGetPixelMapusv", AmiglGetPixelMapusv }, +{ "glTexGend", AmiglTexGend }, +{ "glTexGenf", AmiglTexGenf }, +{ "glTexGendv", AmiglTexGendv }, +{ "glTexGeniv", AmiglTexGeniv }, +{ "glGetTexGendv", AmiglGetTexGendv }, +{ "glGetTexGenfv", AmiglGetTexGenfv }, +{ "glGetTexGeniv", AmiglGetTexGeniv }, +{ "glGetTexEnvfv", AmiglGetTexEnvfv }, +{ "glFogiv", AmiglFogiv }, +{ "glFeedbackBuffer", AmiglFeedbackBuffer }, +{ "glPassThrough", AmiglPassThrough }, +{ "glBlendEquationEXT", AmiglBlendEquationEXT }, +{ "glBlendColorEXT", AmiglBlendColorEXT }, +{ "glPolygonOffsetEXT", AmiglPolygonOffsetEXT }, +{ "glVertexPointerEXT", AmiglVertexPointerEXT }, +{ "glNormalPointerEXT", AmiglNormalPointerEXT }, +{ "glColorPointerEXT", AmiglColorPointerEXT }, +{ "glIndexPointerEXT", AmiglIndexPointerEXT }, +{ "glTexCoordPointerEXT", AmiglTexCoordPointerEXT }, +{ "glEdgeFlagPointerEXT", AmiglEdgeFlagPointerEXT }, +{ "glGetPointervEXT", AmiglGetPointervEXT }, +{ "glArrayElementEXT", AmiglArrayElementEXT }, +{ "glDrawArraysEXT", AmiglDrawArraysEXT }, +{ "glGenTexturesEXT", AmiglGenTexturesEXT }, +{ "glDeleteTexturesEXT", AmiglDeleteTexturesEXT }, +{ "glBindTextureEXT", AmiglBindTextureEXT }, +{ "glPrioritizeTexturesEXT", AmiglPrioritizeTexturesEXT }, +{ "glAreTexturesResidentEXT", AmiglAreTexturesResidentEXT }, +{ "glIsTextureEXT", AmiglIsTextureEXT }, +{ "glTexImage3DEXT", AmiglTexImage3DEXT }, +{ "glTexSubImage3DEXT", AmiglTexSubImage3DEXT }, +{ "glCopyTexSubImage3DEXT", AmiglCopyTexSubImage3DEXT }, +{ "glColorSubTableEXT", AmiglColorSubTableEXT }, +{ "glGetColorTableEXT", AmiglGetColorTableEXT }, +{ "glGetColorTableParameterfvEXT", AmiglGetColorTableParameterfvEXT }, +{ "glGetColorTableParameterivEXT", AmiglGetColorTableParameterivEXT }, +{ "glMultiTexCoord1dSGIS", AmiglMultiTexCoord1dSGIS }, +{ "glMultiTexCoord1dvSGIS", AmiglMultiTexCoord1dvSGIS }, +{ "glMultiTexCoord1fSGIS", AmiglMultiTexCoord1fSGIS }, +{ "glMultiTexCoord1fvSGIS", AmiglMultiTexCoord1fvSGIS }, +{ "glMultiTexCoord1iSGIS", AmiglMultiTexCoord1iSGIS }, +{ "glMultiTexCoord1ivSGIS", AmiglMultiTexCoord1ivSGIS }, +{ "glMultiTexCoord1sSGIS", AmiglMultiTexCoord1sSGIS }, +{ "glMultiTexCoord1svSGIS", AmiglMultiTexCoord1svSGIS }, +{ "glMultiTexCoord2dSGIS", AmiglMultiTexCoord2dSGIS }, +{ "glMultiTexCoord2dvSGIS", AmiglMultiTexCoord2dvSGIS }, +{ "glMultiTexCoord2fSGIS", AmiglMultiTexCoord2fSGIS }, +{ "glMultiTexCoord2fvSGIS", AmiglMultiTexCoord2fvSGIS }, +{ "glMultiTexCoord2iSGIS", AmiglMultiTexCoord2iSGIS }, +{ "glMultiTexCoord2ivSGIS", AmiglMultiTexCoord2ivSGIS }, +{ "glMultiTexCoord2sSGIS", AmiglMultiTexCoord2sSGIS }, +{ "glMultiTexCoord2svSGIS", AmiglMultiTexCoord2svSGIS }, +{ "glMultiTexCoord3dSGIS", AmiglMultiTexCoord3dSGIS }, +{ "glMultiTexCoord3dvSGIS", AmiglMultiTexCoord3dvSGIS }, +{ "glMultiTexCoord3fSGIS", AmiglMultiTexCoord3fSGIS }, +{ "glMultiTexCoord3fvSGIS", AmiglMultiTexCoord3fvSGIS }, +{ "glMultiTexCoord3iSGIS", AmiglMultiTexCoord3iSGIS }, +{ "glMultiTexCoord3ivSGIS", AmiglMultiTexCoord3ivSGIS }, +{ "glMultiTexCoord3sSGIS", AmiglMultiTexCoord3sSGIS }, +{ "glMultiTexCoord3svSGIS", AmiglMultiTexCoord3svSGIS }, +{ "glMultiTexCoord4dSGIS", AmiglMultiTexCoord4dSGIS }, +{ "glMultiTexCoord4dvSGIS", AmiglMultiTexCoord4dvSGIS }, +{ "glMultiTexCoord4fSGIS", AmiglMultiTexCoord4fSGIS }, +{ "glMultiTexCoord4fvSGIS", AmiglMultiTexCoord4fvSGIS }, +{ "glMultiTexCoord4iSGIS", AmiglMultiTexCoord4iSGIS }, +{ "glMultiTexCoord4ivSGIS", AmiglMultiTexCoord4ivSGIS }, +{ "glMultiTexCoord4sSGIS", AmiglMultiTexCoord4sSGIS }, +{ "glMultiTexCoord4svSGIS", AmiglMultiTexCoord4svSGIS }, +{ "glMultiTexCoordPointerSGIS", AmiglMultiTexCoordPointerSGIS }, +{ "glSelectTextureSGIS", AmiglSelectTextureSGIS }, +{ "glSelectTextureCoordSetSGIS", AmiglSelectTextureCoordSetSGIS }, +{ "glMultiTexCoord1dEXT", AmiglMultiTexCoord1dEXT }, +{ "glMultiTexCoord1dvEXT", AmiglMultiTexCoord1dvEXT }, +{ "glMultiTexCoord1fEXT", AmiglMultiTexCoord1fEXT }, +{ "glMultiTexCoord1fvEXT", AmiglMultiTexCoord1fvEXT }, +{ "glMultiTexCoord1iEXT", AmiglMultiTexCoord1iEXT }, +{ "glMultiTexCoord1ivEXT", AmiglMultiTexCoord1ivEXT }, +{ "glMultiTexCoord1sEXT", AmiglMultiTexCoord1sEXT }, +{ "glMultiTexCoord1svEXT", AmiglMultiTexCoord1svEXT }, +{ "glMultiTexCoord2dEXT", AmiglMultiTexCoord2dEXT }, +{ "glMultiTexCoord2dvEXT", AmiglMultiTexCoord2dvEXT }, +{ "glMultiTexCoord2fEXT", AmiglMultiTexCoord2fEXT }, +{ "glMultiTexCoord2fvEXT", AmiglMultiTexCoord2fvEXT }, +{ "glMultiTexCoord2iEXT", AmiglMultiTexCoord2iEXT }, +{ "glMultiTexCoord2ivEXT", AmiglMultiTexCoord2ivEXT }, +{ "glMultiTexCoord2sEXT", AmiglMultiTexCoord2sEXT }, +{ "glMultiTexCoord2svEXT", AmiglMultiTexCoord2svEXT }, +{ "glMultiTexCoord3dEXT", AmiglMultiTexCoord3dEXT }, +{ "glMultiTexCoord3dvEXT", AmiglMultiTexCoord3dvEXT }, +{ "glMultiTexCoord3fEXT", AmiglMultiTexCoord3fEXT }, +{ "glMultiTexCoord3fvEXT", AmiglMultiTexCoord3fvEXT }, +{ "glMultiTexCoord3iEXT", AmiglMultiTexCoord3iEXT }, +{ "glMultiTexCoord3ivEXT", AmiglMultiTexCoord3ivEXT }, +{ "glMultiTexCoord3sEXT", AmiglMultiTexCoord3sEXT }, +{ "glMultiTexCoord3svEXT", AmiglMultiTexCoord3svEXT }, +{ "glMultiTexCoord4dEXT", AmiglMultiTexCoord4dEXT }, +{ "glMultiTexCoord4dvEXT", AmiglMultiTexCoord4dvEXT }, +{ "glMultiTexCoord4fEXT", AmiglMultiTexCoord4fEXT }, +{ "glMultiTexCoord4fvEXT", AmiglMultiTexCoord4fvEXT }, +{ "glMultiTexCoord4iEXT", AmiglMultiTexCoord4iEXT }, +{ "glMultiTexCoord4ivEXT", AmiglMultiTexCoord4ivEXT }, +{ "glMultiTexCoord4sEXT", AmiglMultiTexCoord4sEXT }, +{ "glMultiTexCoord4svEXT", AmiglMultiTexCoord4svEXT }, +{ "glInterleavedTextureCoordSetsEXT", AmiglInterleavedTextureCoordSetsEXT }, +{ "glSelectTextureEXT", AmiglSelectTextureEXT }, +{ "glSelectTextureCoordSetEXT", AmiglSelectTextureCoordSetEXT }, +{ "glSelectTextureTransformEXT", AmiglSelectTextureTransformEXT }, +{ "glPointParameterfEXT", AmiglPointParameterfEXT }, +{ "glPointParameterfvEXT", AmiglPointParameterfvEXT }, +{ "glWindowPos2iMESA", AmiglWindowPos2iMESA }, +{ "glWindowPos2sMESA", AmiglWindowPos2sMESA }, +{ "glWindowPos2fMESA", AmiglWindowPos2fMESA }, +{ "glWindowPos2dMESA", AmiglWindowPos2dMESA }, +{ "glWindowPos2ivMESA", AmiglWindowPos2ivMESA }, +{ "glWindowPos2svMESA", AmiglWindowPos2svMESA }, +{ "glWindowPos2fvMESA", AmiglWindowPos2fvMESA }, +{ "glWindowPos2dvMESA", AmiglWindowPos2dvMESA }, +{ "glWindowPos3iMESA", AmiglWindowPos3iMESA }, +{ "glWindowPos3sMESA", AmiglWindowPos3sMESA }, +{ "glWindowPos3fMESA", AmiglWindowPos3fMESA }, +{ "glWindowPos3dMESA", AmiglWindowPos3dMESA }, +{ "glWindowPos3ivMESA", AmiglWindowPos3ivMESA }, +{ "glWindowPos3svMESA", AmiglWindowPos3svMESA }, +{ "glWindowPos3fvMESA", AmiglWindowPos3fvMESA }, +{ "glWindowPos3dvMESA", AmiglWindowPos3dvMESA }, +{ "glWindowPos4iMESA", AmiglWindowPos4iMESA }, +{ "glWindowPos4sMESA", AmiglWindowPos4sMESA }, +{ "glWindowPos4fMESA", AmiglWindowPos4fMESA }, +{ "glWindowPos4dMESA", AmiglWindowPos4dMESA }, +{ "glWindowPos4ivMESA", AmiglWindowPos4ivMESA }, +{ "glWindowPos4svMESA", AmiglWindowPos4svMESA }, +{ "glWindowPos4fvMESA", AmiglWindowPos4fvMESA }, +{ "glWindowPos4dvMESA", AmiglWindowPos4dvMESA }, +{ "glResizeBuffersMESA", AmiglResizeBuffersMESA }, +{ "glTexImage3D", AmiglTexImage3D }, +{ "glTexSubImage3D", AmiglTexSubImage3D }, +{ "glCopyTexSubImage3D", AmiglCopyTexSubImage3D }, diff --git a/src/video/amigaos4/SDL_os4events.c b/src/video/amigaos4/SDL_os4events.c new file mode 100644 index 0000000000000..aed9edb12974b --- /dev/null +++ b/src/video/amigaos4/SDL_os4events.c @@ -0,0 +1,701 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include +#include + +#include "SDL_os4video.h" +#include "SDL_os4shape.h" +#include "SDL_os4mouse.h" +#include "SDL_os4window.h" +#include "SDL_os4events.h" + +#include "../../events/SDL_keyboard_c.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_windowevents_c.h" +#include "../../events/scancodes_amiga.h" +#include "../../events/SDL_events_c.h" + +//#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +extern SDL_bool (*OS4_ResizeGlContext)(_THIS, SDL_Window * window); + +struct MyIntuiMessage +{ + uint32 Class; + uint16 Code; + uint16 Qualifier; + + struct Gadget *Gadget; + struct Window *IDCMPWindow; + + int16 RelativeMouseX; + int16 RelativeMouseY; + + int16 WindowMouseX; // Absolute pointer position, relative to + int16 WindowMouseY; // top-left corner of inner window + + int16 ScreenMouseX; + int16 ScreenMouseY; + + int16 Width; // Inner window dimensions + int16 Height; +}; + +struct QualifierItem +{ + UWORD qualifier; + SDL_Keymod keymod; + const char* name; +}; + +extern OS4_GlobalMouseState globalMouseState; + +static void +OS4_SyncKeyModifiers(_THIS) +{ + int i; + UWORD qualifiers = IInput->PeekQualifier(); + + struct QualifierItem map[] = { + { IEQUALIFIER_LSHIFT, KMOD_LSHIFT, "Left Shift" }, + { IEQUALIFIER_RSHIFT, KMOD_RSHIFT, "Right Shift" }, + { IEQUALIFIER_CAPSLOCK, KMOD_CAPS, "Capslock" }, + { IEQUALIFIER_CONTROL, KMOD_CTRL, "Control" }, + { IEQUALIFIER_LALT, KMOD_LALT, "Left Alt" }, + { IEQUALIFIER_RALT, KMOD_RALT, "Right Alt" }, + { IEQUALIFIER_LCOMMAND, KMOD_LGUI, "Left Amiga" }, + { IEQUALIFIER_RCOMMAND, KMOD_RGUI, "Right Amiga" } + }; + + dprintf("Current qualifiers: %d\n", qualifiers); + + for (i = 0; i < SDL_arraysize(map); i++) { + dprintf("%s %s\n", map[i].name, (qualifiers & map[i].qualifier) ? "ON" : "off"); + SDL_ToggleModState(map[i].keymod, (qualifiers & map[i].qualifier) != 0); + } +} + +// We could possibly use also Window.userdata field to contain SDL_Window, +// and thus avoid searching +static SDL_Window * +OS4_FindWindow(_THIS, struct Window * syswin) +{ + SDL_Window *sdlwin; + + for (sdlwin = _this->windows; sdlwin; sdlwin = sdlwin->next) { + + SDL_WindowData *data = sdlwin->driverdata; + + if (data->syswin == syswin) { + + //dprintf("Found window %p\n", syswin); + return sdlwin; + } + } + + dprintf("No SDL window found\n"); + + return NULL; +} + +static char +OS4_TranslateUnicode(_THIS, uint16 code, uint32 qualifier) +{ + struct InputEvent ie; + uint16 res; + char buffer[10]; + + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_SubClass = 0; + ie.ie_Code = code & ~(IECODE_UP_PREFIX); + ie.ie_Qualifier = qualifier; + ie.ie_EventAddress = NULL; + + res = IKeymap->MapRawKey(&ie, buffer, sizeof(buffer), 0); + + if (res != 1) + return 0; + else + return buffer[0]; +} + +static void +OS4_HandleKeyboard(_THIS, struct MyIntuiMessage * imsg) +{ + uint8 rawkey = imsg->Code & 0x7F; + + if (rawkey < sizeof(amiga_scancode_table) / sizeof(amiga_scancode_table[0])) { + + SDL_Scancode s = amiga_scancode_table[rawkey]; + + if (imsg->Code < 0x80) { + char text[2]; + + text[0] = OS4_TranslateUnicode(_this, imsg->Code, imsg->Qualifier); + text[1] = '\0'; + + SDL_SendKeyboardKey(SDL_PRESSED, s); + + if (text[0] && text[0] < 0x80) { + /* SDL wants UTF-8 strings. Filter out codes above 7-bit to avoid + interpretation issues later. */ + SDL_SendKeyboardText(text); + } + } else { + SDL_SendKeyboardKey(SDL_RELEASED, s); + } + } +} + +static void +OS4_HandleHitTestMotion(_THIS, SDL_Window * sdlwin, struct MyIntuiMessage * imsg) +{ + HitTestInfo *hti = &((SDL_WindowData *)sdlwin->driverdata)->hti; + + int16 newx = imsg->ScreenMouseX; + int16 newy = imsg->ScreenMouseY; + + int16 deltax = newx - hti->point.x; + int16 deltay = newy - hti->point.y; + + int16 x, y, w, h; + + if (deltax == 0 && deltay == 0) { + return; + } + + x = sdlwin->x; + y = sdlwin->y; + w = sdlwin->w; + h = sdlwin->h; + + hti->point.x = newx; + hti->point.y = newy; + + switch (hti->htr) { + case SDL_HITTEST_DRAGGABLE: + x += deltax; + y += deltay; + break; + + case SDL_HITTEST_RESIZE_TOPLEFT: + x += deltax; + y += deltay; + w -= deltax; + h -= deltay; + break; + + case SDL_HITTEST_RESIZE_TOP: + y += deltay; + h -= deltay; + break; + + case SDL_HITTEST_RESIZE_TOPRIGHT: + y += deltay; + w += deltax; + h -= deltay; + break; + + case SDL_HITTEST_RESIZE_RIGHT: + w += deltax; + break; + + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: + w += deltax; + h += deltay; + break; + + case SDL_HITTEST_RESIZE_BOTTOM: + h += deltay; + break; + + case SDL_HITTEST_RESIZE_BOTTOMLEFT: + x += deltax; + + w -= deltax; + h += deltay; + break; + + case SDL_HITTEST_RESIZE_LEFT: + x += deltax; + w -= deltax; + break; + + default: + break; + } + + dprintf("newx %d, newy %d (dx %d, dy %d) w=%d h=%d\n", newx, newy, deltax, deltay, w, h); + + sdlwin->x = x; + sdlwin->y = y; + sdlwin->w = w; + sdlwin->h = h; + + OS4_SetWindowBox(_this, sdlwin); +} + +static SDL_bool +OS4_IsHitTestResize(HitTestInfo * hti) +{ + switch (hti->htr) { + case SDL_HITTEST_RESIZE_TOPLEFT: + case SDL_HITTEST_RESIZE_TOP: + case SDL_HITTEST_RESIZE_TOPRIGHT: + case SDL_HITTEST_RESIZE_RIGHT: + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: + case SDL_HITTEST_RESIZE_BOTTOM: + case SDL_HITTEST_RESIZE_BOTTOMLEFT: + case SDL_HITTEST_RESIZE_LEFT: + return SDL_TRUE; + + default: + return SDL_FALSE; + } +} + +static void +OS4_HandleMouseMotion(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + HitTestInfo *hti = &((SDL_WindowData *)sdlwin->driverdata)->hti; + + dprintf("X:%d Y:%d, ScreenX: %d ScreenY: %d\n", + imsg->WindowMouseX, imsg->WindowMouseY, imsg->ScreenMouseX, imsg->ScreenMouseY); + + globalMouseState.x = imsg->ScreenMouseX; + globalMouseState.y = imsg->ScreenMouseY; + + if (SDL_GetRelativeMouseMode()) { + SDL_SendMouseMotion(sdlwin, 0 /*mouse->mouseID*/, 1, + imsg->RelativeMouseX, + imsg->RelativeMouseY); + } else { + SDL_SendMouseMotion(sdlwin, 0 /*mouse->mouseID*/, 0, + imsg->WindowMouseX, + imsg->WindowMouseY); + } + + if (hti->htr != SDL_HITTEST_NORMAL) { + OS4_HandleHitTestMotion(_this, sdlwin, imsg); + } + } +} + +static SDL_bool +OS4_HandleHitTest(_THIS, SDL_Window * sdlwin, struct MyIntuiMessage * imsg) +{ + if (sdlwin->hit_test) { + const SDL_Point point = { imsg->WindowMouseX, imsg->WindowMouseY }; + const SDL_HitTestResult rc = sdlwin->hit_test(sdlwin, &point, sdlwin->hit_test_data); + + HitTestInfo *hti = &((SDL_WindowData *)sdlwin->driverdata)->hti; + + switch (rc) { + case SDL_HITTEST_DRAGGABLE: + case SDL_HITTEST_RESIZE_TOPLEFT: + case SDL_HITTEST_RESIZE_TOP: + case SDL_HITTEST_RESIZE_TOPRIGHT: + case SDL_HITTEST_RESIZE_RIGHT: + case SDL_HITTEST_RESIZE_BOTTOMRIGHT: + case SDL_HITTEST_RESIZE_BOTTOM: + case SDL_HITTEST_RESIZE_BOTTOMLEFT: + case SDL_HITTEST_RESIZE_LEFT: + // Store the action and mouse coordinates for later use + hti->htr = rc; + hti->point.x = imsg->ScreenMouseX; + hti->point.y = imsg->ScreenMouseY; + + return SDL_TRUE; + + default: + return SDL_FALSE; + } + } + + return SDL_FALSE; +} + +static int +OS4_GetButtonState(uint16 code) +{ + return (code & IECODE_UP_PREFIX) ? SDL_RELEASED : SDL_PRESSED; +} + +static int +OS4_GetButton(uint16 code) +{ + switch (code & ~IECODE_UP_PREFIX) { + case IECODE_LBUTTON: + return SDL_BUTTON_LEFT; + case IECODE_RBUTTON: + return SDL_BUTTON_RIGHT; + case IECODE_MBUTTON: + return SDL_BUTTON_MIDDLE; + default: + return 0; + } +} + +static void +OS4_HandleMouseButtons(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + uint8 button = OS4_GetButton(imsg->Code); + uint8 state = OS4_GetButtonState(imsg->Code); + + globalMouseState.buttonPressed[button] = state; + + dprintf("X:%d Y:%d button:%d state:%d\n", + imsg->WindowMouseX, imsg->WindowMouseY, button, state); + + if (button == SDL_BUTTON_LEFT) { + if (state == SDL_PRESSED) { + + if (OS4_HandleHitTest(_this, sdlwin, imsg)) { + return; + } + } else { + HitTestInfo *hti = &((SDL_WindowData *)sdlwin->driverdata)->hti; + + hti->htr = SDL_HITTEST_NORMAL; + // TODO: shape resize? OpenGL resize? + SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_RESIZED, + imsg->Width, imsg->Height); + } + } + + // TODO: can we support more buttons? + SDL_SendMouseButton(sdlwin, 0, state, button); + } +} + +static void +OS4_HandleMouseWheel(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + struct IntuiWheelData *data = (struct IntuiWheelData *)imsg->Gadget; + + if (data->WheelY < 0) { + SDL_SendMouseWheel(sdlwin, 0, 0, 1, SDL_MOUSEWHEEL_NORMAL); + } else if (data->WheelY > 0) { + SDL_SendMouseWheel(sdlwin, 0, 0, -1, SDL_MOUSEWHEEL_NORMAL); + } + + if (data->WheelX < 0) { + SDL_SendMouseWheel(sdlwin, 0, 1, 0, SDL_MOUSEWHEEL_NORMAL); + } else if (data->WheelX > 0) { + SDL_SendMouseWheel(sdlwin, 0, -1, 0, SDL_MOUSEWHEEL_NORMAL); + } + } +} + +static void +OS4_HandleResize(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + HitTestInfo *hti = &((SDL_WindowData *)sdlwin->driverdata)->hti; + + if (OS4_IsHitTestResize(hti)) { + // Intuition notifies about resize during hit test action, + // but it will confuse hit test logic. + // That is why we ignore these for now. + dprintf("Resize notification ignored because resize is still in progress\n"); + } else { + dprintf("Window resized to %d*%d\n", imsg->Width, imsg->Height); + + if (imsg->Width != sdlwin->w || imsg->Height != sdlwin->h) { + SDL_WindowData *data = (SDL_WindowData *)sdlwin->driverdata; + + SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_RESIZED, + imsg->Width, + imsg->Height); + + if (SDL_IsShapedWindow(sdlwin)) { + OS4_ResizeWindowShape(sdlwin); + } + + if (data->glContext /*sdlwin->flags & SDL_WINDOW_OPENGL*/ ) { + OS4_ResizeGlContext(_this, sdlwin); + } + } + } + } +} + +static void +OS4_HandleMove(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_MOVED, + imsg->IDCMPWindow->LeftEdge, + imsg->IDCMPWindow->TopEdge); + + dprintf("Window %p changed\n", sdlwin); + } +} + +static void +OS4_HandleActivation(_THIS, struct MyIntuiMessage * imsg, SDL_bool activated) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + if (activated) { + SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_SHOWN, 0, 0); + OS4_SyncKeyModifiers(_this); + + if (SDL_GetKeyboardFocus() != sdlwin) { + SDL_SetKeyboardFocus(sdlwin); + // TODO: do we want to set mouse colors as in SDL1? + } + } else { + if (SDL_GetKeyboardFocus() == sdlwin) { + SDL_SetKeyboardFocus(NULL); + // TODO: do we want to reset mouse colors as in SDL1? + } + } + + dprintf("Window %p activation %d\n", sdlwin, activated); + } +} + +static void +OS4_HandleClose(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_CLOSE, 0, 0); + } +} + +static void +OS4_HandleTicks(_THIS, struct MyIntuiMessage * imsg) +{ + SDL_Window *sdlwin = OS4_FindWindow(_this, imsg->IDCMPWindow); + + if (sdlwin) { + if ((sdlwin->flags & SDL_WINDOW_INPUT_GRABBED) && !(sdlwin->flags & SDL_WINDOW_FULLSCREEN) && + (SDL_GetKeyboardFocus() == sdlwin)) { + + SDL_WindowData *data = sdlwin->driverdata; + + dprintf("Window %p ticks %d\n", imsg->IDCMPWindow, data->pointerGrabTicks); + + // Re-grab the window after our ticks have passed + if (++data->pointerGrabTicks >= POINTER_GRAB_TIMEOUT) { + data->pointerGrabTicks = 0; + + OS4_SetWindowGrabPrivate(_this, imsg->IDCMPWindow, TRUE); + } + } + } +} + +static void +OS4_HandleGadget(_THIS, struct MyIntuiMessage * msg) +{ + dprintf("Gadget event %p\n", msg->Gadget); + + if (msg->Gadget->GadgetID == GID_ICONIFY) { + SDL_Window *sdlwin = OS4_FindWindow(_this, msg->IDCMPWindow); + + if (sdlwin) { + dprintf("Iconify button pressed\n"); + OS4_IconifyWindow(_this, sdlwin); + } + } +} + +static void +OS4_HandleAppWindow(_THIS, struct AppMessage * msg) +{ + SDL_Window *window = (SDL_Window *)msg->am_UserData; + + int i; + for (i = 0; i < msg->am_NumArgs; i++) { + const size_t maxPathLen = 255; + char buf[maxPathLen]; + + if (IDOS->NameFromLock(msg->am_ArgList[i].wa_Lock, buf, sizeof(buf))) { + if (IDOS->AddPart(buf, msg->am_ArgList[i].wa_Name, sizeof(buf))) { + dprintf("%s\n", buf); + SDL_SendDropFile(window, buf); + } + } + } + + SDL_SendDropComplete(window); +} + +static void +OS4_HandleAppIcon(_THIS, struct AppMessage * msg) +{ + SDL_Window *window = (SDL_Window *)msg->am_UserData; + dprintf("Window ptr = %p\n", window); + + OS4_UniconifyWindow(_this, window); +} + +static void +OS4_CopyIdcmpMessage(struct IntuiMessage * src, struct MyIntuiMessage * dst) +{ + // Copy relevant fields. This makes it safer if the window goes away during + // this loop (re-open due to keystroke) + dst->Class = src->Class; + dst->Code = src->Code; + dst->Qualifier = src->Qualifier; + + dst->Gadget = (struct Gadget *) src->IAddress; + + dst->RelativeMouseX = src->MouseX; + dst->RelativeMouseY = src->MouseY; + + dst->IDCMPWindow = src->IDCMPWindow; + + if (src->IDCMPWindow) { + dst->WindowMouseX = src->IDCMPWindow->MouseX - src->IDCMPWindow->BorderLeft; + dst->WindowMouseY = src->IDCMPWindow->MouseY - src->IDCMPWindow->BorderTop; + + dst->ScreenMouseX = src->IDCMPWindow->WScreen->MouseX; + dst->ScreenMouseY = src->IDCMPWindow->WScreen->MouseY; + + dst->Width = src->IDCMPWindow->Width - src->IDCMPWindow->BorderLeft - src->IDCMPWindow->BorderRight; + dst->Height = src->IDCMPWindow->Height - src->IDCMPWindow->BorderTop - src->IDCMPWindow->BorderBottom; + } +} + +// TODO: we need to handle Intuition's window move (repositioning) event and update sdlwin's x&y +static void +OS4_HandleIdcmpMessages(_THIS, struct MsgPort * msgPort) +{ + struct IntuiMessage *imsg; + struct MyIntuiMessage msg; + + while ((imsg = (struct IntuiMessage *)IExec->GetMsg(msgPort))) { + + OS4_CopyIdcmpMessage(imsg, &msg); + + IExec->ReplyMsg((struct Message *) imsg); + + switch (msg.Class) { + case IDCMP_MOUSEMOVE: + OS4_HandleMouseMotion(_this, &msg); + break; + + case IDCMP_RAWKEY: + OS4_HandleKeyboard(_this, &msg); + break; + + case IDCMP_MOUSEBUTTONS: + OS4_HandleMouseButtons(_this, &msg); + break; + + case IDCMP_EXTENDEDMOUSE: + OS4_HandleMouseWheel(_this, &msg); + break; + + case IDCMP_NEWSIZE: + OS4_HandleResize(_this, &msg); + break; + + case IDCMP_CHANGEWINDOW: + OS4_HandleMove(_this, &msg); + OS4_HandleResize(_this, &msg); + break; + + case IDCMP_ACTIVEWINDOW: + OS4_HandleActivation(_this, &msg, SDL_TRUE); + break; + + case IDCMP_INACTIVEWINDOW: + OS4_HandleActivation(_this, &msg, SDL_FALSE); + break; + + case IDCMP_CLOSEWINDOW: + OS4_HandleClose(_this, &msg); + break; + + case IDCMP_INTUITICKS: + OS4_HandleTicks(_this, &msg); + break; + + case IDCMP_GADGETUP: + OS4_HandleGadget(_this, &msg); + break; + + default: + dprintf("Unknown event received class %d, code %d\n", msg.Class, msg.Code); + break; + } + } +} + +static void +OS4_HandleAppMessages(_THIS, struct MsgPort * msgPort) +{ + struct AppMessage *msg; + + while ((msg = (struct AppMessage *)IExec->GetMsg(msgPort))) { + switch (msg->am_Type) { + case AMTYPE_APPWINDOW: + OS4_HandleAppWindow(_this, msg); + break; + case AMTYPE_APPICON: + OS4_HandleAppIcon(_this, msg); + break; + default: + dprintf("Unknown AppMsg %d %p\n", msg->am_Type, (APTR)msg->am_UserData); + break; + } + + IExec->ReplyMsg((struct Message *) msg); + } +} + +void +OS4_PumpEvents(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + OS4_HandleIdcmpMessages(_this, data->userPort); + OS4_HandleAppMessages(_this, data->appMsgPort); +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4events.h b/src/video/amigaos4/SDL_os4events.h new file mode 100644 index 0000000000000..96d194c11b6f8 --- /dev/null +++ b/src/video/amigaos4/SDL_os4events.h @@ -0,0 +1,30 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4events_h +#define _SDL_os4events_h + +extern void OS4_PumpEvents(_THIS); + +#endif /* _SDL_os4events_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4framebuffer.c b/src/video/amigaos4/SDL_os4framebuffer.c new file mode 100644 index 0000000000000..cd04cd8078ac7 --- /dev/null +++ b/src/video/amigaos4/SDL_os4framebuffer.c @@ -0,0 +1,203 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include "SDL_os4video.h" +#include "SDL_os4framebuffer.h" +#include "SDL_os4window.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static Uint32 +OS4_PixfToSdlPixelFormat(PIX_FMT from) +{ + switch (from) { + // 32-bit + case PIXF_A8R8G8B8: return SDL_PIXELFORMAT_ARGB8888; + case PIXF_B8G8R8A8: return SDL_PIXELFORMAT_BGRA8888; + case PIXF_A8B8G8R8: return SDL_PIXELFORMAT_ABGR8888; + case PIXF_R8G8B8A8: return SDL_PIXELFORMAT_RGBA8888; + // 24-bit (WinUAE Picasso-IV may use one) + case PIXF_R8G8B8: return SDL_PIXELFORMAT_RGB888; + case PIXF_B8G8R8: return SDL_PIXELFORMAT_BGR888; + // 16-bit + case PIXF_R5G6B5: return SDL_PIXELFORMAT_RGB565; + // 8-bit + case PIXF_CLUT: return SDL_PIXELFORMAT_INDEX8; + // What else we have... + default: + dprintf("Unknown native pixel format %d\n", from); + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +int +OS4_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int * pitch) +{ + SDL_WindowData *data = window->driverdata; + + if (data) { + APTR lock; + APTR base_address; + uint32 bytes_per_row; + uint32 depth; + PIX_FMT pixf; + + if (data->bitmap) { + dprintf("Freeing old bitmap %p\n", data->bitmap); + IGraphics->FreeBitMap(data->bitmap); + } + + if (!data->syswin) { + dprintf("No system window\n"); + return SDL_SetError("No system window"); + } + + pixf = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_PIXELFORMAT); + depth = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_BITSPERPIXEL); + + *format = OS4_PixfToSdlPixelFormat(pixf); + + dprintf("Native format %d, SDL format %d (%s)\n", pixf, *format, SDL_GetPixelFormatName(*format)); + dprintf("Allocating %d*%d*%d bitmap)\n", window->w, window->h, depth); + + data->bitmap = IGraphics->AllocBitMapTags( + window->w, + window->h, + depth, + BMATags_Clear, TRUE, + BMATags_UserPrivate, TRUE, + //BMATags_Friend, data->syswin->RPort->BitMap, + BMATags_PixelFormat, pixf, + TAG_DONE); + + if (!data->bitmap) { + dprintf("Failed to allocate bitmap\n"); + return SDL_SetError("Failed to allocate bitmap for framebuffer"); + } + + /* Lock the bitmap to get details. Since it's user private, + it should be safe to cache address and pitch. */ + lock = IGraphics->LockBitMapTags( + data->bitmap, + LBM_BaseAddress, &base_address, + LBM_BytesPerRow, &bytes_per_row, + TAG_DONE); + + if (lock) { + *pixels = base_address; + *pitch = bytes_per_row; + + IGraphics->UnlockBitMap(lock); + } else { + dprintf("Failed to lock bitmap\n"); + + IGraphics->FreeBitMap(data->bitmap); + data->bitmap = NULL; + + return SDL_SetError("Failed to lock framebuffer bitmap"); + } + } + + return 0; +} + +#ifndef MIN +# define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +int +OS4_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) +{ + SDL_WindowData * data = window->driverdata; + int32 ret = -1; + + //dprintf("Called\n"); + + if (data && data->bitmap) { + if (data->syswin) { + + int i; + + struct Window *syswin = data->syswin; + + const struct IBox windowBox = { + syswin->BorderLeft, + syswin->BorderTop, + syswin->Width - syswin->BorderLeft - syswin->BorderRight, + syswin->Height - syswin->BorderTop - syswin->BorderBottom }; + + //dprintf("blit box %d*%d\n", windowBox.Width, windowBox.Height); + + ILayers->LockLayer(0, syswin->WLayer); + + for (i = 0; i < numrects; ++i) { + const SDL_Rect * r = &rects[i]; + + ret = IGraphics->BltBitMapTags( + BLITA_Source, data->bitmap, + //BLITA_SrcType, BLITT_BITMAP, + BLITA_Dest, syswin->RPort, + BLITA_DestType, BLITT_RASTPORT, + BLITA_SrcX, r->x, + BLITA_SrcY, r->y, + BLITA_DestX, r->x + windowBox.Left, + BLITA_DestY, r->y + windowBox.Top, + BLITA_Width, MIN(r->w, windowBox.Width), + BLITA_Height, MIN(r->h, windowBox.Height), + TAG_DONE); + + if (ret != -1) { + dprintf("BltBitMapTags() returned %d\n", ret); + } + } + + ILayers->UnlockLayer(syswin->WLayer); + } + } + + if (ret != -1) { + return SDL_SetError("BltBitMapTags failed"); + } + + return 0; +} + +void +OS4_DestroyWindowFramebuffer(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (data && data->bitmap) { + + dprintf("Freeing bitmap %p\n", data->bitmap); + + IGraphics->FreeBitMap(data->bitmap); + data->bitmap = NULL; + } +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4framebuffer.h b/src/video/amigaos4/SDL_os4framebuffer.h new file mode 100644 index 0000000000000..91e6e6839b153 --- /dev/null +++ b/src/video/amigaos4/SDL_os4framebuffer.h @@ -0,0 +1,32 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4framebuffer_h +#define _SDL_os4framebuffer_h + +extern int OS4_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); +extern int OS4_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); +extern void OS4_DestroyWindowFramebuffer(_THIS, SDL_Window * window); + +#endif /* _SDL_os4framebuffer_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4keyboard.c b/src/video/amigaos4/SDL_os4keyboard.c new file mode 100644 index 0000000000000..79d9f437e714e --- /dev/null +++ b/src/video/amigaos4/SDL_os4keyboard.c @@ -0,0 +1,164 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include "SDL_os4video.h" +#include "SDL_os4keyboard.h" + +#include "../../events/SDL_keyboard_c.h" +#include "../../events/scancodes_amiga.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static SDL_Keycode +OS4_MapRawKey(_THIS, int code) +{ + struct InputEvent ie; + int res; + char buffer[2] = {0, 0}; + + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_SubClass = 0; + ie.ie_Code = code; + ie.ie_Qualifier = 0; + ie.ie_EventAddress = NULL; + + res = IKeymap->MapRawKey(&ie, buffer, sizeof(buffer), NULL); + if (res > 0) { + return (buffer[0] + buffer[1] * 256); + } else { + return 0; + } +} + +static void +OS4_UpdateKeymap(_THIS) +{ + int i; + SDL_Scancode scancode; + SDL_Keycode keymap[SDL_NUM_SCANCODES]; + + SDL_GetDefaultKeymap(keymap); + + for (i = 0; i < SDL_arraysize(amiga_scancode_table); i++) { + /* Make sure this scancode is a valid character scancode */ + scancode = amiga_scancode_table[i]; + if (scancode == SDL_SCANCODE_UNKNOWN ) { + continue; + } + + /* If this key is one of the non-mappable keys, ignore it */ + /* Don't allow the number keys right above the qwerty row to translate or the top left key (grave/backquote) */ + /* Not mapping numbers fixes the French layout, giving numeric keycodes for the number keys, which is the expected behavior */ + if ((keymap[scancode] & SDLK_SCANCODE_MASK) || + scancode == SDL_SCANCODE_GRAVE /*|| + (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0)*/ ) { + continue; + } + + keymap[scancode] = OS4_MapRawKey(_this, i); + } + + SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES); +} + +int +OS4_SetClipboardText(_THIS, const char *text) +{ + LONG result = ITextClip->WriteClipVector(text, SDL_strlen(text)); + + //dprintf("Result %s\n", result ? "OK" : "NOK"); + + return result ? 0 : -1; +} + +char * +OS4_GetClipboardText(_THIS) +{ + STRPTR from; + ULONG size; + char *to = NULL; + + LONG result = ITextClip->ReadClipVector(&from, &size); + + //dprintf("Read '%s' (%d bytes) from clipboard\n", from, size); + + if (result) { + + if (size) { + to = SDL_malloc( ++size ); + + if (to) { + SDL_strlcpy(to, from, size); + } else { + dprintf("Failed to allocate memory\n"); + } + } else { + to = SDL_strdup(""); + } + + ITextClip->DisposeClipVector(from); + } + + return to; +} + +SDL_bool +OS4_HasClipboardText(_THIS) +{ + /* This is silly but is there a better way to check? */ + char *to = OS4_GetClipboardText(_this); + + if (to) { + size_t len = SDL_strlen(to); + + SDL_free(to); + + if (len > 0) { + return SDL_TRUE; + } + } + + return SDL_FALSE; +} + +void +OS4_InitKeyboard(_THIS) +{ + OS4_UpdateKeymap(_this); + + //SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); + SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Amiga"); + SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Amiga"); + SDL_SetScancodeName(SDL_SCANCODE_LCTRL, "Control"); +} + +void +OS4_QuitKeyboard(_THIS) +{ +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4keyboard.h b/src/video/amigaos4/SDL_os4keyboard.h new file mode 100644 index 0000000000000..a7401f555d5e7 --- /dev/null +++ b/src/video/amigaos4/SDL_os4keyboard.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4keyboard_h +#define _SDL_os4keyboard_h + +extern int OS4_SetClipboardText(_THIS, const char *text); +extern char * OS4_GetClipboardText(_THIS); +extern SDL_bool OS4_HasClipboardText(_THIS); + +extern void OS4_InitKeyboard(_THIS); +extern void OS4_QuitKeyboard(_THIS); + +#endif /* _SDL_os4keyboard_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4library.c b/src/video/amigaos4/SDL_os4library.c new file mode 100644 index 0000000000000..4d13f9d21b51f --- /dev/null +++ b/src/video/amigaos4/SDL_os4library.c @@ -0,0 +1,118 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include "SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include + +// These symbols are required when libSDL2.so is loaded manually using elf.library (RebelSDL). +struct ExecIFace* IExec; +struct Interface* INewlib; + +static struct Library* NewlibBase = NULL; + +static BOOL newlibOpened = FALSE; + +void _OS4_INIT(void) __attribute__((constructor)); +void _OS4_EXIT(void) __attribute__((destructor)); + +void _OS4_INIT(void) +{ + if (IExec) { + dprintf("IExec %p\n", IExec); + } else { + IExec = ((struct ExecIFace *)((*(struct ExecBase **)4)->MainInterface)); + } + + if (INewlib) { + dprintf("INewlib %p\n", INewlib); + } else { + NewlibBase = OS4_OpenLibrary("newlib.library", 53); + + if (NewlibBase) { + INewlib = OS4_GetInterface(NewlibBase); + newlibOpened = INewlib != NULL; + } + } + + dprintf("IExec %p, INewlib %p\n", IExec, INewlib); +} + +void _OS4_EXIT(void) +{ + if (newlibOpened && INewlib) { + OS4_DropInterface(&INewlib); + } + + if (NewlibBase) { + OS4_CloseLibrary(&NewlibBase); + } +} + +struct Library * +OS4_OpenLibrary(STRPTR name, ULONG version) +{ + struct Library* lib = IExec->OpenLibrary(name, version); + + dprintf("Opening '%s' version %u %s (address %p)\n", + name, version, lib ? "succeeded" : "FAILED", lib); + + return lib; +} + +struct Interface * +OS4_GetInterface(struct Library * lib) +{ + struct Interface* interface = IExec->GetInterface(lib, "main", 1, NULL); + + dprintf("Getting interface for libbase %p %s (address %p)\n", + lib, interface ? "succeeded" : "FAILED", interface); + + return interface; +} + +void +OS4_DropInterface(struct Interface ** interface) +{ + if (interface && *interface) { + dprintf("Dropping interface %p\n", *interface); + IExec->DropInterface(*interface); + *interface = NULL; + } +} + +void +OS4_CloseLibrary(struct Library ** library) +{ + if (library && *library) { + dprintf("Closing library %p\n", *library); + IExec->CloseLibrary(*library); + *library = NULL; + } +} + +#endif diff --git a/src/video/amigaos4/SDL_os4library.h b/src/video/amigaos4/SDL_os4library.h new file mode 100644 index 0000000000000..6d32a0637c908 --- /dev/null +++ b/src/video/amigaos4/SDL_os4library.h @@ -0,0 +1,38 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4library_h +#define _SDL_os4library_h + +#include + +// A couple of helper functions for dealing with AmigaOS libraries + +extern struct Library * OS4_OpenLibrary(STRPTR name, ULONG version); + +extern struct Interface * OS4_GetInterface(struct Library * lib); + +extern void OS4_DropInterface(struct Interface ** interface); + +extern void OS4_CloseLibrary(struct Library ** library); + +#endif diff --git a/src/video/amigaos4/SDL_os4messagebox.c b/src/video/amigaos4/SDL_os4messagebox.c new file mode 100644 index 0000000000000..409bc6bf56eb9 --- /dev/null +++ b/src/video/amigaos4/SDL_os4messagebox.c @@ -0,0 +1,161 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include + +#include "SDL_messagebox.h" +#include "SDL_os4messagebox.h" +#include "SDL_os4window.h" +#include "SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#define BUTTON_BUF_SIZE 1024 + +static struct Library *MB_IntuitionBase = NULL; +static struct IntuitionIFace *MB_IIntuition = NULL; + +/* Message box can be popped up without video initialization, +so let's fetch Intuition interface */ + +static BOOL +OS4_OpenIntuition() +{ + dprintf("Called\n"); + + MB_IntuitionBase = OS4_OpenLibrary("intuition.library", 51); + + if (MB_IntuitionBase) { + MB_IIntuition = (struct IntuitionIFace *) OS4_GetInterface(MB_IntuitionBase); + + if (MB_IIntuition) { + return TRUE; + } + } + + return FALSE; +} + +static void +OS4_CloseIntuition() +{ + dprintf("Called\n"); + + OS4_DropInterface((void *) &MB_IIntuition); + OS4_CloseLibrary(&MB_IntuitionBase); +} + +static char * +OS4_MakeButtonString(const SDL_MessageBoxData * messageboxdata) +{ + char *buttonBuffer = SDL_malloc(BUTTON_BUF_SIZE); + + if (buttonBuffer) { + int b; + + SDL_memset(buttonBuffer, 0, BUTTON_BUF_SIZE); + + /* Generate "Button 1|Button2... "*/ + for (b = 0; b < messageboxdata->numbuttons; b++) { + strncat(buttonBuffer, messageboxdata->buttons[b].text, BUTTON_BUF_SIZE - strlen(buttonBuffer) - 1); + + if (b != (messageboxdata->numbuttons - 1)) { + strncat(buttonBuffer, "|", BUTTON_BUF_SIZE - strlen(buttonBuffer) - 1); + } + } + + dprintf("String '%s'\n", buttonBuffer); + } + + return buttonBuffer; +} + +static struct Window * +OS4_GetWindow(const SDL_MessageBoxData * messageboxdata) +{ + struct Window * syswin = NULL; + + if (messageboxdata->window) { + SDL_WindowData *data = messageboxdata->window->driverdata; + syswin = data->syswin; + } + + return syswin; +} + +int +OS4_ShowMessageBox(const SDL_MessageBoxData * messageboxdata, int * buttonid) +{ + int result = -1; + + if (OS4_OpenIntuition()) { + + char *buttonString; + + if ((buttonString = OS4_MakeButtonString(messageboxdata))) { + + struct EasyStruct es = { + sizeof(struct EasyStruct), + 0, // Flags + messageboxdata->title, + messageboxdata->message, + buttonString, + NULL, // Screen + NULL // TagList + }; + + const int LAST_BUTTON = messageboxdata->numbuttons; + + /* Amiga button order is 1, 2, ..., N, 0! */ + int amigaButton = MB_IIntuition->EasyRequest(OS4_GetWindow(messageboxdata), &es, 0, NULL); + + dprintf("Button %d chosen\n", amigaButton); + + if (amigaButton >= 0 && amigaButton < LAST_BUTTON) { + if (amigaButton == 0) { + /* Last */ + *buttonid = messageboxdata->buttons[LAST_BUTTON - 1].buttonid; + } else { + *buttonid = messageboxdata->buttons[amigaButton - 1].buttonid; + } + + dprintf("Mapped button %d\n", *buttonid); + } + + SDL_free(buttonString); + result = 0; + } + } else { + dprintf("Failed to open IIntuition\n"); + } + + OS4_CloseIntuition(); + + return result; +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4messagebox.h b/src/video/amigaos4/SDL_os4messagebox.h new file mode 100644 index 0000000000000..8275bffd61b16 --- /dev/null +++ b/src/video/amigaos4/SDL_os4messagebox.h @@ -0,0 +1,32 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4messagebox_h +#define _SDL_os4messagebox_h + +struct SDL_MessageBoxData; + +extern int OS4_ShowMessageBox(const SDL_MessageBoxData * messageboxdata, int * buttonid); + +#endif /* _SDL_os4messagebox_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4modes.c b/src/video/amigaos4/SDL_os4modes.c new file mode 100644 index 0000000000000..293de5f698171 --- /dev/null +++ b/src/video/amigaos4/SDL_os4modes.c @@ -0,0 +1,309 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include "SDL_os4video.h" +#include "SDL_os4modes.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static SDL_bool +OS4_GetDisplayMode(_THIS, ULONG id, SDL_DisplayMode * mode) +{ + SDL_DisplayModeData *data; + APTR handle; + struct DimensionInfo diminfo; + struct DisplayInfo dispinfo; + + handle = IGraphics->FindDisplayInfo(id); + if (!handle) { + return SDL_FALSE; + } + + if (!IGraphics->GetDisplayInfoData(handle, (UBYTE *)&diminfo, sizeof(diminfo), DTAG_DIMS, 0)) { + dprintf("Failed to get dim info\n"); + return SDL_FALSE; + } + + if (!IGraphics->GetDisplayInfoData(handle, (UBYTE *)&dispinfo, sizeof(dispinfo), DTAG_DISP, 0)) { + dprintf("Failed to get disp info\n"); + return SDL_FALSE; + } + + data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data)); + if (!data) { + return SDL_FALSE; + } + + SDL_zero(*mode); + data->modeid = id; + data->x = diminfo.Nominal.MinX; + data->y = diminfo.Nominal.MinY; + mode->w = diminfo.Nominal.MaxX - diminfo.Nominal.MinX + 1; + mode->h = diminfo.Nominal.MaxY - diminfo.Nominal.MinY + 1; + mode->refresh_rate = 60; // grab DTAG_MNTR? + mode->format = SDL_PIXELFORMAT_UNKNOWN; + + // We are only interested in RTG modes + if (dispinfo.PropertyFlags & DIPF_IS_RTG) { + + dprintf("RTG mode %d: w=%d, h=%d, bits=%d\n", id, mode->w, mode->h, diminfo.MaxDepth); + + switch (diminfo.MaxDepth) { + case 32: + mode->format = SDL_PIXELFORMAT_ARGB8888; + break; + case 24: + mode->format = SDL_PIXELFORMAT_RGB888; + break; + case 16: + mode->format = SDL_PIXELFORMAT_RGB565; + break; + case 15: + mode->format = SDL_PIXELFORMAT_RGB555; + break; + case 8: + mode->format = SDL_PIXELFORMAT_INDEX8; + break; + } + } + + mode->driverdata = data; + + return SDL_TRUE; +} + +static SDL_bool +OS4_LockPubScreen(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + dprintf("Locking public screen\n"); + + data->publicScreen = IIntuition->LockPubScreen(NULL); + + if (data->publicScreen) { + dprintf("Public screen %p locked\n", data->publicScreen); + return SDL_TRUE; + } else { + dprintf("Failed to lock Workbench screen\n"); + return SDL_FALSE; + } +} + +static void +OS4_UnlockPubScreen(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + if (data->publicScreen) { + dprintf("Unlocking public screen %p\n", data->publicScreen); + + IIntuition->UnlockPubScreen(NULL, data->publicScreen); + data->publicScreen = NULL; + } +} + +int +OS4_InitModes(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + SDL_VideoDisplay display; + SDL_DisplayMode current_mode; + SDL_DisplayData *displaydata; + ULONG modeid; + + dprintf("Called\n"); + + displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata)); + if (!displaydata) { + return SDL_OutOfMemory(); + } + + if (!OS4_LockPubScreen(_this)) { + SDL_free(displaydata); + return SDL_SetError("No displays available"); + } + + IIntuition->GetScreenAttrs(data->publicScreen, SA_DisplayID, &modeid, TAG_DONE); + if (!OS4_GetDisplayMode(_this, modeid, ¤t_mode)) { + dprintf("Failed to get display mode for %d\n", modeid); + SDL_free(displaydata); + return SDL_SetError("Couldn't get display mode\n"); + } + + /* OS4 has no multi-monitor support */ + SDL_zero(display); + display.desktop_mode = current_mode; + display.current_mode = current_mode; + display.driverdata = displaydata; + displaydata->screen = NULL; + + SDL_AddVideoDisplay(&display, SDL_FALSE); + + return 0; +} + +int +OS4_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect) +{ + SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata; + + rect->x = data->x; + rect->y = data->y; + rect->w = display->current_mode.w; + rect->h = display->current_mode.h; + + dprintf("x=%d, y=%d, w=%d, h=%d\n", rect->x, rect->y, rect->w, rect->h); + + return 0; +} + +void +OS4_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + SDL_DisplayMode mode; + ULONG id = INVALID_ID; + + dprintf("Called\n"); + + while ((id = IGraphics->NextDisplayInfo(id)) != INVALID_ID) { + + if (OS4_GetDisplayMode(_this, id, &mode)) { + if (mode.format != SDL_PIXELFORMAT_UNKNOWN) { + if (!SDL_AddDisplayMode(display, &mode)) { + SDL_free(mode.driverdata); + } + } else { + SDL_free(mode.driverdata); + } + } else { + dprintf("Failed to get display mode for %d\n", id); + } + } +} + +void +OS4_CloseScreen(_THIS, struct Screen * screen) +{ + if (screen) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + if (screen != data->publicScreen) { + dprintf("Closing screen %p\n", screen); + + if (IIntuition->CloseScreen(screen) == FALSE) { + dprintf("Screen has open window(s), cannot close\n"); + } else { + dprintf("Screen closed successfully\n"); + } + } else { + dprintf("Public screen, not closing\n"); + } + + } else { + dprintf("NULL pointer\n"); + } +} + +int +OS4_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + SDL_VideoData *driverdata = (SDL_VideoData *) _this->driverdata; + SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; + SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata; + ULONG openError = 0; + int bpp = SDL_BITSPERPIXEL(mode->format); + + if (SDL_memcmp(mode, &display->desktop_mode, sizeof(SDL_DisplayMode)) == 0) { + // Don't create another "Workbench" + dprintf("Desktop mode passed\n"); + + //TODO: should we check the current display ID and reopen the screen when needed? + return 0; + } + + displaydata->screen = IIntuition->OpenScreenTags(NULL, + SA_Width, mode->w, + SA_Height, mode->h, + SA_Depth, bpp, + SA_DisplayID, data->modeid, + SA_Quiet, TRUE, + SA_Title, driverdata->appName, + SA_ShowTitle, FALSE, + SA_ErrorCode, &openError, + SA_LikeWorkbench, TRUE, + SA_Compositing, FALSE, + TAG_DONE); + + dprintf("Opened screen id %d: %d*%d*%d (address %p)\n", + data->modeid, mode->w, mode->h, bpp, displaydata->screen); + + if (!displaydata->screen) { + switch (openError) { + case OSERR_NOMONITOR: + SDL_SetError("Monitor for display mode not available"); + break; + case OSERR_NOCHIPS: + SDL_SetError("Newer custom chips required"); + break; + case OSERR_NOMEM: + case OSERR_NOCHIPMEM: + SDL_OutOfMemory(); + break; + case OSERR_PUBNOTUNIQUE: + SDL_SetError("Public screen name not unique"); + break; + case OSERR_UNKNOWNMODE: + case OSERR_TOODEEP: + SDL_SetError("Unknown display mode"); + break; + case OSERR_ATTACHFAIL: + SDL_SetError("Attachment failed"); + break; + default: + SDL_SetError("OpenScreen failed"); + break; + } + return -1; + } + + // Paint it black (it helps in cases where window doesn't fill the screen) + // ...do we need a backfill hook? + IGraphics->RectFillColor(&displaydata->screen->RastPort, 0, 0, mode->w - 1, mode->h - 1, 0xFF000000); + + return 0; +} + +void +OS4_QuitModes(_THIS) +{ + dprintf("Called\n"); + + OS4_UnlockPubScreen(_this); +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4modes.h b/src/video/amigaos4/SDL_os4modes.h new file mode 100644 index 0000000000000..07547abefc0dd --- /dev/null +++ b/src/video/amigaos4/SDL_os4modes.h @@ -0,0 +1,48 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4modes_h +#define _SDL_os4modes_h + +typedef struct +{ + struct Screen * screen; +} SDL_DisplayData; + +typedef struct +{ + ULONG modeid; + LONG x; + LONG y; +} SDL_DisplayModeData; + +extern int OS4_InitModes(_THIS); +extern int OS4_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect); +extern void OS4_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +extern int OS4_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +extern void OS4_QuitModes(_THIS); + +extern void OS4_CloseScreen(_THIS, struct Screen *screen); + +#endif /* _SDL_os4modes_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4mouse.c b/src/video/amigaos4/SDL_os4mouse.c new file mode 100644 index 0000000000000..691f13b5bae66 --- /dev/null +++ b/src/video/amigaos4/SDL_os4mouse.c @@ -0,0 +1,550 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include + +#include "SDL_os4mouse.h" +#include "SDL_os4video.h" +#include "SDL_os4window.h" + +#include "SDL_hints.h" +#include "../../events/SDL_mouse_c.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#include + +static SDL_Cursor *hidden; + +typedef struct SDL_CursorData { + int hot_x; + int hot_y; + ULONG type; + Object *object; + Uint32 *imageData; +} SDL_CursorData; + +static UWORD fallbackPointerData[2 * 16] = { 0 }; + +static struct BitMap fallbackPointerBitMap = { 2, 16, 0, 2, 0, + { (PLANEPTR)fallbackPointerData, (PLANEPTR)(fallbackPointerData + 16) } }; + + +OS4_GlobalMouseState globalMouseState; + +static Uint32 +OS4_GetDoubleClickTimeInMillis(_THIS) +{ + struct Preferences preferences; + Uint32 interval; + + IIntuition->GetPrefs(&preferences, sizeof(preferences)); + + interval = preferences.DoubleClick.Seconds * 1000 + + preferences.DoubleClick.Microseconds / 1000; + + dprintf("Doubleclick time %d ms\n", interval); + + return interval; +} + +static SDL_Cursor* +OS4_CreateCursorInternal() +{ + SDL_Cursor *cursor = SDL_calloc(1, sizeof(SDL_Cursor)); + + //dprintf("Called\n"); + + if (cursor) { + + SDL_CursorData *data = SDL_calloc(1, sizeof(SDL_CursorData)); + + if (data) { + cursor->driverdata = data; + } else { + dprintf("Failed to create cursor data\n"); + } + + } else { + dprintf("Failed to create cursor\n"); + } + + return cursor; + +} + +static SDL_Cursor* +OS4_CreateDefaultCursor() +{ + SDL_Cursor *cursor = OS4_CreateCursorInternal(); + + dprintf("%p\n", cursor); + + if (cursor && cursor->driverdata) { + SDL_CursorData *data = cursor->driverdata; + + data->type = POINTERTYPE_NORMAL; + } + + return cursor; +} + +static Uint32* +OS4_CopyImageData(SDL_Surface * surface) +{ + const size_t bytesPerRow = surface->w * sizeof(Uint32); + Uint32* buffer = SDL_malloc(bytesPerRow * surface->h); + + dprintf("Copying cursor data %d*%d from surface %p to buffer %p\n", + surface->w, surface->h, surface, buffer); + + if (buffer) { + + if (SDL_MUSTLOCK(surface)) { + SDL_LockSurface(surface); + } + + Uint8* source = surface->pixels; + Uint32* destination = buffer; + int y; + + for (y = 0; y < surface->h; y++) { + SDL_memcpy(destination, source, bytesPerRow); + destination += surface->w; + source += surface->pitch; + } + + if (SDL_MUSTLOCK(surface)) { + SDL_UnlockSurface(surface); + } + } else { + dprintf("Failed to allocate memory\n"); + } + + return buffer; +} + +static SDL_Cursor* +OS4_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) +{ + SDL_Cursor *cursor = OS4_CreateCursorInternal(); + + dprintf("Surface %p, cursor %p, hot_x %d, hot_y %d\n", surface, cursor, hot_x, hot_y); + + if (cursor && cursor->driverdata) { + + if (surface->w > 64) { + dprintf("Invalid width %d\n", surface->w); + } else if (surface->h > 64) { + dprintf("Invalid height %d\n", surface->h); + } else { + _THIS = SDL_GetVideoDevice(); + + Uint32* buffer = OS4_CopyImageData(surface); + + /* We need to pass some compatibility parameters + even though we are going to use just ARGB pointer */ + + Object *object = IIntuition->NewObject( + NULL, + POINTERCLASS, + POINTERA_BitMap, &fallbackPointerBitMap, + POINTERA_XOffset, hot_x, + POINTERA_YOffset, hot_y, + POINTERA_WordWidth, 1, + POINTERA_XResolution, POINTERXRESN_SCREENRES, + POINTERA_YResolution, POINTERYRESN_SCREENRES, + POINTERA_ImageData, buffer, + POINTERA_Width, surface->w, + POINTERA_Height, surface->h, + TAG_DONE); + + if (object) { + SDL_CursorData *data = cursor->driverdata; + data->object = object; + data->imageData = buffer; + } else { + dprintf("Failed to create pointer object\n"); + } + } + } + + return cursor; +} + +static SDL_Cursor* +OS4_CreateHiddenCursor() +{ + dprintf("Called\n"); + + /* Create invisible 1*1 cursor because system version (POINTERTYPE_NONE) has a shadow */ + + SDL_Cursor *cursor = NULL; + SDL_Surface *surface = SDL_CreateRGBSurface(0, 1, 1, 32, + 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + + if (surface) { + SDL_FillRect(surface, NULL, 0x0); + + cursor = OS4_CreateCursor(surface, 0, 0); + + SDL_FreeSurface(surface); + } + + return cursor; +} + + +static ULONG +OS4_MapCursorIdToNative(SDL_SystemCursor id) +{ + switch (id) { + case SDL_SYSTEM_CURSOR_ARROW: return POINTERTYPE_NORMAL; + //case SDL_SYSTEM_CURSOR_IBEAM: return POINTERTYPE_SELECT; 54.21 + case SDL_SYSTEM_CURSOR_WAITARROW: + case SDL_SYSTEM_CURSOR_WAIT: return POINTERTYPE_BUSY; + case SDL_SYSTEM_CURSOR_CROSSHAIR: return POINTERTYPE_CROSS; + case SDL_SYSTEM_CURSOR_SIZENWSE: return POINTERTYPE_NORTHWESTSOUTHEASTRESIZE; + case SDL_SYSTEM_CURSOR_SIZENESW: return POINTERTYPE_NORTHEASTSOUTHWESTRESIZE; + case SDL_SYSTEM_CURSOR_SIZEWE: return POINTERTYPE_EASTWESTRESIZE; + case SDL_SYSTEM_CURSOR_SIZENS: return POINTERTYPE_NORTHSOUTHRESIZE; + case SDL_SYSTEM_CURSOR_NO: return POINTERTYPE_NOTALLOWED; + case SDL_SYSTEM_CURSOR_HAND: return POINTERTYPE_HAND; + // + case SDL_SYSTEM_CURSOR_SIZEALL: + default: + dprintf("Unknown mapping from type %d\n", id); + return POINTERTYPE_NORMAL; + } +} + +static SDL_Cursor* +OS4_CreateSystemCursor(SDL_SystemCursor id) +{ + SDL_Cursor *cursor = OS4_CreateCursorInternal(); + + //dprintf("Called %d\n", id); + + if (cursor && cursor->driverdata) { + SDL_CursorData *data = cursor->driverdata; + + data->type = OS4_MapCursorIdToNative(id); + } + + return cursor; +} + +static void +OS4_SetPointerForEachWindow(ULONG type, Object * object) +{ + SDL_Window *sdlwin; + + _THIS = SDL_GetVideoDevice(); + + for (sdlwin = _this->windows; sdlwin; sdlwin = sdlwin->next) { + + SDL_WindowData *data = sdlwin->driverdata; + + if (data->syswin) { + + if (object || type) { + dprintf("Setting pointer object %p (type %d) for window %p\n", object, type, data->syswin); + } + + if (object) { + IIntuition->SetWindowPointer( + data->syswin, + WA_Pointer, object, + TAG_DONE); + } else { + IIntuition->SetWindowPointer( + data->syswin, + WA_PointerType, type, + TAG_DONE); + } + } + } +} + +static int +OS4_ShowCursor(SDL_Cursor * cursor) +{ + ULONG type = POINTERTYPE_NORMAL; + Object *object = NULL; + + if (cursor) { + SDL_CursorData *data = cursor->driverdata; + + //dprintf("Called %p %p\n", cursor, data); + + if (data) { + type = data->type; + object = data->object; + } else { + dprintf("No cursor data\n"); + return -1; + } + } else { + dprintf("Hiding cursor\n"); + + type = POINTERTYPE_NONE; + + if (hidden) { + SDL_CursorData *data = hidden->driverdata; + + if (data) { + object = data->object; + } + } + } + + OS4_SetPointerForEachWindow(type, object); + + return 0; +} + +static void +OS4_FreeCursor(SDL_Cursor * cursor) +{ + SDL_CursorData *data = cursor->driverdata; + + dprintf("Called %p\n", cursor); + + if (data) { + if (data->object) { + _THIS = SDL_GetVideoDevice(); + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse->cur_cursor == cursor) { + dprintf("Reset to POINTERTYPE_NONE before object disposal\n"); + OS4_SetPointerForEachWindow(POINTERTYPE_NONE, NULL); + } + + IIntuition->DisposeObject(data->object); + data->object = NULL; + } + + if (data->imageData) { + SDL_free(data->imageData); + data->imageData = NULL; + } + + SDL_free(data); + cursor->driverdata = NULL; + } +} + +void +OS4_RefreshCursorState(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + if (mouse) { + dprintf("Mouse shown %d\n", mouse->cursor_shown); + // Force cursor redraw + SDL_SetCursor(NULL); + } +} + +static int +OS4_WarpMouseInternal(struct Screen *screen, int x, int y) +{ + SDL_VideoDevice *device = SDL_GetVideoDevice(); + SDL_VideoData *videoData = device->driverdata; + int result = -1; + + if (videoData->inputReq != NULL) { + struct InputEvent *fakeEvent; + + /* We move the Workbench pointer by stuffing mouse + * movement events in input.device's queue. + * + * This in turn will cause mouse movement events to be + * sent back to us + */ + + fakeEvent = (struct InputEvent *)OS4_SaveAllocPooled( + device, sizeof(struct InputEvent) + sizeof(struct IEPointerPixel)); + + if (fakeEvent) { + struct IEPointerPixel *neoPix = (struct IEPointerPixel *) (fakeEvent + 1); + + neoPix->iepp_Screen = screen ? screen : videoData->publicScreen; + neoPix->iepp_Position.Y = y; + neoPix->iepp_Position.X = x; + + fakeEvent->ie_EventAddress = (APTR)neoPix; + fakeEvent->ie_NextEvent = NULL; + fakeEvent->ie_Class = IECLASS_NEWPOINTERPOS; + fakeEvent->ie_SubClass = IESUBCLASS_PIXEL; + fakeEvent->ie_Code = IECODE_NOBUTTON; + fakeEvent->ie_Qualifier = 0; + + videoData->inputReq->io_Data = (APTR)fakeEvent; + videoData->inputReq->io_Length = sizeof(struct InputEvent); + videoData->inputReq->io_Command = IND_WRITEEVENT; + + dprintf("Sending input event\n"); + + IExec->DoIO((struct IORequest *)videoData->inputReq); + + OS4_SaveFreePooled(device, (void *)fakeEvent, + sizeof(struct InputEvent) + sizeof(struct IEPointerPixel)); + + result = 0; + } + } + + return result; +} + +static int +OS4_WarpMouseGlobal(int x, int y) +{ + dprintf("Warping mouse to %d, %d\n", x, y); + + return OS4_WarpMouseInternal(NULL, x, y); +} + +static void +OS4_WarpMouse(SDL_Window * window, int x, int y) +{ + SDL_WindowData *winData = window->driverdata; + struct Window *syswin = winData->syswin; + + BOOL warpHostPointer; + + dprintf("Warping mouse to %d, %d\n", x, y); + + /* If the host mouse pointer is outside of the SDL window or the SDL + * window is inactive then we just need to warp SDL's notion of where + * the pointer position is - we don't need to move the Workbench + * pointer. In the former case, we don't pass mass movements on to + * to the app anyway and in the latter case we don't receive mouse + * movements events anyway. + */ + //warpHostPointer = (hidden->pointerState == pointer_inside_window) && !hidden->isMouseRelative + // && hidden->windowActive; + + // TODO: "inside window" logic needed/wanted? + warpHostPointer = !SDL_GetRelativeMouseMode() && (window == SDL_GetMouseFocus()); + + if (warpHostPointer) { + + struct Screen *screen = (window->flags & SDL_WINDOW_FULLSCREEN) ? + syswin->WScreen : NULL; + + OS4_WarpMouseInternal(screen, + x + syswin->BorderLeft + syswin->LeftEdge, + y + syswin->BorderTop + syswin->TopEdge); + + } else { + /* Just warp SDL's notion of the pointer position */ + SDL_SendMouseMotion(window, 0, SDL_GetRelativeMouseMode(), x, y); + } +} + +static int +OS4_SetRelativeMouseMode(SDL_bool enabled) +{ + return 0; +} + +static Uint32 +OS4_GetGlobalMouseState(int * x, int * y) +{ + uint32 buttons = 0; + + if (x) { + *x = globalMouseState.x; + } + + if (y) { + *y = globalMouseState.y; + } + + //dprintf("%d, %d\n", *x, *y); + + if (globalMouseState.buttonPressed[SDL_BUTTON_LEFT]) { + buttons |= SDL_BUTTON_LMASK; + } + + if (globalMouseState.buttonPressed[SDL_BUTTON_MIDDLE]) { + buttons |= SDL_BUTTON_MMASK; + } + + if (globalMouseState.buttonPressed[SDL_BUTTON_RIGHT]) { + buttons |= SDL_BUTTON_RMASK; + } + + return buttons; +} + +void +OS4_InitMouse(_THIS) +{ + //SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + SDL_Mouse *mouse = SDL_GetMouse(); + char buffer[16]; + + mouse->CreateCursor = OS4_CreateCursor; + mouse->CreateSystemCursor = OS4_CreateSystemCursor; + mouse->ShowCursor = OS4_ShowCursor; + mouse->FreeCursor = OS4_FreeCursor; + mouse->WarpMouse = OS4_WarpMouse; + mouse->WarpMouseGlobal = OS4_WarpMouseGlobal; + mouse->SetRelativeMouseMode = OS4_SetRelativeMouseMode; + //mouse->CaptureMouse = OS4_CaptureMouse; + mouse->GetGlobalMouseState = OS4_GetGlobalMouseState; + + SDL_SetDefaultCursor( OS4_CreateDefaultCursor() ); + + hidden = OS4_CreateHiddenCursor(); + + SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME, + SDL_uitoa(OS4_GetDoubleClickTimeInMillis(_this), buffer, 10)); +} + +void +OS4_QuitMouse(_THIS) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse->def_cursor) { + OS4_FreeCursor(mouse->def_cursor); + mouse->def_cursor = NULL; + } + + if (hidden) { + OS4_FreeCursor(hidden); + hidden = NULL; + } + + mouse->cur_cursor = NULL; +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4mouse.h b/src/video/amigaos4/SDL_os4mouse.h new file mode 100644 index 0000000000000..882cefff92593 --- /dev/null +++ b/src/video/amigaos4/SDL_os4mouse.h @@ -0,0 +1,42 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" +#include "SDL_os4video.h" +#include "SDL_mouse.h" + +#ifndef _SDL_os4mouse_h +#define _SDL_os4mouse_h + +typedef struct OS4_GlobalMouseState +{ + int x; + int y; + int buttonPressed[SDL_BUTTON_RIGHT+1]; +} OS4_GlobalMouseState; + +extern void OS4_RefreshCursorState(void); + +extern void OS4_InitMouse(_THIS); +extern void OS4_QuitMouse(_THIS); + +#endif /* _SDL_os4mouse_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4opengl.c b/src/video/amigaos4/SDL_os4opengl.c new file mode 100644 index 0000000000000..13b96b2bfd88f --- /dev/null +++ b/src/video/amigaos4/SDL_os4opengl.c @@ -0,0 +1,464 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include "SDL_os4video.h" +#include "SDL_os4window.h" +#include "SDL_os4library.h" +#include "SDL_os4opengl.h" + +#include + +#include +//#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +struct Library *MiniGLBase; +struct MiniGLIFace *IMiniGL; + +/* The client program needs access to this context pointer + * to be able to make GL calls. This presents no problems when + * it is statically linked against libSDL, but when linked + * against a shared library version this will require some + * trickery. + */ +DECLSPEC struct GLContextIFace *mini_CurrentContext = 0; + +void *AmiGetGLProc(const char *proc); + +static void +OS4_GL_LogLibraryError() +{ + dprintf("No MiniGL library available\n"); + SDL_SetError("No MiniGL library available"); +} + +int +OS4_GL_LoadLibrary(_THIS, const char * path) +{ + dprintf("Called %d\n", _this->gl_config.driver_loaded); + + if (!MiniGLBase) { + MiniGLBase = OS4_OpenLibrary("minigl.library", 2); + + if (!MiniGLBase) { + dprintf("Failed to open minigl.library\n"); + SDL_SetError("Failed to open minigl.library"); + return -1; + } + } + + if (!IMiniGL) { + IMiniGL = (struct MiniGLIFace *) OS4_GetInterface(MiniGLBase); + + if (!IMiniGL) { + dprintf("Failed to open MiniGL interace\n"); + SDL_SetError("Failed to open MiniGL interface"); + return -1; + } + + dprintf("MiniGL library opened\n"); + } + + return 0; +} + +void * +OS4_GL_GetProcAddress(_THIS, const char * proc) +{ + void *func = NULL; + + dprintf("Called for '%s' (current context %p)\n", proc, mini_CurrentContext); + + if (IMiniGL && mini_CurrentContext) { + func = AmiGetGLProc(proc); + } + + if (func == NULL) { + dprintf("Failed to load '%s'\n", proc); + } + + return func; +} + +void +OS4_GL_UnloadLibrary(_THIS) +{ + dprintf("Called %d\n", _this->gl_config.driver_loaded); + + OS4_DropInterface((void *) &IMiniGL); + OS4_CloseLibrary(&MiniGLBase); +} + +SDL_bool +OS4_GL_AllocateBuffers(_THIS, int width, int height, int depth, SDL_WindowData * data) +{ + dprintf("Allocate double buffer bitmaps %d*%d*%d\n", width, height, depth); + + if (data->glFrontBuffer || data->glBackBuffer) { + dprintf("Old front buffer pointer %p, back buffer pointer %p\n", + data->glFrontBuffer, data->glBackBuffer); + + OS4_GL_FreeBuffers(_this, data); + } + + if (!(data->glFrontBuffer = IGraphics->AllocBitMapTags( + width, + height, + depth, + BMATags_Displayable, TRUE, + BMATags_Friend, data->syswin->RPort->BitMap, + TAG_DONE))) { + + dprintf("Failed to allocate front buffer\n"); + return SDL_FALSE; + } + + if (!(data->glBackBuffer = IGraphics->AllocBitMapTags( + width, + height, + depth, + BMATags_Displayable, TRUE, + BMATags_Friend, data->syswin->RPort->BitMap, + TAG_DONE))) { + + dprintf("Failed to allocate back buffer\n"); + + IGraphics->FreeBitMap(data->glFrontBuffer); + data->glFrontBuffer = NULL; + + return SDL_FALSE; + } + + uint32 srcFmt = IGraphics->GetBitMapAttr(data->glBackBuffer, BMA_PIXELFORMAT); + uint32 src2Fmt = IGraphics->GetBitMapAttr(data->glFrontBuffer, BMA_PIXELFORMAT); + uint32 dstFmt = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_PIXELFORMAT); + + dprintf("SRC FMT %u, SRC2 FMT %u, DST FMT %u\n", srcFmt, src2Fmt, dstFmt); + + return SDL_TRUE; +} + +void +OS4_GL_FreeBuffers(_THIS, SDL_WindowData * data) +{ + dprintf("Called\n"); + + if (data->glFrontBuffer) { + IGraphics->FreeBitMap(data->glFrontBuffer); + data->glFrontBuffer = NULL; + } + + if (data->glBackBuffer) { + IGraphics->FreeBitMap(data->glBackBuffer); + data->glBackBuffer = NULL; + } +} + +SDL_GLContext +OS4_GL_CreateContext(_THIS, SDL_Window * window) +{ + dprintf("Called\n"); + + if (IMiniGL) { + + int width, height; + uint32 depth; + + SDL_WindowData * data = window->driverdata; + + OS4_GetWindowActiveSize(window, &width, &height); + + if (data->glContext) { + struct GLContextIFace *IGL = (struct GLContextIFace *)data->glContext; + + dprintf("Old context %p found, deleting\n", data->glContext); + + IGL->DeleteContext(); + + data->glContext = NULL; + } + + depth = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_BITSPERPIXEL); + + if (!OS4_GL_AllocateBuffers(_this, width, height, depth, data)) { + SDL_SetError("Failed to allocate MiniGL buffers"); + return NULL; + } + + data->glContext = IMiniGL->CreateContextTags( + MGLCC_PrivateBuffers, 2, + MGLCC_FrontBuffer, data->glFrontBuffer, + MGLCC_BackBuffer, data->glBackBuffer, + MGLCC_Buffers, 2, + MGLCC_PixelDepth, depth, + MGLCC_StencilBuffer, TRUE, + MGLCC_VertexBufferSize, 1 << 17, + TAG_DONE); + + if (data->glContext) { + + dprintf("MiniGL context %p created for window '%s'\n", + data->glContext, window->title); + + ((struct GLContextIFace *)data->glContext)->GLViewport(0, 0, width, height); + mglMakeCurrent(data->glContext); + mglLockMode(MGL_LOCK_SMART); + + return data->glContext; + + } else { + dprintf("Failed to create MiniGL context for window '%s'\n", window->title); + + SDL_SetError("Failed to create MiniGL context"); + + OS4_GL_FreeBuffers(_this, data); + + return NULL; + } + + } else { + OS4_GL_LogLibraryError(); + return NULL; + } +} + +int +OS4_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) +{ + int result = -1; + + if (!window || !context) { + dprintf("Called (window %p, context %p)\n", window, context); + } + + if (IMiniGL) { + mglMakeCurrent(context); + result = 0; + } else { + OS4_GL_LogLibraryError(); + } + + return result; +} + +void +OS4_GL_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h) +{ + OS4_WaitForResize(_this, window, w, h); +} + +int +OS4_GL_SetSwapInterval(_THIS, int interval) +{ + SDL_VideoData *data = _this->driverdata; + + switch (interval) { + case 0: + case 1: + data->vsyncEnabled = interval ? TRUE : FALSE; + dprintf("VSYNC %d\n", interval); + return 0; + default: + dprintf("Unsupported interval %d\n", interval); + return -1; + } +} + +int +OS4_GL_GetSwapInterval(_THIS) +{ + //dprintf("Called\n"); + + SDL_VideoData *data = _this->driverdata; + + return data->vsyncEnabled ? 1 : 0; +} + +int +OS4_GL_SwapWindow(_THIS, SDL_Window * window) +{ + //dprintf("Called\n"); + + if (IMiniGL) { + + SDL_WindowData *data = window->driverdata; + + if (data->glContext) { + SDL_VideoData *videodata = _this->driverdata; + + struct BitMap *temp; + int w, h; + GLint buf; + + int32 blitRet; + + mglUnlockDisplay(); + + ((struct GLContextIFace *)data->glContext)->MGLWaitGL(); // TODO: still needed? + + OS4_GetWindowSize(_this, data->syswin, &w, &h); + + if (videodata->vsyncEnabled) { + IGraphics->WaitTOF(); + } + + glGetIntegerv(GL_DRAW_BUFFER, &buf); + + if (buf == GL_BACK || buf == GL_FRONT) { + struct BitMap *from = (buf == GL_BACK) ? data->glBackBuffer : data->glFrontBuffer; + + BOOL ret = IGraphics->BltBitMapRastPort(from, 0, 0, data->syswin->RPort, + data->syswin->BorderLeft, data->syswin->BorderTop, w, h, 0xC0); + + if (!ret) { + dprintf("BltBitMapRastPort() failed\n"); + } + } + + blitRet = IGraphics->BltBitMapTags(BLITA_Source, data->glBackBuffer, + BLITA_SrcType, BLITT_BITMAP, + BLITA_SrcX, 0, + BLITA_SrcY, 0, + BLITA_Dest, data->glFrontBuffer, + BLITA_DestType,BLITT_BITMAP, + BLITA_DestX, 0, + BLITA_DestY, 0, + BLITA_Width, w, + BLITA_Height, h, + BLITA_Minterm, 0xC0, + TAG_DONE); + + if (blitRet == -1) { + temp = data->glFrontBuffer; + data->glFrontBuffer = data->glBackBuffer; + data->glBackBuffer = temp; + + ((struct GLContextIFace *)data->glContext)->MGLUpdateContextTags( + MGLCC_FrontBuffer,data->glFrontBuffer, + MGLCC_BackBuffer, data->glBackBuffer, + TAG_DONE); + return 0; + } else { + dprintf("BltBitMapTags() returned %d\n", blitRet); + return -1; + } + } else { + dprintf("No MiniGL context\n"); + } + } else { + OS4_GL_LogLibraryError(); + } + + return -1; +} + +void +OS4_GL_DeleteContext(_THIS, SDL_GLContext context) +{ + dprintf("Called with context=%p\n", context); + + if (IMiniGL) { + + if (context) { + SDL_Window *sdlwin; + Uint32 deletions = 0; + + for (sdlwin = _this->windows; sdlwin; sdlwin = sdlwin->next) { + + SDL_WindowData *data = sdlwin->driverdata; + + if (data->glContext == context) { + struct GLContextIFace *IGL = context; + + dprintf("Found MiniGL context, clearing window binding\n"); + + IGL->DeleteContext(); + + data->glContext = NULL; + deletions++; + } + } + + if (deletions == 0) { + dprintf("MiniGL context doesn't seem to have window binding\n"); + } + } else { + dprintf("No context to delete\n"); + } + } else { + OS4_GL_LogLibraryError(); + } +} + +SDL_bool +OS4_GL_ResizeContext(_THIS, SDL_Window * window) +{ + if (IMiniGL) { + SDL_WindowData *data = window->driverdata; + + if (data) { + int width, height; + + uint32 depth = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_BITSPERPIXEL); + + OS4_GetWindowActiveSize(window, &width, &height); + + if (OS4_GL_AllocateBuffers(_this, width, height, depth, data)) { + + dprintf("Resizing MiniGL context to %d*%d\n", width, height); + + ((struct GLContextIFace *)data->glContext)->MGLUpdateContextTags( + MGLCC_FrontBuffer, data->glFrontBuffer, + MGLCC_BackBuffer, data->glBackBuffer, + TAG_DONE); + + ((struct GLContextIFace *)data->glContext)->GLViewport(0, 0, width, height); + + return SDL_TRUE; + + } else { + dprintf("Failed to re-allocate MiniGL buffers\n"); + //SDL_Quit(); + } + } else { + dprintf("Window data NULL\n"); + } + } else { + OS4_GL_LogLibraryError(); + } + + return SDL_FALSE; +} + +void +OS4_GL_UpdateWindowPointer(_THIS, SDL_Window * window) +{ + // Nothing to do for MiniGL +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4opengl.h b/src/video/amigaos4/SDL_os4opengl.h new file mode 100644 index 0000000000000..dae6a8e321821 --- /dev/null +++ b/src/video/amigaos4/SDL_os4opengl.h @@ -0,0 +1,47 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4opengl_h +#define _SDL_os4opengl_h + +#include "SDL_os4window.h" + +extern int OS4_GL_LoadLibrary(_THIS, const char *path); +extern void *OS4_GL_GetProcAddress(_THIS, const char *proc); +extern void OS4_GL_UnloadLibrary(_THIS); +extern SDL_GLContext OS4_GL_CreateContext(_THIS, SDL_Window * window); +extern int OS4_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +extern void OS4_GL_GetDrawableSize(_THIS, SDL_Window * window, int *w, int *h); +extern int OS4_GL_SetSwapInterval(_THIS, int interval); +extern int OS4_GL_GetSwapInterval(_THIS); +extern int OS4_GL_SwapWindow(_THIS, SDL_Window * window); +extern void OS4_GL_DeleteContext(_THIS, SDL_GLContext context); + +/* Non-SDL functions */ +extern SDL_bool OS4_GL_AllocateBuffers(_THIS, int width, int height, int depth, SDL_WindowData * data); +extern void OS4_GL_FreeBuffers(_THIS, SDL_WindowData * data); +extern SDL_bool OS4_GL_ResizeContext(_THIS, SDL_Window * window); +extern void OS4_GL_UpdateWindowPointer(_THIS, SDL_Window * window); + +#endif /* _SDL_os4opengl_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4opengles.c b/src/video/amigaos4/SDL_os4opengles.c new file mode 100644 index 0000000000000..59a9decb2e08b --- /dev/null +++ b/src/video/amigaos4/SDL_os4opengles.c @@ -0,0 +1,368 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#if SDL_VIDEO_OPENGL_ES2 + +#include "SDL_os4video.h" +#include "SDL_os4window.h" +#include "SDL_os4opengl.h" +#include "SDL_os4opengles.h" +#include "SDL_os4library.h" + +#include +#include + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +static struct Library *OGLES2base; +struct OGLES2IFace *IOGLES2; + +void *AmiGetGLESProc(const char *proc); + +static void +OS4_GLES_LogLibraryError() +{ + dprintf("No OpenGL ES 2 library available\n"); + SDL_SetError("No OpenGL ES 2 library available"); +} + +int +OS4_GLES_LoadLibrary(_THIS, const char * path) +{ + dprintf("Called %d\n", _this->gl_config.driver_loaded); + + if (!OGLES2base) { + OGLES2base = OS4_OpenLibrary("ogles2.library", 0); + + if (!OGLES2base) { + dprintf("Failed to open ogles2.library\n"); + SDL_SetError("Failed to open ogles2.library"); + return -1; + } + } + + if (!IOGLES2) { + IOGLES2 = (struct OGLES2IFace *) OS4_GetInterface(OGLES2base); + + if (!IOGLES2) { + dprintf("Failed to open OpenGL ES 2 interface\n"); + SDL_SetError("Failed to open OpenGL ES 2 interface"); + return -1; + } + + dprintf("OpenGL ES 2 library opened\n"); + } + + return 0; +} + +void * +OS4_GLES_GetProcAddress(_THIS, const char * proc) +{ + void *func = NULL; + + dprintf("Called for '%s'\n", proc); + + if (IOGLES2) { + func = AmiGetGLESProc(proc); + } + + if (func == NULL) { + dprintf("Failed to load '%s'\n", proc); + SDL_SetError("Failed to load function"); + } + + return func; +} + +void +OS4_GLES_UnloadLibrary(_THIS) +{ + dprintf("Called %d\n", _this->gl_config.driver_loaded); + + OS4_DropInterface((void *) &IOGLES2); + OS4_CloseLibrary(&OGLES2base); +} + +SDL_GLContext +OS4_GLES_CreateContext(_THIS, SDL_Window * window) +{ + dprintf("Called\n"); + + if (IOGLES2) { + + int width, height; + + OS4_GetWindowActiveSize(window, &width, &height); + +#if MANAGE_BITMAP + uint32 depth; +#endif + + ULONG errCode = 0; + + SDL_WindowData *data = window->driverdata; + + if (data->glContext) { + dprintf("Old context %p found, deleting\n", data->glContext); + + aglDestroyContext(data->glContext); + + data->glContext = NULL; + } + +#if MANAGE_BITMAP + depth = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_BITSPERPIXEL); + + if (!OS4_GL_AllocateBuffers(_this, width, height, depth, data)) { + SDL_SetError("Failed to allocate OpenGL ES 2 buffers"); + return NULL; + } +#endif + dprintf("Depth buffer size %d, stencil buffer size %d\n", + _this->gl_config.depth_size, _this->gl_config.stencil_size); + + data->glContext = aglCreateContextTags2( + &errCode, + OGLES2_CCT_WINDOW, (ULONG)data->syswin, + OGLES2_CCT_VSYNC, 0, +#if MANAGE_BITMAP + OGLES2_CCT_BITMAP, (ULONG)data->glBackBuffer, +#endif + OGLES2_CCT_DEPTH, _this->gl_config.depth_size, + OGLES2_CCT_STENCIL, _this->gl_config.stencil_size, + TAG_DONE); + + if (data->glContext) { + + dprintf("OpenGL ES 2 context %p created for window '%s'\n", + data->glContext, window->title); + + aglMakeCurrent(data->glContext); + glViewport(0, 0, width, height); + return data->glContext; + + } else { + dprintf("Failed to create OpenGL ES 2 context for window '%s' (error code %d)\n", + window->title, errCode); + + SDL_SetError("Failed to create OpenGL ES 2 context"); +#if MANAGE_BITMAP + OS4_GL_FreeBuffers(_this, data); +#endif + return NULL; + } + + } else { + OS4_GLES_LogLibraryError(); + return NULL; + } + + return NULL; +} + +int +OS4_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) +{ + int result = -1; + + if (!window || !context) { + dprintf("Called (window %p, context %p)\n", window, context); + } + + if (IOGLES2) { + aglMakeCurrent(context); + result = 0; + } else { + OS4_GLES_LogLibraryError(); + } + + return result; +} + +int +OS4_GLES_SwapWindow(_THIS, SDL_Window * window) +{ + //dprintf("Called\n"); + + if (IOGLES2) { + + SDL_WindowData *data = window->driverdata; + + if (data->glContext) { + SDL_VideoData *videodata = _this->driverdata; + +#if MANAGE_BITMAP + struct BitMap *temp; + int w, h; + BOOL blitRpRet; + int32 blitRet; + + OS4_GetWindowSize(_this, data->syswin, &w, &h); +#endif + + glFinish(); + + if (videodata->vsyncEnabled) { + IGraphics->WaitTOF(); + } + + aglSwapBuffers(); + +#if MANAGE_BITMAP + blitRpRet = IGraphics->BltBitMapRastPort(data->glBackBuffer, 0, 0, data->syswin->RPort, + data->syswin->BorderLeft, data->syswin->BorderTop, w, h, 0xC0); + + if (!blitRpRet) { + dprintf("BltBitMapRastPort() failed\n"); + } + + blitRet = IGraphics->BltBitMapTags(BLITA_Source, data->glBackBuffer, + BLITA_SrcType, BLITT_BITMAP, + BLITA_SrcX, 0, + BLITA_SrcY, 0, + BLITA_Dest, data->glFrontBuffer, + BLITA_DestType,BLITT_BITMAP, + BLITA_DestX, 0, + BLITA_DestY, 0, + BLITA_Width, w, + BLITA_Height, h, + BLITA_Minterm, 0xC0, + TAG_DONE); + + if (blitRet == -1) { + temp = data->glFrontBuffer; + data->glFrontBuffer = data->glBackBuffer; + data->glBackBuffer = temp; + + aglSetBitmap(data->glBackBuffer); + + return 0; + } else { + dprintf("BltBitMapTags() returned %d\n", blitRet); + } +#endif + } else { + dprintf("No OpenGL ES 2 context\n"); + } + } else { + OS4_GLES_LogLibraryError(); + } + + return -1; +} + +void +OS4_GLES_DeleteContext(_THIS, SDL_GLContext context) +{ + dprintf("Called with context=%p\n", context); + + if (IOGLES2) { + + if (context) { + SDL_Window *sdlwin; + Uint32 deletions = 0; + + for (sdlwin = _this->windows; sdlwin; sdlwin = sdlwin->next) { + + SDL_WindowData *data = sdlwin->driverdata; + + if (data->glContext == context) { + dprintf("Found OpenGL ES 2 context, clearing window binding\n"); + + aglDestroyContext(context); + + data->glContext = NULL; + deletions++; + } + } + + if (deletions == 0) { + dprintf("OpenGL ES 2 context doesn't seem to have window binding\n"); + } + } else { + dprintf("No context to delete\n"); + } + + } else { + OS4_GLES_LogLibraryError(); + } +} + +SDL_bool +OS4_GLES_ResizeContext(_THIS, SDL_Window * window) +{ + if (IOGLES2) { +#if MANAGE_BITMAP + SDL_WindowData *data = window->driverdata; + + if (data) { + int width, height; + + uint32 depth = IGraphics->GetBitMapAttr(data->syswin->RPort->BitMap, BMA_BITSPERPIXEL); + + OS4_GetWindowActiveSize(window, &width, &height); + + if (OS4_GL_AllocateBuffers(_this, width, height, depth, data)) { + + dprintf("Resizing context to %d*%d\n", width, height); + + aglSetBitmap(data->glBackBuffer); + + glViewport(0, 0, width, height); + return SDL_TRUE; + + } else { + dprintf("Failed to re-allocate OpenGL ES 2 buffers\n"); + //SDL_Quit(); + } + } +#endif + return SDL_TRUE; + } else { + OS4_GLES_LogLibraryError(); + } + + return SDL_FALSE; +} + +void +OS4_GLES_UpdateWindowPointer(_THIS, SDL_Window * window) +{ + if (IOGLES2) { + SDL_WindowData *data = window->driverdata; + + dprintf("Updating GLES2 window pointer %p\n", data->syswin); + aglSetParamsTags2(OGLES2_CCT_WINDOW, (ULONG)data->syswin, TAG_DONE); + } else { + OS4_GLES_LogLibraryError(); + } +} + +#endif /* SDL_VIDEO_OPENGL_ES2 */ + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4opengles.h b/src/video/amigaos4/SDL_os4opengles.h new file mode 100644 index 0000000000000..f9138f1db4c16 --- /dev/null +++ b/src/video/amigaos4/SDL_os4opengles.h @@ -0,0 +1,39 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2019 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4opengles_h +#define _SDL_os4opengles_h + +extern int OS4_GLES_LoadLibrary(_THIS, const char *path); +extern void *OS4_GLES_GetProcAddress(_THIS, const char *proc); +extern void OS4_GLES_UnloadLibrary(_THIS); +extern SDL_GLContext OS4_GLES_CreateContext(_THIS, SDL_Window * window); +extern int OS4_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +extern int OS4_GLES_SwapWindow(_THIS, SDL_Window * window); +extern void OS4_GLES_DeleteContext(_THIS, SDL_GLContext context); + +extern SDL_bool OS4_GLES_ResizeContext(_THIS, SDL_Window * window); +extern void OS4_GLES_UpdateWindowPointer(_THIS, SDL_Window * window); + +#endif /* _SDL_os4opengles_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4opengles2wrapper.c b/src/video/amigaos4/SDL_os4opengles2wrapper.c new file mode 100644 index 0000000000000..4e37f10aa7a36 --- /dev/null +++ b/src/video/amigaos4/SDL_os4opengles2wrapper.c @@ -0,0 +1,771 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#if SDL_VIDEO_OPENGL_ES2 + +#include +#include + +/* The OpenGL ES 2.0 API */ + +static void AmiglActiveTexture (GLenum texture) { + return glActiveTexture(texture); +} + +static void AmiglAttachShader (GLuint program, GLuint shader) { + return glAttachShader(program, shader); +} + +static void AmiglBindAttribLocation (GLuint program, GLuint index, const GLchar *name) { + return glBindAttribLocation(program, index, name); +} + +static void AmiglBindBuffer (GLenum target, GLuint buffer) { + return glBindBuffer(target, buffer); +} + +static void AmiglBindFramebuffer (GLenum target, GLuint framebuffer) { + return glBindFramebuffer(target, framebuffer); +} + +static void AmiglBindRenderbuffer (GLenum target, GLuint renderbuffer) { + return glBindRenderbuffer(target, renderbuffer); +} + +static void AmiglBindTexture (GLenum target, GLuint texture) { + return glBindTexture(target, texture); +} + +static void AmiglBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + return glBlendColor(red, green, blue, alpha); +} + +static void AmiglBlendEquation (GLenum mode) { + return glBlendEquation(mode); +} + +static void AmiglBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) { + return glBlendEquationSeparate(modeRGB, modeAlpha); +} + +static void AmiglBlendFunc (GLenum sfactor, GLenum dfactor) { + return glBlendFunc(sfactor, dfactor); +} + +static void AmiglBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) { + return glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); +} + +static void AmiglBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage) { + return glBufferData(target, size, data, usage); +} + +static void AmiglBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data) { + return glBufferSubData(target, offset, size, data); +} + +static GLenum AmiglCheckFramebufferStatus (GLenum target) { + return glCheckFramebufferStatus(target); +} + +static void AmiglClear (GLbitfield mask) { + return glClear(mask); +} + +static void AmiglClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + return glClearColor(red, green, blue, alpha); +} + +static void AmiglClearDepthf (GLfloat d) { + return glClearDepthf(d); +} + +static void AmiglClearStencil (GLint s) { + return glClearStencil(s); +} + +static void AmiglColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { + return glColorMask(red, green, blue, alpha); +} + +static void AmiglCompileShader (GLuint shader) { + return glCompileShader(shader); +} + +static void AmiglCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) { + return glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +static void AmiglCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) { + return glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +static void AmiglCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + return glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} + +static void AmiglCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + return glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +static GLuint AmiglCreateProgram (void) { + return glCreateProgram(); +} + +static GLuint AmiglCreateShader (GLenum type) { + return glCreateShader(type); +} + +static void AmiglCullFace (GLenum mode) { + return glCullFace(mode); +} + +static void AmiglDeleteBuffers (GLsizei n, const GLuint *buffers) { + return glDeleteBuffers(n, buffers); +} + +static void AmiglDeleteFramebuffers (GLsizei n, const GLuint *framebuffers) { + return glDeleteFramebuffers(n, framebuffers); +} + +static void AmiglDeleteProgram (GLuint program) { + return glDeleteProgram(program); +} + +static void AmiglDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers) { + return glDeleteRenderbuffers(n, renderbuffers); +} + +static void AmiglDeleteShader (GLuint shader) { + return glDeleteShader(shader); +} + +static void AmiglDeleteTextures (GLsizei n, const GLuint *textures) { + return glDeleteTextures(n, textures); +} + +static void AmiglDepthFunc (GLenum func) { + return glDepthFunc(func); +} + +static void AmiglDepthMask (GLboolean flag) { + return glDepthMask(flag); +} + +static void AmiglDepthRangef (GLfloat n, GLfloat f) { + return glDepthRangef(n, f); +} + +static void AmiglDetachShader (GLuint program, GLuint shader) { + return glDetachShader(program, shader); +} + +static void AmiglDisable (GLenum cap) { + return glDisable(cap); +} + +static void AmiglDisableVertexAttribArray (GLuint index) { + return glDisableVertexAttribArray(index); +} + +static void AmiglDrawArrays (GLenum mode, GLint first, GLsizei count) { + return glDrawArrays(mode, first, count); +} + +static void AmiglDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices) { + return glDrawElements(mode, count, type, indices); +} + +static void AmiglEnable (GLenum cap) { + return glEnable(cap); +} + +static void AmiglEnableVertexAttribArray (GLuint index) { + return glEnableVertexAttribArray(index); +} + +static void AmiglFinish (void) { + return glFinish(); +} + +static void AmiglFlush (void) { + return glFlush(); +} + +static void AmiglFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { + return glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} + +static void AmiglFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + return glFramebufferTexture2D(target, attachment, textarget, texture, level); +} + +static void AmiglFrontFace (GLenum mode) { + return glFrontFace(mode); +} + +static void AmiglGenBuffers (GLsizei n, GLuint *buffers) { + return glGenBuffers(n, buffers); +} + +static void AmiglGenerateMipmap (GLenum target) { + return glGenerateMipmap(target); +} + +static void AmiglGenFramebuffers (GLsizei n, GLuint *framebuffers) { + return glGenFramebuffers(n, framebuffers); +} + +static void AmiglGenRenderbuffers (GLsizei n, GLuint *renderbuffers) { + return glGenRenderbuffers(n, renderbuffers); +} + +static void AmiglGenTextures (GLsizei n, GLuint *textures) { + return glGenTextures(n, textures); +} + +static void AmiglGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + return glGetActiveAttrib(program, index, bufSize, length, size, type, name); +} + +static void AmiglGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + return glGetActiveUniform(program, index, bufSize, length, size, type, name); +} + +static void AmiglGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) { + return glGetAttachedShaders(program, maxCount, count, shaders); +} + +static GLint AmiglGetAttribLocation (GLuint program, const GLchar *name) { + return glGetAttribLocation(program, name); +} + +static void AmiglGetBooleanv (GLenum pname, GLboolean *data) { + return glGetBooleanv(pname, data); +} + +static void AmiglGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) { + return glGetBufferParameteriv(target, pname, params); +} + +static GLenum AmiglGetError (void) { + return glGetError(); +} + +static void AmiglGetFloatv (GLenum pname, GLfloat *data) { + return glGetFloatv(pname, data); +} + +static void AmiglGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params) { + return glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +} + +static void AmiglGetIntegerv (GLenum pname, GLint *data) { + return glGetIntegerv(pname, data); +} + +static void AmiglGetProgramiv (GLuint program, GLenum pname, GLint *params) { + return glGetProgramiv(program, pname, params); +} + +static void AmiglGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + return glGetProgramInfoLog(program, bufSize, length, infoLog); +} + +static void AmiglGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params) { + return glGetRenderbufferParameteriv(target, pname, params); +} + +static void AmiglGetShaderiv (GLuint shader, GLenum pname, GLint *params) { + return glGetShaderiv(shader, pname, params); +} + +static void AmiglGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + return glGetShaderInfoLog(shader, bufSize, length, infoLog); +} + +static void AmiglGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) { + return glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); +} + +static void AmiglGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) { + return glGetShaderSource(shader, bufSize, length, source); +} + +static const GLubyte *AmiglGetString (GLenum name) { + return glGetString(name); +} + +static void AmiglGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params) { + return glGetTexParameterfv(target, pname, params); +} + +static void AmiglGetTexParameteriv (GLenum target, GLenum pname, GLint *params) { + return glGetTexParameteriv(target, pname, params); +} + +static void AmiglGetUniformfv (GLuint program, GLint location, GLfloat *params) { + return glGetUniformfv(program, location, params); +} + +static void AmiglGetUniformiv (GLuint program, GLint location, GLint *params) { + return glGetUniformiv(program, location, params); +} + +static GLint AmiglGetUniformLocation (GLuint program, const GLchar *name) { + return glGetUniformLocation(program, name); +} + +static void AmiglGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params) { + return glGetVertexAttribfv(index, pname, params); +} + +static void AmiglGetVertexAttribiv (GLuint index, GLenum pname, GLint *params) { + return glGetVertexAttribiv(index, pname, params); +} + +static void AmiglGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer) { + return glGetVertexAttribPointerv(index, pname, pointer); +} + +static void AmiglHint (GLenum target, GLenum mode) { + return glHint(target, mode); +} + +static GLboolean AmiglIsBuffer (GLuint buffer) { + return glIsBuffer(buffer); +} + +static GLboolean AmiglIsEnabled (GLenum cap) { + return glIsEnabled(cap); +} + +static GLboolean AmiglIsFramebuffer (GLuint framebuffer) { + return glIsFramebuffer(framebuffer); +} + +static GLboolean AmiglIsProgram (GLuint program) { + return glIsProgram(program); +} + +static GLboolean AmiglIsRenderbuffer (GLuint renderbuffer) { + return glIsRenderbuffer(renderbuffer); +} + +static GLboolean AmiglIsShader (GLuint shader) { + return glIsShader(shader); +} + +static GLboolean AmiglIsTexture (GLuint texture) { + return glIsTexture(texture); +} + +static void AmiglLineWidth (GLfloat width) { + return glLineWidth(width); +} + +static void AmiglLinkProgram (GLuint program) { + return glLinkProgram(program); +} + +static void AmiglPixelStorei (GLenum pname, GLint param) { + return glPixelStorei(pname, param); +} + +static void AmiglPolygonOffset (GLfloat factor, GLfloat units) { + return glPolygonOffset(factor, units); +} + +static void AmiglReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) { + return glReadPixels(x, y, width, height, format, type, pixels); +} + +static void AmiglReleaseShaderCompiler (void) { + return glReleaseShaderCompiler(); +} + +static void AmiglRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { + return glRenderbufferStorage(target, internalformat, width, height); +} + +static void AmiglSampleCoverage (GLfloat value, GLboolean invert) { + return glSampleCoverage(value, invert); +} + +static void AmiglScissor (GLint x, GLint y, GLsizei width, GLsizei height) { + return glScissor(x, y, width, height); +} + +static void AmiglShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) { + return glShaderBinary(count, shaders, binaryformat, binary, length); +} + +static void AmiglShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) { + return glShaderSource(shader, count, string, length); +} + +static void AmiglStencilFunc (GLenum func, GLint ref, GLuint mask) { + return glStencilFunc(func, ref, mask); +} + +static void AmiglStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) { + return glStencilFuncSeparate(face, func, ref, mask); +} + +static void AmiglStencilMask (GLuint mask) { + return glStencilMask(mask); +} + +static void AmiglStencilMaskSeparate (GLenum face, GLuint mask) { + return glStencilMaskSeparate(face, mask); +} + +static void AmiglStencilOp (GLenum fail, GLenum zfail, GLenum zpass) { + return glStencilOp(fail, zfail, zpass); +} + +static void AmiglStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) { + return glStencilOpSeparate(face, sfail, dpfail, dppass); +} + +static void AmiglTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) { + return glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); +} + +static void AmiglTexParameterf (GLenum target, GLenum pname, GLfloat param) { + return glTexParameterf(target, pname, param); +} + +static void AmiglTexParameterfv (GLenum target, GLenum pname, const GLfloat *params) { + return glTexParameterfv(target, pname, params); +} + +static void AmiglTexParameteri (GLenum target, GLenum pname, GLint param) { + return glTexParameteri(target, pname, param); +} + +static void AmiglTexParameteriv (GLenum target, GLenum pname, const GLint *params) { + return glTexParameteriv(target, pname, params); +} + +static void AmiglTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) { + return glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +static void AmiglUniform1f (GLint location, GLfloat v0) { + return glUniform1f(location, v0); +} + +static void AmiglUniform1fv (GLint location, GLsizei count, const GLfloat *value) { + return glUniform1fv(location, count, value); +} + +static void AmiglUniform1i (GLint location, GLint v0) { + return glUniform1i(location, v0); +} + +static void AmiglUniform1iv (GLint location, GLsizei count, const GLint *value) { + return glUniform1iv(location, count, value); +} + +static void AmiglUniform2f (GLint location, GLfloat v0, GLfloat v1) { + return glUniform2f(location, v0, v1); +} + +static void AmiglUniform2fv (GLint location, GLsizei count, const GLfloat *value) { + return glUniform2fv(location, count, value); +} + +static void AmiglUniform2i (GLint location, GLint v0, GLint v1) { + return glUniform2i(location, v0, v1); +} + +static void AmiglUniform2iv (GLint location, GLsizei count, const GLint *value) { + return glUniform2iv(location, count, value); +} + +static void AmiglUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { + return glUniform3f(location, v0, v1, v2); +} + +static void AmiglUniform3fv (GLint location, GLsizei count, const GLfloat *value) { + return glUniform3fv(location, count, value); +} + +static void AmiglUniform3i (GLint location, GLint v0, GLint v1, GLint v2) { + return glUniform3i(location, v0, v1, v2); +} + +static void AmiglUniform3iv (GLint location, GLsizei count, const GLint *value) { + return glUniform3iv(location, count, value); +} + +static void AmiglUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { + return glUniform4f(location, v0, v1, v2, v3); +} + +static void AmiglUniform4fv (GLint location, GLsizei count, const GLfloat *value) { + return glUniform4fv(location, count, value); +} + +static void AmiglUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { + return glUniform4i(location, v0, v1, v2, v3); +} + +static void AmiglUniform4iv (GLint location, GLsizei count, const GLint *value) { + return glUniform4iv(location, count, value); +} + +static void AmiglUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + return glUniformMatrix2fv(location, count, transpose, value); +} + +static void AmiglUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + return glUniformMatrix3fv(location, count, transpose, value); +} + +static void AmiglUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + return glUniformMatrix4fv(location, count, transpose, value); +} + +static void AmiglUseProgram (GLuint program) { + return glUseProgram(program); +} + +static void AmiglValidateProgram (GLuint program) { + return glValidateProgram(program); +} + +static void AmiglVertexAttrib1f (GLuint index, GLfloat x) { + return glVertexAttrib1f(index, x); +} + +static void AmiglVertexAttrib1fv (GLuint index, const GLfloat *v) { + return glVertexAttrib1fv(index, v); +} + +static void AmiglVertexAttrib2f (GLuint index, GLfloat x, GLfloat y) { + return glVertexAttrib2f(index, x, y); +} + +static void AmiglVertexAttrib2fv (GLuint index, const GLfloat *v) { + return glVertexAttrib2fv(index, v); +} + +static void AmiglVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z) { + return glVertexAttrib3f(index, x, y, z); +} + +static void AmiglVertexAttrib3fv (GLuint index, const GLfloat *v) { + return glVertexAttrib3fv(index, v); +} + +static void AmiglVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { + return glVertexAttrib4f(index, x, y, z, w); +} + +static void AmiglVertexAttrib4fv (GLuint index, const GLfloat *v) { + return glVertexAttrib4fv(index, v); +} + +static void AmiglVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { + return glVertexAttribPointer(index, size, type, normalized, stride, pointer); +} + +static void AmiglViewport (GLint x, GLint y, GLsizei width, GLsizei height) { + return glViewport(x, y, width, height); +} + +struct MyGLFunc +{ + CONST_STRPTR name; + APTR func; +}; + +#define MY_GL_FUNC(name) {#name, Ami##name}, + + +void *AmiGetGLESProc(const char *proc) +{ + static CONST struct MyGLFunc table[] = { + MY_GL_FUNC(glActiveTexture) + MY_GL_FUNC(glAttachShader) + MY_GL_FUNC(glBindAttribLocation) + MY_GL_FUNC(glBindBuffer) + MY_GL_FUNC(glBindFramebuffer) + MY_GL_FUNC(glBindRenderbuffer) + MY_GL_FUNC(glBindTexture) + MY_GL_FUNC(glBlendColor) + MY_GL_FUNC(glBlendEquation) + MY_GL_FUNC(glBlendEquationSeparate) + MY_GL_FUNC(glBlendFunc) + MY_GL_FUNC(glBlendFuncSeparate) + MY_GL_FUNC(glBufferData) + MY_GL_FUNC(glBufferSubData) + MY_GL_FUNC(glCheckFramebufferStatus) + MY_GL_FUNC(glClear) + MY_GL_FUNC(glClearColor) + MY_GL_FUNC(glClearDepthf) + MY_GL_FUNC(glClearStencil) + MY_GL_FUNC(glColorMask) + MY_GL_FUNC(glCompileShader) + MY_GL_FUNC(glCompressedTexImage2D) + MY_GL_FUNC(glCompressedTexSubImage2D) + MY_GL_FUNC(glCopyTexImage2D) + MY_GL_FUNC(glCopyTexSubImage2D) + MY_GL_FUNC(glCreateProgram) + MY_GL_FUNC(glCreateShader) + MY_GL_FUNC(glCullFace) + MY_GL_FUNC(glDeleteBuffers) + MY_GL_FUNC(glDeleteFramebuffers) + MY_GL_FUNC(glDeleteProgram) + MY_GL_FUNC(glDeleteRenderbuffers) + MY_GL_FUNC(glDeleteShader) + MY_GL_FUNC(glDeleteTextures) + MY_GL_FUNC(glDepthFunc) + MY_GL_FUNC(glDepthMask) + MY_GL_FUNC(glDepthRangef) + MY_GL_FUNC(glDetachShader) + MY_GL_FUNC(glDisable) + MY_GL_FUNC(glDisableVertexAttribArray) + MY_GL_FUNC(glDrawArrays) + MY_GL_FUNC(glDrawElements) + MY_GL_FUNC(glEnable) + MY_GL_FUNC(glEnableVertexAttribArray) + MY_GL_FUNC(glFinish) + MY_GL_FUNC(glFlush) + MY_GL_FUNC(glFramebufferRenderbuffer) + MY_GL_FUNC(glFramebufferTexture2D) + MY_GL_FUNC(glFrontFace) + MY_GL_FUNC(glGenBuffers) + MY_GL_FUNC(glGenerateMipmap) + MY_GL_FUNC(glGenFramebuffers) + MY_GL_FUNC(glGenRenderbuffers) + MY_GL_FUNC(glGenTextures) + MY_GL_FUNC(glGetActiveAttrib) + MY_GL_FUNC(glGetActiveUniform) + MY_GL_FUNC(glGetAttachedShaders) + MY_GL_FUNC(glGetAttribLocation) + MY_GL_FUNC(glGetBooleanv) + MY_GL_FUNC(glGetBufferParameteriv) + MY_GL_FUNC(glGetError) + MY_GL_FUNC(glGetFloatv) + MY_GL_FUNC(glGetFramebufferAttachmentParameteriv) + MY_GL_FUNC(glGetIntegerv) + MY_GL_FUNC(glGetProgramiv) + MY_GL_FUNC(glGetProgramInfoLog) + MY_GL_FUNC(glGetRenderbufferParameteriv) + MY_GL_FUNC(glGetShaderiv) + MY_GL_FUNC(glGetShaderInfoLog) + MY_GL_FUNC(glGetShaderPrecisionFormat) + MY_GL_FUNC(glGetShaderSource) + MY_GL_FUNC(glGetString) + MY_GL_FUNC(glGetTexParameterfv) + MY_GL_FUNC(glGetTexParameteriv) + MY_GL_FUNC(glGetUniformfv) + MY_GL_FUNC(glGetUniformiv) + MY_GL_FUNC(glGetUniformLocation) + MY_GL_FUNC(glGetVertexAttribfv) + MY_GL_FUNC(glGetVertexAttribiv) + MY_GL_FUNC(glGetVertexAttribPointerv) + MY_GL_FUNC(glHint) + MY_GL_FUNC(glIsBuffer) + MY_GL_FUNC(glIsEnabled) + MY_GL_FUNC(glIsFramebuffer) + MY_GL_FUNC(glIsProgram) + MY_GL_FUNC(glIsRenderbuffer) + MY_GL_FUNC(glIsShader) + MY_GL_FUNC(glIsTexture) + MY_GL_FUNC(glLineWidth) + MY_GL_FUNC(glLinkProgram) + MY_GL_FUNC(glPixelStorei) + MY_GL_FUNC(glPolygonOffset) + MY_GL_FUNC(glReadPixels) + MY_GL_FUNC(glReleaseShaderCompiler) + MY_GL_FUNC(glRenderbufferStorage) + MY_GL_FUNC(glSampleCoverage) + MY_GL_FUNC(glScissor) + MY_GL_FUNC(glShaderBinary) + MY_GL_FUNC(glShaderSource) + MY_GL_FUNC(glStencilFunc) + MY_GL_FUNC(glStencilFuncSeparate) + MY_GL_FUNC(glStencilMask) + MY_GL_FUNC(glStencilMaskSeparate) + MY_GL_FUNC(glStencilOp) + MY_GL_FUNC(glStencilOpSeparate) + MY_GL_FUNC(glTexImage2D) + MY_GL_FUNC(glTexParameterf) + MY_GL_FUNC(glTexParameterfv) + MY_GL_FUNC(glTexParameteri) + MY_GL_FUNC(glTexParameteriv) + MY_GL_FUNC(glTexSubImage2D) + MY_GL_FUNC(glUniform1f) + MY_GL_FUNC(glUniform1fv) + MY_GL_FUNC(glUniform1i) + MY_GL_FUNC(glUniform1iv) + MY_GL_FUNC(glUniform2f) + MY_GL_FUNC(glUniform2fv) + MY_GL_FUNC(glUniform2i) + MY_GL_FUNC(glUniform2iv) + MY_GL_FUNC(glUniform3f) + MY_GL_FUNC(glUniform3fv) + MY_GL_FUNC(glUniform3i) + MY_GL_FUNC(glUniform3iv) + MY_GL_FUNC(glUniform4f) + MY_GL_FUNC(glUniform4fv) + MY_GL_FUNC(glUniform4i) + MY_GL_FUNC(glUniform4iv) + MY_GL_FUNC(glUniformMatrix2fv) + MY_GL_FUNC(glUniformMatrix3fv) + MY_GL_FUNC(glUniformMatrix4fv) + MY_GL_FUNC(glUseProgram) + MY_GL_FUNC(glValidateProgram) + MY_GL_FUNC(glVertexAttrib1f) + MY_GL_FUNC(glVertexAttrib1fv) + MY_GL_FUNC(glVertexAttrib2f) + MY_GL_FUNC(glVertexAttrib2fv) + MY_GL_FUNC(glVertexAttrib3f) + MY_GL_FUNC(glVertexAttrib3fv) + MY_GL_FUNC(glVertexAttrib4f) + MY_GL_FUNC(glVertexAttrib4fv) + MY_GL_FUNC(glVertexAttribPointer) + MY_GL_FUNC(glViewport) + { NULL, NULL } + }; + + CONST struct MyGLFunc *tb = table; + + do { + if (!strcmp(tb->name, proc)) { + return tb->func; + } + tb++; + } while (tb->name); + + return NULL; +} + +#endif /* SDL_VIDEO_OPENGL_ES2 */ +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ diff --git a/src/video/amigaos4/SDL_os4openglwrapper.c b/src/video/amigaos4/SDL_os4openglwrapper.c new file mode 100644 index 0000000000000..07b5d72d0d767 --- /dev/null +++ b/src/video/amigaos4/SDL_os4openglwrapper.c @@ -0,0 +1,1847 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "SDL_config.h" + +/* wrapper functions for MiniGL */ + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include +#include +#include + +#define NOT_IMPLEMENTED_FUNCS + +#include + +/* The GL API */ + +static void AmiglActiveTexture(GLenum unit) { + return glActiveTexture(unit); +} + +static void AmiglClientActiveTexture(GLenum texture) { + return glClientActiveTexture(texture); +} + +static void AmiglColorTable(GLenum target, GLenum internalformat, GLint width, GLenum format, GLenum type, const GLvoid* data) { + return glColorTable(target, internalformat, width, format, type, data); +} + +static void AmiglColorTableEXT(GLenum target, GLenum internalformat, GLint width, GLenum format, GLenum type, const GLvoid* data) { + return glColorTableEXT(target, internalformat, width, format, type, data); +} + +static void AmiglClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) { + return glClearColor(red, green, blue, alpha); +} + +static void AmiglClear( GLbitfield mask ) { + return glClear(mask); +} + +static void AmiglColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha ) { + return glColorMask(red, green, blue, alpha); +} + +static void AmiglAlphaFunc( GLenum func, GLclampf ref ) { + return glAlphaFunc(func, ref); +} + +static void AmiglBlendFunc( GLenum sfactor, GLenum dfactor ) { + return glBlendFunc(sfactor, dfactor); +} + +static void AmiglLogicOp( GLenum opcode ) { + return glLogicOp(opcode); +} + +static void AmiglCullFace( GLenum mode ) { + return glCullFace(mode); +} + +static void AmiglFrontFace( GLenum mode ) { + return glFrontFace(mode); +} + +static void AmiglPointSize( GLfloat size ) { + return glPointSize(size); +} + +static void AmiglLineWidth( GLfloat width ) { + return glLineWidth(width); +} + +static void AmiglLineStipple( GLint factor, GLushort pattern ) { + return glLineStipple(factor, pattern); +} + +static void AmiglPolygonMode( GLenum face, GLenum mode ) { + return glPolygonMode(face, mode); +} + +static void AmiglPolygonOffset( GLfloat factor, GLfloat units ) { + return glPolygonOffset(factor, units); +} + +static void AmiglPolygonStipple( GLubyte *mask ) { + return glPolygonStipple(mask); +} + +static void AmiglEdgeFlag( GLboolean flag ) { + return glEdgeFlag(flag); +} + +static void AmiglScissor( GLint x, GLint y, GLsizei width, GLsizei height) { + return glScissor(x, y, width, height); +} + +static void AmiglClipPlane( GLenum plane, const GLdouble *equation ) { + return glClipPlane(plane, (GLdouble *)equation); +} + +static void AmiglGetClipPlane( GLenum plane, GLdouble *equation ) { + return glGetClipPlane(plane, equation); +} + +static void AmiglDrawBuffer( GLenum mode ) { + return glDrawBuffer(mode); +} + +static void AmiglReadBuffer( GLenum mode ) { + return glReadBuffer(mode); +} + +static void AmiglEnable( GLenum cap ) { + return glEnable(cap); +} + +static void AmiglDisable( GLenum cap ) { + return glDisable(cap); +} + +static GLboolean AmiglIsEnabled( GLenum cap ) { + return glIsEnabled(cap); +} + +static void AmiglEnableClientState( GLenum cap ) { /* 1.1 */ + return glEnableClientState(cap); +} + +static void AmiglDisableClientState( GLenum cap ) { /* 1.1 */ + return glDisableClientState(cap); +} + +static void AmiglGetBooleanv( GLenum pname, GLboolean *params ) { + return glGetBooleanv(pname, params); +} + +static void AmiglGetDoublev( GLenum pname, GLdouble *params ) { + return glGetDoublev(pname, params); +} + +static void AmiglGetFloatv( GLenum pname, GLfloat *params ) { + return glGetFloatv(pname, params); +} + +static void AmiglGetIntegerv( GLenum pname, GLint *params ) { + return glGetIntegerv(pname, params); +} + +static void AmiglPushAttrib( GLbitfield mask ) { + return glPushAttrib(mask); +} + +static void AmiglPopAttrib( void ) { + return glPopAttrib(); +} + +static void AmiglPushClientAttrib( GLbitfield mask ) { /* 1.1 */ + return glPushClientAttrib(mask); +} + +static void AmiglPopClientAttrib( void ) { /* 1.1 */ + return glPopClientAttrib(); +} + +static GLint AmiglRenderMode( GLenum mode ) { + return glRenderMode(mode); +} + +static GLenum AmiglGetError( void ) { + return glGetError(); +} + +static const GLubyte* AmiglGetString( GLenum name ) { + return glGetString(name); +} + +static void AmiglFinish( void ) { + return glFinish(); +} + +static void AmiglFlush( void ) { + return glFlush(); +} + +static void AmiglHint( GLenum target, GLenum mode ) { + return glHint(target, mode); +} + +static void AmiglClearDepth( GLclampd depth ) { + return glClearDepth(depth); +} + +static void AmiglDepthFunc( GLenum func ) { + return glDepthFunc(func); +} + +static void AmiglDepthMask( GLboolean flag ) { + return glDepthMask(flag); +} + +static void AmiglDepthRange( GLclampd near_val, GLclampd far_val ) { + return glDepthRange(near_val, far_val); +} + +static void AmiglMatrixMode( GLenum mode ) { + return glMatrixMode(mode); +} + +static void AmiglOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val ) { + return glOrtho(left, right, bottom, top, near_val, far_val); +} + +static void AmiglFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val ) { + return glFrustum(left, right, bottom, top, near_val, far_val); +} + +static void AmiglViewport( GLint x, GLint y, GLsizei width, GLsizei height ) { + return glViewport(x, y, width, height); +} + +static void AmiglPushMatrix( void ) { + return glPushMatrix(); +} + +static void AmiglPopMatrix( void ) { + return glPopMatrix(); +} + +static void AmiglLoadIdentity( void ) { + return glLoadIdentity(); +} + +static void AmiglLoadMatrixd( const GLdouble *m ) { + return glLoadMatrixd(m); +} + +static void AmiglLoadMatrixf( const GLfloat *m ) { + return glLoadMatrixf(m); +} + +static void AmiglMultMatrixd( const GLdouble *m ) { + return glMultMatrixd(m); +} + +static void AmiglMultMatrixf( const GLfloat *m ) { + return glMultMatrixf(m); +} + +static void AmiglRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ) { + return glRotated(angle, x, y, z); +} + +static void AmiglRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) { + return glRotatef(angle, x, y, z); +} + +static void AmiglScaled( GLdouble x, GLdouble y, GLdouble z ) { + return glScaled(x, y, z); +} + +static void AmiglScalef( GLfloat x, GLfloat y, GLfloat z ) { + return glScalef(x, y, z); +} + +static void AmiglTranslated( GLdouble x, GLdouble y, GLdouble z ) { + return glTranslated(x, y, z); +} + +static void AmiglTranslatef( GLfloat x, GLfloat y, GLfloat z ) { + return glTranslatef(x, y, z); +} + +static GLboolean AmiglIsList( GLuint list ) { + return glIsList(list); +} + +static void AmiglDeleteLists( GLuint list, GLsizei range ) { + return glDeleteLists(list, range); +} + +static GLuint AmiglGenLists( GLsizei range ) { + return glGenLists(range); +} + +static void AmiglNewList( GLuint list, GLenum mode ) { + return glNewList(list, mode); +} + +static void AmiglEndList( void ) { + return glEndList(); +} + +static void AmiglCallList( GLuint list ) { + return glCallList(list); +} + +static void AmiglCallLists( GLsizei n, GLenum type, GLvoid *lists ) { + return glCallLists(n, type, lists); +} + +static void AmiglListBase( GLuint base ) { + return glListBase(base); +} + +static void AmiglBegin( GLenum mode ) { + return glBegin(mode); +} + +static void AmiglEnd( void ) { + return glEnd(); +} + +static void AmiglVertex2d( GLdouble x, GLdouble y ) { + return glVertex2d(x, y); +} + +static void AmiglVertex2f( GLfloat x, GLfloat y ) { + return glVertex2f(x, y); +} + +static void AmiglVertex2i( GLint x, GLint y ) { + return glVertex2i(x, y); +} + +static void AmiglVertex2s( GLshort x, GLshort y ) { + return glVertex2s(x, y); +} + +static void AmiglVertex3d( GLdouble x, GLdouble y, GLdouble z ) { + return glVertex3d(x, y, z); +} + +static void AmiglVertex3f( GLfloat x, GLfloat y, GLfloat z ) { + return glVertex3f(x, y, z); +} + +static void AmiglVertex3i( GLint x, GLint y, GLint z ) { + return glVertex3i(x, y, z); +} + +static void AmiglVertex3s( GLshort x, GLshort y, GLshort z ) { + return glVertex3s(x, y, z); +} + +static void AmiglVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ) { + return glVertex4d(x, y, z, w); +} + +static void AmiglVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) { + return glVertex4f(x, y, z, w); +} + +static void AmiglVertex4i( GLint x, GLint y, GLint z, GLint w ) { + return glVertex4i(x, y, z, w); +} + +static void AmiglVertex4s( GLshort x, GLshort y, GLshort z, GLshort w ) { + return glVertex4s(x, y, z, w); +} + +static void AmiglVertex2dv( GLdouble *v ) { + return glVertex2dv(v); +} + +static void AmiglVertex2fv( GLfloat *v ) { + return glVertex2fv(v); +} + +static void AmiglVertex2iv( GLint *v ) { + return glVertex2iv(v); +} + +static void AmiglVertex2sv( GLshort *v ) { + return glVertex2sv(v); +} + +static void AmiglVertex3dv( GLdouble *v ) { + return glVertex3dv(v); +} + +static void AmiglVertex3fv( GLfloat *v ) { + return glVertex3fv(v); +} + +static void AmiglVertex3iv( GLint *v ) { + return glVertex3iv(v); +} + +static void AmiglVertex3sv( GLshort *v ) { + return glVertex3sv(v); +} + +static void AmiglVertex4dv( GLdouble *v ) { + return glVertex4dv(v); +} + +static void AmiglVertex4fv( GLfloat *v ) { + return glVertex4fv(v); +} + +static void AmiglVertex4iv( GLint *v ) { + return glVertex4iv(v); +} + +static void AmiglVertex4sv( GLshort *v ) { + return glVertex4sv(v); +} + +static void AmiglNormal3b( GLbyte nx, GLbyte ny, GLbyte nz ) { + return glNormal3b(nx, ny, nz); +} + +static void AmiglNormal3d( GLdouble nx, GLdouble ny, GLdouble nz ) { + return glNormal3d(nx, ny, nz); +} + +static void AmiglNormal3f( GLfloat nx, GLfloat ny, GLfloat nz ) { + return glNormal3f(nx, ny, nz); +} + +static void AmiglNormal3i( GLint nx, GLint ny, GLint nz ) { + return glNormal3i(nx, ny, nz); +} + +static void AmiglNormal3s( GLshort nx, GLshort ny, GLshort nz ) { + return glNormal3s(nx, ny, nz); +} + +static void AmiglNormal3bv( const GLbyte *v ) { + return glNormal3bv(v); +} + +static void AmiglNormal3dv( const GLdouble *v ) { + return glNormal3dv(v); +} + +static void AmiglNormal3fv( GLfloat *v ) { + return glNormal3fv(v); +} + +static void AmiglNormal3iv( const GLint *v ) { + return glNormal3iv(v); +} + +static void AmiglNormal3sv( const GLshort *v ) { + return glNormal3sv(v); +} + +static void AmiglColor3b( GLbyte red, GLbyte green, GLbyte blue ) { + return glColor3b(red, green, blue); +} + +static void AmiglColor3d( GLdouble red, GLdouble green, GLdouble blue ) { + return glColor3d(red, green, blue); +} + +static void AmiglColor3f( GLfloat red, GLfloat green, GLfloat blue ) { + return glColor3f(red, green, blue); +} + +static void AmiglColor3i( GLint red, GLint green, GLint blue ) { + return glColor3i(red, green, blue); +} + +static void AmiglColor3s( GLshort red, GLshort green, GLshort blue ) { + return glColor3s(red, green, blue); +} + +static void AmiglColor3ub( GLubyte red, GLubyte green, GLubyte blue ) { + return glColor3ub(red, green, blue); +} + +static void AmiglColor3ui( GLuint red, GLuint green, GLuint blue ) { + return glColor3ui(red, green, blue); +} + +static void AmiglColor3us( GLushort red, GLushort green, GLushort blue ) { + return glColor3us(red, green, blue); +} + +static void AmiglColor4b( GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha ) { + return glColor4b(red, green, blue, alpha); +} + +static void AmiglColor4d( GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha ) { + return glColor4d(red, green, blue, alpha); +} + +static void AmiglColor4f( GLfloat red, GLfloat green,GLfloat blue, GLfloat alpha ) { + return glColor4f(red, green, blue, alpha); +} + +static void AmiglColor4i( GLint red, GLint green, GLint blue, GLint alpha ) { + return glColor4i(red, green, blue, alpha); +} + +static void AmiglColor4s( GLshort red, GLshort green, GLshort blue, GLshort alpha ) { + return glColor4s(red, green, blue, alpha); +} + +static void AmiglColor4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) { + return glColor4ub(red, green, blue, alpha); +} + +static void AmiglColor4ui( GLuint red, GLuint green, GLuint blue, GLuint alpha ) { + return glColor4ui(red, green, blue, alpha); +} + +static void AmiglColor4us( GLushort red, GLushort green, GLushort blue, GLushort alpha ) { + return glColor4us(red, green, blue, alpha); +} + +static void AmiglColor3bv( const GLbyte *v ) { + return glColor3bv(v); +} + +static void AmiglColor3dv( const GLdouble *v ) { + return glColor3dv(v); +} + +static void AmiglColor3fv( GLfloat *v ) { + return glColor3fv(v); +} + +static void AmiglColor3iv( const GLint *v ) { + return glColor3iv(v); +} + +static void AmiglColor3sv( const GLshort *v ) { + return glColor3sv(v); +} + +static void AmiglColor3ubv( GLubyte *v ) { + return glColor3ubv(v); +} + +static void AmiglColor3uiv( const GLuint *v ) { + return glColor3uiv(v); +} + +static void AmiglColor3usv( const GLushort *v ) { + glColor3usv(v); +} + +static void AmiglColor4bv( const GLbyte *v ) { + return glColor4bv(v); +} + +static void AmiglColor4dv( const GLdouble *v ) { + return glColor4dv(v); +} + +static void AmiglColor4fv( GLfloat *v ) { + return glColor4fv(v); +} + +static void AmiglColor4iv( const GLint *v ) { + return glColor4iv(v); +} + +static void AmiglColor4sv( const GLshort *v ) { + return glColor4sv(v); +} + +static void AmiglColor4ubv( GLubyte *v ) { + return glColor4ubv(v); +} + +static void AmiglColor4uiv( const GLuint *v ) { + return glColor4uiv(v); +} + +static void AmiglColor4usv( const GLushort *v ) { + return glColor4usv(v); +} + +static void AmiglTexCoord1d( GLdouble s ) { + return glTexCoord1d(s); +} + +static void AmiglTexCoord1f( GLfloat s ) { + return glTexCoord1f(s); +} + +static void AmiglTexCoord1i( GLint s ) { + return glTexCoord1i(s); +} + +static void AmiglTexCoord2d( GLdouble s, GLdouble t ) { + return glTexCoord2d(s, t); +} + +static void AmiglTexCoord2f( GLfloat s, GLfloat t ) { + return glTexCoord2f(s, t); +} + +static void AmiglTexCoord2i( GLint s, GLint t ) { + return glTexCoord2i(s, t); +} + +static void AmiglTexCoord3f( GLfloat s, GLfloat t, GLfloat r ) { + return glTexCoord3f(s, t, r); +} + +static void AmiglTexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) { + return glTexCoord4f(s, t, r, q); +} + +static void AmiglTexCoord2fv( GLfloat *v ) { + return glTexCoord2fv(v); +} + +static void AmiglTexCoord2iv( const GLint *v ) { + return glTexCoord2iv(v); +} + +static void AmiglTexCoord3fv( GLfloat *v ) { + return glTexCoord3fv(v); +} + +static void AmiglTexCoord4fv( GLfloat *v ) { + return glTexCoord4fv(v); +} + +static void AmiglClientActiveTextureARB(GLenum texture) { + return glClientActiveTextureARB(texture); +} + +static void AmiglActiveTextureARB(GLenum unit) { + return glActiveTextureARB(unit); +} + +static void AmiglMultiTexCoord2f(GLenum unit, GLfloat s, GLfloat t) { + return glMultiTexCoord2f(unit, s, t); +} + +static void AmiglMultiTexCoord2fv(GLenum unit, GLfloat *v) { + return glMultiTexCoord2fv(unit, v); +} + +static void AmiglMultiTexCoord4f(GLenum unit, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + return glMultiTexCoord4f(unit, s, t, r, q); +} + +static void AmiglMultiTexCoord4fv(GLenum unit, GLfloat *v) { + return glMultiTexCoord4fv(unit, v); +} + +static void AmiglMultiTexCoord2fARB(GLenum unit, GLfloat s, GLfloat t) { + return glMultiTexCoord2fARB(unit, s, t); +} + +static void AmiglMultiTexCoord2fvARB(GLenum unit, GLfloat *v) { + return glMultiTexCoord2fvARB(unit, v); +} + +static void AmiglMultiTexCoord4fARB(GLenum unit, GLfloat s, GLfloat t, GLfloat r, GLfloat q) { + return glMultiTexCoord4fARB(unit, s, t, r, q); +} + +static void AmiglMultiTexCoord4fvARB(GLenum unit, GLfloat *v) { + return glMultiTexCoord4fvARB(unit, v); +} + +static void AmiglRasterPos2d( GLdouble x, GLdouble y ) { + return glRasterPos2d(x, y); +} + +static void AmiglRasterPos2f( GLfloat x, GLfloat y ) { + return glRasterPos2f(x, y); +} + +static void AmiglRasterPos2i( GLint x, GLint y ) { + return glRasterPos2i(x, y); +} + +static void AmiglRasterPos2s( GLshort x, GLshort y ) { + return glRasterPos2s(x, y); +} + +static void AmiglRasterPos3d( GLdouble x, GLdouble y, GLdouble z ) { + return glRasterPos3d(x, y, z); +} + +static void AmiglRasterPos3f( GLfloat x, GLfloat y, GLfloat z ) { + return glRasterPos3f(x, y, z); +} + +static void AmiglRasterPos3i( GLint x, GLint y, GLint z ) { + return glRasterPos3i(x, y, z); +} + +static void AmiglRasterPos3s( GLshort x, GLshort y, GLshort z ) { + return glRasterPos3s(x, y, z); +} + +static void AmiglRasterPos4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ) { + return glRasterPos4d(x, y, z, w); +} + +static void AmiglRasterPos4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) { + return glRasterPos4f(x, y, z, w); +} + +static void AmiglRasterPos4i( GLint x, GLint y, GLint z, GLint w ) { + return glRasterPos4i(x, y, z, w); +} + +static void AmiglRasterPos4s( GLshort x, GLshort y, GLshort z, GLshort w ) { + return glRasterPos4s(x, y, z, w); +} + +static void AmiglRasterPos2dv( GLdouble *v ) { + return glRasterPos2dv(v); +} + +static void AmiglRasterPos2fv( GLfloat *v ) { + return glRasterPos2fv((GLfloat *)v); +} + +static void AmiglRasterPos2iv( GLint *v ) { + return glRasterPos2iv(v); +} + +static void AmiglRasterPos2sv( GLshort *v ) { + return glRasterPos2sv(v); +} + +static void AmiglRasterPos3dv( GLdouble *v ) { + return glRasterPos3dv(v); +} + +static void AmiglRasterPos3fv( GLfloat *v ) { + return glRasterPos3fv((GLfloat *)v); +} + +static void AmiglRasterPos3iv( GLint *v ) { + return glRasterPos3iv(v); +} + +static void AmiglRasterPos3sv( GLshort *v ) { + return glRasterPos3sv(v); +} + +static void AmiglRasterPos4dv( GLdouble *v ) { + return glRasterPos4dv(v); +} + +static void AmiglRasterPos4fv( GLfloat *v ) { + return glRasterPos4fv(v); +} + +static void AmiglRasterPos4iv( GLint *v ) { + return glRasterPos4iv(v); +} + +static void AmiglRasterPos4sv( GLshort *v ) { + return glRasterPos4sv(v); +} + +static void AmiglRectd( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 ) { + return glRectd(x1, y1, x2, y2); +} + +static void AmiglRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) { + return glRectf(x1, y1, x2, y2); +} + +static void AmiglRecti( GLint x1, GLint y1, GLint x2, GLint y2 ) { + return glRecti(x1, y1, x2, y2); +} + +static void AmiglRects( GLshort x1, GLshort y1, GLshort x2, GLshort y2 ) { + return glRects(x1, y1, x2, y2); +} + +static void AmiglRectdv( GLdouble *v1, GLdouble *v2 ) { + return glRectdv(v1, v2); +} + +static void AmiglRectfv( GLfloat *v1, GLfloat *v2 ) { + return glRectfv(v1, v2); +} + +static void AmiglRectiv( GLint *v1, GLint *v2 ) { + return glRectiv(v1, v2); +} + +static void AmiglRectsv( GLshort *v1, GLshort *v2 ) { + return glRectsv(v1, v2); +} + +static void AmiglVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr ) { + return glVertexPointer(size, type, stride, ptr); +} + +static void AmiglNormalPointer( GLenum type, GLsizei stride, const GLvoid *ptr ) { + return glNormalPointer(type, stride, ptr); +} + +static void AmiglColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr ) { + return glColorPointer(size, type, stride, ptr); +} + +static void AmiglTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr ) { + return glTexCoordPointer(size, type, stride, ptr); +} + +static void AmiglArrayElement( GLint i ) { + return glArrayElement(i); +} + +static void AmiglDrawArrays( GLenum mode, GLint first, GLsizei count ) { + return glDrawArrays(mode, first, count); +} + +static void AmiglDrawElements( GLenum mode, GLsizei count, GLenum type, GLvoid *indices ) { + return glDrawElements(mode, count, type, indices); +} + +static void AmiglInterleavedArrays( GLenum format, GLsizei stride, const GLvoid *pointer ) { + return glInterleavedArrays(format, stride, pointer); +} + +static void AmiglShadeModel( GLenum mode ) { + return glShadeModel(mode); +} + +static void AmiglLightf( GLenum light, GLenum pname, GLfloat param ) { + return glLightf(light, pname, param); +} + +static void AmiglLighti( GLenum light, GLenum pname, GLint param ) { + return glLighti(light, pname, param); +} + +static void AmiglLightfv( GLenum light, GLenum pname, GLfloat *params ) { + return glLightfv(light, pname, params); +} + +static void AmiglLightiv( GLenum light, GLenum pname, const GLint *params ) { + return glLightiv(light, pname, params); +} + +static void AmiglGetLightfv( GLenum light, GLenum pname, GLfloat *params ) { + return glGetLightfv(light, pname, params); +} + +static void AmiglGetLightiv( GLenum light, GLenum pname, GLint *params ) { + return glGetLightiv(light, pname, params); +} + +static void AmiglLightModelf( GLenum pname, GLfloat param ) { + return glLightModelf(pname, param); +} + +static void AmiglLightModeli( GLenum pname, GLint param ) { + return glLightModeli(pname, param); +} + +static void AmiglLightModelfv( GLenum pname, GLfloat *params ) { + return glLightModelfv(pname, params); +} + +static void AmiglLightModeliv( GLenum pname, const GLint *params ) { + return glLightModeliv(pname, params); +} + +static void AmiglMaterialf( GLenum face, GLenum pname, GLfloat param ) { + return glMaterialf(face, pname, param); +} + +static void AmiglMateriali( GLenum face, GLenum pname, GLint param ) { + return glMateriali(face, pname, param); +} + +static void AmiglMaterialfv( GLenum face, GLenum pname, GLfloat *params ) { + return glMaterialfv(face, pname, params); +} + +static void AmiglMaterialiv( GLenum face, GLenum pname, const GLint *params ) { + return glMaterialiv(face, pname, params); +} + +static void AmiglGetMaterialfv( GLenum face, GLenum pname, GLfloat *params ) { + return glGetMaterialfv(face, pname, params); +} + +static void AmiglGetMaterialiv( GLenum face, GLenum pname, GLint *params ) { + return glGetMaterialiv(face, pname, params); +} + +static void AmiglColorMaterial( GLenum face, GLenum mode ) { + return glColorMaterial(face, mode); +} + +static void AmiglPixelZoom( GLfloat xfactor, GLfloat yfactor ) { + return glPixelZoom(xfactor, yfactor); +} + +static void AmiglPixelStoref( GLenum pname, GLfloat param ) { + return glPixelStoref(pname, param); +} + +static void AmiglPixelStorei( GLenum pname, GLint param ) { + return glPixelStorei(pname, param); +} + +static void AmiglPixelTransferf( GLenum pname, GLfloat param ) { + return glPixelTransferf(pname, param); +} + +static void AmiglPixelTransferi( GLenum pname, GLint param ) { + return glPixelTransferi(pname, param); +} + +static void AmiglBitmap( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap ) { + return glBitmap(width, height, xorig, yorig, xmove, ymove, bitmap); +} + +static void AmiglReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) { + return glReadPixels(x, y, width, height, format, type, pixels); +} + +static void AmiglDrawPixels( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ) { + return glDrawPixels(width, height, format, type, pixels); +} + +static void AmiglCopyPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum type ) { + return glCopyPixels(x, y, width, height, type); +} + +static void AmiglStencilFunc( GLenum func, GLint ref, GLuint mask ) { + return glStencilFunc(func, ref, mask); +} + +static void AmiglStencilMask( GLuint mask ) { + return glStencilMask(mask); +} + +static void AmiglStencilOp( GLenum fail, GLenum zfail, GLenum zpass ) { + return glStencilOp(fail, zfail, zpass); +} + +static void AmiglClearStencil( GLint s ) { + return glClearStencil(s); +} + +static void AmiglTexGeni( GLenum coord, GLenum pname, GLint param ) { + return glTexGeni(coord, pname, param); +} + +static void AmiglTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) { + return glTexGenfv(coord, pname, params); +} + +static void AmiglTexEnvf( GLenum target, GLenum pname, GLfloat param ) { + return glTexEnvf(target, pname, param); +} + +static void AmiglTexEnvi( GLenum target, GLenum pname, GLint param ) { + return glTexEnvi(target, pname, param); +} + +static void AmiglTexEnvfv( GLenum target, GLenum pname, const GLfloat *params ) { + return glTexEnvfv(target, pname, params); +} + +static void AmiglTexEnviv( GLenum target, GLenum pname, GLint *params ) { + return glTexEnviv(target, pname, params); +} + +static void AmiglGetTexEnviv( GLenum target, GLenum pname, GLint *params ) { + return glGetTexEnviv(target, pname, params); +} + +static void AmiglTexParameterf( GLenum target, GLenum pname, GLfloat param ) { + return glTexParameterf(target, pname, param); +} + +static void AmiglTexParameteri( GLenum target, GLenum pname, GLint param ) { + return glTexParameteri(target, pname, param); +} + +static void AmiglTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) { + return glTexParameterfv(target, pname, params); +} + +static void AmiglTexParameteriv( GLenum target, GLenum pname, GLint *params ) { + return glTexParameteriv(target, pname, params); +} + +static void AmiglGetTexParameterfv( GLenum target, GLenum pname, GLfloat *params) { + return glGetTexParameterfv(target, pname, params); +} + +static void AmiglGetTexParameteriv( GLenum target, GLenum pname, GLint *params ) { + return glGetTexParameteriv(target, pname, params); +} + +static void AmiglGetTexLevelParameterfv( GLenum target, GLint level, GLenum pname, GLfloat *params ) { + return glGetTexLevelParameterfv(target, level, pname, params); +} + +static void AmiglGetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) { + return glGetTexLevelParameteriv(target, level, pname, params); +} + +static void AmiglTexImage1D( GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) { + return glTexImage1D(target, level, internalFormat, width, border, format, type, pixels); +} + +static void AmiglTexImage2D( GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLvoid *pixels ) { + return glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); +} + +static void AmiglGetTexImage( GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels ) { + return glGetTexImage(target, level, format, type, pixels); +} + +static void AmiglGenTextures( GLsizei n, GLuint *textures ) { + return glGenTextures(n, textures); +} + +static void AmiglDeleteTextures( GLsizei n, const GLuint *textures) { + return glDeleteTextures(n, textures); +} + +static void AmiglBindTexture( GLenum target, GLuint texture ) { + return glBindTexture(target, texture); +} + +static void AmiglPrioritizeTextures( GLsizei n, const GLuint *textures, const GLclampf *priorities ) { + return glPrioritizeTextures(n, textures, priorities); +} + +static GLboolean AmiglAreTexturesResident( GLsizei n, GLuint *textures, GLboolean *residences ) { + return glAreTexturesResident(n, textures, residences); +} + +static GLboolean AmiglIsTexture( GLuint texture ) { + return glIsTexture(texture); +} + +static void AmiglTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels ) { + return glTexSubImage1D(target, level, xoffset, width, format, type, pixels); +} + +static void AmiglTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ) { + return glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +static void AmiglCopyTexImage1D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border ) { + return glCopyTexImage1D(target, level, internalformat, x, y, width, border); +} + +static void AmiglCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { + return glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} + +static void AmiglCopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ) { + return glCopyTexSubImage1D(target, level, xoffset, x, y, width); +} + +static void AmiglCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { + return glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +static void AmiglMap1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points ) { + return glMap1d(target, u1, u2, stride, order, points); +} + +static void AmiglMap1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ) { + return glMap1f(target, u1, u2, stride, order, points); +} + +static void AmiglMap2d( GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points ) { + return glMap2d(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points); +} + +static void AmiglMap2f( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points ) { + return glMap2f(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points); + } + +static void AmiglGetMapdv( GLenum target, GLenum query, GLdouble *v ) { + return glGetMapdv(target, query, v); +} + +static void AmiglGetMapfv( GLenum target, GLenum query, GLfloat *v ) { + return glGetMapfv(target, query, v); +} + +static void AmiglGetMapiv( GLenum target, GLenum query, GLint *v ) { + return glGetMapiv(target, query, v); +} + +static void AmiglEvalCoord1d( GLdouble u ) { + return glEvalCoord1d(u); +} + +static void AmiglEvalCoord1f( GLfloat u ) { + return glEvalCoord1f(u); +} + +static void AmiglEvalCoord1dv( GLdouble *u ) { + return glEvalCoord1dv(u); +} + +static void AmiglEvalCoord1fv( GLfloat *u ) { + return glEvalCoord1fv(u); +} + +static void AmiglEvalCoord2d( GLdouble u, GLdouble v ) { + return glEvalCoord2d(u, v); +} + +static void AmiglEvalCoord2f( GLfloat u, GLfloat v ) { + return glEvalCoord2f(u, v); +} + +static void AmiglEvalCoord2dv( GLdouble *u ) { + return glEvalCoord2dv(u); +} + +static void AmiglEvalCoord2fv( GLfloat *u ) { + return glEvalCoord2fv(u); +} + +static void AmiglMapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) { + return glMapGrid1d(un, u1, u2); +} + +static void AmiglMapGrid1f( GLint un, GLfloat u1, GLfloat u2 ) { + return glMapGrid1f(un, u1, u2); +} + +static void AmiglMapGrid2d( GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2 ) { + return glMapGrid2d(un, u1, u2, vn, v1, v2); +} + +static void AmiglMapGrid2f( GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2 ) { + return glMapGrid2f(un, u1, u2, vn, v1, v2); +} + +static void AmiglEvalPoint1( GLint i ) { + return glEvalPoint1(i); +} + +static void AmiglEvalPoint2( GLint i, GLint j ) { + return glEvalPoint2(i, j); +} + +static void AmiglEvalMesh1( GLenum mode, GLint i1, GLint i2 ) { + return glEvalMesh1(mode, i1, i2); +} + +static void AmiglEvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ) { + return glEvalMesh2(mode, i1, i2, j1, j2); +} + +static void AmiglFogf( GLenum pname, GLfloat param ) { + return glFogf(pname, param); +} + +static void AmiglFogi( GLenum pname, GLint param ) { + return glFogi(pname, param); +} + +static void AmiglFogfv( GLenum pname, GLfloat *params ) { + return glFogfv(pname, params); +} + +static void AmiglSelectBuffer( GLsizei size, GLuint *buffer ) { + return glSelectBuffer(size, buffer); +} + +static void AmiglInitNames( void ) { + return glInitNames(); +} + +static void AmiglLoadName( GLuint name ) { + return glLoadName(name); +} + +static void AmiglPushName( GLuint name ) { + return glPushName(name); +} + +static void AmiglPopName( void ) { + return glPopName(); +} + +static void AmiglDrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLvoid *indices ) { + return glDrawRangeElements(mode, start, end, count, type, indices); +} + +static void AmiglLockArraysEXT( GLint first, GLint count ) { + return glLockArraysEXT(first, count); +} + +static void AmiglUnlockArraysEXT( void ) { + return glUnlockArraysEXT(); +} + +/* The GLU API */ + +/* + * + * GLU + * + */ + +static void AmigluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz ) { + return gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz); +} + +static void AmigluOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) { + return gluOrtho2D(left, right, bottom, top); +} + +static void AmigluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) { + return gluPerspective(fovy, aspect, zNear, zFar); +} + +static void AmigluPickMatrix( GLdouble x, GLdouble y, GLdouble width, GLdouble height, const GLint viewport[4] ) { + return gluPickMatrix(x, y, width, height, (GLint *)viewport); +} + +static GLint AmigluProject( GLdouble objx, GLdouble objy, GLdouble objz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *winx, GLdouble *winy, GLdouble *winz ) { + return gluProject(objx, objy, objz, modelMatrix, projMatrix, viewport, winx, winy, winz); +} + +static GLint AmigluUnProject( GLdouble winx, GLdouble winy, GLdouble winz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *objx, GLdouble *objy, GLdouble *objz ) { + return gluUnProject(winx, winy, winz, modelMatrix, projMatrix, viewport, objx, objy, objz); +} + +static const GLubyte* AmigluErrorString( GLenum errorCode ) { + return gluErrorString(errorCode); +} + +static GLint AmigluScaleImage( GLenum format, GLint widthin, GLint heightin, GLenum typein, const void *datain, GLint widthout, GLint heightout, GLenum typeout, void *dataout ) { + return gluScaleImage(format, widthin, heightin, typein, datain, widthout, heightout, typeout, dataout); +} + +#if 0 +static GLint AmigluBuild1DMipmaps( GLenum target, GLint components, GLint width, GLenum format, GLenum type, const void *data ) { +#ifndef __amigaos4__ + return gluBuild1DMipmaps(target, components, width, format, type, data); +#else + return 0; +#endif +} +#endif + +static GLint AmigluBuild2DMipmaps( GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, void *data ) { + return gluBuild2DMipmaps(target, components, width, height, format, type, data); +} + +static GLUquadricObj* AmigluNewQuadric( void ) { + return gluNewQuadric(); +} + +static void AmigluDeleteQuadric( GLUquadricObj *state ) { + return gluDeleteQuadric(state); +} + +static void AmigluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle ) { + return gluQuadricDrawStyle(quadObject, drawStyle); +} + +static void AmigluQuadricOrientation( GLUquadricObj *quadObject, GLenum orientation ) { + return gluQuadricOrientation(quadObject, orientation); +} + +static void AmigluQuadricNormals( GLUquadricObj *quadObject, GLenum normals ) { + return gluQuadricNormals(quadObject, normals); +} + +static void AmigluQuadricTexture( GLUquadricObj *quadObject, GLboolean textureCoords ) { + return gluQuadricTexture(quadObject, textureCoords); +} + +static void AmigluQuadricCallback( GLUquadricObj *qobj, GLenum which, void *fn) { + return gluQuadricCallback(qobj, which, fn); +} + +static void AmigluCylinder( GLUquadricObj *qobj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks ) { + return gluCylinder(qobj, baseRadius, topRadius, height, slices, stacks); +} + +static void AmigluSphere( GLUquadricObj *qobj, GLdouble radius, GLint slices, GLint stacks ) { + return gluSphere(qobj, radius, slices, stacks); +} + +static void AmigluDisk( GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops ) { + return gluDisk(qobj, innerRadius, outerRadius, slices, loops); +} + +static void AmigluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops, GLdouble startAngle, GLdouble sweepAngle ) { + return gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, startAngle, sweepAngle); +} + +static GLUnurbsObj* AmigluNewNurbsRenderer( void ) { + return gluNewNurbsRenderer(); +} + +static void AmigluDeleteNurbsRenderer( GLUnurbsObj *nobj ) { + return gluDeleteNurbsRenderer(nobj); +} + +static void AmigluLoadSamplingMatrices( GLUnurbsObj *nobj, const GLfloat modelMatrix[16], const GLfloat projMatrix[16], const GLint viewport[4] ) { + return gluLoadSamplingMatrices(nobj, modelMatrix, projMatrix, viewport); +} + +static void AmigluNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat value ) { + return gluNurbsProperty(nobj, property, value); +} + +static void AmigluGetNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat *value ) { + return gluGetNurbsProperty(nobj, property, value); +} + +static void AmigluBeginCurve( GLUnurbsObj *nobj ) { + return gluBeginCurve(nobj); +} + +static void AmigluEndCurve( GLUnurbsObj * nobj ) { + return gluEndCurve(nobj); +} + +static void AmigluNurbsCurve( GLUnurbsObj *nobj, GLint nknots, GLfloat *knot, GLint stride, GLfloat *ctlarray, GLint order, GLenum type ) { + return gluNurbsCurve(nobj, nknots, knot, stride, ctlarray, order, type); +} + +static void AmigluBeginSurface( GLUnurbsObj *nobj ) { + return gluBeginSurface(nobj); +} + +static void AmigluEndSurface( GLUnurbsObj * nobj ) { + return gluEndSurface(nobj); +} + +static void AmigluNurbsSurface( GLUnurbsObj *nobj, GLint sknot_count, GLfloat *sknot, GLint tknot_count, GLfloat *tknot, GLint s_stride, GLint t_stride, GLfloat *ctlarray, GLint sorder, GLint torder, GLenum type ) { + return gluNurbsSurface(nobj, sknot_count, sknot, tknot_count, tknot, s_stride, t_stride, ctlarray, sorder, torder, type); +} + +static void AmigluBeginTrim( GLUnurbsObj *nobj ) { + return gluBeginTrim(nobj); +} + +static void AmigluEndTrim( GLUnurbsObj *nobj ) { + return gluEndTrim(nobj); +} + +static void AmigluPwlCurve( GLUnurbsObj *nobj, GLint count, GLfloat *array, GLint stride, GLenum type ) { + return gluPwlCurve(nobj, count, array, stride, type); +} + +static void AmigluNurbsCallback( GLUnurbsObj *nobj, GLenum which, void *fn ) { + return gluNurbsCallback(nobj, which, fn); +} + +static GLUtriangulatorObj* AmigluNewTess( void ) { + return gluNewTess(); +} + +static void AmigluTessCallback( GLUtriangulatorObj *tobj, GLenum which, void *fn ) { + return gluTessCallback(tobj, which, fn); +} + +static void AmigluDeleteTess( GLUtriangulatorObj *tobj ) { + return gluDeleteTess(tobj); +} + +static void AmigluBeginPolygon( GLUtriangulatorObj *tobj ) { + return gluBeginPolygon(tobj); +} + +static void AmigluEndPolygon( GLUtriangulatorObj *tobj ) { + return gluEndPolygon(tobj); +} + +static void AmigluNextContour( GLUtriangulatorObj *tobj, GLenum type ) { + return gluNextContour(tobj, type); +} + +static void AmigluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], void *data ) { + return gluTessVertex(tobj, v, data); +} + +static void AmigluTessProperty(GLUtesselator* tess, GLenum which, GLdouble data) { + return gluTessProperty(tess, which, data); +} + +static void AmigluTessNormal(GLUtesselator* tess, GLdouble X, GLdouble Y, GLdouble Z) { + return gluTessNormal(tess, X, Y, Z); +} + +static void AmigluGetTessProperty(GLUtesselator* tess, GLenum which, GLdouble* data) { + return gluGetTessProperty(tess, which, data); +} + +static void AmigluTessBeginPolygon(GLUtesselator* tess, GLvoid* data) { + return gluTessBeginPolygon(tess, data); +} + +static void AmigluTessEndPolygon(GLUtesselator* tess) { + return gluTessEndPolygon(tess); +} + +static void AmigluTessBeginContour(GLUtesselator* tess) { + return gluTessBeginContour(tess); +} + +static void AmigluTessEndContour(GLUtesselator* tess) { + return gluTessEndContour(tess); +} + +static GLint AmigluBuild2DMipmapLevels(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, const void *data) { + return gluBuild2DMipmapLevels(target, internalFormat, width, height, format, type, level, base, max, data); +} + +static GLint AmigluUnProject4(GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, const GLdouble *model, const GLdouble *proj, const GLint *view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW) { + return gluUnProject4(winX, winY, winZ, clipW, model, proj, view, nearVal, farVal, objX, objY, objZ, objW); +} + +static GLboolean AmigluCheckExtension(const GLubyte *extName, const GLubyte *extString) { + return gluCheckExtension(extName, extString); +} + +static const GLubyte* AmigluGetString( GLenum name ) { + return gluGetString(name); +} + +static void AmigluNurbsCallbackData (GLUnurbs* r, void* userData) { + return gluNurbsCallbackData (r, userData); +} + +static void AmigluNurbsCallbackDataEXT(GLUnurbs* nurb, GLvoid* userData) { + return gluNurbsCallbackDataEXT(nurb, userData); +} + +#ifdef NOT_IMPLEMENTED_FUNCS + #include "SDL_os4_notimplemented_funcs.t" +#endif + +struct MyGLFunc +{ + CONST_STRPTR name; + APTR func; +}; + +void *AmiGetGLProc(const char *proc) +{ + static CONST struct MyGLFunc table[] = { + {"glClipPlane", AmiglClipPlane}, + {"glPolygonOffset", AmiglPolygonOffset}, + {"glTexEnviv", AmiglTexEnviv}, + {"glTexEnvfv", AmiglTexEnvfv}, + {"glGetTexEnviv", AmiglGetTexEnviv}, + {"glGetBooleanv", AmiglGetBooleanv}, + {"glGetIntegerv", AmiglGetIntegerv}, + {"glIsEnabled", AmiglIsEnabled}, + {"glAlphaFunc", AmiglAlphaFunc}, + {"glBegin", AmiglBegin}, + {"glBindTexture", AmiglBindTexture}, + {"glBlendFunc", AmiglBlendFunc}, + {"glClear", AmiglClear}, + {"glClearColor", AmiglClearColor}, + {"glClearDepth", AmiglClearDepth}, + {"glColor3b", AmiglColor3b}, + {"glColor3ub", AmiglColor3ub}, + {"glColor3bv", AmiglColor3bv}, + {"glColor3ubv", AmiglColor3ubv}, + {"glColor3s", AmiglColor3s}, + {"glColor3us", AmiglColor3us}, + {"glColor3sv", AmiglColor3sv}, + {"glColor3usv", AmiglColor3usv}, + {"glColor3i", AmiglColor3i}, + {"glColor3ui", AmiglColor3ui}, + {"glColor3iv", AmiglColor3iv}, + {"glColor3uiv", AmiglColor3uiv}, + {"glColor3f", AmiglColor3f}, + {"glColor3fv", AmiglColor3fv}, + {"glColor3d", AmiglColor3d}, + {"glColor3dv", AmiglColor3dv}, + {"glColor4b", AmiglColor4b}, + {"glColor4ub", AmiglColor4ub}, + {"glColor4bv", AmiglColor4bv}, + {"glColor4ubv", AmiglColor4ubv}, + {"glColor4s", AmiglColor4s}, + {"glColor4us", AmiglColor4us}, + {"glColor4sv", AmiglColor4sv}, + {"glColor4usv", AmiglColor4usv}, + {"glColor4i", AmiglColor4i}, + {"glColor4ui", AmiglColor4ui}, + {"glColor4iv", AmiglColor4iv}, + {"glColor4uiv", AmiglColor4uiv}, + {"glColor4f", AmiglColor4f}, + {"glColor4fv", AmiglColor4fv}, + {"glColor4d", AmiglColor4d}, + {"glColor4dv", AmiglColor4dv}, + {"glCullFace", AmiglCullFace}, + {"glVertex2s", AmiglVertex2s}, + {"glVertex2i", AmiglVertex2i}, + {"glVertex2f", AmiglVertex2f}, + {"glVertex2d", AmiglVertex2d}, + {"glVertex3s", AmiglVertex3s}, + {"glVertex3i", AmiglVertex3i}, + {"glVertex3f", AmiglVertex3f}, + {"glVertex3d", AmiglVertex3d}, + {"glVertex4s", AmiglVertex4s}, + {"glVertex4i", AmiglVertex4i}, + {"glVertex4f", AmiglVertex4f}, + {"glVertex4d", AmiglVertex4d}, + {"glVertex2sv", AmiglVertex2sv}, + {"glVertex2iv", AmiglVertex2iv}, + {"glVertex2fv", AmiglVertex2fv}, + {"glVertex2dv", AmiglVertex2dv}, + {"glVertex3sv", AmiglVertex3sv}, + {"glVertex3iv", AmiglVertex3iv}, + {"glVertex3fv", AmiglVertex3fv}, + {"glVertex3dv", AmiglVertex3dv}, + {"glVertex4sv", AmiglVertex4sv}, + {"glVertex4iv", AmiglVertex4iv}, + {"glVertex4fv", AmiglVertex4fv}, + {"glVertex4dv", AmiglVertex4dv}, + {"glDeleteTextures", AmiglDeleteTextures}, + {"glDepthFunc", AmiglDepthFunc}, + {"glDepthMask", AmiglDepthMask}, + {"glDepthRange", AmiglDepthRange}, + {"glDisable", AmiglDisable}, + {"glDrawBuffer", AmiglDrawBuffer}, + {"glEnable", AmiglEnable}, + {"glEnd", AmiglEnd}, + {"glFinish", AmiglFinish}, + {"glFlush", AmiglFlush}, + {"glFogf", AmiglFogf}, + {"glFogi", AmiglFogi}, + {"glFogfv", AmiglFogfv}, + {"glFrontFace", AmiglFrontFace}, + {"glFrustum", AmiglFrustum}, + {"glGenTextures", AmiglGenTextures}, + {"glGetError", AmiglGetError}, + {"glGetFloatv", AmiglGetFloatv}, + {"glGetString", AmiglGetString}, + {"glHint", AmiglHint}, + {"glLoadIdentity", AmiglLoadIdentity}, + {"glLoadMatrixd", AmiglLoadMatrixd}, + {"glLoadMatrixf", AmiglLoadMatrixf}, + {"glMatrixMode", AmiglMatrixMode}, + {"glMultMatrixd", AmiglMultMatrixd}, + {"glMultMatrixf", AmiglMultMatrixf}, + {"glNormal3f", AmiglNormal3f}, + {"glNormal3d", AmiglNormal3d}, + {"glNormal3i", AmiglNormal3i}, + {"glNormal3s", AmiglNormal3s}, + {"glNormal3b", AmiglNormal3b}, + {"glNormal3fv", AmiglNormal3fv}, + {"glNormal3dv", AmiglNormal3dv}, + {"glNormal3iv", AmiglNormal3iv}, + {"glNormal3sv", AmiglNormal3sv}, + {"glNormal3bv", AmiglNormal3bv}, + {"glOrtho", AmiglOrtho}, + {"glPixelStorei", AmiglPixelStorei}, + {"glPixelStoref", AmiglPixelStoref}, + {"glPolygonMode", AmiglPolygonMode}, + {"glPopMatrix", AmiglPopMatrix}, + {"glPushMatrix", AmiglPushMatrix}, + {"glReadPixels", AmiglReadPixels}, + {"glRectf", AmiglRectf}, + {"glRects", AmiglRects}, + {"glRecti", AmiglRecti}, + {"glRectd", AmiglRectd}, + {"glRectsv", AmiglRectsv}, + {"glRectiv", AmiglRectiv}, + {"glRectfv", AmiglRectfv}, + {"glRectdv", AmiglRectdv}, + {"glRotatef", AmiglRotatef}, + {"glRotated", AmiglRotated}, + {"glScalef", AmiglScalef}, + {"glScaled", AmiglScaled}, + {"glScissor", AmiglScissor}, + {"glShadeModel", AmiglShadeModel}, + {"glTexCoord1f", AmiglTexCoord1f}, + {"glTexCoord1d", AmiglTexCoord1d}, + {"glTexCoord1i", AmiglTexCoord1i}, + {"glTexCoord2f", AmiglTexCoord2f}, + {"glTexCoord2d", AmiglTexCoord2d}, + {"glTexCoord2i", AmiglTexCoord2i}, + {"glTexCoord2fv", AmiglTexCoord2fv}, + {"glTexCoord2iv", AmiglTexCoord2iv}, + {"glTexCoord3f", AmiglTexCoord3f}, + {"glTexCoord3fv", AmiglTexCoord3fv}, + {"glTexCoord4f", AmiglTexCoord4f}, + {"glTexCoord4fv", AmiglTexCoord4fv}, + {"glTexEnvf", AmiglTexEnvf}, + {"glTexEnvi", AmiglTexEnvi}, + {"glTexGeni", AmiglTexGeni}, + {"glTexGenfv", AmiglTexGenfv}, + {"glTexImage1D", AmiglTexImage1D}, + {"glTexImage2D", AmiglTexImage2D}, + {"glTexParameteri", AmiglTexParameteri}, + {"glTexParameterf", AmiglTexParameterf}, + {"glTexParameterfv", AmiglTexParameterfv}, + {"glTexParameteriv", AmiglTexParameteriv}, + {"glTexSubImage1D", AmiglTexSubImage1D}, + {"glTexSubImage2D", AmiglTexSubImage2D}, + {"glTranslated", AmiglTranslated}, + {"glTranslatef", AmiglTranslatef}, + {"glViewport", AmiglViewport}, + {"glColorTable", AmiglColorTable}, + {"glColorTableEXT", AmiglColorTableEXT}, + {"glEnableClientState", AmiglEnableClientState}, + {"glDisableClientState", AmiglDisableClientState}, + {"glClientActiveTexture", AmiglClientActiveTexture}, + {"glClientActiveTextureARB", AmiglClientActiveTextureARB}, + {"glTexCoordPointer", AmiglTexCoordPointer}, + {"glColorPointer", AmiglColorPointer}, + {"glNormalPointer", AmiglNormalPointer}, + {"glVertexPointer", AmiglVertexPointer}, + {"glInterleavedArrays", AmiglInterleavedArrays}, + {"glDrawElements", AmiglDrawElements}, + {"glDrawArrays", AmiglDrawArrays}, + {"glArrayElement", AmiglArrayElement}, + {"glLockArraysEXT", AmiglLockArraysEXT}, + {"glUnlockArraysEXT", AmiglUnlockArraysEXT}, + {"glPushAttrib", AmiglPushAttrib}, + {"glPopAttrib", AmiglPopAttrib}, + {"glActiveTextureARB", AmiglActiveTextureARB}, + {"glMultiTexCoord2fARB", AmiglMultiTexCoord2fARB}, + {"glMultiTexCoord2fvARB", AmiglMultiTexCoord2fvARB}, + {"glMultiTexCoord4fARB", AmiglMultiTexCoord4fARB}, + {"glMultiTexCoord4fvARB", AmiglMultiTexCoord4fvARB}, + {"glActiveTexture", AmiglActiveTexture}, + {"glMultiTexCoord2f", AmiglMultiTexCoord2f}, + {"glMultiTexCoord2fv", AmiglMultiTexCoord2fv}, + {"glMultiTexCoord4f", AmiglMultiTexCoord4f}, + {"glMultiTexCoord4fv", AmiglMultiTexCoord4fv}, + {"glMaterialf", AmiglMaterialf}, + {"glMateriali", AmiglMateriali}, + {"glMaterialfv", AmiglMaterialfv}, + {"glMaterialiv", AmiglMaterialiv}, + {"glGetMaterialiv", AmiglGetMaterialiv}, + {"glGetMaterialfv", AmiglGetMaterialfv}, + {"glLightf", AmiglLightf}, + {"glLighti", AmiglLighti}, + {"glLightfv", AmiglLightfv}, + {"glLightiv", AmiglLightiv}, + {"glLightModelf", AmiglLightModelf}, + {"glLightModeli", AmiglLightModeli}, + {"glLightModelfv", AmiglLightModelfv}, + {"glLightModeliv", AmiglLightModeliv}, + {"glColorMaterial", AmiglColorMaterial}, + {"glGetLightfv", AmiglGetLightfv}, + {"glGetLightiv", AmiglGetLightiv}, + {"glStencilOp", AmiglStencilOp}, + {"glStencilFunc", AmiglStencilFunc}, + {"glClearStencil", AmiglClearStencil}, + {"glStencilMask", AmiglStencilMask}, + {"glColorMask", AmiglColorMask}, + {"glLineWidth", AmiglLineWidth}, + {"glPointSize", AmiglPointSize}, + {"glBitmap", AmiglBitmap}, + {"glLineStipple", AmiglLineStipple}, + {"glPolygonStipple", AmiglPolygonStipple}, + {"glRasterPos2s", AmiglRasterPos2s}, + {"glRasterPos2i", AmiglRasterPos2i}, + {"glRasterPos2f", AmiglRasterPos2f}, + {"glRasterPos2d", AmiglRasterPos2d}, + {"glRasterPos3s", AmiglRasterPos3s}, + {"glRasterPos3i", AmiglRasterPos3i}, + {"glRasterPos3f", AmiglRasterPos3f}, + {"glRasterPos3d", AmiglRasterPos3d}, + {"glRasterPos4s", AmiglRasterPos4s}, + {"glRasterPos4i", AmiglRasterPos4i}, + {"glRasterPos4f", AmiglRasterPos4f}, + {"glRasterPos4d", AmiglRasterPos4d}, + {"glRasterPos2sv", AmiglRasterPos2sv}, + {"glRasterPos2iv", AmiglRasterPos2iv}, + {"glRasterPos2fv", AmiglRasterPos2fv}, + {"glRasterPos2dv", AmiglRasterPos2dv}, + {"glRasterPos3sv", AmiglRasterPos3sv}, + {"glRasterPos3iv", AmiglRasterPos3iv}, + {"glRasterPos3fv", AmiglRasterPos3fv}, + {"glRasterPos3dv", AmiglRasterPos3dv}, + {"glRasterPos4sv", AmiglRasterPos4sv}, + {"glRasterPos4iv", AmiglRasterPos4iv}, + {"glRasterPos4fv", AmiglRasterPos4fv}, + {"glRasterPos4dv", AmiglRasterPos4dv}, + {"glDrawPixels", AmiglDrawPixels}, + {"glCallList", AmiglCallList}, + {"glCallLists", AmiglCallLists}, + {"glDeleteLists", AmiglDeleteLists}, + {"glGenLists", AmiglGenLists}, + {"glNewList", AmiglNewList}, + {"glEndList", AmiglEndList}, + {"glIsList", AmiglIsList}, + {"glListBase", AmiglListBase}, + {"glGetDoublev", AmiglGetDoublev}, + {"glIsTexture", AmiglIsTexture}, + {"glAreTexturesResident", AmiglAreTexturesResident}, + {"glInitNames", AmiglInitNames}, + {"glLoadName", AmiglLoadName}, + {"glPushName", AmiglPushName}, + {"glPopName", AmiglPopName}, + {"glSelectBuffer", AmiglSelectBuffer}, + {"glRenderMode", AmiglRenderMode}, + {"glGetTexLevelParameterfv", AmiglGetTexLevelParameterfv}, + {"glGetTexLevelParameteriv", AmiglGetTexLevelParameteriv}, + {"glMap1f", AmiglMap1f}, + {"glMap1d", AmiglMap1d}, + {"glEvalCoord1f", AmiglEvalCoord1f}, + {"glEvalCoord1d", AmiglEvalCoord1d}, + {"glEvalCoord1fv", AmiglEvalCoord1fv}, + {"glEvalCoord1dv", AmiglEvalCoord1dv}, + {"glMapGrid1f", AmiglMapGrid1f}, + {"glMapGrid1d", AmiglMapGrid1d}, + {"glEvalMesh1", AmiglEvalMesh1}, + {"glEvalPoint1", AmiglEvalPoint1}, + {"glMap2f", AmiglMap2f}, + {"glMap2d", AmiglMap2d}, + {"glEvalCoord2f", AmiglEvalCoord2f}, + {"glEvalCoord2d", AmiglEvalCoord2d}, + {"glEvalCoord2fv", AmiglEvalCoord2fv}, + {"glEvalCoord2dv", AmiglEvalCoord2dv}, + {"glMapGrid2f", AmiglMapGrid2f}, + {"glMapGrid2d", AmiglMapGrid2d}, + {"glEvalMesh2", AmiglEvalMesh2}, + {"glEvalPoint2", AmiglEvalPoint2}, + {"glGetMapfv", AmiglGetMapfv}, + {"glGetMapdv", AmiglGetMapdv}, + {"glGetMapiv", AmiglGetMapiv}, + {"glPushClientAttrib", AmiglPushClientAttrib}, + {"glPopClientAttrib", AmiglPopClientAttrib}, + {"glPixelTransferi", AmiglPixelTransferi}, + {"glPixelTransferf", AmiglPixelTransferf}, + {"glGetTexImage", AmiglGetTexImage}, + {"glCopyTexImage1D", AmiglCopyTexImage1D}, + {"glCopyTexImage2D", AmiglCopyTexImage2D}, + {"glCopyTexSubImage1D", AmiglCopyTexSubImage1D}, + {"glCopyTexSubImage2D", AmiglCopyTexSubImage2D}, + {"glEdgeFlag", AmiglEdgeFlag}, + {"glReadBuffer", AmiglReadBuffer}, + {"glPrioritizeTextures", AmiglPrioritizeTextures}, + {"glDrawRangeElements", AmiglDrawRangeElements}, + {"glGetClipPlane", AmiglGetClipPlane}, + {"gluNewTess", AmigluNewTess}, + {"gluDeleteTess", AmigluDeleteTess}, + {"gluTessProperty", AmigluTessProperty}, + {"gluGetTessProperty", AmigluGetTessProperty}, + {"gluTessNormal", AmigluTessNormal}, + {"gluTessCallback", AmigluTessCallback}, + {"gluTessVertex", AmigluTessVertex}, + {"gluTessBeginPolygon", AmigluTessBeginPolygon}, + {"gluTessBeginContour", AmigluTessBeginContour}, + {"gluTessEndContour", AmigluTessEndContour}, + {"gluTessEndPolygon", AmigluTessEndPolygon}, + {"gluBeginPolygon", AmigluBeginPolygon}, + {"gluNextContour", AmigluNextContour}, + {"gluEndPolygon", AmigluEndPolygon}, + {"gluErrorString", AmigluErrorString}, + {"gluScaleImage", AmigluScaleImage}, + {"gluBuild2DMipmapLevels", AmigluBuild2DMipmapLevels}, + {"gluBuild2DMipmaps", AmigluBuild2DMipmaps}, + {"gluOrtho2D", AmigluOrtho2D}, + {"gluPerspective", AmigluPerspective}, + {"gluLookAt", AmigluLookAt}, + {"gluProject", AmigluProject}, + {"gluUnProject", AmigluUnProject}, + {"gluUnProject4", AmigluUnProject4}, + {"gluPickMatrix", AmigluPickMatrix}, + {"gluNewQuadric", AmigluNewQuadric}, + {"gluDeleteQuadric", AmigluDeleteQuadric}, + {"gluQuadricCallback", AmigluQuadricCallback}, + {"gluQuadricNormals", AmigluQuadricNormals}, + {"gluQuadricTexture", AmigluQuadricTexture}, + {"gluQuadricOrientation", AmigluQuadricOrientation}, + {"gluQuadricDrawStyle", AmigluQuadricDrawStyle}, + {"gluCylinder", AmigluCylinder}, + {"gluDisk", AmigluDisk}, + {"gluPartialDisk", AmigluPartialDisk}, + {"gluSphere", AmigluSphere}, + {"gluGetString", AmigluGetString}, + {"gluCheckExtension", AmigluCheckExtension}, + {"gluNurbsCallbackData", AmigluNurbsCallbackData}, + {"gluBeginCurve", AmigluBeginCurve}, + {"gluBeginSurface", AmigluBeginSurface}, + {"gluBeginTrim", AmigluBeginTrim}, + {"gluDeleteNurbsRenderer", AmigluDeleteNurbsRenderer}, + {"gluEndCurve", AmigluEndCurve}, + {"gluEndSurface", AmigluEndSurface}, + {"gluEndTrim", AmigluEndTrim}, + {"gluGetNurbsProperty", AmigluGetNurbsProperty}, + {"gluLoadSamplingMatrices", AmigluLoadSamplingMatrices}, + {"gluNewNurbsRenderer", AmigluNewNurbsRenderer}, + {"gluNurbsCallback", AmigluNurbsCallback}, + {"gluNurbsCallbackDataEXT", AmigluNurbsCallbackDataEXT}, + {"gluNurbsCurve", AmigluNurbsCurve}, + {"gluNurbsProperty", AmigluNurbsProperty}, + {"gluNurbsSurface", AmigluNurbsSurface}, + {"gluPwlCurve", AmigluPwlCurve}, + {"glGetTexParameteriv", AmiglGetTexParameteriv}, + {"glGetTexParameterfv", AmiglGetTexParameterfv}, + {"glPixelZoom", AmiglPixelZoom}, + {"glLogicOp", AmiglLogicOp}, + {"glCopyPixels", AmiglCopyPixels}, +#ifdef NOT_IMPLEMENTED_FUNCS + #include "SDL_os4_notimplemented_table.t" +#endif + { NULL, NULL } + }; + + CONST struct MyGLFunc *tb = table; + + do { + if (!strcmp(tb->name, proc)) { + return tb->func; + } + tb++; + } while (tb->name); + + return NULL; +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ diff --git a/src/video/amigaos4/SDL_os4shape.c b/src/video/amigaos4/SDL_os4shape.c new file mode 100644 index 0000000000000..aba81e0dde516 --- /dev/null +++ b/src/video/amigaos4/SDL_os4shape.c @@ -0,0 +1,350 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +/* NOTE: shaped windows need compositing enabled for the GUI! */ + +#include "SDL_os4video.h" +#include "SDL_os4shape.h" +#include "SDL_os4window.h" + +#include "SDL_shape.h" +#include "../SDL_shape_internals.h" +#include "SDL_assert.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +SDL_WindowShaper* +OS4_CreateShaper(SDL_Window * window) +{ + _THIS = SDL_GetVideoDevice(); + + SDL_WindowData *windowdata = window->driverdata; + SDL_WindowShaper *result = NULL; + LONG compositing = FALSE; + + dprintf("Called %p\n", window); + + IIntuition->GetScreenAttrs(windowdata->syswin->WScreen, + SA_Compositing, &compositing, + TAG_DONE); + + if (compositing) { + + result = SDL_malloc(sizeof(SDL_WindowShaper)); + + if (result) { + SDL_ShapeData *data = SDL_malloc(sizeof(SDL_ShapeData)); + + result->window = window; + result->mode.mode = ShapeModeDefault; + result->mode.parameters.binarizationCutoff = 1; + result->userx = 0; + result->usery = 0; + + if (data) { + int resized_properly; + + data->width = 0; + data->height = 0; + data->bitmap = NULL; + data->sysbm = NULL; + data->cliprect = NULL; + + result->driverdata = data; + + window->shaper = result; + resized_properly = OS4_ResizeWindowShape(window); + + SDL_assert(resized_properly == 0); + + } else { + dprintf("Failed to allocate driver data\n"); + SDL_free(result); + result = NULL; + } + + } else { + //SDL_SetError("Failed to create shaper"); + dprintf("Failed to create shaper\n"); + } + } else { + dprintf("Compositing not enabled!\n"); + } + + return result; +} + +static struct BitMap * +OS4_MakeAlphaBitMap(void * source, int width, int height) +{ + _THIS = SDL_GetVideoDevice(); + + struct BitMap *sysbm = IGraphics->AllocBitMapTags( + width, + height, + 8, + BMATags_PixelFormat, PIXF_ALPHA8, + BMATags_Displayable, TRUE, + TAG_DONE); + + dprintf("Creating alpha bitmap %d*%d, source %p\n", width, height, source); + + if (sysbm) { + uint32 bytesperrow; + APTR baseaddress; + + APTR lock = IGraphics->LockBitMapTags(sysbm, + LBM_BaseAddress, &baseaddress, + LBM_BytesPerRow, &bytesperrow, + TAG_DONE); + + if (lock) { + + int y; + + uint8 *src = source; + + for (y = 0; y < height; y++) { + + int x; + + uint8 *dst = (uint8 *)baseaddress + y * bytesperrow; + + for (x = 0; x < width; x++) { + *dst++ = *src++; + } + } + + IGraphics->UnlockBitMap(lock); + } else { + dprintf("Failed to lock bitmap\n"); + IGraphics->FreeBitMap(sysbm); + sysbm = NULL; + } + + } else { + dprintf("Couldn't allocate alpha bitmap\n"); + return NULL; + } + + return sysbm; +} + +static struct ClipRect* +OS4_SetAlphaLayer(struct Window * window, SDL_ShapeData * data) +{ + _THIS = SDL_GetVideoDevice(); + + struct ClipRect *cliprect; + struct ClipRect *oldCliprect = NULL; + + ILayers->LockLayerInfo(&window->WScreen->LayerInfo); + + if (data->cliprect) { + dprintf("Freeing old clip rect\n"); + ILayers->FreeClipRect(&window->WScreen->LayerInfo, data->cliprect); + } + + cliprect = ILayers->AllocClipRect(&window->WScreen->LayerInfo); + + if (cliprect) { + cliprect->BitMap = data->sysbm; + + // TODO: anything else to be done? + cliprect->bounds.MinX = 0; + cliprect->bounds.MinY = 0; + cliprect->bounds.MaxX = data->width - 1; + cliprect->bounds.MaxY = data->height - 1; + + oldCliprect = ILayers->ChangeLayerAlpha(window->WLayer, cliprect, NULL); + //IIntuition->SetWindowAttrs(window, WA_AlphaClips, cliprect, TAG_DONE); //TODO: which method is better? + } else { + dprintf("Failed to allocate cliprect\n"); + } + + ILayers->UnlockLayerInfo(&window->WScreen->LayerInfo); + + if (oldCliprect == (struct ClipRect *)-1) { + dprintf("Failed to install layer alpha\n"); + } + + return cliprect; //TODO +} + +void +OS4_DestroyShape(_THIS, SDL_Window * window) +{ + SDL_WindowShaper *shaper = window->shaper; + + dprintf("Called for '%s'\n", window->title); + + if (shaper && shaper->driverdata) { + + SDL_ShapeData *data = shaper->driverdata; + SDL_WindowData *windowdata = window->driverdata; + struct Window *syswin = windowdata->syswin; + + if (data->cliprect) { + ILayers->LockLayerInfo(&syswin->WScreen->LayerInfo); + + data->cliprect->BitMap = NULL; // TODO: is this valid approach?? + + dprintf("Freeing cliprect %p\n", data->cliprect); + + ILayers->FreeClipRect(&syswin->WScreen->LayerInfo, data->cliprect); + data->cliprect = NULL; + + ILayers->UnlockLayerInfo(&syswin->WScreen->LayerInfo); + } + + if (data->sysbm) { + dprintf("Freeing system bitmap %p\n", data->sysbm); + IGraphics->FreeBitMap(data->sysbm); + data->sysbm = NULL; + } + + if (data->bitmap) { + dprintf("Freeing SDL bitmap %p\n", data->bitmap); + SDL_free(data->bitmap); + data->bitmap = NULL; + } + + dprintf("Freeing shape data %p\n", data); + + SDL_free(data); + shaper->driverdata = NULL; + } else { + dprintf("No shaper or shape data\n"); + return; + } + +} + +int +OS4_SetWindowShape(SDL_WindowShaper * shaper, SDL_Surface * shape, SDL_WindowShapeMode * shape_mode) +{ + if (shaper && shape && shape_mode && shaper->driverdata) { + + SDL_ShapeData *data = shaper->driverdata; + SDL_WindowData *windowdata = shaper->window->driverdata; + + if (shape->format->Amask == 0 && SDL_SHAPEMODEALPHA(shape_mode->mode)) { + dprintf("Shape doesn't have alpha channel\n"); + return -2; + } + + if (shape->w != shaper->window->w || shape->h != shaper->window->h) { + + dprintf("Shape dimensions don't match window dimensions\n"); + return -3; + } + + if (data->bitmap) { + SDL_CalculateShapeBitmap(shaper->mode, shape, data->bitmap, 1); + + if (! (data->sysbm = OS4_MakeAlphaBitMap(data->bitmap, shape->w, shape->h))) { + dprintf("Couldn't allocate alpha bitmap\n"); + return -4; + } + + dprintf("Freeing temporary SDL bitmap %p\n", data->bitmap); + + SDL_free(data->bitmap); + data->bitmap = NULL; + + if (! (data->cliprect = OS4_SetAlphaLayer(windowdata->syswin, data))) { + dprintf("Failed to allocate clip rect\n"); + return -5; + } + + dprintf("New alpha layer applied for window '%s'\n", shaper->window->title); + + return 0; + + } else { + dprintf("NULL source bitmap\n"); + return -6; + } + + } else { + dprintf("No shaper, shape or shape_mode\n"); + return -7; + } +} + +int +OS4_ResizeWindowShape(SDL_Window * window) +{ + if (window->shaper) { + + SDL_ShapeData *data = window->shaper->driverdata; + + if (data) { + int width, height; + + OS4_GetWindowActiveSize(window, &width, &height); + + dprintf("Called for '%s'\n", window->title); + + if (data->width != width || + data->height != height || data->bitmap == NULL) { + + Uint32 bitmapsize = width * height; + + data->width = width; + data->height = height; + + if (data->bitmap) { + SDL_free(data->bitmap); + } + + data->bitmap = SDL_malloc(bitmapsize); + + if (data->bitmap) { + SDL_memset(data->bitmap, 0, bitmapsize); + } else { + dprintf("Failed to allocate SDL bitmap\n"); + return SDL_SetError("Could not allocate memory for shaped-window bitmap"); + } + } + + window->shaper->userx = window->x; + window->shaper->usery = window->y; + //SDL_SetWindowPosition(window, -1000, -1000);//?? + + return 0; + } else { + dprintf("No shape data\n"); + return -1; + } + } else { + dprintf("No shaper\n"); + return -1; + } +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4shape.h b/src/video/amigaos4/SDL_os4shape.h new file mode 100644 index 0000000000000..26711ee73be0e --- /dev/null +++ b/src/video/amigaos4/SDL_os4shape.h @@ -0,0 +1,42 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4shape_h +#define _SDL_os4shape_h + +typedef struct { + struct BitMap* sysbm; + struct ClipRect* cliprect; + void* bitmap; + int width; + int height; +} SDL_ShapeData; + +extern SDL_WindowShaper* OS4_CreateShaper(SDL_Window * window); +extern int OS4_SetWindowShape(SDL_WindowShaper * shaper, SDL_Surface * shape, SDL_WindowShapeMode * shape_mode); +extern int OS4_ResizeWindowShape(SDL_Window * window); + +extern void OS4_DestroyShape(_THIS, SDL_Window * window); + +#endif /* _SDL_os4shape_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4video.c b/src/video/amigaos4/SDL_os4video.c new file mode 100644 index 0000000000000..806055a0f0ffb --- /dev/null +++ b/src/video/amigaos4/SDL_os4video.c @@ -0,0 +1,601 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include + +#include "SDL_video.h" +#include "SDL_hints.h" +#include "SDL_version.h" + +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" + +#include "SDL_os4video.h" +#include "SDL_os4events.h" +#include "SDL_os4framebuffer.h" +#include "SDL_os4mouse.h" +#include "SDL_os4opengl.h" +#include "SDL_os4opengles.h" +#include "SDL_os4shape.h" +#include "SDL_os4messagebox.h" +#include "SDL_os4modes.h" +#include "SDL_os4keyboard.h" +#include "SDL_os4library.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +#define OS4VID_DRIVER_NAME "os4" + +static int OS4_VideoInit(_THIS); +static void OS4_VideoQuit(_THIS); + +SDL_bool (*OS4_ResizeGlContext)(_THIS, SDL_Window * window) = NULL; +void (*OS4_UpdateGlWindowPointer)(_THIS, SDL_Window * window) = NULL; + +#define MIN_LIB_VERSION 51 + +static SDL_bool +OS4_OpenLibraries(_THIS) +{ + dprintf("Opening libraries\n"); + + GfxBase = OS4_OpenLibrary("graphics.library", 54); + LayersBase = OS4_OpenLibrary("layers.library", 53); + IntuitionBase = OS4_OpenLibrary("intuition.library", MIN_LIB_VERSION); + IconBase = OS4_OpenLibrary("icon.library", MIN_LIB_VERSION); + WorkbenchBase = OS4_OpenLibrary("workbench.library", MIN_LIB_VERSION); + KeymapBase = OS4_OpenLibrary("keymap.library", MIN_LIB_VERSION); + TextClipBase = OS4_OpenLibrary("textclip.library", MIN_LIB_VERSION); + DOSBase = OS4_OpenLibrary("dos.library", MIN_LIB_VERSION); + + if (GfxBase && LayersBase && IntuitionBase && IconBase && + WorkbenchBase && KeymapBase && TextClipBase && DOSBase) { + + IGraphics = (struct GraphicsIFace *) OS4_GetInterface(GfxBase); + ILayers = (struct LayersIFace *) OS4_GetInterface(LayersBase); + IIntuition = (struct IntuitionIFace *) OS4_GetInterface(IntuitionBase); + IIcon = (struct IconIFace *) OS4_GetInterface(IconBase); + IWorkbench = (struct WorkbenchIFace *) OS4_GetInterface(WorkbenchBase); + IKeymap = (struct KeymapIFace *) OS4_GetInterface(KeymapBase); + ITextClip = (struct TextClipIFace *) OS4_GetInterface(TextClipBase); + IDOS = (struct DOSIFace *) OS4_GetInterface(DOSBase); + + if (IGraphics && ILayers && IIntuition && IIcon && + IWorkbench && IKeymap && ITextClip && IDOS) { + + dprintf("All library interfaces OK\n"); + + return SDL_TRUE; + + } else { + dprintf("Failed to get library interfaces\n"); + } + } else { + dprintf("Failed to open system libraries\n"); + } + + return SDL_FALSE; +} + +static void +OS4_CloseLibraries(_THIS) +{ + dprintf("Closing libraries\n"); + + OS4_DropInterface((void *)&IDOS); + OS4_DropInterface((void *)&ITextClip); + OS4_DropInterface((void *)&IKeymap); + OS4_DropInterface((void *)&IWorkbench); + OS4_DropInterface((void *)&IIcon); + OS4_DropInterface((void *)&IIntuition); + OS4_DropInterface((void *)&ILayers); + OS4_DropInterface((void *)&IGraphics); + + OS4_CloseLibrary(&DOSBase); + OS4_CloseLibrary(&TextClipBase); + OS4_CloseLibrary(&KeymapBase); + OS4_CloseLibrary(&WorkbenchBase); + OS4_CloseLibrary(&IconBase); + OS4_CloseLibrary(&IntuitionBase); + OS4_CloseLibrary(&LayersBase); + OS4_CloseLibrary(&GfxBase); +} + +static void +OS4_FindApplicationName(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + size_t size; + const size_t maxPathLen = 255; + char pathBuffer[maxPathLen]; + + if (IDOS->GetCliProgramName(pathBuffer, maxPathLen - 1)) { + dprintf("GetCliProgramName: '%s'\n", pathBuffer); + } else { + dprintf("Failed to get CLI program name, checking task node\n"); + + struct Task* me = IExec->FindTask(NULL); + SDL_snprintf(pathBuffer, maxPathLen, "%s", ((struct Node *)me)->ln_Name); + } + + size = SDL_strlen(pathBuffer) + 1; + + data->appName = SDL_malloc(size); + + if (data->appName) { + SDL_snprintf(data->appName, size, pathBuffer); + } + + dprintf("Application name: '%s'\n", data->appName); +} + +static SDL_bool +OS4_AllocSystemResources(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + dprintf("Called\n"); + + if (!OS4_OpenLibraries(_this)) { + return SDL_FALSE; + } + + OS4_FindApplicationName(_this); + + if (!(data->userPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE))) { + SDL_SetError("Couldn't allocate message port"); + return SDL_FALSE; + } + + if (!(data->appMsgPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE))) { + SDL_SetError("Couldn't allocate AppMsg port"); + return SDL_FALSE; + } + + /* Create the pool we'll be using (Shared, might be used from threads) */ + if (!(data->pool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, + ASOPOOL_MFlags, MEMF_SHARED, + ASOPOOL_Threshold, 16384, + ASOPOOL_Puddle, 16384, + ASOPOOL_Protected, TRUE, + TAG_DONE))) { + + SDL_SetError("Couldn't allocate pool"); + return SDL_FALSE; + } + + /* inputPort, inputReq and and input.device are created for WarpMouse functionality. (In SDL1 + they were created in library constructor for an unknown reason) */ + if (!(data->inputPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE))) { + + SDL_SetError("Couldn't allocate input port"); + return SDL_FALSE; + } + + if (!(data->inputReq = IExec->AllocSysObjectTags(ASOT_IOREQUEST, + ASOIOR_Size, sizeof(struct IOStdReq), + ASOIOR_ReplyPort, data->inputPort, + TAG_DONE))) { + + SDL_SetError("Couldn't allocate input request"); + return SDL_FALSE; + } + + if (IExec->OpenDevice("input.device", 0, (struct IORequest *)data->inputReq, 0)) + { + SDL_SetError("Couldn't open input.device"); + return SDL_FALSE; + } + + IInput = (struct InputIFace *)OS4_GetInterface((struct Library *)data->inputReq->io_Device); + if (!IInput) { + SDL_SetError("Failed to get IInput interface"); + return SDL_FALSE; + } + + return SDL_TRUE; +} + +static void +OS4_FreeSystemResources(_THIS) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + dprintf("Called\n"); + + OS4_DropInterface((void *)&IInput); + + if (data->inputReq) { + dprintf("Closing input.device\n"); + //IExec->AbortIO((struct IORequest *)data->inputReq); + //IExec->WaitIO((struct IORequest *)data->inputReq); + IExec->CloseDevice((struct IORequest *)data->inputReq); + + dprintf("Freeing IORequest\n"); + IExec->FreeSysObject(ASOT_IOREQUEST, (void *)data->inputReq); + } + + if (data->inputPort) { + dprintf("Freeing MsgPort\n"); + IExec->FreeSysObject(ASOT_PORT, (void *)data->inputPort); + } + + if (data->pool) { + dprintf("Freeing memory pool\n"); + IExec->FreeSysObject(ASOT_MEMPOOL, data->pool); + } + + if (data->appMsgPort) { + struct Message *msg; + + dprintf("Replying app messages\n"); + + while ((msg = IExec->GetMsg(data->appMsgPort))) { + IExec->ReplyMsg((struct Message *) msg); + } + + dprintf("Freeing app message port\n"); + + IExec->FreeSysObject(ASOT_PORT, data->appMsgPort); + } + + if (data->userPort) { + dprintf("Freeing user port\n"); + IExec->FreeSysObject(ASOT_PORT, data->userPort); + } + + if (data->appName) { + SDL_free(data->appName); + } + + OS4_CloseLibraries(_this); +} + +static void +OS4_DeleteDevice(SDL_VideoDevice * device) +{ + dprintf("Called\n"); + + OS4_FreeSystemResources(device); + + SDL_free(device->driverdata); + SDL_free(device); +} + +static void +OS4_SetMiniGLFunctions(SDL_VideoDevice * device) +{ + device->GL_GetProcAddress = OS4_GL_GetProcAddress; + device->GL_UnloadLibrary = OS4_GL_UnloadLibrary; + device->GL_MakeCurrent = OS4_GL_MakeCurrent; + device->GL_GetDrawableSize = OS4_GL_GetDrawableSize; + device->GL_SetSwapInterval = OS4_GL_SetSwapInterval; + device->GL_GetSwapInterval = OS4_GL_GetSwapInterval; + device->GL_SwapWindow = OS4_GL_SwapWindow; + device->GL_CreateContext = OS4_GL_CreateContext; + device->GL_DeleteContext = OS4_GL_DeleteContext; + //device->GL_DefaultProfileConfig = OS4_GL_DefaultProfileConfig; + + OS4_ResizeGlContext = OS4_GL_ResizeContext; + OS4_UpdateGlWindowPointer = OS4_GL_UpdateWindowPointer; +} + +#if SDL_VIDEO_OPENGL_ES2 +static void +OS4_SetGLESFunctions(SDL_VideoDevice * device) +{ + /* Some functions are recycled from SDL_os4opengl.c 100% ... */ + device->GL_GetProcAddress = OS4_GLES_GetProcAddress; + device->GL_UnloadLibrary = OS4_GLES_UnloadLibrary; + device->GL_MakeCurrent = OS4_GLES_MakeCurrent; + device->GL_GetDrawableSize = OS4_GL_GetDrawableSize; + device->GL_SetSwapInterval = OS4_GL_SetSwapInterval; + device->GL_GetSwapInterval = OS4_GL_GetSwapInterval; + device->GL_SwapWindow = OS4_GLES_SwapWindow; + device->GL_CreateContext = OS4_GLES_CreateContext; + device->GL_DeleteContext = OS4_GLES_DeleteContext; + //device->GL_DefaultProfileConfig = OS4_GL(ES)_DefaultProfileConfig; + + OS4_ResizeGlContext = OS4_GLES_ResizeContext; + OS4_UpdateGlWindowPointer = OS4_GLES_UpdateWindowPointer; +} +#endif + +static SDL_bool +OS4_IsMiniGL(_THIS) +{ + if ((_this->gl_config.profile_mask == 0) && + (_this->gl_config.major_version == 1) && + (_this->gl_config.minor_version == 3)) { + dprintf("OpenGL 1.3 requested\n"); + return SDL_TRUE; + } + + return SDL_FALSE; +} + +#if SDL_VIDEO_OPENGL_ES2 +static SDL_bool +OS4_IsOpenGLES2(_THIS) +{ + if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) && + (_this->gl_config.major_version == 2) && + (_this->gl_config.minor_version == 0)) { + dprintf("OpenGL ES 2.0 requested\n"); + return SDL_TRUE; + } + + return SDL_FALSE; +} +#endif + +static int +OS4_LoadGlLibrary(_THIS, const char * path) +{ + dprintf("Profile_mask %d, major ver %d, minor ver %d\n", + _this->gl_config.profile_mask, + _this->gl_config.major_version, + _this->gl_config.minor_version); + + if (OS4_IsMiniGL(_this)) { + OS4_SetMiniGLFunctions(_this); + return OS4_GL_LoadLibrary(_this, path); + } + +#if SDL_VIDEO_OPENGL_ES2 + if (OS4_IsOpenGLES2(_this)) { + OS4_SetGLESFunctions(_this); + return OS4_GLES_LoadLibrary(_this, path); + } +#endif + + dprintf("Invalid OpenGL version\n"); + SDL_SetError("Invalid OpenGL version"); + return -1; +} + +static void +OS4_SetFunctionPointers(SDL_VideoDevice * device) +{ + device->VideoInit = OS4_VideoInit; + device->VideoQuit = OS4_VideoQuit; + //device->ResetTouch = OS4_ResetTouch; + + device->GetDisplayBounds = OS4_GetDisplayBounds; + //device->GetDisplayUsableBounds = OS4_GetDisplayUsableBounds; + //device->GetDisplayDPI = OS4_GetDisplayDPI; + + device->GetDisplayModes = OS4_GetDisplayModes; + device->SetDisplayMode = OS4_SetDisplayMode; + + device->CreateSDLWindow = OS4_CreateWindow; + device->CreateSDLWindowFrom = OS4_CreateWindowFrom; + device->SetWindowTitle = OS4_SetWindowTitle; + //device->SetWindowIcon = OS4_SetWindowIcon; + device->SetWindowPosition = OS4_SetWindowPosition; + device->SetWindowSize = OS4_SetWindowSize; + + device->SetWindowMinimumSize = OS4_SetWindowMinMaxSize; + device->SetWindowMaximumSize = OS4_SetWindowMinMaxSize; + device->GetWindowBordersSize = OS4_GetWindowBordersSize; + + device->SetWindowOpacity = OS4_SetWindowOpacity; + // device->SetWindowModalFor = OS4_SetWindowModalFor; + // device->SetWindowInputFocus = OS4_SetWindowInputFocus; + + device->ShowWindow = OS4_ShowWindow; + device->HideWindow = OS4_HideWindow; + device->RaiseWindow = OS4_RaiseWindow; + + device->MaximizeWindow = OS4_MaximizeWindow; + device->MinimizeWindow = OS4_MinimizeWindow; + device->RestoreWindow = OS4_RestoreWindow; + + //device->SetWindowBordered = OS4_SetWindowBordered; // Not supported by SetWindowAttrs()? + device->SetWindowResizable = OS4_SetWindowResizable; + + device->SetWindowFullscreen = OS4_SetWindowFullscreen; + //device->SetWindowGammaRamp = OS4_SetWindowGammaRamp; + //device->GetWindowGammaRamp = OS4_GetWindowGammaRamp; + + device->SetWindowMouseGrab = OS4_SetWindowMouseGrab; + // device->SetWindowKeyboardGrab = OS4_SetWindowKeyboardGrab; + + device->DestroyWindow = OS4_DestroyWindow; + + device->CreateWindowFramebuffer = OS4_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = OS4_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = OS4_DestroyWindowFramebuffer; + + //device->OnWindowEnter = OS4_OnWindowEnter; + + device->shape_driver.CreateShaper = OS4_CreateShaper; + device->shape_driver.SetWindowShape = OS4_SetWindowShape; + device->shape_driver.ResizeWindowShape = OS4_ResizeWindowShape; + + device->GetWindowWMInfo = OS4_GetWindowWMInfo; + + device->GL_LoadLibrary = OS4_LoadGlLibrary; + OS4_SetMiniGLFunctions(device); + + device->PumpEvents = OS4_PumpEvents; + //device->SuspendScreenSaver = OS4_SuspendScreenSaver; + + //device->StartTextInput = OS4_StartTextInput; + //device->StopTextInput = OS4_StopTextInput; + //device->SetTextInputRect = OS4_SetTextInputRect; + + //device->SetTextInputRect = OS4_SetTextInputRect; + //device->ShowScreenKeyboard = OS4_ShowScreenKeyboard; + //device->HideScreenKeyboard = OS4_HideScreenKeyboard; + //device->IsScreenKeyboardShown = OS4_IsScreenKeyboardShown; + + device->SetClipboardText = OS4_SetClipboardText; + device->GetClipboardText = OS4_GetClipboardText; + device->HasClipboardText = OS4_HasClipboardText; + //device->ShowMessageBox = OS4_ShowMessageBox; Can be called without video initialization + + device->SetWindowHitTest = OS4_SetWindowHitTest; + //device->AcceptDragAndDrop = OS4_AcceptDragAndDrop; + + device->free = OS4_DeleteDevice; +} + +static SDL_VideoDevice * +OS4_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + SDL_VideoData *data; + SDL_version version; + + SDL_GetVersion(&version); + + dprintf("*** SDL %d.%d.%d video initialization starts ***\n", + version.major, version.minor, version.patch); + +#ifdef __AMIGADATE__ + dprintf("Build date: " __AMIGADATE__ "\n"); +#endif + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + + if (device) { + data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); + } else { + data = NULL; + } + + if (!data) { + SDL_free(device); + SDL_OutOfMemory(); + return NULL; + } + + device->driverdata = data; + + if (!OS4_AllocSystemResources(device)) { + /* If we return with NULL, SDL_VideoQuit() can't clean up OS4 stuff. So let's do it now. */ + OS4_FreeSystemResources(device); + + SDL_free(device); + SDL_free(data); + + SDL_Unsupported(); + + return NULL; + } + + OS4_SetFunctionPointers(device); + + return device; +} + +VideoBootStrap OS4_bootstrap = { + OS4VID_DRIVER_NAME, "SDL AmigaOS 4 video driver", + OS4_CreateDevice +}; + +int +OS4_VideoInit(_THIS) +{ + dprintf("Called\n"); + + if (OS4_InitModes(_this) < 0) { + return SDL_SetError("Failed to initialize modes"); + } + + OS4_InitKeyboard(_this); + OS4_InitMouse(_this); + + // We don't want SDL to change window setup in SDL_OnWindowFocusLost() + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); + + return 0; +} + +void +OS4_VideoQuit(_THIS) +{ + dprintf("Called\n"); + + OS4_QuitMouse(_this); + OS4_QuitKeyboard(_this); + OS4_QuitModes(_this); +} + +void * +OS4_SaveAllocPooled(_THIS, uint32 size) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + return IExec->AllocPooled(data->pool, size); +} + +void * +OS4_SaveAllocVecPooled(_THIS, uint32 size) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + return IExec->AllocVecPooled(data->pool, size); +} + +void +OS4_SaveFreePooled(_THIS, void * mem, uint32 size) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + IExec->FreePooled(data->pool, mem, size); +} + +void +OS4_SaveFreeVecPooled(_THIS, void * mem) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + IExec->FreeVecPooled(data->pool, mem); +} + +/* Native window apps may be interested in calling this */ +struct MsgPort * +OS4_GetSharedMessagePort() +{ + SDL_VideoDevice *vd = SDL_GetVideoDevice(); + + if (vd) { + SDL_VideoData *data = (SDL_VideoData *) vd->driverdata; + if (data) { + return data->userPort; + } + } + + return NULL; +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4video.h b/src/video/amigaos4/SDL_os4video.h new file mode 100644 index 0000000000000..193b505bf8782 --- /dev/null +++ b/src/video/amigaos4/SDL_os4video.h @@ -0,0 +1,105 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4video_h +#define _SDL_os4video_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../SDL_sysvideo.h" + +/* Private display data */ + +typedef struct +{ + STRPTR appName; + + struct Screen *publicScreen; + + struct MsgPort *userPort; + struct MsgPort *appMsgPort; + + struct MsgPort *inputPort; + struct IOStdReq *inputReq; + + APTR pool; + + struct Library *gfxbase; + struct Library *layersbase; + struct Library *intuitionbase; + struct Library *iconbase; + struct Library *workbenchbase; + struct Library *keymapbase; + struct Library *textclipbase; + struct Library *dosbase; + + struct GraphicsIFace *iGraphics; + struct LayersIFace *iLayers; + struct IntuitionIFace *iIntuition; + struct IconIFace *iIcon; + struct WorkbenchIFace *iWorkbench; + struct KeymapIFace *iKeymap; + struct TextClipIFace *iTextClip; + struct InputIFace *iInput; + struct DOSIFace *iDos; + + BOOL vsyncEnabled; +} SDL_VideoData; + +#define GfxBase ((SDL_VideoData *) _this->driverdata)->gfxbase +#define LayersBase ((SDL_VideoData *) _this->driverdata)->layersbase +#define IntuitionBase ((SDL_VideoData *) _this->driverdata)->intuitionbase +#define IconBase ((SDL_VideoData *) _this->driverdata)->iconbase +#define WorkbenchBase ((SDL_VideoData *) _this->driverdata)->workbenchbase +#define KeymapBase ((SDL_VideoData *) _this->driverdata)->keymapbase +#define TextClipBase ((SDL_VideoData *) _this->driverdata)->textclipbase +#define DOSBase ((SDL_VideoData *) _this->driverdata)->dosbase + +#define IGraphics ((SDL_VideoData *) _this->driverdata)->iGraphics +#define ILayers ((SDL_VideoData *) _this->driverdata)->iLayers +#define IIntuition ((SDL_VideoData *) _this->driverdata)->iIntuition +#define IIcon ((SDL_VideoData *) _this->driverdata)->iIcon +#define IWorkbench ((SDL_VideoData *) _this->driverdata)->iWorkbench +#define IKeymap ((SDL_VideoData *) _this->driverdata)->iKeymap +#define ITextClip ((SDL_VideoData *) _this->driverdata)->iTextClip +#define IInput ((SDL_VideoData *) _this->driverdata)->iInput +#define IDOS ((SDL_VideoData *) _this->driverdata)->iDos + +extern void * OS4_SaveAllocPooled(_THIS, uint32 size); +extern void * OS4_SaveAllocVecPooled(_THIS, uint32 size); +extern void OS4_SaveFreePooled(_THIS, void *mem, uint32 size); +extern void OS4_SaveFreeVecPooled(_THIS, void *mem); + +extern DECLSPEC struct MsgPort * OS4_GetSharedMessagePort(); + +#endif /* _SDL_os4video_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4window.c b/src/video/amigaos4/SDL_os4window.c new file mode 100644 index 0000000000000..fc84d533f2403 --- /dev/null +++ b/src/video/amigaos4/SDL_os4window.c @@ -0,0 +1,1161 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_AMIGAOS4 + +#include +#include +#include + +#include + +#include "SDL_os4video.h" +#include "SDL_os4shape.h" +#include "SDL_os4window.h" +#include "SDL_os4modes.h" +#include "SDL_os4opengl.h" +#include "SDL_os4mouse.h" +#include "SDL_os4events.h" + +#include "SDL_syswm.h" +#include "../../events/SDL_keyboard_c.h" +#include "../../events/SDL_events_c.h" + +#define DEBUG +#include "../../main/amigaos4/SDL_os4debug.h" + +extern SDL_bool (*OS4_ResizeGlContext)(_THIS, SDL_Window * window); +extern void (*OS4_UpdateGlWindowPointer)(_THIS, SDL_Window * window); + +static void OS4_CloseSystemWindow(_THIS, struct Window * window); +static void OS4_CloseWindow(_THIS, SDL_Window * sdlwin); + +void +OS4_GetWindowSize(_THIS, struct Window * window, int * width, int * height) +{ + LONG ret = IIntuition->GetWindowAttrs( + window, + WA_InnerWidth, width, + WA_InnerHeight, height, + TAG_DONE); + + if (ret) { + dprintf("GetWindowAttrs() returned %d\n", ret); + } +} + +void +OS4_GetWindowActiveSize(SDL_Window * window, int * width, int * height) +{ + if (window->flags & SDL_WINDOW_MAXIMIZED) { + *width = window->max_w; + *height = window->max_h; + } else { + *width = window->w; + *height = window->h; + } +} + +void +OS4_WaitForResize(_THIS, SDL_Window * window, int * width, int * height) +{ + SDL_WindowData * data = window->driverdata; + + int counter = 0; + int activeWidth, activeHeight; + int w = 0; + int h = 0; + + OS4_GetWindowActiveSize(window, &activeWidth, &activeHeight); + + while (counter++ < 100) { + OS4_GetWindowSize(_this, data->syswin, &w, &h); + + if (w == activeWidth && h == activeHeight) { + break; + } + + dprintf("Waiting for Intuition %d\n", counter); + dprintf("System window size (%d * %d), SDL window size (%d * %d)\n", + w, h, activeWidth, activeHeight); + usleep(1000); + } + + if (width) { + *width = w; + } + + if (height) { + *height = h; + } +} + +static SDL_bool +OS4_IsFullscreen(SDL_Window * window) +{ + return (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)); +} + +static void +OS4_RemoveAppWindow(_THIS, SDL_WindowData *data) +{ + if (data->appWin) { + dprintf("Removing AppWindow\n"); + + if (IWorkbench->RemoveAppWindow(data->appWin) == FALSE) { + dprintf("Failed to remove AppWindow\n"); + } + data->appWin = NULL; + } +} + +static void +OS4_RemoveAppIcon(_THIS, SDL_WindowData *data) +{ + if (data->appIcon) { + dprintf("Removing AppIcon\n"); + + if (IWorkbench->RemoveAppIcon(data->appIcon) == FALSE) { + dprintf("Failed to remove AppIcon\n"); + } + data->appIcon = NULL; + } +} + +static int +OS4_SetupWindowData(_THIS, SDL_Window * sdlwin, struct Window * syswin) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + + SDL_WindowData *data; + + if (sdlwin->driverdata) { + data = sdlwin->driverdata; + dprintf("Old window data %p exists\n", data); + } else { + data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data)); + + if (!data) { + return SDL_OutOfMemory(); + } + + sdlwin->driverdata = data; + } + + data->sdlwin = sdlwin; + data->syswin = syswin; + data->pointerGrabTicks = 0; + + if (data->syswin) { + int width = 0; + int height = 0; + + OS4_GetWindowSize(_this, data->syswin, &width, &height); + + dprintf("'%s' dimensions %d*%d\n", sdlwin->title, width, height); + + sdlwin->w = width; + sdlwin->h = height; + } + + // Pass SDL window as user data + data->appWin = IWorkbench->AddAppWindow(0, (ULONG)sdlwin, syswin, + videodata->appMsgPort, TAG_DONE); + + if (!data->appWin) { + dprintf("Couldn't create AppWindow\n"); + // It's sad but don't fail because of this + } + + return 0; +} + +static uint32 +OS4_GetIDCMPFlags(SDL_Window * window, SDL_bool fullscreen) +{ + uint32 IDCMPFlags = IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE + | IDCMP_DELTAMOVE | IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW + | IDCMP_INACTIVEWINDOW | IDCMP_INTUITICKS + | IDCMP_EXTENDEDMOUSE; + + dprintf("Called\n"); + + if (!fullscreen) { + if (!(window->flags & SDL_WINDOW_BORDERLESS)) { + IDCMPFlags |= IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_CHANGEWINDOW; + } + + if (window->flags & SDL_WINDOW_RESIZABLE) { + //IDCMPFlags |= IDCMP_SIZEVERIFY; no handling so far + IDCMPFlags |= IDCMP_NEWSIZE; + } + } + + return IDCMPFlags; +} + +static uint32 +OS4_GetWindowFlags(SDL_Window * window, SDL_bool fullscreen) +{ + uint32 windowFlags = WFLG_REPORTMOUSE | WFLG_RMBTRAP | WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH; + + dprintf("Called\n"); + + if (fullscreen) { + windowFlags |= WFLG_BORDERLESS | WFLG_BACKDROP; + } else { + windowFlags |= WFLG_NEWLOOKMENUS; + + if (window->flags & SDL_WINDOW_BORDERLESS) { + windowFlags |= WFLG_BORDERLESS; + } else { + windowFlags |= WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET; + + if (window->flags & SDL_WINDOW_RESIZABLE) { + windowFlags |= WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM; + } + } + } + + return windowFlags; +} + +static struct Screen * +OS4_GetScreenForWindow(_THIS, SDL_VideoDisplay * display) +{ + if (display) { + SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; + + dprintf("Fullscreen\n"); + return displaydata->screen; + } else { + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + + dprintf("Window mode (public screen)\n"); + return videodata->publicScreen; + } +} + +static ULONG +OS4_BackFill(const struct Hook *hook, struct RastPort *rastport, struct BackFillMessage *message) +{ + struct Rectangle *rect = &message->Bounds; + struct GraphicsIFace *igfx = hook->h_Data; + + struct RastPort bfRastport; + + igfx->InitRastPort(&bfRastport); + bfRastport.BitMap = rastport->BitMap; + + igfx->RectFillColor(&bfRastport, rect->MinX, rect->MinY, rect->MaxX, rect->MaxY, 0xFF000000); + + return 0; +} + +static struct Hook OS4_BackFillHook = { + {0, 0}, /* h_MinNode */ + (void *)OS4_BackFill, /* h_Entry */ + 0, /* h_SubEntry */ + 0 /* h_Data */ +}; + +static void +OS4_CenterWindow(struct Screen * screen, SDL_Window * window) +{ + if (SDL_WINDOWPOS_ISCENTERED(window->windowed.x) || + SDL_WINDOWPOS_ISUNDEFINED(window->windowed.x)) { + + window->windowed.x = (screen->Width - window->windowed.w) / 2; + dprintf("X centered\n"); + } + + if (SDL_WINDOWPOS_ISCENTERED(window->windowed.y) || + SDL_WINDOWPOS_ISUNDEFINED(window->windowed.y)) { + + window->windowed.y = (screen->Height - window->windowed.h) / 2; + dprintf("Y centered\n"); + } +} + +static void +OS4_DefineWindowBox(SDL_Window * window, struct Screen * screen, SDL_bool fullscreen, SDL_Rect * box) +{ + if (fullscreen && screen) { + box->x = 0; // window->x; + box->y = 0; // window->y; + box->w = screen->Width; // window->w; + box->h = screen->Height; // window->h; + } else { + OS4_CenterWindow(screen, window); + + box->x = window->windowed.x; + box->y = window->windowed.y; + box->w = window->windowed.w; + box->h = window->windowed.h; + } +} + +static void +OS4_CreateIconifyGadget(_THIS, SDL_Window * window) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + SDL_WindowData *data = window->driverdata; + + dprintf("Called\n"); + + struct DrawInfo *di = IIntuition->GetScreenDrawInfo(videodata->publicScreen); + + if (di) { + data->image = (struct Image *)IIntuition->NewObject(NULL, SYSICLASS, + SYSIA_Which, ICONIFYIMAGE, + SYSIA_DrawInfo, di, + TAG_DONE); + + if (data->image) { + + dprintf("Image %p for gadget created\n", data->image); + + data->gadget = (struct Gadget *)IIntuition->NewObject(NULL, BUTTONGCLASS, + GA_Image, data->image, + GA_ID, GID_ICONIFY, + GA_TopBorder, TRUE, + GA_RelRight, TRUE, + GA_Titlebar, TRUE, + GA_RelVerify, TRUE, + TAG_DONE); + + if (data->gadget) { + struct Window *syswin = data->syswin; + + IIntuition->AddGadget(syswin, data->gadget, -1); + + dprintf("Gadget %p created and added\n", data->gadget); + } else { + dprintf("Failed to create button class\n"); + } + } else { + dprintf("Failed to create image class\n"); + } + + IIntuition->FreeScreenDrawInfo(videodata->publicScreen, di); + + } else { + dprintf("Failed to get screen draw info\n"); + } +} + +static void +OS4_CreateIconifyGadgetForWindow(_THIS, SDL_Window * window) +{ + if (!OS4_IsFullscreen(window) && !(window->flags & SDL_WINDOW_BORDERLESS)) { + if (window->w > 99 && window->h > 99) { + OS4_CreateIconifyGadget(_this, window); + } else { + dprintf("Don't add gadget for too small window %d*%d (OS4 bug)\n", + window->w, window->h); + } + } +} + +static struct Window * +OS4_CreateSystemWindow(_THIS, SDL_Window * window, SDL_VideoDisplay * display) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + + struct Window *syswin; + + SDL_bool fullscreen = display ? SDL_TRUE : SDL_FALSE; + + uint32 IDCMPFlags = OS4_GetIDCMPFlags(window, fullscreen); + uint32 windowFlags = OS4_GetWindowFlags(window, fullscreen); + + struct Screen *screen = OS4_GetScreenForWindow(_this, display); + + SDL_Rect box; + + OS4_BackFillHook.h_Data = IGraphics; // Smuggle interface ptr for the hook + + OS4_DefineWindowBox(window, screen, fullscreen, &box); + + dprintf("Opening window '%s' at (%d,%d) of size (%dx%d) on screen %p\n", + window->title, box.x, box.y, box.w, box.h, screen); + + syswin = IIntuition->OpenWindowTags( + NULL, + WA_PubScreen, screen, + WA_Title, fullscreen ? NULL : window->title, + WA_ScreenTitle, window->title, + WA_Left, box.x, + WA_Top, box.y, + WA_InnerWidth, box.w, + WA_InnerHeight, box.h, + WA_Flags, windowFlags, + WA_IDCMP, IDCMPFlags, + WA_Hidden, (window->flags & SDL_WINDOW_HIDDEN) ? TRUE : FALSE, + WA_GrabFocus, (window->flags & SDL_WINDOW_INPUT_GRABBED) ? POINTER_GRAB_TIMEOUT : 0, + WA_UserPort, videodata->userPort, + WA_BackFill, &OS4_BackFillHook, + TAG_DONE); + + if (syswin) { + dprintf("Window address %p\n", syswin); + } else { + dprintf("Couldn't create window\n"); + return NULL; + } + + if (window->flags & SDL_WINDOW_RESIZABLE) { + + // If this window is resizable, reset window size limits + // so that the user can actually resize it. + BOOL ret = IIntuition->WindowLimits(syswin, + syswin->BorderLeft + syswin->BorderRight + 100, + syswin->BorderTop + syswin->BorderBottom + 100, + -1, + -1); + + if (!ret) { + dprintf("Failed to set window limits\n"); + } + } + + return syswin; +} + +int +OS4_CreateWindow(_THIS, SDL_Window * window) +{ + struct Window *syswin = NULL; + + if (OS4_IsFullscreen(window)) { + // We may not have the screen opened yet, so let's wait that SDL calls us back with + // SDL_SetWindowFullscreen() and open the window then. + dprintf("Open fullscreen window with delay\n"); + } else { + if (!(syswin = OS4_CreateSystemWindow(_this, window, NULL))) { + return SDL_SetError("Failed to create system window"); + } + } + + if (OS4_SetupWindowData(_this, window, syswin) < 0) { + + // There is no AppWindow in this scenario + OS4_CloseSystemWindow(_this, syswin); + + return SDL_SetError("Failed to setup window data"); + } + + OS4_CreateIconifyGadgetForWindow(_this, window); + + return 0; +} + +int +OS4_CreateWindowFrom(_THIS, SDL_Window * window, const void * data) +{ + struct Window *syswin = (struct Window *) data; + + dprintf("Called for native window %p (flags 0x%X)\n", data, window->flags); + + if (syswin->Title && SDL_strlen(syswin->Title)) { + window->title = SDL_strdup(syswin->Title); + } + + if (OS4_SetupWindowData(_this, window, syswin) < 0) { + return -1; + } + + // TODO: OpenGL, (fullscreen may not be applicable here?) + + return 0; +} + +void +OS4_SetWindowTitle(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + //dprintf("Called\n"); + + if (data && data->syswin) { + STRPTR title = window->title ? window->title : ""; + + IIntuition->SetWindowTitles(data->syswin, title, title); + } +} + +void +OS4_SetWindowBox(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (data && data->syswin) { + int width, height; + LONG ret; + + OS4_GetWindowActiveSize(window, &width, &height); + + ret = IIntuition->SetWindowAttrs(data->syswin, + WA_Left, window->x, + WA_Top, window->y, + WA_InnerWidth, width, + WA_InnerHeight, height, + TAG_DONE); + + if (ret) { + dprintf("SetWindowAttrs() returned %d\n", ret); + } + + if (SDL_IsShapedWindow(window)) { + OS4_ResizeWindowShape(window); + } + + if (data->glContext) { + OS4_ResizeGlContext(_this, window); + } + } +} + +void +OS4_SetWindowPosition(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + dprintf("New window position %d, %d\n", window->x, window->y); + + if (data && data->syswin) { + + LONG ret = IIntuition->SetWindowAttrs(data->syswin, + WA_Left, window->x, + WA_Top, window->y, + TAG_DONE); + + if (ret) { + dprintf("SetWindowAttrs() returned %d\n", ret); + } + } +} + +static void +OS4_ResizeWindow(_THIS, SDL_Window * window, int width, int height) +{ + if (width > 0 && height > 0) { + SDL_WindowData *data = window->driverdata; + + if (data) { + LONG ret = IIntuition->SetWindowAttrs(data->syswin, + WA_InnerWidth, width, + WA_InnerHeight, height, + TAG_DONE); + + if (ret) { + dprintf("SetWindowAttrs() returned %d\n", ret); + } + + OS4_WaitForResize(_this, window, NULL, NULL); + + if (SDL_IsShapedWindow(window)) { + OS4_ResizeWindowShape(window); + } + + if (data->glContext) { + OS4_ResizeGlContext(_this, window); + } + } + } else { + dprintf("Invalid width %d or height %d\n", width, height); + } +} + +void +OS4_SetWindowSize(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (data && data->syswin) { + + int width = 0; + int height = 0; + + OS4_GetWindowSize(_this, data->syswin, &width, &height); + + if (width != window->w || height != window->h) { + + dprintf("New window size %d*%d\n", window->w, window->h); + + OS4_ResizeWindow(_this, window, window->w, window->h); + } else { + dprintf("Ignored size request %d*%d\n", width, height); + } + } +} + +void +OS4_ShowWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (data && data->syswin) { + + LONG ret; + + dprintf("Showing window '%s'\n", window->title); + + // TODO: could use ShowWindow but what we pass for the Other? + ret = IIntuition->SetWindowAttrs(data->syswin, + WA_Hidden, FALSE, + TAG_DONE); + + if (ret) { + dprintf("SetWindowAttrs() returned %d\n", ret); + } + + if (OS4_IsFullscreen(window)) { + IIntuition->ScreenToFront(data->syswin->WScreen); + } + + IIntuition->ActivateWindow(data->syswin); + + window->flags |= SDL_WINDOW_INPUT_FOCUS; + + SDL_SetKeyboardFocus(window); + + // If cursor was disabled earlier, make sure also this window gets the news + OS4_RefreshCursorState(); + } +} + +void +OS4_HideWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (window->is_destroying) { + dprintf("Ignore hide request, window '%s' is destroying\n", window->title); + return; + } + + if (data && data->syswin) { + BOOL result; + + dprintf("Hiding window '%s'\n", window->title); + + // TODO: how to hide a fullscreen window? Close the screen? + result = IIntuition->HideWindow(data->syswin); + + if (!result) { + dprintf("HideWindow() failed\n"); + } + } +} + +void +OS4_RaiseWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + if (data && data->syswin) { + dprintf("Raising window '%s'\n", window->title); + + IIntuition->WindowToFront(data->syswin); + IIntuition->ActivateWindow(data->syswin); + } +} + +static void +OS4_CloseSystemWindow(_THIS, struct Window * window) +{ + if (window) { + dprintf("Closing window '%s' (address %p)\n", window->Title, window); + + struct Screen *screen = window->WScreen; + + IIntuition->CloseWindow(window); + + OS4_CloseScreen(_this, screen); + } else { + dprintf("NULL pointer\n"); + } +} + +static void +OS4_CloseWindow(_THIS, SDL_Window * sdlwin) +{ + SDL_WindowData *data = sdlwin->driverdata; + + if (data) { + OS4_RemoveAppWindow(_this, data); + OS4_RemoveAppIcon(_this, data); + + if (data->syswin) { + + OS4_CloseSystemWindow(_this, data->syswin); + data->syswin = NULL; + + if (data->gadget) { + dprintf("Disposing gadget %p\n", data->gadget); + //IIntuition->RemoveGadget(data->syswin, data->gadget); + IIntuition->DisposeObject((Object *)data->gadget); + data->gadget = NULL; + } + + if (data->image) { + dprintf("Disposing gadget image %p\n", data->image); + IIntuition->DisposeObject((Object *)data->image); + data->image = NULL; + } + } + } else { + dprintf("NULL pointer\n"); + } +} + +void +OS4_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen) +{ + if (window->is_destroying) { + // This function gets also called during window closing + dprintf("Window '%s' is being destroyed, mode change ignored\n", window->title); + } else { + SDL_WindowData *data = window->driverdata; + + dprintf("Trying to set '%s' into %s mode\n", window->title, + fullscreen ? "fullscreen" : "window"); + + if (window->flags & SDL_WINDOW_FOREIGN) { + dprintf("Native window '%s' (%p), mode change ignored\n", window->title, data->syswin); + } else { + + int oldWidth = 0; + int oldHeight = 0; + + if (fullscreen) { + // Detect dummy transition and keep calm + SDL_DisplayData *displayData = display->driverdata; + + if (displayData->screen && data->syswin) { + if (data->syswin->WScreen == displayData->screen) { + dprintf("Same screen, useless mode change ignored\n"); + return; + } + } + } + + if (data->syswin) { + dprintf("Reopening window '%s' (%p) due to mode change\n", + window->title, data->syswin); + + OS4_GetWindowSize(_this, data->syswin, &oldWidth, &oldHeight); + OS4_CloseWindow(_this, window); + + } else { + dprintf("System window doesn't exist yet, let's open it\n"); + } + + data->syswin = OS4_CreateSystemWindow(_this, window, fullscreen ? display : NULL); + + if (data->syswin) { + + OS4_CreateIconifyGadgetForWindow(_this, window); + + // Make sure the new window is active + OS4_ShowWindow(_this, window); + + if ((window->flags & SDL_WINDOW_OPENGL) && data->glContext) { + OS4_UpdateGlWindowPointer(_this, window); + } + + if (oldWidth && oldHeight) { + int width, height; + + OS4_GetWindowSize(_this, data->syswin, &width, &height); + + if (oldWidth != width || oldHeight != height) { + + dprintf("Inform SDL about window resize\n"); + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, + width, height); + } + } + + dprintf("Resetting keyboard\n"); + SDL_ResetKeyboard(); + } + } + } +} + +// This may be called from os4events.c +void +OS4_SetWindowGrabPrivate(_THIS, struct Window * w, SDL_bool activate) +{ + if (w) { + struct IBox grabBox = { + w->BorderLeft, + w->BorderTop, + w->Width - w->BorderLeft - w->BorderRight, + w->Height - w->BorderTop - w->BorderBottom + }; + + LONG ret; + + if (activate) { + // It seems to be that grabbed window should be active, otherwise some other + // window (like shell) may be grabbed? + IIntuition->ActivateWindow(w); + + ret = IIntuition->SetWindowAttrs(w, + WA_MouseLimits, &grabBox, + WA_GrabFocus, POINTER_GRAB_TIMEOUT, + TAG_DONE); + } else { + ret = IIntuition->SetWindowAttrs(w, + WA_MouseLimits, NULL, + WA_GrabFocus, 0, + TAG_DONE); + } + + if (ret) { + dprintf("SetWindowAttrs() returned %d\n", ret); + } else { + dprintf("Window %p ('%s') input was %s\n", + w, w->Title, activate ? "grabbed" : "released"); + } + } +} + +void +OS4_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed) +{ + SDL_WindowData *data = window->driverdata; + + if (data) { + OS4_SetWindowGrabPrivate(_this, data->syswin, grabbed); + data->pointerGrabTicks = 0; + } +} + +void +OS4_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = window->driverdata; + + dprintf("Called for '%s' (flags 0x%X)\n", window->title, window->flags); + + if (data) { + + if (data->syswin) { + + if (!(window->flags & SDL_WINDOW_FOREIGN)) { + + if (SDL_IsShapedWindow(window)) { + OS4_DestroyShape(_this, window); + } + + OS4_CloseWindow(_this, window); + } else { + dprintf("Ignored for native window\n"); + } + } + + if (window->flags & SDL_WINDOW_OPENGL) { + OS4_GL_FreeBuffers(_this, data); + } + + SDL_free(data); + window->driverdata = NULL; + } +} + +SDL_bool +OS4_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo * info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + struct Window *syswin = ((SDL_WindowData *) window->driverdata)->syswin; + + info->subsystem = SDL_SYSWM_OS4; + info->info.os4.window = syswin; + + dprintf("Window pointer %p\n", syswin); + + return SDL_TRUE; + } else { + dprintf("Application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + + SDL_SetError("Application not compiled with SDL %d.%d", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + + return SDL_FALSE; + } +} + +int +OS4_SetWindowHitTest(SDL_Window * window, SDL_bool enabled) +{ + return 0; // just succeed, the real work is done elsewhere +} + +int +OS4_SetWindowOpacity(_THIS, SDL_Window * window, float opacity) +{ + struct Window *syswin = ((SDL_WindowData *) window->driverdata)->syswin; + LONG ret; + + UBYTE value = opacity * 255; + + dprintf("Setting window '%s' opaqueness to %d\n", window->title, value); + + ret = IIntuition->SetWindowAttrs( + syswin, + WA_Opaqueness, value, + TAG_DONE); + + if (ret) { + dprintf("Failed to set window opaqueness to %d\n", value); + return -1; + } + + return 0; +} + +int +OS4_GetWindowBordersSize(_THIS, SDL_Window * window, int * top, int * left, int * bottom, int * right) +{ + struct Window *syswin = ((SDL_WindowData *) window->driverdata)->syswin; + + if (top) { + *top = syswin->BorderTop; + } + + if (left) { + *left = syswin->BorderLeft; + } + + if (bottom) { + *bottom = syswin->BorderBottom; + } + + if (right) { + *right = syswin->BorderRight; + } + + return 0; +} + +void +OS4_SetWindowMinMaxSize(_THIS, SDL_Window * window) +{ + if (window->driverdata) { + + dprintf("Window min size %d*%d, max size %d*%d\n", + window->min_w, window->min_h, + window->max_w, window->max_h); + + if (window->flags & SDL_WINDOW_RESIZABLE) { + + SDL_WindowData *data = window->driverdata; + + if (data->syswin) { + struct Window *syswin = data->syswin; + + int width = syswin->BorderLeft + syswin->BorderRight; + int height = syswin->BorderTop + syswin->BorderBottom; + + BOOL ret =IIntuition->WindowLimits(data->syswin, + window->min_w + width, window->min_h + height, + window->max_w + width, window->max_h + height); + + if (!ret) { + dprintf("Setting window limits failed\n"); + } + } else { + dprintf("NULL window\n"); + } + } else { + dprintf("Window is not resizable\n"); + } + } +} + +void +OS4_MaximizeWindow(_THIS, SDL_Window * window) +{ + dprintf("Maximizing '%s' to %d*%d\n", window->title, window->max_w, window->max_h); + + if (window->flags & SDL_WINDOW_MINIMIZED) { + OS4_UniconifyWindow(_this, window); + } + + // HACK: set flag temporarily so that shaped window and OpenGL + // context can be resized accordingly... + window->flags |= SDL_WINDOW_MAXIMIZED; + + OS4_ResizeWindow(_this, window, window->max_w, window->max_h); + + // ...then remove the flag so that user event can be triggered + window->flags &= ~SDL_WINDOW_MAXIMIZED; + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); +} + +void +OS4_MinimizeWindow(_THIS, SDL_Window * window) +{ + dprintf("Minimizing '%s'\n", window->title); + + OS4_IconifyWindow(_this, window); +} + +void +OS4_RestoreWindow(_THIS, SDL_Window * window) +{ + dprintf("Restoring '%s' to %d*%d\n", window->title, window->w, window->h); + + if (window->flags & SDL_WINDOW_MINIMIZED) { + OS4_UniconifyWindow(_this, window); + } else if (window->flags & SDL_WINDOW_MAXIMIZED) { + OS4_ResizeWindow(_this, window, window->w, window->h); + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0); + } else { + dprintf("Don't know what to do\n"); + } +} + +static struct DiskObject* +OS4_GetDiskObject(_THIS) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + struct DiskObject *diskObject = NULL; + + if (videodata->appName) { + BPTR oldDir = IDOS->SetCurrentDir(IDOS->GetProgramDir()); + diskObject = IIcon->GetDiskObject(videodata->appName); + IDOS->SetCurrentDir(oldDir); + } + + if (!diskObject) { + CONST_STRPTR fallbackIconName = "ENVARC:Sys/def_window"; + + dprintf("Falling back to '%s'\n", fallbackIconName); + diskObject = IIcon->GetDiskObjectNew(fallbackIconName); + } + + return diskObject; +} + +void +OS4_IconifyWindow(_THIS, SDL_Window * window) +{ + if (window && window->driverdata) { + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + + SDL_WindowData *data = window->driverdata; + + if (window->flags & SDL_WINDOW_MINIMIZED) { + dprintf("Window '%s' is already iconified\n", window->title); + } else { + struct DiskObject *diskObject = OS4_GetDiskObject(_this); + + if (diskObject) { + diskObject->do_CurrentX = NO_ICON_POSITION; + diskObject->do_CurrentY = NO_ICON_POSITION; + + data->appIcon = IWorkbench->AddAppIcon( + 0, + (ULONG)window, + videodata->appName, + videodata->appMsgPort, + 0, + diskObject, + TAG_DONE); + + if (!data->appIcon) { + dprintf("Failed to add AppIcon\n"); + } else { + dprintf("Iconifying '%s'\n", window->title); + + OS4_HideWindow(_this, window); + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0); + } + + IIcon->FreeDiskObject(diskObject); + } else { + dprintf("Failed to load icon\n"); + } + } + } +} + +void +OS4_UniconifyWindow(_THIS, SDL_Window * window) +{ + if (window && window->driverdata) { + if (window->flags & SDL_WINDOW_MINIMIZED) { + dprintf("Restoring '%s'\n", window->title); + + OS4_RemoveAppIcon(_this, window->driverdata); + OS4_ShowWindow(_this, window); + + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0); + } else { + dprintf("Window '%s' isn't in iconified state\n", window->title); + } + } +} + +void +OS4_SetWindowResizable (_THIS, SDL_Window * window, SDL_bool resizable) +{ + if (window->flags & SDL_WINDOW_FOREIGN) { + dprintf("Cannot modify native window '%s'\n", window->title); + return; + } + + SDL_WindowData *data = window->driverdata; + + if (data->syswin) { + dprintf("Closing system window '%s' before re-creation\n", window->title); + OS4_CloseWindow(_this, window); + } + + data->syswin = OS4_CreateSystemWindow(_this, window, NULL); + + if (data->syswin) { + OS4_CreateIconifyGadgetForWindow(_this, window); + + // Make sure the new window is active + OS4_ShowWindow(_this, window); + + if ((window->flags & SDL_WINDOW_OPENGL) && data->glContext) { + OS4_UpdateGlWindowPointer(_this, window); + } + } else { + dprintf("Failed to re-create window '%s'\n", window->title); + } +} + +#endif /* SDL_VIDEO_DRIVER_AMIGAOS4 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/amigaos4/SDL_os4window.h b/src/video/amigaos4/SDL_os4window.h new file mode 100644 index 0000000000000..25fca89c2c0e4 --- /dev/null +++ b/src/video/amigaos4/SDL_os4window.h @@ -0,0 +1,105 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_os4window_h +#define _SDL_os4window_h + +#include "../SDL_sysvideo.h" + +#define POINTER_GRAB_TIMEOUT 20 /* Number of ticks before pointer grab needs to be reactivated */ + +#define GID_ICONIFY 123 + +typedef struct HitTestInfo +{ + SDL_HitTestResult htr; + SDL_Point point; +} HitTestInfo; + +typedef struct +{ + SDL_Window * sdlwin; + struct Window * syswin; + struct BitMap * bitmap; + struct AppWindow * appWin; + struct AppIcon * appIcon; + + Uint32 pointerGrabTicks; + + void* * glContext; + struct BitMap * glFrontBuffer; + struct BitMap * glBackBuffer; + + HitTestInfo hti; + + struct Gadget * gadget; + struct Image * image; + +} SDL_WindowData; + +extern void OS4_GetWindowSize(_THIS, struct Window * window, int * width, int * height); +extern void OS4_GetWindowActiveSize(SDL_Window * window, int * width, int * height); +extern void OS4_WaitForResize(_THIS, SDL_Window * window, int * width, int * height); + +extern int OS4_CreateWindow(_THIS, SDL_Window * window); +extern int OS4_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +extern void OS4_SetWindowTitle(_THIS, SDL_Window * window); +//extern void OS4_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); +extern void OS4_SetWindowBox(_THIS, SDL_Window * window); +extern void OS4_SetWindowPosition(_THIS, SDL_Window * window); +extern void OS4_SetWindowSize(_THIS, SDL_Window * window); +extern void OS4_ShowWindow(_THIS, SDL_Window * window); +extern void OS4_HideWindow(_THIS, SDL_Window * window); +extern void OS4_RaiseWindow(_THIS, SDL_Window * window); + +extern void OS4_SetWindowMinMaxSize(_THIS, SDL_Window * window); + +extern void OS4_MaximizeWindow(_THIS, SDL_Window * window); +extern void OS4_MinimizeWindow(_THIS, SDL_Window * window); +extern void OS4_RestoreWindow(_THIS, SDL_Window * window); + +extern void OS4_SetWindowResizable (_THIS, SDL_Window * window, SDL_bool resizable); + +//extern void OS4_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered); +extern void OS4_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); +//extern int OS4_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); +//extern int OS4_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp); + +extern void OS4_SetWindowGrabPrivate(_THIS, struct Window * w, SDL_bool activate); +extern void OS4_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed); +extern void OS4_DestroyWindow(_THIS, SDL_Window * window); +extern SDL_bool OS4_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info); + +//extern void OS4_OnWindowEnter(_THIS, SDL_Window * window); +//extern void OS4_UpdateClipCursor(SDL_Window *window); + +extern int OS4_SetWindowHitTest(SDL_Window * window, SDL_bool enabled); + +extern int OS4_SetWindowOpacity(_THIS, SDL_Window * window, float opacity); +extern int OS4_GetWindowBordersSize(_THIS, SDL_Window * window, int * top, int * left, int * bottom, int * right); + +extern void OS4_IconifyWindow(_THIS, SDL_Window * window); +extern void OS4_UniconifyWindow(_THIS, SDL_Window * window); + +#endif /* _SDL_os4window_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/test/Makefile.amigaos4 b/test/Makefile.amigaos4 new file mode 100644 index 0000000000000..24681247318fd --- /dev/null +++ b/test/Makefile.amigaos4 @@ -0,0 +1,290 @@ +# Makefile to build the AmigaOS4 SDL tests + +CC = ppc-amigaos-gcc +CFLAGS = -gstabs -O2 -Wall -g -I../include -DHAVE_OPENGL +LIBS = -L.. -use-dynld -lSDL2_test -lSDL2 -athread=native + +TARGETS = \ + checkkeys \ + controllermap \ + helloworld \ + loopwave \ + loopwavequeue \ + sdl2benchmark \ + testatomic \ + testaudiocapture \ + testaudiohotplug \ + testaudioinfo \ + testautomation \ + testbounds \ + testcustomcursor \ + testdisplayinfo \ + testdraw2 \ + testdrawchessboard \ + testdropfile \ + testerror \ + testfile \ + testfilesystem \ + testgamecontroller \ + testgesture \ + testgl2 \ + testgles \ + testgles2 \ + testhaptic \ + testhittesting \ + testhotplug \ + testiconv \ + testime \ + testintersections \ + testjoystick \ + testkeys \ + testloadso \ + testlock \ + testmessage \ + testmultiaudio \ + testnative \ + testoffscreen \ + testoverlay2 \ + testplatform \ + testpower \ + testqsort \ + testrelative \ + testrendercopyex \ + testrendertarget \ + testresample \ + testrumble \ + testscale \ + testsem \ + testsensor \ + testshader \ + testshape \ + testsprite2 \ + testspriteminimal \ + teststreaming \ + testthread \ + testtimer \ + testurl \ + testver \ + testviewport \ + testvulkan \ + testwm2 \ + testyuv \ + torturethread \ + +all: $(TARGETS) + +checkkeys: checkkeys.o + $(CC) -o $@ $^ $(LIBS) + +helloworld: helloworld.o + $(CC) -o $@ $^ $(LIBS) + +loopwave: loopwave.o + $(CC) -o $@ $^ $(LIBS) + +loopwavequeue: loopwavequeue.o + $(CC) -o $@ $^ $(LIBS) + +sdl2benchmark: sdl2benchmark.o + $(CC) -o $@ $^ $(LIBS) + +testresample: testresample.o + $(CC) -o $@ $^ $(LIBS) + +testaudioinfo: testaudioinfo.o + $(CC) -o $@ $^ $(LIBS) + +testautomation: testautomation.o \ + testautomation_audio.o \ + testautomation_clipboard.o \ + testautomation_events.o \ + testautomation_keyboard.o \ + testautomation_main.o \ + testautomation_mouse.o \ + testautomation_pixels.o \ + testautomation_platform.o \ + testautomation_rect.o \ + testautomation_render.o \ + testautomation_rwops.o \ + testautomation_sdltest.o \ + testautomation_stdlib.o \ + testautomation_surface.o \ + testautomation_syswm.o \ + testautomation_timer.o \ + testautomation_video.o \ + testautomation_hints.o + $(CC) -o $@ $^ $(LIBS) + +testmultiaudio: testmultiaudio.o + $(CC) -o $@ $^ $(LIBS) + +testaudiohotplug: testaudiohotplug.o + $(CC) -o $@ $^ $(LIBS) + +testaudiocapture: testaudiocapture.o + $(CC) -o $@ $^ $(LIBS) + +testatomic: testatomic.o + $(CC) -o $@ $^ $(LIBS) + +testintersections: testintersections.o + $(CC) -o $@ $^ $(LIBS) + +testrelative: testrelative.o + $(CC) -o $@ $^ $(LIBS) + +testhittesting: testhittesting.o + $(CC) -o $@ $^ $(LIBS) + +testdraw2: testdraw2.o + $(CC) -o $@ $^ $(LIBS) + +testdrawchessboard: testdrawchessboard.o + $(CC) -o $@ $^ $(LIBS) + +testdropfile: testdropfile.o + $(CC) -o $@ $^ $(LIBS) + +testerror: testerror.o + $(CC) -o $@ $^ $(LIBS) + +testfile: testfile.o + $(CC) -o $@ $^ $(LIBS) + +testgamecontroller: testgamecontroller.o + $(CC) -o $@ $^ $(LIBS) + +testgesture: testgesture.o + $(CC) -o $@ $^ $(LIBS) + +testgl2: testgl2.o + $(CC) -o $@ $^ $(LIBS) + +testgles: testgles.o + $(CC) -o $@ $^ $(LIBS) + +testgles2: testgles2.o + $(CC) -o $@ $^ $(LIBS) + +testhaptic: testhaptic.o + $(CC) -o $@ $^ $(LIBS) + +testhotplug: testhotplug.o + $(CC) -o $@ $^ $(LIBS) + +testrumble: testrumble.o + $(CC) -o $@ $^ $(LIBS) + +testthread: testthread.o + $(CC) -o $@ $^ $(LIBS) + +testiconv: testiconv.o + $(CC) -o $@ $^ $(LIBS) + +testime: testime.o + $(CC) -o $@ $^ $(LIBS) + +testjoystick: testjoystick.o + $(CC) -o $@ $^ $(LIBS) + +testkeys: testkeys.o + $(CC) -o $@ $^ $(LIBS) + +testloadso: testloadso.o + $(CC) -o $@ $^ $(LIBS) + +testlock: testlock.o + $(CC) -o $@ $^ $(LIBS) + +testnative: testnative.o testnativeamigaos4.o + $(CC) -o $@ $^ $(LIBS) + +testoffscreen: testoffscreen.o + $(CC) -o $@ $^ $(LIBS) + +testoverlay2: testoverlay2.o testyuv_cvt.o + $(CC) -o $@ $^ $(LIBS) + +testplatform: testplatform.o + $(CC) -o $@ $^ $(LIBS) + +testpower: testpower.o + $(CC) -o $@ $^ $(LIBS) + +testfilesystem: testfilesystem.o + $(CC) -o $@ $^ $(LIBS) + +testrendertarget: testrendertarget.o + $(CC) -o $@ $^ $(LIBS) + +testscale: testscale.o + $(CC) -o $@ $^ $(LIBS) + +testsem: testsem.o + $(CC) -o $@ $^ $(LIBS) + +testsensor: testsensor.o + $(CC) -o $@ $^ $(LIBS) + +testshader: testshader.o + $(CC) -o $@ $^ $(LIBS) + +testshape: testshape.o + $(CC) -o $@ $^ $(LIBS) + +testsprite2: testsprite2.o + $(CC) -o $@ $^ $(LIBS) + +testspriteminimal: testspriteminimal.o + $(CC) -o $@ $^ $(LIBS) + +teststreaming: teststreaming.o + $(CC) -o $@ $^ $(LIBS) + +testtimer: testtimer.o + $(CC) -o $@ $^ $(LIBS) + +testver: testver.o + $(CC) -o $@ $^ $(LIBS) + +testviewport: testviewport.o + $(CC) -o $@ $^ $(LIBS) + +testwm2: testwm2.o + $(CC) -o $@ $^ $(LIBS) + +testyuv: testyuv.o testyuv_cvt.o + $(CC) -o $@ $^ $(LIBS) + +torturethread: torturethread.o + $(CC) -o $@ $^ $(LIBS) + +testrendercopyex: testrendercopyex.o + $(CC) -o $@ $^ $(LIBS) + +testmessage: testmessage.o + $(CC) -o $@ $^ $(LIBS) + +testdisplayinfo: testdisplayinfo.o + $(CC) -o $@ $^ $(LIBS) + +testqsort: testqsort.o + $(CC) -o $@ $^ $(LIBS) + +testbounds: testbounds.o + $(CC) -o $@ $^ $(LIBS) + +testcustomcursor: testcustomcursor.o + $(CC) -o $@ $^ $(LIBS) + +controllermap: controllermap.o + $(CC) -o $@ $^ $(LIBS) + +testvulkan: testvulkan.o + $(CC) -o $@ $^ $(LIBS) + +testurl: testurl.o + $(CC) -o $@ $^ $(LIBS) + +clean: + rm -f $(TARGETS) *.o diff --git a/test/Makefile.in b/test/Makefile.in index 6cf97ed2c27fa..65fe1fd8436df 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -222,14 +222,21 @@ testnative$(EXE): $(srcdir)/testnative.c \ $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @XLIB@ endif +ifeq (@ISAMIGAOS@,true) +testnative$(EXE): $(srcdir)/testnative.c $(srcdir)/testnativeamigaos4.c + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +endif + #there's probably a better way of doing this ifeq (@ISMACOSX@,false) ifeq (@ISWINDOWS@,false) ifeq (@ISUNIX@,false) +ifeq (@ISAMIGAOS@,false) testnative$(EXE): ; endif endif endif +endif testoverlay2$(EXE): $(srcdir)/testoverlay2.c $(srcdir)/testyuv_cvt.c $(CC) -o $@ $^ $(CFLAGS) $(LIBS) diff --git a/test/configure b/test/configure index 59e027cd90df6..e1643c9027f46 100755 --- a/test/configure +++ b/test/configure @@ -603,6 +603,7 @@ PKG_CONFIG ISUNIX ISWINDOWS ISMACOSX +ISAMIGAOS MATHLIB EXE OSMESA_CONFIG @@ -2897,8 +2898,12 @@ fi ISUNIX="false" ISWINDOWS="false" ISMACOSX="false" +ISAMIGAOS="false" case "$host" in + *-*-amigaos*) + ISAMIGAOS="true" + ;; *-*-cygwin* | *-*-mingw*) ISWINDOWS="true" EXE=".exe" diff --git a/test/configure.ac b/test/configure.ac index e2067e3adda2e..110a74353cd35 100644 --- a/test/configure.ac +++ b/test/configure.ac @@ -18,9 +18,13 @@ dnl (Haiku, for example, sets none of these.) ISUNIX="false" ISWINDOWS="false" ISMACOSX="false" +ISAMIGAOS="false" dnl Figure out which math library to use case "$host" in + *-*-amigaos*) + ISAMIGAOS="true" + ;; *-*-cygwin* | *-*-mingw*) ISWINDOWS="true" EXE=".exe" diff --git a/test/helloworld.c b/test/helloworld.c new file mode 100644 index 0000000000000..7fb93760803bb --- /dev/null +++ b/test/helloworld.c @@ -0,0 +1,868 @@ +/* + +This is not an official SDL2 test. It's a collection of random tests +for doing ad-hoc testing related to AmigaOS 4 port. + +*/ + +#include +#include "SDL2/SDL.h" +#include "SDL2/SDL_opengl.h" + +#if SDL_BYTEORDER != SDL_BIG_ENDIAN +#warning "wrong endian?" +#endif + +static SDL_bool eventLoopInner(void) +{ + SDL_bool running = SDL_TRUE; + SDL_Event e; + + while(SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_QUIT: + puts("Quit"); + running = SDL_FALSE; + break; + + case SDL_WINDOWEVENT: + { + SDL_WindowEvent * we = (SDL_WindowEvent *)&e; + printf("Window event %d window %d\n", we->event, we->windowID); + } + break; + + case SDL_SYSWMEVENT: + printf("Sys WM event\n"); + break; + + case SDL_KEYDOWN: + { + SDL_KeyboardEvent * ke = (SDL_KeyboardEvent *)&e; + printf("Key down scancode %d (%s), keycode %d (%s)\n", + ke->keysym.scancode, SDL_GetScancodeName(ke->keysym.scancode), + ke->keysym.sym, SDL_GetKeyName(ke->keysym.sym)); + } + break; + + case SDL_KEYUP: + { + SDL_KeyboardEvent * ke = (SDL_KeyboardEvent *)&e; + printf("Key up %d\n", ke->keysym.scancode); + } + break; + + case SDL_TEXTEDITING: + puts("Text editing"); + break; + + case SDL_TEXTINPUT: + { + SDL_TextEditingEvent * te = (SDL_TextEditingEvent *)&e; + SDL_Window * w = SDL_GetWindowFromID(te->windowID); + + printf("Text input '%s'\n", te->text); + + if (strcmp("q", te->text) == 0) { + running = SDL_FALSE; + } else if (strcmp("w", te->text) == 0) { + SDL_WarpMouseInWindow(w, 50, 50); + } else if (strcmp("f", te->text) == 0) { + static int t = 1; + + printf("Toggle fullscreen %d\n", t); + SDL_SetWindowFullscreen(w, t ? SDL_WINDOW_FULLSCREEN : 0); + + t ^= 1; + } else if (strcmp("t", te->text) == 0) { + puts("Change size..."); + SDL_SetWindowSize(w, rand() % 1000, rand() % 1000); + } else if (strcmp("c", te->text) == 0) { + static int c = 1; + SDL_ShowCursor(c); + c ^= 1; + } + } + break; + + case SDL_MOUSEMOTION: + { + SDL_MouseMotionEvent * me = (SDL_MouseMotionEvent *)&e; + printf("Mouse motion x=%d, y=%d, xrel=%d, yrel=%d\n", me->x, me->y, me->xrel, me->yrel); + } + break; + + case SDL_MOUSEBUTTONDOWN: + { + SDL_MouseButtonEvent * me = (SDL_MouseButtonEvent *)&me; + printf("Mouse button down %d, state %d\n", (int)me->button, (int)me->state); + } + break; + + case SDL_MOUSEBUTTONUP: + { + SDL_MouseButtonEvent * me = (SDL_MouseButtonEvent *)&me; + printf("Mouse button up %d, state %d\n", (int)me->button, (int)me->state); + } + break; + + case SDL_MOUSEWHEEL: + { + SDL_MouseWheelEvent * me = (SDL_MouseWheelEvent *)&me; + printf("Mouse wheel x=%d, y=%d\n", me->x, me->y); + } + break; + + default: + printf("Unhandled event %d\n", e.type); + break; + } + } + + return running; +} + +static void eventLoop() +{ + while (eventLoopInner()) { + SDL_Delay(1); + } +} + +static void testPath(void) +{ + char * bp = SDL_GetBasePath(); + printf("'%s'\n", bp); + SDL_free(bp); + + char* pp = SDL_GetPrefPath("foo", "bar"); + printf("'%s'\n", pp); + SDL_free(pp); +} + +static void testWindow() +{ + SDL_Window * w = SDL_CreateWindow("blah", 100, 100, 100, 100, SDL_WINDOW_RESIZABLE); + + if (w) { + SDL_SetWindowMinimumSize(w, 50, 50); + SDL_SetWindowMaximumSize(w, 200, 200); + + SDL_MinimizeWindow(w); + SDL_Delay(1000); + + SDL_RestoreWindow(w); + SDL_Delay(1000); + + SDL_MinimizeWindow(w); + SDL_Delay(1000); + + SDL_MaximizeWindow(w); + + eventLoop(); + + SDL_DestroyWindow(w); + } +} + +static void testManyWindows() +{ + SDL_Window * w = SDL_CreateWindow("blah", 100, 100, 100, 100, 0); + SDL_Window * w2 = SDL_CreateWindow("blah2", 200, 100, 100, 100, 0/*SDL_WINDOW_FULLSCREEN*/); + + if (w && w2) { + SDL_SetWindowGrab(w, SDL_TRUE); + + eventLoop(); + + SDL_DestroyWindow(w); + SDL_DestroyWindow(w2); + } +} + +static void testRelativeMouse() +{ + SDL_Window * w = SDL_CreateWindow("relative", 100, 100, 100, 100, 0); + + if (w) { + //SDL_SetRelativeMouseMode(SDL_FALSE); + //SDL_SetRelativeMouseMode(SDL_TRUE); + + eventLoop(); + + SDL_DestroyWindow(w); + } +} + +static void testFullscreen() +{ + SDL_Window * w = SDL_CreateWindow("Fullscreen", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + 640, 480, + SDL_WINDOW_FULLSCREEN); + + if (w) { + //SDL_SetWindowSize(w, 1280, 960); + //SDL_SetWindowSize(w, 640, 480); + //SDL_SetWindowSize(w, 800, 600); + + //SDL_SetWindowFullscreen(w, SDL_WINDOW_FULLSCREEN); + //SDL_SetWindowFullscreen(w, SDL_WINDOW_FULLSCREEN); + //SDL_SetWindowFullscreen(w, 0); + //SDL_SetWindowFullscreen(w, 0); + + SDL_Delay(3000); + +#if 0 + SDL_DisplayMode dm; + dm.format = SDL_PIXELFORMAT_ARGB8888; + dm.w = 1280; + dm.h = 960; + dm.refresh_rate = 0; + dm.driverdata = NULL; + + SDL_SetWindowDisplayMode(w, &dm); + SDL_SetWindowFullscreen(w, SDL_WINDOW_FULLSCREEN); +#endif + eventLoop(); + + SDL_DestroyWindow(w); + } +} + +static void testFullscreenDesktop() +{ + SDL_Window * w = SDL_CreateWindow("Desktop mode", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + 640, 400, + SDL_WINDOW_FULLSCREEN_DESKTOP); + + if (w) { + eventLoop(); + + SDL_DestroyWindow(w); + } +} + +// TODO: should load GL functions +// NOTE: will not work on OGLES2 (try testgles2.c instead of) +static void drawUsingFixedFunctionPipeline(SDL_Window *w) +{ + if (w) { + SDL_GLContext c = SDL_GL_CreateContext(w); + + if (c) { + + //SDL_GL_SetSwapInterval(1); + + Uint32 start = SDL_GetTicks(); + Uint32 frames = 0; + + while (eventLoopInner()) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_TRIANGLES); + + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + glVertex3f(-0.5f, -0.5f, 0.0f); + + glColor4f(0.0f, 1.0f, 0.0f, 1.0f); + glVertex3f(0.5f, -0.5f, 0.0f); + + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glVertex3f(0.0f, 0.5f, 0.0f); + + glEnd(); + + SDL_GL_SwapWindow(w); + frames++; + } + + Uint32 end = SDL_GetTicks(); + printf("%u frames in %u ms - %f\n", frames, end - start, 1000.f * frames / (end - start)); + + + SDL_GL_DeleteContext(c); + } + + SDL_DestroyWindow(w); + } + +} + +static SDL_Window* createWindow(const char *name) +{ + return SDL_CreateWindow(name, + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 400, + 300, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL); +} + +static void testDeleteContext() +{ + SDL_Window* w = createWindow("Context deletion"); + if (w) { + SDL_GLContext c = SDL_GL_CreateContext(w); + + if (c) { + SDL_GL_DeleteContext(c); + + printf("Context after deletion: %p\n", SDL_GL_GetCurrentContext()); + + SDL_SetWindowSize(w, 101, 101); + + c = SDL_GL_CreateContext(w); + + if (c) { + SDL_GL_DeleteContext(c); + } + } + SDL_DestroyWindow(w); + } +} + +static void testOpenGL() +{ + SDL_Window * w = createWindow("Centered & Resizable OpenGL window"); + + drawUsingFixedFunctionPipeline(w); +} + +static void testOpenGLES2() +{ + int mask, major, minor; + + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); + + printf("Current GL mask %d, major version %d, minor version %d\n", mask, major, minor); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + + SDL_Window * w = createWindow("Centered & Resizable OGLES2 window"); + + if (w) + { + SDL_GLContext c = SDL_GL_CreateContext(w); + + if (c) { + puts("OGLES2 context created, now exiting"); + SDL_GL_DeleteContext(c); + } else { + puts("Failed to create OGLES2 context"); + } + + SDL_DestroyWindow(w); + } else { + puts("Failed to create OGLES2 window"); + } + + // Restore flags + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); +} + + +static void testOpenGLSwitching() +{ + SDL_Window* w = createWindow("Centered & Resizable OpenGL window"); + + if (w) { + SDL_DestroyWindow(w); + } + + // Switch to OGLES2 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + + w = createWindow("Centered & Resizable OGLES2 window"); + + if (w) { + SDL_DestroyWindow(w); + } else { + printf("%s\n", SDL_GetError()); + } + + // Switch back to MiniGL + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + + w = createWindow("Centered & Resizable OpenGL window"); + + drawUsingFixedFunctionPipeline(w); +} + +static void testFullscreenOpenGL() +{ + SDL_Window * w = SDL_CreateWindow("Fullscreen", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 1200, + 900, + SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL); + + drawUsingFixedFunctionPipeline(w); +} + +static void testOpenGLVersion() +{ + int mask, major, minor; + + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); + + printf("Current GL mask %d, major version %d, minor version %d\n", mask, major, minor); +} + +static void testRenderer() +{ + SDL_Window * r = SDL_CreateWindow("Red", 0, 0, 100, 100, SDL_WINDOW_RESIZABLE); + SDL_Window * g = SDL_CreateWindow("Green", 200, 200, 100, 100, SDL_WINDOW_RESIZABLE); + SDL_Window * b = SDL_CreateWindow("Blue", 400, 400, 100, 100, SDL_WINDOW_RESIZABLE); + + SDL_Renderer * rr = SDL_CreateRenderer(r, -1, SDL_RENDERER_SOFTWARE); + SDL_Renderer * gr = SDL_CreateRenderer(g, -1, SDL_RENDERER_SOFTWARE); + SDL_Renderer * br = SDL_CreateRenderer(b, -1, SDL_RENDERER_ACCELERATED); + + if (r && g && b && rr && gr && br) { + while (eventLoopInner()) { + SDL_SetRenderDrawColor(rr, 255, 0, 0, 255); + SDL_RenderClear(rr); + SDL_RenderPresent(rr); + + SDL_SetRenderDrawColor(gr, 0, 255, 0, 255); + SDL_RenderClear(gr); + SDL_RenderPresent(gr); + + SDL_SetRenderDrawColor(br, 0, 0, 255, 255); + SDL_RenderClear(br); + SDL_RenderPresent(br); + } + + SDL_DestroyRenderer(rr); + SDL_DestroyRenderer(gr); + SDL_DestroyRenderer(br); + + SDL_DestroyWindow(r); + SDL_DestroyWindow(g); + SDL_DestroyWindow(b); + } else { + printf("%s\n", SDL_GetError()); + } +} + +static void testDraw() +{ + SDL_Window * w = SDL_CreateWindow("Draw", 100, 100, 200, 200, SDL_WINDOW_RESIZABLE); + + SDL_Renderer * r = SDL_CreateRenderer(w, -1, /*SDL_RENDERER_SOFTWARE*/ SDL_RENDERER_ACCELERATED); + + if (w && r) { + while (eventLoopInner()) { + SDL_Rect rect; + + SDL_SetRenderDrawColor(r, 100, 100, 100, 255); + SDL_RenderClear(r); + + SDL_SetRenderDrawColor(r, 200, 200, 200, 255); + + rect.x = 10; + rect.y = 10; + rect.w = 100; + rect.h = 100; + + SDL_RenderFillRect(r, &rect); + + SDL_RenderPresent(r); + } + + SDL_DestroyRenderer(r); + SDL_DestroyWindow(w); + } +} + +static void testRenderVsync() +{ + SDL_Window * w = SDL_CreateWindow("Draw", 100, 100, 200, 200, SDL_WINDOW_RESIZABLE); + + SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); + + SDL_Renderer * r = SDL_CreateRenderer(w, -1, /*SDL_RENDERER_SOFTWARE*/ SDL_RENDERER_ACCELERATED); + + if (w && r) { + while (eventLoopInner()) { + SDL_Rect rect; + + SDL_SetRenderDrawColor(r, 100, 100, 100, 255); + SDL_RenderClear(r); + + SDL_SetRenderDrawColor(r, 200, 200, 200, 255); + + rect.x = 10; + rect.y = 10; + rect.w = 100; + rect.h = 100; + + SDL_RenderFillRect(r, &rect); + + SDL_RenderPresent(r); + } + + SDL_DestroyRenderer(r); + SDL_DestroyWindow(w); + } +} + +static void testBmp() +{ + SDL_Surface *s = SDL_LoadBMP("sample.bmp"); + + if (s) { + SDL_FreeSurface(s); + } else { + printf("%s\n", SDL_GetError()); + } +} + +static void testMessageBox() +{ + int button = 0; + int result; + + const SDL_MessageBoxButtonData buttons[] = { + {0, 1, "button 1"}, // flags, id, text + {0, 2, "button 2"} // flags, id, text + }; + + const SDL_MessageBoxData mb = { + 0, // flags + 0, // window + "Title", + "Message", + SDL_arraysize(buttons), // numbuttons + buttons, + NULL + }; + + result = SDL_ShowMessageBox(&mb, &button); + + printf("MB returned %d, button %d\n", result, button); +} + +static void testAltivec() +{ + printf("AltiVec: %d\n", SDL_HasAltiVec()); +} + +static void testPC() +{ + Uint64 pc1 = SDL_GetPerformanceCounter(); + + SDL_Delay(1000); + + Uint64 pc2 = SDL_GetPerformanceCounter(); + + Uint64 f = SDL_GetPerformanceFrequency(); + + double result = (pc2 - pc1) / (double)f; + + printf("%f s\n", result); +} + +static void testSystemCursors() +{ + SDL_Window * w = SDL_CreateWindow("blah", 100, 100, 100, 100, 0); + + if (w) { + int c = 0; + + while (eventLoopInner()) { + + char buf[32]; + snprintf(buf, sizeof(buf), "Cursor %d", c); + + SDL_SetWindowTitle(w, buf); + + SDL_SetCursor( SDL_CreateSystemCursor(c) ); + SDL_ShowCursor(1); + + SDL_Delay(1000); + + if (++c == SDL_NUM_SYSTEM_CURSORS) { + c = 0; + SDL_ShowCursor(0); + SDL_SetWindowTitle(w, "Hidden"); + SDL_Delay(1000); + } + } + + SDL_DestroyWindow(w); + } +} + +static void testCustomCursor() +{ + int w = 64; + int h = 64; + + SDL_Surface *surface = SDL_CreateRGBSurface(0, w, h, 32, + 0x00FF0000, + 0x0000FF00, + 0x000000FF, + 0xFF000000); + + if (surface) { + + int x, y; + + //printf("pitch %d\n", surface->pitch); + + for (y = 0; y < h; y++) { + + Uint32 *p = (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch); + + Uint32 color = 0xFF000000 | rand(); + + for (x = 0; x < w; x++) { + p[x] = color; + } + } + + //SDL_FillRect(surface, NULL, 0xFFFFFFFF); + + SDL_Window * w = SDL_CreateWindow("Custom cursor", 100, 100, 100, 100, 0); + + if (w) { + + SDL_SetCursor( SDL_CreateColorCursor(surface, 0, 0)); + + while (eventLoopInner()) { + + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } + + SDL_FreeSurface(surface); + } +} + + +static void testHiddenCursor() +{ + //SDL_ShowCursor(0); + + SDL_Window * w = SDL_CreateWindow("Hidden cursor", 0, 0, 640, 480, SDL_WINDOW_FULLSCREEN); + + if (w) { + while (eventLoopInner()) { + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } +} + + +static void testClipboard() +{ + SDL_Window * w = SDL_CreateWindow("Clipboard", 100, 100, 100, 100, 0); + + if (w) { + + while (eventLoopInner()) { + + if (SDL_HasClipboardText()) { + printf("Text '%s' found\n", SDL_GetClipboardText()); + } + + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } + + puts("Leaving message to clipboard"); + + SDL_SetClipboardText("Amiga rules!"); +} + +static void testHint() +{ + char *result1 = (char *)SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS); + char *result2 = (char *)SDL_GetHint("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"); + + printf("%s, %s\n", result1, result2); +} + +static void testGlobalMouseState() +{ + SDL_Window * w = SDL_CreateWindow("Global Mouse State", 100, 100, 100, 100, 0); + + if (w) { + + while (eventLoopInner()) { + + int x = 0; + int y = 0; + + printf("State 0x%x (%d, %d)\n", SDL_GetGlobalMouseState(&x, &y), x, y); + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } +} + +static void testGlobalMouseWarp() +{ + SDL_Window * w = SDL_CreateWindow("Global Mouse Warp", 100, 100, 100, 100, 0); + + if (w) { + + while (eventLoopInner()) { + + int x = rand() % 800; + int y = rand() % 600; + + printf("Warping to %d, %d\n", x, y); + SDL_WarpMouseGlobal(x, y); + + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } +} + +static void testOpaqueWindow() +{ + SDL_Window * w = SDL_CreateWindow("Opaque window", 100, 100, 100, 100, 0); + + if (w) { + + while (eventLoopInner()) { + float opacity = 0.0f; + + while (opacity <= 1.1f) { + printf("Opacity %f\n", opacity); + SDL_SetWindowOpacity(w, opacity); + opacity += 0.1f; + SDL_Delay(100); + } + } + + SDL_DestroyWindow(w); + } +} + +static void testWindowBordersSize() +{ + SDL_Window * w = SDL_CreateWindow("BorderSizes window", 100, 100, 100, 100, SDL_WINDOW_RESIZABLE); + + if (w) { + + int top, left, bottom, right; + + SDL_GetWindowBordersSize(w, &top, &left, &bottom, &right); + + printf("top %d, left %d, bottom %d, right %d\n", top, left, bottom, right); + + while (eventLoopInner()) { + SDL_Delay(1000); + } + + SDL_DestroyWindow(w); + } +} + +static void testHiddenWindow() +{ + SDL_Window * w = SDL_CreateWindow("Hidden window", 100, 100, 100, 100, SDL_WINDOW_HIDDEN); + + if (w) { + int i = 0; + + while (eventLoopInner()) { + + SDL_Delay(1000); + + ((i++ % 2) == 0) ? SDL_ShowWindow(w) : SDL_HideWindow(w); + } + + SDL_DestroyWindow(w); + } +} + +static void testInitEverything() +{ + if (SDL_Init(SDL_INIT_EVERYTHING) == 0) { + puts("I works?"); + } else { + puts("Expected failure, there is no force feedback (haptic) here"); + } + + SDL_Quit(); +} + +int main(void) +{ + if (0) testInitEverything(); + + if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) == 0) { + if (1) testPath(); + if (0) testWindow(); + if (0) testManyWindows(); + if (0) testFullscreen(); + if (0) testFullscreenOpenGL(); + if (0) testDeleteContext(); + if (0) testOpenGL(); + if (0) testOpenGLES2(); + if (0) testOpenGLSwitching(); + if (0) testOpenGLVersion(); + if (0) testRenderer(); + if (0) testDraw(); + if (0) testMessageBox(); + if (0) testBmp(); + if (0) testAltivec(); + if (0) testFullscreenDesktop(); + if (0) testRenderVsync(); + if (0) testPC(); + if (0) testPC(); + if (0) testSystemCursors(); + if (0) testCustomCursor(); + if (0) testHiddenCursor(); + if (0) testClipboard(); + if (0) testHint(); + if (0) testGlobalMouseState(); + if (0) testGlobalMouseWarp(); + if (0) testOpaqueWindow(); + if (0) testWindowBordersSize(); + if (0) testHiddenWindow(); + if (0) testRelativeMouse(); + } else { + printf("%s\n", SDL_GetError()); + } + + SDL_Quit(); + + return 0; +} diff --git a/test/sdl2benchmark.c b/test/sdl2benchmark.c new file mode 100755 index 0000000000000..570b71af0e6cd --- /dev/null +++ b/test/sdl2benchmark.c @@ -0,0 +1,738 @@ +/* + +This is a simple SDL2 renderer benchmark tool. It test every active +renderer with available blend modes. + +On AmigaOS, result may be affected by Workbench screen depth in case +pixel conversion takes place. For example compositing renderer works +best with 32-bit screen mode. + +Some blend modes may not be supported for all renderers. These tests +will give failure. + +TODO: +- command line arguments for things like window size, iterations... + +*/ + +#include "SDL2/SDL.h" + +#define BENCHMARK_VERSION "0.6" + +#define WIDTH 800 +#define HEIGHT 600 + +#define RECTSIZE 100 + +#define DURATION 1.0 +#define OBJECTS 100 + +#define SLEEP 0 + +#ifdef __amigaos4__ +static const char stackCookie[] __attribute__((used)) = "$STACK:60000"; +#endif + +typedef struct { + SDL_Renderer *renderer; + SDL_Window *window; + SDL_Texture *texture; + SDL_Surface *surface; + SDL_BlendMode mode; + Uint32 width; + Uint32 height; + Uint32 rectsize; + Uint32 texturewidth; + Uint32 textureheight; + Uint64 frequency; + double duration; + Uint32 objects; + Uint32 sleep; + Uint32 frames; + Uint32 operations; + Uint32 *buffer; + SDL_bool running; + const char* rendname; +} Context; + +typedef struct { + const char *name; + SDL_bool (*testfp)(Context *); + SDL_bool usetexture; +} Test; + +typedef struct { + const char *name; + SDL_BlendMode mode; +} BlendMode; + +/* Test function prototypes */ +static SDL_bool testPoints(Context *); +static SDL_bool testLines(Context *); +static SDL_bool testFillRects(Context *); +static SDL_bool testRenderCopy(Context *); +static SDL_bool testRenderCopyEx(Context *); +static SDL_bool testColorModulation(Context *); +static SDL_bool testAlphaModulation(Context *); +static SDL_bool testUpdateTexture(Context *); +static SDL_bool testReadPixels(Context *); + +/* Insert here new tests */ +static const Test tests[] = { + { "Points", testPoints, SDL_FALSE }, + { "Lines", testLines, SDL_FALSE }, + { "FillRects", testFillRects, SDL_FALSE }, + { "RenderCopy", testRenderCopy, SDL_TRUE }, + { "RenderCopyEx", testRenderCopyEx, SDL_TRUE }, + { "Color modulation", testColorModulation, SDL_TRUE }, + { "Alpha modulation", testAlphaModulation, SDL_TRUE }, + { "UpdateTexture", testUpdateTexture, SDL_TRUE }, + { "ReadPixels", testReadPixels, SDL_TRUE } +}; + +static const BlendMode modes[] = { + { "None", SDL_BLENDMODE_NONE }, + { "Blend", SDL_BLENDMODE_BLEND }, + { "Add", SDL_BLENDMODE_ADD }, + { "Mod", SDL_BLENDMODE_MOD } +}; + +static const char *getModeName(SDL_BlendMode mode) +{ + int i; + + static const char *unknown = "Unknown"; + + for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) + { + if (modes[i].mode == mode) { + return modes[i].name; + } + } + + return unknown; +} + +static void printInfo(Context *ctx) +{ + SDL_RendererInfo ri; + int result; + + result = SDL_GetRendererInfo(ctx->renderer, &ri); + + if (result) { + SDL_Log("Failed to get renderer info: %s\n", SDL_GetError()); + } else { + + SDL_Log("Starting to test renderer called [%s], flags 0x%X\n", ri.name, ri.flags); + } +} + +static void render(Context *ctx) +{ + SDL_RenderPresent(ctx->renderer); + ctx->frames++; +} + +static SDL_bool clearDisplay(Context *ctx) +{ + int result; + + if (ctx->mode != SDL_BLENDMODE_MOD) { + result = SDL_SetRenderDrawColor(ctx->renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + } else { + result = SDL_SetRenderDrawColor(ctx->renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); + } + + if (result) { + SDL_Log("[%s]Failed to set draw color: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + result = SDL_RenderClear(ctx->renderer); + + if (result) { + SDL_Log("[%s]Failed to clear: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + SDL_RenderPresent(ctx->renderer); + + return SDL_TRUE; +} + +/* +static float interpolate(float min, float max, float percentage) +{ + return min + percentage * (max - min); +} +*/ + +static Uint32 getRand(Uint32 max) +{ + return rand() % max; +} + +static void makeRandomTexture(Context *ctx) +{ + int i; + + SDL_memset(ctx->buffer, 0, ctx->texturewidth * ctx->textureheight * sizeof(Uint32)); + + for (i = 0; i < 100; i++) { + ctx->buffer[ + getRand(ctx->texturewidth) + + getRand(ctx->textureheight) * ctx->texturewidth] = 0xFFFFFFFF; + } +} + +static SDL_bool prepareTexture(Context *ctx) +{ + int result; + + result = SDL_SetColorKey(ctx->surface, 1, 0); + + if (result) { + SDL_Log("[%s]Failed to set color key: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + if (ctx->texture) { + SDL_Log("Old texture!\n"); + } + + ctx->texture = SDL_CreateTextureFromSurface(ctx->renderer, ctx->surface); + + if (!ctx->texture) { + SDL_Log("[%s]Failed to create texture: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + result = SDL_SetTextureBlendMode(ctx->texture, ctx->mode); + + if (result) { + SDL_Log("[%s]Failed to set texture blend mode: %s\n", __FUNCTION__, SDL_GetError()); + + SDL_DestroyTexture(ctx->texture); + ctx->texture = NULL; + + return SDL_FALSE; + } + + ctx->texturewidth = ctx->surface->w; + ctx->textureheight = ctx->surface->h; + + ctx->buffer = SDL_malloc(ctx->texturewidth * ctx->textureheight * sizeof(Uint32)); + + if (!ctx->buffer) { + SDL_Log("[%s]Failed to allocate texture buffer: %s\n", __FUNCTION__, SDL_GetError()); + SDL_DestroyTexture(ctx->texture); + ctx->texture = NULL; + return SDL_FALSE; + } + + makeRandomTexture(ctx); + + return SDL_TRUE; +} + +static SDL_bool prepareTest(Context *ctx, const Test *test) +{ + if (!clearDisplay(ctx)) { + return SDL_FALSE; + } + + if (test->usetexture) { + if (!prepareTexture(ctx)) { + return SDL_FALSE; + } + } + + ctx->frames = 0; + ctx->operations = 0; + + return SDL_TRUE; +} + +static void afterTest(Context *ctx) +{ + if (ctx->texture) { + SDL_DestroyTexture(ctx->texture); + ctx->texture = NULL; + } + + if (ctx->buffer) { + SDL_free(ctx->buffer); + ctx->buffer = NULL; + } + + if (ctx->sleep) { + SDL_Delay(ctx->sleep); + } +} + +static SDL_bool runTest(Context *ctx, const Test *test) +{ + Uint64 start, finish; + double duration; + float fps, ops; + + if (!prepareTest(ctx, test)) { + return SDL_FALSE; + } + + start = SDL_GetPerformanceCounter(); + + do { + if (!test->testfp(ctx)) { + afterTest(ctx); + return SDL_FALSE; + } + + finish = SDL_GetPerformanceCounter(); + + duration = (finish - start) / (double)ctx->frequency; + } while (duration < ctx->duration); + + if (duration == 0.0) { + SDL_Log("Division by zero!\n"); + afterTest(ctx); + return SDL_FALSE; + } + + fps = ctx->frames / duration; + ops = ctx->operations / duration; + + if (fps == ops) { + SDL_Log("%s [mode: %s]...%d frames drawn in %.3f seconds => %.1f frames per second\n", + test->name, getModeName(ctx->mode), ctx->frames, duration, fps); + } else { + SDL_Log("%s [mode: %s]...%d frames drawn in %.3f seconds => %.1f frames per second, %.1f operations per second\n", + test->name, getModeName(ctx->mode), ctx->frames, duration, fps, ops); + } + + afterTest(ctx); + + return SDL_TRUE; +} + +static SDL_bool setRandomColor(Context *ctx) +{ + int result; + + result = SDL_SetRenderDrawColor(ctx->renderer, + getRand(256), getRand(256), getRand(256), getRand(256)); + + if (result) { + SDL_Log("[%s]Failed to set color: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + return SDL_TRUE; +} + +static SDL_bool testPointsInner(Context *ctx, SDL_bool linemode) +{ + int result = SDL_SetRenderDrawBlendMode(ctx->renderer, ctx->mode); + + if (result) { + SDL_Log("[%s]Failed to set blend mode: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + SDL_Point points[ctx->objects]; + int object; + + if (!setRandomColor(ctx)) { + return SDL_FALSE; + } + + for (object = 0; object < ctx->objects; object++) { + points[object].x = getRand(ctx->width); + points[object].y = getRand(ctx->height); + } + + result = linemode ? + SDL_RenderDrawLines(ctx->renderer, points, ctx->objects) : + SDL_RenderDrawPoints(ctx->renderer, points, ctx->objects); + + ctx->operations++; + + if (result) { + SDL_Log("[%s]Failed to draw lines/points: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + render(ctx); + + return SDL_TRUE; +} + +static SDL_bool testPoints(Context *ctx) +{ + return testPointsInner(ctx, SDL_FALSE); +} + +static SDL_bool testLines(Context *ctx) +{ + return testPointsInner(ctx, SDL_TRUE); +} + +static SDL_bool testFillRects(Context *ctx) +{ + int result = SDL_SetRenderDrawBlendMode(ctx->renderer, ctx->mode); + + if (result) { + SDL_Log("[%s]Failed to set blend mode: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + SDL_Rect rects[ctx->objects]; + int object; + + if (!setRandomColor(ctx)) { + return SDL_FALSE; + } + + const int rectsize = ctx->rectsize + getRand(100); // + iteration + + for (object = 0; object < ctx->objects; object++) { + rects[object].x = getRand(ctx->width - rectsize); + rects[object].y = getRand(ctx->height - rectsize); + rects[object].w = rectsize; + rects[object].h = rectsize; + } + + result = SDL_RenderFillRects(ctx->renderer, rects, ctx->objects); + + if (result) { + SDL_Log("[%s]Failed to draw filled rectangles: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + ctx->operations++; + + render(ctx); + + return SDL_TRUE; +} + +static SDL_bool testRenderCopyInner(Context *ctx, SDL_bool ex) +{ + int result; + + //int object; + //const float scale = interpolate(0.5f, 2.0f, (float)ctx->iteration / ctx->iterations); + const float scale = (getRand(4) + 1) / 2.0f; + + int w = ctx->texturewidth * scale; + int h = ctx->textureheight * scale; + + //for (object = 0; object < ctx->objects; object++) { + SDL_Rect rect; + + rect.x = getRand(ctx->width - w); + rect.y = getRand(ctx->height - h); + rect.w = w; + rect.h = h; + + if (!ex) { + result = SDL_RenderCopy(ctx->renderer, ctx->texture, NULL, &rect); + } else { + result = SDL_RenderCopyEx( + ctx->renderer, + ctx->texture, + NULL, + &rect, + getRand(360), + NULL, + SDL_FLIP_NONE); + } + + if (result) { + SDL_Log("[%s]Failed to draw texture: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + ctx->operations++; + //} + + render(ctx); + + return SDL_TRUE; +} + +static SDL_bool testRenderCopy(Context *ctx) +{ + return testRenderCopyInner(ctx, SDL_FALSE); +} + +static SDL_bool testRenderCopyEx(Context *ctx) +{ + return testRenderCopyInner(ctx, SDL_TRUE); +} + +static const SDL_Color colors[] = { + {255, 0, 0, 255}, + {0, 255, 0, 255}, + {0, 0, 255, 255}, + {127, 127, 127, 255} +}; + +static const size_t count = sizeof(colors) / sizeof(colors[0]); + +static SDL_bool testColorModulation(Context *ctx) +{ + static int i = 0; + + const int c = i++ % count; + + if (SDL_SetTextureColorMod(ctx->texture, colors[c].r, colors[c].g, colors[c].b)) { + SDL_Log("[%s]Failed to set color modulation: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + return testRenderCopyInner(ctx, SDL_FALSE); +} + +static SDL_bool testAlphaModulation(Context *ctx) +{ + if (SDL_SetTextureAlphaMod(ctx->texture, 127)) { + SDL_Log("[%s]Failed to set alpha modulation: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + return testRenderCopyInner(ctx, SDL_FALSE); +} + +static SDL_bool testUpdateTexture(Context *ctx) +{ + static int i = 0; + + const int c = i++ % count; + + if (SDL_SetTextureColorMod(ctx->texture, colors[c].r, colors[c].g, colors[c].b)) { + SDL_Log("[%s]Failed to set color modulation: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + if (SDL_UpdateTexture(ctx->texture, NULL, ctx->buffer, ctx->texturewidth * sizeof(Uint32))) { + SDL_Log("[%s]Failed to update texture: %s\n", __FUNCTION__, SDL_GetError()); + return SDL_FALSE; + } + + ctx->operations++; + + return testRenderCopyInner(ctx, SDL_FALSE); +} + +static SDL_bool testReadPixels(Context *ctx) +{ + SDL_bool result = SDL_TRUE; + + SDL_Rect rect; + rect.x = getRand(ctx->width - ctx->texturewidth); + rect.y = getRand(ctx->height - ctx->textureheight); + rect.w = ctx->texturewidth; + rect.h = ctx->textureheight; + + if (SDL_RenderReadPixels( + ctx->renderer, + &rect, + SDL_PIXELFORMAT_ARGB8888, + ctx->buffer, + ctx->texturewidth * sizeof(Uint32)) != 0) { + + SDL_Log("[%s]Failed to read pixels: %s\n", __FUNCTION__, SDL_GetError()); + + result = SDL_FALSE; + } + + ctx->operations++; + + return result; +} + +static void checkEvents(Context *ctx) +{ + SDL_Event e; + + while (SDL_PollEvent(&e)) { + if (e.type == SDL_KEYDOWN) { + SDL_KeyboardEvent *ke = (SDL_KeyboardEvent *)&e; + + if (ke->keysym.sym == SDLK_ESCAPE) { + SDL_Log("Quitting...\n"); + ctx->running = SDL_FALSE; + } + } + } +} + +static void runTestSuite(Context *ctx) +{ + int m, t; + + for (t = 0; t < sizeof(tests) / sizeof(tests[0]); t++) { + for (m = 0; m < sizeof(modes) / sizeof(modes[0]); m++) { + ctx->mode = modes[m].mode; + + runTest(ctx, &tests[t]); + + checkEvents(ctx); + + if (!ctx->running) { + return; + } + } + } +} + +/* TODO: need proper handling */ +static void checkParameters(Context *ctx, int argc, char **argv) +{ + if (argc > 3) { + ctx->sleep = atoi(argv[3]); + } + + if (argc > 2) { + ctx->duration = atof(argv[2]); + } + + if (argc > 1) { + ctx->rendname = argv[1]; + } +} + +static void initContext(Context *ctx, int argc, char **argv) +{ + SDL_memset(ctx, 0, sizeof(Context)); + + ctx->frequency = SDL_GetPerformanceFrequency(); + + ctx->width = WIDTH; + ctx->height = HEIGHT; + ctx->rectsize = RECTSIZE; + ctx->duration = DURATION; + ctx->objects = OBJECTS; + ctx->sleep = SLEEP; + ctx->running = SDL_TRUE; + + checkParameters(ctx, argc, argv); + + SDL_Log("Parameters: width %d, height %d, renderer name '%s', duration %.3f s, objects %u, sleep %u\n", + ctx->width, ctx->height, ctx->rendname, ctx->duration, ctx->objects, ctx->sleep); +} + +static void checkPixelFormat(Context *ctx) +{ + Uint32 pf; + + pf = SDL_GetWindowPixelFormat(ctx->window); + + SDL_Log("Pixel format 0x%X (%s)\n", pf, SDL_GetPixelFormatName(pf)); + + if (pf != SDL_PIXELFORMAT_ARGB8888 && pf != SDL_PIXELFORMAT_RGB888) { + SDL_Log("NOTE: window's pixel format not ARGB8888 - possible bitmap conversion can slow down\n"); + } +} + +static void testRenderer(Context *ctx) +{ + if (ctx->renderer) { + printInfo(ctx); + + runTestSuite(ctx); + + SDL_DestroyRenderer(ctx->renderer); + } else { + SDL_Log("Failed to create renderer: %s\n", SDL_GetError()); + } +} + +static void testSpecificRenderer(Context *ctx) +{ + SDL_SetHint(SDL_HINT_RENDER_DRIVER, ctx->rendname); + + ctx->renderer = SDL_CreateRenderer(ctx->window, -1, 0); + + testRenderer(ctx); +} + +static void testAllRenderers(Context *ctx) +{ + int r; + + for (r = 0; r < SDL_GetNumRenderDrivers(); r++) { + + ctx->renderer = SDL_CreateRenderer(ctx->window, r, 0); + + testRenderer(ctx); + + if (!ctx->running) { + break; + } + } +} + +int main(int argc, char **argv) +{ + Context ctx; + SDL_version linked; + + if (SDL_Init(SDL_INIT_VIDEO)) { + SDL_Log("Init failed: %s\n", SDL_GetError()); + return -1; + } + + SDL_GetVersion(&linked); + + SDL_Log("SDL2 renderer benchmark v. " BENCHMARK_VERSION " (SDL version %d.%d.%d)\n", + linked.major, linked.minor, linked.patch); + + SDL_Log("This tool measures the speed of various 2D drawing features\n"); + SDL_Log("Press ESC key to quit\n"); + + initContext(&ctx, argc, argv); + + ctx.surface = SDL_LoadBMP("sample.bmp"); + + if (ctx.surface) { + + SDL_Log("Image size %d*%d\n", ctx.surface->w, ctx.surface->h); + + ctx.window = SDL_CreateWindow( + "SDL2 benchmark", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + ctx.width, + ctx.height, + SDL_WINDOW_FULLSCREEN); + + if (ctx.window) { + + checkPixelFormat(&ctx); + + if (ctx.rendname) { + testSpecificRenderer(&ctx); + } else { + testAllRenderers(&ctx); + } + + SDL_DestroyWindow(ctx.window); + } else { + SDL_Log("Failed to create window: %s\n", SDL_GetError()); + } + + SDL_FreeSurface(ctx.surface); + + } else { + SDL_Log("Failed do load image: %s\n", SDL_GetError()); + } + + SDL_Log("Bye bye\n"); + + SDL_Quit(); + + return 0; +} diff --git a/test/testautomation_rwops.c b/test/testautomation_rwops.c index a7d3c32725ad2..879abe1a425b9 100644 --- a/test/testautomation_rwops.c +++ b/test/testautomation_rwops.c @@ -398,7 +398,11 @@ rwops_testFPRead(void) int result; /* Run read tests. */ +#ifdef __amigaos4__ + fp = fopen64(RWopsReadTestFilename, "r"); +#else fp = fopen(RWopsReadTestFilename, "r"); +#endif SDLTest_AssertCheck(fp != NULL, "Verify handle from opening file '%s' in read mode is not NULL", RWopsReadTestFilename); /* Bail out if NULL */ @@ -448,7 +452,11 @@ rwops_testFPWrite(void) int result; /* Run write tests. */ +#ifdef __amigaos4__ + fp = fopen64(RWopsWriteTestFilename, "w+"); +#else fp = fopen(RWopsWriteTestFilename, "w+"); +#endif SDLTest_AssertCheck(fp != NULL, "Verify handle from opening file '%s' in write mode is not NULL", RWopsWriteTestFilename); /* Bail out if NULL */ diff --git a/test/testgles2.c b/test/testgles2.c index 4a223755aaf64..3aa6cd6c6f5ef 100644 --- a/test/testgles2.c +++ b/test/testgles2.c @@ -21,7 +21,7 @@ #include "SDL_test_common.h" #if defined(__IPHONEOS__) || defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__NACL__) \ - || defined(__WINDOWS__) || defined(__LINUX__) + || defined(__WINDOWS__) || defined(__LINUX__) || defined(__AMIGAOS4__) #define HAVE_OPENGLES2 #endif @@ -31,7 +31,7 @@ typedef struct GLES2_Context { -#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; +#define SDL_PROC(ret,func,params) ret (APIENTRY *my##func) params; #include "../src/render/opengles2/SDL_gles2funcs.h" #undef SDL_PROC } GLES2_Context; @@ -53,12 +53,12 @@ static int LoadContext(GLES2_Context * data) #endif #if defined __SDL_NOGETPROCADDR__ -#define SDL_PROC(ret,func,params) data->func=func; +#define SDL_PROC(ret,func,params) data->my##func=func; #else #define SDL_PROC(ret,func,params) \ do { \ - data->func = SDL_GL_GetProcAddress(#func); \ - if ( ! data->func ) { \ + data->my##func = SDL_GL_GetProcAddress(#func); \ + if ( ! data->my##func ) { \ return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \ } \ } while ( 0 ); @@ -92,7 +92,7 @@ quit(int rc) #define GL_CHECK(x) \ x; \ { \ - GLenum glError = ctx.glGetError(); \ + GLenum glError = ctx.myglGetError(); \ if(glError != GL_NO_ERROR) { \ SDL_Log("glGetError() = %i (0x%.8x) at line %i\n", glError, glError, __LINE__); \ quit(1); \ @@ -204,22 +204,22 @@ process_shader(GLuint *shader, const char * source, GLint shader_type) GLsizei length; /* Create shader and load into GL. */ - *shader = GL_CHECK(ctx.glCreateShader(shader_type)); + *shader = GL_CHECK(ctx.myglCreateShader(shader_type)); shaders[0] = source; - GL_CHECK(ctx.glShaderSource(*shader, 1, shaders, NULL)); + GL_CHECK(ctx.myglShaderSource(*shader, 1, shaders, NULL)); /* Clean up shader source. */ shaders[0] = NULL; /* Try compiling the shader. */ - GL_CHECK(ctx.glCompileShader(*shader)); - GL_CHECK(ctx.glGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); + GL_CHECK(ctx.myglCompileShader(*shader)); + GL_CHECK(ctx.myglGetShaderiv(*shader, GL_COMPILE_STATUS, &status)); /* Dump debug info (source and log) if compilation failed. */ if(status != GL_TRUE) { - ctx.glGetProgramInfoLog(*shader, sizeof(buffer), &length, &buffer[0]); + ctx.myglGetProgramInfoLog(*shader, sizeof(buffer), &length, &buffer[0]); buffer[length] = '\0'; SDL_Log("Shader compilation failed: %s", buffer);fflush(stderr); quit(-1); @@ -396,7 +396,7 @@ Render(unsigned int width, unsigned int height, shader_data* data) perspective_matrix(45.0f, (float)width/height, 0.01f, 100.0f, matrix_perspective); multiply_matrix(matrix_perspective, matrix_modelview, matrix_mvp); - GL_CHECK(ctx.glUniformMatrix4fv(data->attr_mvp, 1, GL_FALSE, matrix_mvp)); + GL_CHECK(ctx.myglUniformMatrix4fv(data->attr_mvp, 1, GL_FALSE, matrix_mvp)); data->angle_x += 3; data->angle_y += 2; @@ -409,8 +409,8 @@ Render(unsigned int width, unsigned int height, shader_data* data) if(data->angle_z >= 360) data->angle_z -= 360; if(data->angle_z < 0) data->angle_z += 360; - GL_CHECK(ctx.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); - GL_CHECK(ctx.glDrawArrays(GL_TRIANGLES, 0, 36)); + GL_CHECK(ctx.myglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); + GL_CHECK(ctx.myglDrawArrays(GL_TRIANGLES, 0, 36)); } int done; @@ -440,7 +440,7 @@ void loop() } /* Change view port to the new window dimensions */ SDL_GL_GetDrawableSize(state->windows[i], &w, &h); - ctx.glViewport(0, 0, w, h); + ctx.myglViewport(0, 0, w, h); state->window_w = event.window.data1; state->window_h = event.window.data2; /* Update window content */ @@ -580,10 +580,10 @@ main(int argc, char *argv[]) SDL_GetCurrentDisplayMode(0, &mode); SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode.format)); SDL_Log("\n"); - SDL_Log("Vendor : %s\n", ctx.glGetString(GL_VENDOR)); - SDL_Log("Renderer : %s\n", ctx.glGetString(GL_RENDERER)); - SDL_Log("Version : %s\n", ctx.glGetString(GL_VERSION)); - SDL_Log("Extensions : %s\n", ctx.glGetString(GL_EXTENSIONS)); + SDL_Log("Vendor : %s\n", ctx.myglGetString(GL_VENDOR)); + SDL_Log("Renderer : %s\n", ctx.myglGetString(GL_RENDERER)); + SDL_Log("Version : %s\n", ctx.myglGetString(GL_VERSION)); + SDL_Log("Extensions : %s\n", ctx.myglGetString(GL_EXTENSIONS)); SDL_Log("\n"); status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value); @@ -655,7 +655,7 @@ main(int argc, char *argv[]) continue; } SDL_GL_GetDrawableSize(state->windows[i], &w, &h); - ctx.glViewport(0, 0, w, h); + ctx.myglViewport(0, 0, w, h); data = &datas[i]; data->angle_x = 0; data->angle_y = 0; data->angle_z = 0; @@ -665,32 +665,32 @@ main(int argc, char *argv[]) process_shader(&data->shader_frag, _shader_frag_src, GL_FRAGMENT_SHADER); /* Create shader_program (ready to attach shaders) */ - data->shader_program = GL_CHECK(ctx.glCreateProgram()); + data->shader_program = GL_CHECK(ctx.myglCreateProgram()); /* Attach shaders and link shader_program */ - GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_vert)); - GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_frag)); - GL_CHECK(ctx.glLinkProgram(data->shader_program)); + GL_CHECK(ctx.myglAttachShader(data->shader_program, data->shader_vert)); + GL_CHECK(ctx.myglAttachShader(data->shader_program, data->shader_frag)); + GL_CHECK(ctx.myglLinkProgram(data->shader_program)); /* Get attribute locations of non-fixed attributes like color and texture coordinates. */ - data->attr_position = GL_CHECK(ctx.glGetAttribLocation(data->shader_program, "av4position")); - data->attr_color = GL_CHECK(ctx.glGetAttribLocation(data->shader_program, "av3color")); + data->attr_position = GL_CHECK(ctx.myglGetAttribLocation(data->shader_program, "av4position")); + data->attr_color = GL_CHECK(ctx.myglGetAttribLocation(data->shader_program, "av3color")); /* Get uniform locations */ - data->attr_mvp = GL_CHECK(ctx.glGetUniformLocation(data->shader_program, "mvp")); + data->attr_mvp = GL_CHECK(ctx.myglGetUniformLocation(data->shader_program, "mvp")); - GL_CHECK(ctx.glUseProgram(data->shader_program)); + GL_CHECK(ctx.myglUseProgram(data->shader_program)); /* Enable attributes for position, color and texture coordinates etc. */ - GL_CHECK(ctx.glEnableVertexAttribArray(data->attr_position)); - GL_CHECK(ctx.glEnableVertexAttribArray(data->attr_color)); + GL_CHECK(ctx.myglEnableVertexAttribArray(data->attr_position)); + GL_CHECK(ctx.myglEnableVertexAttribArray(data->attr_color)); /* Populate attributes for position, color and texture coordinates etc. */ - GL_CHECK(ctx.glVertexAttribPointer(data->attr_position, 3, GL_FLOAT, GL_FALSE, 0, _vertices)); - GL_CHECK(ctx.glVertexAttribPointer(data->attr_color, 3, GL_FLOAT, GL_FALSE, 0, _colors)); + GL_CHECK(ctx.myglVertexAttribPointer(data->attr_position, 3, GL_FLOAT, GL_FALSE, 0, _vertices)); + GL_CHECK(ctx.myglVertexAttribPointer(data->attr_color, 3, GL_FLOAT, GL_FALSE, 0, _colors)); - GL_CHECK(ctx.glEnable(GL_CULL_FACE)); - GL_CHECK(ctx.glEnable(GL_DEPTH_TEST)); + GL_CHECK(ctx.myglEnable(GL_CULL_FACE)); + GL_CHECK(ctx.myglEnable(GL_DEPTH_TEST)); } /* Main render loop */ diff --git a/test/testnative.c b/test/testnative.c index 21aee04c1631f..11504f0fba292 100644 --- a/test/testnative.c +++ b/test/testnative.c @@ -32,6 +32,9 @@ static NativeWindowFactory *factories[] = { #ifdef TEST_NATIVE_COCOA &CocoaWindowFactory, #endif +#ifdef TEST_NATIVE_AMIGAOS4 + &AmigaOS4WindowFactory, +#endif #ifdef TEST_NATIVE_OS2 &OS2WindowFactory, #endif diff --git a/test/testnative.h b/test/testnative.h index 611d99147aba2..c02e505e99b87 100644 --- a/test/testnative.h +++ b/test/testnative.h @@ -36,6 +36,11 @@ extern NativeWindowFactory WindowsWindowFactory; extern NativeWindowFactory X11WindowFactory; #endif +#ifdef SDL_VIDEO_DRIVER_AMIGAOS4 +#define TEST_NATIVE_AMIGAOS4 +extern NativeWindowFactory AmigaOS4WindowFactory; +#endif + #ifdef SDL_VIDEO_DRIVER_COCOA /* Actually, we don't really do this, since it involves adding Objective C support to the build system, which is a little tricky. You can uncomment diff --git a/test/testnativeamigaos4.c b/test/testnativeamigaos4.c new file mode 100644 index 0000000000000..e01c572dc5971 --- /dev/null +++ b/test/testnativeamigaos4.c @@ -0,0 +1,92 @@ +/* + Copyright (C) 1997-2017 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ + +#include "testnative.h" + +#ifdef TEST_NATIVE_AMIGAOS4 + +#include +#include + +#include "../src/video/amigaos4/SDL_os4video.h" + +static struct Library * MyIntuitionBase; +static struct IntuitionIFace * MyIIntuition; + +static void *CreateWindowAmigaOS4(int w, int h); +static void DestroyWindowAmigaOS4(void *window); + +NativeWindowFactory AmigaOS4WindowFactory = { + "os4", + CreateWindowAmigaOS4, + DestroyWindowAmigaOS4 +}; + +static SDL_bool +OS4_OpenIntuition() +{ + SDL_bool result = SDL_FALSE; + + if (MyIIntuition) { + result = SDL_TRUE; + } else { + MyIntuitionBase = IExec->OpenLibrary("intuition.library", 50); + + if (MyIntuitionBase) { + MyIIntuition = (struct IntuitionIFace *) IExec->GetInterface(MyIntuitionBase, "main", 1, NULL); + if (MyIIntuition) { + result = SDL_TRUE; + } + } + } + + return result; +} + +static void * +CreateWindowAmigaOS4(int w, int h) +{ + struct Window * window = NULL; + + if (OS4_OpenIntuition()) { + + struct MsgPort * userport = OS4_GetSharedMessagePort(); + + if (userport) { + window = MyIIntuition->OpenWindowTags( + NULL, + WA_Title, "Native window", + WA_InnerWidth, w, + WA_InnerHeight, h, + WA_Flags, WFLG_CLOSEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW, + WA_UserPort, userport, + TAG_DONE); + } + } + + return (void *) window; +} + +static void +DestroyWindowAmigaOS4(void *window) +{ + if (OS4_OpenIntuition()) { + MyIIntuition->CloseWindow(window); + + IExec->DropInterface((struct Interface *)MyIIntuition); + IExec->CloseLibrary(MyIntuitionBase); + } +} + +#endif + diff --git a/test/testoverlay2.c b/test/testoverlay2.c index 6afac4940ed72..c06232e7e0daf 100644 --- a/test/testoverlay2.c +++ b/test/testoverlay2.c @@ -32,6 +32,10 @@ #define MOOSEFRAME_SIZE (MOOSEPIC_W * MOOSEPIC_H) #define MOOSEFRAMES_COUNT 10 +#ifdef __amigaos4__ +static const char STACK_COOKIE[] __attribute__((used)) = "$STACK:200000"; +#endif + SDL_Color MooseColors[84] = { {49, 49, 49, SDL_ALPHA_OPAQUE} , {66, 24, 0, SDL_ALPHA_OPAQUE}