From ef6ef9a251f8fe28cfe368efa44d99298a66cd76 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 19:57:46 +0300 Subject: [PATCH 01/23] Updated todo --- bugs.txt | 3 --- todo.txt | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bugs.txt b/bugs.txt index 9b8e7566c..4c20d5301 100644 --- a/bugs.txt +++ b/bugs.txt @@ -16,9 +16,6 @@ Requested features, might never get implemented, see todo.txt for features that - Show/hide screen controls with longpress on Text Edit button. -- Floating on-screen joystick - initially invisible, it appears when you touch the screen, - centered on your finger, then it slides with your finger if you bump the joystick edge. - - Export phone vibrator to SDL - interface is available in SDL 1.3. - Control screen brightness with SDL_SetGamma(). diff --git a/todo.txt b/todo.txt index 6998cdd36..333481746 100644 --- a/todo.txt +++ b/todo.txt @@ -21,6 +21,9 @@ TODO, which will get actually done - SDL: user-configurable option to set screen orientation. +- Floating on-screen joystick - initially invisible, it appears when you touch the screen, + centered on your finger, then it slides with your finger if you bump the joystick edge. + - OpenTTD: All menus in the scenario editor are out of the screen. - OpenTTD: 16bpp blitter with palette animation support. From 826a0d34eccae6b74d987a774cfc0cb5f88f6e33 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 20:26:28 +0300 Subject: [PATCH 02/23] Added function to enable/disable floating joystick --- project/jni/application/ballfield/ballfield.cpp | 3 +++ project/jni/sdl-1.2/include/SDL_screenkeyboard.h | 4 ++++ .../sdl-1.2/src/video/android/SDL_touchscreenkeyboard.c | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/project/jni/application/ballfield/ballfield.cpp b/project/jni/application/ballfield/ballfield.cpp index b89a87a0c..0bbca5c79 100644 --- a/project/jni/application/ballfield/ballfield.cpp +++ b/project/jni/application/ballfield/ballfield.cpp @@ -594,6 +594,9 @@ int main(int argc, char* argv[]) fps = (float)fps_count * 1000.0 / (tick - fps_start); fps_count = 0; fps_start = tick; + static int fj = false; + fj=!fj; + SDL_ANDROID_SetScreenKeyboardFloatingJoystick(fj); } print_num(screen, font, screen->w-37, screen->h-12, fps); diff --git a/project/jni/sdl-1.2/include/SDL_screenkeyboard.h b/project/jni/sdl-1.2/include/SDL_screenkeyboard.h index 4af9ccb34..639efc02c 100644 --- a/project/jni/sdl-1.2/include/SDL_screenkeyboard.h +++ b/project/jni/sdl-1.2/include/SDL_screenkeyboard.h @@ -103,6 +103,10 @@ extern DECLSPEC int SDLCALL SDL_ANDROID_SetScreenKeyboardButtonGenerateTouchEven /* Configure a button to stay pressed after touch, and un-press after second touch, to emulate Ctrl/Alt/Shift keys */ extern DECLSPEC int SDLCALL SDL_ANDROID_SetScreenKeyboardButtonStayPressedAfterTouch(int buttonId, int stayPressed); +/* Enable or disable floating joystick, the joystick is hidden after you disable floating joystick, + you should set it's coordinates with SDL_ANDROID_SetScreenKeyboardButtonPos(). */ +extern DECLSPEC int SDLCALL SDL_ANDROID_SetScreenKeyboardFloatingJoystick(int enabled); + /* Set screen keyboard transparency, 255 or SDL_ALPHA_OPAQUE is non-transparent, 0 or SDL_ALPHA_TRANSPARENT is transparent */ extern DECLSPEC int SDLCALL SDL_ANDROID_SetScreenKeyboardTransparency(int alpha); diff --git a/project/jni/sdl-1.2/src/video/android/SDL_touchscreenkeyboard.c b/project/jni/sdl-1.2/src/video/android/SDL_touchscreenkeyboard.c index 0ae6e77b5..4906d3b7e 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_touchscreenkeyboard.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_touchscreenkeyboard.c @@ -1191,6 +1191,14 @@ int SDL_ANDROID_SetScreenKeyboardHintMesage(const char * hint) return 1; } +extern DECLSPEC int SDLCALL SDL_ANDROID_SetScreenKeyboardFloatingJoystick(int enabled) +{ + floatingScreenJoystick = enabled; + SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_DPAD, 0); + return 1; +} + + /** * @brief Dumps OpenGL state for debugging - typically every capability set with glEnable(). */ From eb93f506c783942514b66a6cf537c47d3cfdd214 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 20:28:35 +0300 Subject: [PATCH 03/23] Updated todo --- todo.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo.txt b/todo.txt index 9da834f85..13c553fbd 100644 --- a/todo.txt +++ b/todo.txt @@ -49,6 +49,8 @@ TODO, which will get actually done - OpenTTD: "Open website" button in online resource menu is broken. +- OpenTTD: Frameskip when fast-forward button pressed. + - Debian noroot: audio support. - Debian noroot: add Java dirs to PATH, add support for update scripts. From da0bf9ae6d80e31aec930df8959e4496bb061723 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 20:30:18 +0300 Subject: [PATCH 04/23] Updated todo --- todo.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/todo.txt b/todo.txt index 13c553fbd..dfaabcf78 100644 --- a/todo.txt +++ b/todo.txt @@ -26,9 +26,6 @@ TODO, which will get actually done - SDL: option to disable immersive mode. -- Floating on-screen joystick - initially invisible, it appears when you touch the screen, - centered on your finger, then it slides with your finger if you bump the joystick edge. - - OpenTTD: All menus in the scenario editor are out of the screen. - OpenTTD: 16bpp blitter with palette animation support. @@ -55,6 +52,8 @@ TODO, which will get actually done - Debian noroot: add Java dirs to PATH, add support for update scripts. +- Debian noroot: add paths to external SD cards to the proot. + - XSDL: add downloadable raster fonts, add path to fonts to Debian/Gimp. - Gimp: update - add Java dirs to PATH and use new mouse name in Gimp config. From 51389e0f0fa871cf36a64ad278ecde9a197aafde Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 22:39:23 +0300 Subject: [PATCH 05/23] User-configurable option for on-screen joystick --- project/java/SettingsMenuKeyboard.java | 49 +++++++++++++++++++ project/java/SettingsMenuMouse.java | 4 +- .../unsupported/values-de/strings.xml | 2 +- .../unsupported/values-fi/strings.xml | 2 +- .../java/translations/values-fr/strings.xml | 2 +- .../java/translations/values-ru/strings.xml | 2 +- .../java/translations/values-uk/strings.xml | 2 +- project/java/translations/values/strings.xml | 3 +- .../jni/application/ballfield/ballfield.cpp | 3 -- 9 files changed, 58 insertions(+), 11 deletions(-) diff --git a/project/java/SettingsMenuKeyboard.java b/project/java/SettingsMenuKeyboard.java index ae791b448..a06ec4088 100644 --- a/project/java/SettingsMenuKeyboard.java +++ b/project/java/SettingsMenuKeyboard.java @@ -96,6 +96,7 @@ class SettingsMenuKeyboard extends SettingsMenu new ScreenKeyboardTransparencyConfig(), new RemapScreenKbConfig(), new CustomizeScreenKbLayout(), + new ScreenKeyboardAdvanced(), new OkButton(), }; showMenuOptionsList(p, options); @@ -850,5 +851,53 @@ class SettingsMenuKeyboard extends SettingsMenu } } } + + static class ScreenKeyboardAdvanced extends Menu + { + String title(final MainActivity p) + { + return p.getResources().getString(R.string.advanced); + } + //boolean enabled() { return true; }; + void run (final MainActivity p) + { + CharSequence[] items = { + p.getResources().getString(R.string.screenkb_floating_joystick), + }; + + boolean defaults[] = { + Globals.FloatingScreenJoystick, + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(p); + builder.setTitle(p.getResources().getString(R.string.advanced)); + builder.setMultiChoiceItems(items, defaults, new DialogInterface.OnMultiChoiceClickListener() + { + public void onClick(DialogInterface dialog, int item, boolean isChecked) + { + if( item == 0 ) + Globals.FloatingScreenJoystick = isChecked; + } + }); + builder.setPositiveButton(p.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog, int item) + { + dialog.dismiss(); + goBack(p); + } + }); + builder.setOnCancelListener(new DialogInterface.OnCancelListener() + { + public void onCancel(DialogInterface dialog) + { + goBack(p); + } + }); + AlertDialog alert = builder.create(); + alert.setOwnerActivity(p); + alert.show(); + } + } } diff --git a/project/java/SettingsMenuMouse.java b/project/java/SettingsMenuMouse.java index acd6b230c..f0f20ef1a 100644 --- a/project/java/SettingsMenuMouse.java +++ b/project/java/SettingsMenuMouse.java @@ -409,7 +409,7 @@ class SettingsMenuMouse extends SettingsMenu { String title(final MainActivity p) { - return p.getResources().getString(R.string.mouse_question); + return p.getResources().getString(R.string.advanced); } void run (final MainActivity p) { @@ -433,7 +433,7 @@ class SettingsMenuMouse extends SettingsMenu AlertDialog.Builder builder = new AlertDialog.Builder(p); - builder.setTitle(p.getResources().getString(R.string.mouse_question)); + builder.setTitle(p.getResources().getString(R.string.advanced)); builder.setMultiChoiceItems(items, defaults, new DialogInterface.OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int item, boolean isChecked) diff --git a/project/java/translations/unsupported/values-de/strings.xml b/project/java/translations/unsupported/values-de/strings.xml index 8d6551fda..4d1125092 100644 --- a/project/java/translations/unsupported/values-de/strings.xml +++ b/project/java/translations/unsupported/values-de/strings.xml @@ -62,7 +62,7 @@ Menütaste Touch-Screen mit dem zweiten Finger Touchscreen mit Kraft -Erweiterte Funktionen +Erweiterte Funktionen Halten 4:3-Bildschirm Seitenverhältnis Show-Bildschirm unter dem Finger in einem separaten Fenster Bitte schieben Sie den Finger über den Bildschirm für zwei Sekunden diff --git a/project/java/translations/unsupported/values-fi/strings.xml b/project/java/translations/unsupported/values-fi/strings.xml index 105ca7913..c7e7cfbb9 100644 --- a/project/java/translations/unsupported/values-fi/strings.xml +++ b/project/java/translations/unsupported/values-fi/strings.xml @@ -62,7 +62,7 @@ Valikkonäppäin Kosketusnäyttö on toinen sormi Kosketusnäyttö voimalla -Lisäominaisuudet +Lisäominaisuudet Pidä 04:03 kuvasuhde Näytä näytön alle sormi erillisessä ikkunassa Ole hyvä ja liu\u0026#39;uttamalla sormea näytöllä kaksi sekuntia diff --git a/project/java/translations/values-fr/strings.xml b/project/java/translations/values-fr/strings.xml index 3c1ed1cc3..a1fb1ddd1 100644 --- a/project/java/translations/values-fr/strings.xml +++ b/project/java/translations/values-fr/strings.xml @@ -98,7 +98,7 @@ 1,5 sec Cliquez gauche de la souris avec le Trackball / centre du joystick -Fonctionnalités avancées +Fonctionnalités avancées Gardez le format 4:3 écran Afficher l\'écran sous le doigt dans une fenêtre séparée Loupe à l\'écran diff --git a/project/java/translations/values-ru/strings.xml b/project/java/translations/values-ru/strings.xml index ea560921f..b35cae47c 100644 --- a/project/java/translations/values-ru/strings.xml +++ b/project/java/translations/values-ru/strings.xml @@ -46,7 +46,7 @@ Кнопка меню Касание экрана вторым пальцем Нажатие на экран с силой -Расширенные функции +Расширенные функции Сохранять соотношение сторон 4:3 на экране Экранная лупа Пожалуйста, проведите пальцем по экрану в течение двух секунд diff --git a/project/java/translations/values-uk/strings.xml b/project/java/translations/values-uk/strings.xml index 30d085f2e..6d953fd76 100644 --- a/project/java/translations/values-uk/strings.xml +++ b/project/java/translations/values-uk/strings.xml @@ -46,7 +46,7 @@ Кнопка меню Торкання екрана другим пальцем Натиск на екран силою -Розширені функції +Розширені функції Зберігати співвідношення сторін 4:3 на екрані Наекранна лупа Будь-ласка, проведіть пальцем по екрану на протязі двох секунд diff --git a/project/java/translations/values/strings.xml b/project/java/translations/values/strings.xml index b043d40e2..9f569a1cc 100644 --- a/project/java/translations/values/strings.xml +++ b/project/java/translations/values/strings.xml @@ -98,7 +98,7 @@ 1.5 sec Left mouse click with trackball / joystick center - Advanced features + Advanced features Keep 4:3 screen aspect ratio Show screen under finger in separate window On-screen magnifying glass @@ -144,6 +144,7 @@ Customize on-screen keyboard layout Press BACK when done. Resize buttons by sliding on empty space. + Floating joystick Calibrate touchscreen Touch all edges of the screen, press BACK when done diff --git a/project/jni/application/ballfield/ballfield.cpp b/project/jni/application/ballfield/ballfield.cpp index 0bbca5c79..b89a87a0c 100644 --- a/project/jni/application/ballfield/ballfield.cpp +++ b/project/jni/application/ballfield/ballfield.cpp @@ -594,9 +594,6 @@ int main(int argc, char* argv[]) fps = (float)fps_count * 1000.0 / (tick - fps_start); fps_count = 0; fps_start = tick; - static int fj = false; - fj=!fj; - SDL_ANDROID_SetScreenKeyboardFloatingJoystick(fj); } print_num(screen, font, screen->w-37, screen->h-12, fps); From 7da700e625fd175a225134465cd29a0dd30757e7 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Mon, 23 Jun 2014 23:42:07 +0300 Subject: [PATCH 06/23] Made screen orientation, BPP, immersive mode and sub-frame touch events a user configurable options --- project/AndroidManifestTemplate.xml | 1 - project/java/Globals.java | 8 +++--- project/java/MainActivity.java | 19 ++++++++------ project/java/Settings.java | 8 ++++++ project/java/SettingsMenuMisc.java | 26 +++++++++++++++++--- project/java/SettingsMenuMouse.java | 5 +++- project/java/translations/values/strings.xml | 6 ++++- todo.txt | 11 --------- 8 files changed, 55 insertions(+), 29 deletions(-) diff --git a/project/AndroidManifestTemplate.xml b/project/AndroidManifestTemplate.xml index dca5f9fcb..e51d030ef 100644 --- a/project/AndroidManifestTemplate.xml +++ b/project/AndroidManifestTemplate.xml @@ -13,7 +13,6 @@ android:label="@string/app_name" android:alwaysRetainTaskState="true" android:launchMode="singleTask" - android:screenOrientation="sensorLandscape" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|fontScale|uiMode|screenSize|smallestScreenSize" android:windowSoftInputMode="stateUnspecified|adjustPan" > diff --git a/project/java/Globals.java b/project/java/Globals.java index b1f589f71..13e4e420b 100644 --- a/project/java/Globals.java +++ b/project/java/Globals.java @@ -35,7 +35,6 @@ class Globals public static final boolean Using_SDL_1_3 = false; public static final boolean Using_SDL_2_0 = false; public static String[] DataDownloadUrl = { "Data files are 2 Mb|https://sourceforge.net/projects/libsdl-android/files/CommanderGenius/commandergenius-data.zip/download", "High-quality GFX and music - 40 Mb|https://sourceforge.net/projects/libsdl-android/files/CommanderGenius/commandergenius-hqp.zip/download" }; - public static int VideoDepthBpp = 16; public static boolean SwVideoMode = false; public static boolean NeedDepthBuffer = false; public static boolean NeedStencilBuffer = false; @@ -44,7 +43,6 @@ class Globals public static boolean CompatibilityHacksForceScreenUpdateMouseClick = true; public static boolean CompatibilityHacksStaticInit = false; public static boolean CompatibilityHacksTextInputEmulatesHwKeyboard = false; - public static boolean HorizontalOrientation = true; public static boolean KeepAspectRatioDefaultSetting = false; public static boolean InhibitSuspend = false; public static boolean CreateService = false; @@ -55,7 +53,6 @@ class Globals public static boolean RightMouseButtonLongPress = true; public static boolean ForceRelativeMouseMode = false; // If both on-screen keyboard and mouse are needed, this will only set the default setting, user may override it later public static boolean ShowMouseCursor = false; - public static boolean GenerateSubframeTouchEvents = false; public static boolean AppNeedsArrowKeys = true; public static boolean AppNeedsTextInput = true; public static boolean AppUsesJoystick = false; @@ -65,7 +62,6 @@ class Globals public static boolean AppUsesGyroscope = false; public static boolean AppUsesMultitouch = false; public static boolean NonBlockingSwapBuffers = false; - public static boolean ImmersiveMode = true; public static boolean ResetSdlConfigForThisVersion = false; public static String DeleteFilesOnUpgrade = ""; public static int AppTouchscreenKeyboardKeysAmount = 4; @@ -79,6 +75,9 @@ class Globals public static String AdmobBannerSize = ""; // Phone-specific config, modified by user in "Change phone config" startup dialog + public static int VideoDepthBpp = 16; + public static boolean HorizontalOrientation = true; + public static boolean ImmersiveMode = true; public static boolean DownloadToSdcard = true; public static boolean PhoneHasTrackball = false; public static boolean PhoneHasArrowKeys = false; @@ -115,6 +114,7 @@ class Globals public static int ClickScreenTouchspotSize = 0; public static boolean FingerHover = true; public static boolean HoverJitterFilter = true; + public static boolean GenerateSubframeTouchEvents = false; public static boolean KeepAspectRatio = KeepAspectRatioDefaultSetting; public static int RemapHwKeycode[] = new int[SDL_Keys.JAVA_KEYCODE_LAST]; public static int RemapScreenKbKeycode[] = new int[6]; diff --git a/project/java/MainActivity.java b/project/java/MainActivity.java index e00431fd5..c43df63c1 100644 --- a/project/java/MainActivity.java +++ b/project/java/MainActivity.java @@ -87,12 +87,7 @@ public class MainActivity extends Activity { super.onCreate(savedInstanceState); - //if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2 ) - // setRequestedOrientation(Globals.HorizontalOrientation ? ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); - if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD ) - setRequestedOrientation(Globals.HorizontalOrientation ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); - else - setRequestedOrientation(Globals.HorizontalOrientation ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + setScreenOrientation(); instance = this; // fullscreen mode @@ -127,6 +122,7 @@ public class MainActivity extends Activity setUpStatusLabel(); Log.i("SDL", "libSDL: User clicked change phone config button"); loadedLibraries.acquireUninterruptibly(); + setScreenOrientation(); SettingsMenu.showConfig(p, false); } }; @@ -269,6 +265,7 @@ public class MainActivity extends Activity public void initSDL() { + setScreenOrientation(); (new Thread(new Runnable() { public void run() @@ -312,6 +309,7 @@ public class MainActivity extends Activity Log.i("SDL", "libSDL: Initializing video and SDL application"); sdlInited = true; + DimSystemStatusBar.get().dim(_videoLayout); _videoLayout.removeView(_layout); if( _ad.getView() != null ) _videoLayout.removeView(_ad.getView()); @@ -334,7 +332,6 @@ public class MainActivity extends Activity _videoLayout.addView(_ad.getView()); _ad.getView().setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.TOP | Gravity.RIGHT)); } - // Receive keyboard events DimSystemStatusBar.get().dim(_videoLayout); DimSystemStatusBar.get().dim(mGLView); } @@ -1184,6 +1181,14 @@ public class MainActivity extends Activity return getOrient.getWidth() >= getOrient.getHeight(); } + void setScreenOrientation() + { + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD ) + setRequestedOrientation(Globals.HorizontalOrientation ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); + else + setRequestedOrientation(Globals.HorizontalOrientation ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + public FrameLayout getVideoLayout() { return _videoLayout; } static int NOTIFY_ID = 12367098; // Random ID diff --git a/project/java/Settings.java b/project/java/Settings.java index 4086fb5e2..fa3a34e1e 100644 --- a/project/java/Settings.java +++ b/project/java/Settings.java @@ -178,6 +178,10 @@ class Settings out.writeInt(Globals.MoveMouseWithGyroscopeSpeed); out.writeBoolean(Globals.FingerHover); out.writeBoolean(Globals.FloatingScreenJoystick); + out.writeBoolean(Globals.GenerateSubframeTouchEvents); + out.writeInt(Globals.VideoDepthBpp); + out.writeBoolean(Globals.HorizontalOrientation); + out.writeBoolean(Globals.ImmersiveMode); out.close(); settingsLoaded = true; @@ -366,6 +370,10 @@ class Settings Globals.MoveMouseWithGyroscopeSpeed = settingsFile.readInt(); Globals.FingerHover = settingsFile.readBoolean(); Globals.FloatingScreenJoystick = settingsFile.readBoolean(); + Globals.GenerateSubframeTouchEvents = settingsFile.readBoolean(); + Globals.VideoDepthBpp = settingsFile.readInt(); + Globals.HorizontalOrientation = settingsFile.readBoolean(); + Globals.ImmersiveMode = settingsFile.readBoolean(); settingsLoaded = true; diff --git a/project/java/SettingsMenuMisc.java b/project/java/SettingsMenuMisc.java index 0a3a223ba..6425c0006 100644 --- a/project/java/SettingsMenuMisc.java +++ b/project/java/SettingsMenuMisc.java @@ -345,11 +345,17 @@ class SettingsMenuMisc extends SettingsMenu debugMenuShowCount++; CharSequence[] items = { p.getResources().getString(R.string.mouse_keepaspectratio), - p.getResources().getString(R.string.video_smooth) + p.getResources().getString(R.string.video_smooth), + p.getResources().getString(R.string.video_immersive), + p.getResources().getString(R.string.video_orientation_vertical), + p.getResources().getString(R.string.video_bpp_24), }; - boolean defaults[] = { + boolean defaults[] = { Globals.KeepAspectRatio, - Globals.VideoLinearFilter + Globals.VideoLinearFilter, + Globals.ImmersiveMode, + !Globals.HorizontalOrientation, + Globals.VideoDepthBpp == 24, }; if(Globals.SwVideoMode && !Globals.CompatibilityHacksVideo) @@ -357,12 +363,18 @@ class SettingsMenuMisc extends SettingsMenu CharSequence[] items2 = { p.getResources().getString(R.string.mouse_keepaspectratio), p.getResources().getString(R.string.video_smooth), + p.getResources().getString(R.string.video_immersive), + p.getResources().getString(R.string.video_orientation_vertical), + p.getResources().getString(R.string.video_bpp_24), p.getResources().getString(R.string.video_separatethread), }; boolean defaults2[] = { Globals.KeepAspectRatio, Globals.VideoLinearFilter, - Globals.MultiThreadedVideo + Globals.ImmersiveMode, + !Globals.HorizontalOrientation, + Globals.VideoDepthBpp == 24, + Globals.MultiThreadedVideo, }; items = items2; defaults = defaults2; @@ -391,6 +403,12 @@ class SettingsMenuMisc extends SettingsMenu if( item == 1 ) Globals.VideoLinearFilter = isChecked; if( item == 2 ) + Globals.ImmersiveMode = isChecked; + if( item == 3 ) + Globals.HorizontalOrientation = !isChecked; + if( item == 4 ) + Globals.VideoDepthBpp = (isChecked ? 24 : 16); + if( item == 5 ) Globals.MultiThreadedVideo = isChecked; } }); diff --git a/project/java/SettingsMenuMouse.java b/project/java/SettingsMenuMouse.java index f0f20ef1a..e1f5feeb1 100644 --- a/project/java/SettingsMenuMouse.java +++ b/project/java/SettingsMenuMouse.java @@ -420,6 +420,7 @@ class SettingsMenuMouse extends SettingsMenu p.getResources().getString(R.string.mouse_relative), p.getResources().getString(R.string.mouse_gyroscope_mouse), p.getResources().getString(R.string.mouse_finger_hover), + p.getResources().getString(R.string.mouse_subframe_touch_events), }; boolean defaults[] = { @@ -429,9 +430,9 @@ class SettingsMenuMouse extends SettingsMenu Globals.RelativeMouseMovement, Globals.MoveMouseWithGyroscope, Globals.FingerHover, + Globals.GenerateSubframeTouchEvents, }; - AlertDialog.Builder builder = new AlertDialog.Builder(p); builder.setTitle(p.getResources().getString(R.string.advanced)); builder.setMultiChoiceItems(items, defaults, new DialogInterface.OnMultiChoiceClickListener() @@ -450,6 +451,8 @@ class SettingsMenuMouse extends SettingsMenu Globals.MoveMouseWithGyroscope = isChecked; if( item == 5 ) Globals.FingerHover = isChecked; + if( item == 6 ) + Globals.GenerateSubframeTouchEvents = isChecked; } }); builder.setPositiveButton(p.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() diff --git a/project/java/translations/values/strings.xml b/project/java/translations/values/strings.xml index 9f569a1cc..cccde4f67 100644 --- a/project/java/translations/values/strings.xml +++ b/project/java/translations/values/strings.xml @@ -112,6 +112,7 @@ Control mouse with gyroscope Gyroscope sensitivity Finger hover + Multiple touch events per video frame None @@ -151,7 +152,10 @@ Video settings Linear video filtering - Separate thread for video, will increase FPS on some devices + Separate thread for video, it can increase FPS, it also can crash the app + Portrait/vertical screen orientation + 24 bpp screen color depth + Hide system navigation buttons / immersive mode Tap to start typing, press Back when done diff --git a/todo.txt b/todo.txt index dfaabcf78..e94d90b26 100644 --- a/todo.txt +++ b/todo.txt @@ -15,17 +15,8 @@ TODO, which will get actually done - SuperTux: Update, enable OpenGL renderer, add touchscreen jump helper, add gamepad support, fix zoom in settings. -- SDL: make sub-frame touch events as an user-configurable option. - - SDL: control mouse with right analog gamepad stick. -- SDL: user-configurable option to set screen orientation and BPP. - -- SDL: floating on-screen joystick - initially invisible, it appears when you touch the screen, - centered on your finger, then it slides with your finger if you bump the joystick edge. - -- SDL: option to disable immersive mode. - - OpenTTD: All menus in the scenario editor are out of the screen. - OpenTTD: 16bpp blitter with palette animation support. @@ -54,6 +45,4 @@ TODO, which will get actually done - Debian noroot: add paths to external SD cards to the proot. -- XSDL: add downloadable raster fonts, add path to fonts to Debian/Gimp. - - Gimp: update - add Java dirs to PATH and use new mouse name in Gimp config. From 0a1b80a9dd0da5cd728999ef524e02d4fbfdf670 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 24 Jun 2014 19:09:57 +0300 Subject: [PATCH 07/23] Fixed SDL not sleeping while in background. It's actually a serious bug, but it wasn't that obvious, because all devices are multicore now. --- project/java/GLSurfaceView_SDL.java | 20 ++++++++++++++------ project/java/Video.java | 7 ++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/project/java/GLSurfaceView_SDL.java b/project/java/GLSurfaceView_SDL.java index 93c3a465e..8cc5c8371 100644 --- a/project/java/GLSurfaceView_SDL.java +++ b/project/java/GLSurfaceView_SDL.java @@ -1059,14 +1059,21 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call } while (needToWait()) { //Log.v("SDL", "GLSurfaceView_SDL::run(): paused"); - try { - wait(500); - } catch(Exception e) { } + synchronized(this) { + try + { + wait(500); + } + catch(InterruptedException e) + { + Log.v("SDL", "GLSurfaceView_SDL::GLThread::SwapBuffers(): Who dared to interrupt my slumber?"); + Thread.interrupted(); // Clear the flag + } + } } synchronized (this) { - if (mDone) { + if (mDone) return false; - } // changed = mSizeChanged; w = mWidth; h = mHeight; @@ -1198,6 +1205,7 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call public void requestExitAndWait() { // don't call this from GLThread thread or it is a guaranteed // deadlock! + Log.v("SDL", "GLSurfaceView_SDL::requestExitAndWait()"); synchronized(this) { mDone = true; notify(); @@ -1205,7 +1213,7 @@ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Call try { join(); } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + //Thread.currentThread().interrupt(); } } diff --git a/project/java/Video.java b/project/java/Video.java index 8885661a5..deba57b74 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -960,7 +960,12 @@ class DemoGLSurfaceView extends GLSurfaceView_SDL { try { mRenderer.wait(300L); // And sometimes the app decides not to render at all, so this timeout should not be big. - } catch (InterruptedException e) { } + } + catch (InterruptedException e) + { + Log.v("SDL", "DemoGLSurfaceView::limitEventRate(): Who dared to interrupt my slumber?"); + Thread.interrupted(); + } } } } From e7693951a2f9689756bfc5653308c200fc2bad34 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 24 Jun 2014 20:21:25 +0300 Subject: [PATCH 08/23] Replaced spaces with tabs in Java code --- project/java/GLSurfaceView_SDL.java | 2320 ++++++++--------- project/java/Video.java | 4 +- .../src/video/android/SDL_androidinput.c | 2 + 3 files changed, 1164 insertions(+), 1162 deletions(-) diff --git a/project/java/GLSurfaceView_SDL.java b/project/java/GLSurfaceView_SDL.java index 8cc5c8371..af7ccbd20 100644 --- a/project/java/GLSurfaceView_SDL.java +++ b/project/java/GLSurfaceView_SDL.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -125,1170 +125,1170 @@ import android.app.KeyguardManager; *
  * class MyGLSurfaceView extends GLSurfaceView {
  *
- *     private MyRenderer mMyRenderer;
+ *	   private MyRenderer mMyRenderer;
  *
- *     public void start() {
- *         mMyRenderer = ...;
- *         setRenderer(mMyRenderer);
- *     }
+ *	   public void start() {
+ *		   mMyRenderer = ...;
+ *		   setRenderer(mMyRenderer);
+ *	   }
  *
- *     public boolean onKeyDown(int keyCode, KeyEvent event) {
- *         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- *             queueEvent(new Runnable() {
- *                 // This method will be called on the rendering
- *                 // thread:
- *                 public void run() {
- *                     mMyRenderer.handleDpadCenter();
- *                 }});
- *             return true;
- *         }
- *         return super.onKeyDown(keyCode, event);
- *     }
+ *	   public boolean onKeyDown(int keyCode, KeyEvent event) {
+ *		   if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+ *			   queueEvent(new Runnable() {
+ *				   // This method will be called on the rendering
+ *				   // thread:
+ *				   public void run() {
+ *					   mMyRenderer.handleDpadCenter();
+ *				   }});
+ *			   return true;
+ *		   }
+ *		   return super.onKeyDown(keyCode, event);
+ *	   }
  * }
  * 
