Merged default into iOS-improvements
--HG-- branch : iOS-improvements
This commit is contained in:
commit
fdce275074
63 changed files with 3607 additions and 920 deletions
|
@ -34,7 +34,7 @@ LOCAL_SRC_FILES := \
|
|||
$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/power/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/filesystem/dummy/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/filesystem/android/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/render/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/render/*/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \
|
||||
|
|
|
@ -237,6 +237,7 @@ set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SY
|
|||
set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS})
|
||||
set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS})
|
||||
set_option(VIDEO_MIR "Use Mir video driver" ${UNIX_SYS})
|
||||
set_option(VIDEO_RPI "Use Raspberry Pi video driver" ${UNIX_SYS})
|
||||
dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF)
|
||||
set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm)
|
||||
foreach(_SUB ${SDL_X11_OPTIONS})
|
||||
|
@ -330,11 +331,22 @@ if(USE_GCC OR USE_CLANG)
|
|||
|
||||
check_c_compiler_flag(-Wall HAVE_GCC_WALL)
|
||||
if(HAVE_GCC_WALL)
|
||||
list(APPEND EXTRA_CFLAGS "-Wall")
|
||||
if(HAIKU)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
|
||||
endif()
|
||||
endif()
|
||||
#check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
|
||||
check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
|
||||
if(HAVE_GCC_WSHADOW)
|
||||
list(APPEND EXTRA_CFLAGS "-Wshadow")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
|
||||
check_c_compiler_flag("" HAVE_NO_UNDEFINED)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
if(HAVE_NO_UNDEFINED)
|
||||
list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ASSEMBLY)
|
||||
|
@ -658,6 +670,8 @@ if(UNIX AND NOT APPLE)
|
|||
endif()
|
||||
|
||||
if(SDL_VIDEO)
|
||||
# Need to check for Raspberry PI first and add platform specific compiler flags, otherwise the test for GLES fails!
|
||||
CheckRPI()
|
||||
CheckX11()
|
||||
CheckMir()
|
||||
CheckDirectFB()
|
||||
|
@ -805,6 +819,7 @@ elseif(WINDOWS)
|
|||
check_include_file(dsound.h HAVE_DSOUND_H)
|
||||
check_include_file(dinput.h HAVE_DINPUT_H)
|
||||
check_include_file(xaudio2.h HAVE_XAUDIO2_H)
|
||||
check_include_file(xinput.h HAVE_XINPUT_H)
|
||||
check_include_file(dxgi.h HAVE_DXGI_H)
|
||||
if(HAVE_D3D_H OR HAVE_D3D11_H OR HAVE_DDRAW_H OR HAVE_DSOUND_H OR HAVE_DINPUT_H OR HAVE_XAUDIO2_H)
|
||||
set(HAVE_DIRECTX TRUE)
|
||||
|
@ -910,21 +925,31 @@ elseif(WINDOWS)
|
|||
endif()
|
||||
|
||||
if(SDL_JOYSTICK)
|
||||
file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/windows/*.c)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
|
||||
if(HAVE_DINPUT_H)
|
||||
set(SDL_JOYSTICK_DINPUT 1)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/joystick/windows/SDL_dxjoystick.c)
|
||||
list(APPEND EXTRA_LIBS dinput8 dxguid dxerr)
|
||||
else()
|
||||
endif()
|
||||
if(HAVE_XINPUT_H)
|
||||
set(SDL_JOYSTICK_XINPUT 1)
|
||||
endif()
|
||||
if(NOT HAVE_DINPUT_H AND NOT HAVE_XINPUT_H)
|
||||
set(SDL_JOYSTICK_WINMM 1)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/joystick/windows/SDL_mmjoystick.c)
|
||||
endif()
|
||||
set(HAVE_SDL_JOYSTICK TRUE)
|
||||
endif()
|
||||
|
||||
if(SDL_HAPTIC AND HAVE_DINPUT_H)
|
||||
set(SDL_HAPTIC_DINPUT 1)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/haptic/windows/SDL_syshaptic.c)
|
||||
set(HAVE_SDL_HAPTIC TRUE)
|
||||
if(SDL_HAPTIC)
|
||||
file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/windows/*.c)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
|
||||
if(HAVE_DINPUT_H)
|
||||
set(SDL_HAPTIC_DINPUT 1)
|
||||
endif()
|
||||
if(HAVE_XINPUT_H)
|
||||
set(SDL_HAPTIC_XINPUT 1)
|
||||
endif()
|
||||
set(HAVE_SDL_HAPTIC TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB VERSION_SOURCES ${SDL2_SOURCE_DIR}/src/main/windows/*.rc)
|
||||
|
@ -1306,7 +1331,9 @@ if(NOT WINDOWS OR CYGWIN)
|
|||
# TODO: what about the .spec file? Is it only needed for RPM creation?
|
||||
install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "share/aclocal")
|
||||
else()
|
||||
install(TARGETS SDL2 RUNTIME DESTINATION bin)
|
||||
if(SDL_SHARED)
|
||||
install(TARGETS SDL2 RUNTIME DESTINATION bin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
##### Uninstall target #####
|
||||
|
|
|
@ -543,11 +543,14 @@ public class SDLActivity extends Activity {
|
|||
/** com.android.vending.expansion.zipfile.ZipResourceFile's getInputStream() or null. */
|
||||
private Method expansionFileMethod;
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public InputStream openAPKExtensionInputStream(String fileName) throws IOException {
|
||||
// Get a ZipResourceFile representing a merger of both the main and patch files
|
||||
if (expansionFile == null) {
|
||||
Integer mainVersion = Integer.parseInt(nativeGetHint("SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"));
|
||||
Integer patchVersion = Integer.parseInt(nativeGetHint("SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"));
|
||||
Integer mainVersion = Integer.valueOf(nativeGetHint("SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"));
|
||||
Integer patchVersion = Integer.valueOf(nativeGetHint("SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"));
|
||||
|
||||
try {
|
||||
// To avoid direct dependency on Google APK extension library that is
|
||||
|
|
|
@ -61,13 +61,13 @@ mkdir checker-buildbot
|
|||
cd checker-buildbot
|
||||
|
||||
# You might want to do this for CMake-backed builds instead...
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER="$CHECKERDIR/libexec/ccc-analyzer" ..
|
||||
PATH="$CHECKERDIR:$PATH" scan-build -o analysis cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
|
||||
# ...or run configure without the scan-build wrapper...
|
||||
#CC="$CHECKERDIR/libexec/ccc-analyzer" CFLAGS="-O0" ../configure
|
||||
|
||||
# ...but this works for our buildbots just fine.
|
||||
CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure
|
||||
# ...but this works for our buildbots just fine (EXCEPT ON LATEST MAC OS X).
|
||||
#CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure
|
||||
|
||||
rm -rf analysis
|
||||
PATH="$CHECKERDIR:$PATH" scan-build -o analysis $MAKE
|
||||
|
|
|
@ -917,3 +917,32 @@ macro(CheckUSBHID)
|
|||
set(CMAKE_REQUIRED_FLAGS)
|
||||
endif(HAVE_USBHID)
|
||||
endmacro(CheckUSBHID)
|
||||
|
||||
# Requires:
|
||||
# - n/a
|
||||
macro(CheckRPI)
|
||||
if(VIDEO_RPI)
|
||||
set(VIDEO_RPI_INCLUDE_DIRS "/opt/vc/include" "/opt/vc/include/interface/vcos/pthreads" "/opt/vc/include/interface/vmcs_host/linux/" )
|
||||
set(VIDEO_RPI_LIBRARY_DIRS "/opt/vc/lib" )
|
||||
set(VIDEO_RPI_LIBS bcm_host )
|
||||
listtostr(VIDEO_RPI_INCLUDE_DIRS VIDEO_RPI_INCLUDE_FLAGS "-I")
|
||||
listtostr(VIDEO_RPI_LIBRARY_DIRS VIDEO_RPI_LIBRARY_FLAGS "-L")
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${VIDEO_RPI_LIBS}")
|
||||
check_c_source_compiles("
|
||||
#include <bcm_host.h>
|
||||
int main(int argc, char **argv) {}" HAVE_VIDEO_RPI)
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
if(SDL_VIDEO AND HAVE_VIDEO_RPI)
|
||||
set(HAVE_SDL_VIDEO TRUE)
|
||||
set(SDL_VIDEO_DRIVER_RPI 1)
|
||||
file(GLOB VIDEO_RPI_SOURCES ${SDL2_SOURCE_DIR}/src/video/raspberry/*.c)
|
||||
set(SOURCE_FILES ${SOURCE_FILES} ${VIDEO_RPI_SOURCES})
|
||||
list(APPEND EXTRA_LIBS ${VIDEO_RPI_LIBS})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
|
||||
endif(SDL_VIDEO AND HAVE_VIDEO_RPI)
|
||||
endif(VIDEO_RPI)
|
||||
endmacro(CheckRPI)
|
||||
|
|
|
@ -18,9 +18,9 @@ Joystick support is available for API level >=12 devices.
|
|||
|
||||
- Android applications are Java-based, optionally with parts written in C
|
||||
- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to
|
||||
the SDL library
|
||||
the SDL library
|
||||
- This means that your application C code must be placed inside an Android
|
||||
Java project, along with some C support code that communicates with Java
|
||||
Java project, along with some C support code that communicates with Java
|
||||
- This eventually produces a standard Android .apk package
|
||||
|
||||
The Android Java code implements an "Activity" and can be found in:
|
||||
|
@ -42,15 +42,15 @@ For simple projects you can use the script located at build-scripts/androidbuild
|
|||
|
||||
There's two ways of using it:
|
||||
|
||||
androidbuild.sh com.yourcompany.yourapp < sources.list
|
||||
androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
|
||||
androidbuild.sh com.yourcompany.yourapp < sources.list
|
||||
androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
|
||||
|
||||
sources.list should be a text file with a source file name in each line
|
||||
Filenames should be specified relative to the current directory, for example if
|
||||
you are in the build-scripts directory and want to create the testgles.c test, you'll
|
||||
run:
|
||||
|
||||
./androidbuild.sh org.libsdl.testgles ../test/testgles.c
|
||||
./androidbuild.sh org.libsdl.testgles ../test/testgles.c
|
||||
|
||||
One limitation of this script is that all sources provided will be aggregated into
|
||||
a single directory, thus all your source files should have a unique name.
|
||||
|
@ -74,40 +74,42 @@ For more complex projects, follow these instructions:
|
|||
If you want to use the Eclipse IDE, skip to the Eclipse section below.
|
||||
|
||||
5. Create <project>/local.properties and use that to point to the Android SDK directory, by writing a line with the following form:
|
||||
sdk.dir=PATH_TO_ANDROID_SDK
|
||||
|
||||
sdk.dir=PATH_TO_ANDROID_SDK
|
||||
|
||||
6. Run 'ant debug' in android/project. This compiles the .java and eventually
|
||||
creates a .apk with the native code embedded
|
||||
7. 'ant debug install' will push the apk to the device or emulator (if connected)
|
||||
|
||||
Here's an explanation of the files in the Android project, so you can customize them:
|
||||
|
||||
android-project/
|
||||
AndroidManifest.xml - package manifest. Among others, it contains the class name
|
||||
of the main Activity and the package name of the application.
|
||||
build.properties - empty
|
||||
build.xml - build description file, used by ant. The actual application name
|
||||
is specified here.
|
||||
default.properties - holds the target ABI for the application, android-10 and up
|
||||
project.properties - holds the target ABI for the application, android-10 and up
|
||||
local.properties - holds the SDK path, you should change this to the path to your SDK
|
||||
jni/ - directory holding native code
|
||||
jni/Android.mk - Android makefile that can call recursively the Android.mk files
|
||||
in all subdirectories
|
||||
jni/SDL/ - (symlink to) directory holding the SDL library files
|
||||
jni/SDL/Android.mk - Android makefile for creating the SDL shared library
|
||||
jni/src/ - directory holding your C/C++ source
|
||||
jni/src/Android.mk - Android makefile that you should customize to include your
|
||||
android-project/
|
||||
AndroidManifest.xml - package manifest. Among others, it contains the class name
|
||||
of the main Activity and the package name of the application.
|
||||
build.properties - empty
|
||||
build.xml - build description file, used by ant. The actual application name
|
||||
is specified here.
|
||||
default.properties - holds the target ABI for the application, android-10 and up
|
||||
project.properties - holds the target ABI for the application, android-10 and up
|
||||
local.properties - holds the SDK path, you should change this to the path to your SDK
|
||||
jni/ - directory holding native code
|
||||
jni/Android.mk - Android makefile that can call recursively the Android.mk files
|
||||
in all subdirectories
|
||||
jni/SDL/ - (symlink to) directory holding the SDL library files
|
||||
jni/SDL/Android.mk - Android makefile for creating the SDL shared library
|
||||
jni/src/ - directory holding your C/C++ source
|
||||
jni/src/Android.mk - Android makefile that you should customize to include your
|
||||
source code and any library references
|
||||
res/ - directory holding resources for your application
|
||||
res/drawable-* - directories holding icons for different phone hardware. Could be
|
||||
one dir called "drawable".
|
||||
res/layout/main.xml - Usually contains a file main.xml, which declares the screen layout.
|
||||
We don't need it because we use the SDL video output.
|
||||
res/values/strings.xml - strings used in your application, including the application name
|
||||
shown on the phone.
|
||||
src/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding
|
||||
to SDL. Be very careful changing this, as the SDL library relies
|
||||
on this implementation.
|
||||
res/ - directory holding resources for your application
|
||||
res/drawable-* - directories holding icons for different phone hardware. Could be
|
||||
one dir called "drawable".
|
||||
res/layout/main.xml - Usually contains a file main.xml, which declares the screen layout.
|
||||
We don't need it because we use the SDL video output.
|
||||
res/values/strings.xml - strings used in your application, including the application name
|
||||
shown on the phone.
|
||||
src/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding
|
||||
to SDL. Be very careful changing this, as the SDL library relies
|
||||
on this implementation.
|
||||
|
||||
|
||||
================================================================================
|
||||
|
@ -125,10 +127,10 @@ Instructions:
|
|||
4. create and export an environment variable named NDK_MODULE_PATH that points
|
||||
to the parent directory of this SDL directory. e.g.:
|
||||
|
||||
export NDK_MODULE_PATH="$PWD"/..
|
||||
export NDK_MODULE_PATH="$PWD"/..
|
||||
|
||||
5. Edit <project>/src/org/libsdl/app/SDLActivity.java and remove the call to
|
||||
System.loadLibrary("SDL2") line 42.
|
||||
System.loadLibrary("SDL2").
|
||||
6. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
|
||||
|
||||
|
||||
|
@ -141,21 +143,23 @@ To customize your application name, edit AndroidManifest.xml and replace
|
|||
|
||||
Then create a Java class extending SDLActivity and place it in a directory
|
||||
under src matching your package, e.g.
|
||||
src/com/gamemaker/game/MyGame.java
|
||||
|
||||
src/com/gamemaker/game/MyGame.java
|
||||
|
||||
Here's an example of a minimal class file:
|
||||
--- MyGame.java --------------------------
|
||||
package com.gamemaker.game;
|
||||
|
||||
import org.libsdl.app.SDLActivity;
|
||||
--- MyGame.java --------------------------
|
||||
package com.gamemaker.game;
|
||||
|
||||
/*
|
||||
* A sample wrapper class that just calls SDLActivity
|
||||
*/
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
public class MyGame extends SDLActivity { }
|
||||
/**
|
||||
* A sample wrapper class that just calls SDLActivity
|
||||
*/
|
||||
|
||||
------------------------------------------
|
||||
public class MyGame extends SDLActivity { }
|
||||
|
||||
------------------------------------------
|
||||
|
||||
Then replace "SDLActivity" in AndroidManifest.xml with the name of your
|
||||
class, .e.g. "MyGame"
|
||||
|
@ -182,9 +186,9 @@ standard functions in SDL_rwops.h.
|
|||
|
||||
There are also a few Android specific functions that allow you to get other
|
||||
useful paths for saving and loading data:
|
||||
SDL_AndroidGetInternalStoragePath()
|
||||
SDL_AndroidGetExternalStorageState()
|
||||
SDL_AndroidGetExternalStoragePath()
|
||||
* SDL_AndroidGetInternalStoragePath()
|
||||
* SDL_AndroidGetExternalStorageState()
|
||||
* SDL_AndroidGetExternalStoragePath()
|
||||
|
||||
See SDL_system.h for more details on these functions.
|
||||
|
||||
|
@ -226,11 +230,12 @@ under iOS, if the OS can not restore your GL context it will just kill your app)
|
|||
|
||||
For a quick tour on how Linux native threads interoperate with the Java VM, take
|
||||
a look here: http://developer.android.com/guide/practices/jni.html
|
||||
|
||||
If you want to use threads in your SDL app, it's strongly recommended that you
|
||||
do so by creating them using SDL functions. This way, the required attach/detach
|
||||
handling is managed by SDL automagically. If you have threads created by other
|
||||
means and they make calls to SDL functions, make sure that you call
|
||||
Android_JNI_SetupThread before doing anything else otherwise SDL will attach
|
||||
Android_JNI_SetupThread() before doing anything else otherwise SDL will attach
|
||||
your thread automatically anyway (when you make an SDL call), but it'll never
|
||||
detach it.
|
||||
|
||||
|
@ -240,7 +245,8 @@ detach it.
|
|||
|
||||
You can use STL in your project by creating an Application.mk file in the jni
|
||||
folder and adding the following line:
|
||||
APP_STL := stlport_static
|
||||
|
||||
APP_STL := stlport_static
|
||||
|
||||
For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation.
|
||||
|
||||
|
@ -266,7 +272,7 @@ Once you've copied the SDL android project and customized it, you can create an
|
|||
* Select the Android -> Android Project wizard and click Next
|
||||
* Enter the name you'd like your project to have
|
||||
* Select "Create project from existing source" and browse for your project directory
|
||||
* Make sure the Build Target is set to Android 2.0
|
||||
* Make sure the Build Target is set to Android 3.1 (API 12)
|
||||
* Click Finish
|
||||
|
||||
|
||||
|
@ -290,49 +296,61 @@ You can create and run an emulator from the Eclipse IDE:
|
|||
* Window -> Android SDK and AVD Manager
|
||||
|
||||
You can see if adb can see any devices with the following command:
|
||||
adb devices
|
||||
|
||||
adb devices
|
||||
|
||||
You can see the output of log messages on the default device with:
|
||||
adb logcat
|
||||
|
||||
adb logcat
|
||||
|
||||
You can push files to the device with:
|
||||
adb push local_file remote_path_and_file
|
||||
|
||||
adb push local_file remote_path_and_file
|
||||
|
||||
You can push files to the SD Card at /sdcard, for example:
|
||||
adb push moose.dat /sdcard/moose.dat
|
||||
|
||||
adb push moose.dat /sdcard/moose.dat
|
||||
|
||||
You can see the files on the SD card with a shell command:
|
||||
adb shell ls /sdcard/
|
||||
|
||||
adb shell ls /sdcard/
|
||||
|
||||
You can start a command shell on the default device with:
|
||||
adb shell
|
||||
|
||||
adb shell
|
||||
|
||||
You can remove the library files of your project (and not the SDL lib files) with:
|
||||
ndk-build clean
|
||||
|
||||
ndk-build clean
|
||||
|
||||
You can do a build with the following command:
|
||||
ndk-build
|
||||
|
||||
ndk-build
|
||||
|
||||
You can see the complete command line that ndk-build is using by passing V=1 on the command line:
|
||||
ndk-build V=1
|
||||
|
||||
ndk-build V=1
|
||||
|
||||
If your application crashes in native code, you can use addr2line to convert the
|
||||
addresses in the stack trace to lines in your code.
|
||||
|
||||
For example, if your crash looks like this:
|
||||
I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
|
||||
I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4
|
||||
I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c
|
||||
I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c
|
||||
I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030
|
||||
I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so
|
||||
I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so
|
||||
I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so
|
||||
I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so
|
||||
|
||||
I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
|
||||
I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4
|
||||
I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c
|
||||
I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c
|
||||
I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030
|
||||
I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so
|
||||
I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so
|
||||
I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so
|
||||
I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so
|
||||
|
||||
You can see that there's a crash in the C library being called from the main code.
|
||||
I run addr2line with the debug version of my code:
|
||||
arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
|
||||
|
||||
arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
|
||||
|
||||
and then paste in the number after "pc" in the call stack, from the line that I care about:
|
||||
000014bc
|
||||
|
||||
|
@ -340,13 +358,14 @@ I get output from addr2line showing that it's in the quit function, in testsprit
|
|||
|
||||
You can add logging to your code to help show what's happening:
|
||||
|
||||
#include <android/log.h>
|
||||
#include <android/log.h>
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
|
||||
__android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
|
||||
|
||||
If you need to build without optimization turned on, you can create a file called
|
||||
"Application.mk" in the jni directory, with the following line in it:
|
||||
APP_OPTIM := debug
|
||||
|
||||
APP_OPTIM := debug
|
||||
|
||||
|
||||
================================================================================
|
||||
|
@ -355,7 +374,9 @@ APP_OPTIM := debug
|
|||
|
||||
The best (and slowest) way to debug memory issues on Android is valgrind.
|
||||
Valgrind has support for Android out of the box, just grab code using:
|
||||
svn co svn://svn.valgrind.org/valgrind/trunk valgrind
|
||||
|
||||
svn co svn://svn.valgrind.org/valgrind/trunk valgrind
|
||||
|
||||
... and follow the instructions in the file README.android to build it.
|
||||
|
||||
One thing I needed to do on Mac OS X was change the path to the toolchain,
|
||||
|
@ -364,20 +385,24 @@ export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x8
|
|||
|
||||
Once valgrind is built, you can create a wrapper script to launch your
|
||||
application with it, changing org.libsdl.app to your package identifier:
|
||||
--- start_valgrind_app -------------------
|
||||
#!/system/bin/sh
|
||||
export TMPDIR=/data/data/org.libsdl.app
|
||||
exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
|
||||
------------------------------------------
|
||||
|
||||
--- start_valgrind_app -------------------
|
||||
#!/system/bin/sh
|
||||
export TMPDIR=/data/data/org.libsdl.app
|
||||
exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
|
||||
------------------------------------------
|
||||
|
||||
Then push it to the device:
|
||||
adb push start_valgrind_app /data/local
|
||||
|
||||
adb push start_valgrind_app /data/local
|
||||
|
||||
and make it executable:
|
||||
adb shell chmod 755 /data/local/start_valgrind_app
|
||||
|
||||
adb shell chmod 755 /data/local/start_valgrind_app
|
||||
|
||||
and tell Android to use the script to launch your application:
|
||||
adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
|
||||
|
||||
adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
|
||||
|
||||
If the setprop command says "could not set property", it's likely that
|
||||
your package name is too long and you should make it shorter by changing
|
||||
|
@ -387,10 +412,12 @@ You can then launch your application normally and waaaaaaaiiittt for it.
|
|||
You can monitor the startup process with the logcat command above, and
|
||||
when it's done (or even while it's running) you can grab the valgrind
|
||||
output file:
|
||||
adb pull /sdcard/valgrind.log
|
||||
|
||||
adb pull /sdcard/valgrind.log
|
||||
|
||||
When you're done instrumenting with valgrind, you can disable the wrapper:
|
||||
adb shell setprop wrap.org.libsdl.app ""
|
||||
|
||||
adb shell setprop wrap.org.libsdl.app ""
|
||||
|
||||
================================================================================
|
||||
Why is API level 10 the minimum required?
|
||||
|
|
|
@ -11,11 +11,12 @@ without complication.
|
|||
While still experimental, the build system should be usable on the following
|
||||
platforms:
|
||||
|
||||
* FreeBSD
|
||||
* Linux
|
||||
* VS.NET 2010
|
||||
* MinGW and Msys
|
||||
* OS X with support for XCode
|
||||
* FreeBSD
|
||||
* Linux
|
||||
* VS.NET 2010
|
||||
* MinGW and Msys
|
||||
* OS X with support for XCode
|
||||
|
||||
|
||||
================================================================================
|
||||
Usage
|
||||
|
@ -23,9 +24,9 @@ Usage
|
|||
|
||||
Assuming the source for SDL is located at ~/sdl
|
||||
|
||||
cd ~
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../sdl
|
||||
cd ~
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../sdl
|
||||
|
||||
This will build the static and dynamic versions of SDL in the ~/build directory.
|
||||
|
|
|
@ -11,9 +11,9 @@ Supports:
|
|||
|
||||
What you need:
|
||||
|
||||
DirectFB 1.0.1, 1.2.x, 1.3.0
|
||||
Kernel-Framebuffer support: required: vesafb, radeonfb ....
|
||||
Mesa 7.0.x - optional for OpenGL
|
||||
* DirectFB 1.0.1, 1.2.x, 1.3.0
|
||||
* Kernel-Framebuffer support: required: vesafb, radeonfb ....
|
||||
* Mesa 7.0.x - optional for OpenGL
|
||||
|
||||
/etc/directfbrc
|
||||
|
||||
|
|
|
@ -14,18 +14,18 @@ SDL_RecordGesture(SDL_TouchID touchId), where touchId is the id of the touch dev
|
|||
Recording terminates as soon as a finger comes up. Recording is acknowledged by an SDL_DOLLARRECORD event.
|
||||
A SDL_DOLLARRECORD event is a dgesture with the following fields:
|
||||
|
||||
event.dgesture.touchId - the Id of the touch used to record the gesture.
|
||||
event.dgesture.gestureId - the unique id of the recorded gesture.
|
||||
* event.dgesture.touchId - the Id of the touch used to record the gesture.
|
||||
* event.dgesture.gestureId - the unique id of the recorded gesture.
|
||||
|
||||
|
||||
Performing:
|
||||
-----------
|
||||
As long as there is a dollar gesture assigned to a touch, every finger-up event will also cause an SDL_DOLLARGESTURE event with the following fields:
|
||||
|
||||
event.dgesture.touchId - the Id of the touch which performed the gesture.
|
||||
event.dgesture.gestureId - the unique id of the closest gesture to the performed stroke.
|
||||
event.dgesture.error - the difference between the gesture template and the actual performed gesture. Lower error is a better match.
|
||||
event.dgesture.numFingers - the number of fingers used to draw the stroke.
|
||||
* event.dgesture.touchId - the Id of the touch which performed the gesture.
|
||||
* event.dgesture.gestureId - the unique id of the closest gesture to the performed stroke.
|
||||
* event.dgesture.error - the difference between the gesture template and the actual performed gesture. Lower error is a better match.
|
||||
* event.dgesture.numFingers - the number of fingers used to draw the stroke.
|
||||
|
||||
Most programs will want to define an appropriate error threshold and check to be sure that the error of a gesture is not abnormally high (an indicator that no gesture was performed).
|
||||
|
||||
|
@ -54,12 +54,12 @@ Multi Gestures
|
|||
SDL provides simple support for pinch/rotate/swipe gestures.
|
||||
Every time a finger is moved an SDL_MULTIGESTURE event is sent with the following fields:
|
||||
|
||||
event.mgesture.touchId - the Id of the touch on which the gesture was performed.
|
||||
event.mgesture.x - the normalized x coordinate of the gesture. (0..1)
|
||||
event.mgesture.y - the normalized y coordinate of the gesture. (0..1)
|
||||
event.mgesture.dTheta - the amount that the fingers rotated during this motion.
|
||||
event.mgesture.dDist - the amount that the fingers pinched during this motion.
|
||||
event.mgesture.numFingers - the number of fingers used in the gesture.
|
||||
* event.mgesture.touchId - the Id of the touch on which the gesture was performed.
|
||||
* event.mgesture.x - the normalized x coordinate of the gesture. (0..1)
|
||||
* event.mgesture.y - the normalized y coordinate of the gesture. (0..1)
|
||||
* event.mgesture.dTheta - the amount that the fingers rotated during this motion.
|
||||
* event.mgesture.dDist - the amount that the fingers pinched during this motion.
|
||||
* event.mgesture.numFingers - the number of fingers used in the gesture.
|
||||
|
||||
|
||||
===========================================================================
|
||||
|
|
|
@ -9,7 +9,7 @@ at the Mercurial website ( http://mercurial.selenic.com/ ) for more
|
|||
information on using hg, where you can also download software for
|
||||
Mac OS X, Windows, and Unix systems.
|
||||
|
||||
hg clone http://hg.libsdl.org/SDL
|
||||
hg clone http://hg.libsdl.org/SDL
|
||||
|
||||
If you are building SDL with an IDE, you will need to copy the file
|
||||
include/SDL_config.h.default to include/SDL_config.h before building.
|
||||
|
@ -18,7 +18,6 @@ If you are building SDL via configure, you will need to run autogen.sh
|
|||
before running configure.
|
||||
|
||||
There is a web interface to the subversion repository at:
|
||||
|
||||
http://hg.libsdl.org/SDL/
|
||||
|
||||
There is an RSS feed available at that URL, for those that want to
|
||||
|
|
|
@ -14,11 +14,12 @@ Instructions:
|
|||
There are three build targets:
|
||||
- libSDL.a:
|
||||
Build SDL as a statically linked library
|
||||
- testsdl
|
||||
- testsdl:
|
||||
Build a test program (there are known test failures which are fine)
|
||||
- Template:
|
||||
Package a project template together with the SDL for iPhone static libraries and copies of the SDL headers. The template includes proper references to the SDL library and headers, skeleton code for a basic SDL program, and placeholder graphics for the application icon and startup screen.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Build SDL for iOS from the command line
|
||||
==============================================================================
|
||||
|
@ -47,8 +48,8 @@ FIXME: This needs to be updated for the latest methods
|
|||
|
||||
Here is the easiest method:
|
||||
1. Build the SDL libraries (libSDL.a and libSDLSimulator.a) and the iPhone SDL Application template.
|
||||
1. Install the iPhone SDL Application template by copying it to one of XCode's template directories. I recommend creating a directory called "SDL" in "/Developer/Platforms/iOS.platform/Developer/Library/XCode/Project Templates/" and placing it there.
|
||||
2. Start a new project using the template. The project should be immediately ready for use with SDL.
|
||||
2. Install the iPhone SDL Application template by copying it to one of XCode's template directories. I recommend creating a directory called "SDL" in "/Developer/Platforms/iOS.platform/Developer/Library/XCode/Project Templates/" and placing it there.
|
||||
3. Start a new project using the template. The project should be immediately ready for use with SDL.
|
||||
|
||||
Here is a more manual method:
|
||||
1. Create a new iPhone view based application.
|
||||
|
@ -57,6 +58,7 @@ Here is a more manual method:
|
|||
4. Remove the ApplicationDelegate.h and ApplicationDelegate.m files -- SDL for iPhone provides its own UIApplicationDelegate. Remove MainWindow.xib -- SDL for iPhone produces its user interface programmatically.
|
||||
5. Delete the contents of main.m and program your app as a regular SDL program instead. You may replace main.m with your own main.c, but you must tell XCode not to use the project prefix file, as it includes Objective-C code.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Notes -- Application events
|
||||
==============================================================================
|
||||
|
@ -68,56 +70,56 @@ not give you any processing time after the events are delivered.
|
|||
|
||||
e.g.
|
||||
|
||||
int HandleAppEvents(void *userdata, SDL_Event *event)
|
||||
{
|
||||
switch (event->type)
|
||||
int HandleAppEvents(void *userdata, SDL_Event *event)
|
||||
{
|
||||
case SDL_APP_TERMINATING:
|
||||
/* Terminate the app.
|
||||
Shut everything down before returning from this function.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_LOWMEMORY:
|
||||
/* You will get this when your app is paused and iOS wants more memory.
|
||||
Release as much memory as possible.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_WILLENTERBACKGROUND:
|
||||
/* Prepare your app to go into the background. Stop loops, etc.
|
||||
This gets called when the user hits the home button, or gets a call.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_DIDENTERBACKGROUND:
|
||||
/* This will get called if the user accepted whatever sent your app to the background.
|
||||
If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.
|
||||
When you get this, you have 5 seconds to save all your state or the app will be terminated.
|
||||
Your app is NOT active at this point.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_WILLENTERFOREGROUND:
|
||||
/* This call happens when your app is coming back to the foreground.
|
||||
Restore all your state here.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_DIDENTERFOREGROUND:
|
||||
/* Restart your loops here.
|
||||
Your app is interactive and getting CPU again.
|
||||
*/
|
||||
return 0;
|
||||
default:
|
||||
/* No special processing, add it to the event queue */
|
||||
return 1;
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_APP_TERMINATING:
|
||||
/* Terminate the app.
|
||||
Shut everything down before returning from this function.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_LOWMEMORY:
|
||||
/* You will get this when your app is paused and iOS wants more memory.
|
||||
Release as much memory as possible.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_WILLENTERBACKGROUND:
|
||||
/* Prepare your app to go into the background. Stop loops, etc.
|
||||
This gets called when the user hits the home button, or gets a call.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_DIDENTERBACKGROUND:
|
||||
/* This will get called if the user accepted whatever sent your app to the background.
|
||||
If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.
|
||||
When you get this, you have 5 seconds to save all your state or the app will be terminated.
|
||||
Your app is NOT active at this point.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_WILLENTERFOREGROUND:
|
||||
/* This call happens when your app is coming back to the foreground.
|
||||
Restore all your state here.
|
||||
*/
|
||||
return 0;
|
||||
case SDL_APP_DIDENTERFOREGROUND:
|
||||
/* Restart your loops here.
|
||||
Your app is interactive and getting CPU again.
|
||||
*/
|
||||
return 0;
|
||||
default:
|
||||
/* No special processing, add it to the event queue */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_SetEventFilter(HandleAppEvents, NULL);
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_SetEventFilter(HandleAppEvents, NULL);
|
||||
|
||||
... run your main loop
|
||||
... run your main loop
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
@ -148,11 +150,14 @@ The SDL keyboard API has been extended to support on-screen keyboards:
|
|||
|
||||
void SDL_StartTextInput()
|
||||
-- enables text events and reveals the onscreen keyboard.
|
||||
|
||||
void SDL_StopTextInput()
|
||||
-- disables text events and hides the onscreen keyboard.
|
||||
|
||||
SDL_bool SDL_IsTextInputActive()
|
||||
-- returns whether or not text events are enabled (and the onscreen keyboard is visible)
|
||||
|
||||
|
||||
==============================================================================
|
||||
Notes -- Reading and Writing files
|
||||
==============================================================================
|
||||
|
@ -161,12 +166,12 @@ Each application installed on iPhone resides in a sandbox which includes its own
|
|||
|
||||
Once your application is installed its directory tree looks like:
|
||||
|
||||
MySDLApp Home/
|
||||
MySDLApp.app
|
||||
Documents/
|
||||
Library/
|
||||
Preferences/
|
||||
tmp/
|
||||
MySDLApp Home/
|
||||
MySDLApp.app
|
||||
Documents/
|
||||
Library/
|
||||
Preferences/
|
||||
tmp/
|
||||
|
||||
When your SDL based iPhone application starts up, it sets the working directory to the main bundle (MySDLApp Home/MySDLApp.app), where your application resources are stored. You cannot write to this directory. Instead, I advise you to write document files to "../Documents/" and preferences to "../Library/Preferences".
|
||||
|
||||
|
@ -192,34 +197,34 @@ Game Center
|
|||
|
||||
Game Center integration requires that you break up your main loop in order to yield control back to the system. In other words, instead of running an endless main loop, you run each frame in a callback function, using:
|
||||
|
||||
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
|
||||
int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
|
||||
|
||||
This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.
|
||||
|
||||
e.g.
|
||||
|
||||
extern "C"
|
||||
void ShowFrame(void*)
|
||||
{
|
||||
... do event handling, frame logic and rendering
|
||||
}
|
||||
extern "C"
|
||||
void ShowFrame(void*)
|
||||
{
|
||||
... do event handling, frame logic and rendering ...
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
... initialize game ...
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
... initialize game ...
|
||||
|
||||
#if __IPHONEOS__
|
||||
#if __IPHONEOS__
|
||||
// Initialize the Game Center for scoring and matchmaking
|
||||
InitGameCenter();
|
||||
|
||||
// Set up the game to run in the window animation callback on iOS
|
||||
// so that Game Center and so forth works correctly.
|
||||
SDL_iPhoneSetAnimationCallback(window, 1, ShowFrame, NULL);
|
||||
#else
|
||||
#else
|
||||
while ( running ) {
|
||||
ShowFrame(0);
|
||||
DelayFrame();
|
||||
ShowFrame(0);
|
||||
DelayFrame();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,28 +45,29 @@ Some things you have to be aware of when using SDL on Mac OS X:
|
|||
file with the app. To solve these issues, put the following code in your
|
||||
NSApplicationDelegate implementation:
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_DROPFILE;
|
||||
event.drop.file = SDL_strdup([filename UTF8String]);
|
||||
return (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_DROPFILE;
|
||||
event.drop.file = SDL_strdup([filename UTF8String]);
|
||||
return (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
==============================================================================
|
||||
Using the Simple DirectMedia Layer with a traditional Makefile
|
||||
|
|
|
@ -3,8 +3,8 @@ Native Client
|
|||
|
||||
Requirements:
|
||||
|
||||
* Native Client SDK (https://developer.chrome.com/native-client),
|
||||
(tested with Pepper version 33 or higher).
|
||||
* Native Client SDK (https://developer.chrome.com/native-client),
|
||||
(tested with Pepper version 33 or higher).
|
||||
|
||||
The SDL backend for Chrome's Native Client has been tested only with the PNaCl
|
||||
toolchain, which generates binaries designed to run on ARM and x86_32/64
|
||||
|
@ -91,9 +91,9 @@ To be able to save into the directory "/save/" (like backup of game) :
|
|||
|
||||
And add to manifest.json :
|
||||
|
||||
"permissions": [
|
||||
"unlimitedStorage"
|
||||
]
|
||||
"permissions": [
|
||||
"unlimitedStorage"
|
||||
]
|
||||
|
||||
================================================================================
|
||||
TODO - Known Issues
|
||||
|
|
|
@ -8,27 +8,27 @@ Officially supported platforms
|
|||
==============================
|
||||
(code compiles, and thoroughly tested for release)
|
||||
==============================
|
||||
Windows XP/Vista/7/8
|
||||
Mac OS X 10.5+
|
||||
Linux 2.6+
|
||||
iOS 5.1.1+
|
||||
Android 2.3.3+
|
||||
* Windows XP/Vista/7/8
|
||||
* Mac OS X 10.5+
|
||||
* Linux 2.6+
|
||||
* iOS 5.1.1+
|
||||
* Android 2.3.3+
|
||||
|
||||
Unofficially supported platforms
|
||||
================================
|
||||
(code compiles, but not thoroughly tested)
|
||||
================================
|
||||
FreeBSD
|
||||
NetBSD
|
||||
OpenBSD
|
||||
Solaris
|
||||
* FreeBSD
|
||||
* NetBSD
|
||||
* OpenBSD
|
||||
* Solaris
|
||||
|
||||
Platforms supported by volunteers
|
||||
=================================
|
||||
Haiku - maintained by Axel Dörfler <axeld@pinc-software.de>
|
||||
PSP - maintained by 527721088@qq.com
|
||||
Pandora - maintained by Scott Smith <pickle136@sbcglobal.net>
|
||||
NaCl - maintained by Gabriel Jacobo <gabomdq@gmail.com>
|
||||
* Haiku - maintained by Axel Dörfler <axeld@pinc-software.de>
|
||||
* PSP - maintained by 527721088@qq.com
|
||||
* Pandora - maintained by Scott Smith <pickle136@sbcglobal.net>
|
||||
* NaCl - maintained by Gabriel Jacobo <gabomdq@gmail.com>
|
||||
|
||||
Platforms that need maintainers
|
||||
===============================
|
||||
|
|
|
@ -15,6 +15,7 @@ Raspbian (other Linux distros may work as well).
|
|||
* Input (mouse/keyboard/joystick) via EVDEV
|
||||
* Hotplugging of input devices via UDEV
|
||||
|
||||
|
||||
================================================================================
|
||||
Raspbian Build Dependencies
|
||||
================================================================================
|
||||
|
|
|
@ -20,18 +20,18 @@ Events
|
|||
SDL_FINGERDOWN:
|
||||
Sent when a finger (or stylus) is placed on a touch device.
|
||||
Fields:
|
||||
event.tfinger.touchId - the Id of the touch device.
|
||||
event.tfinger.fingerId - the Id of the finger which just went down.
|
||||
event.tfinger.x - the x coordinate of the touch (0..1)
|
||||
event.tfinger.y - the y coordinate of the touch (0..1)
|
||||
event.tfinger.pressure - the pressure of the touch (0..1)
|
||||
* event.tfinger.touchId - the Id of the touch device.
|
||||
* event.tfinger.fingerId - the Id of the finger which just went down.
|
||||
* event.tfinger.x - the x coordinate of the touch (0..1)
|
||||
* event.tfinger.y - the y coordinate of the touch (0..1)
|
||||
* event.tfinger.pressure - the pressure of the touch (0..1)
|
||||
|
||||
SDL_FINGERMOTION:
|
||||
Sent when a finger (or stylus) is moved on the touch device.
|
||||
Fields:
|
||||
Same as SDL_FINGERDOWN but with additional:
|
||||
event.tfinger.dx - change in x coordinate during this motion event.
|
||||
event.tfinger.dy - change in y coordinate during this motion event.
|
||||
* event.tfinger.dx - change in x coordinate during this motion event.
|
||||
* event.tfinger.dy - change in y coordinate during this motion event.
|
||||
|
||||
SDL_FINGERUP:
|
||||
Sent when a finger (or stylus) is lifted from the touch device.
|
||||
|
@ -70,11 +70,12 @@ A SDL_Finger is guaranteed to be persistent for the duration of a touch, but it
|
|||
As a result, be very careful to check for NULL return values.
|
||||
|
||||
A SDL_Finger has the following fields:
|
||||
>x,y,pressure:
|
||||
* x,y,pressure:
|
||||
The current coordinates of the touch.
|
||||
>pressure:
|
||||
* pressure:
|
||||
The pressure of the touch.
|
||||
|
||||
|
||||
===========================================================================
|
||||
Notes
|
||||
===========================================================================
|
||||
|
|
|
@ -12,7 +12,7 @@ Simple DirectMedia Layer is a cross-platform development library designed
|
|||
to provide low level access to audio, keyboard, mouse, joystick, and graphics
|
||||
hardware via OpenGL and Direct3D. It is used by video playback software,
|
||||
emulators, and popular games including Valve's award winning catalog
|
||||
and many Humble Bundle games. 42
|
||||
and many Humble Bundle games.
|
||||
|
||||
SDL officially supports Windows, Mac OS X, Linux, iOS, and Android.
|
||||
Support for other platforms may be found in the source code.
|
||||
|
|
|
@ -1510,7 +1510,7 @@ DOTFILE_DIRS =
|
|||
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
|
||||
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
|
||||
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
DOT_GRAPH_MAX_NODES = 60
|
||||
|
||||
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
|
||||
# graphs generated by dot. A depth value of 3 means that only nodes reachable
|
||||
|
|
|
@ -263,6 +263,7 @@
|
|||
#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
|
||||
#cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
|
||||
|
||||
#if 0
|
||||
/* !!! FIXME: in configure script version, missing here: */
|
||||
|
|
|
@ -141,7 +141,7 @@
|
|||
/* Enable system power support */
|
||||
#define SDL_POWER_ANDROID 1
|
||||
|
||||
/* !!! FIXME: what does Android do for filesystem stuff? */
|
||||
#define SDL_FILESYSTEM_DUMMY 1
|
||||
/* Enable the filesystem driver */
|
||||
#define SDL_FILESYSTEM_ANDROID 1
|
||||
|
||||
#endif /* _SDL_config_android_h */
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_opengles.h
|
||||
* \file SDL_egl.h
|
||||
*
|
||||
* This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
|
||||
* This is a simple file to encapsulate the EGL API headers.
|
||||
*/
|
||||
#ifndef _MSC_VER
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef enum
|
|||
/* Application events */
|
||||
SDL_QUIT = 0x100, /**< User-requested quit */
|
||||
|
||||
/* These application events have special meaning on iOS, see README-ios.txt for details */
|
||||
/* These application events have special meaning on iOS, see README-ios.md for details */
|
||||
SDL_APP_TERMINATING, /**< The application is being terminated by the OS
|
||||
Called on iOS in applicationWillTerminate()
|
||||
Called on Android in onDestroy()
|
||||
|
|
|
@ -370,7 +370,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
|
|||
^
|
||||
|
|
||||
|
|
||||
(1,0) West <----[ HAPTIC ]----> East (-1,0)
|
||||
(-1,0) West <----[ HAPTIC ]----> East (1,0)
|
||||
|
|
||||
|
|
||||
v
|
||||
|
@ -395,9 +395,9 @@ typedef struct _SDL_Haptic SDL_Haptic;
|
|||
* (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses
|
||||
* the first three \c dir parameters. The cardinal directions would be:
|
||||
* - North: 0,-1, 0
|
||||
* - East: -1, 0, 0
|
||||
* - East: 1, 0, 0
|
||||
* - South: 0, 1, 0
|
||||
* - West: 1, 0, 0
|
||||
* - West: -1, 0, 0
|
||||
*
|
||||
* The Z axis represents the height of the effect if supported, otherwise
|
||||
* it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you
|
||||
|
@ -604,11 +604,11 @@ typedef struct SDL_HapticCondition
|
|||
Uint16 interval; /**< How soon it can be triggered again after button. */
|
||||
|
||||
/* Condition */
|
||||
Uint16 right_sat[3]; /**< Level when joystick is to the positive side. */
|
||||
Uint16 left_sat[3]; /**< Level when joystick is to the negative side. */
|
||||
Uint16 right_sat[3]; /**< Level when joystick is to the positive side; max 0xFFFF. */
|
||||
Uint16 left_sat[3]; /**< Level when joystick is to the negative side; max 0xFFFF. */
|
||||
Sint16 right_coeff[3]; /**< How fast to increase the force towards the positive side. */
|
||||
Sint16 left_coeff[3]; /**< How fast to increase the force towards the negative side. */
|
||||
Uint16 deadband[3]; /**< Size of the dead zone. */
|
||||
Uint16 deadband[3]; /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */
|
||||
Sint16 center[3]; /**< Position of the dead zone. */
|
||||
} SDL_HapticCondition;
|
||||
|
||||
|
|
|
@ -478,6 +478,18 @@ extern "C" {
|
|||
*/
|
||||
#define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"
|
||||
|
||||
/**
|
||||
* \brief A variable to control whether certain IMs should handle text editing internally instead of sending TEXTEDITING events.
|
||||
*
|
||||
*
|
||||
* The variable can be set to the following values:
|
||||
* "0" - TEXTEDITING events are sent, and it is the application's
|
||||
* responsibility to render the text from these events and
|
||||
* differentiate it somehow from committed text. (default)
|
||||
* "1" - If supported by the IM then TEXTEDITING events are not sent,
|
||||
* and text that is being composed will be rendered in its own UI.
|
||||
*/
|
||||
#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
|
||||
|
||||
/**
|
||||
* \brief An enumeration of hint priorities
|
||||
|
|
2179
include/SDL_opengl.h
2179
include/SDL_opengl.h
File diff suppressed because it is too large
Load diff
|
@ -465,8 +465,13 @@ GLAPI void APIENTRY glBlendEquation (GLenum mode);
|
|||
#ifndef GL_VERSION_1_5
|
||||
#define GL_VERSION_1_5 1
|
||||
#include <stddef.h>
|
||||
#ifdef __MACOSX__
|
||||
typedef long GLsizeiptr;
|
||||
typedef long GLintptr;
|
||||
#else
|
||||
typedef ptrdiff_t GLsizeiptr;
|
||||
typedef ptrdiff_t GLintptr;
|
||||
#endif
|
||||
#define GL_BUFFER_SIZE 0x8764
|
||||
#define GL_BUFFER_USAGE 0x8765
|
||||
#define GL_QUERY_COUNTER_BITS 0x8864
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_opengles.h
|
||||
* \file SDL_opengles2.h
|
||||
*
|
||||
* This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
|
||||
*/
|
||||
|
|
|
@ -248,7 +248,11 @@ enum
|
|||
SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
|
||||
SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
|
||||
SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
|
||||
SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U')
|
||||
SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
|
||||
SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */
|
||||
SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'),
|
||||
SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */
|
||||
SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1')
|
||||
};
|
||||
|
||||
typedef struct SDL_Color
|
||||
|
|
|
@ -208,20 +208,20 @@ struct SDL_SysWMinfo
|
|||
#if defined(SDL_VIDEO_DRIVER_COCOA)
|
||||
struct
|
||||
{
|
||||
#if defined(__OBJC__) && __has_feature(objc_arc)
|
||||
NSWindow * __unsafe_unretained window; /* The Cocoa window */
|
||||
#if defined(__OBJC__) && defined(__has_feature) && __has_feature(objc_arc)
|
||||
NSWindow __unsafe_unretained *window; /* The Cocoa window */
|
||||
#else
|
||||
NSWindow *window; /* The Cocoa window */
|
||||
NSWindow *window; /* The Cocoa window */
|
||||
#endif
|
||||
} cocoa;
|
||||
#endif
|
||||
#if defined(SDL_VIDEO_DRIVER_UIKIT)
|
||||
struct
|
||||
{
|
||||
#if defined(__OBJC__) && __has_feature(objc_arc)
|
||||
UIWindow * __unsafe_unretained window; /* The UIKit window */
|
||||
#if defined(__OBJC__) && defined(__has_feature) && __has_feature(objc_arc)
|
||||
UIWindow __unsafe_unretained *window; /* The UIKit window */
|
||||
#else
|
||||
UIWindow *window; /* The UIKit window */
|
||||
UIWindow *window; /* The UIKit window */
|
||||
#endif
|
||||
} uikit;
|
||||
#endif
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
/* The configure script already did any necessary checking */
|
||||
# define SDL_XAUDIO2_HAS_SDK 1
|
||||
#elif defined(__WINRT__)
|
||||
/* WinRT always has access to the the XAudio 2 SDK */
|
||||
/* WinRT always has access to the XAudio 2 SDK */
|
||||
# define SDL_XAUDIO2_HAS_SDK
|
||||
#else
|
||||
/* XAudio2 exists as of the March 2008 DirectX SDK
|
||||
|
|
|
@ -22,10 +22,16 @@
|
|||
|
||||
#ifdef HAVE_IBUS_IBUS_H
|
||||
#include "SDL.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_ibus.h"
|
||||
#include "SDL_dbus.h"
|
||||
#include "../../video/SDL_sysvideo.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
#include "../../video/x11/SDL_x11video.h"
|
||||
#endif
|
||||
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -39,7 +45,7 @@ static char *input_ctx_path = NULL;
|
|||
static SDL_Rect ibus_cursor_rect = {0};
|
||||
static DBusConnection *ibus_conn = NULL;
|
||||
static char *ibus_addr_file = NULL;
|
||||
int inotify_fd = -1;
|
||||
int inotify_fd = -1, inotify_wd = -1;
|
||||
|
||||
static Uint32
|
||||
IBus_ModState(void)
|
||||
|
@ -160,8 +166,6 @@ IBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data)
|
|||
i += sz;
|
||||
cursor += chars;
|
||||
}
|
||||
} else {
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
@ -169,6 +173,11 @@ IBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *user_data)
|
|||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
if(dbus->message_is_signal(msg, IBUS_INPUT_INTERFACE, "HidePreeditText")){
|
||||
SDL_SendEditingText("", 0, 0);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -279,6 +288,41 @@ IBus_GetDBusAddressFilename(void)
|
|||
return SDL_strdup(file_path);
|
||||
}
|
||||
|
||||
static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
|
||||
|
||||
static void
|
||||
IBus_SetCapabilities(void *data, const char *name, const char *old_val,
|
||||
const char *internal_editing)
|
||||
{
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
|
||||
if(IBus_CheckConnection(dbus)){
|
||||
|
||||
DBusMessage *msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
"SetCapabilities");
|
||||
if(msg){
|
||||
Uint32 caps = IBUS_CAP_FOCUS;
|
||||
if(!(internal_editing && *internal_editing == '1')){
|
||||
caps |= IBUS_CAP_PREEDIT_TEXT;
|
||||
}
|
||||
|
||||
dbus->message_append_args(msg,
|
||||
DBUS_TYPE_UINT32, &caps,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if(msg){
|
||||
if(dbus->connection_send(ibus_conn, msg, NULL)){
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SDL_bool
|
||||
IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
|
||||
{
|
||||
|
@ -331,30 +375,14 @@ IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
|
|||
}
|
||||
|
||||
if(result){
|
||||
msg = dbus->message_new_method_call(IBUS_SERVICE,
|
||||
input_ctx_path,
|
||||
IBUS_INPUT_INTERFACE,
|
||||
"SetCapabilities");
|
||||
if(msg){
|
||||
Uint32 caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
|
||||
dbus->message_append_args(msg,
|
||||
DBUS_TYPE_UINT32, &caps,
|
||||
DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
if(msg){
|
||||
if(dbus->connection_send(ibus_conn, msg, NULL)){
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
dbus->message_unref(msg);
|
||||
}
|
||||
SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
|
||||
|
||||
dbus->bus_add_match(ibus_conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
|
||||
dbus->connection_add_filter(ibus_conn, &IBus_MessageFilter, dbus, NULL);
|
||||
dbus->connection_flush(ibus_conn);
|
||||
}
|
||||
|
||||
SDL_IBus_SetFocus(SDL_GetFocusWindow() != NULL);
|
||||
SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL);
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result;
|
||||
|
@ -369,7 +397,7 @@ IBus_CheckConnection(SDL_DBusContext *dbus)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
if(inotify_fd != -1){
|
||||
if(inotify_fd > 0 && inotify_wd > 0){
|
||||
char buf[1024];
|
||||
ssize_t readsize = read(inotify_fd, buf, sizeof(buf));
|
||||
if(readsize > 0){
|
||||
|
@ -422,15 +450,17 @@ SDL_IBus_Init(void)
|
|||
|
||||
char *addr = IBus_ReadAddressFromFile(addr_file);
|
||||
|
||||
inotify_fd = inotify_init();
|
||||
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
|
||||
if(inotify_fd < 0){
|
||||
inotify_fd = inotify_init();
|
||||
fcntl(inotify_fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
char *addr_file_dir = SDL_strrchr(addr_file, '/');
|
||||
if(addr_file_dir){
|
||||
*addr_file_dir = 0;
|
||||
}
|
||||
|
||||
inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
|
||||
inotify_wd = inotify_add_watch(inotify_fd, addr_file, IN_CREATE | IN_MODIFY);
|
||||
SDL_free(addr_file);
|
||||
|
||||
result = IBus_SetupConnection(dbus, addr);
|
||||
|
@ -460,6 +490,13 @@ SDL_IBus_Quit(void)
|
|||
dbus->connection_unref(ibus_conn);
|
||||
}
|
||||
|
||||
if(inotify_fd > 0 && inotify_wd > 0){
|
||||
inotify_rm_watch(inotify_fd, inotify_wd);
|
||||
inotify_wd = -1;
|
||||
}
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &IBus_SetCapabilities, NULL);
|
||||
|
||||
SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
|
@ -532,6 +569,8 @@ SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
|
|||
|
||||
}
|
||||
|
||||
SDL_IBus_UpdateTextRect(NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -542,12 +581,34 @@ SDL_IBus_UpdateTextRect(SDL_Rect *rect)
|
|||
SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect));
|
||||
}
|
||||
|
||||
SDL_Window *focused_win = SDL_GetFocusWindow();
|
||||
SDL_Window *focused_win = SDL_GetKeyboardFocus();
|
||||
|
||||
if(!focused_win) return;
|
||||
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
if(!SDL_GetWindowWMInfo(focused_win, &info)) return;
|
||||
|
||||
int x = 0, y = 0;
|
||||
|
||||
SDL_GetWindowPosition(focused_win, &x, &y);
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11
|
||||
if(info.subsystem == SDL_SYSWM_X11){
|
||||
SDL_DisplayData *displaydata =
|
||||
(SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
|
||||
|
||||
Display *x_disp = info.info.x11.display;
|
||||
Window x_win = info.info.x11.window;
|
||||
int x_screen = displaydata->screen;
|
||||
Window unused;
|
||||
|
||||
X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen),
|
||||
0, 0, &x, &y, &unused);
|
||||
}
|
||||
#endif
|
||||
|
||||
x += ibus_cursor_rect.x;
|
||||
y += ibus_cursor_rect.y;
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ CPU_OSSavesYMM(void)
|
|||
a = 0;
|
||||
#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))
|
||||
asm(".byte 0x0f, 0x01, 0xd0" : "=a" (a) : "c" (0) : "%edx");
|
||||
#elif defined(_MSC_VER) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */
|
||||
a = (int)_xgetbv(0);
|
||||
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
||||
__asm
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
Also, note the bundle layouts are different for iPhone and Mac.
|
||||
*/
|
||||
FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
|
||||
|
@ -41,22 +42,20 @@ FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
|||
return fopen(file, mode);
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
|
||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
|
||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
} else {
|
||||
fp = fopen(file, mode);
|
||||
}
|
||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try]) {
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
} else {
|
||||
fp = fopen(file, mode);
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
|
|
62
src/filesystem/android/SDL_sysfilesystem.c
Normal file
62
src/filesystem/android/SDL_sysfilesystem.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_ANDROID
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent filesystem routines */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_filesystem.h"
|
||||
#include "SDL_system.h"
|
||||
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{
|
||||
/* The current working directory is / on Android */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *path = SDL_AndroidGetInternalStoragePath();
|
||||
if (path) {
|
||||
size_t pathlen = SDL_strlen(path)+2;
|
||||
char *fullpath = (char *)SDL_malloc(pathlen);
|
||||
if (!fullpath) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
SDL_snprintf(fullpath, pathlen, "%s/", path);
|
||||
return fullpath;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_ANDROID */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -35,72 +35,71 @@
|
|||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||
const char *base = NULL;
|
||||
char *retval = NULL;
|
||||
|
||||
if (baseType == NULL) {
|
||||
baseType = "resource";
|
||||
}
|
||||
if (SDL_strcasecmp(baseType, "bundle")==0) {
|
||||
base = [[bundle bundlePath] fileSystemRepresentation];
|
||||
} else if (SDL_strcasecmp(baseType, "parent")==0) {
|
||||
base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation];
|
||||
} else {
|
||||
/* this returns the exedir for non-bundled and the resourceDir for bundled apps */
|
||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||
}
|
||||
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + 2;
|
||||
retval = (char *) SDL_malloc(len);
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
} else {
|
||||
SDL_snprintf(retval, len, "%s/", base);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
char *retval = NULL;
|
||||
|
||||
@autoreleasepool {
|
||||
const char *base = NULL;
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
const char* baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||
if (baseType == NULL) {
|
||||
baseType = "resource";
|
||||
}
|
||||
if (SDL_strcasecmp(baseType, "bundle")==0) {
|
||||
base = [[bundle bundlePath] fileSystemRepresentation];
|
||||
} else if (SDL_strcasecmp(baseType, "parent")==0) {
|
||||
base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation];
|
||||
} else {
|
||||
/* this returns the exedir for non-bundled and the resourceDir for bundled apps */
|
||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||
}
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
|
||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||
NSString *str = [array objectAtIndex:0];
|
||||
const char *base = [str fileSystemRepresentation];
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + 2;
|
||||
const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
retval = (char *) SDL_malloc(len);
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
} else {
|
||||
SDL_snprintf(retval, len, "%s/", base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *retval = NULL;
|
||||
|
||||
@autoreleasepool {
|
||||
NSArray *array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
|
||||
if ([array count] > 0) { /* we only want the first item in the list. */
|
||||
NSString *str = [array objectAtIndex:0];
|
||||
const char *base = [str fileSystemRepresentation];
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
retval = (char *) SDL_malloc(len);
|
||||
if (retval == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
} else {
|
||||
char *ptr;
|
||||
SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app);
|
||||
for (ptr = retval+1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
mkdir(retval, 0700);
|
||||
*ptr = '/';
|
||||
}
|
||||
char *ptr;
|
||||
SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app);
|
||||
for (ptr = retval+1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
mkdir(retval, 0700);
|
||||
*ptr = '/';
|
||||
}
|
||||
mkdir(retval, 0700);
|
||||
}
|
||||
mkdir(retval, 0700);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_COCOA */
|
||||
|
||||
|
|
|
@ -924,10 +924,10 @@ SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest, SDL_HapticEffect * src)
|
|||
condition[i].lNegativeCoefficient =
|
||||
CONVERT(hap_condition->left_coeff[i]);
|
||||
condition[i].dwPositiveSaturation =
|
||||
CCONVERT(hap_condition->right_sat[i]);
|
||||
CCONVERT(hap_condition->right_sat[i] / 2);
|
||||
condition[i].dwNegativeSaturation =
|
||||
CCONVERT(hap_condition->left_sat[i]);
|
||||
condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i]);
|
||||
CCONVERT(hap_condition->left_sat[i] / 2);
|
||||
condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i] / 2);
|
||||
}
|
||||
dest->cbTypeSpecificParams = sizeof(FFCONDITION) * dest->cAxes;
|
||||
dest->lpvTypeSpecificParams = condition;
|
||||
|
|
|
@ -652,15 +652,14 @@ SDL_SYS_ToButton(Uint16 button)
|
|||
|
||||
|
||||
/*
|
||||
* Returns the ff_effect usable direction from a SDL_HapticDirection.
|
||||
* Initializes the ff_effect usable direction from a SDL_HapticDirection.
|
||||
*/
|
||||
static Uint16
|
||||
SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
||||
static int
|
||||
SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection * src)
|
||||
{
|
||||
Uint32 tmp;
|
||||
float f; /* Ideally we'd use fixed point math instead of floats... */
|
||||
|
||||
switch (dir->type) {
|
||||
switch (src->type) {
|
||||
case SDL_HAPTIC_POLAR:
|
||||
/* Linux directions start from south.
|
||||
(and range from 0 to 0xFFFF)
|
||||
|
@ -671,24 +670,31 @@ SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
|||
180 deg -> 0x8000 (up)
|
||||
270 deg -> 0xC000 (right)
|
||||
*/
|
||||
tmp = (((18000 + dir->dir[0]) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = ((src->dir[0] % 36000) * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
break;
|
||||
|
||||
case SDL_HAPTIC_SPHERICAL:
|
||||
case SDL_HAPTIC_SPHERICAL:
|
||||
/*
|
||||
We convert to polar, because that's the only supported direction on Linux.
|
||||
The first value of a spherical direction is practically the same as a
|
||||
Polar direction, except that we have to add 90 degrees. It is the angle
|
||||
from EAST {1,0} towards SOUTH {0,1}.
|
||||
--> add 9000
|
||||
--> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
--> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
*/
|
||||
tmp = ((dir->dir[0]) + 9000) % 36000; /* Convert to polars */
|
||||
tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = ((src->dir[0]) + 9000) % 36000; /* Convert to polars */
|
||||
tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
break;
|
||||
|
||||
case SDL_HAPTIC_CARTESIAN:
|
||||
f = atan2(dir->dir[1], dir->dir[0]);
|
||||
if (!src->dir[1])
|
||||
*dest = (src->dir[0] >= 0 ? 0x4000 : 0xC000);
|
||||
else if (!src->dir[0])
|
||||
*dest = (src->dir[1] >= 0 ? 0x8000 : 0);
|
||||
else {
|
||||
float f = atan2(src->dir[1], src->dir[0]); /* Ideally we'd use fixed point math instead of floats... */
|
||||
/*
|
||||
atan2 takes the parameters: Y-axis-value and X-axis-value (in that order)
|
||||
- Y-axis-value is the second coordinate (from center to SOUTH)
|
||||
|
@ -697,14 +703,16 @@ SDL_SYS_ToDirection(SDL_HapticDirection * dir)
|
|||
have the first spherical value. Therefore we proceed as in case
|
||||
SDL_HAPTIC_SPHERICAL and add another 9000 to get the polar value.
|
||||
--> add 45000 in total
|
||||
--> finally add 18000 and convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
--> finally convert to [0,0xFFFF] as in case SDL_HAPTIC_POLAR.
|
||||
*/
|
||||
tmp = (((int) (f * 18000. / M_PI)) + 45000) % 36000;
|
||||
tmp = (((18000 + tmp) % 36000) * 0xFFFF) / 36000; /* convert to range [0,0xFFFF] */
|
||||
return (Uint16) tmp;
|
||||
tmp = (((Sint32) (f * 18000. / M_PI)) + 45000) % 36000;
|
||||
tmp = (tmp * 0x8000) / 18000; /* convert to range [0,0xFFFF] */
|
||||
*dest = (Uint16) tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (Uint16) SDL_SetError("Haptic: Unsupported direction type.");
|
||||
return SDL_SetError("Haptic: Unsupported direction type.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -735,8 +743,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
|||
|
||||
/* Header */
|
||||
dest->type = FF_CONSTANT;
|
||||
dest->direction = SDL_SYS_ToDirection(&constant->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &constant->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
|
@ -771,8 +778,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
|||
|
||||
/* Header */
|
||||
dest->type = FF_PERIODIC;
|
||||
dest->direction = SDL_SYS_ToDirection(&periodic->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &periodic->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
|
@ -841,20 +847,18 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
|||
|
||||
/* Condition */
|
||||
/* X axis */
|
||||
dest->u.condition[0].right_saturation =
|
||||
CLAMP(condition->right_sat[0]);
|
||||
dest->u.condition[0].left_saturation = CLAMP(condition->left_sat[0]);
|
||||
dest->u.condition[0].right_saturation = condition->right_sat[0];
|
||||
dest->u.condition[0].left_saturation = condition->left_sat[0];
|
||||
dest->u.condition[0].right_coeff = condition->right_coeff[0];
|
||||
dest->u.condition[0].left_coeff = condition->left_coeff[0];
|
||||
dest->u.condition[0].deadband = CLAMP(condition->deadband[0]);
|
||||
dest->u.condition[0].deadband = condition->deadband[0];
|
||||
dest->u.condition[0].center = condition->center[0];
|
||||
/* Y axis */
|
||||
dest->u.condition[1].right_saturation =
|
||||
CLAMP(condition->right_sat[1]);
|
||||
dest->u.condition[1].left_saturation = CLAMP(condition->left_sat[1]);
|
||||
dest->u.condition[1].right_saturation = condition->right_sat[1];
|
||||
dest->u.condition[1].left_saturation = condition->left_sat[1];
|
||||
dest->u.condition[1].right_coeff = condition->right_coeff[1];
|
||||
dest->u.condition[1].left_coeff = condition->left_coeff[1];
|
||||
dest->u.condition[1].deadband = CLAMP(condition->deadband[1]);
|
||||
dest->u.condition[1].deadband = condition->deadband[1];
|
||||
dest->u.condition[1].center = condition->center[1];
|
||||
|
||||
/*
|
||||
|
@ -868,8 +872,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
|
|||
|
||||
/* Header */
|
||||
dest->type = FF_RAMP;
|
||||
dest->direction = SDL_SYS_ToDirection(&ramp->direction);
|
||||
if (dest->direction == (Uint16) - 1)
|
||||
if (SDL_SYS_ToDirection(&dest->direction, &ramp->direction) == -1)
|
||||
return -1;
|
||||
|
||||
/* Replay */
|
||||
|
|
|
@ -602,7 +602,10 @@ SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
|
|||
}
|
||||
}
|
||||
|
||||
#define CONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
|
||||
/* Clamps and converts. */
|
||||
#define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
|
||||
/* Just converts. */
|
||||
#define CONVERT(x) (((x)*10000) / 0x7FFF)
|
||||
/*
|
||||
* Creates the DIEFFECT from a SDL_HapticEffect.
|
||||
*/
|
||||
|
@ -689,9 +692,9 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
SDL_free(dest->lpEnvelope);
|
||||
dest->lpEnvelope = NULL;
|
||||
} else {
|
||||
envelope->dwAttackLevel = CONVERT(hap_constant->attack_level);
|
||||
envelope->dwAttackLevel = CCONVERT(hap_constant->attack_level);
|
||||
envelope->dwAttackTime = hap_constant->attack_length * 1000;
|
||||
envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
|
||||
envelope->dwFadeLevel = CCONVERT(hap_constant->fade_level);
|
||||
envelope->dwFadeTime = hap_constant->fade_length * 1000;
|
||||
}
|
||||
|
||||
|
@ -736,9 +739,9 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
SDL_free(dest->lpEnvelope);
|
||||
dest->lpEnvelope = NULL;
|
||||
} else {
|
||||
envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
|
||||
envelope->dwAttackLevel = CCONVERT(hap_periodic->attack_level);
|
||||
envelope->dwAttackTime = hap_periodic->attack_length * 1000;
|
||||
envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
|
||||
envelope->dwFadeLevel = CCONVERT(hap_periodic->fade_level);
|
||||
envelope->dwFadeTime = hap_periodic->fade_length * 1000;
|
||||
}
|
||||
|
||||
|
@ -763,10 +766,10 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
condition[i].lNegativeCoefficient =
|
||||
CONVERT(hap_condition->left_coeff[i]);
|
||||
condition[i].dwPositiveSaturation =
|
||||
CONVERT(hap_condition->right_sat[i]);
|
||||
CCONVERT(hap_condition->right_sat[i] / 2);
|
||||
condition[i].dwNegativeSaturation =
|
||||
CONVERT(hap_condition->left_sat[i]);
|
||||
condition[i].lDeadBand = CONVERT(hap_condition->deadband[i]);
|
||||
CCONVERT(hap_condition->left_sat[i] / 2);
|
||||
condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i] / 2);
|
||||
}
|
||||
dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
|
||||
dest->lpvTypeSpecificParams = condition;
|
||||
|
@ -819,9 +822,9 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
SDL_free(dest->lpEnvelope);
|
||||
dest->lpEnvelope = NULL;
|
||||
} else {
|
||||
envelope->dwAttackLevel = CONVERT(hap_ramp->attack_level);
|
||||
envelope->dwAttackLevel = CCONVERT(hap_ramp->attack_level);
|
||||
envelope->dwAttackTime = hap_ramp->attack_length * 1000;
|
||||
envelope->dwFadeLevel = CONVERT(hap_ramp->fade_level);
|
||||
envelope->dwFadeLevel = CCONVERT(hap_ramp->fade_level);
|
||||
envelope->dwFadeTime = hap_ramp->fade_length * 1000;
|
||||
}
|
||||
|
||||
|
@ -842,7 +845,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
custom->rglForceData =
|
||||
SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
|
||||
for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */
|
||||
custom->rglForceData[i] = CONVERT(hap_custom->data[i]);
|
||||
custom->rglForceData[i] = CCONVERT(hap_custom->data[i]);
|
||||
}
|
||||
dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
|
||||
dest->lpvTypeSpecificParams = custom;
|
||||
|
@ -864,9 +867,9 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
|
|||
SDL_free(dest->lpEnvelope);
|
||||
dest->lpEnvelope = NULL;
|
||||
} else {
|
||||
envelope->dwAttackLevel = CONVERT(hap_custom->attack_level);
|
||||
envelope->dwAttackLevel = CCONVERT(hap_custom->attack_level);
|
||||
envelope->dwAttackTime = hap_custom->attack_length * 1000;
|
||||
envelope->dwFadeLevel = CONVERT(hap_custom->fade_level);
|
||||
envelope->dwFadeLevel = CCONVERT(hap_custom->fade_level);
|
||||
envelope->dwFadeTime = hap_custom->fade_length * 1000;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ static const char *s_ControllerMappings [] =
|
|||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
|
||||
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
|
||||
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
|
||||
|
|
|
@ -115,6 +115,12 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
|||
}
|
||||
|
||||
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
/* Make sure we're operating on the default render target */
|
||||
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
|
||||
if (saved_target) {
|
||||
SDL_SetRenderTarget(renderer, NULL);
|
||||
}
|
||||
|
||||
if (renderer->logical_w) {
|
||||
UpdateLogicalSize(renderer);
|
||||
} else {
|
||||
|
@ -140,6 +146,10 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
|||
renderer->UpdateViewport(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
if (saved_target) {
|
||||
SDL_SetRenderTarget(renderer, saved_target);
|
||||
}
|
||||
} else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
|
||||
renderer->hidden = SDL_TRUE;
|
||||
} else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
|
||||
|
@ -540,6 +550,10 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
|
|||
|
||||
/* Set up a destination surface for the texture update */
|
||||
dst_fmt = SDL_AllocFormat(format);
|
||||
if (!dst_fmt) {
|
||||
SDL_DestroyTexture(texture);
|
||||
return NULL;
|
||||
}
|
||||
temp = SDL_ConvertSurface(surface, dst_fmt, 0);
|
||||
SDL_FreeFormat(dst_fmt);
|
||||
if (temp) {
|
||||
|
@ -912,12 +926,12 @@ int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
|
|||
SDL_assert(!texture->native);
|
||||
renderer = texture->renderer;
|
||||
SDL_assert(renderer->UpdateTextureYUV);
|
||||
if (renderer->UpdateTextureYUV) {
|
||||
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
|
||||
} else {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
}
|
||||
if (renderer->UpdateTextureYUV) {
|
||||
return renderer->UpdateTextureYUV(renderer, texture, rect, Yplane, Ypitch, Uplane, Upitch, Vplane, Vpitch);
|
||||
} else {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -193,6 +193,9 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
SDL_bool dirty;
|
||||
int w, h;
|
||||
DWORD usage;
|
||||
Uint32 format;
|
||||
IDirect3DTexture9 *texture;
|
||||
IDirect3DTexture9 *staging;
|
||||
} D3D_TextureRep;
|
||||
|
@ -819,6 +822,10 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us
|
|||
HRESULT result;
|
||||
|
||||
texture->dirty = SDL_FALSE;
|
||||
texture->w = w;
|
||||
texture->h = h;
|
||||
texture->usage = usage;
|
||||
texture->format = format;
|
||||
|
||||
result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
|
||||
PixelFormatToD3DFMT(format),
|
||||
|
@ -826,10 +833,18 @@ D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD us
|
|||
if (FAILED(result)) {
|
||||
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (usage != D3DUSAGE_RENDERTARGET) {
|
||||
result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
|
||||
PixelFormatToD3DFMT(format),
|
||||
|
||||
static int
|
||||
D3D_CreateStagingTexture(IDirect3DDevice9 *device, D3D_TextureRep *texture)
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
if (texture->staging == NULL) {
|
||||
result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
|
||||
PixelFormatToD3DFMT(texture->format),
|
||||
D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
|
||||
|
@ -845,14 +860,8 @@ D3D_BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD samp
|
|||
|
||||
if (texture->dirty && texture->staging) {
|
||||
if (!texture->texture) {
|
||||
D3DSURFACE_DESC desc;
|
||||
result = IDirect3DTexture9_GetLevelDesc(texture->staging, 0, &desc);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("GetLevelDesc", result);
|
||||
}
|
||||
|
||||
result = IDirect3DDevice9_CreateTexture(device, desc.Width, desc.Height, 1, 0,
|
||||
desc.Format, D3DPOOL_DEFAULT, &texture->texture, NULL);
|
||||
result = IDirect3DDevice9_CreateTexture(device, texture->w, texture->h, 1, texture->usage,
|
||||
PixelFormatToD3DFMT(texture->format), D3DPOOL_DEFAULT, &texture->texture, NULL);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
|
||||
}
|
||||
|
@ -878,8 +887,10 @@ D3D_RecreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32
|
|||
IDirect3DTexture9_Release(texture->texture);
|
||||
texture->texture = NULL;
|
||||
}
|
||||
IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
|
||||
texture->dirty = SDL_TRUE;
|
||||
if (texture->staging) {
|
||||
IDirect3DTexture9_AddDirtyRect(texture->staging, NULL);
|
||||
texture->dirty = SDL_TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -893,10 +904,15 @@ D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 f
|
|||
int row, length;
|
||||
HRESULT result;
|
||||
|
||||
if (D3D_CreateStagingTexture(device, texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
d3drect.left = x;
|
||||
d3drect.right = x + w;
|
||||
d3drect.top = y;
|
||||
d3drect.bottom = y + h;
|
||||
|
||||
result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("LockRect()", result);
|
||||
|
@ -1068,7 +1084,9 @@ static int
|
|||
D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect, void **pixels, int *pitch)
|
||||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
|
||||
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
|
||||
IDirect3DDevice9 *device = data->device;
|
||||
|
||||
if (!texturedata) {
|
||||
SDL_SetError("Texture is not currently available");
|
||||
|
@ -1095,6 +1113,10 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
D3DLOCKED_RECT locked;
|
||||
HRESULT result;
|
||||
|
||||
if (D3D_CreateStagingTexture(device, &texturedata->texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
d3drect.left = rect->x;
|
||||
d3drect.right = rect->x + rect->w;
|
||||
d3drect.top = rect->y;
|
||||
|
@ -1137,7 +1159,9 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
{
|
||||
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
|
||||
D3D_TextureData *texturedata;
|
||||
D3D_TextureRep *texturerep;
|
||||
HRESULT result;
|
||||
IDirect3DDevice9 *device = data->device;
|
||||
|
||||
/* Release the previous render target if it wasn't the default one */
|
||||
if (data->currentRenderTarget != NULL) {
|
||||
|
@ -1156,6 +1180,24 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure the render target is updated if it was locked and written to */
|
||||
texturerep = &texturedata->texture;
|
||||
if (texturerep->dirty && texturerep->staging) {
|
||||
if (!texturerep->texture) {
|
||||
result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h, 1, texturerep->usage,
|
||||
PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
|
||||
}
|
||||
}
|
||||
|
||||
result = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texturerep->staging, (IDirect3DBaseTexture9 *)texturerep->texture);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("UpdateTexture()", result);
|
||||
}
|
||||
texturerep->dirty = SDL_FALSE;
|
||||
}
|
||||
|
||||
result = IDirect3DTexture9_GetSurfaceLevel(texturedata->texture.texture, 0, &data->currentRenderTarget);
|
||||
if(FAILED(result)) {
|
||||
return D3D_SetError("GetSurfaceLevel()", result);
|
||||
|
@ -1789,9 +1831,10 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
D3DLOCKED_RECT locked;
|
||||
HRESULT result;
|
||||
|
||||
result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
|
||||
if (FAILED(result)) {
|
||||
return D3D_SetError("GetBackBuffer()", result);
|
||||
if (data->currentRenderTarget) {
|
||||
backBuffer = data->currentRenderTarget;
|
||||
} else {
|
||||
backBuffer = data->defaultRenderTarget;
|
||||
}
|
||||
|
||||
result = IDirect3DSurface9_GetDesc(backBuffer, &desc);
|
||||
|
@ -1832,7 +1875,6 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
IDirect3DSurface9_UnlockRect(surface);
|
||||
|
||||
IDirect3DSurface9_Release(surface);
|
||||
IDirect3DSurface9_Release(backBuffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ typedef struct
|
|||
GLDEBUGPROCARB next_error_callback;
|
||||
GLvoid *next_error_userparam;
|
||||
|
||||
SDL_bool GL_ARB_texture_non_power_of_two_supported;
|
||||
SDL_bool GL_ARB_texture_rectangle_supported;
|
||||
struct {
|
||||
GL_Shader shader;
|
||||
|
@ -164,8 +165,9 @@ typedef struct
|
|||
int pitch;
|
||||
SDL_Rect locked_rect;
|
||||
|
||||
/* YV12 texture support */
|
||||
/* YUV texture support */
|
||||
SDL_bool yuv;
|
||||
SDL_bool nv12;
|
||||
GLuint utexture;
|
||||
GLuint vtexture;
|
||||
|
||||
|
@ -498,9 +500,13 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
}
|
||||
|
||||
if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
|
||||
|| SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
|
||||
if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
|
||||
data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
|
||||
} else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
|
||||
SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
|
||||
data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
|
||||
}
|
||||
if (data->GL_ARB_texture_rectangle_supported) {
|
||||
data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
|
||||
renderer->info.max_texture_width = value;
|
||||
renderer->info.max_texture_height = value;
|
||||
|
@ -531,6 +537,8 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
|||
if (data->shaders && data->num_texture_units >= 3) {
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
|
||||
}
|
||||
|
||||
#ifdef __MACOSX__
|
||||
|
@ -611,16 +619,18 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
|
|||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
*internalFormat = GL_LUMINANCE;
|
||||
*format = GL_LUMINANCE;
|
||||
*type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
#ifdef __MACOSX__
|
||||
case SDL_PIXELFORMAT_UYVY:
|
||||
*internalFormat = GL_RGB8;
|
||||
*format = GL_YCBCR_422_APPLE;
|
||||
*type = GL_UNSIGNED_SHORT_8_8_APPLE;
|
||||
break;
|
||||
*internalFormat = GL_RGB8;
|
||||
*format = GL_YCBCR_422_APPLE;
|
||||
*type = GL_UNSIGNED_SHORT_8_8_APPLE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return SDL_FALSE;
|
||||
|
@ -672,6 +682,11 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
/* Need to add size for the U and V planes */
|
||||
size += (2 * (texture->h * data->pitch) / 4);
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||
/* Need to add size for the U/V plane */
|
||||
size += ((texture->h * data->pitch) / 2);
|
||||
}
|
||||
data->pixels = SDL_calloc(1, size);
|
||||
if (!data->pixels) {
|
||||
SDL_free(data);
|
||||
|
@ -687,7 +702,7 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
|
||||
GL_CheckError("", renderer);
|
||||
renderdata->glGenTextures(1, &data->texture);
|
||||
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||
if (GL_CheckError("glGenTextures()", renderer) < 0) {
|
||||
if (data->pixels) {
|
||||
SDL_free(data->pixels);
|
||||
}
|
||||
|
@ -696,8 +711,13 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
}
|
||||
texture->driverdata = data;
|
||||
|
||||
if ((renderdata->GL_ARB_texture_rectangle_supported)
|
||||
/* && texture->access != SDL_TEXTUREACCESS_TARGET */){
|
||||
if (renderdata->GL_ARB_texture_non_power_of_two_supported) {
|
||||
data->type = GL_TEXTURE_2D;
|
||||
texture_w = texture->w;
|
||||
texture_h = texture->h;
|
||||
data->texw = 1.0f;
|
||||
data->texh = 1.0f;
|
||||
} else if (renderdata->GL_ARB_texture_rectangle_supported) {
|
||||
data->type = GL_TEXTURE_RECTANGLE_ARB;
|
||||
texture_w = texture->w;
|
||||
texture_h = texture->h;
|
||||
|
@ -801,6 +821,27 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||
renderdata->glDisable(data->type);
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||
data->nv12 = SDL_TRUE;
|
||||
|
||||
renderdata->glGenTextures(1, &data->utexture);
|
||||
renderdata->glEnable(data->type);
|
||||
|
||||
renderdata->glBindTexture(data->type, data->utexture);
|
||||
renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
|
||||
scaleMode);
|
||||
renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
|
||||
scaleMode);
|
||||
renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_EDGE);
|
||||
renderdata->glTexImage2D(data->type, 0, GL_LUMINANCE_ALPHA, texture_w/2,
|
||||
texture_h/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||
renderdata->glDisable(data->type);
|
||||
}
|
||||
|
||||
return GL_CheckError("", renderer);
|
||||
}
|
||||
|
||||
|
@ -848,6 +889,17 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
rect->w/2, rect->h/2,
|
||||
data->format, data->formattype, pixels);
|
||||
}
|
||||
|
||||
if (data->nv12) {
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2));
|
||||
|
||||
/* Skip to the correct offset into the next texture */
|
||||
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
|
||||
renderdata->glBindTexture(data->type, data->utexture);
|
||||
renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
|
||||
rect->w/2, rect->h/2,
|
||||
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
renderdata->glDisable(data->type);
|
||||
|
||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||
|
@ -1184,15 +1236,10 @@ GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
|
|||
}
|
||||
|
||||
static int
|
||||
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
||||
GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||
{
|
||||
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
||||
GLfloat minx, miny, maxx, maxy;
|
||||
GLfloat minu, maxu, minv, maxv;
|
||||
|
||||
GL_ActivateRenderer(renderer);
|
||||
|
||||
data->glEnable(texturedata->type);
|
||||
if (texturedata->yuv) {
|
||||
|
@ -1204,6 +1251,12 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
|
||||
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
if (texturedata->nv12) {
|
||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
data->glBindTexture(texturedata->type, texturedata->utexture);
|
||||
|
||||
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
data->glBindTexture(texturedata->type, texturedata->texture);
|
||||
|
||||
if (texture->modMode) {
|
||||
|
@ -1215,10 +1268,33 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
GL_SetBlendMode(data, texture->blendMode);
|
||||
|
||||
if (texturedata->yuv) {
|
||||
GL_SetShader(data, SHADER_YV12);
|
||||
GL_SetShader(data, SHADER_YUV);
|
||||
} else if (texturedata->nv12) {
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||
GL_SetShader(data, SHADER_NV12);
|
||||
} else {
|
||||
GL_SetShader(data, SHADER_NV21);
|
||||
}
|
||||
} else {
|
||||
GL_SetShader(data, SHADER_RGB);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
||||
{
|
||||
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
||||
GLfloat minx, miny, maxx, maxy;
|
||||
GLfloat minu, maxu, minv, maxv;
|
||||
|
||||
GL_ActivateRenderer(renderer);
|
||||
|
||||
if (GL_SetupCopy(renderer, texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
minx = dstrect->x;
|
||||
miny = dstrect->y;
|
||||
|
@ -1263,30 +1339,8 @@ GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
|||
|
||||
GL_ActivateRenderer(renderer);
|
||||
|
||||
data->glEnable(texturedata->type);
|
||||
if (texturedata->yuv) {
|
||||
data->glActiveTextureARB(GL_TEXTURE2_ARB);
|
||||
data->glBindTexture(texturedata->type, texturedata->vtexture);
|
||||
|
||||
data->glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
data->glBindTexture(texturedata->type, texturedata->utexture);
|
||||
|
||||
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
}
|
||||
data->glBindTexture(texturedata->type, texturedata->texture);
|
||||
|
||||
if (texture->modMode) {
|
||||
GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
|
||||
} else {
|
||||
GL_SetColor(data, 255, 255, 255, 255);
|
||||
}
|
||||
|
||||
GL_SetBlendMode(data, texture->blendMode);
|
||||
|
||||
if (texturedata->yuv) {
|
||||
GL_SetShader(data, SHADER_YV12);
|
||||
} else {
|
||||
GL_SetShader(data, SHADER_RGB);
|
||||
if (GL_SetupCopy(renderer, texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
centerx = center->x;
|
||||
|
|
|
@ -113,7 +113,7 @@ static const char *shader_source[NUM_SHADERS][2] =
|
|||
"}"
|
||||
},
|
||||
|
||||
/* SHADER_YV12 */
|
||||
/* SHADER_YUV */
|
||||
{
|
||||
/* vertex shader */
|
||||
"varying vec4 v_color;\n"
|
||||
|
@ -150,7 +150,7 @@ static const char *shader_source[NUM_SHADERS][2] =
|
|||
" yuv.x = texture2D(tex0, tcoord).r;\n"
|
||||
"\n"
|
||||
" // Get the U and V values \n"
|
||||
" tcoord *= 0.5;\n"
|
||||
" tcoord *= UVCoordScale;\n"
|
||||
" yuv.y = texture2D(tex1, tcoord).r;\n"
|
||||
" yuv.z = texture2D(tex2, tcoord).r;\n"
|
||||
"\n"
|
||||
|
@ -162,6 +162,106 @@ static const char *shader_source[NUM_SHADERS][2] =
|
|||
"\n"
|
||||
" // That was easy. :) \n"
|
||||
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||
"}"
|
||||
},
|
||||
|
||||
/* SHADER_NV12 */
|
||||
{
|
||||
/* vertex shader */
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec2 v_texCoord;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" v_color = gl_Color;\n"
|
||||
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
|
||||
"}",
|
||||
/* fragment shader */
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec2 v_texCoord;\n"
|
||||
"uniform sampler2D tex0; // Y \n"
|
||||
"uniform sampler2D tex1; // U/V \n"
|
||||
"\n"
|
||||
"// YUV offset \n"
|
||||
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
|
||||
"\n"
|
||||
"// RGB coefficients \n"
|
||||
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
|
||||
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
|
||||
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec2 tcoord;\n"
|
||||
" vec3 yuv, rgb;\n"
|
||||
"\n"
|
||||
" // Get the Y value \n"
|
||||
" tcoord = v_texCoord;\n"
|
||||
" yuv.x = texture2D(tex0, tcoord).r;\n"
|
||||
"\n"
|
||||
" // Get the U and V values \n"
|
||||
" tcoord *= UVCoordScale;\n"
|
||||
" yuv.yz = texture2D(tex1, tcoord).ra;\n"
|
||||
"\n"
|
||||
" // Do the color transform \n"
|
||||
" yuv += offset;\n"
|
||||
" rgb.r = dot(yuv, Rcoeff);\n"
|
||||
" rgb.g = dot(yuv, Gcoeff);\n"
|
||||
" rgb.b = dot(yuv, Bcoeff);\n"
|
||||
"\n"
|
||||
" // That was easy. :) \n"
|
||||
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||
"}"
|
||||
},
|
||||
|
||||
/* SHADER_NV21 */
|
||||
{
|
||||
/* vertex shader */
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec2 v_texCoord;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||
" v_color = gl_Color;\n"
|
||||
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
|
||||
"}",
|
||||
/* fragment shader */
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec2 v_texCoord;\n"
|
||||
"uniform sampler2D tex0; // Y \n"
|
||||
"uniform sampler2D tex1; // U/V \n"
|
||||
"\n"
|
||||
"// YUV offset \n"
|
||||
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
|
||||
"\n"
|
||||
"// RGB coefficients \n"
|
||||
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
|
||||
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
|
||||
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec2 tcoord;\n"
|
||||
" vec3 yuv, rgb;\n"
|
||||
"\n"
|
||||
" // Get the Y value \n"
|
||||
" tcoord = v_texCoord;\n"
|
||||
" yuv.x = texture2D(tex0, tcoord).r;\n"
|
||||
"\n"
|
||||
" // Get the U and V values \n"
|
||||
" tcoord *= UVCoordScale;\n"
|
||||
" yuv.yz = texture2D(tex1, tcoord).ar;\n"
|
||||
"\n"
|
||||
" // Do the color transform \n"
|
||||
" yuv += offset;\n"
|
||||
" rgb.r = dot(yuv, Rcoeff);\n"
|
||||
" rgb.g = dot(yuv, Gcoeff);\n"
|
||||
" rgb.b = dot(yuv, Bcoeff);\n"
|
||||
"\n"
|
||||
" // That was easy. :) \n"
|
||||
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||
"}"
|
||||
},
|
||||
};
|
||||
|
@ -218,7 +318,11 @@ CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData *data)
|
|||
if (ctx->GL_ARB_texture_rectangle_supported) {
|
||||
frag_defines =
|
||||
"#define sampler2D sampler2DRect\n"
|
||||
"#define texture2D texture2DRect\n";
|
||||
"#define texture2D texture2DRect\n"
|
||||
"#define UVCoordScale 0.5\n";
|
||||
} else {
|
||||
frag_defines =
|
||||
"#define UVCoordScale 1.0\n";
|
||||
}
|
||||
|
||||
/* Create one program object to rule them all */
|
||||
|
@ -276,8 +380,9 @@ GL_CreateShaderContext()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
|
||||
|| SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
|
||||
if (!SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two") &&
|
||||
(SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
|
||||
SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle"))) {
|
||||
ctx->GL_ARB_texture_rectangle_supported = SDL_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ typedef enum {
|
|||
SHADER_NONE,
|
||||
SHADER_SOLID,
|
||||
SHADER_RGB,
|
||||
SHADER_YV12,
|
||||
SHADER_YUV,
|
||||
SHADER_NV12,
|
||||
SHADER_NV21,
|
||||
NUM_SHADERS
|
||||
} GL_Shader;
|
||||
|
||||
|
|
|
@ -81,8 +81,9 @@ typedef struct GLES2_TextureData
|
|||
GLenum pixel_type;
|
||||
void *pixel_data;
|
||||
int pitch;
|
||||
/* YV12 texture support */
|
||||
/* YUV texture support */
|
||||
SDL_bool yuv;
|
||||
SDL_bool nv12;
|
||||
GLenum texture_v;
|
||||
GLenum texture_u;
|
||||
GLES2_FBOList *fbo;
|
||||
|
@ -151,7 +152,9 @@ typedef enum
|
|||
GLES2_IMAGESOURCE_TEXTURE_ARGB,
|
||||
GLES2_IMAGESOURCE_TEXTURE_RGB,
|
||||
GLES2_IMAGESOURCE_TEXTURE_BGR,
|
||||
GLES2_IMAGESOURCE_TEXTURE_YUV
|
||||
GLES2_IMAGESOURCE_TEXTURE_YUV,
|
||||
GLES2_IMAGESOURCE_TEXTURE_NV12,
|
||||
GLES2_IMAGESOURCE_TEXTURE_NV21
|
||||
} GLES2_ImageSource;
|
||||
|
||||
typedef struct GLES2_DriverContext
|
||||
|
@ -488,6 +491,8 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
break;
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
format = GL_LUMINANCE;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
@ -505,6 +510,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
data->pixel_format = format;
|
||||
data->pixel_type = type;
|
||||
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
||||
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
|
||||
data->texture_u = 0;
|
||||
data->texture_v = 0;
|
||||
scaleMode = GetScaleQuality();
|
||||
|
@ -518,6 +524,10 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
/* Need to add size for the U and V planes */
|
||||
size += (2 * (texture->h * data->pitch) / 4);
|
||||
}
|
||||
if (data->nv12) {
|
||||
/* Need to add size for the U/V plane */
|
||||
size += ((texture->h * data->pitch) / 2);
|
||||
}
|
||||
data->pixel_data = SDL_calloc(1, size);
|
||||
if (!data->pixel_data) {
|
||||
SDL_free(data);
|
||||
|
@ -557,6 +567,23 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
}
|
||||
}
|
||||
|
||||
if (data->nv12) {
|
||||
renderdata->glGenTextures(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 / 2, texture->h / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
renderdata->glGenTextures(1, &data->texture);
|
||||
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||
return -1;
|
||||
|
@ -673,6 +700,20 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
pixels, pitch / 2, 1);
|
||||
}
|
||||
|
||||
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);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
rect->w / 2,
|
||||
rect->h / 2,
|
||||
GL_LUMINANCE_ALPHA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
pixels, pitch, 2);
|
||||
}
|
||||
|
||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||
}
|
||||
|
||||
|
@ -1093,6 +1134,12 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
|
|||
case GLES2_IMAGESOURCE_TEXTURE_YUV:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
|
||||
break;
|
||||
case GLES2_IMAGESOURCE_TEXTURE_NV12:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC;
|
||||
break;
|
||||
case GLES2_IMAGESOURCE_TEXTURE_NV21:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC;
|
||||
break;
|
||||
default:
|
||||
goto fault;
|
||||
}
|
||||
|
@ -1432,20 +1479,15 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
|
|||
}
|
||||
|
||||
static int
|
||||
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
|
||||
const SDL_FRect *dstrect)
|
||||
GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
SDL_BlendMode blendMode;
|
||||
GLfloat vertices[8];
|
||||
GLfloat texCoords[8];
|
||||
GLES2_ProgramCacheEntry *program;
|
||||
Uint8 r, g, b, a;
|
||||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
/* Activate an appropriate shader and set the projection matrix */
|
||||
blendMode = texture->blendMode;
|
||||
if (renderer->target) {
|
||||
|
@ -1505,11 +1547,22 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unsupported texture format");
|
||||
}
|
||||
}
|
||||
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
switch (texture->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
|
@ -1524,13 +1577,18 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
case SDL_PIXELFORMAT_BGR888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||
break;
|
||||
// TODO: new shader to change yv planes YV12 format
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return SDL_SetError("Unsupported texture format");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1548,6 +1606,12 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
if (tdata->nv12) {
|
||||
data->glActiveTexture(GL_TEXTURE1);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
|
||||
/* Configure color modulation */
|
||||
|
@ -1578,6 +1642,22 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
GLES2_SetBlendMode(data, blendMode);
|
||||
|
||||
GLES2_SetTexCoords(data, SDL_TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
|
||||
const SDL_FRect *dstrect)
|
||||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLfloat vertices[8];
|
||||
GLfloat texCoords[8];
|
||||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
if (GLES2_SetupCopy(renderer, texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Emit the textured quad */
|
||||
vertices[0] = dstrect->x;
|
||||
|
@ -1608,11 +1688,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
|
||||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
GLES2_ProgramCacheEntry *program;
|
||||
Uint8 r, g, b, a;
|
||||
SDL_BlendMode blendMode;
|
||||
GLfloat vertices[8];
|
||||
GLfloat texCoords[8];
|
||||
GLfloat translate[8];
|
||||
|
@ -1621,6 +1696,10 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
|
||||
GLES2_ActivateRenderer(renderer);
|
||||
|
||||
if (GLES2_SetupCopy(renderer, texture) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
|
||||
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
|
||||
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
|
||||
|
@ -1628,124 +1707,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
|
||||
translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
|
||||
|
||||
/* Activate an appropriate shader and set the projection matrix */
|
||||
blendMode = texture->blendMode;
|
||||
if (renderer->target) {
|
||||
/* Check if we need to do color mapping between the source and render target textures */
|
||||
if (renderer->target->format != texture->format) {
|
||||
switch (texture->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
switch (renderer->target->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
case SDL_PIXELFORMAT_BGR888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGB888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
switch (renderer->target->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
case SDL_PIXELFORMAT_RGB888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_BGR888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGB888:
|
||||
switch (renderer->target->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_BGR888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_BGR888:
|
||||
switch (renderer->target->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGB888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
||||
}
|
||||
else {
|
||||
switch (texture->format)
|
||||
{
|
||||
case SDL_PIXELFORMAT_ARGB8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ABGR8888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGB888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_BGR888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
||||
return -1;
|
||||
|
||||
/* Select the target texture */
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
|
||||
/* Configure color modulation */
|
||||
/* !!! FIXME: grep for glUniform4f(), move that stuff to a subroutine, it's a lot of copy/paste. */
|
||||
g = texture->g;
|
||||
a = texture->a;
|
||||
|
||||
if (renderer->target &&
|
||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
||||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
|
||||
r = texture->b;
|
||||
b = texture->r;
|
||||
} else {
|
||||
r = texture->r;
|
||||
b = texture->b;
|
||||
}
|
||||
|
||||
program = data->current_program;
|
||||
|
||||
if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
|
||||
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
|
||||
program->modulation_r = r;
|
||||
program->modulation_g = g;
|
||||
program->modulation_b = b;
|
||||
program->modulation_a = a;
|
||||
}
|
||||
|
||||
/* Configure texture blending */
|
||||
GLES2_SetBlendMode(data, blendMode);
|
||||
|
||||
GLES2_SetTexCoords(data, SDL_TRUE);
|
||||
|
||||
/* Emit the textured quad */
|
||||
vertices[0] = dstrect->x;
|
||||
vertices[1] = dstrect->y;
|
||||
|
@ -2066,6 +2027,8 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
|||
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
|
||||
|
||||
GLES2_ResetState(renderer);
|
||||
|
||||
|
|
|
@ -150,6 +150,50 @@ static const Uint8 GLES2_FragmentSrc_TextureYUVSrc_[] = " \
|
|||
} \
|
||||
";
|
||||
|
||||
/* NV12 to ABGR conversion */
|
||||
static const Uint8 GLES2_FragmentSrc_TextureNV12Src_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform sampler2D u_texture_u; \
|
||||
uniform vec4 u_modulation; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
{ \
|
||||
mediump vec3 yuv; \
|
||||
lowp vec3 rgb; \
|
||||
yuv.x = texture2D(u_texture, v_texCoord).r; \
|
||||
yuv.yz = texture2D(u_texture_u, v_texCoord).ra - 0.5; \
|
||||
rgb = mat3( 1, 1, 1, \
|
||||
0, -0.39465, 2.03211, \
|
||||
1.13983, -0.58060, 0) * yuv; \
|
||||
gl_FragColor = vec4(rgb, 1); \
|
||||
gl_FragColor *= u_modulation; \
|
||||
} \
|
||||
";
|
||||
|
||||
/* NV21 to ABGR conversion */
|
||||
static const Uint8 GLES2_FragmentSrc_TextureNV21Src_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform sampler2D u_texture_u; \
|
||||
uniform vec4 u_modulation; \
|
||||
varying vec2 v_texCoord; \
|
||||
\
|
||||
void main() \
|
||||
{ \
|
||||
mediump vec3 yuv; \
|
||||
lowp vec3 rgb; \
|
||||
yuv.x = texture2D(u_texture, v_texCoord).r; \
|
||||
yuv.yz = texture2D(u_texture_u, v_texCoord).ar - 0.5; \
|
||||
rgb = mat3( 1, 1, 1, \
|
||||
0, -0.39465, 2.03211, \
|
||||
1.13983, -0.58060, 0) * yuv; \
|
||||
gl_FragColor = vec4(rgb, 1); \
|
||||
gl_FragColor *= u_modulation; \
|
||||
} \
|
||||
";
|
||||
|
||||
static const GLES2_ShaderInstance GLES2_VertexSrc_Default = {
|
||||
GL_VERTEX_SHADER,
|
||||
GLES2_SOURCE_SHADER,
|
||||
|
@ -199,6 +243,20 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureYUVSrc = {
|
|||
GLES2_FragmentSrc_TextureYUVSrc_
|
||||
};
|
||||
|
||||
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV12Src = {
|
||||
GL_FRAGMENT_SHADER,
|
||||
GLES2_SOURCE_SHADER,
|
||||
sizeof(GLES2_FragmentSrc_TextureNV12Src_),
|
||||
GLES2_FragmentSrc_TextureNV12Src_
|
||||
};
|
||||
|
||||
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV21Src = {
|
||||
GL_FRAGMENT_SHADER,
|
||||
GLES2_SOURCE_SHADER,
|
||||
sizeof(GLES2_FragmentSrc_TextureNV21Src_),
|
||||
GLES2_FragmentSrc_TextureNV21Src_
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Vertex/fragment shader binaries (NVIDIA Tegra 1/2) *
|
||||
|
@ -731,6 +789,20 @@ static GLES2_Shader GLES2_FragmentShader_TextureYUVSrc = {
|
|||
}
|
||||
};
|
||||
|
||||
static GLES2_Shader GLES2_FragmentShader_TextureNV12Src = {
|
||||
1,
|
||||
{
|
||||
&GLES2_FragmentSrc_TextureNV12Src
|
||||
}
|
||||
};
|
||||
|
||||
static GLES2_Shader GLES2_FragmentShader_TextureNV21Src = {
|
||||
1,
|
||||
{
|
||||
&GLES2_FragmentSrc_TextureNV21Src
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Shader selector *
|
||||
|
@ -820,6 +892,16 @@ const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMo
|
|||
return &GLES2_FragmentShader_TextureYUVSrc;
|
||||
}
|
||||
|
||||
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC:
|
||||
{
|
||||
return &GLES2_FragmentShader_TextureNV12Src;
|
||||
}
|
||||
|
||||
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC:
|
||||
{
|
||||
return &GLES2_FragmentShader_TextureNV21Src;
|
||||
}
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,9 @@ typedef enum
|
|||
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC
|
||||
} GLES2_ShaderType;
|
||||
|
||||
#define GLES2_SOURCE_SHADER (GLenum)-1
|
||||
|
|
|
@ -572,6 +572,12 @@ SDLTest_PrintPixelFormat(Uint32 format)
|
|||
case SDL_PIXELFORMAT_YVYU:
|
||||
fprintf(stderr, "YVYU");
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
fprintf(stderr, "NV12");
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
fprintf(stderr, "NV21");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "0x%8.8x", format);
|
||||
break;
|
||||
|
|
|
@ -122,6 +122,8 @@ SDL_GetPixelFormatName(Uint32 format)
|
|||
CASE(SDL_PIXELFORMAT_YUY2)
|
||||
CASE(SDL_PIXELFORMAT_UYVY)
|
||||
CASE(SDL_PIXELFORMAT_YVYU)
|
||||
CASE(SDL_PIXELFORMAT_NV12)
|
||||
CASE(SDL_PIXELFORMAT_NV21)
|
||||
#undef CASE
|
||||
default:
|
||||
return "SDL_PIXELFORMAT_UNKNOWN";
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "SDL_RLEaccel_c.h"
|
||||
#include "SDL_pixels_c.h"
|
||||
|
||||
|
||||
/* Public routines */
|
||||
/*
|
||||
* Create an empty RGB surface of the appropriate depth
|
||||
|
@ -623,7 +622,12 @@ int
|
|||
SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
|
||||
SDL_Surface * dst, SDL_Rect * dstrect)
|
||||
{
|
||||
SDL_Rect final_src, final_dst, fulldst;
|
||||
double src_x0, src_y0, src_x1, src_y1;
|
||||
double dst_x0, dst_y0, dst_x1, dst_y1;
|
||||
SDL_Rect final_src, final_dst;
|
||||
double scaling_w, scaling_h;
|
||||
int src_w, src_h;
|
||||
int dst_w, dst_h;
|
||||
|
||||
/* Make sure the surfaces aren't locked */
|
||||
if (!src || !dst) {
|
||||
|
@ -633,78 +637,135 @@ SDL_UpperBlitScaled(SDL_Surface * src, const SDL_Rect * srcrect,
|
|||
return SDL_SetError("Surfaces must not be locked during blit");
|
||||
}
|
||||
|
||||
/* If the destination rectangle is NULL, use the entire dest surface */
|
||||
if (dstrect == NULL) {
|
||||
fulldst.x = fulldst.y = 0;
|
||||
fulldst.w = dst->w;
|
||||
fulldst.h = dst->h;
|
||||
dstrect = &fulldst;
|
||||
}
|
||||
|
||||
/* clip the source rectangle to the source surface */
|
||||
if (srcrect) {
|
||||
int maxw, maxh;
|
||||
|
||||
final_src.x = srcrect->x;
|
||||
final_src.w = srcrect->w;
|
||||
if (final_src.x < 0) {
|
||||
final_src.w += final_src.x;
|
||||
final_src.x = 0;
|
||||
}
|
||||
maxw = src->w - final_src.x;
|
||||
if (maxw < final_src.w)
|
||||
final_src.w = maxw;
|
||||
|
||||
final_src.y = srcrect->y;
|
||||
final_src.h = srcrect->h;
|
||||
if (final_src.y < 0) {
|
||||
final_src.h += final_src.y;
|
||||
final_src.y = 0;
|
||||
}
|
||||
maxh = src->h - final_src.y;
|
||||
if (maxh < final_src.h)
|
||||
final_src.h = maxh;
|
||||
|
||||
if (NULL == srcrect) {
|
||||
src_w = src->w;
|
||||
src_h = src->h;
|
||||
} else {
|
||||
final_src.x = final_src.y = 0;
|
||||
final_src.w = src->w;
|
||||
final_src.h = src->h;
|
||||
src_w = srcrect->w;
|
||||
src_h = srcrect->h;
|
||||
}
|
||||
|
||||
/* clip the destination rectangle against the clip rectangle */
|
||||
if (dstrect) {
|
||||
int maxw, maxh;
|
||||
|
||||
final_dst.x = dstrect->x;
|
||||
final_dst.w = dstrect->w;
|
||||
if (final_dst.x < 0) {
|
||||
final_dst.w += final_dst.x;
|
||||
final_dst.x = 0;
|
||||
}
|
||||
maxw = dst->w - final_dst.x;
|
||||
if (maxw < final_dst.w)
|
||||
final_dst.w = maxw;
|
||||
|
||||
final_dst.y = dstrect->y;
|
||||
final_dst.h = dstrect->h;
|
||||
if (final_dst.y < 0) {
|
||||
final_dst.h += final_dst.y;
|
||||
final_dst.y = 0;
|
||||
}
|
||||
maxh = dst->h - final_dst.y;
|
||||
if (maxh < final_dst.h)
|
||||
final_dst.h = maxh;
|
||||
if (NULL == dstrect) {
|
||||
dst_w = dst->w;
|
||||
dst_h = dst->h;
|
||||
} else {
|
||||
final_dst.x = final_dst.y = 0;
|
||||
final_dst.w = dst->w;
|
||||
final_dst.h = dst->h;
|
||||
dst_w = dstrect->w;
|
||||
dst_h = dstrect->h;
|
||||
}
|
||||
|
||||
if (final_dst.w > 0 && final_dst.h > 0) {
|
||||
return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
|
||||
if (dst_w == src_w && dst_h == src_h) {
|
||||
/* No scaling, defer to regular blit */
|
||||
return SDL_BlitSurface(src, srcrect, dst, dstrect);
|
||||
}
|
||||
|
||||
return 0;
|
||||
scaling_w = (double)dst_w / src_w;
|
||||
scaling_h = (double)dst_h / src_h;
|
||||
|
||||
if (NULL == dstrect) {
|
||||
dst_x0 = 0;
|
||||
dst_y0 = 0;
|
||||
dst_x1 = dst_w - 1;
|
||||
dst_y1 = dst_h - 1;
|
||||
} else {
|
||||
dst_x0 = dstrect->x;
|
||||
dst_y0 = dstrect->y;
|
||||
dst_x1 = dst_x0 + dst_w - 1;
|
||||
dst_y1 = dst_y0 + dst_h - 1;
|
||||
}
|
||||
|
||||
if (NULL == srcrect) {
|
||||
src_x0 = 0;
|
||||
src_y0 = 0;
|
||||
src_x1 = src_w - 1;
|
||||
src_y1 = src_h - 1;
|
||||
} else {
|
||||
src_x0 = srcrect->x;
|
||||
src_y0 = srcrect->y;
|
||||
src_x1 = src_x0 + src_w - 1;
|
||||
src_y1 = src_y0 + src_h - 1;
|
||||
|
||||
/* Clip source rectangle to the source surface */
|
||||
|
||||
if (src_x0 < 0) {
|
||||
dst_x0 -= src_x0 * scaling_w;
|
||||
src_x0 = 0;
|
||||
}
|
||||
|
||||
if (src_x1 >= src->w) {
|
||||
dst_x1 -= (src_x1 - src->w + 1) * scaling_w;
|
||||
src_x1 = src->w - 1;
|
||||
}
|
||||
|
||||
if (src_y0 < 0) {
|
||||
dst_y0 -= src_y0 * scaling_h;
|
||||
src_y0 = 0;
|
||||
}
|
||||
|
||||
if (src_y1 >= src->h) {
|
||||
dst_y1 -= (src_y1 - src->h + 1) * scaling_h;
|
||||
src_y1 = src->h - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clip destination rectangle to the clip rectangle */
|
||||
|
||||
/* Translate to clip space for easier calculations */
|
||||
dst_x0 -= dst->clip_rect.x;
|
||||
dst_x1 -= dst->clip_rect.x;
|
||||
dst_y0 -= dst->clip_rect.y;
|
||||
dst_y1 -= dst->clip_rect.y;
|
||||
|
||||
if (dst_x0 < 0) {
|
||||
src_x0 -= dst_x0 / scaling_w;
|
||||
dst_x0 = 0;
|
||||
}
|
||||
|
||||
if (dst_x1 >= dst->clip_rect.w) {
|
||||
src_x1 -= (dst_x1 - dst->clip_rect.w + 1) / scaling_w;
|
||||
dst_x1 = dst->clip_rect.w - 1;
|
||||
}
|
||||
|
||||
if (dst_y0 < 0) {
|
||||
src_y0 -= dst_y0 / scaling_h;
|
||||
dst_y0 = 0;
|
||||
}
|
||||
|
||||
if (dst_y1 >= dst->clip_rect.h) {
|
||||
src_y1 -= (dst_y1 - dst->clip_rect.h + 1) / scaling_h;
|
||||
dst_y1 = dst->clip_rect.h - 1;
|
||||
}
|
||||
|
||||
/* Translate back to surface coordinates */
|
||||
dst_x0 += dst->clip_rect.x;
|
||||
dst_x1 += dst->clip_rect.x;
|
||||
dst_y0 += dst->clip_rect.y;
|
||||
dst_y1 += dst->clip_rect.y;
|
||||
|
||||
final_src.x = SDL_floor(src_x0 + 0.5);
|
||||
final_src.y = SDL_floor(src_y0 + 0.5);
|
||||
final_src.w = SDL_floor(src_x1 - src_x0 + 1.5);
|
||||
final_src.h = SDL_floor(src_y1 - src_y0 + 1.5);
|
||||
|
||||
final_dst.x = SDL_floor(dst_x0 + 0.5);
|
||||
final_dst.y = SDL_floor(dst_y0 + 0.5);
|
||||
final_dst.w = SDL_floor(dst_x1 - dst_x0 + 1.5);
|
||||
final_dst.h = SDL_floor(dst_y1 - dst_y0 + 1.5);
|
||||
|
||||
if (final_dst.w < 0)
|
||||
final_dst.w = 0;
|
||||
if (final_dst.h < 0)
|
||||
final_dst.h = 0;
|
||||
|
||||
if (dstrect)
|
||||
*dstrect = final_dst;
|
||||
|
||||
if (final_dst.w == 0 || final_dst.h == 0 ||
|
||||
final_src.w <= 0 || final_src.h <= 0) {
|
||||
/* No-op. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SDL_LowerBlitScaled(src, &final_src, dst, &final_dst);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -721,43 +782,6 @@ SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
|
|||
SDL_COPY_COLORKEY
|
||||
);
|
||||
|
||||
/* Save off the original dst width, height */
|
||||
int dstW = dstrect->w;
|
||||
int dstH = dstrect->h;
|
||||
SDL_Rect full_rect;
|
||||
SDL_Rect final_dst = *dstrect;
|
||||
SDL_Rect final_src = *srcrect;
|
||||
|
||||
/* Clip the dst surface to the dstrect */
|
||||
full_rect.x = 0;
|
||||
full_rect.y = 0;
|
||||
full_rect.w = dst->w;
|
||||
full_rect.h = dst->h;
|
||||
if (!SDL_IntersectRect(&final_dst, &full_rect, &final_dst)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Did the dst width change? */
|
||||
if ( dstW != final_dst.w ) {
|
||||
/* scale the src width appropriately */
|
||||
final_src.w = final_src.w * dst->clip_rect.w / dstW;
|
||||
}
|
||||
|
||||
/* Did the dst height change? */
|
||||
if ( dstH != final_dst.h ) {
|
||||
/* scale the src width appropriately */
|
||||
final_src.h = final_src.h * dst->clip_rect.h / dstH;
|
||||
}
|
||||
|
||||
/* Clip the src surface to the srcrect */
|
||||
full_rect.x = 0;
|
||||
full_rect.y = 0;
|
||||
full_rect.w = src->w;
|
||||
full_rect.h = src->h;
|
||||
if (!SDL_IntersectRect(&final_src, &full_rect, &final_src)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(src->map->info.flags & SDL_COPY_NEAREST)) {
|
||||
src->map->info.flags |= SDL_COPY_NEAREST;
|
||||
SDL_InvalidateMap(src->map);
|
||||
|
@ -766,9 +790,9 @@ SDL_LowerBlitScaled(SDL_Surface * src, SDL_Rect * srcrect,
|
|||
if ( !(src->map->info.flags & complex_copy_flags) &&
|
||||
src->format->format == dst->format->format &&
|
||||
!SDL_ISPIXELFORMAT_INDEXED(src->format->format) ) {
|
||||
return SDL_SoftStretch( src, &final_src, dst, &final_dst );
|
||||
return SDL_SoftStretch( src, srcrect, dst, dstrect );
|
||||
} else {
|
||||
return SDL_LowerBlit( src, &final_src, dst, &final_dst );
|
||||
return SDL_LowerBlit( src, srcrect, dst, dstrect );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1005,7 +1029,7 @@ int SDL_ConvertPixels(int width, int height,
|
|||
SDL_Rect rect;
|
||||
void *nonconst_src = (void *) src;
|
||||
|
||||
/* Check to make sure we are bliting somewhere, so we don't crash */
|
||||
/* Check to make sure we are blitting somewhere, so we don't crash */
|
||||
if (!dst) {
|
||||
return SDL_InvalidParamError("dst");
|
||||
}
|
||||
|
@ -1015,17 +1039,21 @@ int SDL_ConvertPixels(int width, int height,
|
|||
|
||||
/* Fast path for same format copy */
|
||||
if (src_format == dst_format) {
|
||||
int bpp;
|
||||
int bpp, i;
|
||||
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
||||
switch (src_format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YUY2:
|
||||
case SDL_PIXELFORMAT_UYVY:
|
||||
case SDL_PIXELFORMAT_YVYU:
|
||||
bpp = 2;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
bpp = 1;
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Unknown FOURCC pixel format");
|
||||
}
|
||||
|
@ -1034,11 +1062,32 @@ int SDL_ConvertPixels(int width, int height,
|
|||
}
|
||||
width *= bpp;
|
||||
|
||||
while (height-- > 0) {
|
||||
for (i = height; i--;) {
|
||||
SDL_memcpy(dst, src, width);
|
||||
src = (Uint8*)src + src_pitch;
|
||||
dst = (Uint8*)dst + dst_pitch;
|
||||
}
|
||||
|
||||
if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
|
||||
/* U and V planes are a quarter the size of the Y plane */
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
src_pitch /= 2;
|
||||
dst_pitch /= 2;
|
||||
for (i = height * 2; i--;) {
|
||||
SDL_memcpy(dst, src, width);
|
||||
src = (Uint8*)src + src_pitch;
|
||||
dst = (Uint8*)dst + dst_pitch;
|
||||
}
|
||||
} else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
|
||||
/* U/V plane is half the height of the Y plane */
|
||||
height /= 2;
|
||||
for (i = height; i--;) {
|
||||
SDL_memcpy(dst, src, width);
|
||||
src = (Uint8*)src + src_pitch;
|
||||
dst = (Uint8*)dst + dst_pitch;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,34 +37,28 @@ GetTextFormat(_THIS)
|
|||
|
||||
int
|
||||
Cocoa_SetClipboardText(_THIS, const char *text)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSString *format = GetTextFormat(_this);
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
|
||||
[pasteboard setString:[NSString stringWithUTF8String:text] forType:format];
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
||||
}}
|
||||
|
||||
char *
|
||||
Cocoa_GetClipboardText(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSString *format = GetTextFormat(_this);
|
||||
NSString *available;
|
||||
char *text;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:format]];
|
||||
if ([available isEqualToString:format]) {
|
||||
|
@ -82,10 +76,8 @@ Cocoa_GetClipboardText(_THIS)
|
|||
text = SDL_strdup("");
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return text;
|
||||
}
|
||||
}}
|
||||
|
||||
SDL_bool
|
||||
Cocoa_HasClipboardText(_THIS)
|
||||
|
@ -101,13 +93,11 @@ Cocoa_HasClipboardText(_THIS)
|
|||
|
||||
void
|
||||
Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
NSPasteboard *pasteboard;
|
||||
NSInteger count;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
pasteboard = [NSPasteboard generalPasteboard];
|
||||
count = [pasteboard changeCount];
|
||||
if (count != data->clipboard_count) {
|
||||
|
@ -116,9 +106,7 @@ Cocoa_CheckClipboardUpdate(struct SDL_VideoData * data)
|
|||
}
|
||||
data->clipboard_count = count;
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
|
|
|
@ -248,17 +248,16 @@ CreateApplicationMenus(void)
|
|||
|
||||
void
|
||||
Cocoa_RegisterApp(void)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
/* This can get called more than once! Be careful what you initialize! */
|
||||
ProcessSerialNumber psn;
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
if (!GetCurrentProcess(&psn)) {
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
}
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
if (NSApp == nil) {
|
||||
[SDLApplication sharedApplication];
|
||||
SDL_assert(NSApp != nil);
|
||||
|
@ -287,14 +286,12 @@ Cocoa_RegisterApp(void)
|
|||
appDelegate->seenFirstActivate = YES;
|
||||
}
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_PumpEvents(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
|
||||
/* Update activity every 30 seconds to prevent screensaver */
|
||||
if (_this->suspend_screensaver) {
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
|
@ -306,7 +303,6 @@ Cocoa_PumpEvents(_THIS)
|
|||
}
|
||||
}
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
for ( ; ; ) {
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
|
||||
if ( event == nil ) {
|
||||
|
@ -338,8 +334,7 @@ Cocoa_PumpEvents(_THIS)
|
|||
/* Pass through to NSApp to make sure everything stays in sync */
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
|
|
|
@ -479,9 +479,9 @@ Cocoa_InitKeyboard(_THIS)
|
|||
|
||||
void
|
||||
Cocoa_StartTextInput(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
SDL_Window *window = SDL_GetKeyboardFocus();
|
||||
NSWindow *nswindow = nil;
|
||||
if (window) {
|
||||
|
@ -506,23 +506,20 @@ Cocoa_StartTextInput(_THIS)
|
|||
[parentView addSubview: data->fieldEdit];
|
||||
[nswindow makeFirstResponder: data->fieldEdit];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_StopTextInput(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||
|
||||
if (data && data->fieldEdit) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[data->fieldEdit removeFromSuperview];
|
||||
[data->fieldEdit release];
|
||||
data->fieldEdit = nil;
|
||||
[pool release];
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
void
|
||||
Cocoa_SetTextInputRect(_THIS, SDL_Rect *rect)
|
||||
|
|
|
@ -79,11 +79,10 @@
|
|||
/* Display a Cocoa message box */
|
||||
int
|
||||
Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
Cocoa_RegisterApp();
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
|
||||
|
||||
if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
|
||||
|
@ -125,10 +124,8 @@ Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
returnValue = SDL_SetError("Did not get a valid `clicked button' id: %ld", (long)clicked);
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
}}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
|
|
|
@ -214,8 +214,8 @@ Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
|||
|
||||
void
|
||||
Cocoa_InitModes(_THIS)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
CGDisplayErr result;
|
||||
CGDirectDisplayID *displays;
|
||||
CGDisplayCount numDisplays;
|
||||
|
@ -224,7 +224,6 @@ Cocoa_InitModes(_THIS)
|
|||
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
[pool release];
|
||||
return;
|
||||
}
|
||||
displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
|
||||
|
@ -232,7 +231,6 @@ Cocoa_InitModes(_THIS)
|
|||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
SDL_stack_free(displays);
|
||||
[pool release];
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -297,8 +295,7 @@ Cocoa_InitModes(_THIS)
|
|||
}
|
||||
}
|
||||
SDL_stack_free(displays);
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
int
|
||||
Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
|
||||
|
|
|
@ -66,8 +66,8 @@
|
|||
|
||||
static SDL_Cursor *
|
||||
Cocoa_CreateDefaultCursor()
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSCursor *nscursor;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
|
@ -81,15 +81,13 @@ Cocoa_CreateDefaultCursor()
|
|||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}}
|
||||
|
||||
static SDL_Cursor *
|
||||
Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSImage *nsimage;
|
||||
NSCursor *nscursor = NULL;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
@ -108,15 +106,13 @@ Cocoa_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
|||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}}
|
||||
|
||||
static SDL_Cursor *
|
||||
Cocoa_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSCursor *nscursor = NULL;
|
||||
SDL_Cursor *cursor = NULL;
|
||||
|
||||
|
@ -169,28 +165,23 @@ Cocoa_CreateSystemCursor(SDL_SystemCursor id)
|
|||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return cursor;
|
||||
}
|
||||
}}
|
||||
|
||||
static void
|
||||
Cocoa_FreeCursor(SDL_Cursor * cursor)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSCursor *nscursor = (NSCursor *)cursor->driverdata;
|
||||
|
||||
[nscursor release];
|
||||
SDL_free(cursor);
|
||||
|
||||
[pool release];
|
||||
}
|
||||
}}
|
||||
|
||||
static int
|
||||
Cocoa_ShowCursor(SDL_Cursor * cursor)
|
||||
{ @autoreleasepool
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
SDL_VideoDevice *device = SDL_GetVideoDevice();
|
||||
SDL_Window *window = (device ? device->windows : NULL);
|
||||
for (; window != NULL; window = window->next) {
|
||||
|
@ -201,48 +192,21 @@ Cocoa_ShowCursor(SDL_Cursor * cursor)
|
|||
waitUntilDone:NO];
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
if ([data->listener isMoving]) {
|
||||
DLog("Postponing warp, window being moved.");
|
||||
[data->listener setPendingMoveX:x
|
||||
Y:y];
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
CGPoint point = CGPointMake(x + (float)window->x, y + (float)window->y);
|
||||
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
|
||||
/* According to the docs, this was deprecated in 10.6, but it's still
|
||||
* around. The substitute requires a CGEventSource, but I'm not entirely
|
||||
* sure how we'd procure the right one for this event.
|
||||
*/
|
||||
CGSetLocalEventsSuppressionInterval(0.0);
|
||||
CGWarpMouseCursorPosition(point);
|
||||
CGSetLocalEventsSuppressionInterval(0.25);
|
||||
|
||||
if (!mouse->relative_mode) {
|
||||
/* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
|
||||
* other implementations' APIs.
|
||||
*/
|
||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
static void
|
||||
Cocoa_WarpMouseGlobal(int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse->focus) {
|
||||
SDL_WindowData *data = (SDL_WindowData *) mouse->focus->driverdata;
|
||||
if ([data->listener isMoving]) {
|
||||
DLog("Postponing warp, window being moved.");
|
||||
[data->listener setPendingMoveX:x Y:y];
|
||||
return;
|
||||
}
|
||||
}
|
||||
CGPoint point = CGPointMake((float)x, (float)y);
|
||||
|
||||
Cocoa_HandleMouseWarp(point.x, point.y);
|
||||
|
@ -263,6 +227,12 @@ Cocoa_WarpMouseGlobal(int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
|
||||
{
|
||||
Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
|
||||
}
|
||||
|
||||
static int
|
||||
Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
|
|
|
@ -103,8 +103,7 @@ static Uint32 s_moveHack;
|
|||
|
||||
static void ConvertNSRect(NSScreen *screen, BOOL fullscreen, NSRect *r)
|
||||
{
|
||||
NSRect visibleScreen = fullscreen ? [screen frame] : [screen visibleFrame];
|
||||
r->origin.y = (visibleScreen.origin.y + visibleScreen.size.height) - r->origin.y - r->size.height;
|
||||
r->origin.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - r->origin.y - r->size.height;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -389,11 +388,11 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
isMoving = NO;
|
||||
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (pendingWindowWarpX >= 0 && pendingWindowWarpY >= 0) {
|
||||
mouse->WarpMouse(_data->window, pendingWindowWarpX, pendingWindowWarpY);
|
||||
pendingWindowWarpX = pendingWindowWarpY = -1;
|
||||
if (pendingWindowWarpX != INT_MAX && pendingWindowWarpY != INT_MAX) {
|
||||
mouse->WarpMouseGlobal(pendingWindowWarpX, pendingWindowWarpY);
|
||||
pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
|
||||
}
|
||||
if (mouse->relative_mode && SDL_GetMouseFocus() == _data->window) {
|
||||
if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data->window) {
|
||||
mouse->SetRelativeMouseMode(SDL_TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -413,7 +412,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
- (void)windowWillMove:(NSNotification *)aNotification
|
||||
{
|
||||
if ([_data->nswindow isKindOfClass:[SDLWindow class]]) {
|
||||
pendingWindowWarpX = pendingWindowWarpY = -1;
|
||||
pendingWindowWarpX = pendingWindowWarpY = INT_MAX;
|
||||
isMoving = YES;
|
||||
}
|
||||
}
|
||||
|
@ -500,7 +499,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
{
|
||||
SDL_Window *window = _data->window;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse->relative_mode && ![self isMoving]) {
|
||||
if (mouse->relative_mode && !mouse->relative_mode_warp && ![self isMoving]) {
|
||||
mouse->SetRelativeMouseMode(SDL_TRUE);
|
||||
}
|
||||
|
||||
|
@ -532,7 +531,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
- (void)windowDidResignKey:(NSNotification *)aNotification
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (mouse->relative_mode) {
|
||||
if (mouse->relative_mode && !mouse->relative_mode_warp) {
|
||||
mouse->SetRelativeMouseMode(SDL_FALSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -347,6 +347,9 @@ X11_DispatchFocusIn(SDL_WindowData *data)
|
|||
X11_XSetICFocus(data->ic);
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL_USE_IBUS
|
||||
SDL_IBus_SetFocus(SDL_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -367,6 +370,9 @@ X11_DispatchFocusOut(SDL_WindowData *data)
|
|||
X11_XUnsetICFocus(data->ic);
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL_USE_IBUS
|
||||
SDL_IBus_SetFocus(SDL_FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -646,11 +652,6 @@ X11_DispatchEvent(_THIS)
|
|||
}
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: FocusIn!\n", data);
|
||||
#endif
|
||||
#ifdef SDL_USE_IBUS
|
||||
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
|
||||
SDL_IBus_SetFocus(SDL_TRUE);
|
||||
}
|
||||
#endif
|
||||
if (data->pending_focus == PENDING_FOCUS_OUT &&
|
||||
data->window == SDL_GetKeyboardFocus()) {
|
||||
|
@ -688,11 +689,6 @@ X11_DispatchEvent(_THIS)
|
|||
}
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: FocusOut!\n", data);
|
||||
#endif
|
||||
#ifdef SDL_USE_IBUS
|
||||
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
|
||||
SDL_IBus_SetFocus(SDL_FALSE);
|
||||
}
|
||||
#endif
|
||||
data->pending_focus = PENDING_FOCUS_OUT;
|
||||
data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
|
||||
|
@ -725,16 +721,11 @@ X11_DispatchEvent(_THIS)
|
|||
KeySym keysym = NoSymbol;
|
||||
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
|
||||
Status status = 0;
|
||||
#ifdef SDL_USE_IBUS
|
||||
Bool handled = False;
|
||||
#endif
|
||||
SDL_bool handled_by_ime = SDL_FALSE;
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
|
||||
#endif
|
||||
#ifndef SDL_USE_IBUS
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
|
||||
#endif
|
||||
#if 1
|
||||
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
|
||||
int min_keycode, max_keycode;
|
||||
|
@ -762,7 +753,7 @@ X11_DispatchEvent(_THIS)
|
|||
#endif
|
||||
#ifdef SDL_USE_IBUS
|
||||
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
|
||||
if(!(handled = SDL_IBus_ProcessKeyEvent(keysym, keycode))){
|
||||
if(!(handled_by_ime = SDL_IBus_ProcessKeyEvent(keysym, keycode))){
|
||||
#endif
|
||||
if(*text){
|
||||
SDL_SendKeyboardText(text);
|
||||
|
@ -770,11 +761,11 @@ X11_DispatchEvent(_THIS)
|
|||
#ifdef SDL_USE_IBUS
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
#endif
|
||||
if (!handled_by_ime) {
|
||||
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1073,7 +1064,8 @@ X11_DispatchEvent(_THIS)
|
|||
because they use the NETWM protocol to notify us of changes.
|
||||
*/
|
||||
Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
|
||||
if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) {
|
||||
if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN ||
|
||||
(flags^data->window->flags) & SDL_WINDOW_FULLSCREEN ) {
|
||||
if (flags & SDL_WINDOW_HIDDEN) {
|
||||
X11_DispatchUnmapNotify(data);
|
||||
} else {
|
||||
|
|
|
@ -332,9 +332,7 @@ X11_QuitKeyboard(_THIS)
|
|||
void
|
||||
X11_StartTextInput(_THIS)
|
||||
{
|
||||
#ifdef SDL_USE_IBUS
|
||||
SDL_IBus_SetFocus(SDL_GetFocusWindow() != NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#if HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
struct
|
||||
{
|
||||
SDL_AudioSpec spec;
|
||||
|
|
|
@ -79,14 +79,16 @@ char* _RGBPixelFormatsVerbose[] =
|
|||
};
|
||||
|
||||
/* Definition of all Non-RGB formats used to test pixel conversions */
|
||||
const int _numNonRGBPixelFormats = 5;
|
||||
const int _numNonRGBPixelFormats = 7;
|
||||
Uint32 _nonRGBPixelFormats[] =
|
||||
{
|
||||
SDL_PIXELFORMAT_YV12,
|
||||
SDL_PIXELFORMAT_IYUV,
|
||||
SDL_PIXELFORMAT_YUY2,
|
||||
SDL_PIXELFORMAT_UYVY,
|
||||
SDL_PIXELFORMAT_YVYU
|
||||
SDL_PIXELFORMAT_YVYU,
|
||||
SDL_PIXELFORMAT_NV12,
|
||||
SDL_PIXELFORMAT_NV21
|
||||
};
|
||||
char* _nonRGBPixelFormatsVerbose[] =
|
||||
{
|
||||
|
@ -94,7 +96,9 @@ char* _nonRGBPixelFormatsVerbose[] =
|
|||
"SDL_PIXELFORMAT_IYUV",
|
||||
"SDL_PIXELFORMAT_YUY2",
|
||||
"SDL_PIXELFORMAT_UYVY",
|
||||
"SDL_PIXELFORMAT_YVYU"
|
||||
"SDL_PIXELFORMAT_YVYU",
|
||||
"SDL_PIXELFORMAT_NV12",
|
||||
"SDL_PIXELFORMAT_NV21"
|
||||
};
|
||||
|
||||
/* Definition of some invalid formats for negative tests */
|
||||
|
|
|
@ -45,8 +45,8 @@ main(int argc, char **argv)
|
|||
int i;
|
||||
char *name;
|
||||
int index;
|
||||
SDL_HapticEffect efx[5];
|
||||
int id[5];
|
||||
SDL_HapticEffect efx[9];
|
||||
int id[9];
|
||||
int nefx;
|
||||
unsigned int supported;
|
||||
|
||||
|
@ -149,6 +149,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
nefx++;
|
||||
}
|
||||
|
||||
/* Now the classical constant effect. */
|
||||
if (supported & SDL_HAPTIC_CONSTANT) {
|
||||
SDL_Log(" effect %d: Constant Force\n", nefx);
|
||||
|
@ -166,14 +167,15 @@ main(int argc, char **argv)
|
|||
}
|
||||
nefx++;
|
||||
}
|
||||
|
||||
/* The cute spring effect. */
|
||||
if (supported & SDL_HAPTIC_SPRING) {
|
||||
SDL_Log(" effect %d: Condition Spring\n", nefx);
|
||||
efx[nefx].type = SDL_HAPTIC_SPRING;
|
||||
efx[nefx].condition.length = 5000;
|
||||
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
|
||||
efx[nefx].condition.right_sat[i] = 0x7FFF;
|
||||
efx[nefx].condition.left_sat[i] = 0x7FFF;
|
||||
efx[nefx].condition.right_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.left_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.right_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.left_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.center[i] = 0x1000; /* Displace the center for it to move. */
|
||||
|
@ -185,14 +187,51 @@ main(int argc, char **argv)
|
|||
}
|
||||
nefx++;
|
||||
}
|
||||
/* The interesting damper effect. */
|
||||
if (supported & SDL_HAPTIC_DAMPER) {
|
||||
SDL_Log(" effect %d: Condition Damper\n", nefx);
|
||||
efx[nefx].type = SDL_HAPTIC_DAMPER;
|
||||
efx[nefx].condition.length = 5000;
|
||||
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
|
||||
efx[nefx].condition.right_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.left_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.right_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.left_coeff[i] = 0x2000;
|
||||
}
|
||||
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
|
||||
if (id[nefx] < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
|
||||
abort_execution();
|
||||
}
|
||||
nefx++;
|
||||
}
|
||||
/* The pretty awesome inertia effect. */
|
||||
if (supported & SDL_HAPTIC_INERTIA) {
|
||||
SDL_Log(" effect %d: Condition Inertia\n", nefx);
|
||||
efx[nefx].type = SDL_HAPTIC_INERTIA;
|
||||
efx[nefx].condition.length = 5000;
|
||||
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
|
||||
efx[nefx].condition.right_sat[i] = 0x7FFF;
|
||||
efx[nefx].condition.left_sat[i] = 0x7FFF;
|
||||
efx[nefx].condition.right_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.left_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.right_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.left_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.deadband[i] = 0x1000; /* 1/16th of axis-range around the center is 'dead'. */
|
||||
}
|
||||
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
|
||||
if (id[nefx] < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
|
||||
abort_execution();
|
||||
}
|
||||
nefx++;
|
||||
}
|
||||
/* The hot friction effect. */
|
||||
if (supported & SDL_HAPTIC_FRICTION) {
|
||||
SDL_Log(" effect %d: Condition Friction\n", nefx);
|
||||
efx[nefx].type = SDL_HAPTIC_FRICTION;
|
||||
efx[nefx].condition.length = 5000;
|
||||
for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
|
||||
efx[nefx].condition.right_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.left_sat[i] = 0xFFFF;
|
||||
efx[nefx].condition.right_coeff[i] = 0x2000;
|
||||
efx[nefx].condition.left_coeff[i] = 0x2000;
|
||||
}
|
||||
|
@ -204,6 +243,26 @@ main(int argc, char **argv)
|
|||
nefx++;
|
||||
}
|
||||
|
||||
/* Now we'll try a ramp effect */
|
||||
if (supported & SDL_HAPTIC_RAMP) {
|
||||
SDL_Log(" effect %d: Ramp\n", nefx);
|
||||
efx[nefx].type = SDL_HAPTIC_RAMP;
|
||||
efx[nefx].ramp.direction.type = SDL_HAPTIC_CARTESIAN;
|
||||
efx[nefx].ramp.direction.dir[0] = 1; /* Force comes from */
|
||||
efx[nefx].ramp.direction.dir[1] = -1; /* the north-east. */
|
||||
efx[nefx].ramp.length = 5000;
|
||||
efx[nefx].ramp.start = 0x4000;
|
||||
efx[nefx].ramp.end = -0x4000;
|
||||
efx[nefx].ramp.attack_length = 1000;
|
||||
efx[nefx].ramp.fade_length = 1000;
|
||||
id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
|
||||
if (id[nefx] < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
|
||||
abort_execution();
|
||||
}
|
||||
nefx++;
|
||||
}
|
||||
|
||||
/* Finally we'll try a left/right effect. */
|
||||
if (supported & SDL_HAPTIC_LEFTRIGHT) {
|
||||
SDL_Log(" effect %d: Left/Right\n", nefx);
|
||||
|
|
|
@ -206,6 +206,29 @@ ConvertRGBtoYV12(Uint8 *rgb, Uint8 *out, int w, int h,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConvertRGBtoNV12(Uint8 *rgb, Uint8 *out, int w, int h,
|
||||
int monochrome, int luminance)
|
||||
{
|
||||
int x, y;
|
||||
int yuv[3];
|
||||
Uint8 *op[2];
|
||||
|
||||
op[0] = out;
|
||||
op[1] = op[0] + w*h;
|
||||
for (y = 0; y < h; ++y) {
|
||||
for (x = 0; x < w; ++x) {
|
||||
RGBtoYUV(rgb, yuv, monochrome, luminance);
|
||||
*(op[0]++) = yuv[0];
|
||||
if (x % 2 == 0 && y % 2 == 0) {
|
||||
*(op[1]++) = yuv[1];
|
||||
*(op[1]++) = yuv[2];
|
||||
}
|
||||
rgb += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintUsage(char *argv0)
|
||||
{
|
||||
|
@ -241,7 +264,11 @@ main(int argc, char **argv)
|
|||
int fps = 12;
|
||||
int fpsdelay;
|
||||
int nodelay = 0;
|
||||
#ifdef TEST_NV12
|
||||
Uint32 pixel_format = SDL_PIXELFORMAT_NV12;
|
||||
#else
|
||||
Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
|
||||
#endif
|
||||
int scale = 5;
|
||||
SDL_bool done = SDL_FALSE;
|
||||
|
||||
|
@ -371,7 +398,17 @@ main(int argc, char **argv)
|
|||
rgb[2] = MooseColors[frame[j]].b;
|
||||
rgb += 3;
|
||||
}
|
||||
ConvertRGBtoYV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
||||
switch (pixel_format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
ConvertRGBtoYV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
ConvertRGBtoNV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
||||
break;
|
||||
default:
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unsupported pixel format\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(RawMooseData);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue