summaryrefslogtreecommitdiffstats
path: root/Common/NativeApp
diff options
context:
space:
mode:
authorEgor <egor.yusov@gmail.com>2018-02-11 04:57:27 +0000
committerEgor <egor.yusov@gmail.com>2018-02-11 04:57:27 +0000
commitbc569d8612c4e22924b85576f21e25fc52a4abe8 (patch)
treedbd7876b028d9f2335f9fefe38ee95658faa7489 /Common/NativeApp
parentFixed linux build (diff)
downloadDiligentEngine-bc569d8612c4e22924b85576f21e25fc52a4abe8.tar.gz
DiligentEngine-bc569d8612c4e22924b85576f21e25fc52a4abe8.zip
Fixed Android build
Diffstat (limited to 'Common/NativeApp')
-rw-r--r--Common/NativeApp/CMakeLists.txt51
-rw-r--r--Common/NativeApp/include/Android/AndroidAppBase.h86
-rw-r--r--Common/NativeApp/include/NativeAppBase.h5
-rw-r--r--Common/NativeApp/src/Android/AndroidAppBase.cpp254
-rw-r--r--Common/NativeApp/src/Android/AndroidMain.cpp94
5 files changed, 482 insertions, 8 deletions
diff --git a/Common/NativeApp/CMakeLists.txt b/Common/NativeApp/CMakeLists.txt
index 938e669..5191690 100644
--- a/Common/NativeApp/CMakeLists.txt
+++ b/Common/NativeApp/CMakeLists.txt
@@ -59,8 +59,28 @@ elseif(PLATFORM_UNIVERSAL_WINDOWS)
elseif(PLATFORM_ANDROID)
set(SOURCE
- src/Android/AndroidMainImpl.cpp
+ src/Android/AndroidAppBase.cpp
)
+ set(INCLUDE
+ include/Android/AndroidAppBase.h
+ )
+ function(add_android_app TARGET_NAME SOURCE INCLUDE ASSETS)
+ get_target_property(NATIVE_APP_SOURCE_DIR NativeAppBase SOURCE_DIR)
+ set(ANDROID_SOURCE
+ ${NATIVE_APP_SOURCE_DIR}/src/Android/AndroidMain.cpp
+ )
+ add_library(${TARGET_NAME} SHARED ${SOURCE} ${ANDROID_SOURCE} ${INCLUDE} ${ASSETS})
+ target_link_libraries(${TARGET_NAME}
+ PRIVATE
+ android
+ NativeAppGlue
+ )
+ #target_include_directories(${TARGET_NAME}
+ #PRIVATE
+ # ${ANDROID_NDK}/sources/android/cpufeatures
+ #)
+ source_group("Android" FILES ${ANDROID_SOURCE})
+ endfunction()
elseif(PLATFORM_LINUX)
@@ -202,20 +222,35 @@ PRIVATE
if(PLATFORM_WIN32)
- target_include_directories(NativeAppBase PUBLIC include/Win32)
+ target_include_directories(NativeAppBase
+ PUBLIC
+ include/Win32
+ )
elseif(PLATFORM_UNIVERSAL_WINDOWS)
- target_include_directories(NativeAppBase PUBLIC include/UWP src/UWP)
+ target_include_directories(NativeAppBase
+ PUBLIC
+ include/UWP
+ src/UWP
+ )
elseif(PLATFORM_ANDROID)
- target_link_libraries(NativeAppBase PRIVATE NDKHelper android NativeAppBaseGlue)
- target_include_directories(NativeAppBase PRIVATE
- ${ANDROID_NDK}/sources/android/cpufeatures
+ target_link_libraries(NativeAppBase PUBLIC NDKHelper NativeAppGlue PRIVATE android)
+ target_include_directories(NativeAppBase
+ PUBLIC
+ include/Android
)
elseif(PLATFORM_LINUX)
- target_link_libraries(NativeAppBase PRIVATE X11)
- target_include_directories(NativeAppBase PUBLIC include/Linux)
+ target_link_libraries(NativeAppBase
+ PRIVATE
+ X11
+ )
+ target_include_directories(NativeAppBase
+ PUBLIC
+ include/Linux
+ )
+
elseif(PLATFORM_MACOS OR PLATFORM_IOS)
target_include_directories(NativeAppBase PUBLIC
src/MacOS
diff --git a/Common/NativeApp/include/Android/AndroidAppBase.h b/Common/NativeApp/include/Android/AndroidAppBase.h
new file mode 100644
index 0000000..7b737f4
--- /dev/null
+++ b/Common/NativeApp/include/Android/AndroidAppBase.h
@@ -0,0 +1,86 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <android_native_app_glue.h>
+#include "AppBase.h"
+
+#include "NDKHelper.h"
+
+struct android_app;
+class AndroidAppBase : public AppBase
+{
+public:
+ int InitDisplay();
+ void SetState( android_app* state );
+ void InitSensors();
+ void ProcessSensors( int32_t id );
+ bool IsReady();
+ virtual void TrimMemory() = 0;
+ virtual void TermDisplay() = 0;
+ static int32_t HandleInput( android_app* app, AInputEvent* event );
+ static void HandleCmd( struct android_app* app, int32_t cmd );
+
+protected:
+ virtual void Initialize(ANativeWindow* window) = 0;
+ virtual int Resume(ANativeWindow* window) = 0;
+
+ virtual int32_t HandleInput(AInputEvent* event ){return 0;}
+
+ virtual void LoadResources()
+ {
+ //renderer_.Init();
+ //renderer_.Bind( &tap_camera_ );
+ }
+
+ virtual void UnloadResources()
+ {
+ //renderer_.Unload();
+ }
+
+ ndk_helper::DoubletapDetector doubletap_detector_;
+ ndk_helper::PinchDetector pinch_detector_;
+ ndk_helper::DragDetector drag_detector_;
+ ndk_helper::PerfMonitor monitor_;
+
+ //ndk_helper::TapCamera tap_camera_;
+
+private:
+ void UpdatePosition( AInputEvent* event, int32_t iIndex, float& fX, float& fY );
+ void SuspendSensors();
+ void ResumeSensors();
+ void ShowUI();
+ void UpdateFPS( float fFPS );
+ void DrawFrame();
+
+ android_app* app_ = nullptr;
+ bool initialized_resources_ = false;
+ bool has_focus_ = false;
+
+ ASensorManager* sensor_manager_ = nullptr;
+ const ASensor* accelerometer_sensor_ = nullptr;
+ ASensorEventQueue* sensor_event_queue_ = nullptr;
+};
diff --git a/Common/NativeApp/include/NativeAppBase.h b/Common/NativeApp/include/NativeAppBase.h
index 222dd8d..8e9af92 100644
--- a/Common/NativeApp/include/NativeAppBase.h
+++ b/Common/NativeApp/include/NativeAppBase.h
@@ -37,6 +37,11 @@
#include "LinuxAppBase.h"
using NativeAppBase = LinuxAppBase;
+#elif PLATFORM_ANDROID
+
+ #include "AndroidAppBase.h"
+ using NativeAppBase = AndroidAppBase;
+
#else
# error Usnupported paltform
diff --git a/Common/NativeApp/src/Android/AndroidAppBase.cpp b/Common/NativeApp/src/Android/AndroidAppBase.cpp
new file mode 100644
index 0000000..2743c14
--- /dev/null
+++ b/Common/NativeApp/src/Android/AndroidAppBase.cpp
@@ -0,0 +1,254 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "AndroidAppBase.h"
+#include "Timer.h"
+
+#include <android/sensor.h>
+//#include <android/log.h>
+//#include <android_native_app_glue.h>
+#include <android/native_window_jni.h>
+//#include <cpu-features.h>
+
+int AndroidAppBase::InitDisplay()
+{
+ if( !initialized_resources_ )
+ {
+ Initialize(app_->window);
+
+ LoadResources();
+ initialized_resources_ = true;
+ }
+ else
+ {
+ // initialize OpenGL ES and EGL
+ if( EGL_SUCCESS != Resume( app_->window ) )
+ {
+ UnloadResources();
+ LoadResources();
+ }
+ }
+
+ ShowUI();
+
+ // auto width = pSwapChain_->GetDesc().Width;
+ // auto height = pSwapChain_->GetDesc().Height;
+
+ // //Note that screen size might have been changed
+ // pDeviceContext_->SetViewports( 1, nullptr, width, height );
+ // //renderer_.UpdateViewport();
+
+ // WindowResize(width, height);
+
+ // // Send the new window size to AntTweakBar
+ // TwWindowSize(width, height);
+
+
+ //tap_camera_.SetFlip( 1.f, -1.f, -1.f );
+ //tap_camera_.SetPinchTransformFactor( 2.f, 2.f, 8.f );
+
+ return 0;
+}
+
+void AndroidAppBase::InitSensors()
+{
+ sensor_manager_ = ASensorManager_getInstance();
+ accelerometer_sensor_ = ASensorManager_getDefaultSensor( sensor_manager_, ASENSOR_TYPE_ACCELEROMETER );
+ sensor_event_queue_ = ASensorManager_createEventQueue( sensor_manager_, app_->looper, LOOPER_ID_USER, NULL, NULL );
+}
+
+//
+// Just the current frame in the display.
+//
+void AndroidAppBase::DrawFrame()
+{
+ float fFPS;
+ if( monitor_.Update( fFPS ) )
+ {
+ UpdateFPS( fFPS );
+ }
+
+ static Diligent::Timer Timer;
+ static double PrevTime = Timer.GetElapsedTime();
+ auto CurrTime = Timer.GetElapsedTime();
+ auto ElapsedTime = CurrTime - PrevTime;
+ PrevTime = CurrTime;
+
+ Update(CurrTime, ElapsedTime);
+
+ Render();
+
+ Present();
+ //if( EGL_SUCCESS != pRenderDevice_->Present() )
+ //{
+ // UnloadResources();
+ // LoadResources();
+ //}
+}
+
+
+//
+// Process the next input event.
+//
+int32_t AndroidAppBase::HandleInput( android_app* app, AInputEvent* event )
+{
+ AndroidAppBase* eng = (AndroidAppBase*)app->userData;
+ return eng->HandleInput( event );
+}
+
+//
+// Process the next main command.
+//
+void AndroidAppBase::HandleCmd( struct android_app* app, int32_t cmd )
+{
+ AndroidAppBase* eng = (AndroidAppBase*)app->userData;
+ switch( cmd )
+ {
+ case APP_CMD_SAVE_STATE:
+ break;
+ case APP_CMD_INIT_WINDOW:
+ // The window is being shown, get it ready.
+ if( app->window != NULL )
+ {
+ eng->InitDisplay();
+ eng->DrawFrame();
+ }
+ break;
+ case APP_CMD_TERM_WINDOW:
+ // The window is being hidden or closed, clean it up.
+ eng->TermDisplay();
+ eng->has_focus_ = false;
+ break;
+ case APP_CMD_STOP:
+ break;
+ case APP_CMD_GAINED_FOCUS:
+ eng->ResumeSensors();
+ //Start animation
+ eng->has_focus_ = true;
+ break;
+ case APP_CMD_LOST_FOCUS:
+ eng->SuspendSensors();
+ // Also stop animating.
+ eng->has_focus_ = false;
+ eng->DrawFrame();
+ break;
+ case APP_CMD_LOW_MEMORY:
+ //Free up GL resources
+ eng->TrimMemory();
+ break;
+ }
+}
+
+//-------------------------------------------------------------------------
+//Sensor handlers
+//-------------------------------------------------------------------------
+void AndroidAppBase::ProcessSensors( int32_t id )
+{
+ // If a sensor has data, process it now.
+ if( id == LOOPER_ID_USER )
+ {
+ if( accelerometer_sensor_ != NULL )
+ {
+ ASensorEvent event;
+ while( ASensorEventQueue_getEvents( sensor_event_queue_, &event, 1 ) > 0 )
+ {
+ }
+ }
+ }
+}
+
+void AndroidAppBase::ResumeSensors()
+{
+ // When our app gains focus, we start monitoring the accelerometer.
+ if( accelerometer_sensor_ != NULL )
+ {
+ ASensorEventQueue_enableSensor( sensor_event_queue_, accelerometer_sensor_ );
+ // We'd like to get 60 events per second (in us).
+ ASensorEventQueue_setEventRate( sensor_event_queue_, accelerometer_sensor_,
+ (1000L / 60) * 1000 );
+ }
+}
+
+void AndroidAppBase::SuspendSensors()
+{
+ // When our app loses focus, we stop monitoring the accelerometer.
+ // This is to avoid consuming battery while not being used.
+ if( accelerometer_sensor_ != NULL )
+ {
+ ASensorEventQueue_disableSensor( sensor_event_queue_, accelerometer_sensor_ );
+ }
+}
+
+//-------------------------------------------------------------------------
+//Misc
+//-------------------------------------------------------------------------
+void AndroidAppBase::SetState( android_app* state )
+{
+ app_ = state;
+ doubletap_detector_.SetConfiguration( app_->config );
+ drag_detector_.SetConfiguration( app_->config );
+ pinch_detector_.SetConfiguration( app_->config );
+}
+
+bool AndroidAppBase::IsReady()
+{
+ if( has_focus_ )
+ return true;
+
+ return false;
+}
+
+//void Engine::TransformPosition( ndk_helper::Vec2& vec )
+//{
+// vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec
+// / ndk_helper::Vec2( pDeviceContext_->GetMainBackBufferDesc().Width, pDeviceContext_->GetMainBackBufferDesc().Height )
+// - ndk_helper::Vec2( 1.f, 1.f );
+//}
+
+void AndroidAppBase::ShowUI()
+{
+ JNIEnv *jni;
+ app_->activity->vm->AttachCurrentThread( &jni, NULL );
+
+ //Default class retrieval
+ jclass clazz = jni->GetObjectClass( app_->activity->clazz );
+ jmethodID methodID = jni->GetMethodID( clazz, "showUI", "()V" );
+ jni->CallVoidMethod( app_->activity->clazz, methodID );
+
+ app_->activity->vm->DetachCurrentThread();
+ return;
+}
+
+void AndroidAppBase::UpdateFPS( float fFPS )
+{
+ JNIEnv *jni;
+ app_->activity->vm->AttachCurrentThread( &jni, NULL );
+
+ //Default class retrieval
+ jclass clazz = jni->GetObjectClass( app_->activity->clazz );
+ jmethodID methodID = jni->GetMethodID( clazz, "updateFPS", "(F)V" );
+ jni->CallVoidMethod( app_->activity->clazz, methodID, fFPS );
+
+ app_->activity->vm->DetachCurrentThread();
+ return;
+}
diff --git a/Common/NativeApp/src/Android/AndroidMain.cpp b/Common/NativeApp/src/Android/AndroidMain.cpp
new file mode 100644
index 0000000..4ff35fa
--- /dev/null
+++ b/Common/NativeApp/src/Android/AndroidMain.cpp
@@ -0,0 +1,94 @@
+ /* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include <memory>
+#include <jni.h>
+#include <errno.h>
+
+#include "PlatformDefinitions.h"
+#include "NativeAppBase.h"
+
+
+#define HELPER_CLASS_NAME "com/sample/helper/NDKHelper" //Class name of helper function
+
+
+// This is the main entry point of a native application that is using
+// android_native_app_glue. It runs in its own thread, with its own
+// event loop for receiving input events and doing other things.
+void android_main( android_app* state )
+{
+ // Despite the deprecation warning, removing call to app_dummy causes the app to crash!
+ app_dummy();
+
+ std::unique_ptr<AndroidAppBase> theApp(CreateApplication());
+ theApp->SetState( state );
+
+ //Init helper functions
+ ndk_helper::JNIHelper::Init( state->activity, HELPER_CLASS_NAME );
+
+ state->userData = theApp.get();
+ state->onAppCmd = AndroidAppBase::HandleCmd;
+ state->onInputEvent = AndroidAppBase::HandleInput;
+
+#ifdef USE_NDK_PROFILER
+ monstartup( "libEngineSandbox.so" );
+#endif
+
+ // Prepare to monitor accelerometer
+ theApp->InitSensors();
+
+ // loop waiting for stuff to do.
+ while( 1 )
+ {
+ // Read all pending events.
+ int id;
+ int events;
+ android_poll_source* source;
+
+ // If not animating, we will block forever waiting for events.
+ // If animating, we loop until all events are read, then continue
+ // to draw the next frame of animation.
+ while( (id = ALooper_pollAll( theApp->IsReady() ? 0 : -1, NULL, &events, (void**)&source )) >= 0 )
+ {
+ // Process this event.
+ if( source != NULL )
+ source->process( state, source );
+
+ theApp->ProcessSensors( id );
+
+ // Check if we are exiting.
+ if( state->destroyRequested != 0 )
+ {
+ theApp->TermDisplay();
+ return;
+ }
+ }
+
+ if( theApp->IsReady() )
+ {
+ // Drawing is throttled to the screen update rate, so there
+ // is no need to do timing here.
+ theApp->DrawFrame();
+ }
+ }
+}