* */ public class GLSurfaceView_SDL extends SurfaceView implements SurfaceHolder.Callback { - /** - * The renderer only renders - * when the surface is created, or when {@link #requestRender} is called. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - */ - public final static int RENDERMODE_WHEN_DIRTY = 0; - /** - * The renderer is called - * continuously to re-render the scene. - * - * @see #getRenderMode() - * @see #setRenderMode(int) - * @see #requestRender() - */ - public final static int RENDERMODE_CONTINUOUSLY = 1; - - /** - * Check glError() after every GL call and throw an exception if glError indicates - * that an error has occurred. This can be used to help track down which OpenGL ES call - * is causing an error. - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_CHECK_GL_ERROR = 1; - - /** - * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". - * - * @see #getDebugFlags - * @see #setDebugFlags - */ - public final static int DEBUG_LOG_GL_CALLS = 2; - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context) { - super(context); - init(); - } - - /** - * Standard View constructor. In order to render something, you - * must call {@link #setRenderer} to register a renderer. - */ - public GLSurfaceView_SDL(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - // Install a SurfaceHolder.Callback so we get notified when the - // underlying surface is created and destroyed - SurfaceHolder holder = getHolder(); - holder.addCallback(this); - holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); - mKeyguardManager = ((KeyguardManager)getContext().getSystemService(Context.KEYGUARD_SERVICE)); - } - - /** - * Set the glWrapper. If the glWrapper is not null, its - * {@link GLWrapper#wrap(GL)} method is called - * whenever a surface is created. A GLWrapper can be used to wrap - * the GL object that's passed to the renderer. Wrapping a GL - * object enables examining and modifying the behavior of the - * GL calls made by the renderer. - *

- * Wrapping is typically used for debugging purposes. - *

- * The default value is null. - * @param glWrapper the new GLWrapper - */ - public void setGLWrapper(GLWrapper glWrapper) { - mGLWrapper = glWrapper; - } - - /** - * Set the debug flags to a new value. The value is - * constructed by OR-together zero or more - * of the DEBUG_CHECK_* constants. The debug flags take effect - * whenever a surface is created. The default value is zero. - * @param debugFlags the new debug flags - * @see #DEBUG_CHECK_GL_ERROR - * @see #DEBUG_LOG_GL_CALLS - */ - public void setDebugFlags(int debugFlags) { - mDebugFlags = debugFlags; - } - - /** - * Get the current value of the debug flags. - * @return the current value of the debug flags. - */ - public int getDebugFlags() { - return mDebugFlags; - } - - /** - * Set the renderer associated with this view. Also starts the thread that - * will call the renderer, which in turn causes the rendering to start. - *

This method should be called once and only once in the life-cycle of - * a GLSurfaceView. - *

The following GLSurfaceView methods can only be called before - * setRenderer is called: - *

    - *
  • {@link #setEGLConfigChooser(boolean)} - *
  • {@link #setEGLConfigChooser(EGLConfigChooser)} - *
  • {@link #setEGLConfigChooser(int, int, int, int, int, int)} - *
- *

- * The following GLSurfaceView methods can only be called after - * setRenderer is called: - *

    - *
  • {@link #getRenderMode()} - *
  • {@link #onPause()} - *
  • {@link #onResume()} - *
  • {@link #queueEvent(Runnable)} - *
  • {@link #requestRender()} - *
  • {@link #setRenderMode(int)} - *
- * - * @param renderer the renderer to use to perform OpenGL drawing. - */ - public void setRenderer(Renderer renderer) { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - if (mEGLConfigChooser == null) { - mEGLConfigChooser = getEglConfigChooser(16, false, false, false); - } - mGLThread = new GLThread(renderer); - mGLThread.start(); - } - - /** - * Install a custom EGLConfigChooser. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * @param configChooser - */ - public void setEGLConfigChooser(EGLConfigChooser configChooser) { - if (mGLThread != null) { - throw new IllegalStateException( - "setRenderer has already been called for this instance."); - } - mEGLConfigChooser = configChooser; - } - - /** - * Install a config chooser which will choose a config - * as close to 16-bit RGB as possible, with or without an optional depth - * buffer as close to 16-bits as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - * @param needDepth - */ - public void setEGLConfigChooser(int bpp, boolean needDepth, boolean stencil, boolean gles2) { - setEGLConfigChooser(getEglConfigChooser(bpp, needDepth, stencil, gles2)); - } - - /** - * Install a config chooser which will choose a config - * with at least the specified component sizes, and as close - * to the specified component sizes as possible. - *

If this method is - * called, it must be called before {@link #setRenderer(Renderer)} - * is called. - *

- * If no setEGLConfigChooser method is called, then by default the - * view will choose a config as close to 16-bit RGB as possible, with - * a depth buffer as close to 16 bits as possible. - * - */ - public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize, boolean gles2) { - setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, - blueSize, alphaSize, depthSize, stencilSize, gles2)); - } - /** - * Set the rendering mode. When renderMode is - * RENDERMODE_CONTINUOUSLY, the renderer is called - * repeatedly to re-render the scene. When renderMode - * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface - * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. - *

- * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance - * by allowing the GPU and CPU to idle when the view does not need to be updated. - *

- * This method can only be called after {@link #setRenderer(Renderer)} - * - * @param renderMode one of the RENDERMODE_X constants - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public void setRenderMode(int renderMode) { - mGLThread.setRenderMode(renderMode); - } - - /** - * Get the current rendering mode. May be called - * from any thread. Must not be called before a renderer has been set. - * @return the current rendering mode. - * @see #RENDERMODE_CONTINUOUSLY - * @see #RENDERMODE_WHEN_DIRTY - */ - public int getRenderMode() { - return mGLThread.getRenderMode(); - } - - /** - * Request that the renderer render a frame. - * This method is typically used when the render mode has been set to - * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. - * May be called - * from any thread. Must not be called before a renderer has been set. - */ - public void requestRender() { - mGLThread.requestRender(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceCreated(SurfaceHolder holder) { - mGLThread.surfaceCreated(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceDestroyed(SurfaceHolder holder) { - // Surface will be destroyed when we return - mGLThread.surfaceDestroyed(); - } - - /** - * This method is part of the SurfaceHolder.Callback interface, and is - * not normally called or subclassed by clients of GLSurfaceView. - */ - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - mGLThread.onWindowResize(w, h); - } - - /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. - * Must not be called before a renderer has been set. - */ - public void onPause() { - mGLThread.onPause(); - } - - /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. - * Must not be called before a renderer has been set. - */ - public void onResume() { - mGLThread.onResume(); - } - - /** - * Queue a runnable to be run on the GL rendering thread. This can be used - * to communicate with the Renderer on the rendering thread. - * Must not be called before a renderer has been set. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - mGLThread.queueEvent(r); - } - - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLSurfaceView. - * Must not be called before a renderer has been set. - */ - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mGLThread.requestExitAndWait(); - } - - // ---------------------------------------------------------------------- - - /** - * An interface used to wrap a GL interface. - *

Typically - * used for implementing debugging and tracing on top of the default - * GL interface. You would typically use this by creating your own class - * that implemented all the GL methods by delegating to another GL instance. - * Then you could add your own behavior before or after calling the - * delegate. All the GLWrapper would do was instantiate and return the - * wrapper GL instance: - *

-     * class MyGLWrapper implements GLWrapper {
-     *     GL wrap(GL gl) {
-     *         return new MyGLImplementation(gl);
-     *     }
-     *     static class MyGLImplementation implements GL,GL10,GL11,... {
-     *         ...
-     *     }
-     * }
-     * 
- * @see #setGLWrapper(GLWrapper) - */ - public interface GLWrapper { - /** - * Wraps a gl interface in another gl interface. - * @param gl a GL interface that is to be wrapped. - * @return either the input argument or another GL object that wraps the input argument. - */ - GL wrap(GL gl); - } - - /** - * A generic renderer interface. - *

- * The renderer is responsible for making OpenGL calls to render a frame. - *

- * GLSurfaceView clients typically create their own classes that implement - * this interface, and then call {@link GLSurfaceView#setRenderer} to - * register the renderer with the GLSurfaceView. - *

- *

Threading

- * The renderer will be called on a separate thread, so that rendering - * performance is decoupled from the UI thread. Clients typically need to - * communicate with the renderer from the UI thread, because that's where - * input events are received. Clients can communicate using any of the - * standard Java techniques for cross-thread communication, or they can - * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. - *

- *

EGL Context Lost

- * There are situations where the EGL rendering context will be lost. This - * typically happens when device wakes up after going to sleep. When - * the EGL context is lost, all OpenGL resources (such as textures) that are - * associated with that context will be automatically deleted. In order to - * keep rendering correctly, a renderer must recreate any lost resources - * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method - * is a convenient place to do this. - * - * - * @see #setRenderer(Renderer) - */ - public static interface SwapBuffersCallback { - public boolean SwapBuffers(); - } - - public static abstract class Renderer { - /** - * Called when the surface is created or recreated. - *

- * Called when the rendering thread - * starts and whenever the EGL context is lost. The context will typically - * be lost when the Android device awakes after going to sleep. - *

- * Since this method is called at the beginning of rendering, as well as - * every time the EGL context is lost, this method is a convenient place to put - * code to create resources that need to be created when the rendering - * starts, and that need to be recreated when the EGL context is lost. - * Textures are an example of a resource that you might want to create - * here. - *

- * Note that when the EGL context is lost, all OpenGL resources associated - * with that context will be automatically deleted. You do not need to call - * the corresponding "glDelete" methods such as glDeleteTextures to - * manually delete these lost resources. - *

- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param config the EGLConfig of the created surface. Can be used - * to create matching pbuffers. - */ - public abstract void onSurfaceCreated(GL10 gl, EGLConfig config); - - public abstract void onSurfaceDestroyed(); - - /** - * Called when the surface changed size. - *

- * Called after the surface is created and whenever - * the OpenGL ES surface size changes. - *

- * Typically you will set your viewport here. If your camera - * is fixed then you could also set your projection matrix here: - *

-         * void onSurfaceChanged(GL10 gl, int width, int height) {
-         *     gl.glViewport(0, 0, width, height);
-         *     // for a fixed camera, set the projection too
-         *     float ratio = (float) width / height;
-         *     gl.glMatrixMode(GL10.GL_PROJECTION);
-         *     gl.glLoadIdentity();
-         *     gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - * @param width - * @param height - */ - public abstract void onSurfaceChanged(GL10 gl, int width, int height); - - /** - * Called to draw the current frame. - *

- * This method is responsible for drawing the current frame. - *

- * The implementation of this method typically looks like this: - *

-         * void onDrawFrame(GL10 gl) {
-         *     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-         *     //... other gl calls to render the scene ...
-         * }
-         * 
- * @param gl the GL interface. Use instanceof to - * test if the interface supports GL11 or higher interfaces. - */ - public abstract void onDrawFrame(GL10 gl); - - public boolean SwapBuffers() { - if( mSwapBuffersCallback != null ) - return mSwapBuffersCallback.SwapBuffers(); - return false; - } - - public void setSwapBuffersCallback( SwapBuffersCallback c ) { - mSwapBuffersCallback = c; - } - - private SwapBuffersCallback mSwapBuffersCallback = null; - } - - /** - * An interface for choosing an EGLConfig configuration from a list of - * potential configurations. - *

- * This interface must be implemented by clients wishing to call - * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} - */ - public interface EGLConfigChooser { - /** - * Choose a configuration from the list. Implementors typically - * implement this method by calling - * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the - * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. - * @param egl the EGL10 for the current display. - * @param display the current display. - * @return the chosen configuration. - */ - EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); - public boolean isGles2Required(); - } - - private static abstract class BaseConfigChooser - implements EGLConfigChooser { - public BaseConfigChooser(int[] configSpec) { - mConfigSpec = configSpec; - } - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] num_config = new int[1]; - egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); - - int numConfigs = num_config[0]; - - if (numConfigs <= 0) { - throw new IllegalArgumentException( - "No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, - num_config); - EGLConfig config = chooseConfig(egl, display, configs); - if (config == null) { - throw new IllegalArgumentException("No config chosen"); - } - return config; - } - - abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs); - - protected int[] mConfigSpec; - } - - private static class ComponentSizeChooser extends BaseConfigChooser { - public ComponentSizeChooser(int redSize, int greenSize, int blueSize, - int alphaSize, int depthSize, int stencilSize, boolean isGles2) { - super(new int[] {EGL10.EGL_NONE}); // Get all possible configs - mValue = new int[1]; - mRedSize = redSize; - mGreenSize = greenSize; - mBlueSize = blueSize; - mAlphaSize = alphaSize; - mDepthSize = depthSize; - mStencilSize = stencilSize; - mIsGles2 = isGles2; - } - - @Override - public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, - EGLConfig[] configs) { - EGLConfig closestConfig = null; - int closestDistance = 1000; - String cfglog = ""; - int idx = 0; - int selectidx = -1; - - Log.v("SDL", "Desired GL config: " + "R" + mRedSize + "G" + mGreenSize + "B" + mBlueSize + "A" + mAlphaSize + " depth " + mDepthSize + " stencil " + mStencilSize + " type " + (mIsGles2 ? "GLES2" : "GLES")); - for(EGLConfig config : configs) { - if ( config == null ) - continue; - int r = findConfigAttrib(egl, display, config, - EGL10.EGL_RED_SIZE, 0); - int g = findConfigAttrib(egl, display, config, - EGL10.EGL_GREEN_SIZE, 0); - int b = findConfigAttrib(egl, display, config, - EGL10.EGL_BLUE_SIZE, 0); - int a = findConfigAttrib(egl, display, config, - EGL10.EGL_ALPHA_SIZE, 0); - int d = findConfigAttrib(egl, display, config, - EGL10.EGL_DEPTH_SIZE, 0); - int s = findConfigAttrib(egl, display, config, - EGL10.EGL_STENCIL_SIZE, 0); - int rendertype = findConfigAttrib(egl, display, config, - EGL10.EGL_RENDERABLE_TYPE, 0); - int desiredtype = mIsGles2 ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT; - int nativeRender = findConfigAttrib(egl, display, config, - EGL10.EGL_NATIVE_RENDERABLE, 0); - int caveat = findConfigAttrib(egl, display, config, - EGL10.EGL_CONFIG_CAVEAT, EGL10.EGL_NONE); - int distance = Math.abs(r - mRedSize) + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize); - int dist1 = distance; - if( mAlphaSize - a > 0 ) - distance += mAlphaSize - a; - else if( mAlphaSize - a < 0 ) - distance += 1; // Small penalty if we don't need alpha channel but it is present - int dist2 = distance; - if( (d > 0) != (mDepthSize > 0) ) - distance += (mDepthSize > 0) ? 5 : 1; // Small penalty if we don't need zbuffer but it is present - int dist3 = distance; - if( (s > 0) != (mStencilSize > 0) ) - distance += (mStencilSize > 0) ? 5 : 1; // Small penalty if we don't need stencil buffer but it is present - int dist4 = distance; - if( (rendertype & desiredtype) == 0 ) - distance += 5; - int dist5 = distance; - if( caveat == EGL10.EGL_SLOW_CONFIG ) - distance += 4; - if( caveat == EGL10.EGL_NON_CONFORMANT_CONFIG ) // dunno what that means, probably R and B channels swapped - distance += 1; - - String cfgcur = "R" + r + "G" + g + "B" + b + "A" + a + " depth " + d + " stencil " + s + - " type " + rendertype + " ("; - if((rendertype & EGL_OPENGL_ES_BIT) != 0) - cfgcur += "GLES"; - if((rendertype & EGL_OPENGL_ES2_BIT) != 0) - cfgcur += " GLES2"; - if((rendertype & EGL_OPENGL_BIT) != 0) - cfgcur += " OPENGL"; - if((rendertype & EGL_OPENVG_BIT) != 0) - cfgcur += " OPENVG"; - cfgcur += ")"; - cfgcur += " caveat " + (caveat == EGL10.EGL_NONE ? "none" : - (caveat == EGL10.EGL_SLOW_CONFIG ? "SLOW" : - caveat == EGL10.EGL_NON_CONFORMANT_CONFIG ? "non-conformant" : - String.valueOf(caveat))); - cfgcur += " nr " + nativeRender; - cfgcur += " pos " + distance + " (" + dist1 + "," + dist2 + "," + dist3 + "," + dist4 + "," + dist5 + ")"; - Log.v("SDL", "GL config " + idx + ": " + cfgcur); - if (distance < closestDistance) { - closestDistance = distance; - closestConfig = config; - cfglog = new String(cfgcur); - selectidx = idx; - } - idx += 1; - } - Log.v("SDL", "GLSurfaceView_SDL::EGLConfigChooser::chooseConfig(): selected " + selectidx + ": " + cfglog ); - return closestConfig; - } - - private int findConfigAttrib(EGL10 egl, EGLDisplay display, - EGLConfig config, int attribute, int defaultValue) { - mValue[0] = -1; - if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { - return mValue[0]; - } - Log.w("SDL", "GLSurfaceView_SDL::EGLConfigChooser::findConfigAttrib(): attribute doesn't exist: " + attribute); - return defaultValue; - } - - public boolean isGles2Required() - { - return mIsGles2; - } - - private int[] mValue; - // Subclasses can adjust these values: - protected int mRedSize; - protected int mGreenSize; - protected int mBlueSize; - protected int mAlphaSize; - protected int mDepthSize; - protected int mStencilSize; - protected boolean mIsGles2 = false; - - public static final int EGL_OPENGL_ES_BIT = 1; - public static final int EGL_OPENVG_BIT = 2; - public static final int EGL_OPENGL_ES2_BIT = 4; - public static final int EGL_OPENGL_BIT = 8; - } - - /** - * This class will choose a supported surface as close to - * RGB565 as possible, with or without a depth buffer. - * - */ - private static class SimpleEGLConfigChooser16 extends ComponentSizeChooser { - public SimpleEGLConfigChooser16(boolean withDepthBuffer, boolean stencil, boolean gles2) { - super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); - // Adjust target values. This way we'll accept a 4444 or - // 555 buffer if there's no 565 buffer available. - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - } - } - - private static class SimpleEGLConfigChooser24 extends ComponentSizeChooser { - public SimpleEGLConfigChooser24(boolean withDepthBuffer, boolean stencil, boolean gles2) { - super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - } - } - - private static class SimpleEGLConfigChooser32 extends ComponentSizeChooser { - public SimpleEGLConfigChooser32(boolean withDepthBuffer, boolean stencil, boolean gles2) { - super(8, 8, 8, 8, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - mAlphaSize = 8; - } - } - private static ComponentSizeChooser getEglConfigChooser(int videoDepthBpp, boolean withDepthBuffer, boolean stencil, boolean gles2) { - if(videoDepthBpp == 16) - return new SimpleEGLConfigChooser16(withDepthBuffer, stencil, gles2); - if(videoDepthBpp == 24) - return new SimpleEGLConfigChooser24(withDepthBuffer, stencil, gles2); - if(videoDepthBpp == 32) - return new SimpleEGLConfigChooser32(withDepthBuffer, stencil, gles2); - return null; - }; - - /** - * An EGL helper class. - */ - - private class EglHelper { - public EglHelper() { - - } - - /** - * Initialize EGL for a given configuration spec. - * @param configSpec - */ - public void start(){ - - Log.v("SDL", "GLSurfaceView_SDL::EglHelper::start(): creating GL context"); - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - mEgl.eglInitialize(mEglDisplay, version); - mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); - if( mEglConfig == null ) - Log.e("SDL", "GLSurfaceView_SDL::EglHelper::start(): mEglConfig is NULL"); - - /* - * Create an OpenGL ES context. This must be done only once, an - * OpenGL context is a somewhat heavy object. - */ - final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - final int[] gles2_attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - - mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, - EGL10.EGL_NO_CONTEXT, mEGLConfigChooser.isGles2Required() ? gles2_attrib_list : null ); - - if( mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT ) - Log.e("SDL", "GLSurfaceView_SDL::EglHelper::start(): mEglContext is EGL_NO_CONTEXT, error: " + mEgl.eglGetError()); - - mEglSurface = null; - } - - /* - * React to the creation of a new surface by creating and returning an - * OpenGL interface that renders to that surface. - */ - public GL createSurface(SurfaceHolder holder) { - Log.v("SDL", "GLSurfaceView_SDL::EglHelper::createSurface(): creating GL context"); - /* - * The window size has changed, so we need to create a new - * surface. - */ - if (mEglSurface != null) { - - /* - * Unbind and destroy the old EGL surface, if - * there is one. - */ - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - } - - /* - * Create an EGL surface we can render into. - */ - /* - // This does not have any effect on Galaxy Note - int [] attribList = new int[4]; - attribList[0] = mEgl.EGL_RENDER_BUFFER; - attribList[1] = mEgl.EGL_SINGLE_BUFFER; - attribList[2] = mEgl.EGL_NONE; - attribList[3] = mEgl.EGL_NONE; - */ - mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, - mEglConfig, holder, null); - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, - mEglContext); - - - GL gl = mEglContext.getGL(); - if (mGLWrapper != null) { - gl = mGLWrapper.wrap(gl); - } - - return gl; - } - - /** - * Display the current render surface. - * @return false if the context has been lost. - */ - public boolean swap() { - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - - /* - * Always check for EGL_CONTEXT_LOST, which means the context - * and all associated data were lost (For instance because - * the device went to sleep). We need to sleep until we - * get a new surface. - */ - return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; - } - - public void finish() { - Log.v("SDL", "GLSurfaceView_SDL::EglHelper::finish(): destroying GL context"); - if (mEglSurface != null) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEglSurface = null; - } - if (mEglContext != null) { - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - } - - /** - * A generic GL Thread. Takes care of initializing EGL and GL. Delegates - * to a Renderer instance to do the actual drawing. Can be configured to - * render continuously or on request. - * - */ - class GLThread extends Thread implements SwapBuffersCallback { - GLThread(Renderer renderer) { - super(); - mDone = false; - mWidth = 0; - mHeight = 0; - mRequestRender = true; - mRenderMode = RENDERMODE_CONTINUOUSLY; - mRenderer = renderer; - mRenderer.setSwapBuffersCallback(this); - setName("GLThread"); - } - - @Override - public void run() { - /* - * When the android framework launches a second instance of - * an activity, the new instance's onCreate() method may be - * called before the first instance returns from onDestroy(). - * - * This semaphore ensures that only one instance at a time - * accesses EGL. - */ - try { - sEglSemaphore.acquire(); - } catch (InterruptedException e) { - return; - } - - mEglHelper = new EglHelper(); - // mEglHelper.start(); - mNeedStart = true; - mSizeChanged = true; - SwapBuffers(); - - mRenderer.onDrawFrame(mGL); - - mEglHelper.finish(); - - /* - synchronized (sGLThreadManager) { - stopEglLocked(); - } - sGLThreadManager.threadExiting(this); - */ - - sEglSemaphore.release(); - } - - public boolean SwapBuffers() { - - boolean tellRendererSurfaceCreated = false; - boolean tellRendererSurfaceChanged = false; - - /* - * This is our main activity thread's loop, we go until - * asked to quit. - */ - - /* - * Update the asynchronous state (window size) - */ - while(true) { // Loop until we're re-created GL context and successfully called swap() - - int w, h; - boolean changed = false; - synchronized (this) { - /* - Runnable r; - while ((r = getEvent()) != null) { - r.run(); - } - */ - if (mPaused) { - mRenderer.onSurfaceDestroyed(); - mEglHelper.finish(); - mNeedStart = true; - if( Globals.NonBlockingSwapBuffers ) - return false; - } - } - while (needToWait()) { - //Log.v("SDL", "GLSurfaceView_SDL::run(): paused"); - synchronized(this) { - try - { - wait(500); - } - catch(InterruptedException e) - { - Log.v("SDL", "GLSurfaceView_SDL::GLThread::SwapBuffers(): Who dared to interrupt my slumber?"); - Thread.interrupted(); // Clear the flag - } - } - } - synchronized (this) { - if (mDone) - return false; - // changed = mSizeChanged; - w = mWidth; - h = mHeight; - mSizeChanged = false; - mRequestRender = false; - } - if (mNeedStart) { - mEglHelper.start(); - tellRendererSurfaceCreated = true; - changed = true; - mNeedStart = false; - } - if (changed) { - mGL = (GL10) mEglHelper.createSurface(getHolder()); - tellRendererSurfaceChanged = true; - } - if (tellRendererSurfaceCreated) { - mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); - tellRendererSurfaceCreated = false; - } - if (tellRendererSurfaceChanged) { - mRenderer.onSurfaceChanged(mGL, w, h); - tellRendererSurfaceChanged = false; - } - /* - * Once we're done with GL, we need to call swapBuffers() - * to instruct the system to display the rendered frame - */ - if( mEglHelper.swap() ) - return true; - // We've lost GL context - recreate it - mRenderer.onSurfaceDestroyed(); - mEglHelper.finish(); - mNeedStart = true; - if( Globals.NonBlockingSwapBuffers ) - return false; - } - } - - private boolean needToWait() { - if (mKeyguardManager.inKeyguardRestrictedInputMode()) { - return true; // We're in lockscreen - sleep until user unlocks the device - } - - synchronized (this) { - if (mDone) { - return false; - } - - if ( Globals.HorizontalOrientation != (mWidth > mHeight) ) - return true; // Wait until screen orientation changes - - if (mPaused || (! mHasSurface)) { - return true; - } - - if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { - return false; - } - } - - return true; - } - - public void setRenderMode(int renderMode) { - if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { - throw new IllegalArgumentException("renderMode"); - } - synchronized(this) { - mRenderMode = renderMode; - if (renderMode == RENDERMODE_CONTINUOUSLY) { - notify(); - } - } - } - - public int getRenderMode() { - synchronized(this) { - return mRenderMode; - } - } - - public void requestRender() { - synchronized(this) { - mRequestRender = true; - notify(); - } - } - - public void surfaceCreated() { - synchronized(this) { - mHasSurface = true; - notify(); - } - } - - public void surfaceDestroyed() { - synchronized(this) { - mHasSurface = false; - notify(); - } - } - - public void onPause() { - Log.v("SDL", "GLSurfaceView_SDL::onPause()"); - synchronized (this) { - mPaused = true; - } - } - - public void onResume() { - Log.v("SDL", "GLSurfaceView_SDL::onResume()"); - synchronized (this) { - mPaused = false; - notify(); - } - } - - public void onWindowResize(int w, int h) { - Log.v("SDL", "GLSurfaceView_SDL::onWindowResize(): " + w + "x" + h); - synchronized (this) { - mWidth = w; - mHeight = h; - mSizeChanged = true; - notify(); - } - } - - public void requestExitAndWait() { - // don't call this from GLThread thread or it is a guaranteed - // deadlock! - Log.v("SDL", "GLSurfaceView_SDL::requestExitAndWait()"); - synchronized(this) { - mDone = true; - notify(); - } - try { - join(); - } catch (InterruptedException ex) { - //Thread.currentThread().interrupt(); - } - } - - /** - * Queue an "event" to be run on the GL rendering thread. - * @param r the runnable to be run on the GL rendering thread. - */ - public void queueEvent(Runnable r) { - synchronized(this) { - mEventQueue.add(r); - } - } - - private Runnable getEvent() { - synchronized(this) { - if (mEventQueue.size() > 0) { - return mEventQueue.remove(0); - } - - } - return null; - } - - private boolean mDone; - private boolean mPaused; - private boolean mHasSurface; - private int mWidth; - private int mHeight; - private int mRenderMode; - private boolean mRequestRender; - private Renderer mRenderer; - private ArrayList mEventQueue = new ArrayList(); - private EglHelper mEglHelper; - private GL10 mGL = null; - private boolean mNeedStart = false; - } - - static class LogWriter extends Writer { - - @Override public void close() { - flushBuilder(); - } - - @Override public void flush() { - flushBuilder(); - } - - @Override public void write(char[] buf, int offset, int count) { - for(int i = 0; i < count; i++) { - char c = buf[offset + i]; - if ( c == '\n') { - flushBuilder(); - } - else { - mBuilder.append(c); - } - } - } - - private void flushBuilder() { - if (mBuilder.length() > 0) { - Log.v("GLSurfaceView", mBuilder.toString()); - mBuilder.delete(0, mBuilder.length()); - } - } - - private StringBuilder mBuilder = new StringBuilder(); - } - - private static final Semaphore sEglSemaphore = new Semaphore(1); - private boolean mSizeChanged = true; - - private GLThread mGLThread; - private EGLConfigChooser mEGLConfigChooser; - private GLWrapper mGLWrapper; - private int mDebugFlags; - private KeyguardManager mKeyguardManager; + /** + * The renderer only renders + * when the surface is created, or when {@link #requestRender} is called. + * + * @see #getRenderMode() + * @see #setRenderMode(int) + */ + public final static int RENDERMODE_WHEN_DIRTY = 0; + /** + * The renderer is called + * continuously to re-render the scene. + * + * @see #getRenderMode() + * @see #setRenderMode(int) + * @see #requestRender() + */ + public final static int RENDERMODE_CONTINUOUSLY = 1; + + /** + * Check glError() after every GL call and throw an exception if glError indicates + * that an error has occurred. This can be used to help track down which OpenGL ES call + * is causing an error. + * + * @see #getDebugFlags + * @see #setDebugFlags + */ + public final static int DEBUG_CHECK_GL_ERROR = 1; + + /** + * Log GL calls to the system log at "verbose" level with tag "GLSurfaceView". + * + * @see #getDebugFlags + * @see #setDebugFlags + */ + public final static int DEBUG_LOG_GL_CALLS = 2; + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public GLSurfaceView_SDL(Context context) { + super(context); + init(); + } + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public GLSurfaceView_SDL(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + // Install a SurfaceHolder.Callback so we get notified when the + // underlying surface is created and destroyed + SurfaceHolder holder = getHolder(); + holder.addCallback(this); + holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + mKeyguardManager = ((KeyguardManager)getContext().getSystemService(Context.KEYGUARD_SERVICE)); + } + + /** + * Set the glWrapper. If the glWrapper is not null, its + * {@link GLWrapper#wrap(GL)} method is called + * whenever a surface is created. A GLWrapper can be used to wrap + * the GL object that's passed to the renderer. Wrapping a GL + * object enables examining and modifying the behavior of the + * GL calls made by the renderer. + *

+ * Wrapping is typically used for debugging purposes. + *

+ * The default value is null. + * @param glWrapper the new GLWrapper + */ + public void setGLWrapper(GLWrapper glWrapper) { + mGLWrapper = glWrapper; + } + + /** + * Set the debug flags to a new value. The value is + * constructed by OR-together zero or more + * of the DEBUG_CHECK_* constants. The debug flags take effect + * whenever a surface is created. The default value is zero. + * @param debugFlags the new debug flags + * @see #DEBUG_CHECK_GL_ERROR + * @see #DEBUG_LOG_GL_CALLS + */ + public void setDebugFlags(int debugFlags) { + mDebugFlags = debugFlags; + } + + /** + * Get the current value of the debug flags. + * @return the current value of the debug flags. + */ + public int getDebugFlags() { + return mDebugFlags; + } + + /** + * Set the renderer associated with this view. Also starts the thread that + * will call the renderer, which in turn causes the rendering to start. + *

This method should be called once and only once in the life-cycle of + * a GLSurfaceView. + *

The following GLSurfaceView methods can only be called before + * setRenderer is called: + *

    + *
  • {@link #setEGLConfigChooser(boolean)} + *
  • {@link #setEGLConfigChooser(EGLConfigChooser)} + *
  • {@link #setEGLConfigChooser(int, int, int, int, int, int)} + *
+ *

+ * The following GLSurfaceView methods can only be called after + * setRenderer is called: + *

    + *
  • {@link #getRenderMode()} + *
  • {@link #onPause()} + *
  • {@link #onResume()} + *
  • {@link #queueEvent(Runnable)} + *
  • {@link #requestRender()} + *
  • {@link #setRenderMode(int)} + *
+ * + * @param renderer the renderer to use to perform OpenGL drawing. + */ + public void setRenderer(Renderer renderer) { + if (mGLThread != null) { + throw new IllegalStateException( + "setRenderer has already been called for this instance."); + } + if (mEGLConfigChooser == null) { + mEGLConfigChooser = getEglConfigChooser(16, false, false, false); + } + mGLThread = new GLThread(renderer); + mGLThread.start(); + } + + /** + * Install a custom EGLConfigChooser. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose a config as close to 16-bit RGB as possible, with + * a depth buffer as close to 16 bits as possible. + * @param configChooser + */ + public void setEGLConfigChooser(EGLConfigChooser configChooser) { + if (mGLThread != null) { + throw new IllegalStateException( + "setRenderer has already been called for this instance."); + } + mEGLConfigChooser = configChooser; + } + + /** + * Install a config chooser which will choose a config + * as close to 16-bit RGB as possible, with or without an optional depth + * buffer as close to 16-bits as possible. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose a config as close to 16-bit RGB as possible, with + * a depth buffer as close to 16 bits as possible. + * + * @param needDepth + */ + public void setEGLConfigChooser(int bpp, boolean needDepth, boolean stencil, boolean gles2) { + setEGLConfigChooser(getEglConfigChooser(bpp, needDepth, stencil, gles2)); + } + + /** + * Install a config chooser which will choose a config + * with at least the specified component sizes, and as close + * to the specified component sizes as possible. + *

If this method is + * called, it must be called before {@link #setRenderer(Renderer)} + * is called. + *

+ * If no setEGLConfigChooser method is called, then by default the + * view will choose a config as close to 16-bit RGB as possible, with + * a depth buffer as close to 16 bits as possible. + * + */ + public void setEGLConfigChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize, boolean gles2) { + setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, + blueSize, alphaSize, depthSize, stencilSize, gles2)); + } + /** + * Set the rendering mode. When renderMode is + * RENDERMODE_CONTINUOUSLY, the renderer is called + * repeatedly to re-render the scene. When renderMode + * is RENDERMODE_WHEN_DIRTY, the renderer only rendered when the surface + * is created, or when {@link #requestRender} is called. Defaults to RENDERMODE_CONTINUOUSLY. + *

+ * Using RENDERMODE_WHEN_DIRTY can improve battery life and overall system performance + * by allowing the GPU and CPU to idle when the view does not need to be updated. + *

+ * This method can only be called after {@link #setRenderer(Renderer)} + * + * @param renderMode one of the RENDERMODE_X constants + * @see #RENDERMODE_CONTINUOUSLY + * @see #RENDERMODE_WHEN_DIRTY + */ + public void setRenderMode(int renderMode) { + mGLThread.setRenderMode(renderMode); + } + + /** + * Get the current rendering mode. May be called + * from any thread. Must not be called before a renderer has been set. + * @return the current rendering mode. + * @see #RENDERMODE_CONTINUOUSLY + * @see #RENDERMODE_WHEN_DIRTY + */ + public int getRenderMode() { + return mGLThread.getRenderMode(); + } + + /** + * Request that the renderer render a frame. + * This method is typically used when the render mode has been set to + * {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand. + * May be called + * from any thread. Must not be called before a renderer has been set. + */ + public void requestRender() { + mGLThread.requestRender(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLSurfaceView. + */ + public void surfaceCreated(SurfaceHolder holder) { + mGLThread.surfaceCreated(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLSurfaceView. + */ + public void surfaceDestroyed(SurfaceHolder holder) { + // Surface will be destroyed when we return + mGLThread.surfaceDestroyed(); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of GLSurfaceView. + */ + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + mGLThread.onWindowResize(w, h); + } + + /** + * Inform the view that the activity is paused. The owner of this view must + * call this method when the activity is paused. Calling this method will + * pause the rendering thread. + * Must not be called before a renderer has been set. + */ + public void onPause() { + mGLThread.onPause(); + } + + /** + * Inform the view that the activity is resumed. The owner of this view must + * call this method when the activity is resumed. Calling this method will + * recreate the OpenGL display and resume the rendering + * thread. + * Must not be called before a renderer has been set. + */ + public void onResume() { + mGLThread.onResume(); + } + + /** + * Queue a runnable to be run on the GL rendering thread. This can be used + * to communicate with the Renderer on the rendering thread. + * Must not be called before a renderer has been set. + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + mGLThread.queueEvent(r); + } + + /** + * This method is used as part of the View class and is not normally + * called or subclassed by clients of GLSurfaceView. + * Must not be called before a renderer has been set. + */ + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mGLThread.requestExitAndWait(); + } + + // ---------------------------------------------------------------------- + + /** + * An interface used to wrap a GL interface. + *

Typically + * used for implementing debugging and tracing on top of the default + * GL interface. You would typically use this by creating your own class + * that implemented all the GL methods by delegating to another GL instance. + * Then you could add your own behavior before or after calling the + * delegate. All the GLWrapper would do was instantiate and return the + * wrapper GL instance: + *

+	 * class MyGLWrapper implements GLWrapper {
+	 *	   GL wrap(GL gl) {
+	 *		   return new MyGLImplementation(gl);
+	 *	   }
+	 *	   static class MyGLImplementation implements GL,GL10,GL11,... {
+	 *		   ...
+	 *	   }
+	 * }
+	 * 
+ * @see #setGLWrapper(GLWrapper) + */ + public interface GLWrapper { + /** + * Wraps a gl interface in another gl interface. + * @param gl a GL interface that is to be wrapped. + * @return either the input argument or another GL object that wraps the input argument. + */ + GL wrap(GL gl); + } + + /** + * A generic renderer interface. + *

+ * The renderer is responsible for making OpenGL calls to render a frame. + *

+ * GLSurfaceView clients typically create their own classes that implement + * this interface, and then call {@link GLSurfaceView#setRenderer} to + * register the renderer with the GLSurfaceView. + *

+ *

Threading

+ * The renderer will be called on a separate thread, so that rendering + * performance is decoupled from the UI thread. Clients typically need to + * communicate with the renderer from the UI thread, because that's where + * input events are received. Clients can communicate using any of the + * standard Java techniques for cross-thread communication, or they can + * use the {@link GLSurfaceView#queueEvent(Runnable)} convenience method. + *

+ *

EGL Context Lost

+ * There are situations where the EGL rendering context will be lost. This + * typically happens when device wakes up after going to sleep. When + * the EGL context is lost, all OpenGL resources (such as textures) that are + * associated with that context will be automatically deleted. In order to + * keep rendering correctly, a renderer must recreate any lost resources + * that it still needs. The {@link #onSurfaceCreated(GL10, EGLConfig)} method + * is a convenient place to do this. + * + * + * @see #setRenderer(Renderer) + */ + public static interface SwapBuffersCallback { + public boolean SwapBuffers(); + } + + public static abstract class Renderer { + /** + * Called when the surface is created or recreated. + *

+ * Called when the rendering thread + * starts and whenever the EGL context is lost. The context will typically + * be lost when the Android device awakes after going to sleep. + *

+ * Since this method is called at the beginning of rendering, as well as + * every time the EGL context is lost, this method is a convenient place to put + * code to create resources that need to be created when the rendering + * starts, and that need to be recreated when the EGL context is lost. + * Textures are an example of a resource that you might want to create + * here. + *

+ * Note that when the EGL context is lost, all OpenGL resources associated + * with that context will be automatically deleted. You do not need to call + * the corresponding "glDelete" methods such as glDeleteTextures to + * manually delete these lost resources. + *

+ * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + * @param config the EGLConfig of the created surface. Can be used + * to create matching pbuffers. + */ + public abstract void onSurfaceCreated(GL10 gl, EGLConfig config); + + public abstract void onSurfaceDestroyed(); + + /** + * Called when the surface changed size. + *

+ * Called after the surface is created and whenever + * the OpenGL ES surface size changes. + *

+ * Typically you will set your viewport here. If your camera + * is fixed then you could also set your projection matrix here: + *

+		 * void onSurfaceChanged(GL10 gl, int width, int height) {
+		 *	   gl.glViewport(0, 0, width, height);
+		 *	   // for a fixed camera, set the projection too
+		 *	   float ratio = (float) width / height;
+		 *	   gl.glMatrixMode(GL10.GL_PROJECTION);
+		 *	   gl.glLoadIdentity();
+		 *	   gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+		 * }
+		 * 
+ * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + * @param width + * @param height + */ + public abstract void onSurfaceChanged(GL10 gl, int width, int height); + + /** + * Called to draw the current frame. + *

+ * This method is responsible for drawing the current frame. + *

+ * The implementation of this method typically looks like this: + *

+		 * void onDrawFrame(GL10 gl) {
+		 *	   gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+		 *	   //... other gl calls to render the scene ...
+		 * }
+		 * 
+ * @param gl the GL interface. Use instanceof to + * test if the interface supports GL11 or higher interfaces. + */ + public abstract void onDrawFrame(GL10 gl); + + public boolean SwapBuffers() { + if( mSwapBuffersCallback != null ) + return mSwapBuffersCallback.SwapBuffers(); + return false; + } + + public void setSwapBuffersCallback( SwapBuffersCallback c ) { + mSwapBuffersCallback = c; + } + + private SwapBuffersCallback mSwapBuffersCallback = null; + } + + /** + * An interface for choosing an EGLConfig configuration from a list of + * potential configurations. + *

+ * This interface must be implemented by clients wishing to call + * {@link GLSurfaceView#setEGLConfigChooser(EGLConfigChooser)} + */ + public interface EGLConfigChooser { + /** + * Choose a configuration from the list. Implementors typically + * implement this method by calling + * {@link EGL10#eglChooseConfig} and iterating through the results. Please consult the + * EGL specification available from The Khronos Group to learn how to call eglChooseConfig. + * @param egl the EGL10 for the current display. + * @param display the current display. + * @return the chosen configuration. + */ + EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); + public boolean isGles2Required(); + } + + private static abstract class BaseConfigChooser + implements EGLConfigChooser { + public BaseConfigChooser(int[] configSpec) { + mConfigSpec = configSpec; + } + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int[] num_config = new int[1]; + egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException( + "No configs match configSpec"); + } + + EGLConfig[] configs = new EGLConfig[numConfigs]; + egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config); + EGLConfig config = chooseConfig(egl, display, configs); + if (config == null) { + throw new IllegalArgumentException("No config chosen"); + } + return config; + } + + abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs); + + protected int[] mConfigSpec; + } + + private static class ComponentSizeChooser extends BaseConfigChooser { + public ComponentSizeChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize, boolean isGles2) { + super(new int[] {EGL10.EGL_NONE}); // Get all possible configs + mValue = new int[1]; + mRedSize = redSize; + mGreenSize = greenSize; + mBlueSize = blueSize; + mAlphaSize = alphaSize; + mDepthSize = depthSize; + mStencilSize = stencilSize; + mIsGles2 = isGles2; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs) { + EGLConfig closestConfig = null; + int closestDistance = 1000; + String cfglog = ""; + int idx = 0; + int selectidx = -1; + + Log.v("SDL", "Desired GL config: " + "R" + mRedSize + "G" + mGreenSize + "B" + mBlueSize + "A" + mAlphaSize + " depth " + mDepthSize + " stencil " + mStencilSize + " type " + (mIsGles2 ? "GLES2" : "GLES")); + for(EGLConfig config : configs) { + if ( config == null ) + continue; + int r = findConfigAttrib(egl, display, config, + EGL10.EGL_RED_SIZE, 0); + int g = findConfigAttrib(egl, display, config, + EGL10.EGL_GREEN_SIZE, 0); + int b = findConfigAttrib(egl, display, config, + EGL10.EGL_BLUE_SIZE, 0); + int a = findConfigAttrib(egl, display, config, + EGL10.EGL_ALPHA_SIZE, 0); + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + int rendertype = findConfigAttrib(egl, display, config, + EGL10.EGL_RENDERABLE_TYPE, 0); + int desiredtype = mIsGles2 ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT; + int nativeRender = findConfigAttrib(egl, display, config, + EGL10.EGL_NATIVE_RENDERABLE, 0); + int caveat = findConfigAttrib(egl, display, config, + EGL10.EGL_CONFIG_CAVEAT, EGL10.EGL_NONE); + int distance = Math.abs(r - mRedSize) + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize); + int dist1 = distance; + if( mAlphaSize - a > 0 ) + distance += mAlphaSize - a; + else if( mAlphaSize - a < 0 ) + distance += 1; // Small penalty if we don't need alpha channel but it is present + int dist2 = distance; + if( (d > 0) != (mDepthSize > 0) ) + distance += (mDepthSize > 0) ? 5 : 1; // Small penalty if we don't need zbuffer but it is present + int dist3 = distance; + if( (s > 0) != (mStencilSize > 0) ) + distance += (mStencilSize > 0) ? 5 : 1; // Small penalty if we don't need stencil buffer but it is present + int dist4 = distance; + if( (rendertype & desiredtype) == 0 ) + distance += 5; + int dist5 = distance; + if( caveat == EGL10.EGL_SLOW_CONFIG ) + distance += 4; + if( caveat == EGL10.EGL_NON_CONFORMANT_CONFIG ) // dunno what that means, probably R and B channels swapped + distance += 1; + + String cfgcur = "R" + r + "G" + g + "B" + b + "A" + a + " depth " + d + " stencil " + s + + " type " + rendertype + " ("; + if((rendertype & EGL_OPENGL_ES_BIT) != 0) + cfgcur += "GLES"; + if((rendertype & EGL_OPENGL_ES2_BIT) != 0) + cfgcur += " GLES2"; + if((rendertype & EGL_OPENGL_BIT) != 0) + cfgcur += " OPENGL"; + if((rendertype & EGL_OPENVG_BIT) != 0) + cfgcur += " OPENVG"; + cfgcur += ")"; + cfgcur += " caveat " + (caveat == EGL10.EGL_NONE ? "none" : + (caveat == EGL10.EGL_SLOW_CONFIG ? "SLOW" : + caveat == EGL10.EGL_NON_CONFORMANT_CONFIG ? "non-conformant" : + String.valueOf(caveat))); + cfgcur += " nr " + nativeRender; + cfgcur += " pos " + distance + " (" + dist1 + "," + dist2 + "," + dist3 + "," + dist4 + "," + dist5 + ")"; + Log.v("SDL", "GL config " + idx + ": " + cfgcur); + if (distance < closestDistance) { + closestDistance = distance; + closestConfig = config; + cfglog = new String(cfgcur); + selectidx = idx; + } + idx += 1; + } + Log.v("SDL", "GLSurfaceView_SDL::EGLConfigChooser::chooseConfig(): selected " + selectidx + ": " + cfglog ); + return closestConfig; + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, + EGLConfig config, int attribute, int defaultValue) { + mValue[0] = -1; + if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { + return mValue[0]; + } + Log.w("SDL", "GLSurfaceView_SDL::EGLConfigChooser::findConfigAttrib(): attribute doesn't exist: " + attribute); + return defaultValue; + } + + public boolean isGles2Required() + { + return mIsGles2; + } + + private int[] mValue; + // Subclasses can adjust these values: + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + protected boolean mIsGles2 = false; + + public static final int EGL_OPENGL_ES_BIT = 1; + public static final int EGL_OPENVG_BIT = 2; + public static final int EGL_OPENGL_ES2_BIT = 4; + public static final int EGL_OPENGL_BIT = 8; + } + + /** + * This class will choose a supported surface as close to + * RGB565 as possible, with or without a depth buffer. + * + */ + private static class SimpleEGLConfigChooser16 extends ComponentSizeChooser { + public SimpleEGLConfigChooser16(boolean withDepthBuffer, boolean stencil, boolean gles2) { + super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); + // Adjust target values. This way we'll accept a 4444 or + // 555 buffer if there's no 565 buffer available. + mRedSize = 5; + mGreenSize = 6; + mBlueSize = 5; + } + } + + private static class SimpleEGLConfigChooser24 extends ComponentSizeChooser { + public SimpleEGLConfigChooser24(boolean withDepthBuffer, boolean stencil, boolean gles2) { + super(8, 8, 8, 0, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + } + } + + private static class SimpleEGLConfigChooser32 extends ComponentSizeChooser { + public SimpleEGLConfigChooser32(boolean withDepthBuffer, boolean stencil, boolean gles2) { + super(8, 8, 8, 8, withDepthBuffer ? 16 : 0, stencil ? 8 : 0, gles2); + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + mAlphaSize = 8; + } + } + private static ComponentSizeChooser getEglConfigChooser(int videoDepthBpp, boolean withDepthBuffer, boolean stencil, boolean gles2) { + if(videoDepthBpp == 16) + return new SimpleEGLConfigChooser16(withDepthBuffer, stencil, gles2); + if(videoDepthBpp == 24) + return new SimpleEGLConfigChooser24(withDepthBuffer, stencil, gles2); + if(videoDepthBpp == 32) + return new SimpleEGLConfigChooser32(withDepthBuffer, stencil, gles2); + return null; + }; + + /** + * An EGL helper class. + */ + + private class EglHelper { + public EglHelper() { + + } + + /** + * Initialize EGL for a given configuration spec. + * @param configSpec + */ + public void start(){ + + Log.v("SDL", "GLSurfaceView_SDL::EglHelper::start(): creating GL context"); + /* + * Get an EGL instance + */ + mEgl = (EGL10) EGLContext.getEGL(); + + /* + * Get to the default display. + */ + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + + /* + * We can now initialize EGL for that display + */ + int[] version = new int[2]; + mEgl.eglInitialize(mEglDisplay, version); + mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); + if( mEglConfig == null ) + Log.e("SDL", "GLSurfaceView_SDL::EglHelper::start(): mEglConfig is NULL"); + + /* + * Create an OpenGL ES context. This must be done only once, an + * OpenGL context is a somewhat heavy object. + */ + final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + final int[] gles2_attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; + + mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, + EGL10.EGL_NO_CONTEXT, mEGLConfigChooser.isGles2Required() ? gles2_attrib_list : null ); + + if( mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT ) + Log.e("SDL", "GLSurfaceView_SDL::EglHelper::start(): mEglContext is EGL_NO_CONTEXT, error: " + mEgl.eglGetError()); + + mEglSurface = null; + } + + /* + * React to the creation of a new surface by creating and returning an + * OpenGL interface that renders to that surface. + */ + public GL createSurface(SurfaceHolder holder) { + Log.v("SDL", "GLSurfaceView_SDL::EglHelper::createSurface(): creating GL context"); + /* + * The window size has changed, so we need to create a new + * surface. + */ + if (mEglSurface != null) { + + /* + * Unbind and destroy the old EGL surface, if + * there is one. + */ + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + } + + /* + * Create an EGL surface we can render into. + */ + /* + // This does not have any effect on Galaxy Note + int [] attribList = new int[4]; + attribList[0] = mEgl.EGL_RENDER_BUFFER; + attribList[1] = mEgl.EGL_SINGLE_BUFFER; + attribList[2] = mEgl.EGL_NONE; + attribList[3] = mEgl.EGL_NONE; + */ + mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, + mEglConfig, holder, null); + + /* + * Before we can issue GL commands, we need to make sure + * the context is current and bound to a surface. + */ + mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, + mEglContext); + + + GL gl = mEglContext.getGL(); + if (mGLWrapper != null) { + gl = mGLWrapper.wrap(gl); + } + + return gl; + } + + /** + * Display the current render surface. + * @return false if the context has been lost. + */ + public boolean swap() { + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + + /* + * Always check for EGL_CONTEXT_LOST, which means the context + * and all associated data were lost (For instance because + * the device went to sleep). We need to sleep until we + * get a new surface. + */ + return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST; + } + + public void finish() { + Log.v("SDL", "GLSurfaceView_SDL::EglHelper::finish(): destroying GL context"); + if (mEglSurface != null) { + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_CONTEXT); + mEgl.eglDestroySurface(mEglDisplay, mEglSurface); + mEglSurface = null; + } + if (mEglContext != null) { + mEgl.eglDestroyContext(mEglDisplay, mEglContext); + mEglContext = null; + } + if (mEglDisplay != null) { + mEgl.eglTerminate(mEglDisplay); + mEglDisplay = null; + } + } + + EGL10 mEgl; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLConfig mEglConfig; + EGLContext mEglContext; + } + + /** + * A generic GL Thread. Takes care of initializing EGL and GL. Delegates + * to a Renderer instance to do the actual drawing. Can be configured to + * render continuously or on request. + * + */ + class GLThread extends Thread implements SwapBuffersCallback { + GLThread(Renderer renderer) { + super(); + mDone = false; + mWidth = 0; + mHeight = 0; + mRequestRender = true; + mRenderMode = RENDERMODE_CONTINUOUSLY; + mRenderer = renderer; + mRenderer.setSwapBuffersCallback(this); + setName("GLThread"); + } + + @Override + public void run() { + /* + * When the android framework launches a second instance of + * an activity, the new instance's onCreate() method may be + * called before the first instance returns from onDestroy(). + * + * This semaphore ensures that only one instance at a time + * accesses EGL. + */ + try { + sEglSemaphore.acquire(); + } catch (InterruptedException e) { + return; + } + + mEglHelper = new EglHelper(); + // mEglHelper.start(); + mNeedStart = true; + mSizeChanged = true; + SwapBuffers(); + + mRenderer.onDrawFrame(mGL); + + mEglHelper.finish(); + + /* + synchronized (sGLThreadManager) { + stopEglLocked(); + } + sGLThreadManager.threadExiting(this); + */ + + sEglSemaphore.release(); + } + + public boolean SwapBuffers() { + + boolean tellRendererSurfaceCreated = false; + boolean tellRendererSurfaceChanged = false; + + /* + * This is our main activity thread's loop, we go until + * asked to quit. + */ + + /* + * Update the asynchronous state (window size) + */ + while(true) { // Loop until we're re-created GL context and successfully called swap() + + int w, h; + boolean changed = false; + synchronized (this) { + /* + Runnable r; + while ((r = getEvent()) != null) { + r.run(); + } + */ + if (mPaused) { + mRenderer.onSurfaceDestroyed(); + mEglHelper.finish(); + mNeedStart = true; + if( Globals.NonBlockingSwapBuffers ) + return false; + } + } + while (needToWait()) { + //Log.v("SDL", "GLSurfaceView_SDL::run(): paused"); + synchronized(this) { + try + { + wait(500); + } + catch(InterruptedException e) + { + Log.v("SDL", "GLSurfaceView_SDL::GLThread::SwapBuffers(): Who dared to interrupt my slumber?"); + Thread.interrupted(); // Clear the flag + } + } + } + synchronized (this) { + if (mDone) + return false; + // changed = mSizeChanged; + w = mWidth; + h = mHeight; + mSizeChanged = false; + mRequestRender = false; + } + if (mNeedStart) { + mEglHelper.start(); + tellRendererSurfaceCreated = true; + changed = true; + mNeedStart = false; + } + if (changed) { + mGL = (GL10) mEglHelper.createSurface(getHolder()); + tellRendererSurfaceChanged = true; + } + if (tellRendererSurfaceCreated) { + mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); + tellRendererSurfaceCreated = false; + } + if (tellRendererSurfaceChanged) { + mRenderer.onSurfaceChanged(mGL, w, h); + tellRendererSurfaceChanged = false; + } + /* + * Once we're done with GL, we need to call swapBuffers() + * to instruct the system to display the rendered frame + */ + if( mEglHelper.swap() ) + return true; + // We've lost GL context - recreate it + mRenderer.onSurfaceDestroyed(); + mEglHelper.finish(); + mNeedStart = true; + if( Globals.NonBlockingSwapBuffers ) + return false; + } + } + + private boolean needToWait() { + if (mKeyguardManager.inKeyguardRestrictedInputMode()) { + return true; // We're in lockscreen - sleep until user unlocks the device + } + + synchronized (this) { + if (mDone) { + return false; + } + + if ( Globals.HorizontalOrientation != (mWidth > mHeight) ) + return true; // Wait until screen orientation changes + + if (mPaused || (! mHasSurface)) { + return true; + } + + if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) { + return false; + } + } + + return true; + } + + public void setRenderMode(int renderMode) { + if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) { + throw new IllegalArgumentException("renderMode"); + } + synchronized(this) { + mRenderMode = renderMode; + if (renderMode == RENDERMODE_CONTINUOUSLY) { + notify(); + } + } + } + + public int getRenderMode() { + synchronized(this) { + return mRenderMode; + } + } + + public void requestRender() { + synchronized(this) { + mRequestRender = true; + notify(); + } + } + + public void surfaceCreated() { + synchronized(this) { + mHasSurface = true; + notify(); + } + } + + public void surfaceDestroyed() { + synchronized(this) { + mHasSurface = false; + notify(); + } + } + + public void onPause() { + Log.v("SDL", "GLSurfaceView_SDL::onPause()"); + synchronized (this) { + mPaused = true; + } + } + + public void onResume() { + Log.v("SDL", "GLSurfaceView_SDL::onResume()"); + synchronized (this) { + mPaused = false; + notify(); + } + } + + public void onWindowResize(int w, int h) { + Log.v("SDL", "GLSurfaceView_SDL::onWindowResize(): " + w + "x" + h); + synchronized (this) { + mWidth = w; + mHeight = h; + mSizeChanged = true; + notify(); + } + } + + public void requestExitAndWait() { + // don't call this from GLThread thread or it is a guaranteed + // deadlock! + Log.v("SDL", "GLSurfaceView_SDL::requestExitAndWait()"); + synchronized(this) { + mDone = true; + notify(); + } + try { + join(); + } catch (InterruptedException ex) { + //Thread.currentThread().interrupt(); + } + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + synchronized(this) { + mEventQueue.add(r); + } + } + + private Runnable getEvent() { + synchronized(this) { + if (mEventQueue.size() > 0) { + return mEventQueue.remove(0); + } + + } + return null; + } + + private boolean mDone; + private boolean mPaused; + private boolean mHasSurface; + private int mWidth; + private int mHeight; + private int mRenderMode; + private boolean mRequestRender; + private Renderer mRenderer; + private ArrayList mEventQueue = new ArrayList(); + private EglHelper mEglHelper; + private GL10 mGL = null; + private boolean mNeedStart = false; + } + + static class LogWriter extends Writer { + + @Override public void close() { + flushBuilder(); + } + + @Override public void flush() { + flushBuilder(); + } + + @Override public void write(char[] buf, int offset, int count) { + for(int i = 0; i < count; i++) { + char c = buf[offset + i]; + if ( c == '\n') { + flushBuilder(); + } + else { + mBuilder.append(c); + } + } + } + + private void flushBuilder() { + if (mBuilder.length() > 0) { + Log.v("GLSurfaceView", mBuilder.toString()); + mBuilder.delete(0, mBuilder.length()); + } + } + + private StringBuilder mBuilder = new StringBuilder(); + } + + private static final Semaphore sEglSemaphore = new Semaphore(1); + private boolean mSizeChanged = true; + + private GLThread mGLThread; + private EGLConfigChooser mEGLConfigChooser; + private GLWrapper mGLWrapper; + private int mDebugFlags; + private KeyguardManager mKeyguardManager; } diff --git a/project/java/Video.java b/project/java/Video.java index deba57b74..f7ef28034 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -380,7 +380,7 @@ abstract class DifferentTouchInput } buttonState = buttonStateNew; } - super.process(event); // Push mouse coordinate first + super.process(event); } public void processGenericEvent(final MotionEvent event) { @@ -427,7 +427,7 @@ abstract class DifferentTouchInput DemoGLSurfaceView.nativeMotionEvent( (int)event.getHistoricalX(i), (int)event.getHistoricalY(i), Mouse.SDL_FINGER_MOVE, ptr, (int)( event.getHistoricalPressure(i) * Mouse.MAX_PRESSURE ), (int)( event.getHistoricalSize(i) * Mouse.MAX_PRESSURE ) ); } - super.process(event); // Push mouse coordinate first + super.process(event); } } private static class CrappyDragonRiseDatexGamepadInputWhichNeedsItsOwnHandlerBecauseImTooCheapAndStupidToBuyProperGamepad extends IcsTouchInput diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c index d19fb4535..290d14df0 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c @@ -830,6 +830,8 @@ JAVA_EXPORT_NAME(DemoGLSurfaceView_nativeMotionEvent) ( JNIEnv* env, jobject t return; #endif + //__android_log_print(ANDROID_LOG_INFO, "libSDL", "Motion event: %4d %4d action %d ptr %d, force %d radius %d", x, y, action, pointerId, force, radius); + pointerId = BumpPointerId( pointerId ); if( ProcessTouchscreenKeyboard( x, y, action, pointerId ) ) From ee5753a9cf82d27eb04d803b8d4b365826820125 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 24 Jun 2014 20:32:34 +0300 Subject: [PATCH 09/23] Updated XSDL --- project/jni/application/xserver/AndroidAppSettings.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/jni/application/xserver/AndroidAppSettings.cfg b/project/jni/application/xserver/AndroidAppSettings.cfg index b6ff4fe4f..433eadff1 100644 --- a/project/jni/application/xserver/AndroidAppSettings.cfg +++ b/project/jni/application/xserver/AndroidAppSettings.cfg @@ -204,7 +204,7 @@ FirstStartMenuOptions='SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.Op # Enable multi-ABI binary, with hardware FPU support - it will also work on old devices, # but .apk size is 2x bigger (y) / (n) / (x86) / (all) -MultiABI='armeabi-v7a x86 mips' +MultiABI=all # Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower AppMinimumRAM=0 From 418163f264d9e531cc932582e88f53563d91bae0 Mon Sep 17 00:00:00 2001 From: pelya Date: Sat, 28 Jun 2014 17:53:54 +0300 Subject: [PATCH 10/23] Gimp: fixing minor bugs --- .../xserver-gimp/AndroidAppSettings.cfg | 2 +- .../xserver-gimp/AndroidData/update1.tgz | Bin 0 -> 1147 bytes project/jni/application/xserver-gimp/xserver | 2 +- project/jni/application/xserver/gfx.c | 10 +++++----- 4 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 project/jni/application/xserver-gimp/AndroidData/update1.tgz diff --git a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg index 80bf22c26..420fcea60 100644 --- a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg +++ b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg @@ -18,7 +18,7 @@ AppVersionName="2.8.2.15" # If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir - # these files are put inside .apk package by build system # Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS -AppDataDownloadUrl="!!Data files|:data.tar.gz:http://sourceforge.net/projects/libsdl-android/files/ubuntu/14.05.01/dist-gimp-wheezy-.tar.gz/download^!!XSDL data files|:data-1.tar.gz:data-1.tgz^!!XSDL fonts|:DroidSansMono.ttf:DroidSansMono.ttf^!!Postinstall script|:postinstall.sh:postinstall2.sh" +AppDataDownloadUrl="!!Data files|:data.tar.gz:http://sourceforge.net/projects/libsdl-android/files/ubuntu/14.05.01/dist-gimp-wheezy-.tar.gz/download^!!XSDL data files|:data-1.tar.gz:data-1.tgz^!!XSDL fonts|:DroidSansMono.ttf:DroidSansMono.ttf^!!Postinstall script|:postinstall.sh:postinstall2.sh^!!Update|:update1.tar.gz:update1.tgz" # Reset SDL config when updating application to the new version (y) / (n) ResetSdlConfigForThisVersion=y diff --git a/project/jni/application/xserver-gimp/AndroidData/update1.tgz b/project/jni/application/xserver-gimp/AndroidData/update1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..46556a0017acdb1504b2d04fc0414c28b66c0bbe GIT binary patch literal 1147 zcmb2|=3uyTbzLw6^V^8r;KybH&x-4gUUOf6Ia}7!PsUjBWNg(Ehj!~34924&4%J18{oqeU>V-uFA zU7x$_@r|<08bAdoRDbUO?Drk>UbncWoM64^xb#ur*@SJ?_x@K{zKEY2 zKZmcX{qO4L$BYGx#y@;AR$Q z0oEDI?p1wg?%#XxVAg?1olvIkW9RbzfA9YHp!od~gH1tkTruG%4X%D(IHxhmq$gA8 zz@@v(o;RYNAc*>2($SzF>_`98@=HDx5Mgn ztW2p^{sVKXg%7-!9p&frS-R`&9b4%K%ULcraGrRim1x&9rKe#@)Kj;7BVF5mC%wFS zHr>Qi3JZkUI$JD!8=T(hUn}wqS(w!~ZKI;}jt}bPO6F2t{cSFb6JGn(#y)i}GVbIE za=dI{XuSG~+s1U2u)W!bD-#2cxdtN3P1R;FhH7y3Q_9jnvVPpA>g@437t;z;|(-v?Lx zxgLLEdvDJF^Bp(Rggz|#d_VKizxeEHub=+>FBS1IJ~l_@w#4JtKjY{AU-x>-pZ#od zpVl*XwIAMZeeCql{D{1n|MzprJ&!l+?^KyHdu3W(saeWHdr4*G9XB&_9^Efn`;7Tt z?D9bU&;PGG{Qj%Mm3U~%v!IfmsH;W>)!&z#Ke{71ChkwxJIVLErD05}#-8^G%7Fn&nflwAFv=`jeZk>RkC!n=ROXBRuNV znwYz>VXB5=C*pdHke!>LH^upx57vA>YBagBXTQLY7ZNs$lHE3OPOx5dv}wyRuVowK zzSms5ZX064w`2M3CyvK&N!`rI%k4Q+_kDl3kU1&PaZ?IuEA0ss~R@c)oY4qJPyLHCA2kQyvFz zMtyuLxV&)n*}BQ^*yqm6;n}q}?Cr?~x3ewJ2|I2NxLez>J_ zd&chi`v3mPGEG;vRs8;5^DjKxYW4s9YHI&x{Ewa%Jn#SdM*a8yuWe6{<56QRW?8NB z@$RmO*eTb|Gg#idyB)Q3(+)YC$yN`UuAA{VR(Boe?Ah_aDxt12HF%Lrr;w`G6pcU# RV~^24CYCQ@3mG&R7y$LvO$Gn} literal 0 HcmV?d00001 diff --git a/project/jni/application/xserver-gimp/xserver b/project/jni/application/xserver-gimp/xserver index 5eecca50c..3cce1acc1 160000 --- a/project/jni/application/xserver-gimp/xserver +++ b/project/jni/application/xserver-gimp/xserver @@ -1 +1 @@ -Subproject commit 5eecca50cbd8bad6eb9d2804094b0a603413ff8f +Subproject commit 3cce1acc1f943ded8491e1be814aebfce6e09023 diff --git a/project/jni/application/xserver/gfx.c b/project/jni/application/xserver/gfx.c index 234548096..ce3703197 100644 --- a/project/jni/application/xserver/gfx.c +++ b/project/jni/application/xserver/gfx.c @@ -236,11 +236,11 @@ static void * unpackFilesThread(void * unused) { const char *unpack[][3] = { - {"data.tar.gz", "postinstall.sh", "usr/lib/xorg/protocol.txt" }, - {"xfonts.tar.gz", "", "" }, - {"update1.tar.gz", "update1.sh", "" }, - {"update2.tar.gz", "update2.sh", "" }, - {"update3.tar.gz", "update3.sh", "" }, + { "data.tar.gz", "postinstall.sh", "usr/lib/xorg/protocol.txt" }, + { "xfonts.tar.gz", "", "" }, + { "update1.tar.gz", "update1.sh", "" }, + { "update2.tar.gz", "update2.sh", "" }, + { "update3.tar.gz", "update3.sh", "" }, {NULL, NULL, NULL} }; int i; From fd3db63357b8292c30eb5193e5d6934e4c751de8 Mon Sep 17 00:00:00 2001 From: pelya Date: Sat, 28 Jun 2014 17:58:12 +0300 Subject: [PATCH 11/23] Oops --- project/jni/application/xserver-gimp/AndroidAppSettings.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg index 420fcea60..8af6b13bb 100644 --- a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg +++ b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg @@ -24,7 +24,7 @@ AppDataDownloadUrl="!!Data files|:data.tar.gz:http://sourceforge.net/projects/li ResetSdlConfigForThisVersion=y # Delete application data files when upgrading (specify file/dir paths separated by spaces) -DeleteFilesOnUpgrade="libsdl-DownloadFinished-0.flag libsdl-DownloadFinished-1.flag libsdl-DownloadFinished-2.flag libsdl-DownloadFinished-3.flag" +DeleteFilesOnUpgrade="%" # Here you may type readme text, which will be shown during startup. Format is: # Text in English, use \\\\n to separate lines (that's four backslashes)^de:Text in Deutsch^ru:Text in Russian^button:Button that will open some URL:http://url-to-open/ From 317082448687024df53709332b9e8e9ff36fccc6 Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 29 Jun 2014 00:14:48 +0300 Subject: [PATCH 12/23] Gimp: fixes to the update, decreased Alt/Ctrl/Shift button size --- .../xserver-gimp/AndroidData/update1.tgz | Bin 1147 -> 1461 bytes project/jni/application/xserver/gfx.c | 7 ++++--- project/jni/application/xserver/main.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/project/jni/application/xserver-gimp/AndroidData/update1.tgz b/project/jni/application/xserver-gimp/AndroidData/update1.tgz index 46556a0017acdb1504b2d04fc0414c28b66c0bbe..f58e10b873244fe1b031708314ec7f8dbbc15831 100644 GIT binary patch literal 1461 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 RV~^24CYCQ@3mG&R7y$LvO$Gn} diff --git a/project/jni/application/xserver/gfx.c b/project/jni/application/xserver/gfx.c index ce3703197..b2b511b7d 100644 --- a/project/jni/application/xserver/gfx.c +++ b/project/jni/application/xserver/gfx.c @@ -48,7 +48,6 @@ static int unpackFiles(const char *archive, const char *script, const char *dele return 1; unpackProgressMb = 0; - strcpy( fname, getenv("SECURE_STORAGE_DIR") ); strcat( fname, "/" ); @@ -197,7 +196,7 @@ static int unpackFiles(const char *archive, const char *script, const char *dele strcat( fname2, script ); strcat( fname2, " > " ); strcat( fname2, fname ); - __android_log_print(ANDROID_LOG_INFO, "XSDL", "Copying postinstall scipt from SD card: %s", fname2); + __android_log_print(ANDROID_LOG_INFO, "XSDL", "Copying postinstall script from SD card: %s", fname2); system( fname2 ); } } @@ -220,6 +219,8 @@ static int unpackFiles(const char *archive, const char *script, const char *dele { if( !fgets(buf, sizeof(buf), fo) ) break; + if( strchr(buf, '\n') != NULL ) + strchr(buf, '\n')[0] = 0; __android_log_print(ANDROID_LOG_INFO, "XSDL", "> %s", buf); strncpy(unpackLog[3], unpackLog[2], sizeof(unpackLog[1]) - 4); strncpy(unpackLog[2], unpackLog[1], sizeof(unpackLog[1]) - 4); @@ -228,7 +229,7 @@ static int unpackFiles(const char *archive, const char *script, const char *dele __android_log_print(ANDROID_LOG_INFO, "XSDL", "Postinstall script exited with status %d", pclose(fo)); sprintf(unpackLog[0], "Running postinstall script finished"); - + return 1; } diff --git a/project/jni/application/xserver/main.c b/project/jni/application/xserver/main.c index dfe3ac791..d21a97be8 100644 --- a/project/jni/application/xserver/main.c +++ b/project/jni/application/xserver/main.c @@ -168,7 +168,7 @@ int main( int argc, char* argv[] ) { SDL_Rect pos; pos.x = 0; - pos.h = SDL_ListModes(NULL, 0)[0]->h / 10; + pos.h = SDL_ListModes(NULL, 0)[0]->h / 20; pos.y = SDL_ListModes(NULL, 0)[0]->h - pos.h; pos.w = 40 * SDL_ListModes(NULL, 0)[0]->w / resolutionW; SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_0, 1); From 0ff01e41110ee73e0903c0aecebadf40bf922abb Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 29 Jun 2014 00:39:50 +0300 Subject: [PATCH 13/23] Gimp: fixes, fixes --- .../xserver-gimp/AndroidAppSettings.cfg | 4 ++-- .../xserver-gimp/AndroidData/update1.tgz | Bin 1461 -> 1484 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg index 8af6b13bb..fa2b3d7ac 100644 --- a/project/jni/application/xserver-gimp/AndroidAppSettings.cfg +++ b/project/jni/application/xserver-gimp/AndroidAppSettings.cfg @@ -187,13 +187,13 @@ StartupMenuButtonTimeout=3000 # Menu items to hide from startup menu, available menu items: # SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout -HiddenMenuOptions='' +HiddenMenuOptions='SettingsMenuMisc.OptionalDownloadConfig' # Menu items to show at startup - this is Java code snippet, leave empty for default # new SettingsMenuMisc.ShowReadme(), (AppUsesMouse \&\& \! ForceRelativeMouseMode \? new SettingsMenuMouse.DisplaySizeConfig(true) : new SettingsMenu.DummyMenu()), new SettingsMenuMisc.OptionalDownloadConfig(true), new SettingsMenuMisc.GyroscopeCalibration() # Available menu items: # SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout -FirstStartMenuOptions='SettingsMenu.DummyMenu' +FirstStartMenuOptions='' # Enable multi-ABI binary, with hardware FPU support - it will also work on old devices, # but .apk size is 2x bigger (y) / (n) / (x86) / (all) diff --git a/project/jni/application/xserver-gimp/AndroidData/update1.tgz b/project/jni/application/xserver-gimp/AndroidData/update1.tgz index f58e10b873244fe1b031708314ec7f8dbbc15831..1e20116c1c66baece37df09d386e4d67c6061e49 100644 GIT binary patch literal 1484 zcmb2|=3tm&ygrzL`EAtgqT6NyUyb)Co!<42A@cEV?7XeYLR8F%e$4o){7{9n$LA^^DLSC)xGLJ zw$JW8*7Sc`a&_sH!#$7o?_0}v_n7&)|KINmT27bjKB?f-AtT-9uiAX`U*!9*uKUX? z%l>Vw|FW#S^3OW{L?+`Ok~8d|C46gnu!xtloy&8YkDA45M(H+A?laT%AF^uwVhov~ z`l3nWfXdhKUitlYujKEWSa|O|kq~&}?)$%`_g>dqSZVg&(a>jImz6T%^v{O#4hB+7 zO{5QBdNj50*{*7GFaoVi{8{`XxeXOi8%>7T3myXnuH-1kqGMEg8zcvPa- z?cb;GfA8--`&a*KE2~QWZOg9VufN3E+F(5M&y<5xy0cC1T(;ZSWgxqmWlDUSPQ$_n zh7)4C4!uxcs`|W8MD65SH#l9aJ|jA5h0{?P-Q>os9dGPm$vB?5*g3mSf|X=4sqYQo9F&+OfoES9`5^NQGNu?VJhmof`juZeI(FdwM%=~BP; z+m-3>?wUpOSEsy;*NSvCp7DGC%wzxmX1!y{`Wr61^Q=O`&@mIJ1e!!EYDf+PL|pAPw#Kt*qT`;TuV9m6Yi+4_`a%XL3yj`<- z{Q=?M`yXG8{{G{*#)gI8|HmdA{=0v1&4YCj8ylGxR4LtNKDRzuYu)Z=7N;+nDPDfL z#Z07!)h909W^JLNQkFa43J#UXX;DjO?a9{VyPCFV;?hI$%-)$1iAGPB1-?1AG*N=v z?9Hsh21yxNA6<8S_#p5&+Vfnd(W4~~&q(!cn)x)tz<*MuuCJTg1%(90HtrpAkzc1h zt$4oedfDEx!@rNWNG#8gShs$Di_w{DVfu&puRcEf^n$hF=?n*Bu9_~#%V&SQ@4c(@ zbShilt{FPsM>SJ72wfIb&SH2nEyGgr?ZgL_TH&VrulVkB%<6NFFFUcfYpUs{Yj;jb z_y+eJ$!O!-yliK*(CHtq&$e?{EdRy-K2vB}<(3sTqBSZRJ@YJ+>#qNqxGZL$Olx75 zgXFUb4BtD%xQ?dWs4ri~ZX;UUn+C25qXIsBVL95qUzO$M;XHDs@=52ph zT$bGu`(1E(^osnuFAEs$Ty^MCb(fcO8c4;=pe|54TcM}Avg$umx!zIlqEMiTr$?_Ti literal 1461 zcmb2|=3qFXvObuB`EAtgqT6NyUyb)OrQRu-HLb~`Yl-{BDZ4h#TJl&$?&iGA-$~9Y zDhJg#`5az-`W_pw=xKM#>C7d5Y8L!Tdb_(%M>26c=}11>tGk$w!^YqC?Sa+z>%wkq zmc3qVd%p0`vADbIe)lHuSKfX%!%4ANN#NG$3>)SC6SkrMdz%>l&wOCB{^Z4NwRjNS=b)Ywd_T@%V9zHv~Ui+SsG6>T2*|HC(pRr!587B{P}D47cP;*9BU1_ z53)KocnRrA+gDZJu-=tfFspFl;>yJ8{lBkAZvX!B!w#dO#d`#Hta(_cm|kn=+BC^R z`6q|2PMp;9`EuV9wjR?u>3uk&Q7y4>CQI2Gg)p=SBB9d&7iuOmpOP@ z`~~!uX!OQu>RNgyO^f^ArQ$B!<(A?TcrGyPNymas-zR9RI<|I5Mzk?qEx0;=lkn1u zGul;-39-!H{^_*N>&L4Ln;N}>j_h2z=8?AJ{0Tc&#!Bf4f7baEB5RnK=2vz1@%eW5 z+*GZkNnet+Go&RTN{<**YncsqI^`;YV^Dvp+`(JyTKW6K{+xuR> z{#!4;PbCMo3Gvu<|7V+WdmZniS^s4pF#f;n=ph|{o!jj3{lexp_J#2bf6R04 zU;Oi)Df>rz{E0eM^BZ&ix8+-B{r!GG*yR821CRf#?wJ}W*yl0p(v4YaAH{zh*?g^@ z|J;AR9EPg@_c`aC|6gL@DP`)Bd#6q5M!w0lPw#IYTvERS^tQXJN%cyp7 z2G_}oTV`*g?zUX6KA}8~@Ak8wH|4K2{#=$Uv9^_a!4#D(xzqd-?p=K?!Ljwh71n=~ z&WjZ}&kAx(5`MawXOqdvPm!8G0!$vU%KXtgG^6#pxTSZ-QkM4cjLsvhOL7auh4T{_ z&P}xRJUrD+CVwtxDbI9C&VyX~Q;v1Xohgmp5%g9DB|NOe8@%g$e>Tna#J5ZH!we~dU zxi<@5vih3;IPSvfbFpFVdU@lMpSE7@{^0y|$7YEt?S+<|9)1Gz9WIm@|Eo?m*REX3 zxL8m9bWov}=o*z2kBw3c`&6TRJ&H9dCZ0?^+q~bE9mk;@W(S6dUH672VsyFeodLA%dZjv)w-}Bhh*NWaor&r1@ zkngTMczMngN7;~jGbR6I^hfVll*Kr6n@o>qCvG(;-&gZj-zcN$R`i~~^;Z9iW0&vxU!LP} zJ=glf*MIwkZT9^Czux@G$jYB=^NBB3r*1Oy*I$3r zu*gb3_wbDW> Date: Sun, 29 Jun 2014 01:00:53 +0300 Subject: [PATCH 14/23] Gimp: yet more fixes to update script --- .../xserver-gimp/AndroidData/update1.tgz | Bin 1484 -> 3002 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/project/jni/application/xserver-gimp/AndroidData/update1.tgz b/project/jni/application/xserver-gimp/AndroidData/update1.tgz index 1e20116c1c66baece37df09d386e4d67c6061e49..2fd22642be0f3ebd0c288c83d757fc372249ee01 100644 GIT binary patch literal 3002 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 L)`~JzFfafB-t6n7 literal 1484 zcmb2|=3tm&ygrzL`EAtgqT6NyUyb)Co!<42A@cEV?7XeYLR8F%e$4o){7{9n$LA^^DLSC)xGLJ zw$JW8*7Sc`a&_sH!#$7o?_0}v_n7&)|KINmT27bjKB?f-AtT-9uiAX`U*!9*uKUX? z%l>Vw|FW#S^3OW{L?+`Ok~8d|C46gnu!xtloy&8YkDA45M(H+A?laT%AF^uwVhov~ z`l3nWfXdhKUitlYujKEWSa|O|kq~&}?)$%`_g>dqSZVg&(a>jImz6T%^v{O#4hB+7 zO{5QBdNj50*{*7GFaoVi{8{`XxeXOi8%>7T3myXnuH-1kqGMEg8zcvPa- z?cb;GfA8--`&a*KE2~QWZOg9VufN3E+F(5M&y<5xy0cC1T(;ZSWgxqmWlDUSPQ$_n zh7)4C4!uxcs`|W8MD65SH#l9aJ|jA5h0{?P-Q>os9dGPm$vB?5*g3mSf|X=4sqYQo9F&+OfoES9`5^NQGNu?VJhmof`juZeI(FdwM%=~BP; z+m-3>?wUpOSEsy;*NSvCp7DGC%wzxmX1!y{`Wr61^Q=O`&@mIJ1e!!EYDf+PL|pAPw#Kt*qT`;TuV9m6Yi+4_`a%XL3yj`<- z{Q=?M`yXG8{{G{*#)gI8|HmdA{=0v1&4YCj8ylGxR4LtNKDRzuYu)Z=7N;+nDPDfL z#Z07!)h909W^JLNQkFa43J#UXX;DjO?a9{VyPCFV;?hI$%-)$1iAGPB1-?1AG*N=v z?9Hsh21yxNA6<8S_#p5&+Vfnd(W4~~&q(!cn)x)tz<*MuuCJTg1%(90HtrpAkzc1h zt$4oedfDEx!@rNWNG#8gShs$Di_w{DVfu&puRcEf^n$hF=?n*Bu9_~#%V&SQ@4c(@ zbShilt{FPsM>SJ72wfIb&SH2nEyGgr?ZgL_TH&VrulVkB%<6NFFFUcfYpUs{Yj;jb z_y+eJ$!O!-yliK*(CHtq&$e?{EdRy-K2vB}<(3sTqBSZRJ@YJ+>#qNqxGZL$Olx75 zgXFUb4BtD%xQ?dWs4ri~ZX;UUn+C25qXIsBVL95qUzO$M;XHDs@=52ph zT$bGu`(1E(^osnuFAEs$Ty^MCb(fcO8c4;=pe|54TcM}Avg$umx!zIlqEMiTr$?_Ti From 283b1d6b3ddf4fe42b6d1bfdc2f89dc9493a3b44 Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 29 Jun 2014 01:31:35 +0300 Subject: [PATCH 15/23] Inverted axis for gyroscope mouse movement, because eh, why did I think inverted axes was a nice idea anyway? --- project/jni/sdl-1.2/src/video/android/SDL_androidinput.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c index 290d14df0..db45612a6 100644 --- a/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c +++ b/project/jni/sdl-1.2/src/video/android/SDL_androidinput.c @@ -885,12 +885,9 @@ static void ProcessMoveMouseWithGyroscope(float gx, float gy, float gz) if( hardwareMouseDetected == MOUSE_HW_INPUT_MOUSE ) // We don't need all that stuff with a proper precise input device return; - gx += gz; // Ignore Z? - gx *= -moveMouseWithGyroscopeSpeed; - gy *= moveMouseWithGyroscopeSpeed; // Screen has Y coordinate inverted - - //gx *= 10; // debug - //gy *= 10; // debug + //gx += gz; // Ignore Z + gx *= moveMouseWithGyroscopeSpeed; + gy *= -moveMouseWithGyroscopeSpeed; // Screen has Y coordinate inverted static float subpixelX = 0.0f, subpixelY = 0.0f; From 4cd55d4d07bac71bf70e8be79e8b02faf66576a6 Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 29 Jun 2014 02:59:58 +0300 Subject: [PATCH 16/23] I'm not insane - gyroscope swaps axes when the screen orientation is inverted when holding the phone upside down. --- project/java/Accelerometer.java | 31 ++++++++++++++++++------------- project/java/MainActivity.java | 20 +++++++++++++++++--- project/java/Video.java | 11 +++++++++++ 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/project/java/Accelerometer.java b/project/java/Accelerometer.java index e99043b76..90d19ec22 100644 --- a/project/java/Accelerometer.java +++ b/project/java/Accelerometer.java @@ -90,25 +90,30 @@ class AccelerometerReader implements SensorEventListener static class GyroscopeListener implements SensorEventListener { public float x1 = 0.0f, x2 = 0.0f, xc = 0.0f, y1 = 0.0f, y2 = 0.0f, yc = 0.0f, z1 = 0.0f, z2 = 0.0f, zc = 0.0f; + public boolean invertedOrientation = false; public GyroscopeListener() { } public void onSensorChanged(SensorEvent event) { - // TODO: vertical orientation - if( Globals.HorizontalOrientation ) + if( event.values[0] < x1 || event.values[0] > x2 || + event.values[1] < y1 || event.values[1] > y2 || + event.values[2] < z1 || event.values[2] > z2 ) { - if( event.values[0] < x1 || event.values[0] > x2 || - event.values[1] < y1 || event.values[1] > y2 || - event.values[2] < z1 || event.values[2] > z2 ) - nativeGyroscope(event.values[0] - xc, event.values[1] - yc, event.values[2] - zc); - } - else - { - if( event.values[0] < x1 || event.values[0] > x2 || - event.values[1] < y1 || event.values[1] > y2 || - event.values[2] < z1 || event.values[2] > z2 ) - nativeGyroscope(-(event.values[1] - yc), event.values[0] - xc, event.values[2] - zc); + if( Globals.HorizontalOrientation ) + { + if( invertedOrientation ) + nativeGyroscope(-(event.values[0] - xc), -(event.values[1] - yc), event.values[2] - zc); + else + nativeGyroscope(event.values[0] - xc, event.values[1] - yc, event.values[2] - zc); + } + else + { + if( invertedOrientation ) + nativeGyroscope(event.values[1] - yc, -(event.values[0] - xc), event.values[2] - zc); + else + nativeGyroscope(-(event.values[1] - yc), event.values[0] - xc, event.values[2] - zc); + } } } public void onAccuracyChanged(Sensor s, int a) diff --git a/project/java/MainActivity.java b/project/java/MainActivity.java index c43df63c1..ce82058b0 100644 --- a/project/java/MainActivity.java +++ b/project/java/MainActivity.java @@ -79,6 +79,8 @@ import android.content.pm.ActivityInfo; import android.view.Display; import android.text.InputType; import android.util.Log; +import android.view.Surface; + public class MainActivity extends Activity { @@ -231,7 +233,7 @@ public class MainActivity extends Activity if( Parent._tv == null ) { //Get the display so we can know the screen size - Display display = getWindowManager().getDefaultDisplay(); + Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); int height = display.getHeight(); Parent._tv = new TextView(Parent); @@ -266,6 +268,8 @@ public class MainActivity extends Activity public void initSDL() { setScreenOrientation(); + updateScreenOrientation(); + Log.i("SDL", "onConfigurationChanged(): screen orientation: inverted " + AccelerometerReader.gyro.invertedOrientation); (new Thread(new Runnable() { public void run() @@ -836,10 +840,20 @@ public class MainActivity extends Activity @Override public void onConfigurationChanged(Configuration newConfig) { + // This function is actually never called super.onConfigurationChanged(newConfig); - // Do nothing here + updateScreenOrientation(); } - + + public void updateScreenOrientation() + { + int rotation = Surface.ROTATION_0; + if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO ) + rotation = getWindowManager().getDefaultDisplay().getRotation(); + AccelerometerReader.gyro.invertedOrientation = ( rotation == Surface.ROTATION_180 || rotation == Surface.ROTATION_270 ); + //Log.d("SDL", "updateScreenOrientation(): screen orientation: " + rotation + " inverted " + AccelerometerReader.gyro.invertedOrientation); + } + public void setText(final String t) { class Callback implements Runnable diff --git a/project/java/Video.java b/project/java/Video.java index f7ef28034..e19b970fd 100644 --- a/project/java/Video.java +++ b/project/java/Video.java @@ -719,6 +719,16 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer Thread.sleep(50); // Give some time to the keyboard input thread } catch(Exception e) { }; } + + // We will not receive onConfigurationChanged() inside MainActivity with SCREEN_ORIENTATION_SENSOR_LANDSCAPE + // so we need to create a hacky frame counter to update screen orientation, because this call takes up some time + mOrientationFrameHackyCounter++; + if( mOrientationFrameHackyCounter > 100 ) + { + mOrientationFrameHackyCounter = 0; + context.updateScreenOrientation(); + } + return 1; } @@ -913,6 +923,7 @@ class DemoRenderer extends GLSurfaceView_SDL.Renderer public int mWidth = 0; public int mHeight = 0; private ClipboardManager clipboard = null; + int mOrientationFrameHackyCounter = 0; public static final boolean mRatelimitTouchEvents = true; //(Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO); } From 0802c3cceef97f9feec7c1354e00be0b8a5cff04 Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 29 Jun 2014 03:01:25 +0300 Subject: [PATCH 17/23] Swapped gyroscope axes for vertical screen orientation --- project/java/Accelerometer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/java/Accelerometer.java b/project/java/Accelerometer.java index 90d19ec22..cbcb376b2 100644 --- a/project/java/Accelerometer.java +++ b/project/java/Accelerometer.java @@ -110,9 +110,9 @@ class AccelerometerReader implements SensorEventListener else { if( invertedOrientation ) - nativeGyroscope(event.values[1] - yc, -(event.values[0] - xc), event.values[2] - zc); - else nativeGyroscope(-(event.values[1] - yc), event.values[0] - xc, event.values[2] - zc); + else + nativeGyroscope(event.values[1] - yc, -(event.values[0] - xc), event.values[2] - zc); } } } From ac4abb3d686789d882a7abb082980e4820582299 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 1 Jul 2014 21:11:58 +0300 Subject: [PATCH 18/23] Added several .gitignore files, small fix to XSDL --- .gitignore | 4 ++++ project/jni/application/hid-pc-keyboard/src | 2 +- project/jni/application/openttd/.gitignore | 1 + project/jni/application/openttd/AndroidBuild.sh | 2 +- project/jni/application/supertux/.gitignore | 1 + project/jni/application/teeworlds/.gitignore | 1 + project/jni/application/xserver-debian/xserver | 2 +- project/jni/application/xserver/.gitignore | 2 ++ project/jni/application/xserver/AndroidAppSettings.cfg | 6 +++--- project/jni/application/xserver/main.c | 8 ++++---- 10 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 project/jni/application/openttd/.gitignore create mode 100644 project/jni/application/supertux/.gitignore create mode 100644 project/jni/application/teeworlds/.gitignore diff --git a/.gitignore b/.gitignore index b9564a031..500d6ce7e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,8 @@ project/jni/application/*/libapplication*.so project/jni/application/src project/res/drawable-xhdpi/ouya_icon.png project/res/drawable/app_icon.png +project/proguard-project.txt +project/themes/converter + + diff --git a/project/jni/application/hid-pc-keyboard/src b/project/jni/application/hid-pc-keyboard/src index 1eb04e501..6a61afd4a 160000 --- a/project/jni/application/hid-pc-keyboard/src +++ b/project/jni/application/hid-pc-keyboard/src @@ -1 +1 @@ -Subproject commit 1eb04e5013dcbf5bd3536cc959b04f474c3cbafd +Subproject commit 6a61afd4a2d5422f841abe720cee8fb99cb0ce96 diff --git a/project/jni/application/openttd/.gitignore b/project/jni/application/openttd/.gitignore new file mode 100644 index 000000000..2b107e500 --- /dev/null +++ b/project/jni/application/openttd/.gitignore @@ -0,0 +1 @@ +openttd-build-* diff --git a/project/jni/application/openttd/AndroidBuild.sh b/project/jni/application/openttd/AndroidBuild.sh index 71cd02542..393d3f93b 100755 --- a/project/jni/application/openttd/AndroidBuild.sh +++ b/project/jni/application/openttd/AndroidBuild.sh @@ -2,7 +2,7 @@ LOCAL_PATH=`dirname $0` LOCAL_PATH=`cd $LOCAL_PATH && pwd` -VER=1.4.0-beta5 +VER=build [ -d openttd-$VER-$1 ] || mkdir -p openttd-$VER-$1/bin/baseset diff --git a/project/jni/application/supertux/.gitignore b/project/jni/application/supertux/.gitignore new file mode 100644 index 000000000..137d334da --- /dev/null +++ b/project/jni/application/supertux/.gitignore @@ -0,0 +1 @@ +supertux diff --git a/project/jni/application/teeworlds/.gitignore b/project/jni/application/teeworlds/.gitignore new file mode 100644 index 000000000..b52e154fa --- /dev/null +++ b/project/jni/application/teeworlds/.gitignore @@ -0,0 +1 @@ +AndroidData diff --git a/project/jni/application/xserver-debian/xserver b/project/jni/application/xserver-debian/xserver index 5eecca50c..3cce1acc1 160000 --- a/project/jni/application/xserver-debian/xserver +++ b/project/jni/application/xserver-debian/xserver @@ -1 +1 @@ -Subproject commit 5eecca50cbd8bad6eb9d2804094b0a603413ff8f +Subproject commit 3cce1acc1f943ded8491e1be814aebfce6e09023 diff --git a/project/jni/application/xserver/.gitignore b/project/jni/application/xserver/.gitignore index 5761abcfd..8b4cf3c1c 100644 --- a/project/jni/application/xserver/.gitignore +++ b/project/jni/application/xserver/.gitignore @@ -1 +1,3 @@ *.o +AndroidData/binaries-* +tmp-* diff --git a/project/jni/application/xserver/AndroidAppSettings.cfg b/project/jni/application/xserver/AndroidAppSettings.cfg index 433eadff1..7315a3190 100644 --- a/project/jni/application/xserver/AndroidAppSettings.cfg +++ b/project/jni/application/xserver/AndroidAppSettings.cfg @@ -7,10 +7,10 @@ AppName="XServer XSDL" AppFullName=x.org.server # Application version code (integer) -AppVersionCode=11115 +AppVersionCode=11116 # Application user-visible version name (string) -AppVersionName="1.11.15" +AppVersionName="1.11.16" # Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...' # If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu @@ -21,7 +21,7 @@ AppVersionName="1.11.15" AppDataDownloadUrl="!!Data files|:data.tar.gz:data-1.tgz^!!Data files|:DroidSansMono.ttf:DroidSansMono.ttf^Additional fonts (90Mb)|:xfonts.tar.gz:http://sourceforge.net/projects/libsdl-android/files/apk/XServer-XSDL/xfonts.tgz/download" # Reset SDL config when updating application to the new version (y) / (n) -ResetSdlConfigForThisVersion=y +ResetSdlConfigForThisVersion=n # Delete application data files when upgrading (specify file/dir paths separated by spaces) DeleteFilesOnUpgrade="%" diff --git a/project/jni/application/xserver/main.c b/project/jni/application/xserver/main.c index d21a97be8..7d48072bc 100644 --- a/project/jni/application/xserver/main.c +++ b/project/jni/application/xserver/main.c @@ -51,12 +51,10 @@ int main( int argc, char* argv[] ) __android_log_print(ANDROID_LOG_INFO, "XSDL", "Actual video resolution %d/%dx%d/%d", resolutionW, displayW, resolutionH, displayH); setupEnv(); - SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_0, 0); - SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_1, 0); - SDL_ANDROID_SetScreenKeyboardButtonShown(SDL_ANDROID_SCREENKEYBOARD_BUTTON_2, 0); + SDL_ANDROID_SetScreenKeyboardShown(0); XSDL_initSDL(); - + XSDL_unpackFiles(); XSDL_showConfigMenu(&resolutionW, &displayW, &resolutionH, &displayH); @@ -164,6 +162,8 @@ int main( int argc, char* argv[] ) argnum += 2; } + SDL_ANDROID_SetScreenKeyboardShown(1); + if( screenButtons ) { SDL_Rect pos; From a2ea3778086fc8e61f01bfed8b3f6946e6dedee0 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 1 Jul 2014 21:17:45 +0300 Subject: [PATCH 19/23] Help message in createSourceArchive.sh, to install pxz if it's not available --- createSourceArchive.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/createSourceArchive.sh b/createSourceArchive.sh index f7971c613..f72c4d2ee 100755 --- a/createSourceArchive.sh +++ b/createSourceArchive.sh @@ -6,7 +6,7 @@ APPVER=`grep AppVersionName AndroidAppSettings.cfg | sed 's/.*=//' | tr -d '"' | ARCHIVER=gzip EXT=gz which xz > /dev/null && ARCHIVER="xz -z" && EXT=xz -which pxz > /dev/null && ARCHIVER=pxz && EXT=xz +which pxz > /dev/null && ARCHIVER=pxz && EXT=xz || echo "Install pxz for faster archiving: sudo apt-get isntall pxz" # TODO: Boost, Python and ffmpeg are stored in repository as precompiled binaries, the proper way to fix that is to build them using scripts, and remove that binaries # --exclude="*.a" --exclude="*.so" From 26eef3ab4a452e0798d6cedd730d1e6186104fae Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 1 Jul 2014 21:27:38 +0300 Subject: [PATCH 20/23] Updated todo --- todo.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/todo.txt b/todo.txt index e94d90b26..52677689c 100644 --- a/todo.txt +++ b/todo.txt @@ -17,6 +17,8 @@ TODO, which will get actually done - SDL: control mouse with right analog gamepad stick. +- SDL: sometimes the screen stays black after restoring from background. + - OpenTTD: All menus in the scenario editor are out of the screen. - OpenTTD: 16bpp blitter with palette animation support. @@ -39,10 +41,8 @@ TODO, which will get actually done - OpenTTD: Frameskip when fast-forward button pressed. +- OpenTTD: Face selection dialog is too tall. + - Debian noroot: audio support. - Debian noroot: add Java dirs to PATH, add support for update scripts. - -- Debian noroot: add paths to external SD cards to the proot. - -- Gimp: update - add Java dirs to PATH and use new mouse name in Gimp config. From 7803e91ecdace8259eca4da74b3500eb840ae2cf Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 1 Jul 2014 22:22:24 +0300 Subject: [PATCH 21/23] Updated OpenTTD --- project/jni/application/openttd/AndroidAppSettings.cfg | 8 ++++---- project/jni/application/openttd/src | 2 +- todo.txt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/project/jni/application/openttd/AndroidAppSettings.cfg b/project/jni/application/openttd/AndroidAppSettings.cfg index 3a6e2650c..34b4d08f2 100644 --- a/project/jni/application/openttd/AndroidAppSettings.cfg +++ b/project/jni/application/openttd/AndroidAppSettings.cfg @@ -7,10 +7,10 @@ AppName="OpenTTD" AppFullName=org.openttd.sdl # Application version code (integer) -AppVersionCode=14132 +AppVersionCode=14133 # Application user-visible version name (string) -AppVersionName="1.4.1.32" +AppVersionName="1.4.1.33" # Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...' # If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu @@ -21,7 +21,7 @@ AppVersionName="1.4.1.32" AppDataDownloadUrl="!!Data files - 20 Mb|http://sourceforge.net/projects/libsdl-android/files/OpenTTD/openttd-data-1.4.1.zip/download^!!Config file|:.openttd/openttd.cfg:openttd-1.4.0.30.cfg^!MIDI music support (18 Mb)|timidity.zip|http://sourceforge.net/projects/libsdl-android/files/timidity.zip^!!Internationalization files|http://sourceforge.net/projects/libsdl-android/files/icudt52l.zip/download" # Reset SDL config when updating application to the new version (y) / (n) -ResetSdlConfigForThisVersion=y +ResetSdlConfigForThisVersion=n # Delete application data files when upgrading (specify file/dir paths separated by spaces) DeleteFilesOnUpgrade="" @@ -201,7 +201,7 @@ FirstStartMenuOptions='' # Enable multi-ABI binary, with hardware FPU support - it will also work on old devices, # but .apk size is 2x bigger (y) / (n) / (x86) / (all) -MultiABI=all +MultiABI=armeabi-v7a # Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower AppMinimumRAM=0 diff --git a/project/jni/application/openttd/src b/project/jni/application/openttd/src index 4627d6c93..e4179d342 160000 --- a/project/jni/application/openttd/src +++ b/project/jni/application/openttd/src @@ -1 +1 @@ -Subproject commit 4627d6c939b3b2d8153aca18f633a2580ecab028 +Subproject commit e4179d3428b9b6a1c1c9e346f951117facc0b9c2 diff --git a/todo.txt b/todo.txt index 52677689c..bf181e721 100644 --- a/todo.txt +++ b/todo.txt @@ -45,4 +45,4 @@ TODO, which will get actually done - Debian noroot: audio support. -- Debian noroot: add Java dirs to PATH, add support for update scripts. +- Debian noroot: add Java dirs to PATH, add support for update scripts, make desktop icons text readable. From 0fe4f9b9f6fb14e8e1e3528754fc61000aa31b55 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Tue, 1 Jul 2014 23:31:58 +0300 Subject: [PATCH 22/23] Updated Debian --- .../xserver-debian/AndroidAppSettings.cfg | 10 +++++----- .../xserver-debian/AndroidData/update1.tgz | Bin 0 -> 3133 bytes .../jni/application/xserver-debian/readme.txt | 2 +- project/jni/application/xserver-gimp/readme.txt | 2 +- project/jni/application/xserver/readme.txt | 2 +- todo.txt | 2 -- 6 files changed, 8 insertions(+), 10 deletions(-) create mode 100644 project/jni/application/xserver-debian/AndroidData/update1.tgz diff --git a/project/jni/application/xserver-debian/AndroidAppSettings.cfg b/project/jni/application/xserver-debian/AndroidAppSettings.cfg index f818c6187..a8e5ebf5b 100644 --- a/project/jni/application/xserver-debian/AndroidAppSettings.cfg +++ b/project/jni/application/xserver-debian/AndroidAppSettings.cfg @@ -7,10 +7,10 @@ AppName="Debian" AppFullName=com.cuntubuntu # Application version code (integer) -AppVersionCode=140503 +AppVersionCode=140701 # Application user-visible version name (string) -AppVersionName="14.05.03" +AppVersionName="14.07.01" # Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...' # If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu @@ -18,17 +18,17 @@ AppVersionName="14.05.03" # If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir - # these files are put inside .apk package by build system # Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS -AppDataDownloadUrl="!!System image|:data.tar.gz:http://sourceforge.net/projects/libsdl-android/files/ubuntu/14.05.01/dist-debug-wheezy-proot-.tar.gz/download^!!XSDL data files|:data-1.tar.gz:data-1.tgz^!!XSDL fonts|:DroidSansMono.ttf:DroidSansMono.ttf^!!Postinstall script|:postinstall.sh:postinstall2.sh" +AppDataDownloadUrl="!!System image|:data.tar.gz:http://sourceforge.net/projects/libsdl-android/files/ubuntu/14.05.01/dist-debug-wheezy-proot-.tar.gz/download^!!XSDL data files|:data-1.tar.gz:data-1.tgz^!!XSDL fonts|:DroidSansMono.ttf:DroidSansMono.ttf^!!Postinstall script|:postinstall.sh:postinstall2.sh^!!Update|:update1.tar.gz:update1.tgz" # Reset SDL config when updating application to the new version (y) / (n) ResetSdlConfigForThisVersion=y # Delete application data files when upgrading (specify file/dir paths separated by spaces) -DeleteFilesOnUpgrade="libsdl-DownloadFinished-0.flag libsdl-DownloadFinished-1.flag libsdl-DownloadFinished-2.flag libsdl-DownloadFinished-3.flag" +DeleteFilesOnUpgrade="%" # Here you may type readme text, which will be shown during startup. Format is: # Text in English, use \\\\n to separate lines (that's four backslashes)^de:Text in Deutsch^ru:Text in Russian^button:Button that will open some URL:http://url-to-open/ -ReadmeText='This app will download 220 Mb data,\\\\nand will use 600 Mb of internal storage.\\\\nYour old installation will be removed\\\\n^button:Install old version:http://sourceforge.net/projects/libsdl-android/files/ubuntu/' +ReadmeText='This app will download 220 Mb data,\\\\n and will use 600 Mb of internal storage.' # libSDL version to use (1.2/1.3/2.0) LibSdlVersion=1.2 diff --git a/project/jni/application/xserver-debian/AndroidData/update1.tgz b/project/jni/application/xserver-debian/AndroidData/update1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..389ecb0b94d82310e585740b8b4c880b09f90dbb GIT binary patch literal 3133 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 R`u_jeZ#VWPGE^`y007dSMh5@@ literal 0 HcmV?d00001 diff --git a/project/jni/application/xserver-debian/readme.txt b/project/jni/application/xserver-debian/readme.txt index 2e6cd39b1..117d44fc2 100644 --- a/project/jni/application/xserver-debian/readme.txt +++ b/project/jni/application/xserver-debian/readme.txt @@ -16,7 +16,7 @@ x11proto-xext-dev x11proto-xf86bigfont-dev \ x11proto-xf86dga-dev x11proto-xf86dri-dev \ x11proto-xf86vidmode-dev x11proto-xinerama-dev \ libxmuu-dev libxt-dev libsm-dev libice-dev \ -libxrender-dev libxrandr-dev curl +libxrender-dev libxrandr-dev curl autoconf automake libtool You will need both xcb-proto and python-xcbgen packages to have version 1.10-1, you may download newer packages diff --git a/project/jni/application/xserver-gimp/readme.txt b/project/jni/application/xserver-gimp/readme.txt index 02748d8a5..abc575427 100644 --- a/project/jni/application/xserver-gimp/readme.txt +++ b/project/jni/application/xserver-gimp/readme.txt @@ -16,7 +16,7 @@ x11proto-xext-dev x11proto-xf86bigfont-dev \ x11proto-xf86dga-dev x11proto-xf86dri-dev \ x11proto-xf86vidmode-dev x11proto-xinerama-dev \ libxmuu-dev libxt-dev libsm-dev libice-dev \ -libxrender-dev libxrandr-dev curl +libxrender-dev libxrandr-dev curl autoconf automake libtool You will need both xcb-proto and python-xcbgen packages to have version 1.10-1, you may download newer packages diff --git a/project/jni/application/xserver/readme.txt b/project/jni/application/xserver/readme.txt index 20cb280de..2240e1f9f 100644 --- a/project/jni/application/xserver/readme.txt +++ b/project/jni/application/xserver/readme.txt @@ -16,7 +16,7 @@ x11proto-xext-dev x11proto-xf86bigfont-dev \ x11proto-xf86dga-dev x11proto-xf86dri-dev \ x11proto-xf86vidmode-dev x11proto-xinerama-dev \ libxmuu-dev libxt-dev libsm-dev libice-dev \ -libxrender-dev libxrandr-dev curl +libxrender-dev libxrandr-dev curl autoconf automake libtool You will need both xcb-proto and python-xcbgen packages to have version 1.10-1, you may download newer packages diff --git a/todo.txt b/todo.txt index bf181e721..63d35acf4 100644 --- a/todo.txt +++ b/todo.txt @@ -44,5 +44,3 @@ TODO, which will get actually done - OpenTTD: Face selection dialog is too tall. - Debian noroot: audio support. - -- Debian noroot: add Java dirs to PATH, add support for update scripts, make desktop icons text readable. From 214db63ac96ff3f2586c007af09daeb1025b2f87 Mon Sep 17 00:00:00 2001 From: Sergii Pylypenko Date: Wed, 2 Jul 2014 23:44:13 +0300 Subject: [PATCH 23/23] XSDL: Fixed random screen buttons appearing when user redefined them through SDL dialog. --- project/jni/application/xserver/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/jni/application/xserver/main.c b/project/jni/application/xserver/main.c index 7d48072bc..29b6d82dd 100644 --- a/project/jni/application/xserver/main.c +++ b/project/jni/application/xserver/main.c @@ -164,7 +164,7 @@ int main( int argc, char* argv[] ) SDL_ANDROID_SetScreenKeyboardShown(1); - if( screenButtons ) + if( screenButtons && !SDL_ANDROID_GetScreenKeyboardRedefinedByUser() ) { SDL_Rect pos; pos.x = 0;